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");
}
}
#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>
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)
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);
#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;
#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;
};
/*