Whamcloud - gitweb
LU-1644 mgc: remove obsolete IR swabbing workaround
[fs/lustre-release.git] / lustre / obdclass / lprocfs_status.c
index 18bd5e0..0c434f2 100644 (file)
@@ -23,7 +23,7 @@
  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2016, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -59,6 +59,29 @@ int lprocfs_seq_release(struct inode *inode, struct file *file)
 }
 EXPORT_SYMBOL(lprocfs_seq_release);
 
+struct dentry *ldebugfs_add_simple(struct dentry *root,
+                                  char *name, void *data,
+                                  const struct file_operations *fops)
+{
+       struct dentry *entry;
+       umode_t mode = 0;
+
+       if (!root || !name || !fops)
+               return ERR_PTR(-EINVAL);
+
+       if (fops->read)
+               mode = 0444;
+       if (fops->write)
+               mode |= 0200;
+       entry = debugfs_create_file(name, mode, root, data, fops);
+       if (IS_ERR_OR_NULL(entry)) {
+               CERROR("LprocFS: No memory to create <debugfs> entry %s", name);
+               return entry ?: ERR_PTR(-ENOMEM);
+       }
+       return entry;
+}
+EXPORT_SYMBOL(ldebugfs_add_simple);
+
 struct proc_dir_entry *
 lprocfs_add_simple(struct proc_dir_entry *root, char *name,
                   void *data, const struct file_operations *fops)
@@ -185,7 +208,7 @@ EXPORT_SYMBOL(lprocfs_add_vars);
 
 void ldebugfs_remove(struct dentry **entryp)
 {
-       debugfs_remove(*entryp);
+       debugfs_remove_recursive(*entryp);
        *entryp = NULL;
 }
 EXPORT_SYMBOL_GPL(ldebugfs_remove);
@@ -346,93 +369,6 @@ lprocfs_register(const char *name, struct proc_dir_entry *parent,
 EXPORT_SYMBOL(lprocfs_register);
 
 /* Generic callbacks */
-int lprocfs_uint_seq_show(struct seq_file *m, void *data)
-{
-       seq_printf(m, "%u\n", *(unsigned int *)data);
-       return 0;
-}
-EXPORT_SYMBOL(lprocfs_uint_seq_show);
-
-int lprocfs_wr_uint(struct file *file, const char __user *buffer,
-                    unsigned long count, void *data)
-{
-       unsigned        *p = data;
-       char             dummy[MAX_STRING_SIZE + 1];
-       char            *end;
-       unsigned long    tmp;
-
-       if (count >= sizeof(dummy))
-               return -EINVAL;
-
-       if (count == 0)
-               return 0;
-
-       if (copy_from_user(dummy, buffer, count))
-               return -EFAULT;
-
-       dummy[count] = 0;
-
-       tmp = simple_strtoul(dummy, &end, 0);
-       if (dummy == end)
-               return -EINVAL;
-
-       *p = (unsigned int)tmp;
-       return count;
-}
-EXPORT_SYMBOL(lprocfs_wr_uint);
-
-ssize_t lprocfs_uint_seq_write(struct file *file, const char __user *buffer,
-                              size_t count, loff_t *off)
-{
-       int *data = ((struct seq_file *)file->private_data)->private;
-       int rc;
-       __s64 val = 0;
-
-       rc = lprocfs_str_to_s64(buffer, count, &val);
-       if (rc < 0)
-               return rc;
-
-       return lprocfs_wr_uint(file, buffer, count, data);
-}
-EXPORT_SYMBOL(lprocfs_uint_seq_write);
-
-int lprocfs_u64_seq_show(struct seq_file *m, void *data)
-{
-       LASSERT(data != NULL);
-       seq_printf(m, "%llu\n", *(__u64 *)data);
-       return 0;
-}
-EXPORT_SYMBOL(lprocfs_u64_seq_show);
-
-int lprocfs_atomic_seq_show(struct seq_file *m, void *data)
-{
-       atomic_t *atom = data;
-       LASSERT(atom != NULL);
-       seq_printf(m, "%d\n", atomic_read(atom));
-       return 0;
-}
-EXPORT_SYMBOL(lprocfs_atomic_seq_show);
-
-ssize_t
-lprocfs_atomic_seq_write(struct file *file, const char __user *buffer,
-                       size_t count, loff_t *off)
-{
-       atomic_t *atm = ((struct seq_file *)file->private_data)->private;
-       __s64 val = 0;
-       int rc;
-
-       rc = lprocfs_str_to_s64(buffer, count, &val);
-       if (rc < 0)
-               return rc;
-
-       if (val <= 0 || val > INT_MAX)
-               return -ERANGE;
-
-       atomic_set(atm, val);
-       return count;
-}
-EXPORT_SYMBOL(lprocfs_atomic_seq_write);
-
 int lprocfs_uuid_seq_show(struct seq_file *m, void *data)
 {
        struct obd_device *obd = data;
@@ -447,7 +383,7 @@ static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
                         char *buf)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
 
        return sprintf(buf, "%s\n", obd->obd_uuid.uuid);
 }
