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