* [RFC 1/8] Add kset to file_system_type
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
@ 2016-05-12 18:14 ` Goldwyn Rodrigues
2016-05-12 18:14 ` [RFC 2/8] Add kobject to super_block Goldwyn Rodrigues
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:14 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
Creates the top level /sys/fs/<type> as a part of the kset.
Providing the ktype which would handle super_block entries will
be the responsibility of the FS modules.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/filesystems.c | 7 +++++++
include/linux/fs.h | 4 +++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/fs/filesystems.c b/fs/filesystems.c
index c5618db..a47391f 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -81,6 +81,11 @@ int register_filesystem(struct file_system_type * fs)
else
*p = fs;
write_unlock(&file_systems_lock);
+ /* Filesystems to set sb_ktype only if they want
+ * core to create the sysfs entries
+ */
+ if (fs->sb_ktype)
+ fs->kset = kset_create_and_add(fs->name, NULL, fs_kobj);
return res;
}
@@ -109,6 +114,8 @@ int unregister_filesystem(struct file_system_type * fs)
*tmp = fs->next;
fs->next = NULL;
write_unlock(&file_systems_lock);
+ if (fs->kset)
+ kset_unregister(fs->kset);
synchronize_rcu();
return 0;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 70e61b5..019546b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -35,6 +35,7 @@
#include <asm/byteorder.h>
#include <uapi/linux/fs.h>
+#include <linux/kobject.h>
struct backing_dev_info;
struct bdi_writeback;
@@ -42,7 +43,6 @@ struct export_operations;
struct hd_geometry;
struct iovec;
struct kiocb;
-struct kobject;
struct pipe_inode_info;
struct poll_table_struct;
struct kstatfs;
@@ -1996,6 +1996,8 @@ struct file_system_type {
struct lock_class_key i_lock_key;
struct lock_class_key i_mutex_key;
struct lock_class_key i_mutex_dir_key;
+ struct kobj_type *sb_ktype; /* how to handle super block's kobjects */
+ struct kset *kset; /* For /sys/fs/<type> */
};
#define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME)
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 2/8] Add kobject to super_block
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
2016-05-12 18:14 ` [RFC 1/8] Add kset to file_system_type Goldwyn Rodrigues
@ 2016-05-12 18:14 ` Goldwyn Rodrigues
2016-05-12 18:14 ` [RFC 3/8] Report file system events Goldwyn Rodrigues
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:14 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This creates the /sys/fs/<fs-type>/<s_id> directory.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/super.c | 18 ++++++++++++++++++
include/linux/fs.h | 2 ++
2 files changed, 20 insertions(+)
diff --git a/fs/super.c b/fs/super.c
index 74914b1..42568eb 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -414,6 +414,9 @@ void generic_shutdown_super(struct super_block *sb)
sync_filesystem(sb);
sb->s_flags &= ~MS_ACTIVE;
+ if (sb->s_type->sb_ktype)
+ kobject_put(&sb->s_kobj);
+
fsnotify_unmount_inodes(sb);
cgroup_writeback_umount();
@@ -427,6 +430,9 @@ void generic_shutdown_super(struct super_block *sb)
if (sop->put_super)
sop->put_super(sb);
+ if (sb->s_type->sb_ktype)
+ wait_for_completion(&sb->s_kobj_del);
+
if (!list_empty(&sb->s_inodes)) {
printk("VFS: Busy inodes after unmount of %s. "
"Self-destruct in 5 seconds. Have a nice day...\n",
@@ -1022,6 +1028,18 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
goto error;
}
+ if (fs_type->sb_ktype) {
+ s->s_kobj.kset = fs_type->kset;
+ init_completion(&s->s_kobj_del);
+ error = kobject_init_and_add(&s->s_kobj,
+ fs_type->sb_ktype,
+ NULL, "%s", s->s_id);
+ if (error) {
+ deactivate_locked_super(s);
+ goto error;
+ }
+ }
+
s->s_flags |= MS_ACTIVE;
bdev->bd_super = s;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 019546b..5ac8883 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1419,6 +1419,8 @@ struct super_block {
/* s_inode_list_lock protects s_inodes */
spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp;
struct list_head s_inodes; /* all inodes */
+ struct kobject s_kobj; /* kobject to create /sys/fs/<type>/<s_id> */
+ struct completion s_kobj_del; /* Wait for kobjects deletion */
};
extern struct timespec current_fs_time(struct super_block *sb);
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 3/8] Report file system events
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
2016-05-12 18:14 ` [RFC 1/8] Add kset to file_system_type Goldwyn Rodrigues
2016-05-12 18:14 ` [RFC 2/8] Add kobject to super_block Goldwyn Rodrigues
@ 2016-05-12 18:14 ` Goldwyn Rodrigues
2016-05-12 18:14 ` [RFC 4/8] Helper functions and attributes for super block's sysfs entries Goldwyn Rodrigues
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:14 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This would allow the filesystems to report back events to the userspace.
Examples could be but not limited to:
- Reporting ENOSPC on a filesystem
This could be used to trigger commands that would either clear
up temporary files and/or inform the administrator
- Reporting file errors
Filesystems tend to turn read-only at the drop of a hat. This could
be used to develop utilities that would focus on clearing the errors
as opposed to umounting and checking the entire filesystem. Even
though checking the entire filesystem may be a good idea for this.
Such a feature would improve availability (yes, perhaps at the cost of
integrity) and improve modularize online filesystem checking.
This was the original idea of this effort which extended to kobjectifying
the entire filesystem series.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/super.c | 6 ++++++
include/linux/fs.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/fs/super.c b/fs/super.c
index 42568eb..c6b8801 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -153,6 +153,12 @@ static void destroy_super_rcu(struct rcu_head *head)
schedule_work(&s->destroy_work);
}
+int sb_report_event(struct super_block *sb, char *envp[])
+{
+ return kobject_uevent_env(&sb->s_kobj, KOBJ_CHANGE, envp);
+}
+EXPORT_SYMBOL(sb_report_event);
+
/**
* destroy_super - frees a superblock
* @s: superblock to free
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5ac8883..1cf2e011 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2071,6 +2071,7 @@ extern int vfs_ustat(dev_t, struct kstatfs *);
extern int freeze_super(struct super_block *super);
extern int thaw_super(struct super_block *super);
extern bool our_mnt(struct vfsmount *mnt);
+extern int sb_report_event(struct super_block *sb, char *envp[]);
extern int current_umask(void);
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 4/8] Helper functions and attributes for super block's sysfs entries
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
` (2 preceding siblings ...)
2016-05-12 18:14 ` [RFC 3/8] Report file system events Goldwyn Rodrigues
@ 2016-05-12 18:14 ` Goldwyn Rodrigues
2016-05-12 18:15 ` [RFC 5/8] ocfs2: Use the sb's kset Goldwyn Rodrigues
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:14 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
Introduces super_block_attribute as helper attribute which
encompasses store() and show() fucntions.
Also includes the macros to define attributes.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/super.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 26 ++++++++++++++++++++++++++
2 files changed, 64 insertions(+)
diff --git a/fs/super.c b/fs/super.c
index c6b8801..d6d4d05 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1396,3 +1396,41 @@ out:
return 0;
}
EXPORT_SYMBOL(thaw_super);
+
+static ssize_t super_block_attribute_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct super_block_attribute *sattr =
+ container_of(attr, struct super_block_attribute, attr);
+ struct super_block *sb = container_of(kobj, struct super_block, s_kobj);
+ if (!sattr->show)
+ return -EIO;
+
+ return sattr->show(sb, sattr, buf);
+}
+
+static ssize_t super_block_attribute_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t count)
+{
+ struct super_block_attribute *sattr =
+ container_of(attr, struct super_block_attribute, attr);
+ struct super_block *sb = container_of(kobj, struct super_block, s_kobj);
+ if (!sattr->store)
+ return -EIO;
+
+ return sattr->store(sb, sattr, buf, count);
+}
+
+const struct sysfs_ops super_block_sysfs_ops = {
+ .show = super_block_attribute_show,
+ .store = super_block_attribute_store,
+};
+
+EXPORT_SYMBOL(super_block_sysfs_ops);
+
+void super_block_release(struct kobject *kobj)
+{
+ struct super_block *sb = container_of(kobj, struct super_block, s_kobj);
+ complete(&sb->s_kobj_del);
+}
+EXPORT_SYMBOL(super_block_release);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1cf2e011..117d641 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1423,6 +1423,32 @@ struct super_block {
struct completion s_kobj_del; /* Wait for kobjects deletion */
};
+struct super_block_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct super_block *sb, struct super_block_attribute *,
+ char *buf);
+ ssize_t (*store)(struct super_block *sb, struct super_block_attribute *,
+ const char *buf, size_t count);
+};
+
+#define SB_ATTR(_name, _mode) \
+ struct super_block_attribute sb_attr_##_name = {\
+ .attr = {.name = __stringify(_name), \
+ .mode = _mode}, \
+ .show = _name##_show, \
+ .store = _name##_store, \
+ }
+
+#define SB_ATTR_RO(_name) \
+ struct super_block_attribute sb_attr_##_name = {\
+ .attr = {.name = __stringify(_name), \
+ .mode = S_IRUGO}, \
+ .show = _name##_show, \
+ }
+
+extern const struct sysfs_ops super_block_sysfs_ops;
+void super_block_release(struct kobject *kobj);
+
extern struct timespec current_fs_time(struct super_block *sb);
/*
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 5/8] ocfs2: Use the sb's kset
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
` (3 preceding siblings ...)
2016-05-12 18:14 ` [RFC 4/8] Helper functions and attributes for super block's sysfs entries Goldwyn Rodrigues
@ 2016-05-12 18:15 ` Goldwyn Rodrigues
2016-05-12 18:15 ` [RFC 6/8] ocfs2: create filecheck files Goldwyn Rodrigues
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
Sets the ocfs2_kset and the kobj_type for creating entires in sysfs
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/ocfs2/Makefile | 3 ++-
fs/ocfs2/stackglue.c | 3 +--
fs/ocfs2/super.c | 6 ++----
fs/ocfs2/sysfs.c | 26 ++++++++++++++++++++++++++
fs/ocfs2/sysfs.h | 8 ++++++++
5 files changed, 39 insertions(+), 7 deletions(-)
create mode 100644 fs/ocfs2/sysfs.c
create mode 100644 fs/ocfs2/sysfs.h
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index e27e652..716ed45 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -41,7 +41,8 @@ ocfs2-objs := \
quota_local.o \
quota_global.o \
xattr.o \
- acl.o \
+ acl.o \
+ sysfs.o \
filecheck.o
ocfs2_stackglue-objs := stackglue.o
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index 13219ed..f9b45b3 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -640,8 +640,7 @@ static void ocfs2_sysfs_exit(void)
static int ocfs2_sysfs_init(void)
{
int ret;
-
- ocfs2_kset = kset_create_and_add("ocfs2", NULL, fs_kobj);
+ ocfs2_kset = kset_create_and_add("ocfs2_stack", NULL, fs_kobj);
if (!ocfs2_kset)
return -ENOMEM;
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index d7cae33..0419a4a 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -75,6 +75,7 @@
#include "buffer_head_io.h"
#include "filecheck.h"
+#include "sysfs.h"
static struct kmem_cache *ocfs2_inode_cachep;
struct kmem_cache *ocfs2_dquot_cachep;
@@ -1200,9 +1201,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
/* Start this when the mount is almost sure of being successful */
ocfs2_orphan_scan_start(osb);
- /* Create filecheck sysfile /sys/fs/ocfs2/<devname>/filecheck */
- ocfs2_filecheck_create_sysfs(sb);
-
return status;
read_super_error:
@@ -1233,6 +1231,7 @@ static struct file_system_type ocfs2_fs_type = {
.mount = ocfs2_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
+ .sb_ktype = &ocfs2_sb_ktype,
.next = NULL
};
MODULE_ALIAS_FS("ocfs2");
@@ -1653,7 +1652,6 @@ static void ocfs2_put_super(struct super_block *sb)
ocfs2_sync_blockdev(sb);
ocfs2_dismount_volume(sb, 0);
- ocfs2_filecheck_remove_sysfs(sb);
}
static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
diff --git a/fs/ocfs2/sysfs.c b/fs/ocfs2/sysfs.c
new file mode 100644
index 0000000..e4d538b
--- /dev/null
+++ b/fs/ocfs2/sysfs.c
@@ -0,0 +1,26 @@
+#include <linux/fs.h>
+#include "ocfs2.h"
+#include "sysfs.h"
+
+static ssize_t slot_num_show(struct super_block *sb,
+ struct super_block_attribute *attr,
+ char *buf)
+{
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+ return sprintf(buf, "%d\n", osb->slot_num);
+}
+
+static SB_ATTR_RO(slot_num);
+static struct attribute *ocfs2_sb_attrs[] = {
+ &sb_attr_slot_num.attr,
+ NULL
+};
+
+struct kobj_type ocfs2_sb_ktype = {
+ .default_attrs = ocfs2_sb_attrs,
+ .sysfs_ops = &super_block_sysfs_ops,
+ .release = super_block_release,
+};
+
+
+
diff --git a/fs/ocfs2/sysfs.h b/fs/ocfs2/sysfs.h
new file mode 100644
index 0000000..5809e9b
--- /dev/null
+++ b/fs/ocfs2/sysfs.h
@@ -0,0 +1,8 @@
+
+
+#ifndef _SYS_H
+#define _SYS_H
+
+extern struct kobj_type ocfs2_sb_ktype;
+
+#endif
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 6/8] ocfs2: create filecheck files
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
` (4 preceding siblings ...)
2016-05-12 18:15 ` [RFC 5/8] ocfs2: Use the sb's kset Goldwyn Rodrigues
@ 2016-05-12 18:15 ` Goldwyn Rodrigues
2016-05-12 18:15 ` [RFC 7/8] ocfs2: report inode errors to userspace Goldwyn Rodrigues
2016-05-12 18:15 ` [RFC 8/8] ext4: Let fs create the sysfs entries Goldwyn Rodrigues
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This reduces the code base and removes unnecessary data structures
for filecheck information since all information is stored in ocfs2_super
now.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/ocfs2/filecheck.c | 440 ++++++---------------------------------------------
fs/ocfs2/filecheck.h | 10 ++
fs/ocfs2/ocfs2.h | 7 +
fs/ocfs2/super.c | 7 +
fs/ocfs2/sysfs.c | 81 ++++++++++
5 files changed, 153 insertions(+), 392 deletions(-)
diff --git a/fs/ocfs2/filecheck.c b/fs/ocfs2/filecheck.c
index 2cabbcf..0b41967 100644
--- a/fs/ocfs2/filecheck.c
+++ b/fs/ocfs2/filecheck.c
@@ -17,15 +17,7 @@
* General Public License for more details.
*/
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kmod.h>
#include <linux/fs.h>
-#include <linux/kobject.h>
-#include <linux/sysfs.h>
-#include <linux/sysctl.h>
#include <cluster/masklog.h>
#include "ocfs2.h"
@@ -53,36 +45,6 @@ static const char * const ocfs2_filecheck_errs[] = {
"UNSUPPORTED"
};
-static DEFINE_SPINLOCK(ocfs2_filecheck_sysfs_lock);
-static LIST_HEAD(ocfs2_filecheck_sysfs_list);
-
-struct ocfs2_filecheck {
- struct list_head fc_head; /* File check entry list head */
- spinlock_t fc_lock;
- unsigned int fc_max; /* Maximum number of entry in list */
- unsigned int fc_size; /* Current entry count in list */
- unsigned int fc_done; /* Finished entry count in list */
-};
-
-struct ocfs2_filecheck_sysfs_entry { /* sysfs entry per mounting */
- struct list_head fs_list;
- atomic_t fs_count;
- struct super_block *fs_sb;
- struct kset *fs_devicekset;
- struct kset *fs_fcheckkset;
- struct ocfs2_filecheck *fs_fcheck;
-};
-
-#define OCFS2_FILECHECK_MAXSIZE 100
-#define OCFS2_FILECHECK_MINSIZE 10
-
-/* File check operation type */
-enum {
- OCFS2_FILECHECK_TYPE_CHK = 0, /* Check a file(inode) */
- OCFS2_FILECHECK_TYPE_FIX, /* Fix a file(inode) */
- OCFS2_FILECHECK_TYPE_SET = 100 /* Set entry list maximum size */
-};
-
struct ocfs2_filecheck_entry {
struct list_head fe_list;
unsigned long fe_ino;
@@ -91,14 +53,6 @@ struct ocfs2_filecheck_entry {
unsigned int fe_status:31;
};
-struct ocfs2_filecheck_args {
- unsigned int fa_type;
- union {
- unsigned long fa_ino;
- unsigned int fa_len;
- };
-};
-
static const char *
ocfs2_filecheck_error(int errno)
{
@@ -110,321 +64,51 @@ ocfs2_filecheck_error(int errno)
return ocfs2_filecheck_errs[errno - OCFS2_FILECHECK_ERR_START + 1];
}
-static ssize_t ocfs2_filecheck_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf);
-static ssize_t ocfs2_filecheck_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t count);
-static struct kobj_attribute ocfs2_attr_filecheck_chk =
- __ATTR(check, S_IRUSR | S_IWUSR,
- ocfs2_filecheck_show,
- ocfs2_filecheck_store);
-static struct kobj_attribute ocfs2_attr_filecheck_fix =
- __ATTR(fix, S_IRUSR | S_IWUSR,
- ocfs2_filecheck_show,
- ocfs2_filecheck_store);
-static struct kobj_attribute ocfs2_attr_filecheck_set =
- __ATTR(set, S_IRUSR | S_IWUSR,
- ocfs2_filecheck_show,
- ocfs2_filecheck_store);
-
-static int ocfs2_filecheck_sysfs_wait(atomic_t *p)
-{
- schedule();
- return 0;
-}
-
-static void
-ocfs2_filecheck_sysfs_free(struct ocfs2_filecheck_sysfs_entry *entry)
-{
- struct ocfs2_filecheck_entry *p;
-
- if (!atomic_dec_and_test(&entry->fs_count))
- wait_on_atomic_t(&entry->fs_count, ocfs2_filecheck_sysfs_wait,
- TASK_UNINTERRUPTIBLE);
-
- spin_lock(&entry->fs_fcheck->fc_lock);
- while (!list_empty(&entry->fs_fcheck->fc_head)) {
- p = list_first_entry(&entry->fs_fcheck->fc_head,
- struct ocfs2_filecheck_entry, fe_list);
- list_del(&p->fe_list);
- BUG_ON(!p->fe_done); /* To free a undone file check entry */
- kfree(p);
- }
- spin_unlock(&entry->fs_fcheck->fc_lock);
-
- kset_unregister(entry->fs_fcheckkset);
- kset_unregister(entry->fs_devicekset);
- kfree(entry->fs_fcheck);
- kfree(entry);
-}
-
-static void
-ocfs2_filecheck_sysfs_add(struct ocfs2_filecheck_sysfs_entry *entry)
-{
- spin_lock(&ocfs2_filecheck_sysfs_lock);
- list_add_tail(&entry->fs_list, &ocfs2_filecheck_sysfs_list);
- spin_unlock(&ocfs2_filecheck_sysfs_lock);
-}
-
-static int ocfs2_filecheck_sysfs_del(const char *devname)
-{
- struct ocfs2_filecheck_sysfs_entry *p;
-
- spin_lock(&ocfs2_filecheck_sysfs_lock);
- list_for_each_entry(p, &ocfs2_filecheck_sysfs_list, fs_list) {
- if (!strcmp(p->fs_sb->s_id, devname)) {
- list_del(&p->fs_list);
- spin_unlock(&ocfs2_filecheck_sysfs_lock);
- ocfs2_filecheck_sysfs_free(p);
- return 0;
- }
- }
- spin_unlock(&ocfs2_filecheck_sysfs_lock);
- return 1;
-}
-
-static void
-ocfs2_filecheck_sysfs_put(struct ocfs2_filecheck_sysfs_entry *entry)
-{
- if (atomic_dec_and_test(&entry->fs_count))
- wake_up_atomic_t(&entry->fs_count);
-}
-
-static struct ocfs2_filecheck_sysfs_entry *
-ocfs2_filecheck_sysfs_get(const char *devname)
-{
- struct ocfs2_filecheck_sysfs_entry *p = NULL;
-
- spin_lock(&ocfs2_filecheck_sysfs_lock);
- list_for_each_entry(p, &ocfs2_filecheck_sysfs_list, fs_list) {
- if (!strcmp(p->fs_sb->s_id, devname)) {
- atomic_inc(&p->fs_count);
- spin_unlock(&ocfs2_filecheck_sysfs_lock);
- return p;
- }
- }
- spin_unlock(&ocfs2_filecheck_sysfs_lock);
- return NULL;
-}
-
-int ocfs2_filecheck_create_sysfs(struct super_block *sb)
-{
- int ret = 0;
- struct kset *device_kset = NULL;
- struct kset *fcheck_kset = NULL;
- struct ocfs2_filecheck *fcheck = NULL;
- struct ocfs2_filecheck_sysfs_entry *entry = NULL;
- struct attribute **attrs = NULL;
- struct attribute_group attrgp;
-
- if (!ocfs2_kset)
- return -ENOMEM;
-
- attrs = kmalloc(sizeof(struct attribute *) * 4, GFP_NOFS);
- if (!attrs) {
- ret = -ENOMEM;
- goto error;
- } else {
- attrs[0] = &ocfs2_attr_filecheck_chk.attr;
- attrs[1] = &ocfs2_attr_filecheck_fix.attr;
- attrs[2] = &ocfs2_attr_filecheck_set.attr;
- attrs[3] = NULL;
- memset(&attrgp, 0, sizeof(attrgp));
- attrgp.attrs = attrs;
- }
-
- fcheck = kmalloc(sizeof(struct ocfs2_filecheck), GFP_NOFS);
- if (!fcheck) {
- ret = -ENOMEM;
- goto error;
- } else {
- INIT_LIST_HEAD(&fcheck->fc_head);
- spin_lock_init(&fcheck->fc_lock);
- fcheck->fc_max = OCFS2_FILECHECK_MINSIZE;
- fcheck->fc_size = 0;
- fcheck->fc_done = 0;
- }
-
- if (strlen(sb->s_id) <= 0) {
- mlog(ML_ERROR,
- "Cannot get device basename when create filecheck sysfs\n");
- ret = -ENODEV;
- goto error;
- }
-
- device_kset = kset_create_and_add(sb->s_id, NULL, &ocfs2_kset->kobj);
- if (!device_kset) {
- ret = -ENOMEM;
- goto error;
- }
-
- fcheck_kset = kset_create_and_add("filecheck", NULL,
- &device_kset->kobj);
- if (!fcheck_kset) {
- ret = -ENOMEM;
- goto error;
- }
-
- ret = sysfs_create_group(&fcheck_kset->kobj, &attrgp);
- if (ret)
- goto error;
-
- entry = kmalloc(sizeof(struct ocfs2_filecheck_sysfs_entry), GFP_NOFS);
- if (!entry) {
- ret = -ENOMEM;
- goto error;
- } else {
- atomic_set(&entry->fs_count, 1);
- entry->fs_sb = sb;
- entry->fs_devicekset = device_kset;
- entry->fs_fcheckkset = fcheck_kset;
- entry->fs_fcheck = fcheck;
- ocfs2_filecheck_sysfs_add(entry);
- }
-
- kfree(attrs);
- return 0;
-
-error:
- kfree(attrs);
- kfree(entry);
- kfree(fcheck);
- kset_unregister(fcheck_kset);
- kset_unregister(device_kset);
- return ret;
-}
-
-int ocfs2_filecheck_remove_sysfs(struct super_block *sb)
-{
- return ocfs2_filecheck_sysfs_del(sb->s_id);
-}
-
static int
-ocfs2_filecheck_erase_entries(struct ocfs2_filecheck_sysfs_entry *ent,
+ocfs2_filecheck_erase_entries(struct ocfs2_super *,
unsigned int count);
-static int
-ocfs2_filecheck_adjust_max(struct ocfs2_filecheck_sysfs_entry *ent,
- unsigned int len)
+
+int ocfs2_filecheck_set_max_entries(struct ocfs2_super *osb,
+ int len)
{
int ret;
if ((len < OCFS2_FILECHECK_MINSIZE) || (len > OCFS2_FILECHECK_MAXSIZE))
return -EINVAL;
- spin_lock(&ent->fs_fcheck->fc_lock);
- if (len < (ent->fs_fcheck->fc_size - ent->fs_fcheck->fc_done)) {
+ spin_lock(&osb->fc_lock);
+ if (len < (osb->fc_size - osb->fc_done)) {
mlog(ML_ERROR,
"Cannot set online file check maximum entry number "
"to %u due to too many pending entries(%u)\n",
- len, ent->fs_fcheck->fc_size - ent->fs_fcheck->fc_done);
+ len, osb->fc_size - osb->fc_done);
ret = -EBUSY;
} else {
- if (len < ent->fs_fcheck->fc_size)
- BUG_ON(!ocfs2_filecheck_erase_entries(ent,
- ent->fs_fcheck->fc_size - len));
+ if (len < osb->fc_size)
+ BUG_ON(!ocfs2_filecheck_erase_entries(osb,
+ osb->fc_size - len));
- ent->fs_fcheck->fc_max = len;
+ osb->fc_max = len;
ret = 0;
}
- spin_unlock(&ent->fs_fcheck->fc_lock);
+ spin_unlock(&osb->fc_lock);
return ret;
}
-#define OCFS2_FILECHECK_ARGS_LEN 24
-static int
-ocfs2_filecheck_args_get_long(const char *buf, size_t count,
- unsigned long *val)
-{
- char buffer[OCFS2_FILECHECK_ARGS_LEN];
-
- memcpy(buffer, buf, count);
- buffer[count] = '\0';
-
- if (kstrtoul(buffer, 0, val))
- return 1;
-
- return 0;
-}
-
-static int
-ocfs2_filecheck_type_parse(const char *name, unsigned int *type)
-{
- if (!strncmp(name, "fix", 4))
- *type = OCFS2_FILECHECK_TYPE_FIX;
- else if (!strncmp(name, "check", 6))
- *type = OCFS2_FILECHECK_TYPE_CHK;
- else if (!strncmp(name, "set", 4))
- *type = OCFS2_FILECHECK_TYPE_SET;
- else
- return 1;
-
- return 0;
-}
-
-static int
-ocfs2_filecheck_args_parse(const char *name, const char *buf, size_t count,
- struct ocfs2_filecheck_args *args)
-{
- unsigned long val = 0;
- unsigned int type;
-
- /* too short/long args length */
- if ((count < 1) || (count >= OCFS2_FILECHECK_ARGS_LEN))
- return 1;
-
- if (ocfs2_filecheck_type_parse(name, &type))
- return 1;
- if (ocfs2_filecheck_args_get_long(buf, count, &val))
- return 1;
-
- if (val <= 0)
- return 1;
- args->fa_type = type;
- if (type == OCFS2_FILECHECK_TYPE_SET)
- args->fa_len = (unsigned int)val;
- else
- args->fa_ino = val;
-
- return 0;
-}
-
-static ssize_t ocfs2_filecheck_show(struct kobject *kobj,
- struct kobj_attribute *attr,
+int ocfs2_filecheck_show(struct ocfs2_super *osb, unsigned int type,
char *buf)
{
ssize_t ret = 0, total = 0, remain = PAGE_SIZE;
- unsigned int type;
struct ocfs2_filecheck_entry *p;
- struct ocfs2_filecheck_sysfs_entry *ent;
-
- if (ocfs2_filecheck_type_parse(attr->attr.name, &type))
- return -EINVAL;
-
- ent = ocfs2_filecheck_sysfs_get(kobj->parent->name);
- if (!ent) {
- mlog(ML_ERROR,
- "Cannot get the corresponding entry via device basename %s\n",
- kobj->name);
- return -ENODEV;
- }
-
- if (type == OCFS2_FILECHECK_TYPE_SET) {
- spin_lock(&ent->fs_fcheck->fc_lock);
- total = snprintf(buf, remain, "%u\n", ent->fs_fcheck->fc_max);
- spin_unlock(&ent->fs_fcheck->fc_lock);
- goto exit;
- }
ret = snprintf(buf, remain, "INO\t\tDONE\tERROR\n");
total += ret;
remain -= ret;
- spin_lock(&ent->fs_fcheck->fc_lock);
- list_for_each_entry(p, &ent->fs_fcheck->fc_head, fe_list) {
+ spin_lock(&osb->fc_lock);
+ list_for_each_entry(p, &osb->file_check_entries, fe_list) {
if (p->fe_type != type)
continue;
@@ -443,24 +127,21 @@ static ssize_t ocfs2_filecheck_show(struct kobject *kobj,
total += ret;
remain -= ret;
}
- spin_unlock(&ent->fs_fcheck->fc_lock);
-
-exit:
- ocfs2_filecheck_sysfs_put(ent);
+ spin_unlock(&osb->fc_lock);
return total;
}
static int
-ocfs2_filecheck_erase_entry(struct ocfs2_filecheck_sysfs_entry *ent)
+ocfs2_filecheck_erase_entry(struct ocfs2_super *osb)
{
struct ocfs2_filecheck_entry *p;
- list_for_each_entry(p, &ent->fs_fcheck->fc_head, fe_list) {
+ list_for_each_entry(p, &osb->file_check_entries, fe_list) {
if (p->fe_done) {
list_del(&p->fe_list);
kfree(p);
- ent->fs_fcheck->fc_size--;
- ent->fs_fcheck->fc_done--;
+ osb->fc_size--;
+ osb->fc_done--;
return 1;
}
}
@@ -469,14 +150,14 @@ ocfs2_filecheck_erase_entry(struct ocfs2_filecheck_sysfs_entry *ent)
}
static int
-ocfs2_filecheck_erase_entries(struct ocfs2_filecheck_sysfs_entry *ent,
+ocfs2_filecheck_erase_entries(struct ocfs2_super *osb,
unsigned int count)
{
unsigned int i = 0;
unsigned int ret = 0;
while (i++ < count) {
- if (ocfs2_filecheck_erase_entry(ent))
+ if (ocfs2_filecheck_erase_entry(osb))
ret++;
else
break;
@@ -486,24 +167,24 @@ ocfs2_filecheck_erase_entries(struct ocfs2_filecheck_sysfs_entry *ent,
}
static void
-ocfs2_filecheck_done_entry(struct ocfs2_filecheck_sysfs_entry *ent,
+ocfs2_filecheck_done_entry(struct ocfs2_super *osb,
struct ocfs2_filecheck_entry *entry)
{
entry->fe_done = 1;
- spin_lock(&ent->fs_fcheck->fc_lock);
- ent->fs_fcheck->fc_done++;
- spin_unlock(&ent->fs_fcheck->fc_lock);
+ spin_lock(&osb->fc_lock);
+ osb->fc_done++;
+ spin_unlock(&osb->fc_lock);
}
static unsigned int
-ocfs2_filecheck_handle(struct super_block *sb,
+ocfs2_filecheck_handle(struct ocfs2_super *osb,
unsigned long ino, unsigned int flags)
{
unsigned int ret = OCFS2_FILECHECK_ERR_SUCCESS;
struct inode *inode = NULL;
int rc;
- inode = ocfs2_iget(OCFS2_SB(sb), ino, flags, 0);
+ inode = ocfs2_iget(osb, ino, flags, 0);
if (IS_ERR(inode)) {
rc = (int)(-(long)inode);
if (rc >= OCFS2_FILECHECK_ERR_START &&
@@ -518,89 +199,64 @@ ocfs2_filecheck_handle(struct super_block *sb,
}
static void
-ocfs2_filecheck_handle_entry(struct ocfs2_filecheck_sysfs_entry *ent,
+ocfs2_filecheck_handle_entry(struct ocfs2_super *osb,
struct ocfs2_filecheck_entry *entry)
{
if (entry->fe_type == OCFS2_FILECHECK_TYPE_CHK)
- entry->fe_status = ocfs2_filecheck_handle(ent->fs_sb,
+ entry->fe_status = ocfs2_filecheck_handle(osb,
entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_CHK);
else if (entry->fe_type == OCFS2_FILECHECK_TYPE_FIX)
- entry->fe_status = ocfs2_filecheck_handle(ent->fs_sb,
+ entry->fe_status = ocfs2_filecheck_handle(osb,
entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_FIX);
else
entry->fe_status = OCFS2_FILECHECK_ERR_UNSUPPORTED;
- ocfs2_filecheck_done_entry(ent, entry);
+ ocfs2_filecheck_done_entry(osb, entry);
}
-static ssize_t ocfs2_filecheck_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t count)
+int ocfs2_filecheck_add_inode(struct ocfs2_super *osb,
+ unsigned long ino)
{
- struct ocfs2_filecheck_args args;
struct ocfs2_filecheck_entry *entry;
- struct ocfs2_filecheck_sysfs_entry *ent;
ssize_t ret = 0;
- if (count == 0)
- return count;
-
- if (ocfs2_filecheck_args_parse(attr->attr.name, buf, count, &args)) {
- mlog(ML_ERROR, "Invalid arguments for online file check\n");
- return -EINVAL;
- }
-
- ent = ocfs2_filecheck_sysfs_get(kobj->parent->name);
- if (!ent) {
- mlog(ML_ERROR,
- "Cannot get the corresponding entry via device basename %s\n",
- kobj->parent->name);
- return -ENODEV;
- }
-
- if (args.fa_type == OCFS2_FILECHECK_TYPE_SET) {
- ret = ocfs2_filecheck_adjust_max(ent, args.fa_len);
- goto exit;
- }
-
entry = kmalloc(sizeof(struct ocfs2_filecheck_entry), GFP_NOFS);
if (!entry) {
ret = -ENOMEM;
goto exit;
}
- spin_lock(&ent->fs_fcheck->fc_lock);
- if ((ent->fs_fcheck->fc_size >= ent->fs_fcheck->fc_max) &&
- (ent->fs_fcheck->fc_done == 0)) {
+ spin_lock(&osb->fc_lock);
+ if ((osb->fc_size >= osb->fc_max) &&
+ (osb->fc_done == 0)) {
mlog(ML_ERROR,
"Cannot do more file check "
"since file check queue(%u) is full now\n",
- ent->fs_fcheck->fc_max);
+ osb->fc_max);
ret = -EBUSY;
kfree(entry);
} else {
- if ((ent->fs_fcheck->fc_size >= ent->fs_fcheck->fc_max) &&
- (ent->fs_fcheck->fc_done > 0)) {
+ if ((osb->fc_size >= osb->fc_max) &&
+ (osb->fc_done > 0)) {
/* Delete the oldest entry which was done,
* make sure the entry size in list does
* not exceed maximum value
*/
- BUG_ON(!ocfs2_filecheck_erase_entry(ent));
+ BUG_ON(!ocfs2_filecheck_erase_entry(osb));
}
- entry->fe_ino = args.fa_ino;
- entry->fe_type = args.fa_type;
+ entry->fe_ino = ino;
+ entry->fe_type = OCFS2_FILECHECK_TYPE_CHK;
entry->fe_done = 0;
entry->fe_status = OCFS2_FILECHECK_ERR_INPROGRESS;
- list_add_tail(&entry->fe_list, &ent->fs_fcheck->fc_head);
- ent->fs_fcheck->fc_size++;
+ list_add_tail(&entry->fe_list, &osb->file_check_entries);
+ osb->fc_size++;
}
- spin_unlock(&ent->fs_fcheck->fc_lock);
+ spin_unlock(&osb->fc_lock);
if (!ret)
- ocfs2_filecheck_handle_entry(ent, entry);
+ ocfs2_filecheck_handle_entry(osb, entry);
exit:
- ocfs2_filecheck_sysfs_put(ent);
- return (!ret ? count : ret);
+ return ret;
}
diff --git a/fs/ocfs2/filecheck.h b/fs/ocfs2/filecheck.h
index e5cd002..b1a0d8c 100644
--- a/fs/ocfs2/filecheck.h
+++ b/fs/ocfs2/filecheck.h
@@ -42,8 +42,18 @@ enum {
#define OCFS2_FILECHECK_ERR_START OCFS2_FILECHECK_ERR_FAILED
#define OCFS2_FILECHECK_ERR_END OCFS2_FILECHECK_ERR_UNSUPPORTED
+#define OCFS2_FILECHECK_MAXSIZE 100
+#define OCFS2_FILECHECK_MINSIZE 10
+
+/* File check operation type */
+#define OCFS2_FILECHECK_TYPE_CHK 1 /* Check a file(inode) */
+#define OCFS2_FILECHECK_TYPE_FIX 2 /* Fix a file(inode) */
int ocfs2_filecheck_create_sysfs(struct super_block *sb);
int ocfs2_filecheck_remove_sysfs(struct super_block *sb);
+int ocfs2_filefix_inode(struct ocfs2_super *osb, unsigned long ino);
+int ocfs2_filecheck_add_inode(struct ocfs2_super *osb, unsigned long ino);
+int ocfs2_filecheck_set_max_entries(struct ocfs2_super *osb, int num);
+int ocfs2_filecheck_show(struct ocfs2_super *osb, unsigned int type, char *buf);
#endif /* FILECHECK_H */
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index e63af7d..a727c99 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -472,6 +472,13 @@ struct ocfs2_super
* workqueue and schedule on our own.
*/
struct workqueue_struct *ocfs2_wq;
+
+ /* file check */
+ struct list_head file_check_entries;
+ unsigned int fc_size;
+ unsigned int fc_max;
+ unsigned int fc_done;
+ spinlock_t fc_lock;
};
#define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info)
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 0419a4a..a909215 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -2212,6 +2212,13 @@ static int ocfs2_initialize_super(struct super_block *sb,
get_random_bytes(&osb->s_next_generation, sizeof(u32));
+ /* file check information */
+ INIT_LIST_HEAD(&osb->file_check_entries);
+ osb->fc_max = OCFS2_FILECHECK_MINSIZE;
+ osb->fc_size = 0;
+ osb->fc_done = 0;
+ spin_lock_init(&osb->fc_lock);
+
/* FIXME
* This should be done in ocfs2_journal_init(), but unknown
* ordering issues will cause the filesystem to crash.
diff --git a/fs/ocfs2/sysfs.c b/fs/ocfs2/sysfs.c
index e4d538b..1cf384f 100644
--- a/fs/ocfs2/sysfs.c
+++ b/fs/ocfs2/sysfs.c
@@ -1,6 +1,7 @@
#include <linux/fs.h>
#include "ocfs2.h"
#include "sysfs.h"
+#include "filecheck.h"
static ssize_t slot_num_show(struct super_block *sb,
struct super_block_attribute *attr,
@@ -10,9 +11,89 @@ static ssize_t slot_num_show(struct super_block *sb,
return sprintf(buf, "%d\n", osb->slot_num);
}
+static ssize_t file_check_show(struct super_block *sb,
+ struct super_block_attribute *attr,
+ char *buf)
+{
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+ return ocfs2_filecheck_show(osb, OCFS2_FILECHECK_TYPE_CHK, buf);
+}
+
+static ssize_t file_check_store(struct super_block *sb,
+ struct super_block_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long t;
+ int ret;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+
+ ret = kstrtoul(skip_spaces(buf), 0, &t);
+ if (ret)
+ return ret;
+ return ocfs2_filecheck_add_inode(osb, t);
+}
+
+static ssize_t file_fix_show(struct super_block *sb,
+ struct super_block_attribute *attr,
+ char *buf)
+{
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+ return ocfs2_filecheck_show(osb, OCFS2_FILECHECK_TYPE_FIX, buf);
+}
+
+static ssize_t file_fix_store(struct super_block *sb,
+ struct super_block_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long t;
+ int ret;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+
+ ret = kstrtoul(skip_spaces(buf), 0, &t);
+ if (ret)
+ return ret;
+ return ocfs2_filecheck_add_inode(osb, t);
+}
+
+static ssize_t file_check_max_entries_show(struct super_block *sb,
+ struct super_block_attribute *attr,
+ char *buf)
+{
+ int len = 0;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+ spin_lock(&osb->fc_lock);
+ /* Show done, current size and max */
+ len += sprintf(buf, "%d\t%d\t%d\n", osb->fc_done, osb->fc_size,
+ osb->fc_max);
+ spin_unlock(&osb->fc_lock);
+ return len;
+}
+
+static ssize_t file_check_max_entries_store(struct super_block *sb,
+ struct super_block_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ unsigned long t;
+ int ret;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+
+ ret = kstrtoul(skip_spaces(buf), 0, &t);
+ if (ret)
+ return ret;
+ return ocfs2_filecheck_set_max_entries(osb, (int)t);
+}
+
static SB_ATTR_RO(slot_num);
+static SB_ATTR(file_check, (S_IWUSR | S_IRUGO));
+static SB_ATTR(file_fix, (S_IWUSR | S_IRUGO));
+static SB_ATTR(file_check_max_entries, (S_IWUSR | S_IRUGO));
+
static struct attribute *ocfs2_sb_attrs[] = {
&sb_attr_slot_num.attr,
+ &sb_attr_file_check.attr,
+ &sb_attr_file_fix.attr,
+ &sb_attr_file_check_max_entries.attr,
NULL
};
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 7/8] ocfs2: report inode errors to userspace
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
` (5 preceding siblings ...)
2016-05-12 18:15 ` [RFC 6/8] ocfs2: create filecheck files Goldwyn Rodrigues
@ 2016-05-12 18:15 ` Goldwyn Rodrigues
2016-05-12 18:15 ` [RFC 8/8] ext4: Let fs create the sysfs entries Goldwyn Rodrigues
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/ocfs2/inode.c | 13 +++++++++++++
fs/ocfs2/sysfs.c | 17 ++++++++++++++++-
fs/ocfs2/sysfs.h | 2 ++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 12f4a9e..a6cfe5d 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -54,6 +54,7 @@
#include "refcounttree.h"
#include "ocfs2_trace.h"
#include "filecheck.h"
+#include "sysfs.h"
#include "buffer_head_io.h"
@@ -1412,6 +1413,9 @@ int ocfs2_validate_inode_block(struct super_block *sb,
rc = ocfs2_error(sb, "Invalid dinode #%llu: signature = %.*s\n",
(unsigned long long)bh->b_blocknr, 7,
di->i_signature);
+ ocfs2_report_error(OCFS2_SB(sb), (unsigned long long)bh->b_blocknr,
+ (unsigned long long)bh->b_blocknr,
+ rc);
goto bail;
}
@@ -1419,6 +1423,9 @@ int ocfs2_validate_inode_block(struct super_block *sb,
rc = ocfs2_error(sb, "Invalid dinode #%llu: i_blkno is %llu\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(di->i_blkno));
+ ocfs2_report_error(OCFS2_SB(sb), (unsigned long long)bh->b_blocknr,
+ (unsigned long long)bh->b_blocknr,
+ rc);
goto bail;
}
@@ -1426,6 +1433,9 @@ int ocfs2_validate_inode_block(struct super_block *sb,
rc = ocfs2_error(sb,
"Invalid dinode #%llu: OCFS2_VALID_FL not set\n",
(unsigned long long)bh->b_blocknr);
+ ocfs2_report_error(OCFS2_SB(sb), (unsigned long long)bh->b_blocknr,
+ (unsigned long long)bh->b_blocknr,
+ rc);
goto bail;
}
@@ -1435,6 +1445,9 @@ int ocfs2_validate_inode_block(struct super_block *sb,
"Invalid dinode #%llu: fs_generation is %u\n",
(unsigned long long)bh->b_blocknr,
le32_to_cpu(di->i_fs_generation));
+ ocfs2_report_error(OCFS2_SB(sb), (unsigned long long)bh->b_blocknr,
+ (unsigned long long)bh->b_blocknr,
+ rc);
goto bail;
}
diff --git a/fs/ocfs2/sysfs.c b/fs/ocfs2/sysfs.c
index 1cf384f..fb7231c 100644
--- a/fs/ocfs2/sysfs.c
+++ b/fs/ocfs2/sysfs.c
@@ -103,5 +103,20 @@ struct kobj_type ocfs2_sb_ktype = {
.release = super_block_release,
};
-
+void ocfs2_report_error(struct ocfs2_super *osb, unsigned long long ino,
+ unsigned long long blkno, int errno)
+{
+ char event_name[] = "EVENT=FS_ERROR";
+ char device[16];
+ char inode_number[16];
+ char error_number[16];
+ char block_number[16];
+ char *envp[] = {event_name, inode_number, error_number, block_number,
+ NULL};
+ snprintf(device, 16, "DEVICE=%s", osb->sb->s_id);
+ snprintf(error_number, 16, "ERROR=%d", errno);
+ snprintf(inode_number, 16, "INODE=%llu", ino);
+ snprintf(block_number, 16, "BLOCK=%llu", blkno);
+ sb_report_event(osb->sb, envp);
+}
diff --git a/fs/ocfs2/sysfs.h b/fs/ocfs2/sysfs.h
index 5809e9b..e31107c 100644
--- a/fs/ocfs2/sysfs.h
+++ b/fs/ocfs2/sysfs.h
@@ -4,5 +4,7 @@
#define _SYS_H
extern struct kobj_type ocfs2_sb_ktype;
+void ocfs2_report_error(struct ocfs2_super *osb, unsigned long long ino,
+ unsigned long long blkno, int error);
#endif
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 8/8] ext4: Let fs create the sysfs entries
2016-05-12 18:14 [RFC v2 0/8] kobject in sysfs superblock Goldwyn Rodrigues
` (6 preceding siblings ...)
2016-05-12 18:15 ` [RFC 7/8] ocfs2: report inode errors to userspace Goldwyn Rodrigues
@ 2016-05-12 18:15 ` Goldwyn Rodrigues
7 siblings, 0 replies; 9+ messages in thread
From: Goldwyn Rodrigues @ 2016-05-12 18:15 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
Another example of usage
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/ext4/ext4.h | 3 ++-
fs/ext4/super.c | 14 ++++++++------
fs/ext4/sysfs.c | 39 +++++++--------------------------------
3 files changed, 17 insertions(+), 39 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 349afeb..294d74d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -3165,8 +3165,9 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations;
/* sysfs.c */
extern int ext4_register_sysfs(struct super_block *sb);
extern void ext4_unregister_sysfs(struct super_block *sb);
-extern int __init ext4_init_sysfs(void);
+extern int __init ext4_init_sysfs(struct kset *kset);
extern void ext4_exit_sysfs(void);
+extern struct kobj_type ext4_sb_ktype;
/* block_validity */
extern void ext4_release_system_zone(struct super_block *sb);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 304c712..be7c0ef 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -5356,6 +5356,7 @@ static struct file_system_type ext4_fs_type = {
.mount = ext4_mount,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
+ .sb_ktype = &ext4_sb_ktype,
};
MODULE_ALIAS_FS("ext4");
@@ -5388,10 +5389,6 @@ static int __init ext4_init_fs(void)
if (err)
goto out4;
- err = ext4_init_sysfs();
- if (err)
- goto out3;
-
err = ext4_init_mballoc();
if (err)
goto out2;
@@ -5402,18 +5399,23 @@ static int __init ext4_init_fs(void)
register_as_ext2();
err = register_filesystem(&ext4_fs_type);
if (err)
+ goto out0;
+
+ err = ext4_init_sysfs(ext4_fs_type.kset);
+ if (err)
goto out;
+
return 0;
out:
+ unregister_filesystem(&ext4_fs_type);
+out0:
unregister_as_ext2();
unregister_as_ext3();
destroy_inodecache();
out1:
ext4_exit_mballoc();
out2:
- ext4_exit_sysfs();
-out3:
ext4_exit_system_zone();
out4:
ext4_exit_pageio();
diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
index 1420a3c..94390d0 100644
--- a/fs/ext4/sysfs.c
+++ b/fs/ext4/sysfs.c
@@ -329,28 +329,18 @@ static const struct sysfs_ops ext4_attr_ops = {
.store = ext4_attr_store,
};
-static struct kobj_type ext4_sb_ktype = {
+struct kobj_type ext4_sb_ktype = {
.default_attrs = ext4_attrs,
.sysfs_ops = &ext4_attr_ops,
.release = ext4_sb_release,
};
-static struct kobj_type ext4_ktype = {
- .sysfs_ops = &ext4_attr_ops,
-};
-
-static struct kset ext4_kset = {
- .kobj = {.ktype = &ext4_ktype},
-};
-
static struct kobj_type ext4_feat_ktype = {
.default_attrs = ext4_feat_attrs,
.sysfs_ops = &ext4_attr_ops,
};
-static struct kobject ext4_feat = {
- .kset = &ext4_kset,
-};
+static struct kobject ext4_feat;
#define PROC_FILE_SHOW_DEFN(name) \
static int name##_open(struct inode *inode, struct file *file) \
@@ -386,14 +376,6 @@ int ext4_register_sysfs(struct super_block *sb)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_proc_files *p;
- int err;
-
- sbi->s_kobj.kset = &ext4_kset;
- init_completion(&sbi->s_kobj_unregister);
- err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, NULL,
- "%s", sb->s_id);
- if (err)
- return err;
if (ext4_proc_root)
sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
@@ -419,29 +401,22 @@ void ext4_unregister_sysfs(struct super_block *sb)
kobject_del(&sbi->s_kobj);
}
-int __init ext4_init_sysfs(void)
+int __init ext4_init_sysfs(struct kset *kset)
{
int ret;
- kobject_set_name(&ext4_kset.kobj, "ext4");
- ext4_kset.kobj.parent = fs_kobj;
- ret = kset_register(&ext4_kset);
- if (ret)
- return ret;
-
+ ext4_feat.kset = kset;
ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype,
NULL, "features");
if (ret)
- kset_unregister(&ext4_kset);
- else
- ext4_proc_root = proc_mkdir(proc_dirname, NULL);
- return ret;
+ return ret;
+ ext4_proc_root = proc_mkdir(proc_dirname, NULL);
+ return 0;
}
void ext4_exit_sysfs(void)
{
kobject_put(&ext4_feat);
- kset_unregister(&ext4_kset);
remove_proc_entry(proc_dirname, NULL);
ext4_proc_root = NULL;
}
--
2.6.6
^ permalink raw reply related [flat|nested] 9+ messages in thread