@@ -467,11 +403,13 @@ static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
                              char *buf)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
        struct obd_statfs osfs;
-       int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
-                           cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
-                           OBD_STATFS_NODELAY);
+       int rc;
+
+       rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+                       ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+                       OBD_STATFS_NODELAY);
        if (!rc)
                return sprintf(buf, "%u\n", osfs.os_bsize);
 
@@ -483,11 +421,13 @@ static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
                                char *buf)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
        struct obd_statfs osfs;
-       int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
-                           cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
-                           OBD_STATFS_NODELAY);
+       int rc;
+
+       rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+                       ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+                       OBD_STATFS_NODELAY);
        if (!rc) {
                u32 blk_size = osfs.os_bsize >> 10;
                u64 result = osfs.os_blocks;
@@ -506,11 +446,13 @@ static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
                               char *buf)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
        struct obd_statfs osfs;
-       int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
-                           cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
-                           OBD_STATFS_NODELAY);
+       int rc;
+
+       rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+                       ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+                       OBD_STATFS_NODELAY);
        if (!rc) {
                u32 blk_size = osfs.os_bsize >> 10;
                u64 result = osfs.os_bfree;
@@ -529,11 +471,13 @@ static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
                                char *buf)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
        struct obd_statfs osfs;
-       int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
-                           cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
-                           OBD_STATFS_NODELAY);
+       int rc;
+
+       rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+                       ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+                       OBD_STATFS_NODELAY);
        if (!rc) {
                u32 blk_size = osfs.os_bsize >> 10;
                u64 result = osfs.os_bavail;
@@ -552,11 +496,13 @@ static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
                               char *buf)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
        struct obd_statfs osfs;
-       int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
-                           cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
-                           OBD_STATFS_NODELAY);
+       int rc;
+
+       rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+                       ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+                       OBD_STATFS_NODELAY);
        if (!rc)
                return sprintf(buf, "%llu\n", osfs.os_files);
 
@@ -568,11 +514,13 @@ static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
                              char *buf)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
        struct obd_statfs osfs;
-       int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
-                           cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
-                           OBD_STATFS_NODELAY);
+       int rc;
+
+       rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+                       ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+                       OBD_STATFS_NODELAY);
        if (!rc)
                return sprintf(buf, "%llu\n", osfs.os_ffree);
 
@@ -580,6 +528,25 @@ static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
 }
 LUSTRE_RO_ATTR(filesfree);
 
+ssize_t conn_uuid_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+       struct obd_device *obd = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+       struct ptlrpc_connection *conn;
+       ssize_t count;
+
+       LPROCFS_CLIMP_CHECK(obd);
+       conn = obd->u.cli.cl_import->imp_connection;
+       if (conn && obd->u.cli.cl_import)
+               count = sprintf(buf, "%s\n", conn->c_remote_uuid.uuid);
+       else
+               count = sprintf(buf, "%s\n", "<none>");
+
+       LPROCFS_CLIMP_EXIT(obd);
+       return count;
+}
+EXPORT_SYMBOL(conn_uuid_show);
+
 int lprocfs_server_uuid_seq_show(struct seq_file *m, void *data)
 {
        struct obd_device *obd = data;
@@ -746,16 +713,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
        lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
 }
 
