* [PoC 0/7] Kobjectify filesystem
@ 2016-04-29 2:01 Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 1/7] Add kset to file_system_type Goldwyn Rodrigues
` (7 more replies)
0 siblings, 8 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This is an effort to represent fs structures in terms of kobjects.
The primary goal of this was to provide a mechanism for the filesystems
to provide feedback to userspace but grew more than that.
In case of errors users may fix errors and could schedule a
complete filesystem check at a later point of time.
ENOSPC errors could be automated to delete temporary files
etc.
As a implementation example, I have changed ocfs2 to support the change,
though it is not completely feasible change because of the way ksets are
represented in kset, but it delivers the idea.
Taking this forward may reduce the house-keeping tasks such as searching,
list handling and locking. One example shown here is the super_block
destruction using kobjects. Since most filesystems do represent their
structures in sysfs, this would consolidate individual representations
under the filesystem, hopefully reducing code.
Let me know what you think about the idea.
--
Goldwyn
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PoC 1/7] Add kset to file_system_type
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
@ 2016-04-29 2:01 ` Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 2/7] Add kobject to super_block Goldwyn Rodrigues
` (6 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
Most of the filesystems use kset, even though they don't use
the functions/features associated with kset.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/filesystems.c | 3 +++
include/linux/fs.h | 4 +++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/filesystems.c b/fs/filesystems.c
index c5618db..64560a2 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -81,6 +81,8 @@ int register_filesystem(struct file_system_type * fs)
else
*p = fs;
write_unlock(&file_systems_lock);
+ if (!res && (fs->fs_flags & FS_CREATE_SYSFS))
+ fs->kset = kset_create_and_add(fs->name, NULL, fs_kobj);
return res;
}
@@ -109,6 +111,7 @@ int unregister_filesystem(struct file_system_type * fs)
*tmp = fs->next;
fs->next = NULL;
write_unlock(&file_systems_lock);
+ kset_unregister(fs->kset);
synchronize_rcu();
return 0;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 70e61b5..cfea7b4 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;
@@ -1980,6 +1980,7 @@ struct file_system_type {
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
#define FS_USERNS_DEV_MOUNT 16 /* A userns mount does not imply MNT_NODEV */
#define FS_USERNS_VISIBLE 32 /* FS must already be visible */
+#define FS_CREATE_SYSFS 128 /* Create sysfs entries, temporary flag to explain RFC */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
@@ -1996,6 +1997,7 @@ 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 kset *kset;
};
#define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME)
--
2.6.6
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PoC 2/7] Add kobject to super_block
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 1/7] Add kset to file_system_type Goldwyn Rodrigues
@ 2016-04-29 2:01 ` Goldwyn Rodrigues
2016-04-29 2:26 ` Al Viro
2016-04-29 2:01 ` [PoC 3/7] Create sysfs files under sb Goldwyn Rodrigues
` (5 subsequent siblings)
7 siblings, 1 reply; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This automatically creates the /sys/fs/<fs-type>/<s_id>
It is not necessary to use super_block_attribute structures.
Filesystems can build their own attribute structs. These are just
helper functions if a filesystem chooses to use a simple way to
show it's variables in sysfs.
Also, the SB_ATTR and SB_ATTR_RO helpers to build the
super_block_attribute.
We can use the kobject to (delay) destroy the super block.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/super.c | 57 +++++++++++++++++++++++++++++++++++++++++++++---------
include/linux/fs.h | 26 +++++++++++++++++++++++--
2 files changed, 72 insertions(+), 11 deletions(-)
diff --git a/fs/super.c b/fs/super.c
index 74914b1..5f5e25d 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -135,10 +135,36 @@ static unsigned long super_cache_count(struct shrinker *shrink,
return total_objects;
}
-static void destroy_super_work(struct work_struct *work)
+/* kobject super_block handling */
+
+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->show)
+ return -EIO;
+
+ return sattr->store(sb, sattr, buf, count);
+}
+
+static void release_super(struct kobject *kobj)
{
- struct super_block *s = container_of(work, struct super_block,
- destroy_work);
+ struct super_block *s = container_of(kobj, struct super_block,
+ s_kobj);
int i;
for (i = 0; i < SB_FREEZE_LEVELS; i++)
@@ -146,11 +172,22 @@ static void destroy_super_work(struct work_struct *work)
kfree(s);
}
-static void destroy_super_rcu(struct rcu_head *head)
+static const struct sysfs_ops sb_sysfs_ops = {
+ .show = super_block_attribute_show,
+ .store = super_block_attribute_store,
+};
+
+static int register_kobj(struct super_block *sb)
{
- struct super_block *s = container_of(head, struct super_block, rcu);
- INIT_WORK(&s->destroy_work, destroy_super_work);
- schedule_work(&s->destroy_work);
+ struct kobj_type *ktype;
+ ktype = kzalloc(sizeof(struct kobj_type), GFP_USER);
+ if (IS_ERR(ktype))
+ return PTR_ERR(ktype);
+ ktype->sysfs_ops = &sb_sysfs_ops;
+ ktype->release = release_super;
+ sb->s_kobj.kset = sb->s_type->kset;
+ return kobject_init_and_add(&sb->s_kobj, ktype, NULL,
+ "%s", sb->s_id);
}
/**
@@ -167,7 +204,8 @@ static void destroy_super(struct super_block *s)
WARN_ON(!list_empty(&s->s_mounts));
kfree(s->s_subtype);
kfree(s->s_options);
- call_rcu(&s->rcu, destroy_super_rcu);
+ if (s->s_type->fs_flags & FS_CREATE_SYSFS)
+ kobject_del(&s->s_kobj);
}
/**
@@ -1021,7 +1059,8 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
deactivate_locked_super(s);
goto error;
}
-
+ if (s->s_type->fs_flags & FS_CREATE_SYSFS)
+ register_kobj(s);
s->s_flags |= MS_ACTIVE;
bdev->bd_super = s;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cfea7b4..e6b9d89 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1317,6 +1317,29 @@ struct sb_writers {
struct percpu_rw_semaphore rw_sem[SB_FREEZE_LEVELS];
};
+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, \
+}
+
struct super_block {
struct list_head s_list; /* Keep this first */
dev_t s_dev; /* search index; _not_ kdev_t */
@@ -1406,8 +1429,6 @@ struct super_block {
*/
struct list_lru s_dentry_lru ____cacheline_aligned_in_smp;
struct list_lru s_inode_lru ____cacheline_aligned_in_smp;
- struct rcu_head rcu;
- struct work_struct destroy_work;
struct mutex s_sync_lock; /* sync serialisation lock */
@@ -1419,6 +1440,7 @@ 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;
};
extern struct timespec current_fs_time(struct super_block *sb);
--
2.6.6
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PoC 3/7] Create sysfs files under sb
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 1/7] Add kset to file_system_type Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 2/7] Add kobject to super_block Goldwyn Rodrigues
@ 2016-04-29 2:01 ` Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 4/7] Report file system events Goldwyn Rodrigues
` (4 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This would create sysfs entries under /sys/fs/<fstype>/<s_id>.
fill_super() must initialize attrs. This may not be the best
way to do it. Suggestions?
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/super.c | 8 ++++----
include/linux/fs.h | 1 +
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/fs/super.c b/fs/super.c
index 5f5e25d..f6cef10 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -179,12 +179,12 @@ static const struct sysfs_ops sb_sysfs_ops = {
static int register_kobj(struct super_block *sb)
{
- struct kobj_type *ktype;
- ktype = kzalloc(sizeof(struct kobj_type), GFP_USER);
- if (IS_ERR(ktype))
- return PTR_ERR(ktype);
+ struct kobj_type *ktype = kzalloc(sizeof(struct kobj_type), GFP_USER);
+ if (!ktype)
+ return -ENOMEM;
ktype->sysfs_ops = &sb_sysfs_ops;
ktype->release = release_super;
+ ktype->default_attrs = sb->s_attr;
sb->s_kobj.kset = sb->s_type->kset;
return kobject_init_and_add(&sb->s_kobj, ktype, NULL,
"%s", sb->s_id);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e6b9d89..59b84a8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1441,6 +1441,7 @@ struct super_block {
spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp;
struct list_head s_inodes; /* all inodes */
struct kobject s_kobj;
+ struct attribute **s_attr;
};
extern struct timespec current_fs_time(struct super_block *sb);
--
2.6.6
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PoC 4/7] Report file system events
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
` (2 preceding siblings ...)
2016-04-29 2:01 ` [PoC 3/7] Create sysfs files under sb Goldwyn Rodrigues
@ 2016-04-29 2:01 ` Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 5/7] ocfs2: Use the sb's kset Goldwyn Rodrigues
` (3 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 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 f6cef10..50b5ae5 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -190,6 +190,12 @@ static int register_kobj(struct super_block *sb)
"%s", sb->s_id);
}
+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 59b84a8..d356485 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2092,6 +2092,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] 17+ messages in thread
* [PoC 5/7] ocfs2: Use the sb's kset
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
` (3 preceding siblings ...)
2016-04-29 2:01 ` [PoC 4/7] Report file system events Goldwyn Rodrigues
@ 2016-04-29 2:01 ` Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 6/7] ocfs2: create filecheck files Goldwyn Rodrigues
` (2 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 UTC (permalink / raw)
To: linux-fsdevel; +Cc: Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This is just for demonstration. The original ocfs2_kset has been
used to create ocfs2_stack. Not the ideal way to do it.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
fs/ocfs2/Makefile | 3 ++-
fs/ocfs2/stackglue.c | 3 +--
fs/ocfs2/super.c | 8 ++++----
fs/ocfs2/sysfs.c | 26 ++++++++++++++++++++++++++
fs/ocfs2/sysfs.h | 8 ++++++++
5 files changed, 41 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..b899cde 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,8 +1201,8 @@ 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);
+ /* Create sysfs entries */
+ ocfs2_sysfs_sb_init(sb);
return status;
@@ -1232,7 +1233,7 @@ static struct file_system_type ocfs2_fs_type = {
.name = "ocfs2",
.mount = ocfs2_mount,
.kill_sb = kill_block_super,
- .fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
+ .fs_flags = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE|FS_CREATE_SYSFS,
.next = NULL
};
MODULE_ALIAS_FS("ocfs2");
@@ -1653,7 +1654,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..1e57e6c
--- /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
+};
+
+int ocfs2_sysfs_sb_init(struct super_block *sb)
+{
+ sb->s_attr = ocfs2_sb_attrs;
+ return 0;
+
+}
+
+
diff --git a/fs/ocfs2/sysfs.h b/fs/ocfs2/sysfs.h
new file mode 100644
index 0000000..328f9c749
--- /dev/null
+++ b/fs/ocfs2/sysfs.h
@@ -0,0 +1,8 @@
+
+
+#ifndef _SYS_H
+#define _SYS_H
+
+int ocfs2_sysfs_sb_init(struct super_block *sb);
+
+#endif
--
2.6.6
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PoC 6/7] ocfs2: create filecheck files
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
` (4 preceding siblings ...)
2016-04-29 2:01 ` [PoC 5/7] ocfs2: Use the sb's kset Goldwyn Rodrigues
@ 2016-04-29 2:01 ` Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 7/7] ocfs2: report inode errors to userspace Goldwyn Rodrigues
2016-04-29 17:32 ` [PoC 0/7] Kobjectify filesystem Viacheslav Dubeyko
7 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 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 b899cde..7e282fc 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -2214,6 +2214,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 1e57e6c..738bad6 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] 17+ messages in thread
* [PoC 7/7] ocfs2: report inode errors to userspace
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
` (5 preceding siblings ...)
2016-04-29 2:01 ` [PoC 6/7] ocfs2: create filecheck files Goldwyn Rodrigues
@ 2016-04-29 2:01 ` Goldwyn Rodrigues
2016-04-29 17:32 ` [PoC 0/7] Kobjectify filesystem Viacheslav Dubeyko
7 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 2:01 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, 32 insertions(+)
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 738bad6..886ce57 100644
--- a/fs/ocfs2/sysfs.c
+++ b/fs/ocfs2/sysfs.c
@@ -97,6 +97,23 @@ static struct attribute *ocfs2_sb_attrs[] = {
NULL
};
+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);
+}
+
int ocfs2_sysfs_sb_init(struct super_block *sb)
{
sb->s_attr = ocfs2_sb_attrs;
diff --git a/fs/ocfs2/sysfs.h b/fs/ocfs2/sysfs.h
index 328f9c749..9eddcf6 100644
--- a/fs/ocfs2/sysfs.h
+++ b/fs/ocfs2/sysfs.h
@@ -3,6 +3,8 @@
#ifndef _SYS_H
#define _SYS_H
+void ocfs2_report_error(struct ocfs2_super *osb, unsigned long long ino,
+ unsigned long long blkno, int error);
int ocfs2_sysfs_sb_init(struct super_block *sb);
#endif
--
2.6.6
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PoC 2/7] Add kobject to super_block
2016-04-29 2:01 ` [PoC 2/7] Add kobject to super_block Goldwyn Rodrigues
@ 2016-04-29 2:26 ` Al Viro
2016-04-29 19:09 ` Goldwyn Rodrigues
0 siblings, 1 reply; 17+ messages in thread
From: Al Viro @ 2016-04-29 2:26 UTC (permalink / raw)
To: Goldwyn Rodrigues; +Cc: linux-fsdevel, Goldwyn Rodrigues
On Thu, Apr 28, 2016 at 09:01:17PM -0500, Goldwyn Rodrigues wrote:
> @@ -167,7 +204,8 @@ static void destroy_super(struct super_block *s)
> WARN_ON(!list_empty(&s->s_mounts));
> kfree(s->s_subtype);
> kfree(s->s_options);
> - call_rcu(&s->rcu, destroy_super_rcu);
> + if (s->s_type->fs_flags & FS_CREATE_SYSFS)
> + kobject_del(&s->s_kobj);
So we have kobject_del() under a spinlock. Wonderful... Better yet,
you have the sodding kobjects sitting around well past the point when
the filesystem driver has gone through rmmod.
sysfs: lifetime rules made simple. So simple that they don't fit a lot of
situations, but hey - it sure *looks* easy to use...
NAK. If you want a description of super_block life cycle, I can describe it
to you. But please, don't play with it until you understand it.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 0/7] Kobjectify filesystem
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
` (6 preceding siblings ...)
2016-04-29 2:01 ` [PoC 7/7] ocfs2: report inode errors to userspace Goldwyn Rodrigues
@ 2016-04-29 17:32 ` Viacheslav Dubeyko
2016-04-29 18:28 ` Goldwyn Rodrigues
7 siblings, 1 reply; 17+ messages in thread
From: Viacheslav Dubeyko @ 2016-04-29 17:32 UTC (permalink / raw)
To: Goldwyn Rodrigues; +Cc: linux-fsdevel, Goldwyn Rodrigues
Hi Goldwyn,
On Thu, 2016-04-28 at 21:01 -0500, Goldwyn Rodrigues wrote:
> From: Goldwyn Rodrigues <rgoldwyn@suse.com>
>
> This is an effort to represent fs structures in terms of kobjects.
>
> The primary goal of this was to provide a mechanism for the filesystems
> to provide feedback to userspace but grew more than that.
> In case of errors users may fix errors and could schedule a
> complete filesystem check at a later point of time.
> ENOSPC errors could be automated to delete temporary files
> etc.
>
> As a implementation example, I have changed ocfs2 to support the change,
> though it is not completely feasible change because of the way ksets are
> represented in kset, but it delivers the idea.
>
> Taking this forward may reduce the house-keeping tasks such as searching,
> list handling and locking. One example shown here is the super_block
> destruction using kobjects. Since most filesystems do represent their
> structures in sysfs, this would consolidate individual representations
> under the filesystem, hopefully reducing code.
>
> Let me know what you think about the idea.
>
You can register any attributes in sysfs. So, what do you suggest
finally? What common scheme for all file systems do you suggest to use?
Suppose, I didn't catch the idea. Did you invent sysfs itself? Could you
describe your vision more clearly? The idea looks obscure right now,
from my point of view.
Thanks,
Vyacheslav Dubeyko.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 0/7] Kobjectify filesystem
2016-04-29 17:32 ` [PoC 0/7] Kobjectify filesystem Viacheslav Dubeyko
@ 2016-04-29 18:28 ` Goldwyn Rodrigues
2016-04-29 20:16 ` Viacheslav Dubeyko
2016-04-29 22:31 ` Al Viro
0 siblings, 2 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 18:28 UTC (permalink / raw)
To: Viacheslav Dubeyko; +Cc: linux-fsdevel, Goldwyn Rodrigues
On 04/29/2016 12:32 PM, Viacheslav Dubeyko wrote:
> Hi Goldwyn,
>
> On Thu, 2016-04-28 at 21:01 -0500, Goldwyn Rodrigues wrote:
>> From: Goldwyn Rodrigues <rgoldwyn@suse.com>
>>
>> This is an effort to represent fs structures in terms of kobjects.
>>
>> The primary goal of this was to provide a mechanism for the filesystems
>> to provide feedback to userspace but grew more than that.
>> In case of errors users may fix errors and could schedule a
>> complete filesystem check at a later point of time.
>> ENOSPC errors could be automated to delete temporary files
>> etc.
>>
>> As a implementation example, I have changed ocfs2 to support the change,
>> though it is not completely feasible change because of the way ksets are
>> represented in kset, but it delivers the idea.
>>
>> Taking this forward may reduce the house-keeping tasks such as searching,
>> list handling and locking. One example shown here is the super_block
>> destruction using kobjects. Since most filesystems do represent their
>> structures in sysfs, this would consolidate individual representations
>> under the filesystem, hopefully reducing code.
>>
>> Let me know what you think about the idea.
>>
>
> You can register any attributes in sysfs. So, what do you suggest
> finally? What common scheme for all file systems do you suggest to use?
> Suppose, I didn't catch the idea. Did you invent sysfs itself? Could you
> describe your vision more clearly? The idea looks obscure right now,
> from my point of view.
>
Yes, you can register any attribute to sysfs, and most filesystems are
doing exactly that. They maintain the kobject in their <fs>_super_block
struct and use it to create /sys/fs/<fstype>/<id> entries. So what I
propose is this:
1. Move the kobject to super_block from individual filesystem's
super_block structs and institute it when the filesystem mounts. We
could use explicit flags if filesystems choose not to use this "feature"
and do it on their own.
2. Add a kset to files_system_type to create the /sys/fs/<fstype> entry.
Again, most filesystems are doing this anyways.
3. Provide super_block_attribute structures if filesystems want to
export their filesystem attributes via sysfs. Individual filesystems
would have to write their own <name>_store() and <name>_show() functions
to describe how/what they want to export the values. These are purely
helping functions.
4. (Primary objective: Improve availability of filesystems) Use the
kobject in the super_block to generate filesystem uevents which could be
used to communicate errors. The idea was to provide an option of
errors=continue in filesystems so filesystems continue in case of
errors. While the process encountering the error will be terminated with
say an EIO, however an error-code is also delivered through uevent which
can be picked up by udev scripts. Since the filesystem module is also
listed, each individual filesystems should come out with a utility to
fix the problem while the filesystem is online at best-effort ability.
Or could take backups or inform the administrator etc.
For a fix, the uevent would deliver the necessary information, say the
inode number or file path, which could be used to fix this. The
filesystem utility would use this to fix the error online. Once fixed,
the program which caused the error can be restarted. Other possible
errors are ENOSPC being interrupt based as opposed to poll based
applications which exist today.
Currently, ocfs2 performs an online fix, albeit at a basic inode block
level. You write the faulty inode number into a sysfs file and it tries
to fix inode block.
Please note, this is a trade-off between availability and
consistency/integrity in the system. While such a system would keep the
system alive and running at peak hours, a complete fsck may still be
required when the administrators are more at peace (off-peak hours)
--
Goldwyn
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 2/7] Add kobject to super_block
2016-04-29 2:26 ` Al Viro
@ 2016-04-29 19:09 ` Goldwyn Rodrigues
0 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 19:09 UTC (permalink / raw)
To: Al Viro; +Cc: linux-fsdevel, Goldwyn Rodrigues
On 04/28/2016 09:26 PM, Al Viro wrote:
> On Thu, Apr 28, 2016 at 09:01:17PM -0500, Goldwyn Rodrigues wrote:
>> @@ -167,7 +204,8 @@ static void destroy_super(struct super_block *s)
>> WARN_ON(!list_empty(&s->s_mounts));
>> kfree(s->s_subtype);
>> kfree(s->s_options);
>> - call_rcu(&s->rcu, destroy_super_rcu);
>> + if (s->s_type->fs_flags & FS_CREATE_SYSFS)
>> + kobject_del(&s->s_kobj);
>
> So we have kobject_del() under a spinlock. Wonderful... Better yet,
> you have the sodding kobjects sitting around well past the point when
> the filesystem driver has gone through rmmod.
>
> sysfs: lifetime rules made simple. So simple that they don't fit a lot of
> situations, but hey - it sure *looks* easy to use...
>
> NAK. If you want a description of super_block life cycle, I can describe it
> to you. But please, don't play with it until you understand it.
>
Yes, I understand what you are trying to say. Using kobject to destroy
super_block does not make sense in the current scenario.
Thanks for your feedback.
--
Goldwyn
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 0/7] Kobjectify filesystem
2016-04-29 18:28 ` Goldwyn Rodrigues
@ 2016-04-29 20:16 ` Viacheslav Dubeyko
2016-04-29 22:09 ` Goldwyn Rodrigues
2016-04-29 22:31 ` Al Viro
1 sibling, 1 reply; 17+ messages in thread
From: Viacheslav Dubeyko @ 2016-04-29 20:16 UTC (permalink / raw)
To: Goldwyn Rodrigues; +Cc: linux-fsdevel, Goldwyn Rodrigues
On Fri, 2016-04-29 at 13:28 -0500, Goldwyn Rodrigues wrote:
>
> On 04/29/2016 12:32 PM, Viacheslav Dubeyko wrote:
> >
> > You can register any attributes in sysfs. So, what do you suggest
> > finally? What common scheme for all file systems do you suggest to use?
> > Suppose, I didn't catch the idea. Did you invent sysfs itself? Could you
> > describe your vision more clearly? The idea looks obscure right now,
> > from my point of view.
> >
> Yes, you can register any attribute to sysfs, and most filesystems are
> doing exactly that. They maintain the kobject in their <fs>_super_block
> struct and use it to create /sys/fs/<fstype>/<id> entries. So what I
> propose is this:
>
> 1. Move the kobject to super_block from individual filesystem's
> super_block structs and institute it when the filesystem mounts. We
> could use explicit flags if filesystems choose not to use this "feature"
> and do it on their own.
>
> 2. Add a kset to files_system_type to create the /sys/fs/<fstype> entry.
> Again, most filesystems are doing this anyways.
>
OK. I see your point. Sounds reasonable for me.
> 3. Provide super_block_attribute structures if filesystems want to
> export their filesystem attributes via sysfs. Individual filesystems
> would have to write their own <name>_store() and <name>_show() functions
> to describe how/what they want to export the values. These are purely
> helping functions.
>
> 4. (Primary objective: Improve availability of filesystems) Use the
> kobject in the super_block to generate filesystem uevents which could be
> used to communicate errors. The idea was to provide an option of
> errors=continue in filesystems so filesystems continue in case of
> errors. While the process encountering the error will be terminated with
> say an EIO, however an error-code is also delivered through uevent which
> can be picked up by udev scripts. Since the filesystem module is also
> listed, each individual filesystems should come out with a utility to
> fix the problem while the filesystem is online at best-effort ability.
> Or could take backups or inform the administrator etc.
> For a fix, the uevent would deliver the necessary information, say the
> inode number or file path, which could be used to fix this. The
> filesystem utility would use this to fix the error online. Once fixed,
> the program which caused the error can be restarted. Other possible
> errors are ENOSPC being interrupt based as opposed to poll based
> applications which exist today.
Are you sure that error code or inode number will be enough for file
system consistency recovering? Usually, it needs to unmount a file
system for recovering activity. Are you sure that application will be
able to survive after or during fsck utility activity? How do you
imagine the whole workflow? Again, not every file system has fsck
utility and not every corruption could be fixed by fsck.
> Currently, ocfs2 performs an online fix, albeit at a basic inode block
> level. You write the faulty inode number into a sysfs file and it tries
> to fix inode block.
> Please note, this is a trade-off between availability and
> consistency/integrity in the system. While such a system would keep the
> system alive and running at peak hours, a complete fsck may still be
> required when the administrators are more at peace (off-peak hours)
>
So, what generalized functionality are you ready to provide for other
file systems? And what generalized interface should be used by file
systems? Could you share your preliminary vision?
Thanks,
Vyacheslav Dubeyko.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 0/7] Kobjectify filesystem
2016-04-29 20:16 ` Viacheslav Dubeyko
@ 2016-04-29 22:09 ` Goldwyn Rodrigues
0 siblings, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 22:09 UTC (permalink / raw)
To: Viacheslav Dubeyko; +Cc: linux-fsdevel, Goldwyn Rodrigues
On 04/29/2016 03:16 PM, Viacheslav Dubeyko wrote:
> On Fri, 2016-04-29 at 13:28 -0500, Goldwyn Rodrigues wrote:
>>
>> On 04/29/2016 12:32 PM, Viacheslav Dubeyko wrote:
>>>
>>> You can register any attributes in sysfs. So, what do you suggest
>>> finally? What common scheme for all file systems do you suggest to use?
>>> Suppose, I didn't catch the idea. Did you invent sysfs itself? Could you
>>> describe your vision more clearly? The idea looks obscure right now,
>>> from my point of view.
>>>
>> Yes, you can register any attribute to sysfs, and most filesystems are
>> doing exactly that. They maintain the kobject in their <fs>_super_block
>> struct and use it to create /sys/fs/<fstype>/<id> entries. So what I
>> propose is this:
>>
>> 1. Move the kobject to super_block from individual filesystem's
>> super_block structs and institute it when the filesystem mounts. We
>> could use explicit flags if filesystems choose not to use this "feature"
>> and do it on their own.
>>
>> 2. Add a kset to files_system_type to create the /sys/fs/<fstype> entry.
>> Again, most filesystems are doing this anyways.
>>
>
> OK. I see your point. Sounds reasonable for me.
>
>> 3. Provide super_block_attribute structures if filesystems want to
>> export their filesystem attributes via sysfs. Individual filesystems
>> would have to write their own <name>_store() and <name>_show() functions
>> to describe how/what they want to export the values. These are purely
>> helping functions.
>>
>> 4. (Primary objective: Improve availability of filesystems) Use the
>> kobject in the super_block to generate filesystem uevents which could be
>> used to communicate errors. The idea was to provide an option of
>> errors=continue in filesystems so filesystems continue in case of
>> errors. While the process encountering the error will be terminated with
>> say an EIO, however an error-code is also delivered through uevent which
>> can be picked up by udev scripts. Since the filesystem module is also
>> listed, each individual filesystems should come out with a utility to
>> fix the problem while the filesystem is online at best-effort ability.
>> Or could take backups or inform the administrator etc.
>> For a fix, the uevent would deliver the necessary information, say the
>> inode number or file path, which could be used to fix this. The
>> filesystem utility would use this to fix the error online. Once fixed,
>> the program which caused the error can be restarted. Other possible
>> errors are ENOSPC being interrupt based as opposed to poll based
>> applications which exist today.
>
> Are you sure that error code or inode number will be enough for file
> system consistency recovering? Usually, it needs to unmount a file
> system for recovering activity.
Perhaps not, but filesystems would have enough information required to
focus on the error and hence the fix. And that should be provided in the
uevent by individual filesystems. This is an effort to improve
availability in case of errors and avoid an umount (translated downtime)
for fsck, or at least postpone it to a later time.
> Are you sure that application will be
> able to survive after or during fsck utility activity?
No, the application will not survive. The application will get an EIO or
some other error. However, as soon as the online fsck has done it's
patching (successfully), the application would be able to re-start
immediately until a downtime can be scheduled.
Consider this approach as a EMS (Emergency Medical Service) as opposed
to a full hospital recovery. A paramedic will provide the best possible
first aid until the time the patient can be taken to a hospital for a
full recovery (offline fsck recovery). Depending on the kind of failure,
it is possible the paramedic can handle everything required to get
the patient on his feet or cannot do anything to fix the problem.
> How do you
> imagine the whole workflow? Again, not every file system has fsck
> utility and not every corruption could be fixed by fsck.
This hopefully would provide an ecosystem for the filesystem developers
to come up with ideas and utilities which can fix the error as soon as
possible. This can/would be automated through udev scripts. Yes,
filesystems don't have it as yet, but I am hoping this effort will lead
to it. If the error cannot be solved from an offline fsck, I doubt an
online fsck would be able to solve it.
>
>> Currently, ocfs2 performs an online fix, albeit at a basic inode block
>> level. You write the faulty inode number into a sysfs file and it tries
>> to fix inode block.
>> Please note, this is a trade-off between availability and
>> consistency/integrity in the system. While such a system would keep the
>> system alive and running at peak hours, a complete fsck may still be
>> required when the administrators are more at peace (off-peak hours)
>>
>
> So, what generalized functionality are you ready to provide for other
> file systems? And what generalized interface should be used by file
> systems? Could you share your preliminary vision?
The fs layer would provide a function report_event() for filesystems to
use. When a filesystem encounters an error, it reports to userspace
using uevents/udev in the form of "VARIABLE=VALUE" arrays. A udev script
will interpret this information and take the necessary action, which
could be a user defined script. Users are creative enough to do what
they want. It could be any of:
- Mailing the administrator
- Fixing the error through online checks
- Something else the user wants to do.
I know xfs has been working on online filesystem checks for a while:
http://xfs.org/index.php/Reliable_Detection_and_Repair_of_Metadata_Corruption
--
Goldwyn
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 0/7] Kobjectify filesystem
2016-04-29 18:28 ` Goldwyn Rodrigues
2016-04-29 20:16 ` Viacheslav Dubeyko
@ 2016-04-29 22:31 ` Al Viro
2016-04-29 22:45 ` Goldwyn Rodrigues
2016-05-04 22:20 ` Dave Chinner
1 sibling, 2 replies; 17+ messages in thread
From: Al Viro @ 2016-04-29 22:31 UTC (permalink / raw)
To: Goldwyn Rodrigues; +Cc: Viacheslav Dubeyko, linux-fsdevel, Goldwyn Rodrigues
On Fri, Apr 29, 2016 at 01:28:00PM -0500, Goldwyn Rodrigues wrote:
> Yes, you can register any attribute to sysfs, and most filesystems
> are doing exactly that. They maintain the kobject in their
> <fs>_super_block struct and use it to create /sys/fs/<fstype>/<id>
> entries. So what I propose is this:
[snip]
What's really missing here is
0. carefully audit the existing sysfs users of that sort - they are _very_
easy to get wrong, especially wrt lifetime issues and locking. As you have
demonstrated yourself in this patchset, BTW...
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 0/7] Kobjectify filesystem
2016-04-29 22:31 ` Al Viro
@ 2016-04-29 22:45 ` Goldwyn Rodrigues
2016-05-04 22:20 ` Dave Chinner
1 sibling, 0 replies; 17+ messages in thread
From: Goldwyn Rodrigues @ 2016-04-29 22:45 UTC (permalink / raw)
To: Al Viro; +Cc: Viacheslav Dubeyko, linux-fsdevel, Goldwyn Rodrigues
On 04/29/2016 05:31 PM, Al Viro wrote:
> On Fri, Apr 29, 2016 at 01:28:00PM -0500, Goldwyn Rodrigues wrote:
>
>> Yes, you can register any attribute to sysfs, and most filesystems
>> are doing exactly that. They maintain the kobject in their
>> <fs>_super_block struct and use it to create /sys/fs/<fstype>/<id>
>> entries. So what I propose is this:
>
> [snip]
>
> What's really missing here is
>
> 0. carefully audit the existing sysfs users of that sort - they are _very_
> easy to get wrong, especially wrt lifetime issues and locking. As you have
> demonstrated yourself in this patchset, BTW...
>
Agree. And I accept the way I have used the kobjects in this patchset
is incorrect. I am reading on existing usage to get this right and have
not yet completed my reading. Thank you for pointing me to the right
direction.
However, if you feel that it is absolutely infeasible to use kobjects at
all in these fs structures with respect to lifetime and locking, please
let me know the reason and I will stop my effort in this direction and
think of alternative ways to do this.
--
Goldwyn
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PoC 0/7] Kobjectify filesystem
2016-04-29 22:31 ` Al Viro
2016-04-29 22:45 ` Goldwyn Rodrigues
@ 2016-05-04 22:20 ` Dave Chinner
1 sibling, 0 replies; 17+ messages in thread
From: Dave Chinner @ 2016-05-04 22:20 UTC (permalink / raw)
To: Al Viro
Cc: Goldwyn Rodrigues, Viacheslav Dubeyko, linux-fsdevel,
Goldwyn Rodrigues
On Fri, Apr 29, 2016 at 11:31:48PM +0100, Al Viro wrote:
> On Fri, Apr 29, 2016 at 01:28:00PM -0500, Goldwyn Rodrigues wrote:
>
> > Yes, you can register any attribute to sysfs, and most filesystems
> > are doing exactly that. They maintain the kobject in their
> > <fs>_super_block struct and use it to create /sys/fs/<fstype>/<id>
> > entries. So what I propose is this:
>
> [snip]
>
> What's really missing here is
>
> 0. carefully audit the existing sysfs users of that sort - they are _very_
> easy to get wrong, especially wrt lifetime issues and locking. As you have
> demonstrated yourself in this patchset, BTW...
They don't screw with superblock lifetimes for this very reason.
On the XFS side, we create the kset object for /sys/fs/xfs in the
XFs module init function, and destroy it in the module exit
function. There are also some "global" sysfs objects
created/destroyed under /sys/fs/xfs at the same time.
The per-superblock objects (e.g. /sys/fs/xfs/<dev>/*) are created
inside the struct xfs_mount, which means their life cycle is
maintained inside the life of the struct superblock. i.e. they are
created inside ->fill_super, and removal (and removal completion)
occurs inside ->put_super and hence have no impact on or control
over the superblock life cycle.
ext4 has the same structure of init and teardown, as does btrfs
(though it identifies mounted filesystems by uuid rather than device
names).
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2016-05-04 22:20 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-04-29 2:01 [PoC 0/7] Kobjectify filesystem Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 1/7] Add kset to file_system_type Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 2/7] Add kobject to super_block Goldwyn Rodrigues
2016-04-29 2:26 ` Al Viro
2016-04-29 19:09 ` Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 3/7] Create sysfs files under sb Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 4/7] Report file system events Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 5/7] ocfs2: Use the sb's kset Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 6/7] ocfs2: create filecheck files Goldwyn Rodrigues
2016-04-29 2:01 ` [PoC 7/7] ocfs2: report inode errors to userspace Goldwyn Rodrigues
2016-04-29 17:32 ` [PoC 0/7] Kobjectify filesystem Viacheslav Dubeyko
2016-04-29 18:28 ` Goldwyn Rodrigues
2016-04-29 20:16 ` Viacheslav Dubeyko
2016-04-29 22:09 ` Goldwyn Rodrigues
2016-04-29 22:31 ` Al Viro
2016-04-29 22:45 ` Goldwyn Rodrigues
2016-05-04 22:20 ` Dave Chinner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).