Whamcloud - gitweb
LU-3227 tests: fix for acl test
[fs/lustre-release.git] / lustre / obdclass / lprocfs_status.c
index 9b39be3..938cb7a 100644 (file)
@@ -288,25 +288,105 @@ static struct file_operations lprocfs_generic_fops = { };
 #ifdef HAVE_SERVER_SUPPORT
 int lprocfs_evict_client_open(struct inode *inode, struct file *f)
 {
-        struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
-        struct obd_device *obd = dp->data;
-
-        cfs_atomic_inc(&obd->obd_evict_inprogress);
+       struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
 
-        return 0;
+       atomic_inc(&obd->obd_evict_inprogress);
+       return 0;
 }
 
 int lprocfs_evict_client_release(struct inode *inode, struct file *f)
 {
-       struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
-       struct obd_device *obd = dp->data;
+       struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
 
-       cfs_atomic_dec(&obd->obd_evict_inprogress);
+       atomic_dec(&obd->obd_evict_inprogress);
        wake_up(&obd->obd_evict_inprogress_waitq);
 
        return 0;
 }
 
+#define BUFLEN (UUID_MAX + 5)
+
+#ifndef HAVE_ONLY_PROCFS_SEQ
+int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
+                           unsigned long count, void *data)
+{
+       struct obd_device *obd = data;
+       char              *kbuf;
+       char              *tmpbuf;
+
+       OBD_ALLOC(kbuf, BUFLEN);
+       if (kbuf == NULL)
+               return -ENOMEM;
+
+       /*
+        * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
+        * bytes into kbuf, to ensure that the string is NUL-terminated.
+        * UUID_MAX should include a trailing NUL already.
+        */
+       if (copy_from_user(kbuf, buffer,
+                          min_t(unsigned long, BUFLEN - 1, count))) {
+               count = -EFAULT;
+               goto out;
+       }
+       tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
+       class_incref(obd, __FUNCTION__, current);
+
+       if (strncmp(tmpbuf, "nid:", 4) == 0)
+               obd_export_evict_by_nid(obd, tmpbuf + 4);
+       else if (strncmp(tmpbuf, "uuid:", 5) == 0)
+               obd_export_evict_by_uuid(obd, tmpbuf + 5);
+       else
+               obd_export_evict_by_uuid(obd, tmpbuf);
+
+       class_decref(obd, __FUNCTION__, current);
+out:
+       OBD_FREE(kbuf, BUFLEN);
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_wr_evict_client);
+#endif
+
+ssize_t
+lprocfs_evict_client_seq_write(struct file *file, const char *buffer,
+                              size_t count, loff_t *off)
+{
+       struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
+       char *tmpbuf, *kbuf;
+
+       OBD_ALLOC(kbuf, BUFLEN);
+       if (kbuf == NULL)
+               return -ENOMEM;
+
+       /*
+        * OBD_ALLOC() will zero kbuf, but we only copy BUFLEN - 1
+        * bytes into kbuf, to ensure that the string is NUL-terminated.
+        * UUID_MAX should include a trailing NUL already.
+        */
+       if (copy_from_user(kbuf, buffer,
+                          min_t(unsigned long, BUFLEN - 1, count))) {
+               count = -EFAULT;
+               goto out;
+       }
+       tmpbuf = cfs_firststr(kbuf, min_t(unsigned long, BUFLEN - 1, count));
+       class_incref(obd, __FUNCTION__, current);
+
+       if (strncmp(tmpbuf, "nid:", 4) == 0)
+               obd_export_evict_by_nid(obd, tmpbuf + 4);
+       else if (strncmp(tmpbuf, "uuid:", 5) == 0)
+               obd_export_evict_by_uuid(obd, tmpbuf + 5);
+       else
+               obd_export_evict_by_uuid(obd, tmpbuf);
+
+       class_decref(obd, __FUNCTION__, current);
+
+out:
+       OBD_FREE(kbuf, BUFLEN);
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_evict_client_seq_write);
+
+#undef BUFLEN
+
 struct file_operations lprocfs_evict_client_fops = {
         .owner = THIS_MODULE,
         .read = lprocfs_fops_read,
@@ -652,7 +732,7 @@ EXPORT_SYMBOL(lprocfs_u64_seq_show);
 
 int lprocfs_atomic_seq_show(struct seq_file *m, void *data)
 {
-       cfs_atomic_t *atom = data;
+       atomic_t *atom = data;
        LASSERT(atom != NULL);
        return seq_printf(m, "%d\n", atomic_read(atom));
 }
@@ -662,7 +742,7 @@ ssize_t
 lprocfs_atomic_seq_write(struct file *file, const char *buffer,
                        size_t count, loff_t *off)
 {
-       cfs_atomic_t *atm = ((struct seq_file *)file->private_data)->private;
+       atomic_t *atm = ((struct seq_file *)file->private_data)->private;
        int val = 0;
        int rc;
 
@@ -673,7 +753,7 @@ lprocfs_atomic_seq_write(struct file *file, const char *buffer,
        if (val <= 0)
                return -ERANGE;
 
-       cfs_atomic_set(atm, val);
+       atomic_set(atm, val);
        return count;
 }
 EXPORT_SYMBOL(lprocfs_atomic_seq_write);
@@ -1279,6 +1359,17 @@ int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data)
 }
 EXPORT_SYMBOL(lprocfs_connect_flags_seq_show);
 
+#ifdef HAVE_SERVER_SUPPORT
+int lprocfs_num_exports_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_device *obd = data;
+
+       LASSERT(obd != NULL);
+       return seq_printf(m, "%u\n", obd->obd_num_exports);
+}
+EXPORT_SYMBOL(lprocfs_num_exports_seq_show);
+#endif
+
 #ifndef HAVE_ONLY_PROCFS_SEQ
 
 int lprocfs_rd_uint(char *page, char **start, off_t off,
@@ -1301,17 +1392,17 @@ EXPORT_SYMBOL(lprocfs_rd_u64);
 int lprocfs_rd_atomic(char *page, char **start, off_t off,
                    int count, int *eof, void *data)
 {
-        cfs_atomic_t *atom = data;
+       atomic_t *atom = data;
         LASSERT(atom != NULL);
         *eof = 1;
-        return snprintf(page, count, "%d\n", cfs_atomic_read(atom));
+       return snprintf(page, count, "%d\n", atomic_read(atom));
 }
 EXPORT_SYMBOL(lprocfs_rd_atomic);
 
 int lprocfs_wr_atomic(struct file *file, const char *buffer,
                       unsigned long count, void *data)
 {
-        cfs_atomic_t *atm = data;
+       atomic_t *atm = data;
         int val = 0;
         int rc;
 
@@ -1322,7 +1413,7 @@ int lprocfs_wr_atomic(struct file *file, const char *buffer,
         if (val <= 0)
                 return -ERANGE;
 
-        cfs_atomic_set(atm, val);
+       atomic_set(atm, val);
         return count;
 }
 EXPORT_SYMBOL(lprocfs_wr_atomic);
@@ -1589,7 +1680,7 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count,
                              libcfs_nid2str(imp->imp_connection->c_peer.nid),
                      imp->imp_conn_cnt,
                      imp->imp_generation,
-                     cfs_atomic_read(&imp->imp_inval_count));
+                     atomic_read(&imp->imp_inval_count));
        spin_unlock(&imp->imp_lock);
 
        if (obd->obd_svc_stats == NULL)
@@ -1610,9 +1701,9 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count,
                       "       unregistering: %u\n"
                       "       timeouts: %u\n"
                       "       avg_waittime: "LPU64" %s\n",
-                      cfs_atomic_read(&imp->imp_inflight),
-                      cfs_atomic_read(&imp->imp_unregistering),
-                      cfs_atomic_read(&imp->imp_timeouts),
+                     atomic_read(&imp->imp_inflight),
+                     atomic_read(&imp->imp_unregistering),
+                     atomic_read(&imp->imp_timeouts),
                      ret.lc_sum, header->lc_units);
 
         k = 0;
