Whamcloud - gitweb
LU-1330 obdclass: splits server-side procfs handling 77/2677/16
authorLiu Xuezhao <xuezhao.liu@emc.com>
Mon, 5 May 2014 13:16:36 +0000 (09:16 -0400)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 20 May 2014 04:04:51 +0000 (04:04 +0000)
Moves some server-side procfs routines to lprocfs_status_server.c.
Only compiles lprocfs_jobstats.c for server.

Signed-off-by: Liu Xuezhao <xuezhao.liu@emc.com>
Signed-off-by: Peng Tao <tao.peng@emc.com>
Signed-off-by: James Simmons <uja.ornl@gmail.com>
Change-Id: I32d5feda324bf76386a176e8bd78d74e59643f43
Reviewed-on: http://review.whamcloud.com/2677
Reviewed-by: Bob Glossman <bob.glossman@intel.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
lustre/include/lprocfs_status.h
lustre/obdclass/Makefile.in
lustre/obdclass/lprocfs_status.c
lustre/obdclass/lprocfs_status_server.c [new file with mode: 0644]

index 42cec9e..4cb3112 100644 (file)
@@ -604,16 +604,17 @@ extern int lprocfs_add_clear_entry(struct obd_device * obd,
 #ifdef HAVE_SERVER_SUPPORT
 extern int lprocfs_exp_setup(struct obd_export *exp,
                              lnet_nid_t *peer_nid, int *newnid);
-#endif
 extern int lprocfs_exp_cleanup(struct obd_export *exp);
-extern cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
-                                                char *name,
+#else
+static inline int lprocfs_exp_cleanup(struct obd_export *exp)
+{ return 0; }
+#endif
+extern struct proc_dir_entry *
+lprocfs_add_simple(struct proc_dir_entry *root, char *name,
 #ifndef HAVE_ONLY_PROCFS_SEQ
-                                               read_proc_t *read_proc,
-                                               write_proc_t *write_proc,
+                  read_proc_t *read_proc, write_proc_t *write_proc,
 #endif
-                                                void *data,
-                                                struct file_operations *fops);
+                  void *data, const struct file_operations *fops);
 extern struct proc_dir_entry *
 lprocfs_add_symlink(const char *name, struct proc_dir_entry *parent,
                     const char *format, ...);
@@ -666,9 +667,9 @@ extern int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list);
 extern int lprocfs_seq_obd_setup(struct obd_device *dev);
 extern int lprocfs_obd_cleanup(struct obd_device *obd);
 #ifdef HAVE_SERVER_SUPPORT
-extern struct file_operations lprocfs_evict_client_fops;
+extern const struct file_operations lprocfs_evict_client_fops;
 #endif
-extern int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, const char *name,
+extern int lprocfs_seq_create(struct proc_dir_entry *parent, const char *name,
                              mode_t mode,
                              const struct file_operations *seq_fops,
                              void *data);
@@ -742,6 +743,10 @@ lprocfs_timeouts_seq_write(struct file *file, const char *buffer,
                           size_t count, loff_t *off);
 #ifndef HAVE_ONLY_PROCFS_SEQ
 #ifdef HAVE_SERVER_SUPPORT
+extern ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
+                                size_t size, loff_t *ppos);
+extern ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
+                                 size_t size, loff_t *ppos);
 extern int lprocfs_wr_evict_client(struct file *file, const char *buffer,
                                    unsigned long count, void *data);
 #endif
@@ -1126,12 +1131,12 @@ static inline int lprocfs_exp_setup(struct obd_export *exp,lnet_nid_t *peer_nid,
 #endif
 static inline int lprocfs_exp_cleanup(struct obd_export *exp)
 { return 0; }
-static inline cfs_proc_dir_entry_t *
+static inline struct proc_dir_entry *
 lprocfs_add_simple(struct proc_dir_entry *root, char *name,
 #ifndef HAVE_ONLY_PROCFS_SEQ
                   read_proc_t *read_proc, write_proc_t *write_proc,
 #endif
-                  void *data, struct file_operations *fops)
+                  void *data, const struct file_operations *fops)
 {return 0; }
 static inline struct proc_dir_entry *
 lprocfs_add_symlink(const char *name, struct proc_dir_entry *parent,
index 0276c98..d6aeb7c 100644 (file)
@@ -16,7 +16,7 @@ obdclass-all-objs += acl.o idmap.o
 obdclass-all-objs += md_attrs.o linkea.o
 obdclass-all-objs += lu_ucred.o
 
-@SERVER_TRUE@obdclass-all-objs += lprocfs_jobstats.o
+@SERVER_TRUE@obdclass-all-objs += lprocfs_status_server.o lprocfs_jobstats.o
 @SERVER_TRUE@obdclass-all-objs += obd_mount_server.o
 
 obdclass-objs := $(obdclass-linux-objs) $(obdclass-all-objs)
@@ -25,7 +25,7 @@ EXTRA_PRE_CFLAGS := -I@LINUX@/fs -I@LDISKFS_DIR@ -I@LDISKFS_DIR@/ldiskfs
 
 EXTRA_DIST = $(obdclass-all-objs:.o=.c) llog_test.c llog_internal.h
 EXTRA_DIST += cl_internal.h local_storage.h
-@SERVER_FALSE@EXTRA_DIST += lprocfs_jobstats.c
+@SERVER_FALSE@EXTRA_DIST += lprocfs_jobstats.c lprocfs_status_server.c
 @SERVER_FALSE@EXTRA_DIST += obd_mount_server.c
 
 @INCLUDE_RULES@
index dcc00a8..4226176 100644 (file)
@@ -68,79 +68,15 @@ int lprocfs_seq_release(struct inode *inode, struct file *file)
 }
 EXPORT_SYMBOL(lprocfs_seq_release);
 
