From: Charles Manning Date: Sun, 17 May 2015 08:02:46 +0000 (+1200) Subject: yaffs: fix missing checkpooint on yaffs remount X-Git-Tag: aleph1-release~32 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=9ec94eea1865dfb884640c4db487d6855f801107 yaffs: fix missing checkpooint on yaffs remount For yaffs file system, the mode of reading or writing is restricted at four pointer where are mnt->mnt_flags,mnt->mnt_sb->s_flags,mtd->flags and dev->read_only,the first three is used handle file and file system(eg,remount) operation, and last one(dev->read_only) almost is used handle checkpoint of yaffs2. However, in current code, the dev->read_only only can be changed at first time when the yaffs2 file system is mounted, later it can't be changed again(eg,mount -o remount), the result is that the checkpoint's saving operation always can't succeed if you set readonly mode for yaffs2 file system when it is mounted at the first time. To fix this issue, we implement yaffs_remount_fs() which allows the rootfs to be remounted as r/w. Also fix one missing argument in yaffs_flush_whole_cache() call. Signed-off-by: Wenlin Kang --- diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index db97c10..6540434 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -2200,7 +2200,7 @@ static void yaffs_flush_super(struct super_block *sb, int do_checkpoint) yaffs_flush_inodes(sb); yaffs_update_dirty_dirs(dev); - yaffs_flush_whole_cache(dev); + yaffs_flush_whole_cache(dev, 1); if (do_checkpoint) yaffs_checkpoint_save(dev); } @@ -2579,7 +2579,45 @@ static int yaffs_sync_fs(struct super_block *sb) return 0; } +/* the function only is used to change dev->read_only when this file system + * is remounted. + */ +static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) +{ + int read_only = 0; + struct mtd_info *mtd; + struct yaffs_dev *dev = 0; + /* Get the device */ + mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); + if (!mtd) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device #%u doesn't appear to exist", + MINOR(sb->s_dev)); + return 1; + } + + /* Check it's NAND */ + if (mtd->type != MTD_NANDFLASH) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device is not NAND it's type %d", + mtd->type); + return 1; + } + + read_only = ((*flags & MS_RDONLY) != 0); + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) { + read_only = 1; + printk(KERN_INFO + "yaffs: mtd is read only, setting superblock read only"); + *flags |= MS_RDONLY; + } + + dev = sb->s_fs_info; + dev->read_only = read_only; + + return 0; +} static const struct super_operations yaffs_super_ops = { .statfs = yaffs_statfs, @@ -2601,6 +2639,7 @@ static const struct super_operations yaffs_super_ops = { #ifdef YAFFS_HAS_WRITE_SUPER .write_super = yaffs_write_super, #endif + .remount_fs = yaffs_remount_fs, }; struct yaffs_options { diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c index 2d6c991..d77c87d 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -1510,7 +1510,7 @@ static void yaffs_flush_super(struct super_block *sb, int do_checkpoint) yaffs_flush_inodes(sb); yaffs_update_dirty_dirs(dev); - yaffs_flush_whole_cache(dev); + yaffs_flush_whole_cache(dev, 1); if (do_checkpoint) yaffs_checkpoint_save(dev); } @@ -1943,8 +1943,6 @@ static void yaffs_put_super(struct super_block *sb) kfree(dev); - - if (mtd && mtd->sync) mtd->sync(mtd); @@ -1952,12 +1950,54 @@ static void yaffs_put_super(struct super_block *sb) put_mtd_device(mtd); } +/* the function only is used to change dev->read_only when this file system + * is remounted. + */ +static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) +{ + int read_only = 0; + struct mtd_info *mtd; + struct yaffs_dev *dev = 0; + + /* Get the device */ + mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); + if (!mtd) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device #%u doesn't appear to exist", + MINOR(sb->s_dev)); + return 1; + } + + /* Check it's NAND */ + if (mtd->type != MTD_NANDFLASH) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device is not NAND it's type %d", + mtd->type); + return 1; + } + + read_only = ((*flags & MS_RDONLY) != 0); + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) { + read_only = 1; + printk(KERN_INFO + "yaffs: mtd is read only, setting superblock read only"); + *flags |= MS_RDONLY; + } + + dev = sb->s_fs_info; + dev->read_only = read_only; + + return 0; +} + + static const struct super_operations yaffs_super_ops = { .statfs = yaffs_statfs, .put_super = yaffs_put_super, .evict_inode = yaffs_evict_inode, .sync_fs = yaffs_sync_fs, .write_super = yaffs_write_super, + .remount_fs = yaffs_remount_fs, }; static struct super_block *yaffs_internal_read_super(int yaffs_version,