fs/exfat: send uevnet from workqueue
authorShiyong Li <a22381@motorola.com>
Sat, 9 Dec 2017 01:36:20 +0000 (17:36 -0800)
committerlingsen1 <lingsen1@lenovo.com>
Sun, 7 Feb 2021 09:36:50 +0000 (17:36 +0800)
We can not send uevent directly because it might be called
from atomic context.

Change-Id: I384a7f197b22b1fcb8d068c98908e4fa5a1d3b82
Signed-off-by: Lianwei Wang <a22439@motorola.com>
Signed-off-by: Shiyong Li <a22381@motorola.com>
Reviewed-on: https://gerrit.mot.com/1102182
SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: Igor Kovalenko <igork@motorola.com>
Submit-Approved: Jira Key
Reviewed-on: https://gerrit.mot.com/1276883
Reviewed-by: Hua Tan <tanhua1@motorola.com>
fs/exfat/exfat_core.c
fs/exfat/exfat_super.c
fs/exfat/exfat_super.h

index 71c75e1c93671e6531c19eb51e16c7aae4650ecb..248af20ea32feef3b6a39b3910c0b38133d529c6 100644 (file)
@@ -1754,12 +1754,14 @@ void fs_sync(struct super_block *sb, s32 do_sync)
 void fs_error(struct super_block *sb)
 {
        struct exfat_mount_options *opts = &EXFAT_SB(sb)->options;
+       struct exfat_sb_info *sbi = EXFAT_SB(sb);
 
        if (opts->errors == EXFAT_ERRORS_PANIC)
                panic("[EXFAT] Filesystem panic from previous error\n");
        else if ((opts->errors == EXFAT_ERRORS_RO) && !(sb->s_flags & MS_RDONLY)) {
                sb->s_flags |= MS_RDONLY;
-               kobject_uevent(&disk_to_dev(sb->s_bdev->bd_disk)->kobj, KOBJ_CHANGE);
+               if (sbi && !sbi->disable_uevent)
+                       schedule_work(&sbi->uevent_work);
                printk(KERN_ERR "[EXFAT] Filesystem has been set read-only\n");
        }
 }
index 53e21a3db873037a4d544265880dd53c8e42e6e4..2e041cdede7e29aa2feef7ddd66066e32ab1c680 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/sched.h>
 #include <linux/fs_struct.h>
 #include <linux/namei.h>
+#include <linux/genhd.h>
 #include <asm/current.h>
 #include <asm/unaligned.h>
 
@@ -132,6 +133,14 @@ static time_t accum_days_in_year[] = {
 
 static void _exfat_truncate(struct inode *inode, loff_t old_size);
 
+static void exfat_sbi_uevent_work(struct work_struct *work)
+{
+       struct exfat_sb_info *sbi = container_of(work, struct exfat_sb_info,
+                                                uevent_work);
+
+       kobject_uevent(&disk_to_dev(sbi->sb->s_bdev->bd_disk)->kobj, KOBJ_CHANGE);
+}
+
 /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
 void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec *ts,
                                                 DATE_TIME_T *tp)
@@ -2057,6 +2066,10 @@ static void exfat_free_super(struct exfat_sb_info *sbi)
 static void exfat_put_super(struct super_block *sb)
 {
        struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+       sbi->disable_uevent = 1;
+       cancel_work_sync(&sbi->uevent_work);
+
        if (__is_sb_dirty(sb))
                exfat_write_super(sb);
 
@@ -2480,6 +2493,9 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
        mutex_init(&sbi->s_lock);
 #endif
+       sbi->sb = sb;
+       INIT_WORK(&sbi->uevent_work, exfat_sbi_uevent_work);
+
        sb->s_fs_info = sbi;
        sb->s_flags |= MS_NODIRATIME;
        sb->s_magic = EXFAT_SUPER_MAGIC;
index f647daa41b261f2ec3a6bbae78f5bd9be657c55c..0e716074b75ae0fec7142e917571167ad65d35b9 100644 (file)
@@ -91,6 +91,9 @@ struct exfat_sb_info {
 #ifdef CONFIG_EXFAT_KERNEL_DEBUG
        long debug_flags;
 #endif /* CONFIG_EXFAT_KERNEL_DEBUG */
+       struct super_block *sb;
+       struct work_struct uevent_work;
+       int disable_uevent;
 };
 
 /*