From 334eb5fc4472c791e4c4ce6d50e650d2b2732f02 Mon Sep 17 00:00:00 2001 From: Charles Manning Date: Fri, 15 May 2020 13:57:54 +1200 Subject: [PATCH] Handle cleanup when remounting rw after mounting read-only Deferend clean ups were not happening properly. Thanks to andriy.grytsenko@globallogic.com for providing a patch that forms the babsis of these changes. Signed-off-by: Charles Manning --- direct/yaffsfs.c | 5 +++++ yaffs_guts.c | 17 +++++++++++++---- yaffs_guts.h | 1 + yaffs_vfs_multi.c | 11 +++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index af8c82b..d1e4e4e 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -3050,6 +3050,7 @@ int yaffs_remount_common(struct yaffs_dev *dev, const YCHAR *path, int force, int read_only) { int retVal = -1; + int was_read_only; if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); @@ -3072,7 +3073,11 @@ int yaffs_remount_common(struct yaffs_dev *dev, const YCHAR *path, if (force || !yaffsfs_IsDevBusy(dev)) { if (read_only) yaffs_checkpoint_save(dev); + was_read_only = dev->read_only; dev->read_only = read_only ? 1 : 0; + if (was_read_only && !read_only) { + yaffs_guts_cleanup(dev); + } retVal = 0; } else yaffsfs_SetError(-EBUSY); diff --git a/yaffs_guts.c b/yaffs_guts.c index 40a5b46..c52ff84 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -4799,6 +4799,18 @@ int yaffs_guts_format_dev(struct yaffs_dev *dev) return YAFFS_OK; } +/* + * If the dev is mounted r/w then the cleanup will happen during + * yaffs_guts_initialise. However if the dev is mounted ro then + * the cleanup will be dfered until yaffs is remounted r/w. + */ +void yaffs_guts_cleanup(struct yaffs_dev *dev) +{ + yaffs_strip_deleted_objs(dev); + yaffs_fix_hanging_objs(dev); + if (dev->param.empty_lost_n_found) + yaffs_empty_l_n_f(dev); +} int yaffs_guts_initialise(struct yaffs_dev *dev) { @@ -5012,10 +5024,7 @@ int yaffs_guts_initialise(struct yaffs_dev *dev) init_failed = 1; } - yaffs_strip_deleted_objs(dev); - yaffs_fix_hanging_objs(dev); - if (dev->param.empty_lost_n_found) - yaffs_empty_l_n_f(dev); + yaffs_guts_cleanup(dev); } if (init_failed) { diff --git a/yaffs_guts.h b/yaffs_guts.h index 5ebc378..124e4c9 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -885,6 +885,7 @@ struct yaffs_xattr_mod { int yaffs_guts_initialise(struct yaffs_dev *dev); void yaffs_deinitialise(struct yaffs_dev *dev); +void yaffs_guts_cleanup(struct yaffs_dev *dev); int yaffs_get_n_free_chunks(struct yaffs_dev *dev); diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index e4edb2c..3044db7 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -2718,6 +2718,7 @@ static int yaffs_sync_fs(struct super_block *sb) static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) { int read_only = 0; + int was_read_only = 0; struct mtd_info *mtd; struct yaffs_dev *dev = 0; @@ -2747,8 +2748,18 @@ static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) } dev = sb->s_fs_info; + was_read_only = dev->read_only; dev->read_only = read_only; + if (was_read_only && !read_only) { + yaffs_gross_lock(dev); + yaffs_guts_cleanup(dev); + yaffs_gross_unlock(dev); + yaffs_bg_start(dev); + } else if (!was_read_only && read_only) { + yaffs_bg_stop(dev); + } + return 0; } -- 2.30.2