Mercurial > yaffs-ecoscentric-gpl
annotate yaffs_fs.c @ 171:fcfa82492193
Updated headers so they really are the same
| author | wookey <wookey> |
|---|---|
| date | Wed, 14 Feb 2007 01:09:06 +0000 |
| parents | b8f20fdc3a58 |
| children | 6c5c85e954a8 |
| rev | line source |
|---|---|
| 7 | 1 /* |
| 168 | 2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. |
| 7 | 3 * |
| 168 | 4 * Copyright (C) 2002-2007 Aleph One Ltd. |
| 7 | 5 * for Toby Churchill Ltd and Brightstar Engineering |
| 6 * | |
| 7 * Created by Charles Manning <charles@aleph1.co.uk> | |
| 168 | 8 * Acknowledgements: |
| 9 * Luc van OostenRyck for numerous patches. | |
| 10 * Nick Bane for numerous patches. | |
| 11 * Nick Bane for 2.5/2.6 integration. | |
| 12 * Andras Toth for mknod rdev issue. | |
| 13 * Michael Fischer for finding the problem with inode inconsistency. | |
| 14 * Some code bodily lifted from JFFS | |
| 7 | 15 * |
| 16 * This program is free software; you can redistribute it and/or modify | |
| 17 * it under the terms of the GNU General Public License version 2 as | |
| 18 * published by the Free Software Foundation. | |
| 168 | 19 */ |
| 20 | |
| 21 /* | |
| 22 * | |
| 7 | 23 * This is the file system front-end to YAFFS that hooks it up to |
| 24 * the VFS. | |
| 25 * | |
| 26 * Special notes: | |
| 76 | 27 * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with |
| 28 * this superblock | |
| 29 * >> 2.6: sb->s_fs_info points to the yaffs_Device associated with this | |
| 30 * superblock | |
| 7 | 31 * >> inode->u.generic_ip points to the associated yaffs_Object. |
| 32 */ | |
| 33 | |
| 76 | 34 const char *yaffs_fs_c_version = |
|
171
fcfa82492193
Updated headers so they really are the same
wookey <wookey>
parents:
168
diff
changeset
|
35 "$Id: yaffs_fs.c,v 1.58 2007-02-14 01:09:06 wookey Exp $"; |
| 7 | 36 extern const char *yaffs_guts_c_version; |
| 37 | |
| 166 | 38 #include <linux/version.h> |
| 39 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) | |
| 7 | 40 #include <linux/config.h> |
| 166 | 41 #endif |
| 7 | 42 #include <linux/kernel.h> |
| 43 #include <linux/module.h> | |
| 44 #include <linux/slab.h> | |
| 45 #include <linux/init.h> | |
| 46 #include <linux/list.h> | |
| 47 #include <linux/fs.h> | |
| 48 #include <linux/proc_fs.h> | |
| 27 | 49 #include <linux/smp_lock.h> |
| 7 | 50 #include <linux/pagemap.h> |
| 51 #include <linux/mtd/mtd.h> | |
| 52 #include <linux/interrupt.h> | |
| 53 #include <linux/string.h> | |
|
115
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
54 #include <linux/ctype.h> |
| 7 | 55 |
| 56 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 57 | |
| 58 #include <linux/statfs.h> /* Added NCB 15-8-2003 */ | |
| 59 #include <asm/statfs.h> | |
| 60 #define UnlockPage(p) unlock_page(p) | |
| 61 #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) | |
| 76 | 62 |
| 63 /* FIXME: use sb->s_id instead ? */ | |
| 64 #define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf) | |
| 7 | 65 |
| 66 #else | |
| 67 | |
| 68 #include <linux/locks.h> | |
|
37
843d9d0add74
Fix devname which was faked by always using "(unavailable)".
luc <luc>
parents:
36
diff
changeset
|
69 #define BDEVNAME_SIZE 0 |
|
843d9d0add74
Fix devname which was faked by always using "(unavailable)".
luc <luc>
parents:
36
diff
changeset
|
70 #define yaffs_devname(sb, buf) kdevname(sb->s_dev) |
| 7 | 71 |
| 137 | 72 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) |
| 73 /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */ | |
| 74 #define __user | |
| 75 #endif | |
| 76 | |
| 7 | 77 #endif |
| 78 | |
| 79 #include <asm/uaccess.h> | |
| 80 | |
| 81 #include "yportenv.h" | |
| 82 #include "yaffs_guts.h" | |
| 83 | |
| 127 | 84 unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | |
| 85 YAFFS_TRACE_BAD_BLOCKS | | |
| 86 YAFFS_TRACE_CHECKPOINT | |
| 87 /* | 0xFFFFFFFF */; | |
| 7 | 88 |
| 89 #include <linux/mtd/mtd.h> | |
| 90 #include "yaffs_mtdif.h" | |
| 91 #include "yaffs_mtdif2.h" | |
| 92 | |
| 76 | 93 /*#define T(x) printk x */ |
| 7 | 94 |
| 166 | 95 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) |
| 96 #define yaffs_InodeToObjectLV(iptr) (iptr)->i_private | |
| 97 #else | |
| 98 #define yaffs_InodeToObjectLV(iptr) (iptr)->u.generic_ip | |
| 99 #endif | |
| 100 | |
| 101 #define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr))) | |
| 7 | 102 #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode) |
| 103 | |
| 104 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 105 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->s_fs_info) | |
| 106 #else | |
| 107 #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp) | |
| 108 #endif | |
| 109 | |
| 110 static void yaffs_put_super(struct super_block *sb); | |
| 111 | |
| 76 | 112 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, |
| 113 loff_t * pos); | |
| 7 | 114 |
| 143 | 115 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 116 static int yaffs_file_flush(struct file *file, fl_owner_t id); | |
| 117 #else | |
| 76 | 118 static int yaffs_file_flush(struct file *file); |
| 143 | 119 #endif |
| 7 | 120 |
| 76 | 121 static int yaffs_sync_object(struct file *file, struct dentry *dentry, |
| 122 int datasync); | |
| 7 | 123 |
| 124 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir); | |
| 125 | |
| 126 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 76 | 127 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, |
| 128 struct nameidata *n); | |
| 129 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, | |
| 130 struct nameidata *n); | |
| 7 | 131 #else |
| 132 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode); | |
| 76 | 133 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry); |
| 7 | 134 #endif |
| 76 | 135 static int yaffs_link(struct dentry *old_dentry, struct inode *dir, |
| 136 struct dentry *dentry); | |
| 137 static int yaffs_unlink(struct inode *dir, struct dentry *dentry); | |
| 138 static int yaffs_symlink(struct inode *dir, struct dentry *dentry, | |
| 139 const char *symname); | |
| 140 static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode); | |
| 7 | 141 |
| 142 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 76 | 143 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, |
| 144 dev_t dev); | |
| 7 | 145 #else |
| 76 | 146 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, |
| 147 int dev); | |
| 7 | 148 #endif |
| 76 | 149 static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, |
| 150 struct inode *new_dir, struct dentry *new_dentry); | |
| 7 | 151 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr); |
| 152 | |
| 143 | 153 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 154 static int yaffs_sync_fs(struct super_block *sb, int wait); | |
| 155 static void yaffs_write_super(struct super_block *sb); | |
| 156 #else | |
| 129 | 157 static int yaffs_sync_fs(struct super_block *sb); |
| 158 static int yaffs_write_super(struct super_block *sb); | |
| 143 | 159 #endif |
| 129 | 160 |
| 143 | 161 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 162 static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf); | |
| 163 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 7 | 164 static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf); |
| 165 #else | |
| 166 static int yaffs_statfs(struct super_block *sb, struct statfs *buf); | |
| 167 #endif | |
| 76 | 168 static void yaffs_read_inode(struct inode *inode); |
| 7 | 169 |
| 76 | 170 static void yaffs_put_inode(struct inode *inode); |
| 7 | 171 static void yaffs_delete_inode(struct inode *); |
| 172 static void yaffs_clear_inode(struct inode *); | |
| 173 | |
| 76 | 174 static int yaffs_readpage(struct file *file, struct page *page); |
| 23 | 175 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
| 176 static int yaffs_writepage(struct page *page, struct writeback_control *wbc); | |
| 177 #else | |
| 7 | 178 static int yaffs_writepage(struct page *page); |
| 23 | 179 #endif |
| 76 | 180 static int yaffs_prepare_write(struct file *f, struct page *pg, |
| 181 unsigned offset, unsigned to); | |
| 182 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, | |
| 183 unsigned to); | |
| 7 | 184 |
| 76 | 185 static int yaffs_readlink(struct dentry *dentry, char __user * buffer, |
| 186 int buflen); | |
| 99 | 187 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) |
| 188 static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); | |
| 189 #else | |
| 7 | 190 static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); |
| 99 | 191 #endif |
| 7 | 192 |
| 193 static struct address_space_operations yaffs_file_address_operations = { | |
| 76 | 194 .readpage = yaffs_readpage, |
| 195 .writepage = yaffs_writepage, | |
| 196 .prepare_write = yaffs_prepare_write, | |
| 197 .commit_write = yaffs_commit_write, | |
| 7 | 198 }; |
| 199 | |
| 200 static struct file_operations yaffs_file_operations = { | |
| 166 | 201 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) |
| 202 .read = do_sync_read, | |
| 203 .write = do_sync_write, | |
| 204 .aio_read = generic_file_aio_read, | |
| 205 .aio_write = generic_file_aio_write, | |
| 206 #else | |
| 76 | 207 .read = generic_file_read, |
| 208 .write = generic_file_write, | |
| 166 | 209 #endif |
| 76 | 210 .mmap = generic_file_mmap, |
| 211 .flush = yaffs_file_flush, | |
| 212 .fsync = yaffs_sync_object, | |
|
112
0f8838615001
Add generic sendfile method for yaffs2, also thereby allowing loopback mount.
tpoynor <tpoynor>
parents:
109
diff
changeset
|
213 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
|
0f8838615001
Add generic sendfile method for yaffs2, also thereby allowing loopback mount.
tpoynor <tpoynor>
parents:
109
diff
changeset
|
214 .sendfile = generic_file_sendfile, |
|
0f8838615001
Add generic sendfile method for yaffs2, also thereby allowing loopback mount.
tpoynor <tpoynor>
parents:
109
diff
changeset
|
215 #endif |
|
0f8838615001
Add generic sendfile method for yaffs2, also thereby allowing loopback mount.
tpoynor <tpoynor>
parents:
109
diff
changeset
|
216 |
| 7 | 217 }; |
| 218 | |
| 219 static struct inode_operations yaffs_file_inode_operations = { | |
| 76 | 220 .setattr = yaffs_setattr, |
| 7 | 221 }; |
| 222 | |
| 76 | 223 static struct inode_operations yaffs_symlink_inode_operations = { |
| 224 .readlink = yaffs_readlink, | |
| 225 .follow_link = yaffs_follow_link, | |
| 226 .setattr = yaffs_setattr, | |
| 7 | 227 }; |
| 228 | |
| 229 static struct inode_operations yaffs_dir_inode_operations = { | |
| 76 | 230 .create = yaffs_create, |
| 231 .lookup = yaffs_lookup, | |
| 232 .link = yaffs_link, | |
| 233 .unlink = yaffs_unlink, | |
| 234 .symlink = yaffs_symlink, | |
| 235 .mkdir = yaffs_mkdir, | |
| 236 .rmdir = yaffs_unlink, | |
| 237 .mknod = yaffs_mknod, | |
| 238 .rename = yaffs_rename, | |
| 239 .setattr = yaffs_setattr, | |
| 7 | 240 }; |
| 241 | |
| 242 static struct file_operations yaffs_dir_operations = { | |
| 76 | 243 .read = generic_read_dir, |
| 244 .readdir = yaffs_readdir, | |
| 245 .fsync = yaffs_sync_object, | |
| 7 | 246 }; |
| 247 | |
| 248 static struct super_operations yaffs_super_ops = { | |
| 76 | 249 .statfs = yaffs_statfs, |
| 250 .read_inode = yaffs_read_inode, | |
| 251 .put_inode = yaffs_put_inode, | |
| 252 .put_super = yaffs_put_super, | |
| 253 .delete_inode = yaffs_delete_inode, | |
| 254 .clear_inode = yaffs_clear_inode, | |
| 129 | 255 .sync_fs = yaffs_sync_fs, |
| 256 .write_super = yaffs_write_super, | |
| 7 | 257 }; |
| 258 | |
| 76 | 259 static void yaffs_GrossLock(yaffs_Device * dev) |
| 7 | 260 { |
| 76 | 261 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs locking\n")); |
| 7 | 262 |
| 263 down(&dev->grossLock); | |
| 264 } | |
| 265 | |
| 76 | 266 static void yaffs_GrossUnlock(yaffs_Device * dev) |
| 7 | 267 { |
| 76 | 268 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs unlocking\n")); |
| 7 | 269 up(&dev->grossLock); |
| 270 | |
| 271 } | |
| 272 | |
| 76 | 273 static int yaffs_readlink(struct dentry *dentry, char __user * buffer, |
| 274 int buflen) | |
| 7 | 275 { |
| 276 unsigned char *alias; | |
| 277 int ret; | |
| 278 | |
| 279 yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; | |
| 280 | |
| 76 | 281 yaffs_GrossLock(dev); |
| 7 | 282 |
| 283 alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); | |
| 76 | 284 |
| 7 | 285 yaffs_GrossUnlock(dev); |
| 76 | 286 |
| 287 if (!alias) | |
| 7 | 288 return -ENOMEM; |
| 289 | |
| 290 ret = vfs_readlink(dentry, buffer, buflen, alias); | |
| 291 kfree(alias); | |
| 292 return ret; | |
| 293 } | |
| 294 | |
| 99 | 295 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) |
| 296 static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) | |
| 297 #else | |
| 7 | 298 static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) |
| 99 | 299 #endif |
| 7 | 300 { |
| 301 unsigned char *alias; | |
| 302 int ret; | |
| 303 yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; | |
| 304 | |
| 305 yaffs_GrossLock(dev); | |
| 306 | |
| 307 alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); | |
| 76 | 308 |
| 7 | 309 yaffs_GrossUnlock(dev); |
| 76 | 310 |
| 311 if (!alias) | |
| 99 | 312 { |
| 313 ret = -ENOMEM; | |
| 314 goto out; | |
| 315 } | |
| 7 | 316 |
| 76 | 317 ret = vfs_follow_link(nd, alias); |
| 7 | 318 kfree(alias); |
| 99 | 319 out: |
| 320 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) | |
| 321 return ERR_PTR (ret); | |
| 322 #else | |
| 7 | 323 return ret; |
| 99 | 324 #endif |
| 7 | 325 } |
| 326 | |
| 76 | 327 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, |
| 328 yaffs_Object * obj); | |
| 7 | 329 |
| 330 /* | |
| 331 * Lookup is used to find objects in the fs | |
| 332 */ | |
| 333 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 334 | |
| 76 | 335 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, |
| 336 struct nameidata *n) | |
| 7 | 337 #else |
| 76 | 338 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) |
| 7 | 339 #endif |
| 340 { | |
| 341 yaffs_Object *obj; | |
| 76 | 342 struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */ |
| 343 | |
| 7 | 344 yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev; |
| 345 | |
| 346 yaffs_GrossLock(dev); | |
| 347 | |
| 76 | 348 T(YAFFS_TRACE_OS, |
| 349 (KERN_DEBUG "yaffs_lookup for %d:%s\n", | |
| 350 yaffs_InodeToObject(dir)->objectId, dentry->d_name.name)); | |
| 351 | |
| 352 obj = | |
| 353 yaffs_FindObjectByName(yaffs_InodeToObject(dir), | |
| 354 dentry->d_name.name); | |
| 355 | |
| 356 obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */ | |
|
106
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
357 |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
358 /* Can't hold gross lock when calling yaffs_get_inode() */ |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
359 yaffs_GrossUnlock(dev); |
| 7 | 360 |
| 76 | 361 if (obj) { |
| 362 T(YAFFS_TRACE_OS, | |
| 363 (KERN_DEBUG "yaffs_lookup found %d\n", obj->objectId)); | |
| 364 | |
| 365 inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); | |
| 366 | |
| 367 if (inode) { | |
| 368 T(YAFFS_TRACE_OS, | |
| 369 (KERN_DEBUG "yaffs_loookup dentry \n")); | |
| 370 /* #if 0 asserted by NCB for 2.5/6 compatability - falls through to | |
| 371 * d_add even if NULL inode */ | |
| 7 | 372 #if 0 |
| 76 | 373 /*dget(dentry); // try to solve directory bug */ |
| 374 d_add(dentry, inode); | |
| 375 | |
| 376 /* return dentry; */ | |
| 7 | 377 return NULL; |
| 378 #endif | |
| 379 } | |
| 380 | |
| 76 | 381 } else { |
| 382 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n")); | |
| 383 | |
| 7 | 384 } |
| 385 | |
| 76 | 386 /* added NCB for 2.5/6 compatability - forces add even if inode is |
| 387 * NULL which creates dentry hash */ | |
| 388 d_add(dentry, inode); | |
| 389 | |
| 7 | 390 return NULL; |
| 76 | 391 /* return (ERR_PTR(-EIO)); */ |
| 392 | |
| 7 | 393 } |
| 394 | |
| 76 | 395 /* For now put inode is just for debugging |
| 396 * Put inode is called when the inode **structure** is put. | |
| 397 */ | |
| 7 | 398 static void yaffs_put_inode(struct inode *inode) |
| 399 { | |
| 76 | 400 T(YAFFS_TRACE_OS, |
| 401 ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino, | |
| 402 atomic_read(&inode->i_count))); | |
| 403 | |
| 7 | 404 } |
| 405 | |
| 76 | 406 /* clear is called to tell the fs to release any per-inode data it holds */ |
| 7 | 407 static void yaffs_clear_inode(struct inode *inode) |
| 408 { | |
| 409 yaffs_Object *obj; | |
| 410 yaffs_Device *dev; | |
| 76 | 411 |
| 7 | 412 obj = yaffs_InodeToObject(inode); |
| 413 | |
| 76 | 414 T(YAFFS_TRACE_OS, |
| 415 ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, | |
| 416 atomic_read(&inode->i_count), | |
| 417 obj ? "object exists" : "null object")); | |
| 418 | |
| 419 if (obj) { | |
| 7 | 420 dev = obj->myDev; |
| 421 yaffs_GrossLock(dev); | |
| 76 | 422 |
| 423 /* Clear the association between the inode and | |
| 424 * the yaffs_Object. | |
| 425 */ | |
| 7 | 426 obj->myInode = NULL; |
| 166 | 427 yaffs_InodeToObjectLV(inode) = NULL; |
| 76 | 428 |
| 429 /* If the object freeing was deferred, then the real | |
| 430 * free happens now. | |
| 431 * This should fix the inode inconsistency problem. | |
| 432 */ | |
| 433 | |
| 7 | 434 yaffs_HandleDeferedFree(obj); |
| 76 | 435 |
| 7 | 436 yaffs_GrossUnlock(dev); |
| 437 } | |
| 76 | 438 |
| 7 | 439 } |
| 440 | |
| 76 | 441 /* delete is called when the link count is zero and the inode |
| 442 * is put (ie. nobody wants to know about it anymore, time to | |
| 443 * delete the file). | |
| 444 * NB Must call clear_inode() | |
| 445 */ | |
| 7 | 446 static void yaffs_delete_inode(struct inode *inode) |
| 447 { | |
| 448 yaffs_Object *obj = yaffs_InodeToObject(inode); | |
| 449 yaffs_Device *dev; | |
| 450 | |
| 76 | 451 T(YAFFS_TRACE_OS, |
| 452 ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, | |
| 453 atomic_read(&inode->i_count), | |
| 454 obj ? "object exists" : "null object")); | |
| 455 | |
| 456 if (obj) { | |
| 457 dev = obj->myDev; | |
| 7 | 458 yaffs_GrossLock(dev); |
| 459 yaffs_DeleteFile(obj); | |
| 460 yaffs_GrossUnlock(dev); | |
| 461 } | |
| 99 | 462 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) |
| 463 truncate_inode_pages (&inode->i_data, 0); | |
| 464 #endif | |
| 7 | 465 clear_inode(inode); |
| 466 } | |
| 467 | |
| 143 | 468 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 469 static int yaffs_file_flush(struct file *file, fl_owner_t id) | |
| 470 #else | |
| 76 | 471 static int yaffs_file_flush(struct file *file) |
| 143 | 472 #endif |
| 7 | 473 { |
| 474 yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry); | |
| 76 | 475 |
| 7 | 476 yaffs_Device *dev = obj->myDev; |
| 76 | 477 |
| 478 T(YAFFS_TRACE_OS, | |
| 479 (KERN_DEBUG "yaffs_file_flush object %d (%s)\n", obj->objectId, | |
| 480 obj->dirty ? "dirty" : "clean")); | |
| 7 | 481 |
| 482 yaffs_GrossLock(dev); | |
| 76 | 483 |
| 484 yaffs_FlushFile(obj, 1); | |
| 7 | 485 |
| 486 yaffs_GrossUnlock(dev); | |
| 487 | |
| 76 | 488 return 0; |
| 7 | 489 } |
| 490 | |
| 76 | 491 static int yaffs_readpage_nolock(struct file *f, struct page *pg) |
| 492 { | |
| 493 /* Lifted from jffs2 */ | |
| 7 | 494 |
| 495 yaffs_Object *obj; | |
| 496 unsigned char *pg_buf; | |
| 497 int ret; | |
| 498 | |
| 499 yaffs_Device *dev; | |
| 500 | |
| 76 | 501 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage at %08x, size %08x\n", |
| 502 (unsigned)(pg->index << PAGE_CACHE_SHIFT), | |
| 503 (unsigned)PAGE_CACHE_SIZE)); | |
| 7 | 504 |
| 76 | 505 obj = yaffs_DentryToObject(f->f_dentry); |
| 7 | 506 |
| 507 dev = obj->myDev; | |
| 76 | 508 |
| 23 | 509 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
| 76 | 510 BUG_ON(!PageLocked(pg)); |
| 23 | 511 #else |
| 7 | 512 if (!PageLocked(pg)) |
| 76 | 513 PAGE_BUG(pg); |
| 23 | 514 #endif |
| 7 | 515 |
| 516 pg_buf = kmap(pg); | |
| 517 /* FIXME: Can kmap fail? */ | |
| 518 | |
| 519 yaffs_GrossLock(dev); | |
| 76 | 520 |
| 521 ret = | |
| 522 yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, | |
| 523 PAGE_CACHE_SIZE); | |
| 7 | 524 |
| 525 yaffs_GrossUnlock(dev); | |
| 76 | 526 |
| 527 if (ret >= 0) | |
| 528 ret = 0; | |
| 7 | 529 |
| 530 if (ret) { | |
| 531 ClearPageUptodate(pg); | |
| 532 SetPageError(pg); | |
| 533 } else { | |
| 534 SetPageUptodate(pg); | |
| 535 ClearPageError(pg); | |
| 536 } | |
| 537 | |
| 538 flush_dcache_page(pg); | |
| 539 kunmap(pg); | |
| 540 | |
| 76 | 541 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage done\n")); |
| 7 | 542 return ret; |
| 543 } | |
| 544 | |
| 545 static int yaffs_readpage_unlock(struct file *f, struct page *pg) | |
| 546 { | |
| 76 | 547 int ret = yaffs_readpage_nolock(f, pg); |
| 7 | 548 UnlockPage(pg); |
| 549 return ret; | |
| 550 } | |
| 551 | |
| 76 | 552 static int yaffs_readpage(struct file *f, struct page *pg) |
| 7 | 553 { |
| 76 | 554 return yaffs_readpage_unlock(f, pg); |
| 7 | 555 } |
| 556 | |
| 76 | 557 /* writepage inspired by/stolen from smbfs */ |
| 7 | 558 |
| 23 | 559 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
| 560 static int yaffs_writepage(struct page *page, struct writeback_control *wbc) | |
| 561 #else | |
| 7 | 562 static int yaffs_writepage(struct page *page) |
| 23 | 563 #endif |
| 7 | 564 { |
| 565 struct address_space *mapping = page->mapping; | |
| 76 | 566 loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT; |
| 7 | 567 struct inode *inode; |
| 568 unsigned long end_index; | |
| 569 char *buffer; | |
| 570 yaffs_Object *obj; | |
| 571 int nWritten = 0; | |
| 572 unsigned nBytes; | |
| 573 | |
| 574 if (!mapping) | |
| 575 BUG(); | |
| 576 inode = mapping->host; | |
| 577 if (!inode) | |
| 578 BUG(); | |
| 579 | |
| 76 | 580 if (offset > inode->i_size) { |
| 581 T(YAFFS_TRACE_OS, | |
| 582 (KERN_DEBUG | |
| 583 "yaffs_writepage at %08x, inode size = %08x!!!\n", | |
| 584 (unsigned)(page->index << PAGE_CACHE_SHIFT), | |
| 585 (unsigned)inode->i_size)); | |
| 586 T(YAFFS_TRACE_OS, | |
| 587 (KERN_DEBUG " -> don't care!!\n")); | |
|
67
cb8afec5ad31
Fix an error in writepage when a file is extended.
luc <luc>
parents:
61
diff
changeset
|
588 unlock_page(page); |
|
cb8afec5ad31
Fix an error in writepage when a file is extended.
luc <luc>
parents:
61
diff
changeset
|
589 return 0; |
|
cb8afec5ad31
Fix an error in writepage when a file is extended.
luc <luc>
parents:
61
diff
changeset
|
590 } |
|
cb8afec5ad31
Fix an error in writepage when a file is extended.
luc <luc>
parents:
61
diff
changeset
|
591 |
| 7 | 592 end_index = inode->i_size >> PAGE_CACHE_SHIFT; |
| 593 | |
| 594 /* easy case */ | |
| 76 | 595 if (page->index < end_index) { |
| 7 | 596 nBytes = PAGE_CACHE_SIZE; |
| 76 | 597 } else { |
| 598 nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1); | |
| 7 | 599 } |
| 600 | |
| 601 get_page(page); | |
| 602 | |
| 603 buffer = kmap(page); | |
| 604 | |
| 605 obj = yaffs_InodeToObject(inode); | |
| 606 yaffs_GrossLock(obj->myDev); | |
| 607 | |
| 76 | 608 T(YAFFS_TRACE_OS, |
| 609 (KERN_DEBUG "yaffs_writepage at %08x, size %08x\n", | |
| 610 (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); | |
| 611 T(YAFFS_TRACE_OS, | |
| 612 (KERN_DEBUG "writepag0: obj = %05x, ino = %05x\n", | |
| 613 (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); | |
| 7 | 614 |
| 76 | 615 nWritten = |
| 616 yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT, | |
| 617 nBytes, 0); | |
| 7 | 618 |
| 76 | 619 T(YAFFS_TRACE_OS, |
| 620 (KERN_DEBUG "writepag1: obj = %05x, ino = %05x\n", | |
| 621 (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); | |
|
67
cb8afec5ad31
Fix an error in writepage when a file is extended.
luc <luc>
parents:
61
diff
changeset
|
622 |
| 7 | 623 yaffs_GrossUnlock(obj->myDev); |
| 76 | 624 |
| 7 | 625 kunmap(page); |
| 626 SetPageUptodate(page); | |
| 627 UnlockPage(page); | |
| 628 put_page(page); | |
| 629 | |
| 76 | 630 return (nWritten == nBytes) ? 0 : -ENOSPC; |
| 7 | 631 } |
| 632 | |
| 76 | 633 static int yaffs_prepare_write(struct file *f, struct page *pg, |
| 634 unsigned offset, unsigned to) | |
| 7 | 635 { |
| 636 | |
| 76 | 637 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n")); |
| 638 if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) | |
| 639 return yaffs_readpage_nolock(f, pg); | |
| 7 | 640 |
| 641 return 0; | |
| 76 | 642 |
| 7 | 643 } |
| 644 | |
| 76 | 645 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, |
| 646 unsigned to) | |
| 7 | 647 { |
| 648 | |
| 649 void *addr = page_address(pg) + offset; | |
| 76 | 650 loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset; |
| 7 | 651 int nBytes = to - offset; |
| 652 int nWritten; | |
| 76 | 653 |
| 7 | 654 unsigned spos = pos; |
| 655 unsigned saddr = (unsigned)addr; | |
| 656 | |
| 76 | 657 T(YAFFS_TRACE_OS, |
| 658 (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr, | |
| 659 spos, nBytes)); | |
| 660 | |
| 661 nWritten = yaffs_file_write(f, addr, nBytes, &pos); | |
| 662 | |
| 663 if (nWritten != nBytes) { | |
| 664 T(YAFFS_TRACE_OS, | |
| 665 (KERN_DEBUG | |
| 666 "yaffs_commit_write not same size nWritten %d nBytes %d\n", | |
| 667 nWritten, nBytes)); | |
| 7 | 668 SetPageError(pg); |
| 669 ClearPageUptodate(pg); | |
| 76 | 670 } else { |
| 7 | 671 SetPageUptodate(pg); |
| 672 } | |
| 673 | |
| 76 | 674 T(YAFFS_TRACE_OS, |
| 94 | 675 (KERN_DEBUG "yaffs_commit_write returning %d\n", |
|
113
325f5d3a757c
Handle partial writes more gracefully: return partial byte counts, return
tpoynor <tpoynor>
parents:
112
diff
changeset
|
676 nWritten == nBytes ? 0 : nWritten)); |
| 76 | 677 |
|
113
325f5d3a757c
Handle partial writes more gracefully: return partial byte counts, return
tpoynor <tpoynor>
parents:
112
diff
changeset
|
678 return nWritten == nBytes ? 0 : nWritten; |
| 7 | 679 |
| 680 } | |
| 681 | |
| 76 | 682 static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj) |
| 7 | 683 { |
| 76 | 684 if (inode && obj) { |
| 139 | 685 |
| 686 | |
| 687 /* Check mode against the variant type and attempt to repair if broken. */ | |
| 688 __u32 mode = obj->yst_mode; | |
| 689 switch( obj->variantType ){ | |
| 690 case YAFFS_OBJECT_TYPE_FILE : | |
| 691 if( ! S_ISREG(mode) ){ | |
| 692 obj->yst_mode &= ~S_IFMT; | |
| 693 obj->yst_mode |= S_IFREG; | |
| 694 } | |
| 695 | |
| 696 break; | |
| 697 case YAFFS_OBJECT_TYPE_SYMLINK : | |
| 698 if( ! S_ISLNK(mode) ){ | |
| 699 obj->yst_mode &= ~S_IFMT; | |
| 700 obj->yst_mode |= S_IFLNK; | |
| 701 } | |
| 702 | |
| 703 break; | |
| 704 case YAFFS_OBJECT_TYPE_DIRECTORY : | |
| 705 if( ! S_ISDIR(mode) ){ | |
| 706 obj->yst_mode &= ~S_IFMT; | |
| 707 obj->yst_mode |= S_IFDIR; | |
| 708 } | |
| 709 | |
| 710 break; | |
| 711 case YAFFS_OBJECT_TYPE_UNKNOWN : | |
| 712 case YAFFS_OBJECT_TYPE_HARDLINK : | |
| 713 case YAFFS_OBJECT_TYPE_SPECIAL : | |
| 714 default: | |
| 715 /* TODO? */ | |
| 716 break; | |
| 717 } | |
| 718 | |
| 7 | 719 inode->i_ino = obj->objectId; |
|
22
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
720 inode->i_mode = obj->yst_mode; |
|
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
721 inode->i_uid = obj->yst_uid; |
|
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
722 inode->i_gid = obj->yst_gid; |
| 166 | 723 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) |
| 7 | 724 inode->i_blksize = inode->i_sb->s_blocksize; |
| 166 | 725 #endif |
| 7 | 726 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
| 727 | |
|
22
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
728 inode->i_rdev = old_decode_dev(obj->yst_rdev); |
| 76 | 729 inode->i_atime.tv_sec = (time_t) (obj->yst_atime); |
| 7 | 730 inode->i_atime.tv_nsec = 0; |
| 76 | 731 inode->i_mtime.tv_sec = (time_t) obj->yst_mtime; |
| 732 inode->i_mtime.tv_nsec = 0; | |
| 733 inode->i_ctime.tv_sec = (time_t) obj->yst_ctime; | |
| 7 | 734 inode->i_ctime.tv_nsec = 0; |
| 735 #else | |
|
22
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
736 inode->i_rdev = obj->yst_rdev; |
|
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
737 inode->i_atime = obj->yst_atime; |
|
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
738 inode->i_mtime = obj->yst_mtime; |
|
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
739 inode->i_ctime = obj->yst_ctime; |
| 7 | 740 #endif |
| 741 inode->i_size = yaffs_GetObjectFileLength(obj); | |
| 742 inode->i_blocks = (inode->i_size + 511) >> 9; | |
| 743 | |
| 744 inode->i_nlink = yaffs_GetObjectLinkCount(obj); | |
| 76 | 745 |
| 746 T(YAFFS_TRACE_OS, | |
| 747 (KERN_DEBUG | |
| 748 "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", | |
| 749 inode->i_mode, inode->i_uid, inode->i_gid, | |
| 750 (int)inode->i_size, atomic_read(&inode->i_count))); | |
| 751 | |
| 752 switch (obj->yst_mode & S_IFMT) { | |
| 753 default: /* fifo, device or socket */ | |
| 12 | 754 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
| 76 | 755 init_special_inode(inode, obj->yst_mode, |
| 756 old_decode_dev(obj->yst_rdev)); | |
| 12 | 757 #else |
| 76 | 758 init_special_inode(inode, obj->yst_mode, |
| 759 (dev_t) (obj->yst_rdev)); | |
| 760 #endif | |
| 761 break; | |
| 762 case S_IFREG: /* file */ | |
| 763 inode->i_op = &yaffs_file_inode_operations; | |
| 764 inode->i_fop = &yaffs_file_operations; | |
| 765 inode->i_mapping->a_ops = | |
| 766 &yaffs_file_address_operations; | |
| 767 break; | |
| 768 case S_IFDIR: /* directory */ | |
| 769 inode->i_op = &yaffs_dir_inode_operations; | |
| 770 inode->i_fop = &yaffs_dir_operations; | |
| 771 break; | |
| 772 case S_IFLNK: /* symlink */ | |
| 773 inode->i_op = &yaffs_symlink_inode_operations; | |
| 774 break; | |
| 7 | 775 } |
| 76 | 776 |
| 166 | 777 yaffs_InodeToObjectLV(inode) = obj; |
| 778 | |
| 7 | 779 obj->myInode = inode; |
| 76 | 780 |
| 781 } else { | |
| 782 T(YAFFS_TRACE_OS, | |
| 783 (KERN_DEBUG "yaffs_FileInode invalid parameters\n")); | |
| 7 | 784 } |
| 785 | |
| 786 } | |
| 787 | |
| 76 | 788 struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, |
| 789 yaffs_Object * obj) | |
| 7 | 790 { |
| 76 | 791 struct inode *inode; |
| 792 | |
| 793 if (!sb) { | |
| 794 T(YAFFS_TRACE_OS, | |
| 795 (KERN_DEBUG "yaffs_get_inode for NULL super_block!!\n")); | |
| 796 return NULL; | |
| 797 | |
| 7 | 798 } |
| 76 | 799 |
| 800 if (!obj) { | |
| 801 T(YAFFS_TRACE_OS, | |
| 802 (KERN_DEBUG "yaffs_get_inode for NULL object!!\n")); | |
| 803 return NULL; | |
| 804 | |
| 7 | 805 } |
| 76 | 806 |
| 807 T(YAFFS_TRACE_OS, | |
| 808 (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId)); | |
| 7 | 809 |
| 76 | 810 inode = iget(sb, obj->objectId); |
| 7 | 811 |
| 76 | 812 /* NB Side effect: iget calls back to yaffs_read_inode(). */ |
| 813 /* iget also increments the inode's i_count */ | |
|
106
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
814 /* NB You can't be holding grossLock or deadlock will happen! */ |
| 76 | 815 |
| 7 | 816 return inode; |
| 817 } | |
| 818 | |
| 76 | 819 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, |
| 820 loff_t * pos) | |
| 7 | 821 { |
| 822 yaffs_Object *obj; | |
| 76 | 823 int nWritten, ipos; |
| 7 | 824 struct inode *inode; |
| 825 yaffs_Device *dev; | |
| 76 | 826 |
| 827 obj = yaffs_DentryToObject(f->f_dentry); | |
| 828 | |
| 7 | 829 dev = obj->myDev; |
| 76 | 830 |
| 7 | 831 yaffs_GrossLock(dev); |
| 832 | |
| 833 inode = f->f_dentry->d_inode; | |
| 834 | |
| 76 | 835 if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) { |
| 7 | 836 ipos = inode->i_size; |
| 76 | 837 } else { |
| 7 | 838 ipos = *pos; |
| 839 } | |
| 76 | 840 |
| 841 if (!obj) { | |
| 842 T(YAFFS_TRACE_OS, | |
| 843 (KERN_DEBUG "yaffs_file_write: hey obj is null!\n")); | |
| 844 } else { | |
| 845 T(YAFFS_TRACE_OS, | |
| 846 (KERN_DEBUG | |
| 847 "yaffs_file_write about to write writing %d bytes" | |
| 848 "to object %d at %d\n", | |
| 849 n, obj->objectId, ipos)); | |
| 7 | 850 } |
| 851 | |
| 76 | 852 nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0); |
| 7 | 853 |
| 76 | 854 T(YAFFS_TRACE_OS, |
| 855 (KERN_DEBUG "yaffs_file_write writing %d bytes, %d written at %d\n", | |
| 856 n, nWritten, ipos)); | |
| 857 if (nWritten > 0) { | |
| 7 | 858 ipos += nWritten; |
| 859 *pos = ipos; | |
| 76 | 860 if (ipos > inode->i_size) { |
| 7 | 861 inode->i_size = ipos; |
| 76 | 862 inode->i_blocks = (ipos + 511) >> 9; |
| 863 | |
| 864 T(YAFFS_TRACE_OS, | |
| 865 (KERN_DEBUG | |
| 866 "yaffs_file_write size updated to %d bytes, " | |
| 867 "%d blocks\n", | |
| 868 ipos, (int)(inode->i_blocks))); | |
| 7 | 869 } |
| 76 | 870 |
| 7 | 871 } |
| 872 yaffs_GrossUnlock(dev); | |
|
113
325f5d3a757c
Handle partial writes more gracefully: return partial byte counts, return
tpoynor <tpoynor>
parents:
112
diff
changeset
|
873 return nWritten == 0 ? -ENOSPC : nWritten; |
| 7 | 874 } |
| 875 | |
| 876 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) | |
| 877 { | |
| 878 yaffs_Object *obj; | |
| 879 yaffs_Device *dev; | |
| 880 struct inode *inode = f->f_dentry->d_inode; | |
| 881 unsigned long offset, curoffs; | |
| 76 | 882 struct list_head *i; |
| 7 | 883 yaffs_Object *l; |
| 76 | 884 |
| 885 char name[YAFFS_MAX_NAME_LENGTH + 1]; | |
| 886 | |
| 887 obj = yaffs_DentryToObject(f->f_dentry); | |
| 7 | 888 dev = obj->myDev; |
| 76 | 889 |
| 7 | 890 yaffs_GrossLock(dev); |
| 76 | 891 |
| 7 | 892 offset = f->f_pos; |
| 76 | 893 |
| 894 T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset)); | |
| 895 | |
| 896 if (offset == 0) { | |
| 897 T(YAFFS_TRACE_OS, | |
| 898 (KERN_DEBUG "yaffs_readdir: entry . ino %d \n", | |
| 899 (int)inode->i_ino)); | |
| 900 if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) | |
| 901 < 0) { | |
| 7 | 902 goto out; |
| 903 } | |
| 904 offset++; | |
| 905 f->f_pos++; | |
| 906 } | |
| 76 | 907 if (offset == 1) { |
| 908 T(YAFFS_TRACE_OS, | |
| 909 (KERN_DEBUG "yaffs_readdir: entry .. ino %d \n", | |
| 910 (int)f->f_dentry->d_parent->d_inode->i_ino)); | |
| 911 if (filldir | |
| 912 (dirent, "..", 2, offset, | |
| 913 f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { | |
| 7 | 914 goto out; |
| 915 } | |
| 916 offset++; | |
| 917 f->f_pos++; | |
| 918 } | |
| 76 | 919 |
| 7 | 920 curoffs = 1; |
| 76 | 921 |
| 117 | 922 /* If the directory has changed since the open or last call to |
| 923 readdir, rewind to after the 2 canned entries. */ | |
| 924 | |
| 925 if (f->f_version != inode->i_version) { | |
| 926 offset = 2; | |
| 927 f->f_pos = offset; | |
| 928 f->f_version = inode->i_version; | |
| 929 } | |
| 930 | |
| 76 | 931 list_for_each(i, &obj->variant.directoryVariant.children) { |
| 7 | 932 curoffs++; |
| 76 | 933 if (curoffs >= offset) { |
| 934 l = list_entry(i, yaffs_Object, siblings); | |
| 935 | |
| 936 yaffs_GetObjectName(l, name, | |
| 937 YAFFS_MAX_NAME_LENGTH + 1); | |
| 938 T(YAFFS_TRACE_OS, | |
| 939 (KERN_DEBUG "yaffs_readdir: %s inode %d\n", name, | |
| 940 yaffs_GetObjectInode(l))); | |
| 941 | |
| 942 if (filldir(dirent, | |
| 943 name, | |
| 944 strlen(name), | |
| 945 offset, | |
| 946 yaffs_GetObjectInode(l), | |
| 947 yaffs_GetObjectType(l)) | |
| 948 < 0) { | |
| 7 | 949 goto up_and_out; |
| 950 } | |
| 76 | 951 |
| 7 | 952 offset++; |
| 76 | 953 f->f_pos++; |
| 7 | 954 } |
| 955 } | |
| 956 | |
| 76 | 957 up_and_out: |
| 958 out: | |
| 959 | |
| 960 yaffs_GrossUnlock(dev); | |
| 961 | |
| 7 | 962 return 0; |
| 963 } | |
| 964 | |
| 965 /* | |
| 966 * File creation. Allocate an inode, and we're done.. | |
| 967 */ | |
| 968 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 76 | 969 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, |
| 970 dev_t rdev) | |
| 7 | 971 #else |
| 76 | 972 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, |
| 973 int rdev) | |
| 7 | 974 #endif |
| 975 { | |
| 976 struct inode *inode; | |
| 76 | 977 |
| 7 | 978 yaffs_Object *obj = NULL; |
| 979 yaffs_Device *dev; | |
| 76 | 980 |
| 7 | 981 yaffs_Object *parent = yaffs_InodeToObject(dir); |
| 76 | 982 |
| 7 | 983 int error = -ENOSPC; |
|
36
e98ab6dcd6b7
Set the correct uid/gid of newly created files when: use fsuid & fsgid and take care when the SGID bit is set on the parent directory.
luc <luc>
parents:
32
diff
changeset
|
984 uid_t uid = current->fsuid; |
|
e98ab6dcd6b7
Set the correct uid/gid of newly created files when: use fsuid & fsgid and take care when the SGID bit is set on the parent directory.
luc <luc>
parents:
32
diff
changeset
|
985 gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; |
| 133 | 986 |
| 987 if((dir->i_mode & S_ISGID) && S_ISDIR(mode)) | |
| 988 mode |= S_ISGID; | |
| 7 | 989 |
| 76 | 990 if (parent) { |
| 991 T(YAFFS_TRACE_OS, | |
| 992 (KERN_DEBUG "yaffs_mknod: parent object %d type %d\n", | |
| 993 parent->objectId, parent->variantType)); | |
| 994 } else { | |
| 995 T(YAFFS_TRACE_OS, | |
| 996 (KERN_DEBUG "yaffs_mknod: could not get parent object\n")); | |
| 7 | 997 return -EPERM; |
| 998 } | |
| 76 | 999 |
| 1000 T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, " | |
| 1001 "mode %x dev %x\n", | |
| 1002 dentry->d_name.name, mode, rdev)); | |
| 7 | 1003 |
| 1004 dev = parent->myDev; | |
| 76 | 1005 |
| 7 | 1006 yaffs_GrossLock(dev); |
| 1007 | |
| 76 | 1008 switch (mode & S_IFMT) { |
| 1009 default: | |
| 1010 /* Special (socket, fifo, device...) */ | |
| 1011 T(YAFFS_TRACE_OS, (KERN_DEBUG | |
| 1012 "yaffs_mknod: making special\n")); | |
| 12 | 1013 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
| 76 | 1014 obj = |
| 1015 yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, | |
| 1016 gid, old_encode_dev(rdev)); | |
| 12 | 1017 #else |
| 76 | 1018 obj = |
| 1019 yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, | |
| 1020 gid, rdev); | |
| 1021 #endif | |
| 1022 break; | |
| 1023 case S_IFREG: /* file */ | |
| 1024 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); | |
| 1025 obj = | |
| 1026 yaffs_MknodFile(parent, dentry->d_name.name, mode, uid, | |
| 1027 gid); | |
| 1028 break; | |
| 1029 case S_IFDIR: /* directory */ | |
| 1030 T(YAFFS_TRACE_OS, | |
| 1031 (KERN_DEBUG "yaffs_mknod: making directory\n")); | |
| 1032 obj = | |
| 1033 yaffs_MknodDirectory(parent, dentry->d_name.name, mode, | |
| 1034 uid, gid); | |
| 1035 break; | |
| 1036 case S_IFLNK: /* symlink */ | |
| 1037 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); | |
| 1038 obj = NULL; /* Do we ever get here? */ | |
| 1039 break; | |
| 7 | 1040 } |
|
106
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1041 |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1042 /* Can not call yaffs_get_inode() with gross lock held */ |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1043 yaffs_GrossUnlock(dev); |
| 76 | 1044 |
| 1045 if (obj) { | |
| 7 | 1046 inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); |
| 1047 d_instantiate(dentry, inode); | |
| 76 | 1048 T(YAFFS_TRACE_OS, |
| 1049 (KERN_DEBUG "yaffs_mknod created object %d count = %d\n", | |
| 1050 obj->objectId, atomic_read(&inode->i_count))); | |
| 7 | 1051 error = 0; |
| 76 | 1052 } else { |
| 1053 T(YAFFS_TRACE_OS, | |
| 1054 (KERN_DEBUG "yaffs_mknod failed making object\n")); | |
| 7 | 1055 error = -ENOMEM; |
| 1056 } | |
| 1057 | |
| 1058 return error; | |
| 1059 } | |
| 1060 | |
| 76 | 1061 static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
| 7 | 1062 { |
| 1063 int retVal; | |
| 76 | 1064 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mkdir\n")); |
| 1065 retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0); | |
| 7 | 1066 #if 0 |
| 76 | 1067 /* attempt to fix dir bug - didn't work */ |
| 1068 if (!retVal) { | |
| 7 | 1069 dget(dentry); |
| 1070 } | |
| 1071 #endif | |
| 1072 return retVal; | |
| 1073 } | |
| 1074 | |
| 1075 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 76 | 1076 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, |
| 1077 struct nameidata *n) | |
| 7 | 1078 #else |
| 1079 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode) | |
| 1080 #endif | |
| 1081 { | |
| 76 | 1082 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_create\n")); |
| 7 | 1083 return yaffs_mknod(dir, dentry, mode | S_IFREG, 0); |
| 1084 } | |
| 1085 | |
| 76 | 1086 static int yaffs_unlink(struct inode *dir, struct dentry *dentry) |
| 7 | 1087 { |
| 1088 int retVal; | |
| 76 | 1089 |
| 7 | 1090 yaffs_Device *dev; |
| 76 | 1091 |
| 1092 T(YAFFS_TRACE_OS, | |
| 1093 (KERN_DEBUG "yaffs_unlink %d:%s\n", (int)(dir->i_ino), | |
| 1094 dentry->d_name.name)); | |
| 1095 | |
| 7 | 1096 dev = yaffs_InodeToObject(dir)->myDev; |
| 76 | 1097 |
| 7 | 1098 yaffs_GrossLock(dev); |
| 76 | 1099 |
| 1100 retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name); | |
| 1101 | |
| 1102 if (retVal == YAFFS_OK) { | |
| 7 | 1103 dentry->d_inode->i_nlink--; |
| 117 | 1104 dir->i_version++; |
| 1105 yaffs_GrossUnlock(dev); | |
| 7 | 1106 mark_inode_dirty(dentry->d_inode); |
| 1107 return 0; | |
| 1108 } | |
| 117 | 1109 yaffs_GrossUnlock(dev); |
| 1110 return -ENOTEMPTY; | |
| 7 | 1111 } |
| 1112 | |
| 1113 /* | |
| 1114 * Create a link... | |
| 1115 */ | |
| 76 | 1116 static int yaffs_link(struct dentry *old_dentry, struct inode *dir, |
| 1117 struct dentry *dentry) | |
| 7 | 1118 { |
| 1119 struct inode *inode = old_dentry->d_inode; | |
| 1120 yaffs_Object *obj = NULL; | |
| 76 | 1121 yaffs_Object *link = NULL; |
| 7 | 1122 yaffs_Device *dev; |
| 76 | 1123 |
| 1124 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_link\n")); | |
| 1125 | |
| 7 | 1126 obj = yaffs_InodeToObject(inode); |
| 1127 dev = obj->myDev; | |
| 76 | 1128 |
| 7 | 1129 yaffs_GrossLock(dev); |
| 1130 | |
| 76 | 1131 if (!S_ISDIR(inode->i_mode)) /* Don't link directories */ |
| 7 | 1132 { |
| 76 | 1133 link = |
| 1134 yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name, | |
| 1135 obj); | |
| 7 | 1136 } |
| 1137 | |
| 76 | 1138 if (link) { |
| 1139 old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj); | |
| 7 | 1140 d_instantiate(dentry, old_dentry->d_inode); |
| 1141 atomic_inc(&old_dentry->d_inode->i_count); | |
| 76 | 1142 T(YAFFS_TRACE_OS, |
| 1143 (KERN_DEBUG "yaffs_link link count %d i_count %d\n", | |
| 1144 old_dentry->d_inode->i_nlink, | |
| 1145 atomic_read(&old_dentry->d_inode->i_count))); | |
| 1146 | |
| 7 | 1147 } |
| 76 | 1148 |
| 7 | 1149 yaffs_GrossUnlock(dev); |
| 1150 | |
| 76 | 1151 if (link) { |
| 1152 | |
| 7 | 1153 return 0; |
| 1154 } | |
| 76 | 1155 |
| 1156 return -EPERM; | |
| 7 | 1157 } |
| 1158 | |
| 76 | 1159 static int yaffs_symlink(struct inode *dir, struct dentry *dentry, |
| 1160 const char *symname) | |
| 7 | 1161 { |
| 1162 yaffs_Object *obj; | |
| 1163 yaffs_Device *dev; | |
|
36
e98ab6dcd6b7
Set the correct uid/gid of newly created files when: use fsuid & fsgid and take care when the SGID bit is set on the parent directory.
luc <luc>
parents:
32
diff
changeset
|
1164 uid_t uid = current->fsuid; |
|
e98ab6dcd6b7
Set the correct uid/gid of newly created files when: use fsuid & fsgid and take care when the SGID bit is set on the parent directory.
luc <luc>
parents:
32
diff
changeset
|
1165 gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; |
| 76 | 1166 |
| 1167 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_symlink\n")); | |
| 1168 | |
| 7 | 1169 dev = yaffs_InodeToObject(dir)->myDev; |
| 1170 yaffs_GrossLock(dev); | |
| 76 | 1171 obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, |
| 1172 S_IFLNK | S_IRWXUGO, uid, gid, symname); | |
| 7 | 1173 yaffs_GrossUnlock(dev); |
| 1174 | |
| 76 | 1175 if (obj) { |
| 7 | 1176 |
| 76 | 1177 struct inode *inode; |
| 1178 | |
|
22
0b57027b96fe
Some improvements to garbage collection and st_xxx to yst_xxx changes
charles <charles>
parents:
19
diff
changeset
|
1179 inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); |
| 7 | 1180 d_instantiate(dentry, inode); |
| 76 | 1181 T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink created OK\n")); |
| 7 | 1182 return 0; |
| 76 | 1183 } else { |
| 1184 T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink not created\n")); | |
| 7 | 1185 |
| 1186 } | |
| 76 | 1187 |
| 7 | 1188 return -ENOMEM; |
| 1189 } | |
| 1190 | |
| 76 | 1191 static int yaffs_sync_object(struct file *file, struct dentry *dentry, |
| 1192 int datasync) | |
| 7 | 1193 { |
| 1194 | |
| 1195 yaffs_Object *obj; | |
| 1196 yaffs_Device *dev; | |
| 76 | 1197 |
| 7 | 1198 obj = yaffs_DentryToObject(dentry); |
| 1199 | |
| 1200 dev = obj->myDev; | |
| 76 | 1201 |
| 1202 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_object\n")); | |
| 7 | 1203 yaffs_GrossLock(dev); |
| 76 | 1204 yaffs_FlushFile(obj, 1); |
| 7 | 1205 yaffs_GrossUnlock(dev); |
| 1206 return 0; | |
| 1207 } | |
| 1208 | |
| 1209 /* | |
| 1210 * The VFS layer already does all the dentry stuff for rename. | |
| 1211 * | |
| 1212 * NB: POSIX says you can rename an object over an old object of the same name | |
| 1213 */ | |
| 76 | 1214 static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, |
| 1215 struct inode *new_dir, struct dentry *new_dentry) | |
| 7 | 1216 { |
| 1217 yaffs_Device *dev; | |
| 1218 int retVal = YAFFS_FAIL; | |
| 1219 yaffs_Object *target; | |
| 76 | 1220 |
| 83 | 1221 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_rename\n")); |
| 7 | 1222 dev = yaffs_InodeToObject(old_dir)->myDev; |
| 1223 | |
| 1224 yaffs_GrossLock(dev); | |
| 76 | 1225 |
| 1226 /* Check if the target is an existing directory that is not empty. */ | |
| 1227 target = | |
| 1228 yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), | |
| 1229 new_dentry->d_name.name); | |
| 83 | 1230 |
| 1231 | |
| 76 | 1232 |
| 1233 if (target && | |
| 1234 target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && | |
| 1235 !list_empty(&target->variant.directoryVariant.children)) { | |
| 83 | 1236 |
| 1237 T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n")); | |
| 1238 | |
| 7 | 1239 retVal = YAFFS_FAIL; |
| 76 | 1240 } else { |
| 1241 | |
| 1242 /* Now does unlinking internally using shadowing mechanism */ | |
| 83 | 1243 T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n")); |
| 1244 | |
| 76 | 1245 retVal = |
| 1246 yaffs_RenameObject(yaffs_InodeToObject(old_dir), | |
| 1247 old_dentry->d_name.name, | |
| 1248 yaffs_InodeToObject(new_dir), | |
| 1249 new_dentry->d_name.name); | |
| 1250 | |
| 7 | 1251 } |
| 1252 yaffs_GrossUnlock(dev); | |
| 76 | 1253 |
| 1254 if (retVal == YAFFS_OK) { | |
| 88 | 1255 if(target) { |
| 1256 new_dentry->d_inode->i_nlink--; | |
| 1257 mark_inode_dirty(new_dentry->d_inode); | |
| 1258 } | |
| 76 | 1259 |
| 7 | 1260 return 0; |
| 76 | 1261 } else { |
| 7 | 1262 return -ENOTEMPTY; |
| 1263 } | |
| 1264 | |
| 1265 } | |
| 1266 | |
| 1267 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) | |
| 1268 { | |
| 1269 struct inode *inode = dentry->d_inode; | |
| 1270 int error; | |
| 1271 yaffs_Device *dev; | |
| 76 | 1272 |
| 1273 T(YAFFS_TRACE_OS, | |
| 1274 (KERN_DEBUG "yaffs_setattr of object %d\n", | |
| 1275 yaffs_InodeToObject(inode)->objectId)); | |
| 1276 | |
| 1277 if ((error = inode_change_ok(inode, attr)) == 0) { | |
| 1278 | |
| 7 | 1279 dev = yaffs_InodeToObject(inode)->myDev; |
| 1280 yaffs_GrossLock(dev); | |
| 76 | 1281 if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) == |
| 1282 YAFFS_OK) { | |
| 7 | 1283 error = 0; |
| 76 | 1284 } else { |
| 7 | 1285 error = -EPERM; |
| 1286 } | |
| 1287 yaffs_GrossUnlock(dev); | |
| 23 | 1288 if (!error) |
| 76 | 1289 error = inode_setattr(inode, attr); |
| 7 | 1290 } |
| 1291 return error; | |
| 1292 } | |
| 1293 | |
| 143 | 1294 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1295 static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) | |
| 1296 { | |
| 1297 yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; | |
| 1298 struct super_block *sb = dentry->d_sb; | |
| 1299 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 7 | 1300 static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf) |
| 143 | 1301 { |
| 1302 yaffs_Device *dev = yaffs_SuperToDevice(sb); | |
| 7 | 1303 #else |
| 1304 static int yaffs_statfs(struct super_block *sb, struct statfs *buf) | |
| 143 | 1305 { |
| 1306 yaffs_Device *dev = yaffs_SuperToDevice(sb); | |
| 7 | 1307 #endif |
| 15 | 1308 |
| 76 | 1309 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n")); |
| 7 | 1310 |
| 1311 yaffs_GrossLock(dev); | |
| 76 | 1312 |
| 7 | 1313 buf->f_type = YAFFS_MAGIC; |
| 1314 buf->f_bsize = sb->s_blocksize; | |
| 1315 buf->f_namelen = 255; | |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1316 if (sb->s_blocksize > dev->nDataBytesPerChunk) { |
| 76 | 1317 |
| 1318 buf->f_blocks = | |
| 1319 (dev->endBlock - dev->startBlock + | |
| 1320 1) * dev->nChunksPerBlock / (sb->s_blocksize / | |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1321 dev->nDataBytesPerChunk); |
| 76 | 1322 buf->f_bfree = |
| 1323 yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize / | |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1324 dev->nDataBytesPerChunk); |
| 76 | 1325 } else { |
| 1326 | |
| 1327 buf->f_blocks = | |
| 1328 (dev->endBlock - dev->startBlock + | |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1329 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk / |
| 76 | 1330 sb->s_blocksize); |
| 1331 buf->f_bfree = | |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1332 yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk / |
| 76 | 1333 sb->s_blocksize); |
| 15 | 1334 } |
| 7 | 1335 buf->f_files = 0; |
| 1336 buf->f_ffree = 0; | |
| 76 | 1337 buf->f_bavail = buf->f_bfree; |
| 1338 | |
| 7 | 1339 yaffs_GrossUnlock(dev); |
| 1340 return 0; | |
| 1341 } | |
| 1342 | |
| 129 | 1343 |
| 166 | 1344 /** |
| 129 | 1345 static int yaffs_do_sync_fs(struct super_block *sb) |
| 1346 { | |
| 1347 | |
| 1348 yaffs_Device *dev = yaffs_SuperToDevice(sb); | |
| 1349 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n")); | |
| 1350 | |
| 1351 if(sb->s_dirt) { | |
| 1352 yaffs_GrossLock(dev); | |
| 1353 | |
| 1354 if(dev) | |
| 1355 yaffs_CheckpointSave(dev); | |
| 1356 | |
| 1357 yaffs_GrossUnlock(dev); | |
| 1358 | |
| 1359 sb->s_dirt = 0; | |
| 1360 } | |
| 1361 return 0; | |
| 1362 } | |
| 166 | 1363 **/ |
| 129 | 1364 |
| 143 | 1365 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1366 static void yaffs_write_super(struct super_block *sb) | |
| 1367 #else | |
| 129 | 1368 static int yaffs_write_super(struct super_block *sb) |
| 143 | 1369 #endif |
| 129 | 1370 { |
| 1371 | |
| 1372 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n")); | |
| 143 | 1373 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) |
| 129 | 1374 return 0; /* yaffs_do_sync_fs(sb);*/ |
| 143 | 1375 #endif |
| 129 | 1376 } |
| 1377 | |
| 1378 | |
| 143 | 1379 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1380 static int yaffs_sync_fs(struct super_block *sb, int wait) | |
| 1381 #else | |
| 129 | 1382 static int yaffs_sync_fs(struct super_block *sb) |
| 143 | 1383 #endif |
| 129 | 1384 { |
| 1385 | |
| 1386 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); | |
| 1387 | |
| 1388 return 0; /* yaffs_do_sync_fs(sb);*/ | |
| 1389 | |
| 1390 } | |
| 1391 | |
| 1392 | |
| 76 | 1393 static void yaffs_read_inode(struct inode *inode) |
| 7 | 1394 { |
|
106
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1395 /* NB This is called as a side effect of other functions, but |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1396 * we had to release the lock to prevent deadlocks, so |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1397 * need to lock again. |
| 76 | 1398 */ |
| 1399 | |
| 1400 yaffs_Object *obj; | |
| 7 | 1401 yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb); |
| 76 | 1402 |
| 1403 T(YAFFS_TRACE_OS, | |
| 1404 (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); | |
| 7 | 1405 |
|
106
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1406 yaffs_GrossLock(dev); |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1407 |
| 76 | 1408 obj = yaffs_FindObjectByNumber(dev, inode->i_ino); |
| 1409 | |
| 1410 yaffs_FillInodeFromObject(inode, obj); | |
| 7 | 1411 |
|
106
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1412 yaffs_GrossUnlock(dev); |
| 7 | 1413 } |
| 1414 | |
| 27 | 1415 static LIST_HEAD(yaffs_dev_list); |
| 7 | 1416 |
| 1417 static void yaffs_put_super(struct super_block *sb) | |
| 1418 { | |
| 1419 yaffs_Device *dev = yaffs_SuperToDevice(sb); | |
| 76 | 1420 |
| 129 | 1421 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n")); |
| 1422 | |
| 7 | 1423 yaffs_GrossLock(dev); |
| 123 | 1424 |
| 1425 yaffs_FlushEntireDeviceCache(dev); | |
| 1426 | |
| 76 | 1427 if (dev->putSuperFunc) { |
| 1428 dev->putSuperFunc(sb); | |
| 7 | 1429 } |
| 127 | 1430 |
| 1431 yaffs_CheckpointSave(dev); | |
| 7 | 1432 yaffs_Deinitialise(dev); |
| 127 | 1433 |
| 7 | 1434 yaffs_GrossUnlock(dev); |
| 1435 | |
| 27 | 1436 /* we assume this is protected by lock_kernel() in mount/umount */ |
| 1437 list_del(&dev->devList); | |
| 124 | 1438 |
| 1439 if(dev->spareBuffer){ | |
| 1440 YFREE(dev->spareBuffer); | |
| 1441 dev->spareBuffer = NULL; | |
| 1442 } | |
| 27 | 1443 |
| 7 | 1444 kfree(dev); |
| 1445 } | |
| 1446 | |
| 1447 | |
| 76 | 1448 static void yaffs_MTDPutSuper(struct super_block *sb) |
| 7 | 1449 { |
| 76 | 1450 |
| 7 | 1451 struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; |
| 76 | 1452 |
| 1453 if (mtd->sync) { | |
| 7 | 1454 mtd->sync(mtd); |
| 1455 } | |
| 76 | 1456 |
| 7 | 1457 put_mtd_device(mtd); |
| 1458 } | |
| 1459 | |
| 1460 | |
| 129 | 1461 static void yaffs_MarkSuperBlockDirty(void *vsb) |
| 1462 { | |
| 1463 struct super_block *sb = (struct super_block *)vsb; | |
| 1464 | |
| 1465 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb)); | |
| 1466 // if(sb) | |
| 1467 // sb->s_dirt = 1; | |
| 1468 } | |
| 1469 | |
| 76 | 1470 static struct super_block *yaffs_internal_read_super(int yaffsVersion, |
| 1471 struct super_block *sb, | |
| 1472 void *data, int silent) | |
| 7 | 1473 { |
| 1474 int nBlocks; | |
| 76 | 1475 struct inode *inode = NULL; |
| 1476 struct dentry *root; | |
| 27 | 1477 yaffs_Device *dev = 0; |
| 76 | 1478 char devname_buf[BDEVNAME_SIZE + 1]; |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1479 struct mtd_info *mtd; |
| 7 | 1480 int err; |
| 76 | 1481 |
| 7 | 1482 sb->s_magic = YAFFS_MAGIC; |
| 1483 sb->s_op = &yaffs_super_ops; | |
| 76 | 1484 |
| 1485 if (!sb) | |
| 1486 printk(KERN_INFO "yaffs: sb is NULL\n"); | |
| 1487 else if (!sb->s_dev) | |
| 1488 printk(KERN_INFO "yaffs: sb->s_dev is NULL\n"); | |
| 1489 else if (!yaffs_devname(sb, devname_buf)) | |
| 1490 printk(KERN_INFO "yaffs: devname is NULL\n"); | |
| 7 | 1491 else |
| 76 | 1492 printk(KERN_INFO "yaffs: dev is %d name is \"%s\"\n", |
| 1493 sb->s_dev, | |
| 1494 yaffs_devname(sb, devname_buf)); | |
| 7 | 1495 |
| 1496 sb->s_blocksize = PAGE_CACHE_SIZE; | |
| 1497 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | |
| 76 | 1498 T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion)); |
| 1499 T(YAFFS_TRACE_OS, | |
| 1500 ("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize))); | |
| 7 | 1501 |
| 1502 #ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY | |
| 76 | 1503 T(YAFFS_TRACE_OS, |
| 1504 ("yaffs: Write verification disabled. All guarantees " | |
| 1505 "null and void\n")); | |
| 7 | 1506 #endif |
| 1507 | |
| 76 | 1508 T(YAFFS_TRACE_ALWAYS, ("yaffs: Attempting MTD mount on %u.%u, " |
| 1509 "\"%s\"\n", | |
| 1510 MAJOR(sb->s_dev), MINOR(sb->s_dev), | |
| 1511 yaffs_devname(sb, devname_buf))); | |
| 7 | 1512 |
| 76 | 1513 /* Check it's an mtd device..... */ |
| 1514 if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { | |
| 1515 return NULL; /* This isn't an mtd device */ | |
| 1516 } | |
| 1517 /* Get the device */ | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1518 mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); |
| 76 | 1519 if (!mtd) { |
| 1520 T(YAFFS_TRACE_ALWAYS, | |
| 1521 ("yaffs: MTD device #%u doesn't appear to exist\n", | |
| 1522 MINOR(sb->s_dev))); | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1523 return NULL; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1524 } |
| 76 | 1525 /* Check it's NAND */ |
| 1526 if (mtd->type != MTD_NANDFLASH) { | |
| 1527 T(YAFFS_TRACE_ALWAYS, | |
| 1528 ("yaffs: MTD device is not NAND it's type %d\n", mtd->type)); | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1529 return NULL; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1530 } |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1531 |
| 76 | 1532 T(YAFFS_TRACE_OS, (" erase %p\n", mtd->erase)); |
| 1533 T(YAFFS_TRACE_OS, (" read %p\n", mtd->read)); | |
| 1534 T(YAFFS_TRACE_OS, (" write %p\n", mtd->write)); | |
| 1535 T(YAFFS_TRACE_OS, (" readoob %p\n", mtd->read_oob)); | |
| 1536 T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob)); | |
| 1537 T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad)); | |
| 1538 T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad)); | |
| 143 | 1539 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1540 T(YAFFS_TRACE_OS, (" writesize %d\n", mtd->writesize)); | |
| 1541 #else | |
| 76 | 1542 T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock)); |
| 143 | 1543 #endif |
| 76 | 1544 T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); |
| 1545 T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); | |
| 1546 T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); | |
| 108 | 1547 |
| 109 | 1548 #ifdef CONFIG_YAFFS_AUTO_YAFFS2 |
| 108 | 1549 |
| 1550 if (yaffsVersion == 1 && | |
| 143 | 1551 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1552 mtd->writesize >= 2048) { | |
| 1553 #else | |
| 108 | 1554 mtd->oobblock >= 2048) { |
| 143 | 1555 #endif |
| 108 | 1556 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); |
| 1557 yaffsVersion = 2; | |
| 1558 } | |
| 137 | 1559 |
| 1560 /* Added NCB 26/5/2006 for completeness */ | |
| 1561 if (yaffsVersion == 2 && | |
| 143 | 1562 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1563 mtd->writesize == 512) { | |
| 1564 #else | |
| 148 | 1565 mtd->oobblock == 512) { |
| 143 | 1566 #endif |
| 137 | 1567 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); |
| 1568 yaffsVersion = 1; | |
| 1569 } | |
| 1570 | |
| 108 | 1571 #endif |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1572 |
| 76 | 1573 if (yaffsVersion == 2) { |
| 1574 /* Check for version 2 style functions */ | |
| 1575 if (!mtd->erase || | |
| 1576 !mtd->block_isbad || | |
| 1577 !mtd->block_markbad || | |
| 1578 !mtd->read || | |
| 1579 !mtd->write || | |
| 143 | 1580 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1581 !mtd->read_oob || !mtd->write_oob) { | |
| 1582 #else | |
| 76 | 1583 !mtd->write_ecc || |
| 1584 !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { | |
| 143 | 1585 #endif |
| 76 | 1586 T(YAFFS_TRACE_ALWAYS, |
| 1587 ("yaffs: MTD device does not support required " | |
| 1588 "functions\n"));; | |
| 7 | 1589 return NULL; |
| 1590 } | |
| 76 | 1591 |
| 143 | 1592 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1593 if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE || | |
| 1594 #else | |
| 76 | 1595 if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE || |
| 143 | 1596 #endif |
| 76 | 1597 mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) { |
| 1598 T(YAFFS_TRACE_ALWAYS, | |
|
126
2e7fd6d40037
Fix a couple of mistakes in TRACE/Error messages. Update copyright date.
wookey <wookey>
parents:
124
diff
changeset
|
1599 ("yaffs: MTD device does not have the " |
| 76 | 1600 "right page sizes\n")); |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1601 return NULL; |
| 7 | 1602 } |
| 76 | 1603 } else { |
| 1604 /* Check for V1 style functions */ | |
| 1605 if (!mtd->erase || | |
| 1606 !mtd->read || | |
| 1607 !mtd->write || | |
| 143 | 1608 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1609 !mtd->read_oob || !mtd->write_oob) { | |
| 1610 #else | |
| 76 | 1611 !mtd->write_ecc || |
| 1612 !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) { | |
| 143 | 1613 #endif |
| 76 | 1614 T(YAFFS_TRACE_ALWAYS, |
| 1615 ("yaffs: MTD device does not support required " | |
| 1616 "functions\n"));; | |
| 1617 return NULL; | |
| 1618 } | |
| 1619 | |
| 143 | 1620 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1621 if (mtd->writesize < YAFFS_BYTES_PER_CHUNK || | |
| 1622 #else | |
| 1623 if (mtd->oobblock < YAFFS_BYTES_PER_CHUNK || | |
| 1624 #endif | |
| 76 | 1625 mtd->oobsize != YAFFS_BYTES_PER_SPARE) { |
| 1626 T(YAFFS_TRACE_ALWAYS, | |
| 1627 ("yaffs: MTD device does not support have the " | |
| 1628 "right page sizes\n")); | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1629 return NULL; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1630 } |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1631 } |
| 7 | 1632 |
| 76 | 1633 /* OK, so if we got here, we have an MTD that's NAND and looks |
| 1634 * like it has the right capabilities | |
| 1635 * Set the yaffs_Device up for mtd | |
| 1636 */ | |
| 7 | 1637 |
| 1638 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 76 | 1639 sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); |
| 7 | 1640 #else |
| 76 | 1641 sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); |
| 7 | 1642 #endif |
| 76 | 1643 if (!dev) { |
| 1644 /* Deep shit could not allocate device structure */ | |
| 1645 T(YAFFS_TRACE_ALWAYS, | |
| 1646 ("yaffs_read_super: Failed trying to allocate " | |
| 1647 "yaffs_Device. \n")); | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1648 return NULL; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1649 } |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1650 |
| 76 | 1651 memset(dev, 0, sizeof(yaffs_Device)); |
| 1652 dev->genericDevice = mtd; | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1653 dev->name = mtd->name; |
| 7 | 1654 |
| 76 | 1655 /* Set up the memory size parameters.... */ |
| 1656 | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1657 nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1658 dev->startBlock = 0; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1659 dev->endBlock = nBlocks - 1; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1660 dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1661 dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1662 dev->nReservedBlocks = 5; |
| 76 | 1663 dev->nShortOpCaches = 10; /* Enable short op caching */ |
| 7 | 1664 |
| 76 | 1665 /* ... and the functions. */ |
| 1666 if (yaffsVersion == 2) { | |
| 1667 dev->writeChunkWithTagsToNAND = | |
| 1668 nandmtd2_WriteChunkWithTagsToNAND; | |
| 1669 dev->readChunkWithTagsFromNAND = | |
| 1670 nandmtd2_ReadChunkWithTagsFromNAND; | |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1671 dev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1672 dev->queryNANDBlock = nandmtd2_QueryNANDBlock; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1673 dev->spareBuffer = YMALLOC(mtd->oobsize); |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1674 dev->isYaffs2 = 1; |
| 143 | 1675 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1676 dev->nDataBytesPerChunk = mtd->writesize; |
| 143 | 1677 dev->nChunksPerBlock = mtd->erasesize / mtd->writesize; |
| 1678 #else | |
|
146
1a32267ef1c1
Add large NAND support and improve retirement handling
charles <charles>
parents:
143
diff
changeset
|
1679 dev->nDataBytesPerChunk = mtd->oobblock; |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1680 dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; |
| 143 | 1681 #endif |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1682 nBlocks = mtd->size / mtd->erasesize; |
| 131 | 1683 |
| 165 | 1684 dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS; |
| 129 | 1685 dev->startBlock = 0; |
| 7 | 1686 dev->endBlock = nBlocks - 1; |
| 76 | 1687 } else { |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1688 dev->writeChunkToNAND = nandmtd_WriteChunkToNAND; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1689 dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1690 dev->isYaffs2 = 0; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1691 } |
| 76 | 1692 /* ... and common functions */ |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1693 dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; |
|
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1694 dev->initialiseNAND = nandmtd_InitialiseNAND; |
| 76 | 1695 |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1696 dev->putSuperFunc = yaffs_MTDPutSuper; |
| 129 | 1697 |
| 1698 dev->superBlock = (void *)sb; | |
| 1699 dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty; | |
| 1700 | |
| 76 | 1701 |
|
61
49f66fca0b09
newconfig: use YAFFS_DOES_ECC instead of USE_NANDECC
luc <luc>
parents:
59
diff
changeset
|
1702 #ifndef CONFIG_YAFFS_DOES_ECC |
|
59
d6ff669317b8
Adapt the code structure after removing of the yaffsram support.
luc <luc>
parents:
58
diff
changeset
|
1703 dev->useNANDECC = 1; |
| 7 | 1704 #endif |
| 1705 | |
| 104 | 1706 #ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES |
| 1707 dev->wideTnodesDisabled = 1; | |
| 1708 #endif | |
| 1709 | |
| 27 | 1710 /* we assume this is protected by lock_kernel() in mount/umount */ |
| 1711 list_add_tail(&dev->devList, &yaffs_dev_list); | |
| 1712 | |
| 7 | 1713 init_MUTEX(&dev->grossLock); |
| 76 | 1714 |
| 7 | 1715 yaffs_GrossLock(dev); |
| 76 | 1716 |
| 7 | 1717 err = yaffs_GutsInitialise(dev); |
| 1718 | |
| 76 | 1719 T(YAFFS_TRACE_OS, |
| 1720 ("yaffs_read_super: guts initialised %s\n", | |
| 1721 (err == YAFFS_OK) ? "OK" : "FAILED")); | |
|
106
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1722 |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1723 /* Release lock before yaffs_get_inode() */ |
|
5b8f68c30468
Apply Reed's deadlocking fix (manually applied)
charles <charles>
parents:
104
diff
changeset
|
1724 yaffs_GrossUnlock(dev); |
| 7 | 1725 |
| 76 | 1726 /* Create root inode */ |
| 1727 if (err == YAFFS_OK) | |
| 1728 inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, | |
| 1729 yaffs_Root(dev)); | |
| 7 | 1730 |
| 1731 if (!inode) | |
| 1732 return NULL; | |
| 1733 | |
| 76 | 1734 inode->i_op = &yaffs_dir_inode_operations; |
| 1735 inode->i_fop = &yaffs_dir_operations; | |
| 1736 | |
| 1737 T(YAFFS_TRACE_OS, ("yaffs_read_super: got root inode\n")); | |
| 7 | 1738 |
| 1739 root = d_alloc_root(inode); | |
| 1740 | |
| 76 | 1741 T(YAFFS_TRACE_OS, ("yaffs_read_super: d_alloc_root done\n")); |
| 7 | 1742 |
| 1743 if (!root) { | |
| 1744 iput(inode); | |
| 1745 return NULL; | |
| 1746 } | |
| 1747 sb->s_root = root; | |
| 1748 | |
| 76 | 1749 T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n")); |
| 7 | 1750 return sb; |
| 1751 } | |
| 1752 | |
|
32
e344a10a3a1e
Move the internals read_super() functions near the declaration of
luc <luc>
parents:
29
diff
changeset
|
1753 |
|
e344a10a3a1e
Move the internals read_super() functions near the declaration of
luc <luc>
parents:
29
diff
changeset
|
1754 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) |
| 76 | 1755 static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, |
| 1756 int silent) | |
| 7 | 1757 { |
| 95 | 1758 return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; |
| 7 | 1759 } |
| 1760 | |
| 143 | 1761 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1762 static int yaffs_read_super(struct file_system_type *fs, | |
| 1763 int flags, const char *dev_name, | |
| 1764 void *data, struct vfsmount *mnt) | |
| 1765 { | |
| 1766 | |
| 1767 return get_sb_bdev(fs, flags, dev_name, data, | |
| 1768 yaffs_internal_read_super_mtd, mnt); | |
| 1769 } | |
| 1770 #else | |
| 76 | 1771 static struct super_block *yaffs_read_super(struct file_system_type *fs, |
| 1772 int flags, const char *dev_name, | |
| 1773 void *data) | |
| 7 | 1774 { |
| 1775 | |
| 76 | 1776 return get_sb_bdev(fs, flags, dev_name, data, |
| 1777 yaffs_internal_read_super_mtd); | |
| 7 | 1778 } |
| 143 | 1779 #endif |
| 7 | 1780 |
| 1781 static struct file_system_type yaffs_fs_type = { | |
| 76 | 1782 .owner = THIS_MODULE, |
| 1783 .name = "yaffs", | |
| 1784 .get_sb = yaffs_read_super, | |
| 1785 .kill_sb = kill_block_super, | |
| 1786 .fs_flags = FS_REQUIRES_DEV, | |
| 7 | 1787 }; |
| 1788 #else | |
| 76 | 1789 static struct super_block *yaffs_read_super(struct super_block *sb, void *data, |
| 1790 int silent) | |
| 7 | 1791 { |
| 76 | 1792 return yaffs_internal_read_super(1, sb, data, silent); |
| 7 | 1793 } |
| 1794 | |
| 76 | 1795 static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, |
| 1796 FS_REQUIRES_DEV); | |
| 7 | 1797 #endif |
| 1798 | |
| 1799 | |
| 49 | 1800 #ifdef CONFIG_YAFFS_YAFFS2 |
| 7 | 1801 |
| 1802 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) | |
| 76 | 1803 static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, |
| 1804 int silent) | |
|
32
e344a10a3a1e
Move the internals read_super() functions near the declaration of
luc <luc>
parents:
29
diff
changeset
|
1805 { |
| 95 | 1806 return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; |
|
32
e344a10a3a1e
Move the internals read_super() functions near the declaration of
luc <luc>
parents:
29
diff
changeset
|
1807 } |
|
e344a10a3a1e
Move the internals read_super() functions near the declaration of
luc <luc>
parents:
29
diff
changeset
|
1808 |
| 143 | 1809 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 1810 static int yaffs2_read_super(struct file_system_type *fs, | |
| 1811 int flags, const char *dev_name, void *data, | |
| 1812 struct vfsmount *mnt) | |
| 1813 { | |
| 1814 return get_sb_bdev(fs, flags, dev_name, data, | |
| 1815 yaffs2_internal_read_super_mtd, mnt); | |
| 1816 } | |
| 1817 #else | |
| 76 | 1818 static struct super_block *yaffs2_read_super(struct file_system_type *fs, |
| 1819 int flags, const char *dev_name, | |
| 1820 void *data) | |
| 7 | 1821 { |
| 1822 | |
| 76 | 1823 return get_sb_bdev(fs, flags, dev_name, data, |
| 1824 yaffs2_internal_read_super_mtd); | |
| 7 | 1825 } |
| 143 | 1826 #endif |
| 7 | 1827 |
| 1828 static struct file_system_type yaffs2_fs_type = { | |
| 76 | 1829 .owner = THIS_MODULE, |
| 1830 .name = "yaffs2", | |
| 1831 .get_sb = yaffs2_read_super, | |
| 1832 .kill_sb = kill_block_super, | |
| 1833 .fs_flags = FS_REQUIRES_DEV, | |
| 7 | 1834 }; |
| 1835 #else | |
| 76 | 1836 static struct super_block *yaffs2_read_super(struct super_block *sb, |
| 1837 void *data, int silent) | |
| 7 | 1838 { |
| 76 | 1839 return yaffs_internal_read_super(2, sb, data, silent); |
| 7 | 1840 } |
| 1841 | |
| 76 | 1842 static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, |
| 1843 FS_REQUIRES_DEV); | |
| 7 | 1844 #endif |
| 1845 | |
| 76 | 1846 #endif /* CONFIG_YAFFS_YAFFS2 */ |
| 7 | 1847 |
| 1848 static struct proc_dir_entry *my_proc_entry; | |
| 1849 | |
| 76 | 1850 static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) |
| 7 | 1851 { |
| 76 | 1852 buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); |
| 1853 buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); | |
| 1854 buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits); | |
| 1855 buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize); | |
| 1856 buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks); | |
| 1857 buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated); | |
| 1858 buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes); | |
| 1859 buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated); | |
| 1860 buf += sprintf(buf, "nFreeObjects....... %d\n", dev->nFreeObjects); | |
| 1861 buf += sprintf(buf, "nFreeChunks........ %d\n", dev->nFreeChunks); | |
| 1862 buf += sprintf(buf, "nPageWrites........ %d\n", dev->nPageWrites); | |
| 1863 buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads); | |
| 1864 buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures); | |
| 1865 buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies); | |
| 1866 buf += | |
| 1867 sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); | |
| 1868 buf += | |
| 1869 sprintf(buf, "passiveGCs......... %d\n", | |
| 1870 dev->passiveGarbageCollections); | |
| 1871 buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites); | |
| 1872 buf += sprintf(buf, "nRetireBlocks...... %d\n", dev->nRetiredBlocks); | |
| 1873 buf += sprintf(buf, "eccFixed........... %d\n", dev->eccFixed); | |
| 1874 buf += sprintf(buf, "eccUnfixed......... %d\n", dev->eccUnfixed); | |
| 1875 buf += sprintf(buf, "tagsEccFixed....... %d\n", dev->tagsEccFixed); | |
| 1876 buf += sprintf(buf, "tagsEccUnfixed..... %d\n", dev->tagsEccUnfixed); | |
| 1877 buf += sprintf(buf, "cacheHits.......... %d\n", dev->cacheHits); | |
| 1878 buf += sprintf(buf, "nDeletedFiles...... %d\n", dev->nDeletedFiles); | |
| 1879 buf += sprintf(buf, "nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles); | |
| 1880 buf += | |
| 1881 sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); | |
| 1882 buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC); | |
| 1883 buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); | |
| 7 | 1884 |
| 76 | 1885 return buf; |
| 7 | 1886 } |
| 1887 | |
| 76 | 1888 static int yaffs_proc_read(char *page, |
| 1889 char **start, | |
| 1890 off_t offset, int count, int *eof, void *data) | |
| 7 | 1891 { |
| 27 | 1892 struct list_head *item; |
| 1893 char *buf = page; | |
| 1894 int step = offset; | |
| 1895 int n = 0; | |
| 7 | 1896 |
| 27 | 1897 /* Get proc_file_read() to step 'offset' by one on each sucessive call. |
| 1898 * We use 'offset' (*ppos) to indicate where we are in devList. | |
| 1899 * This also assumes the user has posted a read buffer large | |
| 1900 * enough to hold the complete output; but that's life in /proc. | |
| 1901 */ | |
| 7 | 1902 |
| 27 | 1903 *(int *)start = 1; |
| 1904 | |
| 1905 /* Print header first */ | |
| 1906 if (step == 0) { | |
| 76 | 1907 buf += sprintf(buf, "YAFFS built:" __DATE__ " " __TIME__ |
| 1908 "\n%s\n%s\n", yaffs_fs_c_version, | |
| 1909 yaffs_guts_c_version); | |
| 27 | 1910 } |
| 7 | 1911 |
| 27 | 1912 /* hold lock_kernel while traversing yaffs_dev_list */ |
| 1913 lock_kernel(); | |
| 7 | 1914 |
| 27 | 1915 /* Locate and print the Nth entry. Order N-squared but N is small. */ |
| 1916 list_for_each(item, &yaffs_dev_list) { | |
| 1917 yaffs_Device *dev = list_entry(item, yaffs_Device, devList); | |
| 1918 if (n < step) { | |
| 1919 n++; | |
| 1920 continue; | |
| 1921 } | |
| 76 | 1922 buf += sprintf(buf, "\nDevice %d \"%s\"\n", n, dev->name); |
| 27 | 1923 buf = yaffs_dump_dev(buf, dev); |
| 1924 break; | |
| 1925 } | |
| 1926 unlock_kernel(); | |
| 1927 | |
| 76 | 1928 return buf - page < count ? buf - page : count; |
| 7 | 1929 } |
| 1930 | |
|
115
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1931 /** |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1932 * Set the verbosity of the warnings and error messages. |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1933 * |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1934 */ |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1935 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1936 static struct { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1937 char *mask_name; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1938 unsigned mask_bitfield; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1939 } mask_flags[] = { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1940 {"allocate", YAFFS_TRACE_ALLOCATE}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1941 {"always", YAFFS_TRACE_ALWAYS}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1942 {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1943 {"buffers", YAFFS_TRACE_BUFFERS}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1944 {"bug", YAFFS_TRACE_BUG}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1945 {"deletion", YAFFS_TRACE_DELETION}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1946 {"erase", YAFFS_TRACE_ERASE}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1947 {"error", YAFFS_TRACE_ERROR}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1948 {"gc_detail", YAFFS_TRACE_GC_DETAIL}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1949 {"gc", YAFFS_TRACE_GC}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1950 {"mtd", YAFFS_TRACE_MTD}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1951 {"nandaccess", YAFFS_TRACE_NANDACCESS}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1952 {"os", YAFFS_TRACE_OS}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1953 {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1954 {"scan", YAFFS_TRACE_SCAN}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1955 {"tracing", YAFFS_TRACE_TRACING}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1956 {"write", YAFFS_TRACE_WRITE}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1957 {"all", 0xffffffff}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1958 {"none", 0}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1959 {NULL, 0}, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1960 }; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1961 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1962 static int yaffs_proc_write(struct file *file, const char *buf, |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1963 unsigned long count, void *data) |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1964 { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1965 unsigned rg = 0, mask_bitfield; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1966 char *end, *mask_name; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1967 int i; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1968 int done = 0; |
| 166 | 1969 int add, len = 0; |
|
115
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1970 int pos = 0; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1971 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1972 rg = yaffs_traceMask; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1973 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1974 while (!done && (pos < count)) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1975 done = 1; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1976 while ((pos < count) && isspace(buf[pos])) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1977 pos++; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1978 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1979 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1980 switch (buf[pos]) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1981 case '+': |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1982 case '-': |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1983 case '=': |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1984 add = buf[pos]; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1985 pos++; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1986 break; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1987 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1988 default: |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1989 add = ' '; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1990 break; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1991 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1992 mask_name = NULL; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1993 mask_bitfield = simple_strtoul(buf + pos, &end, 0); |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1994 if (end > buf + pos) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1995 mask_name = "numeral"; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1996 len = end - (buf + pos); |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1997 done = 0; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1998 } else { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
1999 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2000 for (i = 0; mask_flags[i].mask_name != NULL; i++) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2001 len = strlen(mask_flags[i].mask_name); |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2002 if (strncmp(buf + pos, mask_flags[i].mask_name, len) == 0) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2003 mask_name = mask_flags[i].mask_name; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2004 mask_bitfield = mask_flags[i].mask_bitfield; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2005 done = 0; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2006 break; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2007 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2008 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2009 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2010 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2011 if (mask_name != NULL) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2012 pos += len; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2013 done = 0; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2014 switch(add) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2015 case '-': |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2016 rg &= ~mask_bitfield; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2017 break; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2018 case '+': |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2019 rg |= mask_bitfield; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2020 break; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2021 case '=': |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2022 rg = mask_bitfield; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2023 break; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2024 default: |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2025 rg |= mask_bitfield; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2026 break; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2027 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2028 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2029 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2030 |
| 165 | 2031 yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS; |
| 2032 | |
|
115
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2033 if (rg & YAFFS_TRACE_ALWAYS) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2034 for (i = 0; mask_flags[i].mask_name != NULL; i++) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2035 char flag; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2036 flag = ((rg & mask_flags[i].mask_bitfield) == mask_flags[i].mask_bitfield) ? '+' : '-'; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2037 printk("%c%s\n", flag, mask_flags[i].mask_name); |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2038 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2039 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2040 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2041 return count; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2042 } |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2043 |
| 76 | 2044 /* Stuff to handle installation of file systems */ |
| 2045 struct file_system_to_install { | |
| 2046 struct file_system_type *fst; | |
| 2047 int installed; | |
| 7 | 2048 }; |
| 2049 | |
| 76 | 2050 static struct file_system_to_install fs_to_install[] = { |
| 83 | 2051 //#ifdef CONFIG_YAFFS_YAFFS1 |
| 76 | 2052 {&yaffs_fs_type, 0}, |
| 83 | 2053 //#endif |
| 2054 //#ifdef CONFIG_YAFFS_YAFFS2 | |
| 76 | 2055 {&yaffs2_fs_type, 0}, |
| 83 | 2056 //#endif |
| 76 | 2057 {NULL, 0} |
| 7 | 2058 }; |
| 2059 | |
| 2060 static int __init init_yaffs_fs(void) | |
| 2061 { | |
| 2062 int error = 0; | |
| 76 | 2063 struct file_system_to_install *fsinst; |
| 7 | 2064 |
| 76 | 2065 T(YAFFS_TRACE_ALWAYS, |
| 2066 ("yaffs " __DATE__ " " __TIME__ " Installing. \n")); | |
| 7 | 2067 |
| 76 | 2068 /* Install the proc_fs entry */ |
|
115
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2069 my_proc_entry = create_proc_entry("yaffs", |
| 76 | 2070 S_IRUGO | S_IFREG, |
|
115
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2071 &proc_root); |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2072 |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2073 if (my_proc_entry) { |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2074 my_proc_entry->write_proc = yaffs_proc_write; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2075 my_proc_entry->read_proc = yaffs_proc_read; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2076 my_proc_entry->data = NULL; |
|
06a072660af9
Add /proc interface for modifying debugging trace flags, from John M Cavallo.
tpoynor <tpoynor>
parents:
113
diff
changeset
|
2077 } else { |
| 76 | 2078 return -ENOMEM; |
| 2079 } | |
| 2080 | |
| 2081 /* Now add the file system entries */ | |
| 2082 | |
| 2083 fsinst = fs_to_install; | |
| 7 | 2084 |
| 76 | 2085 while (fsinst->fst && !error) { |
| 2086 error = register_filesystem(fsinst->fst); | |
| 2087 if (!error) { | |
| 2088 fsinst->installed = 1; | |
| 2089 } | |
| 2090 fsinst++; | |
| 2091 } | |
| 2092 | |
| 2093 /* Any errors? uninstall */ | |
| 2094 if (error) { | |
| 2095 fsinst = fs_to_install; | |
| 2096 | |
| 2097 while (fsinst->fst) { | |
| 2098 if (fsinst->installed) { | |
| 2099 unregister_filesystem(fsinst->fst); | |
| 2100 fsinst->installed = 0; | |
| 2101 } | |
| 2102 fsinst++; | |
| 2103 } | |
| 2104 } | |
| 2105 | |
| 2106 return error; | |
| 7 | 2107 } |
| 2108 | |
| 2109 static void __exit exit_yaffs_fs(void) | |
| 2110 { | |
| 2111 | |
| 76 | 2112 struct file_system_to_install *fsinst; |
| 2113 | |
| 2114 T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__ | |
| 2115 " removing. \n")); | |
| 2116 | |
| 2117 remove_proc_entry("yaffs", &proc_root); | |
| 7 | 2118 |
| 76 | 2119 fsinst = fs_to_install; |
| 2120 | |
| 2121 while (fsinst->fst) { | |
| 2122 if (fsinst->installed) { | |
| 2123 unregister_filesystem(fsinst->fst); | |
| 2124 fsinst->installed = 0; | |
| 2125 } | |
| 2126 fsinst++; | |
| 2127 } | |
| 7 | 2128 |
| 2129 } | |
| 2130 | |
| 2131 module_init(init_yaffs_fs) | |
| 2132 module_exit(exit_yaffs_fs) | |
| 2133 | |
| 2134 MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system"); | |
|
126
2e7fd6d40037
Fix a couple of mistakes in TRACE/Error messages. Update copyright date.
wookey <wookey>
parents:
124
diff
changeset
|
2135 MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2006"); |
| 7 | 2136 MODULE_LICENSE("GPL"); |