-/**
- * Append a space separated list of current set flags to str.
- */
-#define flag2str(flag)                                         \
-       do {                                                            \
-               if (imp->imp_##flag) {                                  \
-                       seq_printf(m, "%s" #flag, first ? "" : ", ");   \
-                       first = false;                                  \
-               }                                                       \
-       } while (0)
 static void obd_import_flags2str(struct obd_import *imp, struct seq_file *m)
 {
        bool first = true;
@@ -765,19 +722,16 @@ static void obd_import_flags2str(struct obd_import *imp, struct seq_file *m)
                first = false;
        }
 
-       flag2str(invalid);
-       flag2str(deactive);
-       flag2str(replayable);
-       flag2str(delayed_recovery);
-       flag2str(no_lock_replay);
-       flag2str(vbr_failed);
-       flag2str(pingable);
-       flag2str(resend_replay);
-       flag2str(no_pinger_recover);
-       flag2str(need_mne_swab);
-       flag2str(connect_tried);
+       flag2str(imp, invalid);
+       flag2str(imp, deactive);
+       flag2str(imp, replayable);
+       flag2str(imp, delayed_recovery);
+       flag2str(imp, vbr_failed);
+       flag2str(imp, pingable);
+       flag2str(imp, resend_replay);
+       flag2str(imp, no_pinger_recover);
+       flag2str(imp, connect_tried);
 }
-#undef flag2str
 
 static const char *obd_connect_names[] = {
        /* flags names  */
@@ -841,17 +795,18 @@ static const char *obd_connect_names[] = {
        "multi_mod_rpcs",
        "dir_stripe",
        "subtree",
-       "lock_ahead",
+       "lockahead",
        "bulk_mbits",
        "compact_obdo",
        "second_flags",
        /* flags2 names */
        "file_secctx",
+       "lockaheadv2",
        NULL
 };
 
-static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags,
-                                     __u64 flags2, const char *sep)
+void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, __u64 flags2,
+                              const char *sep)
 {
        bool first = true;
        __u64 mask;
@@ -888,6 +843,7 @@ static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags,
                first = false;
        }
 }
+EXPORT_SYMBOL(obd_connect_seq_flags2str);
 
 int obd_connect_flags2str(char *page, int count, __u64 flags, __u64 flags2,
                          const char *sep)
@@ -924,8 +880,8 @@ int obd_connect_flags2str(char *page, int count, __u64 flags, __u64 flags2,
 }
 EXPORT_SYMBOL(obd_connect_flags2str);
 