+struct proc_dir_entry *
+lprocfs_add_simple(struct proc_dir_entry *root, char *name,
 #ifndef HAVE_ONLY_PROCFS_SEQ
-/* for b=10866, global variable */
-DECLARE_RWSEM(_lprocfs_lock);
-EXPORT_SYMBOL(_lprocfs_lock);
-
-static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
-                                             const char *name)
-{
-        struct proc_dir_entry *temp;
-
-        if (head == NULL)
-                return NULL;
-
-        temp = head->subdir;
-        while (temp != NULL) {
-                if (strcmp(temp->name, name) == 0) {
-                        return temp;
-                }
-
-                temp = temp->next;
-        }
-        return NULL;
-}
-
-struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
-                                    const char *name)
-{
-        struct proc_dir_entry *temp;
-
-        LPROCFS_SRCH_ENTRY();
-        temp = __lprocfs_srch(head, name);
-        LPROCFS_SRCH_EXIT();
-        return temp;
-}
-EXPORT_SYMBOL(lprocfs_srch);
-
-/* lprocfs API calls */
-
-/* Function that emulates snprintf but also has the side effect of advancing
-   the page pointer for the next write into the buffer, incrementing the total
-   length written to the buffer, and decrementing the size left in the
-   buffer. */
-#ifdef HAVE_SERVER_SUPPORT
-static int lprocfs_obd_snprintf(char **page, int end, int *len,
-                                const char *format, ...)
-{
-        va_list list;
-        int n;
-
-        if (*len >= end)
-                return 0;
-
-        va_start(list, format);
-        n = vsnprintf(*page, end - *len, format, list);
-        va_end(list);
-
-        *page += n; *len += n;
-        return n;
-}
-#endif /* HAVE_SERVER_SUPPORT */
-#endif /* HAVE_ONLY_PROCFS_SEQ */
-
-cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root,
-                                         char *name,
-#ifndef HAVE_ONLY_PROCFS_SEQ
-                                        read_proc_t *read_proc,
-                                        write_proc_t *write_proc,
+                  read_proc_t *read_proc, write_proc_t *write_proc,
 #endif
-                                         void *data,
-                                         struct file_operations *fops)
+                  void *data, const struct file_operations *fops)
 {
-        cfs_proc_dir_entry_t *proc;
-        mode_t mode = 0;
+       struct proc_dir_entry *proc;
+       mode_t mode = 0;
 
         if (root == NULL || name == NULL)
                 return ERR_PTR(-EINVAL);
@@ -210,9 +146,12 @@ struct proc_dir_entry *lprocfs_add_symlink(const char *name,
 }
 EXPORT_SYMBOL(lprocfs_add_symlink);
 
-#ifndef HAVE_ONLY_PROCFS_SEQ
-static ssize_t lprocfs_fops_read(struct file *f, char __user *buf,
-                                 size_t size, loff_t *ppos)
+#ifdef HAVE_ONLY_PROCFS_SEQ
+static const struct file_operations lprocfs_generic_fops = { };
+#else
+
+ssize_t
+lprocfs_fops_read(struct file *f, char __user *buf, size_t size, loff_t *ppos)
 {
         struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
         char *page, *start = NULL;
@@ -263,8 +202,9 @@ out:
         return rc;
 }
 
-static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf,
-                                  size_t size, loff_t *ppos)
+ssize_t
+lprocfs_fops_write(struct file *f, const char __user *buf, size_t size,
+                  loff_t *ppos)
 {
         struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode);
         int rc = -EIO;
@@ -281,123 +221,40 @@ static struct file_operations lprocfs_generic_fops = {
         .read = lprocfs_fops_read,
         .write = lprocfs_fops_write,
 };
-#else
-static struct file_operations lprocfs_generic_fops = { };
-#endif
-
-#ifdef HAVE_SERVER_SUPPORT
-int lprocfs_evict_client_open(struct inode *inode, struct file *f)
-{
-       struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
-
-       atomic_inc(&obd->obd_evict_inprogress);
-       return 0;
-}
 
-int lprocfs_evict_client_release(struct inode *inode, struct file *f)
-{
-       struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
-
-       atomic_dec(&obd->obd_evict_inprogress);
-       wake_up(&obd->obd_evict_inprogress_waitq);
-
-       return 0;
-}
-
-#define BUFLEN (UUID_MAX + 5)
+/* for b=10866, global variable */
+DECLARE_RWSEM(_lprocfs_lock);
+EXPORT_SYMBOL(_lprocfs_lock);
 
