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. Signed-off-by: Wenlin Kang --- yaffs_vfs_multi.c | 40 ++++++++++++++++++++++++++++++++++++++++ yaffs_vfs_single.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index 76bc1db..605438a 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -2580,6 +2580,45 @@ static int yaffs_sync_fs(struct super_block *sb) } +/* 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 +2640,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 232dc26..a510f22 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -1952,12 +1952,53 @@ 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, -- 1.7.9.5