@@ -1794,6 +1885,7 @@ int lprocfs_rd_connect_flags(char *page, char **start, off_t off,
 }
 EXPORT_SYMBOL(lprocfs_rd_connect_flags);
 
+#ifdef HAVE_SERVER_SUPPORT
 int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
                            int *eof,  void *data)
 {
@@ -1804,6 +1896,7 @@ int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count,
         return snprintf(page, count, "%u\n", obd->obd_num_exports);
 }
 EXPORT_SYMBOL(lprocfs_rd_num_exports);
+#endif
 
 int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count,
                        int *eof, void *data)
@@ -1843,7 +1936,6 @@ lprocfs_seq_obd_setup(struct obd_device *obd)
        int rc = 0;
 
        LASSERT(obd != NULL);
-       LASSERT(obd->obd_vars != NULL);
        LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
        LASSERT(obd->obd_type->typ_procroot != NULL);
 
@@ -1881,7 +1973,7 @@ static void lprocfs_free_client_stats(struct nid_stat *client_stat)
        CDEBUG(D_CONFIG, "stat %p - data %p/%p\n", client_stat,
               client_stat->nid_proc, client_stat->nid_stats);
 
-        LASSERTF(cfs_atomic_read(&client_stat->nid_exp_ref_count) == 0,
+       LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0,
                  "nid %s:count %d\n", libcfs_nid2str(client_stat->nid),
                  atomic_read(&client_stat->nid_exp_ref_count));
 
@@ -2256,8 +2348,6 @@ void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs_async);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, packmd);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpackmd);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, create);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
@@ -2265,24 +2355,12 @@ void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr_async);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, merge_lvb);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, adjust_kms);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, preprw);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_cbdata);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, find_cbdata);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, extent_calc);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_init);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_connect);
         LPROCFS_OBD_OP_INIT(num_private_stats, stats, llog_finish);
@@ -2382,12 +2460,15 @@ void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats)
         LPROCFS_MD_OP_INIT(num_private_stats, stats, setattr);
        LPROCFS_MD_OP_INIT(num_private_stats, stats, fsync);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, readpage);
+       LPROCFS_MD_OP_INIT(num_private_stats, stats, read_entry);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, unlink);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, setxattr);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, getxattr);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, init_ea_size);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, get_lustre_md);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, free_lustre_md);
+       LPROCFS_MD_OP_INIT(num_private_stats, stats, update_lsm_md);
+       LPROCFS_MD_OP_INIT(num_private_stats, stats, merge_attr);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_open_replay_data);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, clear_open_replay_data);
         LPROCFS_MD_OP_INIT(num_private_stats, stats, set_lock_data);
@@ -2487,6 +2568,111 @@ void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats)
 }
 EXPORT_SYMBOL(lprocfs_init_ldlm_stats);
 
+#ifdef HAVE_SERVER_SUPPORT
+int lprocfs_exp_nid_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_export *exp = m->private;
+       LASSERT(exp != NULL);
+       return seq_printf(m, "%s\n", obd_export_nid2str(exp));
+}
+
+int lprocfs_exp_print_uuid_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+                               cfs_hlist_node_t *hnode, void *cb_data)
+
+{
+       struct obd_export *exp = cfs_hash_object(hs, hnode);
+       struct seq_file *m = cb_data;
+
+       if (exp->exp_nid_stats)
+               seq_printf(m, "%s\n", obd_uuid2str(&exp->exp_client_uuid));
+       return 0;
+}
+
+int lprocfs_exp_uuid_seq_show(struct seq_file *m, void *data)
+{
+       struct nid_stat *stats = m->private;
+       struct obd_device *obd = stats->nid_obd;
+
+       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
+                               lprocfs_exp_print_uuid_seq, m);
+       return 0;
+}
+LPROC_SEQ_FOPS_RO(lprocfs_exp_uuid);
+
+int lprocfs_exp_print_hash_seq(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+                               cfs_hlist_node_t *hnode, void *cb_data)
+
+{
+       struct seq_file *m = cb_data;
+       struct obd_export *exp = cfs_hash_object(hs, hnode);
+
+       if (exp->exp_lock_hash != NULL) {
+               cfs_hash_debug_header_seq(m);
+               cfs_hash_debug_str_seq(hs, m);
+       }
+       return 0;
+}
+
+int lprocfs_exp_hash_seq_show(struct seq_file *m, void *data)
+{
+       struct nid_stat *stats = m->private;
+       struct obd_device *obd = stats->nid_obd;
+
+       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
+                               lprocfs_exp_print_hash_seq, m);
+       return 0;
+}
+LPROC_SEQ_FOPS_RO(lprocfs_exp_hash);
+
+int lprocfs_nid_stats_clear_seq_show(struct seq_file *m, void *data)
+{
+       return seq_printf(m, "%s\n", "Write into this file to clear all nid "
+                               "stats and stale nid entries");
+}
+EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_show);
+
+static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
+{
+       struct nid_stat *stat = obj;
+       ENTRY;
+
+       CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count));
+       if (atomic_read(&stat->nid_exp_ref_count) == 1) {
+               /* object has only hash references. */
+               spin_lock(&stat->nid_obd->obd_nid_lock);
+               cfs_list_move(&stat->nid_list, data);
+               spin_unlock(&stat->nid_obd->obd_nid_lock);
+               RETURN(1);
+       }
+       /* we has reference to object - only clear data*/
+       if (stat->nid_stats)
+               lprocfs_clear_stats(stat->nid_stats);
+
+       RETURN(0);
+}
+
+ssize_t
+lprocfs_nid_stats_clear_seq_write(struct file *file, const char *buffer,
+                                       size_t count, loff_t *off)
+{
+       struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
+       struct nid_stat *client_stat;
+       CFS_LIST_HEAD(free_list);
+
+       cfs_hash_cond_del(obd->obd_nid_stats_hash,
+                               lprocfs_nid_stats_clear_write_cb, &free_list);
+
+       while (!cfs_list_empty(&free_list)) {
+               client_stat = cfs_list_entry(free_list.next, struct nid_stat,
+                                               nid_list);
+               cfs_list_del_init(&client_stat->nid_list);
+               lprocfs_free_client_stats(client_stat);
+       }
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_nid_stats_clear_seq_write);
+
+#ifndef HAVE_ONLY_PROCFS_SEQ
 int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
                          int *eof,  void *data)
 {
@@ -2497,10 +2683,10 @@ int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
 }
 
 struct exp_uuid_cb_data {
-        char                   *page;
-        int                     count;
-        int                    *eof;
-        int                    *len;
+       char                   *page;
+       int                     count;
+       int                    *eof;
+       int                    *len;
 };
 
 static void
@@ -2589,26 +2775,6 @@ int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
 }
 EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
 
-static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
-{
-        struct nid_stat *stat = obj;
-        ENTRY;
-
-        CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count));
-        if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) {
-                /* object has only hash references. */
-               spin_lock(&stat->nid_obd->obd_nid_lock);
-               cfs_list_move(&stat->nid_list, data);
-               spin_unlock(&stat->nid_obd->obd_nid_lock);
-                RETURN(1);
-        }
-        /* we has reference to object - only clear data*/
-        if (stat->nid_stats)
-                lprocfs_clear_stats(stat->nid_stats);
-
-        RETURN(0);
-}
-
 int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
                                   unsigned long count, void *data)
 {
@@ -2629,8 +2795,8 @@ int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
         return count;
 }
 EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
+#endif
 
-#ifdef HAVE_SERVER_SUPPORT
 int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
 {
         struct nid_stat *new_stat, *old_stat;
@@ -2670,18 +2836,24 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
         new_stat->nid               = *nid;
         new_stat->nid_obd           = exp->exp_obd;
         /* we need set default refcount to 1 to balance obd_disconnect */
-        cfs_atomic_set(&new_stat->nid_exp_ref_count, 1);
+       atomic_set(&new_stat->nid_exp_ref_count, 1);
 
         old_stat = cfs_hash_findadd_unique(obd->obd_nid_stats_hash,
                                            nid, &new_stat->nid_hash);
         CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
                old_stat, libcfs_nid2str(*nid),
-               cfs_atomic_read(&new_stat->nid_exp_ref_count));
+              atomic_read(&new_stat->nid_exp_ref_count));
 
        /* Return -EALREADY here so that we know that the /proc
         * entry already has been created */
        if (old_stat != new_stat) {
-               nidstat_putref(old_stat);
+               spin_lock(&exp->exp_lock);
+               if (exp->exp_nid_stats) {
+                       LASSERT(exp->exp_nid_stats == old_stat);
+                       nidstat_putref(exp->exp_nid_stats);
+               }
+               exp->exp_nid_stats = old_stat;
+               spin_unlock(&exp->exp_lock);
                GOTO(destroy_new, rc = -EALREADY);
        }
         /* not found - create */
@@ -2689,11 +2861,17 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
         if (buffer == NULL)
                 GOTO(destroy_new, rc = -ENOMEM);
 
-        memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
+       memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE);
+#ifndef HAVE_ONLY_PROCFS_SEQ
         new_stat->nid_proc = lprocfs_register(buffer,
-                                              obd->obd_proc_exports_entry,
-                                              NULL, NULL);
-        OBD_FREE(buffer, LNET_NIDSTR_SIZE);
+                                               obd->obd_proc_exports_entry,
+                                               NULL, NULL);
+#else
+       new_stat->nid_proc = lprocfs_seq_register(buffer,
+                                               obd->obd_proc_exports_entry,
+                                               NULL, NULL);
+#endif
+       OBD_FREE(buffer, LNET_NIDSTR_SIZE);
 
        if (IS_ERR(new_stat->nid_proc)) {
                rc = PTR_ERR(new_stat->nid_proc);
@@ -2703,16 +2881,26 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid)
                GOTO(destroy_new_ns, rc);
        }
 
+#ifndef HAVE_ONLY_PROCFS_SEQ
         entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
                                    lprocfs_exp_rd_uuid, NULL, new_stat, NULL);
+#else
+       entry = lprocfs_add_simple(new_stat->nid_proc, "uuid",
+                                       new_stat, &lprocfs_exp_uuid_fops);
+#endif
         if (IS_ERR(entry)) {
                 CWARN("Error adding the NID stats file\n");
                 rc = PTR_ERR(entry);
                 GOTO(destroy_new_ns, rc);
         }
 
+#ifndef HAVE_ONLY_PROCFS_SEQ
         entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
                                    lprocfs_exp_rd_hash, NULL, new_stat, NULL);
+#else
+       entry = lprocfs_add_simple(new_stat->nid_proc, "hash",
+                                       new_stat, &lprocfs_exp_hash_fops);
+#endif
         if (IS_ERR(entry)) {
                 CWARN("Error adding the hash file\n");
                 rc = PTR_ERR(entry);
@@ -3117,6 +3305,181 @@ void lprocfs_oh_clear(struct obd_histogram *oh)
 }
 EXPORT_SYMBOL(lprocfs_oh_clear);
 
+#ifdef HAVE_SERVER_SUPPORT
+int lprocfs_hash_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_device *obd = m->private;
+       int c = 0;
+
+       if (obd == NULL)
+               return 0;
+
+       c += cfs_hash_debug_header_seq(m);
+       c += cfs_hash_debug_str_seq(obd->obd_uuid_hash, m);
+       c += cfs_hash_debug_str_seq(obd->obd_nid_hash, m);
+       c += cfs_hash_debug_str_seq(obd->obd_nid_stats_hash, m);
+       return c;
+}
+EXPORT_SYMBOL(lprocfs_hash_seq_show);
+
+int lprocfs_recovery_status_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_device *obd = m->private;
+
+       LASSERT(obd != NULL);
+
+       seq_printf(m, "status: ");
+       if (obd->obd_max_recoverable_clients == 0) {
+               seq_printf(m, "INACTIVE\n");
+               goto out;
+       }
+
+       /* sampled unlocked, but really... */
+       if (obd->obd_recovering == 0) {
+               seq_printf(m, "COMPLETE\n");
+               seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
+               seq_printf(m, "recovery_duration: %lu\n",
+                               obd->obd_recovery_end - obd->obd_recovery_start);
+               /* Number of clients that have completed recovery */
+               seq_printf(m, "completed_clients: %d/%d\n",
+                               obd->obd_max_recoverable_clients -
+                               obd->obd_stale_clients,
+                               obd->obd_max_recoverable_clients);
+               seq_printf(m, "replayed_requests: %d\n",
+                               obd->obd_replayed_requests);
+               seq_printf(m, "last_transno: "LPD64"\n",
+                               obd->obd_next_recovery_transno - 1);
+               seq_printf(m, "VBR: %s\n", obd->obd_version_recov ?
+                               "ENABLED" : "DISABLED");
+               seq_printf(m, "IR: %s\n", obd->obd_no_ir ?
+                               "DISABLED" : "ENABLED");
+               goto out;
+       }
+
+       seq_printf(m, "RECOVERING\n");
+       seq_printf(m, "recovery_start: %lu\n", obd->obd_recovery_start);
+       seq_printf(m, "time_remaining: %lu\n",
+                       cfs_time_current_sec() >=
+                       obd->obd_recovery_start +
+                       obd->obd_recovery_timeout ? 0 :
+                       obd->obd_recovery_start +
+                       obd->obd_recovery_timeout -
+                       cfs_time_current_sec());
+       seq_printf(m, "connected_clients: %d/%d\n",
+                       atomic_read(&obd->obd_connected_clients),
+                       obd->obd_max_recoverable_clients);
+       /* Number of clients that have completed recovery */
+       seq_printf(m, "req_replay_clients: %d\n",
+                       atomic_read(&obd->obd_req_replay_clients));
+       seq_printf(m, "lock_repay_clients: %d\n",
+                       atomic_read(&obd->obd_lock_replay_clients));
+       seq_printf(m, "completed_clients: %d\n",
+                       atomic_read(&obd->obd_connected_clients) -
+                       atomic_read(&obd->obd_lock_replay_clients));
+       seq_printf(m, "evicted_clients: %d\n", obd->obd_stale_clients);
+       seq_printf(m, "replayed_requests: %d\n", obd->obd_replayed_requests);
+       seq_printf(m, "queued_requests: %d\n",
+                       obd->obd_requests_queued_for_recovery);
+       seq_printf(m, "next_transno: "LPD64"\n",
+                       obd->obd_next_recovery_transno);
+out:
+       return 0;
+}
+EXPORT_SYMBOL(lprocfs_recovery_status_seq_show);
+
+int lprocfs_ir_factor_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_device *obd = m->private;
+
+       LASSERT(obd != NULL);
+       return seq_printf(m, "%d\n", obd->obd_recovery_ir_factor);
+}
+EXPORT_SYMBOL(lprocfs_ir_factor_seq_show);
+
+ssize_t
+lprocfs_ir_factor_seq_write(struct file *file, const char *buffer,
+                               size_t count, loff_t *off)
+{
+       struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
+       int val, rc;
+
+       LASSERT(obd != NULL);
+       rc = lprocfs_write_helper(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       if (val < OBD_IR_FACTOR_MIN || val > OBD_IR_FACTOR_MAX)
+               return -EINVAL;
+
+       obd->obd_recovery_ir_factor = val;
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_ir_factor_seq_write);
+
+int lprocfs_recovery_time_soft_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_device *obd = m->private;
+
+       LASSERT(obd != NULL);
+       return seq_printf(m, "%d\n", obd->obd_recovery_timeout);
+}
+EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_show);
+
+ssize_t
+lprocfs_recovery_time_soft_seq_write(struct file *file, const char *buffer,
+                                       size_t count, loff_t *off)
+{
+       struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
+       int val, rc;
+
+       LASSERT(obd != NULL);
+       rc = lprocfs_write_helper(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       obd->obd_recovery_timeout = val;
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_recovery_time_soft_seq_write);
+
+int lprocfs_recovery_time_hard_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_device *obd = m->private;
+
+       LASSERT(obd != NULL);
+       return seq_printf(m, "%u\n", obd->obd_recovery_time_hard);
+}
+EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_show);
+
+ssize_t
+lprocfs_recovery_time_hard_seq_write(struct file *file, const char *buffer,
+                                       size_t count, loff_t *off)
+{
+       struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
+       int val, rc;
+
+       LASSERT(obd != NULL);
+       rc = lprocfs_write_helper(buffer, count, &val);
+       if (rc)
+               return rc;
+
+       obd->obd_recovery_time_hard = val;
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_recovery_time_hard_seq_write);
+
+int lprocfs_target_instance_seq_show(struct seq_file *m, void *data)
+{
+       struct obd_device *obd = m->private;
+       struct obd_device_target *target = &obd->u.obt;
+
+       LASSERT(obd != NULL);
+       LASSERT(target->obt_magic == OBT_MAGIC);
+       return seq_printf(m, "%u\n", obd->u.obt.obt_instance);
+}
+EXPORT_SYMBOL(lprocfs_target_instance_seq_show);
+
+#ifndef HAVE_ONLY_PROCFS_SEQ
 int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
                         int count, int *eof, void *data)
 {
@@ -3135,7 +3498,6 @@ int lprocfs_obd_rd_hash(char *page, char **start, off_t off,
 }
 EXPORT_SYMBOL(lprocfs_obd_rd_hash);
 
-#ifdef HAVE_SERVER_SUPPORT
 int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
                                    int count, int *eof, void *data)
 {
@@ -3224,21 +3586,21 @@ int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
                                  cfs_time_current_sec()) <= 0)
                 goto out;
         if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
-                                 cfs_atomic_read(&obd->obd_connected_clients),
+                                atomic_read(&obd->obd_connected_clients),
                                  obd->obd_max_recoverable_clients) <= 0)
                 goto out;
         /* Number of clients that have completed recovery */
         if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n",
-                                 cfs_atomic_read(&obd->obd_req_replay_clients))
+                                atomic_read(&obd->obd_req_replay_clients))
                 <= 0)
                 goto out;
         if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
-                                 cfs_atomic_read(&obd->obd_lock_replay_clients))
+                                atomic_read(&obd->obd_lock_replay_clients))
                 <=0)
                 goto out;
         if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
-                                 cfs_atomic_read(&obd->obd_connected_clients) -
-                                 cfs_atomic_read(&obd->obd_lock_replay_clients))
+                                atomic_read(&obd->obd_connected_clients) -
+                                atomic_read(&obd->obd_lock_replay_clients))
                 <=0)
                 goto out;
         if (lprocfs_obd_snprintf(&page, size, &len,"evicted_clients: %d\n",
@@ -3261,7 +3623,6 @@ out:
         return min(count, len - (int)off);
 }
 EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
-#endif
 
 int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
                              int count, int *eof, void *data)
@@ -3346,6 +3707,21 @@ int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
 }
 EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard);
 
+int lprocfs_target_rd_instance(char *page, char **start, off_t off,
+                              int count, int *eof, void *data)
+{
+       struct obd_device *obd = (struct obd_device *)data;
+       struct obd_device_target *target = &obd->u.obt;
+
+       LASSERT(obd != NULL);
+       LASSERT(target->obt_magic == OBT_MAGIC);
+       *eof = 1;
+       return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
+}
+EXPORT_SYMBOL(lprocfs_target_rd_instance);
+#endif /* HAVE_ONLY_PROCFS_SEQ */
+#endif /* HAVE_SERVER_SUPPORT */
+
 int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
                                      int count, int *eof, void *data)
 {
@@ -3372,19 +3748,4 @@ int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);
-
-#ifdef HAVE_SERVER_SUPPORT
-int lprocfs_target_rd_instance(char *page, char **start, off_t off,
-                               int count, int *eof, void *data)
-{
-        struct obd_device *obd = (struct obd_device *)data;
-        struct obd_device_target *target = &obd->u.obt;
-
-        LASSERT(obd != NULL);
-        LASSERT(target->obt_magic == OBT_MAGIC);
-        *eof = 1;
-        return snprintf(page, count, "%u\n", obd->u.obt.obt_instance);
-}
-EXPORT_SYMBOL(lprocfs_target_rd_instance);
-#endif
 #endif /* LPROCFS*/