-#ifndef HAVE_ONLY_PROCFS_SEQ
-int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
-                           unsigned long count, void *data)
+static struct proc_dir_entry *__lprocfs_srch(struct proc_dir_entry *head,
+                                            const char *name)
 {
-       struct obd_device *obd = data;
-       char              *kbuf;
-       char              *tmpbuf;
+       struct proc_dir_entry *temp;
 
-       OBD_ALLOC(kbuf, BUFLEN);
-       if (kbuf == NULL)
-               return -ENOMEM;
+       if (head == NULL)
+               return NULL;
 
-       /*
-        * 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;
+       temp = head->subdir;
+       while (temp != NULL) {
+               if (strcmp(temp->name, name) == 0)
+                       return temp;
+               temp = temp->next;
        }
-       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;
+       return NULL;
 }
-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 proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head,
+                                   const char *name)
 {
-       struct obd_device *obd = ((struct seq_file *)file->private_data)->private;
-       char *tmpbuf, *kbuf;
-
-       OBD_ALLOC(kbuf, BUFLEN);
-       if (kbuf == NULL)
-               return -ENOMEM;
+       struct proc_dir_entry *temp;
 
-       /*
-        * 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;
+       LPROCFS_SRCH_ENTRY();
+       temp = __lprocfs_srch(head, name);
+       LPROCFS_SRCH_EXIT();
+       return temp;
 }
-EXPORT_SYMBOL(lprocfs_evict_client_seq_write);
-
-#undef BUFLEN
-
-struct file_operations lprocfs_evict_client_fops = {
-        .owner = THIS_MODULE,
-        .read = lprocfs_fops_read,
-        .write = lprocfs_fops_write,
-        .open = lprocfs_evict_client_open,
-        .release = lprocfs_evict_client_release,
-};
-EXPORT_SYMBOL(lprocfs_evict_client_fops);
-#endif
+EXPORT_SYMBOL(lprocfs_srch);
 
-#ifndef HAVE_ONLY_PROCFS_SEQ
 static int __lprocfs_add_vars(struct proc_dir_entry *root,
                              struct lprocfs_vars *list,
                              void *data)
@@ -486,7 +343,6 @@ int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list,
        return rc;
 }
 EXPORT_SYMBOL(lprocfs_add_vars);
-
 #endif
 
 /**
@@ -1359,17 +1215,6 @@ 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,
@@ -1665,7 +1510,7 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count,
                       "       failover_nids: [");
        spin_lock(&imp->imp_lock);
         j = 0;
-        cfs_list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
+       list_for_each_entry(conn, &imp->imp_conn_list, oic_item) {
                 i += snprintf(page + i, count - i, "%s%s", j ? ", " : "",
                               libcfs_nid2str(conn->oic_conn->c_peer.nid));
                 j++;
@@ -1885,19 +1730,6 @@ 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)
-{
-        struct obd_device *obd = data;
-
-        LASSERT(obd != NULL);
-        *eof = 1;
-        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)
 {
@@ -1968,48 +1800,6 @@ int lprocfs_obd_cleanup(struct obd_device *obd)
 }
 EXPORT_SYMBOL(lprocfs_obd_cleanup);
 
-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(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));
-
-        if (client_stat->nid_proc)
-                lprocfs_remove(&client_stat->nid_proc);
-
-        if (client_stat->nid_stats)
-                lprocfs_free_stats(&client_stat->nid_stats);
-
-        if (client_stat->nid_ldlm_stats)
-                lprocfs_free_stats(&client_stat->nid_ldlm_stats);
-
-        OBD_FREE_PTR(client_stat);
-        return;
-
-}
-
-void lprocfs_free_per_client_stats(struct obd_device *obd)
-{
-        cfs_hash_t *hash = obd->obd_nid_stats_hash;
-        struct nid_stat *stat;
-        ENTRY;
-
-        /* we need extra list - because hash_exit called to early */
-        /* not need locking because all clients is died */
-        while (!cfs_list_empty(&obd->obd_nid_stats)) {
-                stat = cfs_list_entry(obd->obd_nid_stats.next,
-                                      struct nid_stat, nid_list);
-                cfs_list_del_init(&stat->nid_list);
-                cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
-                lprocfs_free_client_stats(stat);
-        }
-        EXIT;
-}
-EXPORT_SYMBOL(lprocfs_free_per_client_stats);
-
 int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
 {
        struct lprocfs_counter  *cntr;
@@ -2317,118 +2107,6 @@ void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
 }
 EXPORT_SYMBOL(lprocfs_counter_init);
 
-#define LPROCFS_OBD_OP_INIT(base, stats, op)                               \
-do {                                                                       \
-        unsigned int coffset = base + OBD_COUNTER_OFFSET(op);              \
-        LASSERT(coffset < stats->ls_num);                                  \
-        lprocfs_counter_init(stats, coffset, 0, #op, "reqs");              \
-} while (0)
-
-void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
-{
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
-        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, create);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
-        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, preprw);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
-        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, init_export);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
-        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);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
-        LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
-
-       CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
-}
-EXPORT_SYMBOL(lprocfs_init_ops_stats);
-
-int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
-{
-        struct lprocfs_stats *stats;
-        unsigned int num_stats;
-        int rc, i;
-
-        LASSERT(obd->obd_stats == NULL);
-        LASSERT(obd->obd_proc_entry != NULL);
-        LASSERT(obd->obd_cntr_base == 0);
-
-       num_stats = NUM_OBD_STATS + num_private_stats;
-        stats = lprocfs_alloc_stats(num_stats, 0);
-        if (stats == NULL)
-                return -ENOMEM;
-
-        lprocfs_init_ops_stats(num_private_stats, stats);
-
-        for (i = num_private_stats; i < num_stats; i++) {
-                /* If this LBUGs, it is likely that an obd
-                 * operation was added to struct obd_ops in
-                 * <obd.h>, and that the corresponding line item
-                 * LPROCFS_OBD_OP_INIT(.., .., opname)
-                 * is missing from the list above. */
-               LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
-                         "Missing obd_stat initializer obd_op "
-                         "operation at offset %d.\n", i - num_private_stats);
-        }
-        rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
-        if (rc < 0) {
-                lprocfs_free_stats(&stats);
-        } else {
-                obd->obd_stats  = stats;
-                obd->obd_cntr_base = num_private_stats;
-        }
-        return rc;
-}
-EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
-
-void lprocfs_free_obd_stats(struct obd_device *obd)
-{
-        if (obd->obd_stats)
-                lprocfs_free_stats(&obd->obd_stats);
-}
-EXPORT_SYMBOL(lprocfs_free_obd_stats);
-
 /* Note that we only init md counters for ops whose offset is less
  * than NUM_MD_STATS. This is explained in a comment in the definition
  * of struct md_ops. */
