yaffs: Batter read-only support handling
authorCharles Manning <cdhmanning@gmail.com>
Tue, 10 Aug 2010 00:38:32 +0000 (12:38 +1200)
committerCharles Manning <cdhmanning@gmail.com>
Tue, 10 Aug 2010 00:38:32 +0000 (12:38 +1200)
Check read only flags in both the mount flags and mtd flags.

If the mount is read only then don't do some clean ups or start the
background gc thread.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
yaffs_fs.c
yaffs_guts.c

index 8d1f3aa8da71cdd6670e6b2412c6eb4525721cf8..49ff8708d27067cfb1089beb3bdfdccfa17b3098 100644 (file)
@@ -2275,6 +2275,9 @@ static int yaffs_BackgroundStart(yaffs_Device *dev)
        int retval = 0;
        struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev);
 
        int retval = 0;
        struct yaffs_LinuxContext *context = yaffs_DeviceToLC(dev);
 
+       if(dev->readOnly)
+               return -1;
+
        context->bgRunning = 1;
 
        context->bgThread = kthread_run(yaffs_BackgroundThread,
        context->bgRunning = 1;
 
        context->bgThread = kthread_run(yaffs_BackgroundThread,
@@ -2566,6 +2569,8 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
        struct yaffs_LinuxContext *context = NULL;
        yaffs_DeviceParam *param;
 
        struct yaffs_LinuxContext *context = NULL;
        yaffs_DeviceParam *param;
 
+       int readOnly = 0;
+
        yaffs_options options;
 
        unsigned mount_id;
        yaffs_options options;
 
        unsigned mount_id;
@@ -2577,6 +2582,9 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
        sb->s_op = &yaffs_super_ops;
        sb->s_flags |= MS_NOATIME;
 
        sb->s_op = &yaffs_super_ops;
        sb->s_flags |= MS_NOATIME;
 
+       readOnly =((sb->s_flags & MS_RDONLY) != 0);
+
+
 #ifdef YAFFS_COMPILE_EXPORTFS
        sb->s_export_op = &yaffs_export_ops;
 #endif
 #ifdef YAFFS_COMPILE_EXPORTFS
        sb->s_export_op = &yaffs_export_ops;
 #endif
@@ -2588,9 +2596,10 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
        else if (!yaffs_devname(sb, devname_buf))
                printk(KERN_INFO "yaffs: devname is NULL\n");
        else
        else if (!yaffs_devname(sb, devname_buf))
                printk(KERN_INFO "yaffs: devname is NULL\n");
        else
-               printk(KERN_INFO "yaffs: dev is %d name is \"%s\"\n",
+               printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
                       sb->s_dev,
                       sb->s_dev,
-                      yaffs_devname(sb, devname_buf));
+                      yaffs_devname(sb, devname_buf),
+                      readOnly ? "ro" : "rw");
 
        if (!data_str)
                data_str = "";
 
        if (!data_str)
                data_str = "";
@@ -2730,6 +2739,12 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
         * Set the yaffs_Device up for mtd
         */
 
         * Set the yaffs_Device up for mtd
         */
 
+       if (!readOnly && !(mtd->flags & MTD_WRITEABLE)){
+               readOnly = 1;
+               printk(KERN_INFO "yaffs: mtd is read only, setting superblock read only");
+               sb->s_flags |= MS_RDONLY;
+       }
+
        dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);
        context = kmalloc(sizeof(struct yaffs_LinuxContext),GFP_KERNEL);
        
        dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);
        context = kmalloc(sizeof(struct yaffs_LinuxContext),GFP_KERNEL);
        
@@ -2758,7 +2773,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
        context->dev = dev;
        context->superBlock = sb;
 
        context->dev = dev;
        context->superBlock = sb;
 
-       
+       dev->readOnly = readOnly;
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
        sb->s_fs_info = dev;
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
        sb->s_fs_info = dev;
index c01f00c8b6b37239d9562a6bbf8461d486ce8308..6524f5f5dc39211897a8c7ad3d3802f711701cc2 100644 (file)
@@ -4189,6 +4189,9 @@ static void yaffs_StripDeletedObjects(yaffs_Device *dev)
        struct ylist_head *n;
        yaffs_Object *l;
 
        struct ylist_head *n;
        yaffs_Object *l;
 
+       if (dev->readOnly)
+               return;
+
        /* Soft delete all the unlinked files */
        ylist_for_each_safe(i, n,
                &dev->unlinkedDir->variant.directoryVariant.children) {
        /* Soft delete all the unlinked files */
        ylist_for_each_safe(i, n,
                &dev->unlinkedDir->variant.directoryVariant.children) {
@@ -4242,6 +4245,8 @@ static void yaffs_FixHangingObjects(yaffs_Device *dev)
        int depthLimit;
        int hanging;
 
        int depthLimit;
        int hanging;
 
+       if (dev->readOnly)
+               return;
 
        /* Iterate through the objects in each hash entry,
         * looking at each object.
 
        /* Iterate through the objects in each hash entry,
         * looking at each object.