-static void obd_connect_data_seqprint(struct seq_file *m,
-                                     struct obd_connect_data *ocd)
+void
+obd_connect_data_seqprint(struct seq_file *m, struct obd_connect_data *ocd)
 {
        __u64 flags;
 
@@ -1241,57 +1197,72 @@ static struct attribute *obd_def_attrs[] = {
 static void obd_sysfs_release(struct kobject *kobj)
 {
        struct obd_device *obd = container_of(kobj, struct obd_device,
-                                             obd_kobj);
+                                             obd_kset.kobj);
 
        complete(&obd->obd_kobj_unregister);
 }
 
-static struct kobj_type obd_ktype = {
-       .sysfs_ops      = &lustre_sysfs_ops,
-       .release        = obd_sysfs_release,
-};
-
-int
-lprocfs_obd_setup(struct obd_device *obd, bool uuid_only)
+int lprocfs_obd_setup(struct obd_device *obd, bool uuid_only)
 {
-       int rc = 0;
+       struct lprocfs_vars *debugfs_vars = NULL;
+       int rc;
 
-       LASSERT(obd != NULL);
-       LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
+       if (!obd || obd->obd_magic != OBD_DEVICE_MAGIC)
+               return -ENODEV;
 
-       if (uuid_only)
-               obd_ktype.default_attrs = obd_def_uuid_attrs;
-       else
-               obd_ktype.default_attrs = obd_def_attrs;
+       rc = kobject_set_name(&obd->obd_kset.kobj, "%s", obd->obd_name);
+       if (rc)
+               return rc;
+
+       obd->obd_ktype.sysfs_ops = &lustre_sysfs_ops;
+       obd->obd_ktype.release = obd_sysfs_release;
+       if (obd->obd_attrs)
+               obd->obd_ktype.default_attrs = obd->obd_attrs;
 
+       obd->obd_kset.kobj.parent = obd->obd_type->typ_kobj;
+       obd->obd_kset.kobj.ktype = &obd->obd_ktype;
        init_completion(&obd->obd_kobj_unregister);
-       rc = kobject_init_and_add(&obd->obd_kobj, &obd_ktype,
-                                 obd->obd_type->typ_kobj,
-                                 "%s", obd->obd_name);
+       rc = kset_register(&obd->obd_kset);
        if (rc)
                return rc;
 
-       if (obd->obd_attrs) {
-               rc = sysfs_create_group(&obd->obd_kobj, obd->obd_attrs);
-               if (rc) {
-                       kobject_put(&obd->obd_kobj);
-                       return rc;
-               }
+       if (uuid_only)
+               obd->obd_attrs_group.attrs = obd_def_uuid_attrs;
+       else
+               obd->obd_attrs_group.attrs = obd_def_attrs;
+
+       rc = sysfs_create_group(&obd->obd_kset.kobj, &obd->obd_attrs_group);
+       if (rc) {
+               kset_unregister(&obd->obd_kset);
+               return rc;
        }
 
-       if (obd->obd_proc_entry)
-               GOTO(already_registered, rc);
+       if (!obd->obd_type->typ_procroot)
+               debugfs_vars = obd->obd_vars;
+       obd->obd_debugfs_entry = ldebugfs_register(obd->obd_name,
+                                                  obd->obd_type->typ_debugfs_entry,
+                                                  debugfs_vars, obd);
+       if (IS_ERR_OR_NULL(obd->obd_debugfs_entry)) {
+               rc = obd->obd_debugfs_entry ? PTR_ERR(obd->obd_debugfs_entry)
+                                           : -ENOMEM;
+               CERROR("error %d setting up debugfs for %s\n",
+                      rc, obd->obd_name);
+               obd->obd_debugfs_entry = NULL;
+               lprocfs_obd_cleanup(obd);
+               return rc;
+       }
 
-       LASSERT(obd->obd_type->typ_procroot != NULL);
+       if (obd->obd_proc_entry || !obd->obd_type->typ_procroot)
+               GOTO(already_registered, rc);
 
        obd->obd_proc_entry = lprocfs_register(obd->obd_name,
                                               obd->obd_type->typ_procroot,
                                               obd->obd_vars, obd);
        if (IS_ERR(obd->obd_proc_entry)) {
-               kobject_put(&obd->obd_kobj);
                rc = PTR_ERR(obd->obd_proc_entry);
                CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
                obd->obd_proc_entry = NULL;
+               lprocfs_obd_cleanup(obd);
        }
 already_registered:
        return rc;
@@ -1314,8 +1285,13 @@ int lprocfs_obd_cleanup(struct obd_device *obd)
                obd->obd_proc_entry = NULL;
        }
 
-       kobject_put(&obd->obd_kobj);
+       if (!IS_ERR_OR_NULL(obd->obd_debugfs_entry))
+               ldebugfs_remove(&obd->obd_debugfs_entry);
+
+       sysfs_remove_group(&obd->obd_kset.kobj, &obd->obd_attrs_group);
+       kset_unregister(&obd->obd_kset);
        wait_for_completion(&obd->obd_kobj_unregister);
+
        return 0;
 }
 EXPORT_SYMBOL(lprocfs_obd_cleanup);
@@ -1580,7 +1556,7 @@ static int lprocfs_stats_seq_open(struct inode *inode, struct file *file)
        if (rc)
                return rc;
        seq = file->private_data;
-       seq->private = inode->i_private ? : PDE_DATA(inode);
+       seq->private = inode->i_private ? inode->i_private : PDE_DATA(inode);
        return 0;
 }
 
