ocfs2: sysfs and cleanup
v2 cover ocfs2: sysfs and cleanup
From: Goldwyn Rodrigues <[email protected]>
This adds /sys/fs/ocfs2/<s_id> to the sys filesystem. All other files are added in this directory. This is done by:
1. Adding kobject in the ocfs2_super structure
2. Using ocfs2_sb_attr which encompass all the show() and store() functions
This also reduce code and does away with unnecessary data structure, but adds some in the ocfs2_super for house keeping.
Hopefully, this would be used to further add configurable parameters for the super block.
Suggestions/Criticism welcome.
Changes since v1:
- Corrected store() function check
Signature · 1 line
Goldwyn
PATCH v2 1/5 ocfs2: Provisions for sysfs entries
From: Goldwyn Rodrigues <[email protected]>
This adds /sys/fs/ocfs2/<s_id> to the sys filesystem. This is done by adding the kobj into the ocfs2_super. All other files are added in this directory.
Introduce ocfs2_sb_attr which encompasses the store() and show() functions. Move all the important data structures with respect to filechecks to ocfs2_super.
More superblock information should move in here.
--- fs/ocfs2/Makefile | 3 +- fs/ocfs2/ocfs2.h | 4 +++ fs/ocfs2/super.c | 7 +++-- fs/ocfs2/sysfs.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/sysfs.h | 9 ++++++ 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 fs/ocfs2/sysfs.c create mode 100644 fs/ocfs2/sysfs.h
fs/ocfs2/Makefile +2 -1
@@ -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
fs/ocfs2/ocfs2.h +4 -0
@@ -37,6 +37,7 @@#include <linux/mutex.h> #include <linux/lockdep.h> #include <linux/jbd2.h> +#include <linux/kobject.h> /* For union ocfs2_dlm_lksb */ #include "stackglue.h"
@@ -472,6 +473,9 @@ struct ocfs2_super* workqueue and schedule on our own. */ struct workqueue_struct *ocfs2_wq; + +struct kobject kobj; +struct completion kobj_unregister; };#define OCFS2_SB (sb) ((struct ocfs2_super *)(sb)->s_fs_info)
fs/ocfs2/super.c +4 -3
@@ -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;
@@ -1651,9 +1652,9 @@ static void ocfs2_put_super(struct super_block *sb) {trace_ocfs2_put_super (sb); +ocfs2_sysfs_sb_exit (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)
fs/ocfs2/sysfs.c new file +92 -0
92 lines not on this page · raw message
fs/ocfs2/sysfs.h new file +9 -0
@@ -0,0 +1,9 @@ + + +#ifndef _SYS_H +#define _SYS_H + +int ocfs2_sysfs_sb_init (struct super_block *sb); +void ocfs2_sysfs_sb_exit (struct super_block *sb); + +#endif
Signature · 1 line
2.6.6
PATCH 1/5 ocfs2: Provisions for sysfs entries
Hello Goldwyn,
Thanks for your code, my comments are inline.
Quoted 4 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
This adds /sys/fs/ocfs2/<s_id> to the sys filesystem. This
Gang: My suggestion is to create a sysfs directory device_name under /sys/fs/ocfs2 per each file system, The file system generic attributes should be located under this top sub directory /sys/fs/ocfs2/<s_id>, but we should create a separate sub directory (e.g. filecheck) under this top sub directory for file check feature, then, all the file check related attributes should be located under that directory /sys/fs/ocfs2/<s_id>/filecheck. You know, in the future, we maybe add more attributes/sub directories under /sys/fs/ocfs2/<s_id>,
I should make sure the file check feature is not mixed with other things, it is easy to read/debug for the users/developers.
fs/ocfs2/sysfs.c
Quoted 97 lines
is done by adding the kobj into the
ocfs2_super. All other files are added in this directory.Introduce
ocfs2_sb_attrwhich encompasses thestore()andshow()functions. Move all the important data structures with respect to filechecks toocfs2_super.More superblock information should move in here.
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/Makefile | 3 +- fs/ocfs2/ocfs2.h | 4 +++ fs/ocfs2/super.c | 7 +++-- fs/ocfs2/sysfs.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/sysfs.h | 9 ++++++ 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 fs/ocfs2/sysfs.c create mode 100644 fs/ocfs2/sysfs.hfs/ocfs2/Makefile +2
-1@@ -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.ofs/ocfs2/ocfs2.h +4
-0@@ -37,6 +37,7 @@#include <linux/mutex.h> #include <linux/lockdep.h> #include <linux/jbd2.h> +#include <linux/kobject.h> /* For union ocfs2_dlm_lksb */ #include "stackglue.h" @@ -472,6 +473,9 @@ struct ocfs2_super* workqueue and schedule on our own. */ struct workqueue_struct *ocfs2_wq; + +struct kobject kobj; +struct completion kobj_unregister; };#define OCFS2_SB (sb) ((struct ocfs2_super *)(sb)->s_fs_info)fs/ocfs2/super.c +4
-3@@ -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;@@ -1651,9 +1652,9 @@ static void ocfs2_put_super(struct super_block *sb) {trace_ocfs2_put_super (sb); +ocfs2_sysfs_sb_exit (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)fs/ocfs2/sysfs.c new file +0
-0
Gang: please add source file comments like other source files.
fs/ocfs2/sysfs.h
Quoted 98 lines
fs/ocfs2/sysfs.c new file +92
-0@@ -0,0 +1,92 @@ +#include "ocfs2.h" +#include "sysfs.h" + +struct ocfs2_sb_attr { +struct attribute attr; +ssize_t (*show)(struct ocfs2_super *,struct ocfs2_sb_attr *, +char *buf); +ssize_t (*store)(struct ocfs2_super *,struct ocfs2_sb_attr *, +const char *buf,size_t count); +}; + +#define OCFS2_SB_ATTR (_name, _mode) \ +struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) + +#define OCFS2_SB_ATTR_RO (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name) + +static ssize_t ocfs2_sb_attr_show (struct kobject *kobj, +struct attribute *attr,char *buf) +{ +struct ocfs2_sb_attr *oa = + container_of(attr, struct ocfs2_sb_attr, attr); + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +if (!oa->show) +return -EIO ; + +return oa->show (osb, oa, buf); +} + +static ssize_t ocfs2_sb_attr_store (struct kobject *kobj, +struct attribute *attr,const char *buf,size_t count) +{ +struct ocfs2_sb_attr *oa = + container_of(attr, struct ocfs2_sb_attr, attr); + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +if (!oa->store) +return -EIO ; + +return oa->store (osb, oa, buf, count); +} + +static ssize_t slot_num_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return sprintf (buf,"%d\n" , osb->slot_num); +} + +static void sb_release (struct kobject *kobj) +{ + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +complete (&osb->kobj_unregister); +} + +static const struct sysfs_ops ocfs2_sb_sysfs_ops = { + .show = ocfs2_sb_attr_show, + .store = ocfs2_sb_attr_store, +}; + +static OCFS2_SB_ATTR_RO (slot_num); +static struct attribute *ocfs2_sb_attrs[] = { + &sb_attr_slot_num.attr, +NULL +}; + +static struct kobj_type ocfs2_sb_ktype = { + .sysfs_ops = &ocfs2_sb_sysfs_ops, + .default_attrs = ocfs2_sb_attrs, + .release = sb_release, +}; + + +int ocfs2_sysfs_sb_init (struct super_block *sb) +{ +int err; +struct ocfs2_super *osb =OCFS2_SB (sb); +init_completion (&osb->kobj_unregister); + osb->kobj.kset = ocfs2_kset; + err =kobject_init_and_add (&osb->kobj, &ocfs2_sb_ktype,NULL ,"%s" , sb->s_id); +return err; + +} + +void ocfs2_sysfs_sb_exit (struct super_block *sb) +{ +struct ocfs2_super *osb =OCFS2_SB (sb); +kobject_del (&osb->kobj); +kobject_put (&osb->kobj); +wait_for_completion (&osb->kobj_unregister); +} + +fs/ocfs2/sysfs.h new file +0
-0
Gang: please add header file comments like other header files.
Quoted 18 lines
fs/ocfs2/sysfs.h new file +9
-0@@ -0,0 +1,9 @@ + + +#ifndef _SYS_H +#define _SYS_H + +int ocfs2_sysfs_sb_init (struct super_block *sb); +void ocfs2_sysfs_sb_exit (struct super_block *sb); + +#endif Signature · 7 lines
2.6.6 _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel at oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/5 ocfs2: Provisions for sysfs entries
Quoted 8 lines · Gang He
Hello Goldwyn,
Thanks for your code, my comments are inline.
Quoted 3 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Quoted 8 lines
Quoted 1 line
This adds /sys/fs/ocfs2/<s_id> to the sys filesystem. This
Gang: My suggestion is to create a sysfs directory
device_nameunder/sys/fs/ocfs2per each file system, The file system generic attributes should be located under this top sub directory /sys/fs/ocfs2/<s_id>, but we should create a separate sub directory (e.g. filecheck) under this top sub directory for file check feature, then, all the file check related attributes should be located under that directory /sys/fs/ocfs2/<s_id>/filecheck. You know, in the future, we maybe add more attributes/sub directories under /sys/fs/ocfs2/<s_id>,
I should make sure the file check feature is not mixed with other things, it is easy to read/debug for the users/developers.
I don't think keeping it separate is important. We would need a separate kset for incorporating all of this. Besides, mulitple redirections will mess it up more than keep it simple. However, we should document what each portion is used for.
I don't see a point in using multiple structures when they would not be references at multiple points, at least in this case.
Quoted 190 lines
fs/ocfs2/sysfs.c
Quoted 97 lines
is done by adding the kobj into the
ocfs2_super. All other files are added in this directory.Introduce
ocfs2_sb_attrwhich encompasses thestore()andshow()functions. Move all the important data structures with respect to filechecks toocfs2_super.More superblock information should move in here.
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/Makefile | 3 +- fs/ocfs2/ocfs2.h | 4 +++ fs/ocfs2/super.c | 7 +++-- fs/ocfs2/sysfs.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/sysfs.h | 9 ++++++ 5 files changed, 111 insertions(+), 4 deletions(-)create mode 100644
fs/ocfs2/sysfs.c
create mode 100644fs/ocfs2/sysfs.hfs/ocfs2/Makefile +2
-1@@ -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.ofs/ocfs2/ocfs2.h +4
-0@@ -37,6 +37,7 @@#include <linux/mutex.h> #include <linux/lockdep.h> #include <linux/jbd2.h> +#include <linux/kobject.h> /* For union ocfs2_dlm_lksb */ #include "stackglue.h" @@ -472,6 +473,9 @@ struct ocfs2_super* workqueue and schedule on our own. */ struct workqueue_struct *ocfs2_wq; + +struct kobject kobj; +struct completion kobj_unregister; };#define OCFS2_SB (sb) ((struct ocfs2_super *)(sb)->s_fs_info)fs/ocfs2/super.c +4
-3@@ -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;@@ -1651,9 +1652,9 @@ static void ocfs2_put_super(struct super_block *sb) {trace_ocfs2_put_super (sb); +ocfs2_sysfs_sb_exit (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)fs/ocfs2/sysfs.c new file +0
-0Gang: please add source file comments like other source files.
Quoted 91 lines
fs/ocfs2/sysfs.c new file +90
-0@@ -0,0 +1,92 @@ +#include "ocfs2.h" +#include "sysfs.h" + +struct ocfs2_sb_attr { +struct attribute attr; +ssize_t (*show)(struct ocfs2_super *,struct ocfs2_sb_attr *, +char *buf); +ssize_t (*store)(struct ocfs2_super *,struct ocfs2_sb_attr *, +const char *buf,size_t count); +}; + +#define OCFS2_SB_ATTR (_name, _mode) \ +struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) + +#define OCFS2_SB_ATTR_RO (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name) + +static ssize_t ocfs2_sb_attr_show (struct kobject *kobj, +struct attribute *attr,char *buf) +{ +struct ocfs2_sb_attr *oa = + container_of(attr, struct ocfs2_sb_attr, attr); + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +if (!oa->show) +return -EIO ; + +return oa->show (osb, oa, buf); +} + +static ssize_t ocfs2_sb_attr_store (struct kobject *kobj, +struct attribute *attr,const char *buf,size_t count) +{ +struct ocfs2_sb_attr *oa = + container_of(attr, struct ocfs2_sb_attr, attr); + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +if (!oa->store) +return -EIO ; + +return oa->store (osb, oa, buf, count); +} + +static ssize_t slot_num_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return sprintf (buf,"%d\n" , osb->slot_num); +} + +static void sb_release (struct kobject *kobj) +{ + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +complete (&osb->kobj_unregister); +} + +static const struct sysfs_ops ocfs2_sb_sysfs_ops = { + .show = ocfs2_sb_attr_show, + .store = ocfs2_sb_attr_store, +}; + +static OCFS2_SB_ATTR_RO (slot_num); +static struct attribute *ocfs2_sb_attrs[] = { + &sb_attr_slot_num.attr, +NULL +}; + +static struct kobj_type ocfs2_sb_ktype = { + .sysfs_ops = &ocfs2_sb_sysfs_ops, + .default_attrs = ocfs2_sb_attrs, + .release = sb_release, +}; + + +int ocfs2_sysfs_sb_init (struct super_block *sb) +{ +int err; +struct ocfs2_super *osb =OCFS2_SB (sb); +init_completion (&osb->kobj_unregister); + osb->kobj.kset = ocfs2_kset; + err =kobject_init_and_add (&osb->kobj, &ocfs2_sb_ktype,NULL ,"%s" , sb->s_id); +return err; + +} + +void ocfs2_sysfs_sb_exit (struct super_block *sb) +{ +struct ocfs2_super *osb =OCFS2_SB (sb); +kobject_del (&osb->kobj); +kobject_put (&osb->kobj); +wait_for_completion (&osb->kobj_unregister); +}
Quoted 9 lines
fs/ocfs2/sysfs.h
Quoted 7 lines
fs/ocfs2/sysfs.c new file +2
-0+ +fs/ocfs2/sysfs.h new file +0
-0Gang: please add header file comments like other header files.
Agree.
Quoted 18 lines
Quoted 18 lines
fs/ocfs2/sysfs.h new file +9
-1@@ -0,0 +1,9 @@ + + +#ifndef _SYS_H +#define _SYS_H + +int ocfs2_sysfs_sb_init (struct super_block *sb); +void ocfs2_sysfs_sb_exit (struct super_block *sb); + +#endif --2.6.6
_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel at oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel
Signature · 1 line
Goldwyn
PATCH 1/5 ocfs2: Provisions for sysfs entries
Quoted 30 lines
Quoted 4 lines
Quoted 4 lines
Quoted 10 lines · Gang He
Hello Goldwyn,
Thanks for your code, my comments are inline.
Quoted 4 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
This adds /sys/fs/ocfs2/<s_id> to the sys filesystem. This
Gang: My suggestion is to create a sysfs directory
device_nameunder
/sys/fs/ocfs2per each file system,Quoted 1 line
The file system generic attributes should be located under this top sub
directory /sys/fs/ocfs2/<s_id>,
Quoted 1 line
but we should create a separate sub directory (e.g. filecheck) under this
top sub directory for file check feature,
Quoted 1 line
then, all the file check related attributes should be located under that
directory /sys/fs/ocfs2/<s_id>/filecheck.
Quoted 1 line
You know, in the future, we maybe add more attributes/sub directories under
/sys/fs/ocfs2/<s_id>,
Quoted 1 line
I should make sure the file check feature is not mixed with other things, it
is easy to read/debug for the users/developers.
Quoted 1 line
Quoted 7 lines
I don't think keeping it separate is important. We would need a separate kset for incorporating all of this. Besides, mulitple redirections will mess it up more than keep it simple. However, we should document what each portion is used for.
I don't see a point in using multiple structures when they would not be references at multiple points, at least in this case.
Gang: I prefer to use a separate sysfs directory for file check things, you know, maybe in the future
there will be more and more generic attributes under <device_name> sysfs directory for each file system. this will make the thing complicated, but actually the existing code have done like that, just re-use the code. But anyway, it is not too important for using/not using a separate sysfs directory for file check, I just worry about the future.
Quoted 225 lines
Quoted 192 lines
fs/ocfs2/sysfs.c
Quoted 99 lines
is done by adding the kobj into the
ocfs2_super. All other files are added in this directory.Introduce
ocfs2_sb_attrwhich encompasses thestore()andshow()functions. Move all the important data structures with respect to filechecks toocfs2_super.More superblock information should move in here.
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/Makefile | 3 +- fs/ocfs2/ocfs2.h | 4 +++ fs/ocfs2/super.c | 7 +++-- fs/ocfs2/sysfs.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/sysfs.h | 9 ++++++ 5 files changed, 111 insertions(+), 4 deletions(-)create mode 100644
fs/ocfs2/sysfs.c
create mode 100644fs/ocfs2/sysfs.hfs/ocfs2/Makefile +2
-1@@ -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.ofs/ocfs2/ocfs2.h +4
-0@@ -37,6 +37,7 @@#include <linux/mutex.h> #include <linux/lockdep.h> #include <linux/jbd2.h> +#include <linux/kobject.h> /* For union ocfs2_dlm_lksb */ #include "stackglue.h" @@ -472,6 +473,9 @@ struct ocfs2_super* workqueue and schedule on our own. */ struct workqueue_struct *ocfs2_wq; + +struct kobject kobj; +struct completion kobj_unregister; };#define OCFS2_SB (sb) ((struct ocfs2_super *)(sb)->s_fs_info)fs/ocfs2/super.c +4
-3@@ -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;@@ -1651,9 +1652,9 @@ static void ocfs2_put_super(struct super_block *sb) {trace_ocfs2_put_super (sb); +ocfs2_sysfs_sb_exit (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)fs/ocfs2/sysfs.c new file +0
-0Gang: please add source file comments like other source files.
Quoted 91 lines
fs/ocfs2/sysfs.c new file +90
-0@@ -0,0 +1,92 @@ +#include "ocfs2.h" +#include "sysfs.h" + +struct ocfs2_sb_attr { +struct attribute attr; +ssize_t (*show)(struct ocfs2_super *,struct ocfs2_sb_attr *, +char *buf); +ssize_t (*store)(struct ocfs2_super *,struct ocfs2_sb_attr *, +const char *buf,size_t count); +}; + +#define OCFS2_SB_ATTR (_name, _mode) \ +struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) + +#define OCFS2_SB_ATTR_RO (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name) + +static ssize_t ocfs2_sb_attr_show (struct kobject *kobj, +struct attribute *attr,char *buf) +{ +struct ocfs2_sb_attr *oa = + container_of(attr, struct ocfs2_sb_attr, attr); + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +if (!oa->show) +return -EIO ; + +return oa->show (osb, oa, buf); +} + +static ssize_t ocfs2_sb_attr_store (struct kobject *kobj, +struct attribute *attr,const char *buf,size_t count) +{ +struct ocfs2_sb_attr *oa = + container_of(attr, struct ocfs2_sb_attr, attr); + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +if (!oa->store) +return -EIO ; + +return oa->store (osb, oa, buf, count); +} + +static ssize_t slot_num_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return sprintf (buf,"%d\n" , osb->slot_num); +} + +static void sb_release (struct kobject *kobj) +{ + struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj); +complete (&osb->kobj_unregister); +} + +static const struct sysfs_ops ocfs2_sb_sysfs_ops = { + .show = ocfs2_sb_attr_show, + .store = ocfs2_sb_attr_store, +}; + +static OCFS2_SB_ATTR_RO (slot_num); +static struct attribute *ocfs2_sb_attrs[] = { + &sb_attr_slot_num.attr, +NULL +}; + +static struct kobj_type ocfs2_sb_ktype = { + .sysfs_ops = &ocfs2_sb_sysfs_ops, + .default_attrs = ocfs2_sb_attrs, + .release = sb_release, +}; + + +int ocfs2_sysfs_sb_init (struct super_block *sb) +{ +int err; +struct ocfs2_super *osb =OCFS2_SB (sb); +init_completion (&osb->kobj_unregister); + osb->kobj.kset = ocfs2_kset; + err =kobject_init_and_add (&osb->kobj, &ocfs2_sb_ktype,NULL ,"%s" , sb->s_id); +return err; + +} + +void ocfs2_sysfs_sb_exit (struct super_block *sb) +{ +struct ocfs2_super *osb =OCFS2_SB (sb); +kobject_del (&osb->kobj); +kobject_put (&osb->kobj); +wait_for_completion (&osb->kobj_unregister); +}Quoted 9 lines
fs/ocfs2/sysfs.h
Quoted 7 lines
fs/ocfs2/sysfs.c new file +2
-0+ +fs/ocfs2/sysfs.h new file +0
-0Gang: please add header file comments like other header files.
Agree.
Quoted 18 lines
Quoted 18 lines
fs/ocfs2/sysfs.h new file +9
-1@@ -0,0 +1,9 @@ + + +#ifndef _SYS_H +#define _SYS_H + +int ocfs2_sysfs_sb_init (struct super_block *sb); +void ocfs2_sysfs_sb_exit (struct super_block *sb); + +#endif --2.6.6
_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel at oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-develSignature · 1 line
Goldwyn
PATCH v2 2/5 Use the sysfs interface for creating filecheck files
In reply to Goldwyn RodriguesFrom: Goldwyn Rodrigues <[email protected]>
This reduces the code base and removes unnecessary data structures for filecheck information since all information is stored in ocfs2_super now.
--- fs/ocfs2/filecheck.c | 440 ++++++--------------------------------------------- fs/ocfs2/filecheck.h | 10 ++ fs/ocfs2/ocfs2.h | 7 + fs/ocfs2/super.c | 7 + fs/ocfs2/sysfs.c | 91 ++++++++++- 5 files changed, 161 insertions(+), 394 deletions(-)
fs/ocfs2/filecheck.c +48 -392
@@ -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; }
fs/ocfs2/filecheck.h +10 -0
@@ -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 */
fs/ocfs2/ocfs2.h +7 -0
@@ -474,6 +474,13 @@ struct ocfs2_super*/ 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; +struct kobject kobj;struct completion kobj_unregister; };
fs/ocfs2/super.c +7 -0
@@ -2215,6 +2215,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.
fs/ocfs2/sysfs.c +89 -2
116 lines not on this page · raw message
Signature · 1 line
2.6.6
PATCH 2/5 Use the sysfs interface for creating filecheck files
Hello Goldwyn,
Please see my comments inline.
I just suggest to re-use the existing code as most as possible, since the code was tested by us.
Thanks
Gang
Quoted 41 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
This reduces the code base and removes unnecessary data structures for filecheck information since all information is stored in
ocfs2_supernow.Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 440 ++++++--------------------------------------------- fs/ocfs2/filecheck.h | 10 ++ fs/ocfs2/ocfs2.h | 7 + fs/ocfs2/super.c | 7 + fs/ocfs2/sysfs.c | 91 ++++++++++- 5 files changed, 161 insertions(+), 394 deletions(-)fs/ocfs2/filecheck.c +0
-9@@ -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);
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 66
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-9-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 */ -};
Gang: we can reuse this structure, please move this structure into struct ocfs2_super, instead of defining a few members in struct ocfs2_super. We should use a separate structure to handle all the file check related thing, make the code simple and easy to maintain.
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 74
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-9- -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; -};
Gang: I think that we can not delete this structure directly, some members are still useful.
e.g. fs_count, which is used to track if there are any pending file check entries, can be moved into struct ocfs2_filecheck. kset members maybe be kept in struct ocfs2_filecheck.
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 77
Quoted 3 lines
fs/ocfs2/filecheck.c +0
-3- -#define OCFS2_FILECHECK_MAXSIZE 100 -#define OCFS2_FILECHECK_MINSIZE 10
Gang: any file will reference these two macro?
if not, that means these are not interfaces, should be kept in source file.
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 84
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7- -/* 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 */ -};
Gang: delete the member OCFS2_FILECHECK_TYPE_SET,
Move this enum to the header file if any other source file will use, otherwise should be kept in source file.
Quoted 62 lines
fs/ocfs2/filecheck.c +0
-1-struct ocfs2_filecheck_entry {struct list_head fe_list;fs/ocfs2/filecheck.c +0
-47unsigned 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);
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 161
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-10-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); -}
Gang: we cannot delete the function ocfs2_filecheck_sysfs_free() directly, this will be used to free the file check entries. Please keep the code, otherwise, it will lead to memory leak.
Quoted 39 lines
fs/ocfs2/filecheck.c +0
-39- -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);
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 210
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-10-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 ; -}
Gang: We can't delete these code directly, fs_count variable is used to track if there is any process to use file check related data. Please consider this variable before delete this part code.
Quoted 81 lines
fs/ocfs2/filecheck.c +0
-81-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);
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 302
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-10-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); -}
Gang: this part code can be re-used after a little modification.
Quoted 94 lines
fs/ocfs2/filecheck.c +12
-62-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 ;
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 394
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-9- args->fa_type = type; -if (type ==OCFS2_FILECHECK_TYPE_SET ) - args->fa_len = (unsigned int )val; -else - args->fa_ino = val; - -return 0 ; -} -
Gang: please keep the ocfs2_filecheck_args_parse function, or write a similar argument checking function since the arguments are from user-space, must be check strictly. Otherwise, this will be a way for malicious users to panic the kernel.
Quoted 5 lines
fs/ocfs2/filecheck.c +1
-2-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) {
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 408
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-7ssize_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);
Gang: if delete file check data reference count mechanism, how to make sure the resource race condition (e.g. list the check results during the file system umounting.) Please consider this race condition problem.
Quoted 220 lines
fs/ocfs2/filecheck.c +7
-23-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 ; }fs/ocfs2/filecheck.c +2
-2}@@ -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 fs/ocfs2/filecheck.c +6
-6break ;@@ -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);fs/ocfs2/filecheck.c +20
-45if (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; }fs/ocfs2/filecheck.h +0
-0
fs/ocfs2/filecheck.h enum { · line 50
Quoted 9 lines
fs/ocfs2/filecheck.h +6
-0@@ -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) */
Please use enum, not use macro definitions, maybe there will be more type. OCFS2_FILECHECK_TYPE_CHK should be zero, otherwise this macro is different with previous enum definitions.
Quoted 15 lines
fs/ocfs2/filecheck.h +4
-0int 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 */ fs/ocfs2/ocfs2.h +0
-0
fs/ocfs2/ocfs2.h struct ocfs2_super · line 483
Quoted 10 lines
fs/ocfs2/ocfs2.h +7
-0@@ -474,6 +474,13 @@ struct ocfs2_super*/ 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; +
Gang: please use a separate structure to include all the file check members, easy to read/maintain.
Quoted 9 lines
fs/ocfs2/ocfs2.h +0
-0struct kobject kobj;struct completion kobj_unregister; };fs/ocfs2/super.c +0
-0@@ -2215,6 +2215,13 @@ static int ocfs2_initialize_super(struct super_block *sb,
fs/ocfs2/super.c static int ocfs2_initialize_super(struct super_block · line 2225
Quoted 10 lines
fs/ocfs2/super.c +7
-0get_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); +
Gang: write a separate funtion in filecheck.c to include these line code, easy to read/maintain.
Quoted 90 lines
fs/ocfs2/super.c +0
-0/* FIXME * This should be done in ocfs2_journal_init(), but unknown fs/ocfs2/super.c +0
-0* ordering issues will cause the filesystem to crash. fs/ocfs2/sysfs.c +64
-2@@ -1,5 +1,6 @@#include "ocfs2.h" #include "sysfs.h" +#include "filecheck.h" struct ocfs2_sb_attr {struct attribute attr;@@ -9,8 +10,12 @@ struct ocfs2_sb_attr { const char *buf, size_t count); }; -#define OCFS2_SB_ATTR (_name, _mode) \ -struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) +#define OCFS2_SB_ATTR (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = (S_IWUSR | S_IRUGO)}, \ + .show = _name##_show, \ + .store = _name##_store \ +}#define OCFS2_SB_ATTR_RO (_name) \ struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name)@@ -46,6 +51,81 @@ static ssize_t slot_num_show(struct ocfs2_super *osb,return sprintf (buf,"%d\n" , osb->slot_num); } +static ssize_t file_check_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_CHK , buf); +} + +static ssize_t file_check_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_fix_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_FIX , buf); +} + +static ssize_t file_fix_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_check_max_entries_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +int len =0 ; +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;
fs/ocfs2/sysfs.c static ssize_t slot_num_show(struct ocfs2_super *osb, · line 120
Quoted 10 lines
fs/ocfs2/sysfs.c +10
-0+} + +static ssize_t file_check_max_entries_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr,const char *buf,size_t count) +{ + +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t);
Gang: please make sure the function kstrtoul does work well since the inputed buf has not terminating null character. This is why I write a wrapper function ocfs2_filecheck_args_get_long().
Quoted 16 lines
fs/ocfs2/sysfs.c +9
-0+if (ret) +return ret; + ret =ocfs2_filecheck_set_max_entries (osb, (int )t); +if (ret) +return ret; +return count; +} +static void sb_release (struct kobject *kobj) { struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj);@@ -58,8 +138,15 @@ static const struct sysfs_ops ocfs2_sb_sysfs_ops = { };static OCFS2_SB_ATTR_RO (slot_num); +static OCFS2_SB_ATTR (file_check);
fs/ocfs2/sysfs.c static const struct sysfs_ops ocfs2_sb_sysfs_ops = { · line 151
Quoted 10 lines
fs/ocfs2/sysfs.c +6
-0+static OCFS2_SB_ATTR (file_fix); +static OCFS2_SB_ATTR (file_check_max_entries); +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 };
Gang: as I said in the first patch, please make all the file check related attributes in a separate sub directory. It will let us to be easy to read/debug, especially if there is any reference count leaking problem.
Quoted 9 lines
Signature · 8 lines
-- 2.6.6 _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel at oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 2/5 Use the sysfs interface for creating filecheck files
Quoted 53 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
I just suggest to re-use the existing code as most as possible, since the code was tested by us.Thanks
GangQuoted 43 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
This reduces the code base and removes unnecessary data structures for filecheck information since all information is stored in
ocfs2_supernow.Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 440 ++++++--------------------------------------------- fs/ocfs2/filecheck.h | 10 ++ fs/ocfs2/ocfs2.h | 7 + fs/ocfs2/super.c | 7 + fs/ocfs2/sysfs.c | 91 ++++++++++- 5 files changed, 161 insertions(+), 394 deletions(-)fs/ocfs2/filecheck.c +0
-11@@ -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); -
Quoted 9 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 65
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-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 */ -};Gang: we can reuse this structure, please move this structure into struct
ocfs2_super, instead of defining a few members in structocfs2_super. We should use a separate structure to handle all the file check related thing, make the code simple and easy to maintain.
Not sure why you are insistent on keeping a separate structure when it would not be references from different structures. Keeping a prefix of fc will make sure it is for filecheck attributes.
Quoted 14 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 74
Quoted 11 lines
fs/ocfs2/filecheck.c +0
-9- -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; -};Gang: I think that we can not delete this structure directly, some members are still useful.
e.g.fs_count, which is used to track if there are any pending file check entries, can be moved into structocfs2_filecheck. kset members maybe be kept in structocfs2_filecheck.
Okay, I will fix that.
Quoted 6 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 77
Quoted 4 lines
fs/ocfs2/filecheck.c +0
-3- -#define OCFS2_FILECHECK_MAXSIZE 100 -#define OCFS2_FILECHECK_MINSIZE 10Gang: any file will reference these two macro?
if not, that means these are not interfaces, should be kept in source file.
Yes, they are referenced by multiple files.
Quoted 10 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 84
Quoted 8 lines
fs/ocfs2/filecheck.c +0
-7- -/* 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 */ -};Gang: delete the member
OCFS2_FILECHECK_TYPE_SET,
Move this enum to the header file if any other source file will use, otherwise should be kept in source file.
The idea of removing this structures was to simplify the code. More structures make more complicated code.
Quoted 67 lines
Quoted 67 lines
fs/ocfs2/filecheck.c +0
-52-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);
Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 161
Quoted 6 lines
fs/ocfs2/filecheck.c +0
-6- -kset_unregister (entry->fs_fcheckkset); -kset_unregister (entry->fs_devicekset); -kfree (entry->fs_fcheck); -kfree (entry); -}Gang: we cannot delete the function
ocfs2_filecheck_sysfs_free()directly, this will be used to free the file check entries. Please keep the code, otherwise, it will lead to memory leak.
Yes, there should a cleanup routine.
Quoted 138 lines
Quoted 40 lines
fs/ocfs2/filecheck.c +0
-39- -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);fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 210
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-10-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 ; -}Gang: We can't delete these code directly,
fs_countvariable is used to track if there is any process to use file check related data. Please consider this variable before delete this part code.Quoted 84 lines
fs/ocfs2/filecheck.c +0
-84-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);
Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 302
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-return ret; -} - -int ocfs2_filecheck_remove_sysfs (struct super_block *sb) -{ -return ocfs2_filecheck_sysfs_del (sb->s_id); -}Gang: this part code can be re-used after a little modification.
For what?
Quoted 96 lines
Quoted 96 lines
fs/ocfs2/filecheck.c +12
-62-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 ;
Quoted 11 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 394
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-9- args->fa_type = type; -if (type ==OCFS2_FILECHECK_TYPE_SET ) - args->fa_len = (unsigned int )val; -else - args->fa_ino = val; - -return 0 ; -} -Gang: please keep the
ocfs2_filecheck_args_parsefunction, or write a similar argument checking function since the arguments are from user-space, must be check strictly. Otherwise, this will be a way for malicious users to panic the kernel.
How? Do you have an example?
Quoted 7 lines
Quoted 7 lines
fs/ocfs2/filecheck.c +1
-2-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) {
Quoted 11 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 408
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-7ssize_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);Gang: if delete file check data reference count mechanism, how to make sure the resource race condition (e.g. list the check results during the file system umounting.) Please consider this race condition problem.
Isn't spinlock enough? What is the race?
Quoted 251 lines
Quoted 221 lines
fs/ocfs2/filecheck.c +7
-23-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 ; }}fs/ocfs2/filecheck.c +2
-2@@ -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;
fs/ocfs2/filecheck.c +6
-6@@ -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&&fs/ocfs2/filecheck.c +20
-45@@ -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; }fs/ocfs2/filecheck.h +0
-0fs/ocfs2/filecheck.h enum { · line 50
Quoted 9 lines
fs/ocfs2/filecheck.h +6
-0@@ -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) */ Please use enum, not use macro definitions, maybe there will be more type.
OCFS2_FILECHECK_TYPE_CHKshould be zero, otherwise this macro is different with previous enum definitions.Quoted 18 lines
fs/ocfs2/filecheck.h +4
-0int 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 */ fs/ocfs2/ocfs2.h +0
-0@@ -474,6 +474,13 @@ struct ocfs2_super*/ struct workqueue_struct *ocfs2_wq;
Quoted 8 lines
fs/ocfs2/ocfs2.h struct ocfs2_super · line 483
Quoted 7 lines
fs/ocfs2/ocfs2.h +7
-0+/* file check */ +struct list_head file_check_entries; +unsigned int fc_size; +unsigned int fc_max; +unsigned int fc_done; +spinlock_t fc_lock; +Gang: please use a separate structure to include all the file check members, easy to read/maintain.
I would prefer it to be a part of ocfs2_super. It is easier to maintain and read.
Quoted 13 lines
Quoted 13 lines
fs/ocfs2/ocfs2.h +0
-0struct kobject kobj;struct completion kobj_unregister; };fs/ocfs2/super.c +0
-0@@ -2215,6 +2215,13 @@ static int ocfs2_initialize_super(struct super_block *sb,get_random_bytes (&osb->s_next_generation,sizeof (u32));
Quoted 8 lines
fs/ocfs2/super.c static int ocfs2_initialize_super(struct super_block *sb, · line 2224
Quoted 7 lines
fs/ocfs2/super.c +7
-0+/* 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); +Gang: write a separate funtion in
filecheck.cto include these line code, easy to read/maintain.
Why? Unless we are starting something specific to filecheck, I don't see any need.
Quoted 95 lines
Quoted 95 lines
fs/ocfs2/super.c +0
-0/* FIXME * This should be done in ocfs2_journal_init(), but unknown * ordering issues will cause the filesystem to crash.
fs/ocfs2/sysfs.c +68
-2@@ -1,5 +1,6 @@#include "ocfs2.h" #include "sysfs.h" +#include "filecheck.h" struct ocfs2_sb_attr {struct attribute attr;@@ -9,8 +10,12 @@ struct ocfs2_sb_attr { const char *buf, size_t count); }; -#define OCFS2_SB_ATTR (_name, _mode) \ -struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) +#define OCFS2_SB_ATTR (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = (S_IWUSR | S_IRUGO)}, \ + .show = _name##_show, \ + .store = _name##_store \ +}#define OCFS2_SB_ATTR_RO (_name) \ struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name)@@ -46,6 +51,81 @@ static ssize_t slot_num_show(struct ocfs2_super *osb,return sprintf (buf,"%d\n" , osb->slot_num); } +static ssize_t file_check_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_CHK , buf); +} + +static ssize_t file_check_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_fix_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_FIX , buf); +} + +static ssize_t file_fix_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_check_max_entries_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +int len =0 ; +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 ocfs2_super *osb, +struct ocfs2_sb_attr *attr,const char *buf,size_t count)
Quoted 8 lines
fs/ocfs2/sysfs.c static ssize_t slot_num_show(struct ocfs2_super *osb, · line 68
Quoted 6 lines
fs/ocfs2/sysfs.c +6
-0+{ + +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t);Gang: please make sure the function kstrtoul does work well since the inputed buf has not terminating null character. This is why I write a wrapper function
ocfs2_filecheck_args_get_long().
Can you give an example on how this can be activated? Maybe a check on value < 0 may make sense.
Quoted 15 lines
Quoted 15 lines
fs/ocfs2/sysfs.c +8
-0+if (ret) +return ret; + ret =ocfs2_filecheck_set_max_entries (osb, (int )t); +if (ret) +return ret; +return count; +} +static void sb_release (struct kobject *kobj) { struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj);@@ -58,8 +138,15 @@ static const struct sysfs_ops ocfs2_sb_sysfs_ops = { };
Quoted 14 lines
fs/ocfs2/sysfs.c static const struct sysfs_ops ocfs2_sb_sysfs_ops = { · line 151
Quoted 12 lines
fs/ocfs2/sysfs.c +7
-0static OCFS2_SB_ATTR_RO (slot_num); +static OCFS2_SB_ATTR (file_check); +static OCFS2_SB_ATTR (file_fix); +static OCFS2_SB_ATTR (file_check_max_entries); +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 };Gang: as I said in the first patch, please make all the file check related attributes in a separate sub directory. It will let us to be easy to read/debug, especially if there is any reference count leaking problem.
The main reason of the code is to remove unnecessary data structures which is making the code hard to understand. I don't see a point in keeping them in a separate structure besides adding more indirections.
Signature · 1 line
Goldwyn
PATCH 2/5 Use the sysfs interface for creating filecheck files
Quoted 70 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
I just suggest to re-use the existing code as most as possible, since thecode was tested by us.
Quoted 15 lines
Thanks
GangQuoted 10 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
This reduces the code base and removes unnecessary data structures for filecheck information since all information is stored in
ocfs2_supernow.Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 440++++++---------------------------------------------
Quoted 34 lines
Quoted 33 lines
fs/ocfs2/filecheck.h | 10 ++ fs/ocfs2/ocfs2.h | 7 + fs/ocfs2/super.c | 7 + fs/ocfs2/sysfs.c | 91 ++++++++++- 5 files changed, 161 insertions(+), 394 deletions(-)fs/ocfs2/filecheck.c +0
-11@@ -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); -Quoted 8 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 65
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-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 */ -};Gang: we can reuse this structure, please move this structure into struct
Quoted 8 lines
ocfs2_super, instead of defining a few members in structocfs2_super.Quoted 1 line
We should use a separate structure to handle all the file check related
thing, make the code simple and easy to maintain.
Not sure why you are insistent on keeping a separate structure when it would not be references from different structures. Keeping a prefix of fc will make sure it is for filecheck attributes.
Gang: I just want to make the feature code more independent in other source files, define a separate data structure to make the file check code more easily read for the developer, and keep the code change more less in other source file. Actually, the existing struct ocfs2_filecheck can be re-used here.
Quoted 39 lines
Quoted 13 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 74
Quoted 12 lines
fs/ocfs2/filecheck.c +0
-9- -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; -};Gang: I think that we can not delete this structure directly, some members
are still useful.
Quoted 1 line
e.g.
fs_count, which is used to track if there are any pending file checkentries, can be moved into struct
ocfs2_filecheck.Quoted 1 line
kset members maybe be kept in struct
ocfs2_filecheck.Okay, I will fix that.
Quoted 6 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 77
Quoted 4 lines
fs/ocfs2/filecheck.c +0
-3- -#define OCFS2_FILECHECK_MAXSIZE 100 -#define OCFS2_FILECHECK_MINSIZE 10Gang: any file will reference these two macro?
if not, that means these are not interfaces, should be kept in source file.Yes, they are referenced by multiple files.
Quoted 10 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 84
Quoted 8 lines
fs/ocfs2/filecheck.c +0
-7- -/* 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 */ -};Gang: delete the member
OCFS2_FILECHECK_TYPE_SET,
Move this enum to the header file if any other source file will use,
Quoted 4 lines
otherwise should be kept in source file.
The idea of removing this structures was to simplify the code. More structures make more complicated code.
Gang: that is OK, but please define the OCFS2_FILECHECK_TYPE_CHK to 0, otherwise this replacing is not equivalent.
Quoted 228 lines
Quoted 67 lines
Quoted 67 lines
fs/ocfs2/filecheck.c +0
-51-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); - }Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 161
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-spin_unlock (&entry->fs_fcheck->fc_lock); - -kset_unregister (entry->fs_fcheckkset); -kset_unregister (entry->fs_devicekset); -kfree (entry->fs_fcheck); -kfree (entry); -}Gang: we cannot delete the function
ocfs2_filecheck_sysfs_free()directly,this will be used to free the file check entries.
Quoted 1 line
Please keep the code, otherwise, it will lead to memory leak.
Yes, there should a cleanup routine.
Quoted 43 lines
Quoted 43 lines
fs/ocfs2/filecheck.c +0
-42- -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);Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 210
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-spin_unlock (&ocfs2_filecheck_sysfs_lock); -return p; - } - } -spin_unlock (&ocfs2_filecheck_sysfs_lock); -return NULL ; -}Gang: We can't delete these code directly,
fs_countvariable is used totrack if there is any process to use file check related data.
Quoted 87 lines
Please consider this variable before delete this part code.
Quoted 84 lines
fs/ocfs2/filecheck.c +0
-84-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);Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 302
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-return ret; -} - -int ocfs2_filecheck_remove_sysfs (struct super_block *sb) -{ -return ocfs2_filecheck_sysfs_del (sb->s_id); -}Gang: this part code can be re-used after a little modification.
Quoted 1 line
For what?
Gang: this part code have a complete creating/releasing kset code, have been tested, it will not bring any memory leak.
Quoted 107 lines
Quoted 97 lines
Quoted 97 lines
fs/ocfs2/filecheck.c +12
-62-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 ;Quoted 10 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 394
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-9- args->fa_type = type; -if (type ==OCFS2_FILECHECK_TYPE_SET ) - args->fa_len = (unsigned int )val; -else - args->fa_ino = val; - -return 0 ; -} -Gang: please keep the
ocfs2_filecheck_args_parsefunction, or write a
Quoted 5 lines
similar argument checking function since the arguments are from user-space, must be check strictly.
Quoted 1 line
Otherwise, this will be a way for malicious users to panic the kernel.
How? Do you have an example?
Gang: for example, user input a too long number string, we should return a invalid error directly, not do the further file check operation. We need a ocfs2_filecheck_args_parse function, add some argument checking rules for now and future (when we find more limitations), return the error to the user process directly, to avoid bringing the further IO checking efforts.
Quoted 18 lines
Quoted 8 lines
Quoted 8 lines
fs/ocfs2/filecheck.c +1
-2-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) {Quoted 10 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 408
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-7ssize_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);Gang: if delete file check data reference count mechanism, how to make sure
Quoted 5 lines
the resource race condition (e.g. list the check results during the file system umounting.)
Quoted 1 line
Please consider this race condition problem.
Isn't spinlock enough? What is the race?
Gang: No, since file check operation is executed without spinlock, we need a reference count to keep the related data, until the last usage is finished.
Quoted 288 lines
Quoted 223 lines
Quoted 223 lines
fs/ocfs2/filecheck.c +7
-23-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 ; }}fs/ocfs2/filecheck.c +2
-2@@ -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;
fs/ocfs2/filecheck.c +6
-6@@ -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&&fs/ocfs2/filecheck.c +20
-45@@ -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; }fs/ocfs2/filecheck.h +0
-0@@ -42,8 +42,18 @@ enum {Quoted 10 lines
fs/ocfs2/filecheck.h enum { · line 50
Quoted 8 lines
fs/ocfs2/filecheck.h +6
-0#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) */ Please use enum, not use macro definitions, maybe there will be more type.
OCFS2_FILECHECK_TYPE_CHKshould be zero, otherwise this macro is differentwith previous enum definitions.
Quoted 19 lines
Quoted 19 lines
fs/ocfs2/filecheck.h +4
-0int 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 */ fs/ocfs2/ocfs2.h +0
-0@@ -474,6 +474,13 @@ struct ocfs2_super*/ struct workqueue_struct *ocfs2_wq;Quoted 8 lines
fs/ocfs2/ocfs2.h struct ocfs2_super · line 483
Quoted 7 lines
fs/ocfs2/ocfs2.h +7
-0+/* file check */ +struct list_head file_check_entries; +unsigned int fc_size; +unsigned int fc_max; +unsigned int fc_done; +spinlock_t fc_lock; +Gang: please use a separate structure to include all the file check members,
easy to read/maintain.
I would prefer it to be a part of
ocfs2_super. It is easier to maintain and read.Quoted 13 lines
Quoted 13 lines
fs/ocfs2/ocfs2.h +0
-0struct kobject kobj;struct completion kobj_unregister; };fs/ocfs2/super.c +0
-0@@ -2215,6 +2215,13 @@ static int ocfs2_initialize_super(struct super_block *sb,get_random_bytes (&osb->s_next_generation,sizeof (u32));Quoted 8 lines
fs/ocfs2/super.c static int ocfs2_initialize_super(struct super_block *sb, · line 2224
Quoted 7 lines
fs/ocfs2/super.c +7
-0+/* 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); +Gang: write a separate funtion in
filecheck.cto include these line code,
Quoted 4 lines
easy to read/maintain.
Why? Unless we are starting something specific to filecheck, I don't see any need.
Gang: I just want to make the file check thing is done in filecheck source file, the other module just call some functions. Let the code more clear.
Quoted 103 lines
Quoted 95 lines
Quoted 95 lines
fs/ocfs2/super.c +0
-0/* FIXME * This should be done in ocfs2_journal_init(), but unknown * ordering issues will cause the filesystem to crash.
fs/ocfs2/sysfs.c +67
-2@@ -1,5 +1,6 @@#include "ocfs2.h" #include "sysfs.h" +#include "filecheck.h" struct ocfs2_sb_attr {struct attribute attr;@@ -9,8 +10,12 @@ struct ocfs2_sb_attr { const char *buf, size_t count); }; -#define OCFS2_SB_ATTR (_name, _mode) \ -struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) +#define OCFS2_SB_ATTR (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = (S_IWUSR | S_IRUGO)}, \ + .show = _name##_show, \ + .store = _name##_store \ +}#define OCFS2_SB_ATTR_RO (_name) \ struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name)@@ -46,6 +51,81 @@ static ssize_t slot_num_show(struct ocfs2_super *osb,return sprintf (buf,"%d\n" , osb->slot_num); } +static ssize_t file_check_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_CHK , buf); +} + +static ssize_t file_check_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_fix_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_FIX , buf); +} + +static ssize_t file_fix_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_check_max_entries_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +int len =0 ; +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 ocfs2_super *osb,Quoted 8 lines
fs/ocfs2/sysfs.c static ssize_t slot_num_show(struct ocfs2_super *osb, · line 120
Quoted 7 lines
fs/ocfs2/sysfs.c +7
-0+ struct ocfs2_sb_attr *attr, const char *buf, size_t count) +{ + + unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t);Gang: please make sure the function kstrtoul does work well since the
Quoted 5 lines
inputed buf has not terminating null character.
Quoted 1 line
This is why I write a wrapper function
ocfs2_filecheck_args_get_long().Can you give an example on how this can be activated? Maybe a check on value < 0 may make sense.
Gang: I am not sure if this function works well when the string is inputed without a terminating null character. need to test all the case if using the function directly. But we test all the case with a terminating null character.
Quoted 40 lines
Quoted 16 lines
Quoted 16 lines
fs/ocfs2/sysfs.c +8
-0+if (ret) +return ret; + ret =ocfs2_filecheck_set_max_entries (osb, (int )t); +if (ret) +return ret; +return count; +} +static void sb_release (struct kobject *kobj) { struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj);@@ -58,8 +138,15 @@ static const struct sysfs_ops ocfs2_sb_sysfs_ops = { };Quoted 13 lines
fs/ocfs2/sysfs.c static const struct sysfs_ops ocfs2_sb_sysfs_ops = { · line 151
Quoted 12 lines
fs/ocfs2/sysfs.c +7
-0static OCFS2_SB_ATTR_RO (slot_num); +static OCFS2_SB_ATTR (file_check); +static OCFS2_SB_ATTR (file_fix); +static OCFS2_SB_ATTR (file_check_max_entries); +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 };Gang: as I said in the first patch, please make all the file check related
attributes in a separate sub directory.
Quoted 1 line
It will let us to be easy to read/debug, especially if there is any
reference count leaking problem.
The main reason of the code is to remove unnecessary data structures which is making the code hard to understand. I don't see a point in keeping them in a separate structure besides adding more indirections.
Signature · 1 line
Goldwyn
PATCH v2 2/5 Use the sysfs interface for creating filecheck files
Quoted 75 lines · Gang He
Quoted 75 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
I just suggest to re-use the existing code as most as possible, since thecode was tested by us.
Quoted 15 lines
Thanks
GangQuoted 10 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
This reduces the code base and removes unnecessary data structures for filecheck information since all information is stored in
ocfs2_supernow.Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 440++++++---------------------------------------------
Quoted 34 lines
Quoted 33 lines
fs/ocfs2/filecheck.h | 10 ++ fs/ocfs2/ocfs2.h | 7 + fs/ocfs2/super.c | 7 + fs/ocfs2/sysfs.c | 91 ++++++++++- 5 files changed, 161 insertions(+), 394 deletions(-)fs/ocfs2/filecheck.c +0
-11@@ -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); -Quoted 8 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 65
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-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 */ -};Gang: we can reuse this structure, please move this structure into struct
ocfs2_super, instead of defining a few members in structocfs2_super.Quoted 1 line
We should use a separate structure to handle all the file check related
thing, make the code simple and easy to maintain.
Quoted 6 lines
Quoted 3 lines
Not sure why you are insistent on keeping a separate structure when it would not be references from different structures. Keeping a prefix of fc will make sure it is for filecheck attributes.
Gang: I just want to make the feature code more independent in other source files, define a separate data structure to make the file check code more easily read for the developer, and keep the code change more less in other source file. Actually, the existing struct
ocfs2_filecheckcan be re-used here.
Yes, but it is just initialization of the fields. I understand if you are doing something more..
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 74
Quoted 12 lines
fs/ocfs2/filecheck.c +0
-9- -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; -};Gang: I think that we can not delete this structure directly, some members
Quoted 6 lines
Quoted 6 lines
are still useful.
Quoted 1 line
e.g.
fs_count, which is used to track if there are any pending file checkentries, can be moved into struct
ocfs2_filecheck.Quoted 1 line
kset members maybe be kept in struct
ocfs2_filecheck.Okay, I will fix that.
On second though, this may not be required.
Quoted 20 lines
Quoted 20 lines
Quoted 7 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 77
Quoted 5 lines
fs/ocfs2/filecheck.c +0
-3- -#define OCFS2_FILECHECK_MAXSIZE 100 -#define OCFS2_FILECHECK_MINSIZE 10Gang: any file will reference these two macro?
if not, that means these are not interfaces, should be kept in source file.Yes, they are referenced by multiple files.
Quoted 10 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 84
Quoted 8 lines
fs/ocfs2/filecheck.c +0
-7- -/* 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 */ -};Gang: delete the member
OCFS2_FILECHECK_TYPE_SET,
Move this enum to the header file if any other source file will use,
Quoted 6 lines
Quoted 4 lines
otherwise should be kept in source file.
The idea of removing this structures was to simplify the code. More structures make more complicated code.
Gang: that is OK, but please define the
OCFS2_FILECHECK_TYPE_CHKto 0, otherwise this replacing is not equivalent.
I am doing away with this in the future posts.
Quoted 367 lines
Quoted 228 lines
Quoted 67 lines
Quoted 67 lines
fs/ocfs2/filecheck.c +0
-51-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); - }Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 161
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-spin_unlock (&entry->fs_fcheck->fc_lock); - -kset_unregister (entry->fs_fcheckkset); -kset_unregister (entry->fs_devicekset); -kfree (entry->fs_fcheck); -kfree (entry); -}Gang: we cannot delete the function
ocfs2_filecheck_sysfs_free()directly,this will be used to free the file check entries.
Quoted 1 line
Please keep the code, otherwise, it will lead to memory leak.
Yes, there should a cleanup routine.
Quoted 43 lines
Quoted 43 lines
fs/ocfs2/filecheck.c +0
-42- -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);Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 210
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-spin_unlock (&ocfs2_filecheck_sysfs_lock); -return p; - } - } -spin_unlock (&ocfs2_filecheck_sysfs_lock); -return NULL ; -}Gang: We can't delete these code directly,
fs_countvariable is used totrack if there is any process to use file check related data.
Quoted 87 lines
Please consider this variable before delete this part code.
Quoted 84 lines
fs/ocfs2/filecheck.c +0
-84-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);Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 302
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-return ret; -} - -int ocfs2_filecheck_remove_sysfs (struct super_block *sb) -{ -return ocfs2_filecheck_sysfs_del (sb->s_id); -}Gang: this part code can be re-used after a little modification.
Quoted 1 line
For what?
Gang: this part code have a complete creating/releasing kset code, have been tested, it will not bring any memory leak.
Quoted 107 lines
Quoted 97 lines
Quoted 97 lines
fs/ocfs2/filecheck.c +12
-62-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 ;Quoted 10 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 394
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-9- args->fa_type = type; -if (type ==OCFS2_FILECHECK_TYPE_SET ) - args->fa_len = (unsigned int )val; -else - args->fa_ino = val; - -return 0 ; -} -Gang: please keep the
ocfs2_filecheck_args_parsefunction, or write aQuoted 5 lines
similar argument checking function since the arguments are from user-space, must be check strictly.
Quoted 1 line
Otherwise, this will be a way for malicious users to panic the kernel.
How? Do you have an example?
Gang: for example, user input a too long number string, we should return a invalid error directly, not do the further file check operation. We need a
ocfs2_filecheck_args_parsefunction, add some argument checking rules for now and future (when we find more limitations), return the error to the user process directly, to avoid bringing the further IO checking efforts.Quoted 20 lines
Quoted 8 lines
Quoted 8 lines
fs/ocfs2/filecheck.c +1
-2-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) {Quoted 10 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 408
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-7ssize_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);Gang: if delete file check data reference count mechanism, how to make sure
the resource race condition (e.g. list the check results during the file system umounting.)
Quoted 7 lines
Quoted 6 lines
Quoted 1 line
Please consider this race condition problem.
Isn't spinlock enough? What is the race?
Gang: No, since file check operation is executed without spinlock, we need a reference count to keep the related data, until the last usage is finished.
Filesystem unmonting is a different game. It evicts inodes. Could you clarify more?
Anyways, doing away with fe_done and using the status instead should help.
Quoted 399 lines
Quoted 289 lines
Quoted 224 lines
Quoted 224 lines
fs/ocfs2/filecheck.c +7
-23-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 ; }}fs/ocfs2/filecheck.c +2
-2@@ -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;fs/ocfs2/filecheck.c +6
-6@@ -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 &&fs/ocfs2/filecheck.c +20
-45@@ -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; }fs/ocfs2/filecheck.h +0
-0@@ -42,8 +42,18 @@ enum {Quoted 10 lines
fs/ocfs2/filecheck.h enum { · line 50
Quoted 8 lines
fs/ocfs2/filecheck.h +6
-0#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) */ Please use enum, not use macro definitions, maybe there will be more type.
OCFS2_FILECHECK_TYPE_CHKshould be zero, otherwise this macro is differentwith previous enum definitions.
Quoted 19 lines
Quoted 19 lines
fs/ocfs2/filecheck.h +4
-0int 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 */ fs/ocfs2/ocfs2.h +0
-0@@ -474,6 +474,13 @@ struct ocfs2_super*/ struct workqueue_struct *ocfs2_wq;Quoted 8 lines
fs/ocfs2/ocfs2.h struct ocfs2_super · line 483
Quoted 7 lines
fs/ocfs2/ocfs2.h +7
-0+/* file check */ +struct list_head file_check_entries; +unsigned int fc_size; +unsigned int fc_max; +unsigned int fc_done; +spinlock_t fc_lock; +Gang: please use a separate structure to include all the file check members,
easy to read/maintain.
I would prefer it to be a part of
ocfs2_super. It is easier to maintain and read.Quoted 13 lines
Quoted 13 lines
fs/ocfs2/ocfs2.h +0
-0struct kobject kobj;struct completion kobj_unregister; };fs/ocfs2/super.c +0
-0@@ -2215,6 +2215,13 @@ static int ocfs2_initialize_super(struct super_block *sb,get_random_bytes (&osb->s_next_generation,sizeof (u32));Quoted 8 lines
fs/ocfs2/super.c static int ocfs2_initialize_super(struct super_block *sb, · line 2224
Quoted 7 lines
fs/ocfs2/super.c +7
-0+/* 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); +Gang: write a separate funtion in
filecheck.cto include these line code,Quoted 4 lines
easy to read/maintain.
Why? Unless we are starting something specific to filecheck, I don't see any need.
Gang: I just want to make the file check thing is done in filecheck source file, the other module just call some functions. Let the code more clear.
Quoted 103 lines
Quoted 103 lines
Quoted 92 lines
fs/ocfs2/super.c +0
-0/* FIXME * This should be done in ocfs2_journal_init(), but unknown * ordering issues will cause the filesystem to crash.
fs/ocfs2/sysfs.c +64
-2@@ -1,5 +1,6 @@#include "ocfs2.h" #include "sysfs.h" +#include "filecheck.h" struct ocfs2_sb_attr {struct attribute attr;@@ -9,8 +10,12 @@ struct ocfs2_sb_attr { const char *buf, size_t count); }; -#define OCFS2_SB_ATTR (_name, _mode) \ -struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) +#define OCFS2_SB_ATTR (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = (S_IWUSR | S_IRUGO)}, \ + .show = _name##_show, \ + .store = _name##_store \ +}#define OCFS2_SB_ATTR_RO (_name) \ struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name)@@ -46,6 +51,81 @@ static ssize_t slot_num_show(struct ocfs2_super *osb,return sprintf (buf,"%d\n" , osb->slot_num); } +static ssize_t file_check_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_CHK , buf); +} + +static ssize_t file_check_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_fix_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_FIX , buf); +} + +static ssize_t file_fix_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_check_max_entries_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +int len =0 ; +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;fs/ocfs2/sysfs.c static ssize_t slot_num_show(struct ocfs2_super *osb, · line 120
Quoted 10 lines
fs/ocfs2/sysfs.c +10
-0+} + +static ssize_t file_check_max_entries_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr,const char *buf,size_t count) +{ + +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t);Gang: please make sure the function kstrtoul does work well since the
Quoted 8 lines
Quoted 5 lines
inputed buf has not terminating null character.
Quoted 1 line
This is why I write a wrapper function
ocfs2_filecheck_args_get_long().Can you give an example on how this can be activated? Maybe a check on value < 0 may make sense.
Gang: I am not sure if this function works well when the string is inputed without a terminating null character. need to test all the case if using the function directly. But we test all the case with a terminating null character.
So, do you have a testcase?
Quoted 41 lines
Quoted 41 lines
Quoted 17 lines
Quoted 17 lines
fs/ocfs2/sysfs.c +8
-0+if (ret) +return ret; + ret =ocfs2_filecheck_set_max_entries (osb, (int )t); +if (ret) +return ret; +return count; +} +static void sb_release (struct kobject *kobj) { struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj);@@ -58,8 +138,15 @@ static const struct sysfs_ops ocfs2_sb_sysfs_ops = { };Quoted 13 lines
fs/ocfs2/sysfs.c static const struct sysfs_ops ocfs2_sb_sysfs_ops = { · line 151
Quoted 12 lines
fs/ocfs2/sysfs.c +7
-0static OCFS2_SB_ATTR_RO (slot_num); +static OCFS2_SB_ATTR (file_check); +static OCFS2_SB_ATTR (file_fix); +static OCFS2_SB_ATTR (file_check_max_entries); +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 };Gang: as I said in the first patch, please make all the file check related
attributes in a separate sub directory.
Quoted 1 line
It will let us to be easy to read/debug, especially if there is any
reference count leaking problem.
The main reason of the code is to remove unnecessary data structures which is making the code hard to understand. I don't see a point in keeping them in a separate structure besides adding more indirections.
--
Goldwyn
Signature · 1 line
Goldwyn
PATCH 2/5 Use the sysfs interface for creating filecheck files
Quoted 107 lines
Quoted 4 lines
Quoted 4 lines
Quoted 71 lines · Gang He
Quoted 71 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
I just suggest to re-use the existing code as most as possible, since thecode was tested by us.
Quoted 15 lines
Thanks
GangQuoted 10 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
This reduces the code base and removes unnecessary data structures for filecheck information since all information is stored in
ocfs2_supernow.Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 440++++++---------------------------------------------
Quoted 34 lines
Quoted 33 lines
fs/ocfs2/filecheck.h | 10 ++ fs/ocfs2/ocfs2.h | 7 + fs/ocfs2/super.c | 7 + fs/ocfs2/sysfs.c | 91 ++++++++++- 5 files changed, 161 insertions(+), 394 deletions(-)fs/ocfs2/filecheck.c +0
-11@@ -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); -Quoted 8 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 65
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-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 */ -};Gang: we can reuse this structure, please move this structure into struct
ocfs2_super, instead of defining a few members in structocfs2_super.Quoted 8 lines
Quoted 7 lines
Quoted 1 line
We should use a separate structure to handle all the file check related
thing, make the code simple and easy to maintain.
Not sure why you are insistent on keeping a separate structure when it would not be references from different structures. Keeping a prefix of fc will make sure it is for filecheck attributes.
Gang: I just want to make the feature code more independent in other source
files, define a separate data structure to
Quoted 1 line
make the file check code more easily read for the developer, and keep the
code change more less in other source file.
Quoted 1 line
Actually, the existing struct
ocfs2_filecheckcan be re-used here.Yes, but it is just initialization of the fields. I understand if you are doing something more..
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 74
Quoted 12 lines
fs/ocfs2/filecheck.c +0
-9- -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; -};Gang: I think that we can not delete this structure directly, some members
Quoted 8 lines
Quoted 6 lines
Quoted 6 lines
are still useful.
Quoted 1 line
e.g.
fs_count, which is used to track if there are any pending file checkentries, can be moved into struct
ocfs2_filecheck.Quoted 1 line
kset members maybe be kept in struct
ocfs2_filecheck.Okay, I will fix that.
On second though, this may not be required.
Gang: This should need a reference count to track if the related data is still needed by others before we delete in the umount stage. You know, file check entry operation is running in the kernel without holding the list spin_lock (actually can not hold), if we try to release the list during umounting, how to make sure all the filecheck IO operation is done?
Quoted 409 lines
Quoted 22 lines
Quoted 22 lines
Quoted 9 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 77
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-3- -#define OCFS2_FILECHECK_MAXSIZE 100 -#define OCFS2_FILECHECK_MINSIZE 10Gang: any file will reference these two macro?
if not, that means these are not interfaces, should be kept in source file.Yes, they are referenced by multiple files.
Quoted 10 lines
fs/ocfs2/filecheck.c static const char * const ocfs2_filecheck_errs[] = { · line 84
Quoted 8 lines
fs/ocfs2/filecheck.c +0
-7- -/* 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 */ -};Gang: delete the member
OCFS2_FILECHECK_TYPE_SET,
Move this enum to the header file if any other source file will use,Quoted 5 lines
Quoted 4 lines
otherwise should be kept in source file.
The idea of removing this structures was to simplify the code. More structures make more complicated code.
Gang: that is OK, but please define the
OCFS2_FILECHECK_TYPE_CHKto 0,otherwise this replacing is not equivalent.
Quoted 1 line
I am doing away with this in the future posts.
Quoted 228 lines
Quoted 228 lines
Quoted 67 lines
Quoted 67 lines
fs/ocfs2/filecheck.c +0
-51-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); - }Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 161
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-spin_unlock (&entry->fs_fcheck->fc_lock); - -kset_unregister (entry->fs_fcheckkset); -kset_unregister (entry->fs_devicekset); -kfree (entry->fs_fcheck); -kfree (entry); -}Gang: we cannot delete the function
ocfs2_filecheck_sysfs_free()directly,this will be used to free the file check entries.
Quoted 1 line
Please keep the code, otherwise, it will lead to memory leak.
Yes, there should a cleanup routine.
Quoted 43 lines
Quoted 43 lines
fs/ocfs2/filecheck.c +0
-42- -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);Quoted 8 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 210
Quoted 7 lines
fs/ocfs2/filecheck.c +0
-7-spin_unlock (&ocfs2_filecheck_sysfs_lock); -return p; - } - } -spin_unlock (&ocfs2_filecheck_sysfs_lock); -return NULL ; -}Gang: We can't delete these code directly,
fs_countvariable is used totrack if there is any process to use file check related data.
Quoted 95 lines
Please consider this variable before delete this part code.
Quoted 81 lines
fs/ocfs2/filecheck.c +0
-81-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);fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 302
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-10-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); -}Gang: this part code can be re-used after a little modification.
Quoted 2 lines
Quoted 1 line
For what?
Gang: this part code have a complete creating/releasing kset code, have been
tested, it will not bring any memory leak.
Quoted 108 lines
Quoted 108 lines
Quoted 108 lines
Quoted 97 lines
fs/ocfs2/filecheck.c +12
-62-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 ;fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 394
Quoted 10 lines
fs/ocfs2/filecheck.c +0
-9- args->fa_type = type; -if (type ==OCFS2_FILECHECK_TYPE_SET ) - args->fa_len = (unsigned int )val; -else - args->fa_ino = val; - -return 0 ; -} -Gang: please keep the
ocfs2_filecheck_args_parsefunction, or write aQuoted 6 lines
Quoted 5 lines
similar argument checking function since the arguments are from user-space, must be check strictly.
Quoted 1 line
Otherwise, this will be a way for malicious users to panic the kernel.
How? Do you have an example?
Gang: for example, user input a too long number string, we should return a
invalid error directly, not do the further file check operation.
Quoted 1 line
We need a
ocfs2_filecheck_args_parsefunction, add some argument checkingrules for now and future (when we find more limitations),
Quoted 1 line
return the error to the user process directly, to avoid bringing the further
IO checking efforts.
Quoted 27 lines
Quoted 27 lines
Quoted 9 lines
Quoted 9 lines
fs/ocfs2/filecheck.c +1
-2-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) {Quoted 10 lines
fs/ocfs2/filecheck.c ocfs2_filecheck_error(int errno) · line 408
Quoted 9 lines
fs/ocfs2/filecheck.c +0
-7ssize_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);Gang: if delete file check data reference count mechanism, how to make sure
the resource race condition (e.g. list the check results during the file system umounting.)
Quoted 1 line
Please consider this race condition problem.
Isn't spinlock enough? What is the race?
Quoted 8 lines
Quoted 1 line
Gang: No, since file check operation is executed without spinlock, we need a
reference count to keep the related data, until the last usage is finished.
Filesystem unmonting is a different game. It evicts inodes. Could you clarify more?
Anyways, doing away with
fe_doneand using the status instead should help.
Gang: the file check entry is on behalf of one file check user trigger, is not related with inode object in the kernel. When we get to handle one inode object, we need to follow all the locks of inode.
Quoted 406 lines
Quoted 290 lines
Quoted 290 lines
Quoted 225 lines
Quoted 225 lines
fs/ocfs2/filecheck.c +7
-23-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 ; }}fs/ocfs2/filecheck.c +2
-2@@ -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;fs/ocfs2/filecheck.c +6
-6@@ -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 &&fs/ocfs2/filecheck.c +20
-45@@ -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; }fs/ocfs2/filecheck.h +0
-0@@ -42,8 +42,18 @@ enum {Quoted 10 lines
fs/ocfs2/filecheck.h enum { · line 50
Quoted 8 lines
fs/ocfs2/filecheck.h +6
-0#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) */ Please use enum, not use macro definitions, maybe there will be more type.
OCFS2_FILECHECK_TYPE_CHKshould be zero, otherwise this macro is differentwith previous enum definitions.
Quoted 19 lines
Quoted 19 lines
fs/ocfs2/filecheck.h +4
-0int 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 */ fs/ocfs2/ocfs2.h +0
-0@@ -474,6 +474,13 @@ struct ocfs2_super*/ struct workqueue_struct *ocfs2_wq;Quoted 8 lines
fs/ocfs2/ocfs2.h struct ocfs2_super · line 483
Quoted 7 lines
fs/ocfs2/ocfs2.h +7
-0+/* file check */ +struct list_head file_check_entries; +unsigned int fc_size; +unsigned int fc_max; +unsigned int fc_done; +spinlock_t fc_lock; +Gang: please use a separate structure to include all the file check members,
easy to read/maintain.
I would prefer it to be a part of
ocfs2_super. It is easier to maintain and read.Quoted 21 lines
Quoted 10 lines
fs/ocfs2/ocfs2.h +0
-0struct kobject kobj;struct completion kobj_unregister; };fs/ocfs2/super.c +0
-0@@ -2215,6 +2215,13 @@ static int ocfs2_initialize_super(struct super_block *sb,fs/ocfs2/super.c static int ocfs2_initialize_super(struct super_block · line 2225
Quoted 10 lines
fs/ocfs2/super.c +7
-0get_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); +Gang: write a separate funtion in
filecheck.cto include these line code,Quoted 5 lines
Quoted 4 lines
easy to read/maintain.
Why? Unless we are starting something specific to filecheck, I don't see any need.
Gang: I just want to make the file check thing is done in filecheck source
file, the other module just call some functions.
Quoted 110 lines
Let the code more clear.
Quoted 108 lines
Quoted 95 lines
Quoted 95 lines
fs/ocfs2/super.c +0
-0/* FIXME * This should be done in ocfs2_journal_init(), but unknown * ordering issues will cause the filesystem to crash.
fs/ocfs2/sysfs.c +67
-2@@ -1,5 +1,6 @@#include "ocfs2.h" #include "sysfs.h" +#include "filecheck.h" struct ocfs2_sb_attr {struct attribute attr;@@ -9,8 +10,12 @@ struct ocfs2_sb_attr { const char *buf, size_t count); }; -#define OCFS2_SB_ATTR (_name, _mode) \ -struct ocfs2_sb_attr sb_attr_##_name = __ATTR(name, _mode, _show, _store) +#define OCFS2_SB_ATTR (_name) \ +struct ocfs2_sb_attr sb_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = (S_IWUSR | S_IRUGO)}, \ + .show = _name##_show, \ + .store = _name##_store \ +}#define OCFS2_SB_ATTR_RO (_name) \ struct ocfs2_sb_attr sb_attr_##_name = __ATTR_RO(_name)@@ -46,6 +51,81 @@ static ssize_t slot_num_show(struct ocfs2_super *osb,return sprintf (buf,"%d\n" , osb->slot_num); } +static ssize_t file_check_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_CHK , buf); +} + +static ssize_t file_check_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_fix_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +return ocfs2_filecheck_show (osb,OCFS2_FILECHECK_TYPE_FIX , buf); +} + +static ssize_t file_fix_store (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +const char *buf,size_t count) +{ +unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t); +if (ret) +return ret; + ret =ocfs2_filecheck_add_inode (osb, t); +if (ret) +return ret; +return count; +} + +static ssize_t file_check_max_entries_show (struct ocfs2_super *osb, +struct ocfs2_sb_attr *attr, +char *buf) +{ +int len =0 ; +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 ocfs2_super *osb,Quoted 8 lines
fs/ocfs2/sysfs.c static ssize_t slot_num_show(struct ocfs2_super *osb, · line 120
Quoted 7 lines
fs/ocfs2/sysfs.c +7
-0+ struct ocfs2_sb_attr *attr, const char *buf, size_t count) +{ + + unsigned long t; +int ret; + + ret =kstrtoul (skip_spaces (buf),0 , &t);Gang: please make sure the function kstrtoul does work well since the
inputed buf has not terminating null character.
Quoted 1 line
This is why I write a wrapper function
ocfs2_filecheck_args_get_long().Can you give an example on how this can be activated? Maybe a check on value < 0 may make sense.
Quoted 7 lines
Quoted 1 line
Gang: I am not sure if this function works well when the string is inputed
without a terminating null character.
Quoted 1 line
need to test all the case if using the function directly. But we test all
the case with a terminating null character.
Quoted 1 line
So, do you have a testcase?
Gang: Eric tested this manually in various possible cases, not sure if he wrote these cases in the scripts.
Quoted 45 lines
Quoted 42 lines
Quoted 42 lines
Quoted 18 lines
Quoted 18 lines
fs/ocfs2/sysfs.c +8
-0+if (ret) +return ret; + ret =ocfs2_filecheck_set_max_entries (osb, (int )t); +if (ret) +return ret; +return count; +} +static void sb_release (struct kobject *kobj) { struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj);@@ -58,8 +138,15 @@ static const struct sysfs_ops ocfs2_sb_sysfs_ops = { };Quoted 13 lines
fs/ocfs2/sysfs.c static const struct sysfs_ops ocfs2_sb_sysfs_ops = { · line 151
Quoted 12 lines
fs/ocfs2/sysfs.c +7
-0static OCFS2_SB_ATTR_RO (slot_num); +static OCFS2_SB_ATTR (file_check); +static OCFS2_SB_ATTR (file_fix); +static OCFS2_SB_ATTR (file_check_max_entries); +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 };Gang: as I said in the first patch, please make all the file check related
attributes in a separate sub directory.
Quoted 1 line
It will let us to be easy to read/debug, especially if there is any
reference count leaking problem.
The main reason of the code is to remove unnecessary data structures which is making the code hard to understand. I don't see a point in keeping them in a separate structure besides adding more indirections.
--
GoldwynSignature · 1 line
Goldwyn
PATCH v2 3/5 Generate uevents for errors
In reply to Goldwyn RodriguesFrom: Goldwyn Rodrigues <[email protected]>
--- fs/ocfs2/inode.c | 13 +++++++++++++ fs/ocfs2/sysfs.c | 17 +++++++++++++++++ fs/ocfs2/sysfs.h | 2 ++ 3 files changed, 32 insertions(+)
fs/ocfs2/inode.c +13 -0
@@ -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; }
fs/ocfs2/sysfs.c +17 -0
@@ -126,6 +126,23 @@ static ssize_t file_check_max_entries_store(struct ocfs2_super *osb,return count; } +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); +kobject_uevent_env (&osb->kobj,KOBJ_CHANGE , envp); +} +static void sb_release (struct kobject *kobj) { struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj);
fs/ocfs2/sysfs.h +2 -0
@@ -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);void ocfs2_sysfs_sb_exit (struct super_block *sb);
Signature · 1 line
2.6.6
PATCH 3/5 Generate uevents for errors
Looks good for me.
Thanks
Gang
Quoted 112 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/inode.c | 13 +++++++++++++ fs/ocfs2/sysfs.c | 17 +++++++++++++++++ fs/ocfs2/sysfs.h | 2 ++ 3 files changed, 32 insertions(+)fs/ocfs2/inode.c +13
-0@@ -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; }fs/ocfs2/sysfs.c +17
-0@@ -126,6 +126,23 @@ static ssize_t file_check_max_entries_store(structocfs2_super *osb, return count; } +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); +kobject_uevent_env (&osb->kobj,KOBJ_CHANGE , envp); +} +static void sb_release (struct kobject *kobj) {fs/ocfs2/sysfs.c +0
-0struct ocfs2_super *osb = container_of(kobj, struct ocfs2_super, kobj);fs/ocfs2/sysfs.h +2
-0@@ -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);void ocfs2_sysfs_sb_exit (struct super_block *sb);Signature · 7 lines
2.6.6 _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel at oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel
PATCH v2 4/5 ocfs2: Disallow duplicate entries in the list
In reply to Goldwyn RodriguesFrom: Goldwyn Rodrigues <[email protected]>
--- fs/ocfs2/filecheck.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
fs/ocfs2/filecheck.c +17 -9
@@ -217,14 +217,12 @@ ocfs2_filecheck_handle_entry(struct ocfs2_super *osb,int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) { -struct ocfs2_filecheck_entry *entry; +struct ocfs2_filecheck_entry *entry, *p;ssize_t ret =0 ; entry =kmalloc (sizeof (struct ocfs2_filecheck_entry ),GFP_NOFS ); -if (!entry) { - ret = -ENOMEM ; - goto exit; - } +if (!entry) +return -ENOMEM ;spin_lock (&osb->fc_lock); if ((osb->fc_size >= osb->fc_max) &&
@@ -244,6 +242,12 @@ int ocfs2_filecheck_add_inode(struct ocfs2_super *osb,*/ BUG_ON (!ocfs2_filecheck_erase_entry (osb)); } +list_for_each_entry (p, &osb->file_check_entries, fe_list) +if (p->fe_ino == ino) { + ret = -EEXIST ; +kfree (entry); + goto unlock; + } entry->fe_ino = ino; entry->fe_type =OCFS2_FILECHECK_TYPE_CHK ;
@@ -252,11 +256,15 @@ int ocfs2_filecheck_add_inode(struct ocfs2_super *osb,list_add_tail (&entry->fe_list, &osb->file_check_entries); osb->fc_size++; } +unlock:spin_unlock (&osb->fc_lock); -if (!ret) -ocfs2_filecheck_handle_entry (osb, entry); +if (ret) +return ret; -exit: -return ret; + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; }
Signature · 1 line
2.6.6
PATCH 4/5 ocfs2: Disallow duplicate entries in the list
Looks good to me.
Thanks
Gang
Quoted 71 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)fs/ocfs2/filecheck.c +17
-9@@ -217,14 +217,12 @@ ocfs2_filecheck_handle_entry(struct ocfs2_super *osb,int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) { -struct ocfs2_filecheck_entry *entry; +struct ocfs2_filecheck_entry *entry, *p;ssize_t ret =0 ; entry =kmalloc (sizeof (struct ocfs2_filecheck_entry ),GFP_NOFS ); -if (!entry) { - ret = -ENOMEM ; - goto exit; - } +if (!entry) +return -ENOMEM ;spin_lock (&osb->fc_lock); if ((osb->fc_size >= osb->fc_max) &&@@ -244,6 +242,12 @@ int ocfs2_filecheck_add_inode(struct ocfs2_super *osb,*/ BUG_ON (!ocfs2_filecheck_erase_entry (osb)); } +list_for_each_entry (p, &osb->file_check_entries, fe_list) +if (p->fe_ino == ino) { + ret = -EEXIST ; +kfree (entry); + goto unlock; + } entry->fe_ino = ino; entry->fe_type =OCFS2_FILECHECK_TYPE_CHK ;@@ -252,11 +256,15 @@ int ocfs2_filecheck_add_inode(struct ocfs2_super *osb,list_add_tail (&entry->fe_list, &osb->file_check_entries); osb->fc_size++; } +unlock:spin_unlock (&osb->fc_lock); -if (!ret) -ocfs2_filecheck_handle_entry (osb, entry); +if (ret) +return ret; -exit: -return ret; + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; }Signature · 7 lines
2.6.6 _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel at oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel
PATCH v2 5/5 Fix files when an inode is written in file_fix
In reply to Goldwyn RodriguesFrom: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)
fs/ocfs2/filecheck.c +25 -16
@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {
@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{ +struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ; + ret =0 ; +break ; + } +spin_unlock (&osb->fc_lock); +if (ret) +return ret; + + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_FIX ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; +} +
fs/ocfs2/filecheck.h +1 -0
@@ -53,6 +53,7 @@ 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_filefix_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);
fs/ocfs2/sysfs.c +1 -1
@@ -91,7 +91,7 @@ static ssize_t file_fix_store(struct ocfs2_super *osb, ret =kstrtoul (skip_spaces (buf),0 , &t);if (ret)return ret; - ret =ocfs2_filecheck_add_inode (osb, t); + ret =ocfs2_filefix_add_inode (osb, t);if (ret)return ret;return count;
Signature · 1 line
2.6.6
PATCH 5/5 Fix files when an inode is written in file_fix
Hello Goldwyn,
Please see my comments inline.
Thanks
Gang
Quoted 45 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +1
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } +
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 10 lines
fs/ocfs2/filecheck.c +10
-0+int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{ +struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;
Gang: It looks that we can not do it directly, why? because the entry pointer can be freed by the function ocfs2_filecheck_erase_entries().
We can not use the same entry pointer within two user processes.
The simple solution is to return -EBUSY error in case there is the same ino number entry in the list, then the user can try again after the previous user process is returned.
Quoted 48 lines
fs/ocfs2/filecheck.c +14
-0+ ret =0 ; +break ; + } +spin_unlock (&osb->fc_lock); +if (ret) +return ret; + + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_FIX ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; +} +fs/ocfs2/filecheck.h +1
-0@@ -53,6 +53,7 @@ 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_filefix_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);fs/ocfs2/sysfs.c +1
-1@@ -91,7 +91,7 @@ static ssize_t file_fix_store(struct ocfs2_super *osb, ret =kstrtoul (skip_spaces (buf),0 , &t);if (ret)return ret; - ret =ocfs2_filecheck_add_inode (osb, t); + ret =ocfs2_filefix_add_inode (osb, t);if (ret)return ret;return count;Signature · 7 lines
2.6.6 _______________________________________________ Ocfs2-devel mailing list Ocfs2-devel at oss.oracle.com https://oss.oracle.com/mailman/listinfo/ocfs2-devel
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 5/5 Fix files when an inode is written in file_fix
Quoted 59 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 50 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +6
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{ +struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ;
Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 5 lines
fs/ocfs2/filecheck.c +5
-0+ +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry pointer can be freed by the function
ocfs2_filecheck_erase_entries().
We can not use the same entry pointer within two user processes.
The simple solution is to return-EBUSYerror in case there is the same ino number entry in the list, then the user can try again after the previous user process is returned.
How? is it not protected under spinlock?
Anyways, I plan to make a separate list for this so we can do away with more macros.
Besides, any I/O and check operation should be done in a separate thread/work queue.
Quoted 49 lines
Quoted 49 lines
fs/ocfs2/filecheck.c +14
-0+ ret =0 ; +break ; + } +spin_unlock (&osb->fc_lock); +if (ret) +return ret; + + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_FIX ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; +} +fs/ocfs2/filecheck.h +1
-0@@ -53,6 +53,7 @@ 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_filefix_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);fs/ocfs2/sysfs.c +1
-2@@ -91,7 +91,7 @@ static ssize_t file_fix_store(struct ocfs2_super *osb, ret =kstrtoul (skip_spaces (buf),0 , &t);if (ret)return ret; - ret =ocfs2_filecheck_add_inode (osb, t); + ret =ocfs2_filefix_add_inode (osb, t);if (ret)return ret;return count; --2.6.6
_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel at oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel
Signature · 1 line
Goldwyn
PATCH 5/5 Fix files when an inode is written in file_fix
Hello Goldwyn,
Quoted 69 lines
Quoted 1 line
Quoted 1 line
Quoted 57 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 48 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +4
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 7 lines
fs/ocfs2/filecheck.c +7
-0+struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry
Quoted 7 lines
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous user process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock fc_lock is used to protect entry list (adding entry/deleting entry), not protect entry itself.
The first user process will mark the entry's status to done after the file check operation is finished, then the function ocfs2_filecheck_erase_entries() will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry. You know, the spinlock can not protect the file check operation (too long time IO operation).
Quoted 2 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the thing simple.
Just return a -EBUSY error when the same inode is on the progress, then the user can try again after that file check process returns.
Quoted 3 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check operation, each user trigger process is used to execute its file check operation.
Why? first, keep the thing simple, avoid to involve more logic/thread. second, if we involved a thread/work queue to run the file check operations,
that means the user trigger process will return directly and need not to wait for the actual file check operation, there will be a risk that the user can
not see the result from the result history record (via cat check/fix), since the new submits result will make the oldest result records to be released,
we have a fixed length list to keep these status records. If we use the user trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 53 lines
Quoted 50 lines
Quoted 50 lines
fs/ocfs2/filecheck.c +14
-0+ ret =0 ; +break ; + } +spin_unlock (&osb->fc_lock); +if (ret) +return ret; + + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_FIX ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; +} +fs/ocfs2/filecheck.h +1
-0@@ -53,6 +53,7 @@ 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_filefix_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);fs/ocfs2/sysfs.c +1
-2@@ -91,7 +91,7 @@ static ssize_t file_fix_store(struct ocfs2_super *osb, ret =kstrtoul (skip_spaces (buf),0 , &t);if (ret)return ret; - ret =ocfs2_filecheck_add_inode (osb, t); + ret =ocfs2_filefix_add_inode (osb, t);if (ret)return ret;return count; --2.6.6
_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel at oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-develSignature · 1 line
Goldwyn
PATCH v2 5/5 Fix files when an inode is written in file_fix
Quoted 75 lines · Gang He
Hello Goldwyn,
Quoted 72 lines
Quoted 1 line
Quoted 1 line
Quoted 57 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 48 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +4
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 7 lines
fs/ocfs2/filecheck.c +7
-0+struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same ino
Quoted 7 lines
Quoted 4 lines
number entry in the list, then the user can try again after the previous user process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list (adding entry/deleting entry), not protect entry itself.
The first user process will mark the entry's status to done after the file check operation is finished, then the functionocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry. You know, the spinlock can not protect the file check operation (too long time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
In any case, if we check on status, we can do away with it. We may require filecheck_entry spinlocks later on, but for now it is not required.
Quoted 5 lines
Quoted 3 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the thing simple.
Just return a-EBUSYerror when the same inode is on the progress, then the user can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 10 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check operation, each user trigger process is used to execute its file check operation.
Why? first, keep the thing simple, avoid to involve more logic/thread. second, if we involved a thread/work queue to run the file check operations,
that means the user trigger process will return directly and need not to wait for the actual file check operation, there will be a risk that the user can
not see the result from the result history record (via cat check/fix), since the new submits result will make the oldest result records to be released,
we have a fixed length list to keep these status records. If we use the user trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
In the future, how do you plan to extend this? How would you check for extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?
Quoted 54 lines
Quoted 54 lines
Quoted 47 lines
Quoted 47 lines
fs/ocfs2/filecheck.c +14
-0+ ret =0 ; +break ; + } +spin_unlock (&osb->fc_lock); +if (ret) +return ret; + + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_FIX ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; +} +fs/ocfs2/filecheck.h +1
-0@@ -53,6 +53,7 @@ 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_filefix_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);fs/ocfs2/sysfs.c +1
-2@@ -91,7 +91,7 @@ static ssize_t file_fix_store(struct ocfs2_super *osb, ret =kstrtoul (skip_spaces (buf),0 , &t);if (ret)return ret; - ret =ocfs2_filecheck_add_inode (osb, t); + ret =ocfs2_filefix_add_inode (osb, t);if (ret)return ret;return count; --2.6.6
Quoted 4 lines
Quoted 4 lines
_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel at oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel--
Goldwyn
Signature · 1 line
Goldwyn
PATCH 5/5 Fix files when an inode is written in file_fix
Quoted 94 lines
Quoted 4 lines
Quoted 4 lines
Quoted 76 lines · Gang He
Hello Goldwyn,
Quoted 73 lines
Quoted 1 line
Quoted 1 line
Quoted 57 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 48 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +4
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 7 lines
fs/ocfs2/filecheck.c +7
-0+struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous
user
Quoted 4 lines
Quoted 3 lines
process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list(adding entry/deleting entry), not protect entry itself.
Quoted 1 line
The first user process will mark the entry's status to done after the file
check operation is finished, then the function
ocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry.
Quoted 5 lines
Quoted 1 line
You know, the spinlock can not protect the file check operation (too long
time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
Gang: we can not delete the file check entry after it's operation is done, since we need to keep them to provide the result history records.
Quoted 3 lines
In any case, if we check on status, we can do away with it. We may require
filecheck_entryspinlocks later on, but for now it is not required.
Gang: Why we need a spinlock for each filecheck entry? the entry is only occupied by one user process. we only need to get the lock when adding/deleting the entry from the list, this operation is very short.
Quoted 28 lines
Quoted 6 lines
Quoted 5 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the
thing simple.
Quoted 1 line
Just return a
-EBUSYerror when the same inode is on the progress, then theuser can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 5 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check
operation, each user trigger process is used to execute its file check operation.
Quoted 1 line
Why? first, keep the thing simple, avoid to involve more logic/thread.
second, if we involved a thread/work queue to run the file check operations,
Quoted 1 line
that means the user trigger process will return directly and need not to
wait for the actual file check operation, there will be a risk that the user can
Quoted 1 line
not see the result from the result history record (via cat check/fix), since
the new submits result will make the oldest result records to be released,
Quoted 1 line
we have a fixed length list to keep these status records. If we use the user
Quoted 8 lines
trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 1 line
In the future, how do you plan to extend this? How would you check for
extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?
Gang: Yes, the trigger user process can wait for this I/O operation, just like a system call. If we want to check multiple files (inode), we can use a batch to call this interface one by one (of course, you can use multiple threads/processes), this is why I did not use a work queue/thread in the kernel module to do this asynchronously, because in the user space, we can do the same thing. let's keep the kernel module logic simple.
Quoted 59 lines
Quoted 18 lines
Quoted 18 lines
Quoted 18 lines
Quoted 18 lines
fs/ocfs2/filecheck.c +14
-0+ ret =0 ; +break ; + } +spin_unlock (&osb->fc_lock); +if (ret) +return ret; + + entry->fe_status =ocfs2_filecheck_handle (osb, + entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_FIX ); + +ocfs2_filecheck_done_entry (osb, entry); +return 0 ; +} +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
fs/ocfs2/filecheck.h int ocfs2_filecheck_create_sysfs(struct super_block *sb); · line 55
Quoted 8 lines
fs/ocfs2/filecheck.h +0
-0@@ -53,6 +53,7 @@ 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 longino);
Quoted 29 lines
Quoted 29 lines
Quoted 22 lines
Quoted 22 lines
fs/ocfs2/filecheck.h +1
-0+int ocfs2_filefix_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);fs/ocfs2/sysfs.c +1
-2@@ -91,7 +91,7 @@ static ssize_t file_fix_store(struct ocfs2_super *osb, ret =kstrtoul (skip_spaces (buf),0 , &t);if (ret)return ret; - ret =ocfs2_filecheck_add_inode (osb, t); + ret =ocfs2_filefix_add_inode (osb, t);if (ret)return ret;return count; --2.6.6
Quoted 4 lines
Quoted 4 lines
_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel at oss.oracle.com
https://oss.oracle.com/mailman/listinfo/ocfs2-devel--
GoldwynSignature · 1 line
Goldwyn
PATCH v2 5/5 Fix files when an inode is written in file_fix
Quoted 141 lines · Gang He
Quoted 94 lines
Quoted 4 lines
Quoted 4 lines
Quoted 76 lines · Gang He
Hello Goldwyn,
Quoted 73 lines
Quoted 1 line
Quoted 1 line
Quoted 57 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 48 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +4
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 7 lines
fs/ocfs2/filecheck.c +7
-0+struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous
user
Quoted 4 lines
Quoted 3 lines
process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list(adding entry/deleting entry), not protect entry itself.
Quoted 1 line
The first user process will mark the entry's status to done after the file
check operation is finished, then the function
ocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry.Quoted 5 lines
Quoted 1 line
You know, the spinlock can not protect the file check operation (too long
time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
Gang: we can not delete the file check entry after it's operation is done, since we need to keep them to provide the result history records.
Quoted 3 lines
In any case, if we check on status, we can do away with it. We may require
filecheck_entryspinlocks later on, but for now it is not required.Gang: Why we need a spinlock for each filecheck entry? the entry is only occupied by one user process. we only need to get the lock when adding/deleting the entry from the list, this operation is very short.
Quoted 33 lines
Quoted 6 lines
Quoted 5 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the
thing simple.
Quoted 1 line
Just return a
-EBUSYerror when the same inode is on the progress, then theuser can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 5 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check
operation, each user trigger process is used to execute its file check operation.
Quoted 1 line
Why? first, keep the thing simple, avoid to involve more logic/thread.
second, if we involved a thread/work queue to run the file check operations,
Quoted 1 line
that means the user trigger process will return directly and need not to
wait for the actual file check operation, there will be a risk that the user can
Quoted 1 line
not see the result from the result history record (via cat check/fix), since
the new submits result will make the oldest result records to be released,
Quoted 1 line
we have a fixed length list to keep these status records. If we use the user
trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 1 line
Quoted 8 lines
Quoted 3 lines
In the future, how do you plan to extend this? How would you check for
extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?Gang: Yes, the trigger user process can wait for this I/O operation, just like a system call. If we want to check multiple files (inode), we can use a batch to call this interface one by one (of course, you can use multiple threads/processes), this is why I did not use a work queue/thread in the kernel module to do this asynchronously, because in the user space, we can do the same thing. let's keep the kernel module logic simple.
If you were planning to keep the process synchronous, why keep multiple entries. Just one would have been enough. This way the check/fix cycle would have a better probability of finding stuff in the cache as well.
Signature · 1 line
Goldwyn
PATCH 5/5 Fix files when an inode is written in file_fix
Quoted 160 lines
Quoted 4 lines
Quoted 4 lines
Quoted 94 lines · Gang He
Quoted 94 lines
Quoted 4 lines
Quoted 4 lines
Quoted 76 lines · Gang He
Hello Goldwyn,
Quoted 73 lines
Quoted 1 line
Quoted 1 line
Quoted 57 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 48 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +4
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 7 lines
fs/ocfs2/filecheck.c +7
-0+struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous
user
Quoted 4 lines
Quoted 3 lines
process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list(adding entry/deleting entry), not protect entry itself.
Quoted 1 line
The first user process will mark the entry's status to done after the file
check operation is finished, then the function
ocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry.Quoted 6 lines
Quoted 5 lines
Quoted 1 line
You know, the spinlock can not protect the file check operation (too long
time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
Gang: we can not delete the file check entry after it's operation is done,
since we need to keep
Quoted 6 lines
them to provide the result history records.
Quoted 3 lines
In any case, if we check on status, we can do away with it. We may require
filecheck_entryspinlocks later on, but for now it is not required.Gang: Why we need a spinlock for each filecheck entry? the entry is only
occupied by one user process.
Quoted 1 line
we only need to get the lock when adding/deleting the entry from the list,
this operation is very short.
Quoted 34 lines
Quoted 34 lines
Quoted 7 lines
Quoted 6 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the
thing simple.
Quoted 1 line
Just return a
-EBUSYerror when the same inode is on the progress, then theuser can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 5 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check
operation, each user trigger process is used to execute its file check operation.
Quoted 1 line
Why? first, keep the thing simple, avoid to involve more logic/thread.
second, if we involved a thread/work queue to run the file check operations,
Quoted 1 line
that means the user trigger process will return directly and need not to
wait for the actual file check operation, there will be a risk that the user can
Quoted 1 line
not see the result from the result history record (via cat check/fix), since
the new submits result will make the oldest result records to be released,
Quoted 1 line
we have a fixed length list to keep these status records. If we use the user
trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 1 line
Quoted 4 lines
Quoted 3 lines
In the future, how do you plan to extend this? How would you check for
extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?Gang: Yes, the trigger user process can wait for this I/O operation, just
like a system call.
Quoted 1 line
If we want to check multiple files (inode), we can use a batch to call this
interface one by one
Quoted 1 line
(of course, you can use multiple threads/processes), this is why I did not
use a work queue/thread
Quoted 8 lines
Quoted 1 line
in the kernel module to do this asynchronously, because in the user space,
we can do the same thing.
Quoted 1 line
let's keep the kernel module logic simple.
If you were planning to keep the process synchronous, why keep multiple entries. Just one would have been enough. This way the check/fix cycle would have a better probability of finding stuff in the cache as well.
The list be used for file check entry history status, and for supporting to multiple user threads/processes to trigger a check/fix request parallelly.
Quoted 4 lines
Signature · 2 lines
-- Goldwyn
PATCH v2 5/5 Fix files when an inode is written in file_fix
Quoted 161 lines · Gang He
Quoted 161 lines
Quoted 4 lines
Quoted 4 lines
Quoted 94 lines · Gang He
Quoted 94 lines
Quoted 4 lines
Quoted 4 lines
Quoted 76 lines · Gang He
Hello Goldwyn,
Quoted 73 lines
Quoted 1 line
Quoted 1 line
Quoted 57 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 48 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +4
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 7 lines
fs/ocfs2/filecheck.c +7
-0+struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous
user
Quoted 4 lines
Quoted 3 lines
process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list(adding entry/deleting entry), not protect entry itself.
Quoted 1 line
The first user process will mark the entry's status to done after the file
check operation is finished, then the function
ocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry.Quoted 6 lines
Quoted 5 lines
Quoted 1 line
You know, the spinlock can not protect the file check operation (too long
time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
Gang: we can not delete the file check entry after it's operation is done,
since we need to keep
Quoted 6 lines
them to provide the result history records.
Quoted 3 lines
In any case, if we check on status, we can do away with it. We may require
filecheck_entryspinlocks later on, but for now it is not required.Gang: Why we need a spinlock for each filecheck entry? the entry is only
occupied by one user process.
Quoted 1 line
we only need to get the lock when adding/deleting the entry from the list,
this operation is very short.
Quoted 34 lines
Quoted 34 lines
Quoted 7 lines
Quoted 6 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the
thing simple.
Quoted 1 line
Just return a
-EBUSYerror when the same inode is on the progress, then theuser can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 5 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check
operation, each user trigger process is used to execute its file check operation.
Quoted 1 line
Why? first, keep the thing simple, avoid to involve more logic/thread.
second, if we involved a thread/work queue to run the file check operations,
Quoted 1 line
that means the user trigger process will return directly and need not to
wait for the actual file check operation, there will be a risk that the user can
Quoted 1 line
not see the result from the result history record (via cat check/fix), since
the new submits result will make the oldest result records to be released,
Quoted 1 line
we have a fixed length list to keep these status records. If we use the user
trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 1 line
Quoted 4 lines
Quoted 3 lines
In the future, how do you plan to extend this? How would you check for
extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?Gang: Yes, the trigger user process can wait for this I/O operation, just
like a system call.
Quoted 1 line
If we want to check multiple files (inode), we can use a batch to call this
interface one by one
Quoted 1 line
(of course, you can use multiple threads/processes), this is why I did not
use a work queue/thread
Quoted 1 line
in the kernel module to do this asynchronously, because in the user space,
Quoted 9 lines
Quoted 7 lines
we can do the same thing.
Quoted 1 line
let's keep the kernel module logic simple.
If you were planning to keep the process synchronous, why keep multiple entries. Just one would have been enough. This way the check/fix cycle would have a better probability of finding stuff in the cache as well.
The list be used for file check entry history status, and for supporting to multiple user threads/processes to trigger a check/fix request parallelly.
Why do you need history in a synchronous process. The error is received as soon as the process ends. Besides, in multiple threads each thread will have his context so you don't need to store in a global location. Why did you need to use sysfs for this? Why couldn't you use something else for synchronous processing, say an ioctl()?
Signature · 1 line
Goldwyn
PATCH 5/5 Fix files when an inode is written in file_fix
Quoted 175 lines
Quoted 4 lines
Quoted 4 lines
Quoted 168 lines · Gang He
Quoted 168 lines
Quoted 4 lines
Quoted 4 lines
Quoted 94 lines · Gang He
Quoted 94 lines
Quoted 4 lines
Quoted 4 lines
Quoted 76 lines · Gang He
Hello Goldwyn,
Quoted 73 lines
Quoted 1 line
Quoted 1 line
Quoted 57 lines · Gang He
Hello Goldwyn,
Please see my comments inline.
Thanks
GangQuoted 48 lines
Quoted 1 line
Quoted 1 line
From: Goldwyn Rodrigues <[email protected]>
Check that the entriy exists and has been filed for check. Also perform some code cleanup
Signed-off-by Goldwyn Rodrigues <[email protected]>--- fs/ocfs2/filecheck.c | 41 +++++++++++++++++++++++++---------------- fs/ocfs2/filecheck.h | 1 + fs/ocfs2/sysfs.c | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-)fs/ocfs2/filecheck.c +4
-16@@ -198,22 +198,6 @@ ocfs2_filecheck_handle(struct ocfs2_super *osb,return ret; } -static void -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 (osb, - entry->fe_ino,OCFS2_FI_FLAG_FILECHECK_CHK ); -else if (entry->fe_type ==OCFS2_FILECHECK_TYPE_FIX ) - 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 (osb, entry); -} -int ocfs2_filecheck_add_inode (struct ocfs2_super *osb,unsigned long ino) {@@ -268,3 +252,28 @@ unlock:ocfs2_filecheck_done_entry (osb, entry);return 0 ; } + +int ocfs2_filefix_add_inode (struct ocfs2_super *osb, +unsigned long ino) +{Quoted 8 lines
fs/ocfs2/filecheck.c unlock: · line 265
Quoted 7 lines
fs/ocfs2/filecheck.c +7
-0+struct ocfs2_filecheck_entry *entry; +int ret = -ENOENT ; + +spin_lock (&osb->fc_lock); +list_for_each_entry (entry, &osb->file_check_entries, fe_list) +if (entry->fe_ino == ino) { + entry->fe_type =OCFS2_FILECHECK_TYPE_FIX ;Gang: It looks that we can not do it directly, why? because the entry
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous
user
Quoted 4 lines
Quoted 3 lines
process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list(adding entry/deleting entry), not protect entry itself.
Quoted 1 line
The first user process will mark the entry's status to done after the file
check operation is finished, then the function
ocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry.Quoted 6 lines
Quoted 5 lines
Quoted 1 line
You know, the spinlock can not protect the file check operation (too long
time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
Gang: we can not delete the file check entry after it's operation is done,
since we need to keep
Quoted 6 lines
them to provide the result history records.
Quoted 3 lines
In any case, if we check on status, we can do away with it. We may require
filecheck_entryspinlocks later on, but for now it is not required.Gang: Why we need a spinlock for each filecheck entry? the entry is only
occupied by one user process.
Quoted 1 line
we only need to get the lock when adding/deleting the entry from the list,
this operation is very short.
Quoted 34 lines
Quoted 34 lines
Quoted 7 lines
Quoted 6 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the
thing simple.
Quoted 1 line
Just return a
-EBUSYerror when the same inode is on the progress, then theuser can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 5 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check
operation, each user trigger process is used to execute its file check operation.
Quoted 1 line
Why? first, keep the thing simple, avoid to involve more logic/thread.
second, if we involved a thread/work queue to run the file check operations,
Quoted 1 line
that means the user trigger process will return directly and need not to
wait for the actual file check operation, there will be a risk that the user can
Quoted 1 line
not see the result from the result history record (via cat check/fix), since
the new submits result will make the oldest result records to be released,
Quoted 1 line
we have a fixed length list to keep these status records. If we use the user
trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 1 line
Quoted 4 lines
Quoted 3 lines
In the future, how do you plan to extend this? How would you check for
extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?Gang: Yes, the trigger user process can wait for this I/O operation, just
like a system call.
Quoted 1 line
If we want to check multiple files (inode), we can use a batch to call this
interface one by one
Quoted 1 line
(of course, you can use multiple threads/processes), this is why I did not
use a work queue/thread
Quoted 1 line
in the kernel module to do this asynchronously, because in the user space,
we can do the same thing.
Quoted 1 line
let's keep the kernel module logic simple.
If you were planning to keep the process synchronous, why keep multiple entries. Just one would have been enough. This way the check/fix cycle would have a better probability of finding stuff in the cache as well.
Quoted 6 lines
Quoted 1 line
The list be used for file check entry history status, and for supporting to
multiple user threads/processes to trigger a check/fix request parallelly.
Quoted 1 line
Why do you need history in a synchronous process. The error is received as soon as the process ends.
How do you return a file check specific error number to the trigger user process? then I use a list to save these file check entries (running/done).
The user maybe want to see the file check result again after the file check was done, this just give an chance for user to inquire the result again, but will not occupy too much memory.
Besides, in multiple threads each thread
Quoted 1 line
will have his context so you don't need to store in a global location.
Gang: I prefer to do the thing with independent design, do not depend some other data structures/mechanism, since these data structures/mechanism will be changed according kernel versions possibly. we should try to implement our functions in our module code, then export some interfaces(extern functions) to be invoked by some kernel sensitive data structures/mechanism (e.g. Kobject, ioctl, etc). Why I user a global location, at that moment, I did not aware that we can embed kobject in super block structure like ext4, now we can embed kobject in the super, the idea
is better.
Quoted 2 lines
Why did you need to use sysfs for this? Why couldn't you use something else for synchronous processing, say an
ioctl()?
Gang: Yes, this is a way to reach user process, as you said in a RFC one year ago.
Of course, we also can use ioctl to commutation, but this will means that we have to add some code to implement a user tool.
Anyway, I think it is not too important about if we use synchronous/asynchronous to handle a file check operation, if you like, please create a dedicated kernel thread to execute these file check entries in the list. It is OK for both ways.
Thanks
Gang
Quoted 4 lines
Signature · 2 lines
-- Goldwyn
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v2 5/5 Fix files when an inode is written in file_fix
Quoted 103 lines · Gang He
Quoted 103 lines
Quoted 103 lines
Quoted 103 lines
Quoted 36 lines
Quoted 36 lines
Quoted 21 lines
Quoted 21 lines
Quoted 21 lines
Quoted 10 lines
int ocfs2_filecheck_add_inode(struct
ocfs2_super*osb,
unsigned long ino)
{(quoted diff) +1
-0@@ -268,3 +252,28 @@ unlock: ocfs2_filecheck_done_entry(osb, entry); return 0; } +Review unlock: · line 265
Quoted 10 lines
(quoted diff) +10
-0+int ocfs2_filefix_add_inode(struct ocfs2_super *osb, + unsigned long ino) +{ + struct ocfs2_filecheck_entry *entry; + int ret = -ENOENT; + + spin_lock(&osb->fc_lock); + list_for_each_entry(entry, &osb->file_check_entries, fe_list) + if (entry->fe_ino == ino) { + entry->fe_type = OCFS2_FILECHECK_TYPE_FIX;Gang: It looks that we can not do it directly, why? because the entry
Quoted 4 lines
Quoted 4 lines
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous
user
Quoted 4 lines
Quoted 3 lines
process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list(adding entry/deleting entry), not protect entry itself.
Quoted 1 line
The first user process will mark the entry's status to done after the file
check operation is finished, then the function
ocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry.Quoted 6 lines
Quoted 5 lines
Quoted 1 line
You know, the spinlock can not protect the file check operation (too long
time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
Gang: we can not delete the file check entry after it's operation is done,
since we need to keep
Quoted 6 lines
them to provide the result history records.
Quoted 3 lines
In any case, if we check on status, we can do away with it. We may require
filecheck_entryspinlocks later on, but for now it is not required.Gang: Why we need a spinlock for each filecheck entry? the entry is only
occupied by one user process.
Quoted 1 line
we only need to get the lock when adding/deleting the entry from the list,
this operation is very short.
Quoted 34 lines
Quoted 34 lines
Quoted 7 lines
Quoted 6 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the
thing simple.
Quoted 1 line
Just return a
-EBUSYerror when the same inode is on the progress, then theuser can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 5 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check
operation, each user trigger process is used to execute its file check operation.
Quoted 1 line
Why? first, keep the thing simple, avoid to involve more logic/thread.
second, if we involved a thread/work queue to run the file check operations,
Quoted 1 line
that means the user trigger process will return directly and need not to
wait for the actual file check operation, there will be a risk that the user can
Quoted 1 line
not see the result from the result history record (via cat check/fix), since
the new submits result will make the oldest result records to be released,
Quoted 1 line
we have a fixed length list to keep these status records. If we use the user
trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 1 line
Quoted 4 lines
Quoted 3 lines
In the future, how do you plan to extend this? How would you check for
extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?Gang: Yes, the trigger user process can wait for this I/O operation, just
like a system call.
Quoted 1 line
If we want to check multiple files (inode), we can use a batch to call this
interface one by one
Quoted 1 line
(of course, you can use multiple threads/processes), this is why I did not
use a work queue/thread
Quoted 1 line
in the kernel module to do this asynchronously, because in the user space,
we can do the same thing.
Quoted 1 line
let's keep the kernel module logic simple.
If you were planning to keep the process synchronous, why keep multiple entries. Just one would have been enough. This way the check/fix cycle would have a better probability of finding stuff in the cache as well.
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
The list be used for file check entry history status, and for supporting to
multiple user threads/processes to trigger a check/fix request parallelly.
Quoted 1 line
Why do you need history in a synchronous process. The error is received as soon as the process ends.
How do you return a file check specific error number to the trigger user process? then I use a list to save these file check entries (running/done).
The user maybe want to see the file check result again after the file check was done, this just give an chance for user to inquire the result again, but will not occupy too much memory.
There are quite a few ways, one of them being ioctl()s.
In synchronous processing, you don't need to check error values again and again. It is returned when you execute the request. Just like synchronous system calls such as read() and write() receive errors
Quoted 6 lines
Besides, in multiple threads each thread
Quoted 1 line
will have his context so you don't need to store in a global location.
Gang: I prefer to do the thing with independent design, do not depend some other data structures/mechanism, since these data structures/mechanism will be changed according kernel versions possibly. we should try to implement our functions in our module code, then export some interfaces(extern functions) to be invoked by some kernel sensitive data structures/mechanism (e.g. Kobject, ioctl, etc). Why I user a global location, at that moment, I did not aware that we can embed kobject in super block structure like ext4, now we can embed kobject in the super, the idea
is better.
But how will you code in the kernel if you don't use the kernel data structures?
Quoted 6 lines
Quoted 4 lines
Why did you need to use sysfs for this? Why couldn't you use something else for synchronous processing, say an
ioctl()?Gang: Yes, this is a way to reach user process, as you said in a RFC one year ago.
Of course, we also can use ioctl to commutation, but this will means that we have to add some code to implement a user tool.
Yes, the main reason I suggested to maintain a history in the RFC was to keep it asynchronous.
Quoted 3 lines
Anyway, I think it is not too important about if we use synchronous/asynchronous to handle a file check operation, if you like, please create a dedicated kernel thread to execute these file check entries in the list. It is OK for both ways.
It is not as complicated as you think. I will send it once I finish the code.
Signature · 1 line
Goldwyn
PATCH 5/5 Fix files when an inode is written in file_fix
Hi Goldwyn,
I have no more comments, let's discuss when your update code is finished.
Thanks
Gang
Quoted 165 lines
Quoted 1 line
Quoted 1 line
Quoted 103 lines · Gang He
Quoted 103 lines
Quoted 103 lines
Quoted 103 lines
Quoted 36 lines
Quoted 36 lines
Quoted 21 lines
Quoted 21 lines
Quoted 21 lines
Quoted 10 lines
int ocfs2_filecheck_add_inode(struct
ocfs2_super*osb,
unsigned long ino)
{(quoted diff) +1
-0@@ -268,3 +252,28 @@ unlock: ocfs2_filecheck_done_entry(osb, entry); return 0; } +Review unlock: · line 265
Quoted 10 lines
(quoted diff) +10
-0+int ocfs2_filefix_add_inode(struct ocfs2_super *osb, + unsigned long ino) +{ + struct ocfs2_filecheck_entry *entry; + int ret = -ENOENT; + + spin_lock(&osb->fc_lock); + list_for_each_entry(entry, &osb->file_check_entries, fe_list) + if (entry->fe_ino == ino) { + entry->fe_type = OCFS2_FILECHECK_TYPE_FIX;Gang: It looks that we can not do it directly, why? because the entry
Quoted 4 lines
Quoted 4 lines
pointer can be freed by the function
ocfs2_filecheck_erase_entries().Quoted 2 lines
We can not use the same entry pointer within two user processes. The simple solution is to return
-EBUSYerror in case there is the same inonumber entry in the list, then the user can try again after the previous
user
Quoted 4 lines
Quoted 3 lines
process is returned.
How? is it not protected under spinlock?
Gang: please aware that this spinlock
fc_lockis used to protect entry list(adding entry/deleting entry), not protect entry itself.
Quoted 1 line
The first user process will mark the entry's status to done after the file
check operation is finished, then the function
ocfs2_filecheck_erase_entries()will possibly delete this entry from the list, to free the entry memory during the second user process is referencing on this entry.Quoted 6 lines
Quoted 5 lines
Quoted 1 line
You know, the spinlock can not protect the file check operation (too long
time IO operation).
Yes, a possible reason for separating the lists too. The entries will be deleted after a check, and the user will not be able to perform a fix on it.
Gang: we can not delete the file check entry after it's operation is done,
since we need to keep
Quoted 6 lines
them to provide the result history records.
Quoted 3 lines
In any case, if we check on status, we can do away with it. We may require
filecheck_entryspinlocks later on, but for now it is not required.Gang: Why we need a spinlock for each filecheck entry? the entry is only
occupied by one user process.
Quoted 1 line
we only need to get the lock when adding/deleting the entry from the list,
this operation is very short.
Quoted 34 lines
Quoted 34 lines
Quoted 7 lines
Quoted 6 lines
Anyways, I plan to make a separate list for this so we can do away with more macros.
Gang: you can use two lists, but I think that one list is also OK, keep the
thing simple.
Quoted 1 line
Just return a
-EBUSYerror when the same inode is on the progress, then theuser can try again after that file check process returns.
Thanks for the suggestions, I have incorporated that, with the two lists, of course.
Quoted 5 lines
Quoted 4 lines
Besides, any I/O and check operation should be done in a separate thread/work queue.
Gang: current design is no a separated thread is used to run file check
operation, each user trigger process is used to execute its file check operation.
Quoted 1 line
Why? first, keep the thing simple, avoid to involve more logic/thread.
second, if we involved a thread/work queue to run the file check operations,
Quoted 1 line
that means the user trigger process will return directly and need not to
wait for the actual file check operation, there will be a risk that the user can
Quoted 1 line
not see the result from the result history record (via cat check/fix), since
the new submits result will make the oldest result records to be released,
Quoted 1 line
we have a fixed length list to keep these status records. If we use the user
trigger process to do the file check operation, the user can surely see the result after this user process returns (since this file check operation is done in the kernel space).
Quoted 1 line
Quoted 4 lines
Quoted 3 lines
In the future, how do you plan to extend this? How would you check for
extent_blocks? Or worse, system files? Would you keep the system waiting until all I/O has completed?Gang: Yes, the trigger user process can wait for this I/O operation, just
like a system call.
Quoted 1 line
If we want to check multiple files (inode), we can use a batch to call this
interface one by one
Quoted 1 line
(of course, you can use multiple threads/processes), this is why I did not
use a work queue/thread
Quoted 1 line
in the kernel module to do this asynchronously, because in the user space,
we can do the same thing.
Quoted 1 line
let's keep the kernel module logic simple.
If you were planning to keep the process synchronous, why keep multiple entries. Just one would have been enough. This way the check/fix cycle would have a better probability of finding stuff in the cache as well.
Quoted 7 lines
Quoted 6 lines
Quoted 1 line
The list be used for file check entry history status, and for supporting to
multiple user threads/processes to trigger a check/fix request parallelly.
Quoted 1 line
Why do you need history in a synchronous process. The error is received as soon as the process ends.
How do you return a file check specific error number to the trigger user
process? then I use a list to save these file check entries (running/done).
Quoted 1 line
The user maybe want to see the file check result again after the file check
was done, this just give an chance for user to inquire the result again, but will not occupy too much memory.
There are quite a few ways, one of them being ioctl()s.
In synchronous processing, you don't need to check error values again and again. It is returned when you execute the request. Just like synchronous system calls such asread()andwrite()receive errorsQuoted 4 lines
Besides, in multiple threads each thread
Quoted 1 line
will have his context so you don't need to store in a global location.
Gang: I prefer to do the thing with independent design, do not depend some
other data structures/mechanism, since these data structures/mechanism will be changed according kernel versions possibly. we should try to implement our functions in our module code, then export some interfaces(extern functions) to be invoked by some kernel sensitive data structures/mechanism (e.g.
Quoted 1 line
Kobject, ioctl, etc). Why I user a global location, at that moment, I did
not aware that we can embed kobject in super block structure like ext4, now we can embed kobject in the super, the idea
Quoted 1 line
is better.
But how will you code in the kernel if you don't use the kernel data structures?
Quoted 5 lines
Quoted 4 lines
Why did you need to use sysfs for this? Why couldn't you use something else for synchronous processing, say an
ioctl()?Gang: Yes, this is a way to reach user process, as you said in a RFC one
year ago.
Quoted 1 line
Of course, we also can use ioctl to commutation, but this will means that we
have to add some code to implement a user tool.
Yes, the main reason I suggested to maintain a history in the RFC was to keep it asynchronous.
Quoted 2 lines
Anyway, I think it is not too important about if we use
synchronous/asynchronous to handle a file check operation, if you like, please create a dedicated kernel thread to execute these file check entries in the list. It is OK for both ways.
Quoted 1 line
It is not as complicated as you think. I will send it once I finish the code.
Signature · 1 line
Goldwyn