From: Hongbo Li <lihongbo22@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/release-management/issues/ID5W1P ------------------ In the previous logic, when the umount path will reback -EBUSY if the target device is opened. But it is difficult to control the critical section due to the mount_lock is unable to be accessed. And some testcase will cause the following exeception: ```c mntput_no_expire+0x3a3/0x3c0 mntput+0x28/0x60 mfs_dev_release+0x3e/0x60 [mfs] __fput+0x10f/0x450 ____fput+0x12/0x20 task_work_run+0x9f/0x110 do_exit+0x2d3/0x780 do_group_exit+0x35/0xd0 get_signal+0x9aa/0x9b0 arch_do_signal_or_restart+0x2d/0x180 syscall_exit_to_user_mode+0x207/0x220 do_syscall_64+0x62/0x100 entry_SYSCALL_64_after_hwframe+0x78/0xe2 ``` To solve this issue, we choose to pending when the device is opening. Fixes: 3236f3b541d1 ("mfs: Add communication devie and event acquisition operations") Signed-off-by: Hongbo Li <lihongbo22@huawei.com> --- fs/mfs/dev.c | 10 ---------- fs/mfs/internal.h | 2 -- fs/mfs/super.c | 7 +++++-- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/fs/mfs/dev.c b/fs/mfs/dev.c index e957be7f02a7..902f73b1c25c 100644 --- a/fs/mfs/dev.c +++ b/fs/mfs/dev.c @@ -7,7 +7,6 @@ #include <linux/idr.h> #include <linux/poll.h> #include <linux/list.h> -#include "../mount.h" #include <trace/events/mfs.h> @@ -24,7 +23,6 @@ static int mfs_dev_open(struct inode *inode, struct file *file) { struct mfs_caches *caches; struct mfs_sb_info *sbi; - struct mount *mnt; unsigned minor = iminor(inode); sbi = minor < U8_MAX ? idr_find(&mfs_dev_minor, minor) : NULL; @@ -40,13 +38,6 @@ static int mfs_dev_open(struct inode *inode, struct file *file) clear_bit(MFS_CACHE_OPENED, &caches->flags); return -EBUSY; } - mnt = list_first_entry(&sbi->sb->s_mounts, struct mount, mnt_instance); - /* during mounting or delete from s_mounts in umounting */ - if (list_empty(&sbi->sb->s_mounts)) { - clear_bit(MFS_CACHE_OPENED, &caches->flags); - return -EBUSY; - } - sbi->mnt = mntget(&mnt->mnt); file->private_data = sbi; set_bit(MFS_CACHE_READY, &caches->flags); @@ -61,7 +52,6 @@ static int mfs_dev_release(struct inode *inode, struct file *file) clear_bit(MFS_CACHE_READY, &caches->flags); smp_mb__after_atomic(); mfs_cancel_all_events(sbi); - mntput(sbi->mnt); smp_mb__before_atomic(); clear_bit(MFS_CACHE_OPENED, &caches->flags); return 0; diff --git a/fs/mfs/internal.h b/fs/mfs/internal.h index 1e6e1defd862..66c6c0a38c68 100644 --- a/fs/mfs/internal.h +++ b/fs/mfs/internal.h @@ -13,7 +13,6 @@ #include <linux/wait.h> #include <linux/completion.h> #include <linux/types.h> -#include <linux/mount.h> #include <linux/mfs.h> #define MFS_NAME "mfs" @@ -71,7 +70,6 @@ struct mfs_sb_info { int minor; unsigned long flags; - struct vfsmount *mnt; struct super_block *sb; struct mfs_caches caches; diff --git a/fs/mfs/super.c b/fs/mfs/super.c index 614dab54e270..91b1b13b0657 100644 --- a/fs/mfs/super.c +++ b/fs/mfs/super.c @@ -400,9 +400,12 @@ static void mfs_kill_sb(struct super_block *sb) clear_bit(MFS_MOUNTED, &sbi->flags); if (support_event(sbi)) { while (test_bit(MFS_CACHE_OPENED, &caches->flags)) { + static DEFINE_RATELIMIT_STATE(busy_open, 30 * HZ, 1); + msleep(100); - printk_once(KERN_WARNING "Pending until close the /dev/mfs%u...\n", - sbi->minor); + if (!__ratelimit(&busy_open)) + continue; + pr_warn("Pending until close the /dev/mfs%u...\n", sbi->minor); } mfs_fs_dev_exit(sb); } -- 2.25.1