@@ -2568,383 +2246,6 @@ 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)
-{
-        struct obd_export *exp = data;
-        LASSERT(exp != NULL);
-        *eof = 1;
-        return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
-}
-
-struct exp_uuid_cb_data {
-       char                   *page;
-       int                     count;
-       int                    *eof;
-       int                    *len;
-};
-
-static void
-lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
-                            int count, int *eof, int *len)
-{
-        cb_data->page = page;
-        cb_data->count = count;
-        cb_data->eof = eof;
-        cb_data->len = len;
-}
-
-int lprocfs_exp_print_uuid(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 exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
-
-        if (exp->exp_nid_stats)
-                *data->len += snprintf((data->page + *data->len),
-                                       data->count, "%s\n",
-                                       obd_uuid2str(&exp->exp_client_uuid));
-        return 0;
-}
-
-int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
-                        int *eof,  void *data)
-{
-        struct nid_stat *stats = (struct nid_stat *)data;
-        struct exp_uuid_cb_data cb_data;
-        struct obd_device *obd = stats->nid_obd;
-        int len = 0;
-
-        *eof = 1;
-        page[0] = '\0';
-        lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
-        cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                              lprocfs_exp_print_uuid, &cb_data);
-        return (*cb_data.len);
-}
-
-int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
-                           cfs_hlist_node_t *hnode, void *cb_data)
-
-{
-        struct exp_uuid_cb_data *data = cb_data;
-        struct obd_export       *exp = cfs_hash_object(hs, hnode);
-
-        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);
-        }
-
-        return 0;
-}
-
-int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
-                        int *eof,  void *data)
-{
-        struct nid_stat *stats = (struct nid_stat *)data;
-        struct exp_uuid_cb_data cb_data;
-        struct obd_device *obd = stats->nid_obd;
-        int len = 0;
-
-        *eof = 1;
-        page[0] = '\0';
-        lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
-
-        cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
-                              lprocfs_exp_print_hash, &cb_data);
-        return (*cb_data.len);
-}
-
-int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
-                                        int count, int *eof,  void *data)
-{
-        *eof = 1;
-        return snprintf(page, count, "%s\n",
-                        "Write into this file to clear all nid stats and "
-                        "stale nid entries");
-}
-EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
-
-int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
-                                  unsigned long count, void *data)
-{
-        struct obd_device *obd = (struct obd_device *)data;
-        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_write);
-#endif
-
-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;
-        cfs_proc_dir_entry_t *entry;
-        char *buffer = NULL;
-        int rc = 0;
-        ENTRY;
-
-        *newnid = 0;
-
-        if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
-            !exp->exp_obd->obd_nid_stats_hash)
-                RETURN(-EINVAL);
-
-        /* not test against zero because eric say:
-         * You may only test nid against another nid, or LNET_NID_ANY.
-         * Anything else is nonsense.*/
-        if (!nid || *nid == LNET_NID_ANY)
-                RETURN(0);
-
-       spin_lock(&exp->exp_lock);
-       if (exp->exp_nid_stats != NULL) {
-               spin_unlock(&exp->exp_lock);
-               RETURN(-EALREADY);
-       }
-       spin_unlock(&exp->exp_lock);
-
-        obd = exp->exp_obd;
-
-        CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
-
-        OBD_ALLOC_PTR(new_stat);
-        if (new_stat == NULL)
-                RETURN(-ENOMEM);
-
-        new_stat->nid               = *nid;
-        new_stat->nid_obd           = exp->exp_obd;
-        /* we need set default refcount to 1 to balance obd_disconnect */
-       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),
-              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) {
-               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 */
-        OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
-        if (buffer == NULL)
-                GOTO(destroy_new, rc = -ENOMEM);
-
-       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);
-#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);
-               new_stat->nid_proc = NULL;
-               CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
-                      obd->obd_name, libcfs_nid2str(*nid), rc);
-               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);
-                GOTO(destroy_new_ns, rc);
-        }
-
-       spin_lock(&exp->exp_lock);
-       exp->exp_nid_stats = new_stat;
-       spin_unlock(&exp->exp_lock);
-        *newnid = 1;
-        /* protect competitive add to list, not need locking on destroy */
-       spin_lock(&obd->obd_nid_lock);
-       cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats);
-       spin_unlock(&obd->obd_nid_lock);
-
-        RETURN(rc);
-
-destroy_new_ns:
-        if (new_stat->nid_proc != NULL)
-                lprocfs_remove(&new_stat->nid_proc);
-        cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
-
-destroy_new:
-        nidstat_putref(new_stat);
-        OBD_FREE_PTR(new_stat);
-        RETURN(rc);
-}
-EXPORT_SYMBOL(lprocfs_exp_setup);
-#endif
-
-int lprocfs_exp_cleanup(struct obd_export *exp)
-{
-        struct nid_stat *stat = exp->exp_nid_stats;
-
-        if(!stat || !exp->exp_obd)
-                RETURN(0);
-
-        nidstat_putref(exp->exp_nid_stats);
-        exp->exp_nid_stats = NULL;
-
-        return 0;
-}
-EXPORT_SYMBOL(lprocfs_exp_cleanup);
-
 __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
                          struct lprocfs_counter_header *header,
                          enum lprocfs_stats_flags flags,
@@ -3232,7 +2533,7 @@ char *lprocfs_find_named_value(const char *buffer, const char *name,
 }
 EXPORT_SYMBOL(lprocfs_find_named_value);
 
-int lprocfs_seq_create(cfs_proc_dir_entry_t *parent,
+int lprocfs_seq_create(struct proc_dir_entry *parent,
                       const char *name,
                       mode_t mode,
                       const struct file_operations *seq_fops,
@@ -3305,423 +2606,6 @@ 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)
-{
-        struct obd_device *obd = data;
-        int c = 0;
-
-        if (obd == NULL)
-                return 0;
-
-        c += cfs_hash_debug_header(page, count);
-        c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
-        c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
-        c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
-
-        return c;
-}
-EXPORT_SYMBOL(lprocfs_obd_rd_hash);
-
-int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
-                                   int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        int len = 0, size;
-
-        LASSERT(obd != NULL);
-        LASSERT(count >= 0);
-
-        /* Set start of user data returned to
-           page + off since the user may have
-           requested to read much smaller than
-           what we need to read */
-        *start = page + off;
-
-       /*
-        * We know we are allocated a page here.
-        * Also we know that this function will
-        * not need to write more than a page
-        * so we can truncate at PAGE_CACHE_SIZE.
-        */
-       size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
-
-        /* Initialize the page */
-        memset(page, 0, size);
-
-        if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
-                goto out;
-        if (obd->obd_max_recoverable_clients == 0) {
-                if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
-                        goto out;
-
-                goto fclose;
-        }
-
-        /* sampled unlocked, but really... */
-        if (obd->obd_recovering == 0) {
-                if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
-                        goto out;
-                if (lprocfs_obd_snprintf(&page, size, &len,
-                                         "recovery_start: %lu\n",
-                                         obd->obd_recovery_start) <= 0)
-                        goto out;
-                if (lprocfs_obd_snprintf(&page, size, &len,
-                                         "recovery_duration: %lu\n",
-                                         obd->obd_recovery_end -
-                                         obd->obd_recovery_start) <= 0)
-                        goto out;
-                /* Number of clients that have completed recovery */
-                if (lprocfs_obd_snprintf(&page, size, &len,
-                                         "completed_clients: %d/%d\n",
-                                         obd->obd_max_recoverable_clients -
-                                         obd->obd_stale_clients,
-                                         obd->obd_max_recoverable_clients) <= 0)
-                        goto out;
-                if (lprocfs_obd_snprintf(&page, size, &len,
-                                         "replayed_requests: %d\n",
-                                         obd->obd_replayed_requests) <= 0)
-                        goto out;
-                if (lprocfs_obd_snprintf(&page, size, &len,
-                                         "last_transno: "LPD64"\n",
-                                         obd->obd_next_recovery_transno - 1)<=0)
-                        goto out;
-               if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
-                                        obd->obd_version_recov ?
-                                        "ENABLED" : "DISABLED") <=0)
-                        goto out;
-               if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
-                                        obd->obd_no_ir ?
-                                        "DISABLED" : "ENABLED") <= 0)
-                        goto out;
-                goto fclose;
-        }
-
-        if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
-                goto out;
-        if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
-                                 obd->obd_recovery_start) <= 0)
-                goto out;
-        if (lprocfs_obd_snprintf(&page, size, &len, "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()) <= 0)
-                goto out;
-        if (lprocfs_obd_snprintf(&page, size, &len,"connected_clients: %d/%d\n",
-                                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",
-                                atomic_read(&obd->obd_req_replay_clients))
-                <= 0)
-                goto out;
-        if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n",
-                                atomic_read(&obd->obd_lock_replay_clients))
-                <=0)
-                goto out;
-        if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n",
-                                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",
-                                 obd->obd_stale_clients) <= 0)
-                goto out;
-        if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d\n",
-                                 obd->obd_replayed_requests) <= 0)
-                goto out;
-        if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
-                                 obd->obd_requests_queued_for_recovery) <= 0)
-                goto out;
-
-        if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
-                                 obd->obd_next_recovery_transno) <= 0)
-                goto out;
-
-fclose:
-        *eof = 1;
-out:
-        return min(count, len - (int)off);
-}
-EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
-
-int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
-                             int count, int *eof, void *data)
-{
-        struct obd_device *obd = (struct obd_device *)data;
-        LASSERT(obd != NULL);
-
-        return snprintf(page, count, "%d\n",
-                        obd->obd_recovery_ir_factor);
-}
-EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
-
-int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
-                             unsigned long count, void *data)
-{
-        struct obd_device *obd = (struct obd_device *)data;
-        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_obd_wr_ir_factor);
-
-int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
-                                      int count, int *eof, void *data)
-{
-        struct obd_device *obd = (struct obd_device *)data;
-        LASSERT(obd != NULL);
-
-        return snprintf(page, count, "%d\n",
-                        obd->obd_recovery_timeout);
-}
-EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
-
-int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
-                                      unsigned long count, void *data)
-{
-        struct obd_device *obd = (struct obd_device *)data;
-        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_obd_wr_recovery_time_soft);
-
-int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
-                                      int count, int *eof, void *data)
-{
-        struct obd_device *obd = data;
-        LASSERT(obd != NULL);
-
-        return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
-}
-EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
-
-int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
-                                      unsigned long count, void *data)
-{
-        struct obd_device *obd = data;
-        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_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)
 {
diff --git a/lustre/obdclass/lprocfs_status_server.c b/lustre/obdclass/lprocfs_status_server.c
new file mode 100644 (file)
index 0000000..a943b7b
--- /dev/null
@@ -0,0 +1,1145 @@
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2013, Intel Corporation.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
+ *
+ * lustre/obdclass/lprocfs_status_server.c
+ */
+
+#define DEBUG_SUBSYSTEM S_CLASS
+
+#ifndef __KERNEL__
+#include <liblustre.h>
+#endif
+
+#include <obd_class.h>
+#include <lprocfs_status.h>
+#include <lustre/lustre_idl.h>
+
+#if defined(LPROCFS)
+
+int lprocfs_evict_client_open(struct inode *inode, struct file *f)
+{
+       struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
+
+       atomic_inc(&obd->obd_evict_inprogress);
+       return 0;
+}
+
+int lprocfs_evict_client_release(struct inode *inode, struct file *f)
+{
+       struct obd_device *obd = PDE_DATA(f->f_dentry->d_inode);
+
+       atomic_dec(&obd->obd_evict_inprogress);
+       wake_up(&obd->obd_evict_inprogress_waitq);
+
+       return 0;
+}
+
+#define BUFLEN (UUID_MAX + 5)
+
+ssize_t
+lprocfs_evict_client_seq_write(struct file *file, const char *buffer,
+                              size_t count, loff_t *off)
+{
+       struct seq_file *m = file->private_data;
+       struct obd_device *obd = m->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, __func__, 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, __func__, current);
+
+out:
+       OBD_FREE(kbuf, BUFLEN);
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_evict_client_seq_write);
+
+#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, __func__, 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, __func__, current);
+out:
+       OBD_FREE(kbuf, BUFLEN);
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_wr_evict_client);
+
+const struct file_operations lprocfs_evict_client_fops = {
+       .owner = THIS_MODULE,
+       .read = lprocfs_fops_read,
+       .write = lprocfs_fops_write,
+       .open = lprocfs_evict_client_open,
+       .release = lprocfs_evict_client_release,
+};
+EXPORT_SYMBOL(lprocfs_evict_client_fops);
+
+/* Function that emulates snprintf but also has the side effect of advancing
+   the page pointer for the next write into the buffer, incrementing the total
+   length written to the buffer, and decrementing the size left in the
+   buffer. */
+static int lprocfs_obd_snprintf(char **page, int end, int *len,
+                               const char *format, ...)
+{
+       va_list list;
+       int n;
+
+       if (*len >= end)
+               return 0;
+
+       va_start(list, format);
+       n = vsnprintf(*page, end - *len, format, list);
+       va_end(list);
+
+       *page += n; *len += n;
+       return n;
+}
+#endif /* HAVE_ONLY_PROCFS_SEQ */
+
+#undef BUFLEN
+
+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);
+
+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(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));
+
+       if (client_stat->nid_proc)
+               lprocfs_remove(&client_stat->nid_proc);
+
+       if (client_stat->nid_stats)
+               lprocfs_free_stats(&client_stat->nid_stats);
+
+       if (client_stat->nid_ldlm_stats)
+               lprocfs_free_stats(&client_stat->nid_ldlm_stats);
+
+       OBD_FREE_PTR(client_stat);
+       return;
+}
+
+void lprocfs_free_per_client_stats(struct obd_device *obd)
+{
+       cfs_hash_t *hash = obd->obd_nid_stats_hash;
+       struct nid_stat *stat;
+       ENTRY;
+
+       /* we need extra list - because hash_exit called to early */
+       /* not need locking because all clients is died */
+       while (!list_empty(&obd->obd_nid_stats)) {
+               stat = list_entry(obd->obd_nid_stats.next,
+                                     struct nid_stat, nid_list);
+               list_del_init(&stat->nid_list);
+               cfs_hash_del(hash, &stat->nid, &stat->nid_hash);
+               lprocfs_free_client_stats(stat);
+       }
+       EXIT;
+}
+EXPORT_SYMBOL(lprocfs_free_per_client_stats);
+
+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,
+                               struct hlist_node *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,
+                               struct hlist_node *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);
+               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 list_head free_list = LIST_HEAD_INIT(free_list);
+       struct seq_file *m = file->private_data;
+       struct obd_device *obd = m->private;
+       struct nid_stat *client_stat;
+
+       cfs_hash_cond_del(obd->obd_nid_stats_hash,
+                         lprocfs_nid_stats_clear_write_cb, &free_list);
+
+       while (!list_empty(&free_list)) {
+               client_stat = list_entry(free_list.next, struct nid_stat,
+                                        nid_list);
+               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_rd_num_exports(char *page, char **start, off_t off, int count,
+                          int *eof,  void *data)
+{
+       struct obd_device *obd = data;
+
+       LASSERT(obd != NULL);
+       *eof = 1;
+       return snprintf(page, count, "%u\n", obd->obd_num_exports);
+}
+EXPORT_SYMBOL(lprocfs_rd_num_exports);
+
+int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
+                        int *eof,  void *data)
+{
+       struct obd_export *exp = data;
+       LASSERT(exp != NULL);
+       *eof = 1;
+       return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
+}
+
+struct exp_uuid_cb_data {
+       char                   *page;
+       int                     count;
+       int                    *eof;
+       int                    *len;
+};
+
+static void
+lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page,
+                           int count, int *eof, int *len)
+{
+       cb_data->page = page;
+       cb_data->count = count;
+       cb_data->eof = eof;
+       cb_data->len = len;
+}
+
+int lprocfs_exp_print_uuid(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+                          struct hlist_node *hnode, void *cb_data)
+
+{
+       struct obd_export *exp = cfs_hash_object(hs, hnode);
+       struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data;
+
+       if (exp->exp_nid_stats)
+               *data->len += snprintf((data->page + *data->len),
+                                      data->count, "%s\n",
+                                      obd_uuid2str(&exp->exp_client_uuid));
+       return 0;
+}
+
+int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
+                       int *eof,  void *data)
+{
+       struct nid_stat *stats = (struct nid_stat *)data;
+       struct exp_uuid_cb_data cb_data;
+       struct obd_device *obd = stats->nid_obd;
+       int len = 0;
+
+       *eof = 1;
+       page[0] = '\0';
+       lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
+       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
+                             lprocfs_exp_print_uuid, &cb_data);
+       return *cb_data.len;
+}
+
+int lprocfs_exp_print_hash(cfs_hash_t *hs, cfs_hash_bd_t *bd,
+                          struct hlist_node *hnode, void *cb_data)
+
+{
+       struct exp_uuid_cb_data *data = cb_data;
+       struct obd_export       *exp = cfs_hash_object(hs, hnode);
+
+       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);
+       }
+       return 0;
+}
+
+int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count,
+                       int *eof,  void *data)
+{
+       struct nid_stat *stats = (struct nid_stat *)data;
+       struct exp_uuid_cb_data cb_data;
+       struct obd_device *obd = stats->nid_obd;
+       int len = 0;
+
+       *eof = 1;
+       page[0] = '\0';
+       lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len);
+
+       cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid,
+                             lprocfs_exp_print_hash, &cb_data);
+       return *cb_data.len;
+}
+
+int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
+                                       int count, int *eof,  void *data)
+{
+       *eof = 1;
+       return snprintf(page, count, "%s\n",
+                       "Write into this file to clear all nid stats and "
+                       "stale nid entries");
+}
+EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);
+
+int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
+                                 unsigned long count, void *data)
+{
+       struct list_head free_list = LIST_HEAD_INIT(free_list);
+       struct obd_device *obd = (struct obd_device *)data;
+       struct nid_stat *client_stat;
+
+       cfs_hash_cond_del(obd->obd_nid_stats_hash,
+                         lprocfs_nid_stats_clear_write_cb, &free_list);
+
+       while (!list_empty(&free_list)) {
+               client_stat = list_entry(free_list.next, struct nid_stat,
+                                            nid_list);
+               list_del_init(&client_stat->nid_list);
+               lprocfs_free_client_stats(client_stat);
+       }
+
+       return count;
+}
+EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
+#endif
+
+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;
+       struct proc_dir_entry *entry;
+       char *buffer = NULL;
+       int rc = 0;
+       ENTRY;
+
+       *newnid = 0;
+
+       if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
+           !exp->exp_obd->obd_nid_stats_hash)
+               RETURN(-EINVAL);
+
+       /* not test against zero because eric say:
+        * You may only test nid against another nid, or LNET_NID_ANY.
+        * Anything else is nonsense.*/
+       if (!nid || *nid == LNET_NID_ANY)
+               RETURN(0);
+
+       spin_lock(&exp->exp_lock);
+       if (exp->exp_nid_stats != NULL) {
+               spin_unlock(&exp->exp_lock);
+               RETURN(-EALREADY);
+       }
+       spin_unlock(&exp->exp_lock);
+
+       obd = exp->exp_obd;
+
+       CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash);
+
+       OBD_ALLOC_PTR(new_stat);
+       if (new_stat == NULL)
+               RETURN(-ENOMEM);
+
+       new_stat->nid           = *nid;
+       new_stat->nid_obd       = exp->exp_obd;
+       /* we need set default refcount to 1 to balance obd_disconnect */
+       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),
+              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) {
+               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 */
+       OBD_ALLOC(buffer, LNET_NIDSTR_SIZE);
+       if (buffer == NULL)
+               GOTO(destroy_new, rc = -ENOMEM);
+
+       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);
+#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);
+               new_stat->nid_proc = NULL;
+               CERROR("%s: cannot create proc entry for export %s: rc = %d\n",
+                      obd->obd_name, libcfs_nid2str(*nid), rc);
+               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);
+               GOTO(destroy_new_ns, rc);
+       }
+
+       spin_lock(&exp->exp_lock);
+       exp->exp_nid_stats = new_stat;
+       spin_unlock(&exp->exp_lock);
+       *newnid = 1;
+       /* protect competitive add to list, not need locking on destroy */
+       spin_lock(&obd->obd_nid_lock);
+       list_add(&new_stat->nid_list, &obd->obd_nid_stats);
+       spin_unlock(&obd->obd_nid_lock);
+
+       RETURN(rc);
+
+destroy_new_ns:
+       if (new_stat->nid_proc != NULL)
+               lprocfs_remove(&new_stat->nid_proc);
+       cfs_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash);
+
+destroy_new:
+       nidstat_putref(new_stat);
+       OBD_FREE_PTR(new_stat);
+       RETURN(rc);
+}
+EXPORT_SYMBOL(lprocfs_exp_setup);
+
+int lprocfs_exp_cleanup(struct obd_export *exp)
+{
+       struct nid_stat *stat = exp->exp_nid_stats;
+
+       if (!stat || !exp->exp_obd)
+               RETURN(0);
+
+       nidstat_putref(exp->exp_nid_stats);
+       exp->exp_nid_stats = NULL;
+
+       return 0;
+}
+EXPORT_SYMBOL(lprocfs_exp_cleanup);
+
+#define LPROCFS_OBD_OP_INIT(base, stats, op)                   \
+do {                                                           \
+       unsigned int coffset = base + OBD_COUNTER_OFFSET(op);   \
+       LASSERT(coffset < stats->ls_num);                       \
+       lprocfs_counter_init(stats, coffset, 0, #op, "reqs");   \
+} while (0)
+
+void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats)
+{
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, iocontrol);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_info);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_info_async);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, attach);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, detach);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, setup);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, precleanup);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, cleanup);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, process_config);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, postrecov);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, add_conn);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, del_conn);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, reconnect);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_init);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_fini);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, fid_alloc);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs);
+       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, create);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, create_async);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, setattr);
+       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, preprw);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw);
+       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, init_export);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, destroy_export);
+       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);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, pin);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, unpin);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, import_event);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, notify);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, health_check);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, get_uuid);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotacheck);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, quotactl);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, ping);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_new);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_rem);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_add);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, pool_del);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, getref);
+       LPROCFS_OBD_OP_INIT(num_private_stats, stats, putref);
+
+       CLASSERT(NUM_OBD_STATS == OBD_COUNTER_OFFSET(putref) + 1);
+}
+EXPORT_SYMBOL(lprocfs_init_ops_stats);
+
+int lprocfs_alloc_obd_stats(struct obd_device *obd, unsigned num_private_stats)
+{
+       struct lprocfs_stats *stats;
+       unsigned int num_stats;
+       int rc, i;
+
+       LASSERT(obd->obd_stats == NULL);
+       LASSERT(obd->obd_proc_entry != NULL);
+       LASSERT(obd->obd_cntr_base == 0);
+
+       num_stats = NUM_OBD_STATS + num_private_stats;
+       stats = lprocfs_alloc_stats(num_stats, 0);
+       if (stats == NULL)
+               return -ENOMEM;
+
+       lprocfs_init_ops_stats(num_private_stats, stats);
+
+       for (i = num_private_stats; i < num_stats; i++) {
+               /* If this LBUGs, it is likely that an obd
+                * operation was added to struct obd_ops in
+                * <obd.h>, and that the corresponding line item
+                * LPROCFS_OBD_OP_INIT(.., .., opname)
+                * is missing from the list above. */
+               LASSERTF(stats->ls_cnt_header[i].lc_name != NULL,
+                        "Missing obd_stat initializer obd_op "
+                        "operation at offset %d.\n", i - num_private_stats);
+       }
+       rc = lprocfs_register_stats(obd->obd_proc_entry, "stats", stats);
+       if (rc < 0) {
+               lprocfs_free_stats(&stats);
+       } else {
+               obd->obd_stats  = stats;
+               obd->obd_cntr_base = num_private_stats;
+       }
+       return rc;
+}
+EXPORT_SYMBOL(lprocfs_alloc_obd_stats);
+
+void lprocfs_free_obd_stats(struct obd_device *obd)
+{
+       if (obd->obd_stats)
+               lprocfs_free_stats(&obd->obd_stats);
+}
+EXPORT_SYMBOL(lprocfs_free_obd_stats);
+
+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 seq_file *m = file->private_data;
+       struct obd_device *obd = m->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 seq_file *m = file->private_data;
+       struct obd_device *obd = m->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 seq_file *m = file->private_data;
+       struct obd_device *obd = m->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)
+{
+       struct obd_device *obd = data;
+       int c = 0;
+
+       if (obd == NULL)
+               return 0;
+
+       c += cfs_hash_debug_header(page, count);
+       c += cfs_hash_debug_str(obd->obd_uuid_hash, page + c, count - c);
+       c += cfs_hash_debug_str(obd->obd_nid_hash, page + c, count - c);
+       c += cfs_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c);
+
+       return c;
+}
+EXPORT_SYMBOL(lprocfs_obd_rd_hash);
+
+int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off,
+                                  int count, int *eof, void *data)
+{
+       struct obd_device *obd = data;
+       int len = 0, size;
+
+       LASSERT(obd != NULL);
+       LASSERT(count >= 0);
+
+       /* Set start of user data returned to
+          page + off since the user may have
+          requested to read much smaller than
+          what we need to read */
+       *start = page + off;
+
+       /*
+        * We know we are allocated a page here.
+        * Also we know that this function will
+        * not need to write more than a page
+        * so we can truncate at PAGE_CACHE_SIZE.
+        */
+       size = min(count + (int)off + 1, (int)PAGE_CACHE_SIZE);
+
+       /* Initialize the page */
+       memset(page, 0, size);
+
+       if (lprocfs_obd_snprintf(&page, size, &len, "status: ") <= 0)
+               goto out;
+       if (obd->obd_max_recoverable_clients == 0) {
+               if (lprocfs_obd_snprintf(&page, size, &len, "INACTIVE\n") <= 0)
+                       goto out;
+
+               goto fclose;
+       }
+
+       /* sampled unlocked, but really... */
+       if (obd->obd_recovering == 0) {
+               if (lprocfs_obd_snprintf(&page, size, &len, "COMPLETE\n") <= 0)
+                       goto out;
+               if (lprocfs_obd_snprintf(&page, size, &len,
+                                        "recovery_start: %lu\n",
+                                        obd->obd_recovery_start) <= 0)
+                       goto out;
+               if (lprocfs_obd_snprintf(&page, size, &len,
+                                        "recovery_duration: %lu\n",
+                                        obd->obd_recovery_end -
+                                        obd->obd_recovery_start) <= 0)
+                       goto out;
+               /* Number of clients that have completed recovery */
+               if (lprocfs_obd_snprintf(&page, size, &len,
+                                        "completed_clients: %d/%d\n",
+                                        obd->obd_max_recoverable_clients -
+                                        obd->obd_stale_clients,
+                                        obd->obd_max_recoverable_clients) <= 0)
+                       goto out;
+               if (lprocfs_obd_snprintf(&page, size, &len,
+                                        "replayed_requests: %d\n",
+                                        obd->obd_replayed_requests) <= 0)
+                       goto out;
+               if (lprocfs_obd_snprintf(&page, size, &len,
+                                        "last_transno: "LPD64"\n",
+                                        obd->obd_next_recovery_transno - 1) <= 0)
+                       goto out;
+               if (lprocfs_obd_snprintf(&page, size, &len, "VBR: %s\n",
+                                        obd->obd_version_recov ?
+                                        "ENABLED" : "DISABLED") <= 0)
+                       goto out;
+               if (lprocfs_obd_snprintf(&page, size, &len, "IR: %s\n",
+                                        obd->obd_no_ir ?
+                                        "DISABLED" : "ENABLED") <= 0)
+                       goto out;
+               goto fclose;
+       }
+
+       if (lprocfs_obd_snprintf(&page, size, &len, "RECOVERING\n") <= 0)
+               goto out;
+       if (lprocfs_obd_snprintf(&page, size, &len, "recovery_start: %lu\n",
+                                obd->obd_recovery_start) <= 0)
+               goto out;
+       if (lprocfs_obd_snprintf(&page, size, &len, "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()) <= 0)
+               goto out;
+       if (lprocfs_obd_snprintf(&page, size, &len,
+                                "connected_clients: %d/%d\n",
+                                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",
+                                atomic_read(&obd->obd_req_replay_clients))
+               <= 0)
+               goto out;
+       if (lprocfs_obd_snprintf(&page, size, &len, "lock_repay_clients: %d\n",
+                                atomic_read(&obd->obd_lock_replay_clients))
+               <= 0)
+               goto out;
+       if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d\n",
+                                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",
+                                obd->obd_stale_clients) <= 0)
+               goto out;
+       if (lprocfs_obd_snprintf(&page, size, &len, "replayed_requests: %d\n",
+                                obd->obd_replayed_requests) <= 0)
+               goto out;
+       if (lprocfs_obd_snprintf(&page, size, &len, "queued_requests: %d\n",
+                                obd->obd_requests_queued_for_recovery) <= 0)
+               goto out;
+
+       if (lprocfs_obd_snprintf(&page, size, &len, "next_transno: "LPD64"\n",
+                                obd->obd_next_recovery_transno) <= 0)
+               goto out;
+
+fclose:
+       *eof = 1;
+out:
+       return min(count, len - (int)off);
+}
+EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status);
+
+int lprocfs_obd_rd_ir_factor(char *page, char **start, off_t off,
+                            int count, int *eof, void *data)
+{
+       struct obd_device *obd = (struct obd_device *)data;
+       LASSERT(obd != NULL);
+
+       return snprintf(page, count, "%d\n",
+                       obd->obd_recovery_ir_factor);
+}
+EXPORT_SYMBOL(lprocfs_obd_rd_ir_factor);
+
+int lprocfs_obd_wr_ir_factor(struct file *file, const char *buffer,
+                            unsigned long count, void *data)
+{
+       struct obd_device *obd = (struct obd_device *)data;
+       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_obd_wr_ir_factor);
+
+int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off,
+                                     int count, int *eof, void *data)
+{
+       struct obd_device *obd = (struct obd_device *)data;
+       LASSERT(obd != NULL);
+
+       return snprintf(page, count, "%d\n",
+                       obd->obd_recovery_timeout);
+}
+EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft);
+
+int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer,
+                                     unsigned long count, void *data)
+{
+       struct obd_device *obd = (struct obd_device *)data;
+       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_obd_wr_recovery_time_soft);
+
+int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off,
+                                     int count, int *eof, void *data)
+{
+       struct obd_device *obd = data;
+       LASSERT(obd != NULL);
+
+       return snprintf(page, count, "%u\n", obd->obd_recovery_time_hard);
+}
+EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard);
+
+int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer,
+                                     unsigned long count, void *data)
+{
+       struct obd_device *obd = data;
+       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_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 /* LPROCFS*/