@@ -2165,26 +2141,6 @@ static int str_to_s64_internal(const char __user *buffer, unsigned long count,
 
 /**
  * Convert a user string into a signed 64 bit number. This function produces
- * an error when the value parsed from the string underflows or
- * overflows. This function accepts strings which contain digits and
- * optionally a decimal or hex strings which are prefixed with "0x".
- *
- * \param[in] buffer   string consisting of numbers and optionally a decimal
- * \param[in] count    buffer length
- * \param[in] val      if successful, the value represented by the string
- *
- * \retval             0 on success
- * \retval             negative number on error
- */
-int lprocfs_str_to_s64(const char __user *buffer, unsigned long count,
-                      __s64 *val)
-{
-       return str_to_s64_internal(buffer, count, val, 1, false);
-}
-EXPORT_SYMBOL(lprocfs_str_to_s64);
-
-/**
- * Convert a user string into a signed 64 bit number. This function produces
  * an error when the value parsed from the string times multiplier underflows or
  * overflows. This function only accepts strings that contains digits, an
  * optional decimal, and a char representing a unit at the end. If a unit is
@@ -2216,7 +2172,7 @@ int lprocfs_str_with_units_to_s64(const char __user *buffer,
 }
 EXPORT_SYMBOL(lprocfs_str_with_units_to_s64);
 
-static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
+char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
 {
        size_t l2;
 
@@ -2231,6 +2187,7 @@ static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
        }
        return NULL;
 }
+EXPORT_SYMBOL(lprocfs_strnstr);
 
 /**
  * Find the string \a name in the input \a buffer, and return a pointer to the
@@ -2396,7 +2353,7 @@ ssize_t lprocfs_obd_max_pages_per_rpc_seq_write(struct file *file,
        struct client_obd *cli = &dev->u.cli;
        struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
        int chunk_mask, rc;
-       __s64 val;
+       s64 val;
 
        rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '1');
        if (rc)
@@ -2428,6 +2385,57 @@ ssize_t lprocfs_obd_max_pages_per_rpc_seq_write(struct file *file,
 }
 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_write);
 
+ssize_t short_io_bytes_show(struct kobject *kobj, struct attribute *attr,
+                           char *buf)
+{
+       struct obd_device *dev = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+       struct client_obd *cli = &dev->u.cli;
+       int rc;
+
+       spin_lock(&cli->cl_loi_list_lock);
+       rc = sprintf(buf, "%d\n", cli->cl_short_io_bytes);
+       spin_unlock(&cli->cl_loi_list_lock);
+       return rc;
+}
+EXPORT_SYMBOL(short_io_bytes_show);
+
+/* Used to catch people who think they're specifying pages. */
+#define MIN_SHORT_IO_BYTES 64
+
+ssize_t short_io_bytes_store(struct kobject *kobj, struct attribute *attr,
+                            const char *buffer, size_t count)
+{
+       struct obd_device *dev = container_of(kobj, struct obd_device,
+                                             obd_kset.kobj);
+       struct client_obd *cli = &dev->u.cli;
+       u32 val;
+       int rc;
+
+       LPROCFS_CLIMP_CHECK(dev);
+
+       rc = kstrtouint(buffer, 0, &val);
+       if (rc)
+               GOTO(out, rc);
+
+       if (val < MIN_SHORT_IO_BYTES || val > OBD_MAX_SHORT_IO_BYTES)
+               GOTO(out, rc = -ERANGE);
+
+       rc = count;
+
+       spin_lock(&cli->cl_loi_list_lock);
+       if (val > (cli->cl_max_pages_per_rpc << PAGE_SHIFT))
+               rc = -ERANGE;
+       else
+               cli->cl_short_io_bytes = val;
+       spin_unlock(&cli->cl_loi_list_lock);
+
+out:
+       LPROCFS_CLIMP_EXIT(dev);
+       return rc;
+}
+EXPORT_SYMBOL(short_io_bytes_store);
+
 int lprocfs_wr_root_squash(const char __user *buffer, unsigned long count,
                           struct root_squash_info *squash, char *name)
 {