[PATCH 4/5] FAT: notify userspace of fs errors with uevents

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add mechnism to optionally notify userspace about fs errors with
uevents associated with fs kobject's attribute:
	/sys/fs/fat/<part_bdev>/fs_fault

uevent's type is KOBJ_CHANGE, uevent's environment variable FS_FAULT=1.

Signed-off-by: Denis Karpov <ext-denis.2.karpov@xxxxxxxxx>
---
 fs/fat/fat.h   |    6 +++---
 fs/fat/inode.c |   37 +++++++++++++++++++++++++++++++------
 fs/fat/misc.c  |    4 ++--
 3 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index 480be11..ebf4c62 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -87,9 +87,9 @@ struct msdos_sb_info {
 #define FAT_CACHE_VALID	0	/* special case for valid cache */
 
 /* Mark FAT run-time errors  */
-#define FAT_FS_FAULT_SET(sbi, val) \
+#define FAT_FS_FAULT_SET(sbi, val, notify) \
 	fat_sbi_attr_set_notify(sbi, offsetof(struct msdos_sb_info, fs_fault), \
-				val)
+				val, notify)
 
 /*
  * MS-DOS file system inode data in memory
@@ -320,7 +320,7 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent,
 extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
 		            struct inode *i2);
 extern int fat_sbi_attr_set_notify(struct msdos_sb_info *sbi,
-			unsigned long offset, unsigned long val);
+			unsigned long offset, unsigned long val, int notify);
 
 /* fat/misc.c */
 extern void fat_fs_error(struct super_block *s, const char *function,
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 4613343..b1a0c8d 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -527,7 +527,7 @@ static int fat_remount(struct super_block *sb, int *flags, char *data)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	*flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME);
-	FAT_FS_FAULT_SET(sbi, 0);
+	FAT_FS_FAULT_SET(sbi, 0, 0);
 	return 0;
 }
 
@@ -1185,6 +1185,7 @@ struct fat_attr {
 	ssize_t (*store)(struct fat_attr *, struct msdos_sb_info *,
 			 const char *, size_t);
 	unsigned short offset;
+	unsigned short uevent;
 };
 
 static ssize_t fat_sbi_attr_show(struct fat_attr *a, struct msdos_sb_info *sbi,
@@ -1206,17 +1207,22 @@ static ssize_t fat_sbi_attr_store(struct fat_attr *a,
 	return count;
 }
 
-#define FAT_SBI_ATTR(_name, _mode, _show, _store) \
+#define FAT_SBI_ATTR(_name, _mode, _show, _store, _uevent) \
 static struct fat_attr fat_attr_##_name = {			\
 	.attr = {.name = __stringify(_name), .mode = _mode },	\
 	.show	= _show,					\
 	.store	= _store,					\
 	.offset = offsetof(struct msdos_sb_info, _name),	\
+	.uevent = _uevent,					\
 }
 #define FAT_SBI_RO_ATTR(name) FAT_SBI_ATTR(name, 0444, \
-				fat_sbi_attr_show, NULL)
+				fat_sbi_attr_show, NULL, 0)
 #define FAT_SBI_RW_ATTR(name) FAT_SBI_ATTR(name, 0644 \
-				fat_sbi_attr_show, fat_sbi_attr_store)
+				fat_sbi_attr_show, fat_sbi_attr_store, 0)
+#define FAT_SBI_RO_ATTR_NOTIFY(name) FAT_SBI_ATTR(name, 0444, \
+				fat_sbi_attr_show, NULL, 1)
+#define FAT_SBI_RW_ATTR_NOTIFY(name) FAT_SBI_ATTR(name, 0644, \
+				fat_sbi_attr_show, fat_sbi_attr_store, 1)
 
 #define ATTR_LIST(name) (&fat_attr_ ##name.attr)
 
@@ -1240,11 +1246,15 @@ static struct attribute *find_attr_by_offset(struct kobject *kobj,
 
 int fat_sbi_attr_set_notify(struct msdos_sb_info *sbi,
 			unsigned long offset,
-			unsigned long val)
+			unsigned long val,
+			int notify)
 {
 	struct fat_attr *a =
 		(struct fat_attr *) find_attr_by_offset(&sbi->s_kobj, offset);
 	unsigned long *attr_val;
+	int ev_len;
+	char *t_str;
+	char *envp[] = { NULL, NULL };
 
 	if (!a)
 		return -EINVAL;
@@ -1257,6 +1267,21 @@ int fat_sbi_attr_set_notify(struct msdos_sb_info *sbi,
 
 	sysfs_notify(&sbi->s_kobj, NULL, a->attr.name);
 
+	if (!notify || !a->uevent)
+		return 0;
+
+	/* dec MAX_UINT == 10 char string */
+	ev_len = strlen(a->attr.name) + 1 + 10 + 1;
+	envp[0] = t_str = kzalloc(ev_len, GFP_KERNEL);
+	if (!t_str)
+		return -ENOMEM;
+
+	snprintf(t_str, ev_len, "%s=%lu", a->attr.name, val);
+	while ((*t_str++ = toupper(*t_str)))
+		;
+	kobject_uevent_env(&sbi->s_kobj, KOBJ_CHANGE, envp);
+	kfree(envp[0]);
+
 	return 0;
 }
 EXPORT_SYMBOL(fat_sbi_attr_set_notify);
@@ -1573,7 +1598,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
 		printk(KERN_ERR "FAT: create fs kobject failed\n");
 		goto out_fail;
 	}
-	FAT_FS_FAULT_SET(sbi, 0);
+	FAT_FS_FAULT_SET(sbi, 0, 0);
 
 	return 0;
 
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index ce478be..8cdefd8 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -35,7 +35,7 @@ void fat_fs_error(struct super_block *s, const char *function,
 		printk(KERN_ERR "    File system has been set read-only\n");
 	}
 
-	FAT_FS_FAULT_SET(sbi, 1);
+	FAT_FS_FAULT_SET(sbi, 1, 0);
 }
 EXPORT_SYMBOL_GPL(fat_fs_error);
 
@@ -58,7 +58,7 @@ void fat_fs_warning(struct super_block *s, const char * function,
 	printk("\n");
 	va_end(args);
 
-	FAT_FS_FAULT_SET(sbi, 1);
+	FAT_FS_FAULT_SET(sbi, 1, 0);
 }
 EXPORT_SYMBOL_GPL(fat_fs_warning);
 
-- 
1.6.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux