On 05/30/2016 04:23 AM, Gang He wrote:
> 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
>
>
>>>>
>> 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_super
>> now.
>>
>> 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(-)
>>
>> diff --git a/fs/ocfs2/filecheck.c b/fs/ocfs2/filecheck.c
>> index 2cabbcf..0b41967 100644
>> --- a/fs/ocfs2/filecheck.c
>> +++ b/fs/ocfs2/filecheck.c
>> @@ -17,15 +17,7 @@
>>    * General Public License for more details.
>>    */
>>
>> -#include <linux/list.h>
>> -#include <linux/spinlock.h>
>> -#include <linux/module.h>
>> -#include <linux/slab.h>
>> -#include <linux/kmod.h>
>>   #include <linux/fs.h>
>> -#include <linux/kobject.h>
>> -#include <linux/sysfs.h>
>> -#include <linux/sysctl.h>
>>   #include <cluster/masklog.h>
>>
>>   #include "ocfs2.h"
>> @@ -53,36 +45,6 @@ static const char * const ocfs2_filecheck_errs[] = {
>>      "UNSUPPORTED"
>>   };
>>
>> -static DEFINE_SPINLOCK(ocfs2_filecheck_sysfs_lock);
>> -static LIST_HEAD(ocfs2_filecheck_sysfs_list);
>> -
>
>> -struct ocfs2_filecheck {
>> -    struct list_head fc_head;       /* File check entry list head */
>> -    spinlock_t fc_lock;
>> -    unsigned int fc_max;    /* Maximum number of entry in list */
>> -    unsigned int fc_size;   /* Current entry count in list */
>> -    unsigned int fc_done;   /* Finished entry count in list */
>> -};
> 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.


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.

>
>
>> -
>> -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.

Okay, I will fix that.

>
>> -
>> -#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.

Yes, they are referenced by multiple files.

