Add generic sendfile method for yaffs2, also thereby allowing loopback mount.
[yaffs2.git] / yaffs_fs.c
index 02d6b82197e101a89a286068c4fcbd7f5b138024..3ded1fe8751bdfb8e52aa17daf507bd303702c87 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 const char *yaffs_fs_c_version =
-    "$Id: yaffs_fs.c,v 1.34 2005-11-14 21:00:54 charles Exp $";
+    "$Id: yaffs_fs.c,v 1.39 2006-01-24 22:22:52 tpoynor Exp $";
 extern const char *yaffs_guts_c_version;
 
 #include <linux/config.h>
@@ -171,6 +171,10 @@ static struct file_operations yaffs_file_operations = {
        .mmap = generic_file_mmap,
        .flush = yaffs_file_flush,
        .fsync = yaffs_sync_object,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+       .sendfile = generic_file_sendfile,
+#endif
+
 };
 
 static struct inode_operations yaffs_file_inode_operations = {
@@ -309,6 +313,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,
@@ -325,8 +332,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
@@ -336,7 +341,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 */
@@ -725,6 +729,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;
 }
@@ -940,6 +945,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);
@@ -954,8 +962,6 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
                error = -ENOMEM;
        }
 
-       yaffs_GrossUnlock(dev);
-
        return error;
 }
 
@@ -1236,8 +1242,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;
@@ -1246,10 +1253,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);
@@ -1358,6 +1368,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 */
@@ -1465,6 +1484,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);
 
@@ -1477,14 +1500,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;