Whamcloud - gitweb
LU-473 llite: improve error for 2.x cli + 1.8 srv
[fs/lustre-release.git] / lustre / obdclass / lprocfs_status.c
index 87e4277..eed7097 100644 (file)
@@ -30,6 +30,9 @@
  * Use is subject to license terms.
  */
 /*
+ * Copyright (c) 2011 Whamcloud, Inc.
+ */
+/*
  * This file is part of Lustre, http://www.lustre.org/
  * Lustre is a trademark of Sun Microsystems, Inc.
  *
@@ -92,9 +95,9 @@ struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
 {
         struct proc_dir_entry *temp;
 
-        LPROCFS_ENTRY();
+        LPROCFS_SRCH_ENTRY();
         temp = __lprocfs_srch(head, name);
-        LPROCFS_EXIT();
+        LPROCFS_SRCH_EXIT();
         return temp;
 }
 
@@ -401,9 +404,23 @@ void lprocfs_remove(struct proc_dir_entry **rooth)
                          "0x%p  %s/%s len %d\n", rm_entry, temp->name,
                          rm_entry->name, (int)strlen(rm_entry->name));
 
+#ifdef HAVE_PROCFS_USERS
+                /* if procfs uses user count to synchronize deletion of
+                 * proc entry, there is no protection for rm_entry->data,
+                 * then lprocfs_fops_read and lprocfs_fops_write maybe
+                 * call proc_dir_entry->read_proc (or write_proc) with
+                 * proc_dir_entry->data == NULL, then cause kernel Oops.
+                 * see bug19706 for detailed information */
+
+                /* procfs won't free rm_entry->data if it isn't a LINK,
+                 * and Lustre won't use rm_entry->data if it is a LINK */
+                if (S_ISLNK(rm_entry->mode))
+                        rm_entry->data = NULL;
+#else
                 /* Now, the rm_entry->deleted flags is protected
                  * by _lprocfs_lock. */
                 rm_entry->data = NULL;
+#endif
                 remove_proc_entry(rm_entry->name, temp);
                 if (temp == parent)
                         break;
@@ -701,10 +718,7 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
 
         cnt->lc_min = LC_MIN_INIT;
 
-        if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU)
-                num_cpu = 1;
-        else
-                num_cpu = cfs_num_possible_cpus();
+        num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
 
         for (i = 0; i < num_cpu; i++) {
                 percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx];
@@ -731,6 +745,7 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
         }
 
         cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units;
+        lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
 }
 
 /**
@@ -793,10 +808,12 @@ static const char *obd_connect_names[] = {
         "large_ea",
         "full20",
         "layout_lock",
+        "64bithash",
+        "object_max_bytes",
         NULL
 };
 
-static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
+int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
 {
         __u64 mask = 1;
         int i, ret = 0;
@@ -812,6 +829,7 @@ static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep)
                                 ret ? sep : "", flags & ~(mask - 1));
         return ret;
 }
+EXPORT_SYMBOL(obd_connect_flags2str);
 
 int lprocfs_rd_import(char *page, char **start, off_t off, int count,
                       int *eof, void *data)
@@ -1122,8 +1140,8 @@ static void lprocfs_free_client_stats(struct nid_stat *client_stat)
                client_stat->nid_brw_stats);
 
         LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
-                 "count %d\n",
-                 cfs_atomic_read(&client_stat->nid_exp_ref_count));
+                 "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
+                 atomic_read(&client_stat->nid_exp_ref_count));
 
         cfs_hlist_del_init(&client_stat->nid_hash);
 
@@ -1258,7 +1276,7 @@ void lprocfs_clear_stats(struct lprocfs_stats *stats)
                 }
         }
 
-        lprocfs_stats_unlock(stats);
+        lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
 }
 
 static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf,
@@ -1414,7 +1432,7 @@ void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
                 c->lc_units = units;
         }
 
-        lprocfs_stats_unlock(stats);
+        lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU);
 }
 EXPORT_SYMBOL(lprocfs_counter_init);
 
@@ -1718,13 +1736,15 @@ int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
         struct exp_uuid_cb_data *data = cb_data;
         struct obd_export       *exp = cfs_hash_object(hs, hnode);
 
-        LASSERT(hs == exp->exp_lock_hash);
-        if (!*data->len) {
-                *data->len += cfs_hash_debug_header(data->page,
-                                                    data->count);
+        if (exp->exp_lock_hash != NULL) {
+                if (!*data->len) {
+                        *data->len += cfs_hash_debug_header(data->page,
+                                                            data->count);
+                }
+                *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
+                                                 data->count);
         }
-        *data->len += cfs_hash_debug_str(hs, data->page + *data->len,
-                                         data->count);
+
         return 0;
 }
 
@@ -1801,8 +1821,7 @@ int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
 }
 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
 
-int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int reconnect,
-                      int *newnid)
+int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
 {
         struct nid_stat *new_stat, *old_stat;
         struct obd_device *obd = NULL;
@@ -1842,15 +1861,16 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int reconnect,
                old_stat, libcfs_nid2str(*nid),
                cfs_atomic_read(&new_stat->nid_exp_ref_count));
 
+        /* We need to release old stats because lprocfs_exp_cleanup() hasn't
+         * been and will never be called. */
+        if (exp->exp_nid_stats) {
+                nidstat_putref(exp->exp_nid_stats);
+                exp->exp_nid_stats = NULL;
+        }
+
         /* Return -EALREADY here so that we know that the /proc
          * entry already has been created */
         if (old_stat != new_stat) {
-                /* if this connects to the existing export of same nid,
-                 * we need to release old stats for obd_disconnect won't
-                 * balance the reference gotten in "cfs_hash_findadd_uinque" */
-                if (reconnect && exp->exp_nid_stats)
-                        nidstat_putref(old_stat);
-
                 exp->exp_nid_stats = old_stat;
                 GOTO(destroy_new, rc = -EALREADY);
         }
@@ -2364,6 +2384,46 @@ int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off,
 }
 EXPORT_SYMBOL(lprocfs_obd_rd_mntdev);
 
+int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
+                                     int count, int *eof, void *data)
+{
+        struct obd_device *dev = data;
+        struct client_obd *cli = &dev->u.cli;
+        int rc;
+
+        client_obd_list_lock(&cli->cl_loi_list_lock);
+        rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
+        client_obd_list_unlock(&cli->cl_loi_list_lock);
+        return rc;
+}
+EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc);
+
+int lprocfs_obd_wr_max_pages_per_rpc(struct file *file, const char *buffer,
+                                     unsigned long count, void *data)
+{
+        struct obd_device *dev = data;
+        struct client_obd *cli = &dev->u.cli;
+        struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
+        int val, rc;
+
+        rc = lprocfs_write_helper(buffer, count, &val);
+        if (rc)
+                return rc;
+
+        LPROCFS_CLIMP_CHECK(dev);
+        if (val < 1 || val > ocd->ocd_brw_size >> CFS_PAGE_SHIFT) {
+                LPROCFS_CLIMP_EXIT(dev);
+                return -ERANGE;
+        }
+        client_obd_list_lock(&cli->cl_loi_list_lock);
+        cli->cl_max_pages_per_rpc = val;
+        client_obd_list_unlock(&cli->cl_loi_list_lock);
+
+        LPROCFS_CLIMP_EXIT(dev);
+        return count;
+}
+EXPORT_SYMBOL(lprocfs_obd_wr_max_pages_per_rpc);
+
 EXPORT_SYMBOL(lprocfs_register);
 EXPORT_SYMBOL(lprocfs_srch);
 EXPORT_SYMBOL(lprocfs_remove);