>
>> -
>> -/* 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.

>
>> -
>>   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);
>> -}
> 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.

>
>> -
>> -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;
>> -}
> 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.
>
>
>> -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);
>> -}
> Gang: this part code can be re-used after a little modification.

For what?

>
>> -
>>   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;
>> -}
>> -
> 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.

How? Do you have an example?

>
>> -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);
> 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?

>
>> -    if (!ent) {
>> -            mlog(ML_ERROR,
>> -            "Cannot get the corresponding entry via device basename %s\n",
>> -            kobj->name);
>> -            return -ENODEV;
>> -    }
>> -
>> -    if (type == OCFS2_FILECHECK_TYPE_SET) {
>> -            spin_lock(&ent->fs_fcheck->fc_lock);
>> -            total = snprintf(buf, remain, "%u\n", ent->fs_fcheck->fc_max);
>> -            spin_unlock(&ent->fs_fcheck->fc_lock);
>> -            goto exit;
>> -    }
>>
>>      ret = snprintf(buf, remain, "INO\t\tDONE\tERROR\n");
>>      total += ret;
>>      remain -= ret;
>> -    spin_lock(&ent->fs_fcheck->fc_lock);
>> -    list_for_each_entry(p, &ent->fs_fcheck->fc_head, fe_list) {
>> +    spin_lock(&osb->fc_lock);
>> +    list_for_each_entry(p, &osb->file_check_entries, fe_list) {
>>              if (p->fe_type != type)
>>                      continue;
>>
>> @@ -443,24 +127,21 @@ static ssize_t ocfs2_filecheck_show(struct kobject
>> *kobj,
>>              total += ret;
>>              remain -= ret;
>>      }
>> -    spin_unlock(&ent->fs_fcheck->fc_lock);
>> -
>> -exit:
>> -    ocfs2_filecheck_sysfs_put(ent);
>> +    spin_unlock(&osb->fc_lock);
>>      return total;
>>   }
>>
>>   static int
>> -ocfs2_filecheck_erase_entry(struct ocfs2_filecheck_sysfs_entry *ent)
>> +ocfs2_filecheck_erase_entry(struct ocfs2_super *osb)
>>   {
>>      struct ocfs2_filecheck_entry *p;
>>
>> -    list_for_each_entry(p, &ent->fs_fcheck->fc_head, fe_list) {
>> +    list_for_each_entry(p, &osb->file_check_entries, fe_list) {
>>              if (p->fe_done) {
>>                      list_del(&p->fe_list);
>>                      kfree(p);
>> -                    ent->fs_fcheck->fc_size--;
>> -                    ent->fs_fcheck->fc_done--;
>> +                    osb->fc_size--;
>> +                    osb->fc_done--;
>>                      return 1;
>>              }
>>      }
>> @@ -469,14 +150,14 @@ ocfs2_filecheck_erase_entry(struct
>> ocfs2_filecheck_sysfs_entry *ent)
>>   }
>>
>>   static int
>> -ocfs2_filecheck_erase_entries(struct ocfs2_filecheck_sysfs_entry *ent,
>> +ocfs2_filecheck_erase_entries(struct ocfs2_super *osb,
>>                            unsigned int count)
>>   {
>>      unsigned int i = 0;
>>      unsigned int ret = 0;
>>
>>      while (i++ < count) {
>> -            if (ocfs2_filecheck_erase_entry(ent))
>> +            if (ocfs2_filecheck_erase_entry(osb))
>>                      ret++;
>>              else
>>                      break;
>> @@ -486,24 +167,24 @@ ocfs2_filecheck_erase_entries(struct
>> ocfs2_filecheck_sysfs_entry *ent,
>>   }
>>
>>   static void
>> -ocfs2_filecheck_done_entry(struct ocfs2_filecheck_sysfs_entry *ent,
>> +ocfs2_filecheck_done_entry(struct ocfs2_super *osb,
>>                         struct ocfs2_filecheck_entry *entry)
>>   {
>>      entry->fe_done = 1;
>> -    spin_lock(&ent->fs_fcheck->fc_lock);
>> -    ent->fs_fcheck->fc_done++;
>> -    spin_unlock(&ent->fs_fcheck->fc_lock);
>> +    spin_lock(&osb->fc_lock);
>> +    osb->fc_done++;
>> +    spin_unlock(&osb->fc_lock);
>>   }
>>
>>   static unsigned int
>> -ocfs2_filecheck_handle(struct super_block *sb,
>> +ocfs2_filecheck_handle(struct ocfs2_super *osb,
>>                     unsigned long ino, unsigned int flags)
>>   {
>>      unsigned int ret = OCFS2_FILECHECK_ERR_SUCCESS;
>>      struct inode *inode = NULL;
>>      int rc;
>>
>> -    inode = ocfs2_iget(OCFS2_SB(sb), ino, flags, 0);
>> +    inode = ocfs2_iget(osb, ino, flags, 0);
>>      if (IS_ERR(inode)) {
>>              rc = (int)(-(long)inode);
>>              if (rc >= OCFS2_FILECHECK_ERR_START &&
>> @@ -518,89 +199,64 @@ ocfs2_filecheck_handle(struct super_block *sb,
>>   }
>>
>>   static void
>> -ocfs2_filecheck_handle_entry(struct ocfs2_filecheck_sysfs_entry *ent,
>> +ocfs2_filecheck_handle_entry(struct ocfs2_super *osb,
>>                           struct ocfs2_filecheck_entry *entry)
>>   {
>>      if (entry->fe_type == OCFS2_FILECHECK_TYPE_CHK)
>> -            entry->fe_status = ocfs2_filecheck_handle(ent->fs_sb,
>> +            entry->fe_status = ocfs2_filecheck_handle(osb,
>>                              entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_CHK);
>>      else if (entry->fe_type == OCFS2_FILECHECK_TYPE_FIX)
>> -            entry->fe_status = ocfs2_filecheck_handle(ent->fs_sb,
>> +            entry->fe_status = ocfs2_filecheck_handle(osb,
>>                              entry->fe_ino, OCFS2_FI_FLAG_FILECHECK_FIX);
>>      else
>>              entry->fe_status = OCFS2_FILECHECK_ERR_UNSUPPORTED;
>>
>> -    ocfs2_filecheck_done_entry(ent, entry);
>> +    ocfs2_filecheck_done_entry(osb, entry);
>>   }
>>
>> -static ssize_t ocfs2_filecheck_store(struct kobject *kobj,
>> -                                 struct kobj_attribute *attr,
>> -                                 const char *buf, size_t count)
>> +int ocfs2_filecheck_add_inode(struct ocfs2_super *osb,
>> +                                 unsigned long ino)
>>   {
>> -    struct ocfs2_filecheck_args args;
>>      struct ocfs2_filecheck_entry *entry;
>> -    struct ocfs2_filecheck_sysfs_entry *ent;
>>      ssize_t ret = 0;
>>
>> -    if (count == 0)
>> -            return count;
>> -
>> -    if (ocfs2_filecheck_args_parse(attr->attr.name, buf, count, &args)) {
>> -            mlog(ML_ERROR, "Invalid arguments for online file check\n");
>> -            return -EINVAL;
>> -    }
>> -
>> -    ent = ocfs2_filecheck_sysfs_get(kobj->parent->name);
>> -    if (!ent) {
>> -            mlog(ML_ERROR,
>> -            "Cannot get the corresponding entry via device basename %s\n",
>> -            kobj->parent->name);
>> -            return -ENODEV;
>> -    }
>> -
>> -    if (args.fa_type == OCFS2_FILECHECK_TYPE_SET) {
>> -            ret = ocfs2_filecheck_adjust_max(ent, args.fa_len);
>> -            goto exit;
>> -    }
>> -
>>      entry = kmalloc(sizeof(struct ocfs2_filecheck_entry), GFP_NOFS);
>>      if (!entry) {
>>              ret = -ENOMEM;
>>              goto exit;
>>      }
>>
>> -    spin_lock(&ent->fs_fcheck->fc_lock);
>> -    if ((ent->fs_fcheck->fc_size >= ent->fs_fcheck->fc_max) &&
>> -        (ent->fs_fcheck->fc_done == 0)) {
>> +    spin_lock(&osb->fc_lock);
>> +    if ((osb->fc_size >= osb->fc_max) &&
>> +        (osb->fc_done == 0)) {
>>              mlog(ML_ERROR,
>>              "Cannot do more file check "
>>              "since file check queue(%u) is full now\n",
>> -            ent->fs_fcheck->fc_max);
>> +            osb->fc_max);
>>              ret = -EBUSY;
>>              kfree(entry);
>>      } else {
>> -            if ((ent->fs_fcheck->fc_size >= ent->fs_fcheck->fc_max) &&
>> -                (ent->fs_fcheck->fc_done > 0)) {
>> +            if ((osb->fc_size >= osb->fc_max) &&
>> +                (osb->fc_done > 0)) {
>>                      /* Delete the oldest entry which was done,
>>                       * make sure the entry size in list does
>>                       * not exceed maximum value
>>                       */
>> -                    BUG_ON(!ocfs2_filecheck_erase_entry(ent));
>> +                    BUG_ON(!ocfs2_filecheck_erase_entry(osb));
>>              }
>>
>> -            entry->fe_ino = args.fa_ino;
>> -            entry->fe_type = args.fa_type;
>> +            entry->fe_ino = ino;
>> +            entry->fe_type = OCFS2_FILECHECK_TYPE_CHK;
>>              entry->fe_done = 0;
>>              entry->fe_status = OCFS2_FILECHECK_ERR_INPROGRESS;
>> -            list_add_tail(&entry->fe_list, &ent->fs_fcheck->fc_head);
>> -            ent->fs_fcheck->fc_size++;
>> +            list_add_tail(&entry->fe_list, &osb->file_check_entries);
>> +            osb->fc_size++;
>>      }
>> -    spin_unlock(&ent->fs_fcheck->fc_lock);
>> +    spin_unlock(&osb->fc_lock);
>>
>>      if (!ret)
>> -            ocfs2_filecheck_handle_entry(ent, entry);
>> +            ocfs2_filecheck_handle_entry(osb, entry);
>>
>>   exit:
>> -    ocfs2_filecheck_sysfs_put(ent);
>> -    return (!ret ? count : ret);
>> +    return ret;
>>   }
>> diff --git a/fs/ocfs2/filecheck.h b/fs/ocfs2/filecheck.h
>> index e5cd002..b1a0d8c 100644
>> --- a/fs/ocfs2/filecheck.h
>> +++ b/fs/ocfs2/filecheck.h
>> @@ -42,8 +42,18 @@ enum {
>>
>>   #define OCFS2_FILECHECK_ERR_START  OCFS2_FILECHECK_ERR_FAILED
>>   #define OCFS2_FILECHECK_ERR_END            OCFS2_FILECHECK_ERR_UNSUPPORTED
>> +#define OCFS2_FILECHECK_MAXSIZE         100
>> +#define OCFS2_FILECHECK_MINSIZE         10
>> +
>> +/* File check operation type */
>> +#define OCFS2_FILECHECK_TYPE_CHK    1   /* Check a file(inode) */
>> +#define OCFS2_FILECHECK_TYPE_FIX    2   /* Fix a file(inode) */
> 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.
>
>>
>>   int ocfs2_filecheck_create_sysfs(struct super_block *sb);
>>   int ocfs2_filecheck_remove_sysfs(struct super_block *sb);
>> +int ocfs2_filefix_inode(struct ocfs2_super *osb, unsigned long ino);
>> +int ocfs2_filecheck_add_inode(struct ocfs2_super *osb, unsigned long ino);
>> +int ocfs2_filecheck_set_max_entries(struct ocfs2_super *osb, int num);
>> +int ocfs2_filecheck_show(struct ocfs2_super *osb, unsigned int type, char
>> *buf);
>>
>>   #endif  /* FILECHECK_H */
>> diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
>> index 8e66cdf..9ced543 100644
>> --- a/fs/ocfs2/ocfs2.h
>> +++ b/fs/ocfs2/ocfs2.h
>> @@ -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.


I would prefer it to be a part of ocfs2_super. It is easier to maintain 
and read.

>
>>      struct kobject kobj;
>>      struct completion kobj_unregister;
>>   };
>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>> index 96b7a9f..a7791fa 100644
>> --- a/fs/ocfs2/super.c
>> +++ b/fs/ocfs2/super.c
>> @@ -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);
>> +
> Gang: write a separate funtion in filecheck.c to include these line code, 
> easy to read/maintain.

Why? Unless we are starting something specific to filecheck, I don't see 
any need.

>
>>      /* FIXME
>>       * This should be done in ocfs2_journal_init(), but unknown
>>       * ordering issues will cause the filesystem to crash.
>> diff --git a/fs/ocfs2/sysfs.c b/fs/ocfs2/sysfs.c
>> index e21e699..81e3dd4 100644
>> --- a/fs/ocfs2/sysfs.c
>> +++ b/fs/ocfs2/sysfs.c
>> @@ -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)
>> +{
>> +
>> +    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.

>
>> +    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);
>> +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.


-- 
Goldwyn

_______________________________________________
Ocfs2-devel mailing list
[email protected]
https://oss.oracle.com/mailman/listinfo/ocfs2-devel

Reply via email to