X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_fs.c;h=fb3c13010ee93b55653b87cfc60ef2a6909e152a;hp=14fd0b8d04906ad39a955fdf506a58f5c24af311;hb=394fcf7b50181f9f4bde6748f1870de94c9e0732;hpb=549731ddfef7956f9c11c87697be04a075af953b diff --git a/yaffs_fs.c b/yaffs_fs.c index 14fd0b8..fb3c130 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -31,7 +31,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.33 2005-10-27 22:24:04 marty Exp $"; + "$Id: yaffs_fs.c,v 1.38 2005-12-15 20:27:56 charles Exp $"; extern const char *yaffs_guts_c_version; #include @@ -152,7 +152,11 @@ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, static int yaffs_readlink(struct dentry *dentry, char __user * buffer, int buflen); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); +#else static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); +#endif static struct address_space_operations yaffs_file_address_operations = { .readpage = yaffs_readpage, @@ -243,7 +247,11 @@ static int yaffs_readlink(struct dentry *dentry, char __user * buffer, return ret; } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) +#else static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) +#endif { unsigned char *alias; int ret; @@ -256,11 +264,19 @@ static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) yaffs_GrossUnlock(dev); if (!alias) - return -ENOMEM; + { + ret = -ENOMEM; + goto out; + } ret = vfs_follow_link(nd, alias); kfree(alias); +out: +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + return ERR_PTR (ret); +#else return ret; +#endif } struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, @@ -293,6 +309,9 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) dentry->d_name.name); obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */ + + /* Can't hold gross lock when calling yaffs_get_inode() */ + yaffs_GrossUnlock(dev); if (obj) { T(YAFFS_TRACE_OS, @@ -309,8 +328,6 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) /*dget(dentry); // try to solve directory bug */ d_add(dentry, inode); - yaffs_GrossUnlock(dev); - /* return dentry; */ return NULL; #endif @@ -320,7 +337,6 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n")); } - yaffs_GrossUnlock(dev); /* added NCB for 2.5/6 compatability - forces add even if inode is * NULL which creates dentry hash */ @@ -398,6 +414,9 @@ static void yaffs_delete_inode(struct inode *inode) yaffs_DeleteFile(obj); yaffs_GrossUnlock(dev); } +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + truncate_inode_pages (&inode->i_data, 0); +#endif clear_inode(inode); } @@ -706,6 +725,7 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, /* NB Side effect: iget calls back to yaffs_read_inode(). */ /* iget also increments the inode's i_count */ + /* NB You can't be holding grossLock or deadlock will happen! */ return inode; } @@ -921,6 +941,9 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, obj = NULL; /* Do we ever get here? */ break; } + + /* Can not call yaffs_get_inode() with gross lock held */ + yaffs_GrossUnlock(dev); if (obj) { inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); @@ -935,8 +958,6 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, error = -ENOMEM; } - yaffs_GrossUnlock(dev); - return error; } @@ -1217,8 +1238,9 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf) static void yaffs_read_inode(struct inode *inode) { - /* NB This is called as a side effect of other functions and - * thus gross locking should always be in place already. + /* NB This is called as a side effect of other functions, but + * we had to release the lock to prevent deadlocks, so + * need to lock again. */ yaffs_Object *obj; @@ -1227,10 +1249,13 @@ static void yaffs_read_inode(struct inode *inode) T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); + yaffs_GrossLock(dev); + obj = yaffs_FindObjectByNumber(dev, inode->i_ino); yaffs_FillInodeFromObject(inode, obj); + yaffs_GrossUnlock(dev); } static LIST_HEAD(yaffs_dev_list); @@ -1339,6 +1364,15 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); + +#ifdef CONFIG_YAFFS_AUTO_YAFFS2 + + if (yaffsVersion == 1 && + mtd->oobblock >= 2048) { + T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); + yaffsVersion = 2; + } +#endif if (yaffsVersion == 2) { /* Check for version 2 style functions */ @@ -1446,6 +1480,10 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, dev->useNANDECC = 1; #endif +#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES + dev->wideTnodesDisabled = 1; +#endif + /* we assume this is protected by lock_kernel() in mount/umount */ list_add_tail(&dev->devList, &yaffs_dev_list); @@ -1458,14 +1496,15 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, T(YAFFS_TRACE_OS, ("yaffs_read_super: guts initialised %s\n", (err == YAFFS_OK) ? "OK" : "FAILED")); + + /* Release lock before yaffs_get_inode() */ + yaffs_GrossUnlock(dev); /* Create root inode */ if (err == YAFFS_OK) inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_Root(dev)); - yaffs_GrossUnlock(dev); - if (!inode) return NULL;