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