diff --git a/lustre/include/class_hash.h b/lustre/include/class_hash.h
index 5e8a3686e90b063118b0f870253ffb23cc200a35..efc81442e091164756f9cc317cef98b0722a4bd8 100644
--- a/lustre/include/class_hash.h
+++ b/lustre/include/class_hash.h
@@ -93,6 +93,9 @@ int lustre_hash_delitem_by_key(struct lustre_class_hash_body *hash_body,
                                void *key);
 int lustre_hash_delitem(struct lustre_class_hash_body *hash_body, void *key, 
                         struct hlist_node *hash_item);
+void lustre_hash_bucket_iterate(struct lustre_class_hash_body *hash_body,
+                                void *key, hash_item_iterate_cb,
+                                void *data);
 void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
                                       void *key);
 
diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h
index 8a21292a243c9cb36824cb76ca646ae0d236c8ba..90e599cd35495bda4e61e4cc78dc40d887db1a7a 100644
--- a/lustre/include/lprocfs_status.h
+++ b/lustre/include/lprocfs_status.h
@@ -273,8 +273,17 @@ extern void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
                                  const char *units);
 extern void lprocfs_free_obd_stats(struct obd_device *obddev);
 struct obd_export;
-extern int lprocfs_exp_setup(struct obd_export *exp);
+struct nid_stat;
+extern int lprocfs_add_clear_entry(struct obd_device * obd,
+                                   cfs_proc_dir_entry_t *entry);
+extern int lprocfs_exp_setup(struct obd_export *exp,
+                             lnet_nid_t peer_nid, int *newnid);
 extern int lprocfs_exp_cleanup(struct obd_export *exp);
+extern int lprocfs_add_simple(struct proc_dir_entry *root,
+                              char *name, read_proc_t *read_proc,
+                              write_proc_t *write_proc, void *data);
+extern void lprocfs_free_client_stats(struct nid_stat *stat);
+extern void lprocfs_free_per_client_stats(struct obd_device *obd);
 extern int lprocfs_register_stats(cfs_proc_dir_entry_t *root, const char *name,
                                   struct lprocfs_stats *stats);
 
@@ -308,6 +317,11 @@ extern cfs_proc_dir_entry_t *lprocfs_srch(cfs_proc_dir_entry_t *root,
 
 extern int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list);
 extern int lprocfs_obd_cleanup(struct obd_device *obd);
+extern int lprocfs_add_simple(struct proc_dir_entry *root, char *name,
+                              read_proc_t *read_proc, write_proc_t *write_proc,
+                              void *data);
+extern void lprocfs_free_client_stats(struct nid_stat *stat);
+extern void lprocfs_free_per_client_stats(struct obd_device *obd);
 extern struct file_operations lprocfs_evict_client_fops;
 
 extern int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, 
@@ -495,10 +509,21 @@ static inline void lprocfs_free_obd_stats(struct obd_device *obddev)
 { return; }
 
 struct obd_export;
+static inline int lprocfs_add_clear_entry(struct obd_export *exp)
+{ return 0; }
 static inline int lprocfs_exp_setup(struct obd_export *exp)
 { return 0; }
 static inline int lprocfs_exp_cleanup(struct obd_export *exp)
 { return 0; }
+static inline int lprocfs_add_simple(struct proc_dir_entry *root,
+                                     char *name,
+                                     read_proc_t *read_proc,
+                                     write_proc_t *write_proc,
+                                     void *data)
+{return 0; }
+static inline void lprocfs_free_client_stats(struct nid_stat *stat){}
+static inline void lprocfs_free_per_client_stats(struct obd_device *obd)
+{}
 
 static inline cfs_proc_dir_entry_t *
 lprocfs_register(const char *name, cfs_proc_dir_entry_t *parent,
diff --git a/lustre/include/lustre_export.h b/lustre/include/lustre_export.h
index 679b45112528de2cf1ca9af4e7a792f91205c724..ef3d8c243ada5947d250f7ee1f9677b79d9e1c4a 100644
--- a/lustre/include/lustre_export.h
+++ b/lustre/include/lustre_export.h
@@ -57,6 +57,16 @@ struct filter_export_data {
         struct brw_stats           fed_brw_stats;
 };
 
+typedef struct nid_stat {
+        lnet_nid_t               nid;
+        struct list_head         nid_chain;
+        struct obd_device       *nid_obd;
+        struct proc_dir_entry   *nid_proc;
+        struct lprocfs_stats    *nid_stats;
+        struct brw_stats        *nid_brw_stats;
+        int                      nid_exp_ref_count;
+}nid_stat_t;
+
 struct obd_export {
         struct portals_handle     exp_handle;
         atomic_t                  exp_refcount;
@@ -69,8 +79,7 @@ struct obd_export {
         struct list_head          exp_obd_chain_timed;
         struct obd_device        *exp_obd;
         struct obd_import        *exp_imp_reverse; /* to make RPCs backwards */
-        struct proc_dir_entry    *exp_proc;
-        struct lprocfs_stats     *exp_ops_stats;
+        struct nid_stat          *exp_nid_stats;
         struct lprocfs_stats     *exp_ldlm_stats;
         struct ptlrpc_connection *exp_connection;
         __u32                     exp_conn_cnt;
@@ -117,7 +126,16 @@ static inline int imp_connect_lru_resize(struct obd_import *imp)
                       OBD_CONNECT_LRU_RESIZE;
 }
 
+struct exp_uuid_cb_data {
+        char                   *page;
+        int                     count;
+        int                    *eof;
+        int                    *len;
+        struct obd_export      *exp;
+};
+
 extern struct obd_export *class_conn2export(struct lustre_handle *conn);
 extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
+typedef void (*hash_item_iterate_cb) (void *);
 
 #endif /* __EXPORT_H */
diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h
index d59777c0afcad7e7c9e9706cfed18b9c6bbb1bef..3738aea33b3b98e7fb364e58b52951fbcfb9d4eb 100644
--- a/lustre/include/lustre_net.h
+++ b/lustre/include/lustre_net.h
@@ -880,7 +880,8 @@ ptlrpc_req_set_repsize(struct ptlrpc_request *req, int count, int *lens)
 int client_obd_setup(struct obd_device *obddev, obd_count len, void *buf);
 int client_obd_cleanup(struct obd_device * obddev);
 int client_connect_import(struct lustre_handle *conn, struct obd_device *obd,
-                          struct obd_uuid *cluuid, struct obd_connect_data *);
+                          struct obd_uuid *cluuid, struct obd_connect_data *,
+                          void *localdata);
 int client_disconnect_export(struct obd_export *exp);
 int client_import_add_conn(struct obd_import *imp, struct obd_uuid *uuid,
                            int priority);
diff --git a/lustre/include/obd.h b/lustre/include/obd.h
index 8baea5e28d51e71f302af978b70ee8a66d36e42a..d24bc351396425a74fa28a7856757b022d822d7a 100644
--- a/lustre/include/obd.h
+++ b/lustre/include/obd.h
@@ -735,6 +735,8 @@ struct obd_device {
         cfs_waitq_t             obd_llog_waitq;
         struct list_head        obd_exports;
         int                     obd_num_exports;
+        struct list_head        obd_proc_nid_list;
+        spinlock_t              nid_lock;
         struct ldlm_namespace  *obd_namespace;
         struct ptlrpc_client    obd_ldlm_client; /* XXX OST/MDS only */
         /* a spinlock is OK for what we do now, may need a semaphore later */
@@ -787,12 +789,11 @@ struct obd_device {
         } u;
         /* Fields used by LProcFS */
         cfs_proc_dir_entry_t  *obd_proc_entry;
-        cfs_proc_dir_entry_t  *obd_proc_exports;
+        cfs_proc_dir_entry_t  *obd_proc_exports_entry;
         cfs_proc_dir_entry_t  *obd_svc_procroot;
         struct lprocfs_stats  *obd_stats;
         struct lprocfs_stats  *obd_svc_stats;
         unsigned int           obd_cntr_base;
-        struct semaphore       obd_proc_exp_sem;
         atomic_t               obd_evict_inprogress;
         cfs_waitq_t            obd_evict_inprogress_waitq;
 };
@@ -849,7 +850,8 @@ struct obd_ops {
          * granted by the target, which are guaranteed to be a subset of flags
          * asked for. If @ocd == NULL, use default parameters. */
         int (*o_connect)(struct lustre_handle *conn, struct obd_device *src,
-                         struct obd_uuid *cluuid, struct obd_connect_data *ocd);
+                         struct obd_uuid *cluuid, struct obd_connect_data *ocd,
+                         void *localdata);
         int (*o_reconnect)(struct obd_export *exp, struct obd_device *src,
                            struct obd_uuid *cluuid,
                            struct obd_connect_data *ocd);
diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h
index 19bf151fd070dae3ecab45407408db1a24225c8e..06b21e33e838cc521a1b7f7bb7b91d9f4dadd30f 100644
--- a/lustre/include/obd_class.h
+++ b/lustre/include/obd_class.h
@@ -247,9 +247,10 @@ do {                                                            \
                         OBD_COUNTER_OFFSET(op);                              \
                 LASSERT(coffset < (export)->exp_obd->obd_stats->ls_num);     \
                 lprocfs_counter_incr((export)->exp_obd->obd_stats, coffset); \
-                if ((export)->exp_ops_stats != NULL)                         \
+                if ((export)->exp_nid_stats != NULL &&                       \
+                    (export)->exp_nid_stats->nid_stats != NULL)              \
                         lprocfs_counter_incr(                                \
-                                (export)->exp_ops_stats, coffset);           \
+                                (export)->exp_nid_stats->nid_stats, coffset);\
         }
 
 #else
@@ -627,7 +628,8 @@ static inline int obd_del_conn(struct obd_import *imp, struct obd_uuid *uuid)
 
 static inline int obd_connect(struct lustre_handle *conn,struct obd_device *obd,
                               struct obd_uuid *cluuid,
-                              struct obd_connect_data *d)
+                              struct obd_connect_data *d,
+                              void *localdata)
 {
         int rc;
         __u64 ocf = d ? d->ocd_connect_flags : 0; /* for post-condition check */
@@ -637,7 +639,7 @@ static inline int obd_connect(struct lustre_handle *conn,struct obd_device *obd,
         OBD_CHECK_OP(obd, connect, -EOPNOTSUPP);
         OBD_COUNTER_INCREMENT(obd, connect);
 
-        rc = OBP(obd, connect)(conn, obd, cluuid, d);
+        rc = OBP(obd, connect)(conn, obd, cluuid, d, localdata);
         /* check that only subset is granted */
         LASSERT(ergo(d != NULL,
                      (d->ocd_connect_flags & ocf) == d->ocd_connect_flags));
diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c
index 4bd360d584e718bd4b1cf5a87e68d4e640c1fff7..817fd2d9a0cf2dae7d9c9ec2d0e014aa43928720 100644
--- a/lustre/ldlm/ldlm_lib.c
+++ b/lustre/ldlm/ldlm_lib.c
@@ -353,7 +353,7 @@ int client_obd_cleanup(struct obd_device *obddev)
 /* ->o_connect() method for client side (OSC and MDC and MGC) */
 int client_connect_import(struct lustre_handle *dlm_handle,
                           struct obd_device *obd, struct obd_uuid *cluuid,
-                          struct obd_connect_data *data)
+                          struct obd_connect_data *data, void *localdata)
 {
         struct client_obd *cli = &obd->u.cli;
         struct obd_import *imp = cli->cl_import;
@@ -565,6 +565,7 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         int rc = 0, abort_recovery;
         struct obd_connect_data *data;
         int size[2] = { sizeof(struct ptlrpc_body), sizeof(*data) };
+        lnet_nid_t client_nid = 0;
         ENTRY;
 
         OBD_RACE(OBD_FAIL_TGT_CONN_RACE);
@@ -775,6 +776,7 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
         /* Tell the client if we support replayable requests */
         if (target->obd_replayable)
                 lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_REPLAYABLE);
+        client_nid = req->rq_peer.nid;
 
         if (export == NULL) {
                 if (target->obd_recovering) {
@@ -788,7 +790,8 @@ int target_handle_connect(struct ptlrpc_request *req, svc_handler_t handler)
                         rc = -EBUSY;
                 } else {
  dont_check_exports:
-                        rc = obd_connect(&conn, target, &cluuid, data);
+                        rc = obd_connect(&conn, target, &cluuid, data,
+                                         &client_nid);
                 }
         } else {
                 rc = obd_reconnect(export, target, &cluuid, data);
diff --git a/lustre/liblustre/llite_lib.c b/lustre/liblustre/llite_lib.c
index 86705286c0374667b23c6ceb8e569d8c5b379f29..a4b3e421aa059d45169dea0a27f94eb92da27de5 100644
--- a/lustre/liblustre/llite_lib.c
+++ b/lustre/liblustre/llite_lib.c
@@ -159,7 +159,7 @@ int liblustre_process_log(struct config_llog_instance *cfg,
         ocd->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT;
         ocd->ocd_version = LUSTRE_VERSION_CODE;
 
-        rc = obd_connect(&mgc_conn, obd, &mgc_uuid, ocd);
+        rc = obd_connect(&mgc_conn, obd, &mgc_uuid, ocd, NULL);
         if (rc) {
                 CERROR("cannot connect to %s at %s: rc = %d\n",
                        LUSTRE_MGS_OBDNAME, mgsnid, rc);
diff --git a/lustre/liblustre/super.c b/lustre/liblustre/super.c
index 8a5966698c374b6904733d7f2f83a8d2b91172b6..6abda5ef8771362a21b8f3dc4a5cbd8c8e2b5157 100644
--- a/lustre/liblustre/super.c
+++ b/lustre/liblustre/super.c
@@ -1941,7 +1941,7 @@ llu_fsswop_mount(const char *source,
         ocd.ocd_version = LUSTRE_VERSION_CODE;
 
         /* setup mdc */
-        err = obd_connect(&mdc_conn, obd, &sbi->ll_sb_uuid, &ocd);
+        err = obd_connect(&mdc_conn, obd, &sbi->ll_sb_uuid, &ocd, NULL);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", mdc, err);
                 GOTO(out_free, err);
@@ -1971,7 +1971,7 @@ llu_fsswop_mount(const char *source,
         ocd.ocd_connect_flags = OBD_CONNECT_SRVLOCK | OBD_CONNECT_REQPORTAL |
                 OBD_CONNECT_VERSION | OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_AT;
         ocd.ocd_version = LUSTRE_VERSION_CODE;
-        err = obd_connect(&osc_conn, obd, &sbi->ll_sb_uuid, &ocd);
+        err = obd_connect(&osc_conn, obd, &sbi->ll_sb_uuid, &ocd, NULL);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", osc, err);
                 GOTO(out_mdc, err);
diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c
index 9cacc16ec04d9b0495d5a747dbd361bfc8a24900..da1716fe2ffe31c619cf293d62b12cecca3b478f 100644
--- a/lustre/llite/llite_lib.c
+++ b/lustre/llite/llite_lib.c
@@ -196,7 +196,7 @@ static int client_common_fill_super(struct super_block *sb,
         else
                 sbi->ll_fop = &ll_file_operations_noflock;
 
-        err = obd_connect(&mdc_conn, obd, &sbi->ll_sb_uuid, data);
+        err = obd_connect(&mdc_conn, obd, &sbi->ll_sb_uuid, data, NULL);
         if (err == -EBUSY) {
                 LCONSOLE_ERROR_MSG(0x14f, "An MDT (mdc %s) is performing "
                                    "recovery, of which this client is not a "
@@ -288,7 +288,7 @@ static int client_common_fill_super(struct super_block *sb,
         data->ocd_brw_size = PTLRPC_MAX_BRW_PAGES << CFS_PAGE_SHIFT;
 
 
-        err = obd_connect(&osc_conn, obd, &sbi->ll_sb_uuid, data);
+        err = obd_connect(&osc_conn, obd, &sbi->ll_sb_uuid, data, NULL);
         if (err == -EBUSY) {
                 LCONSOLE_ERROR_MSG(0x150, "An OST (osc %s) is performing "
                                    "recovery, of which this client is not a "
@@ -878,7 +878,7 @@ static int old_lustre_process_log(struct super_block *sb, char *newprofile,
         /* If we don't have this then an ACL MDS will refuse the connection */
         ocd.ocd_connect_flags = OBD_CONNECT_ACL;
 
-        rc = obd_connect(&mdc_conn, obd, &mdc_uuid, &ocd);
+        rc = obd_connect(&mdc_conn, obd, &mdc_uuid, &ocd, NULL);
         if (rc) {
                 CERROR("cannot connect to %s: rc = %d\n", mdt, rc);
                 GOTO(out_cleanup, rc);
diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c
index ece42efe13a3c219167c50fd216a5ebb620febf8..65f99e1199ec5f76f57e2532fd39a051c47b3e52 100644
--- a/lustre/lov/lov_obd.c
+++ b/lustre/lov/lov_obd.c
@@ -147,7 +147,7 @@ static int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
                 RETURN(0);
         }
 
-        rc = obd_connect(&conn, tgt_obd, &lov_osc_uuid, data);
+        rc = obd_connect(&conn, tgt_obd, &lov_osc_uuid, data, NULL);
         if (rc) {
                 CERROR("Target %s connect error %d\n",
                        obd_uuid2str(&tgt_uuid), rc);
@@ -209,7 +209,8 @@ static int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
 }
 
 static int lov_connect(struct lustre_handle *conn, struct obd_device *obd,
-                       struct obd_uuid *cluuid, struct obd_connect_data *data)
+                       struct obd_uuid *cluuid, struct obd_connect_data *data,
+                       void *localdata)
 {
         struct lov_obd *lov = &obd->u.lov;
         struct lov_tgt_desc *tgt;
diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c
index 7dea5eec64ebb23a77b5c8e177cb1714b868eb03..2964f7356ac52f9f0cc51f8e946f8907e0909f00 100644
--- a/lustre/mds/handler.c
+++ b/lustre/mds/handler.c
@@ -322,11 +322,13 @@ static int mds_reconnect(struct obd_export *exp, struct obd_device *obd,
  * on the server, etc.
  */
 static int mds_connect(struct lustre_handle *conn, struct obd_device *obd,
-                       struct obd_uuid *cluuid, struct obd_connect_data *data)
+                       struct obd_uuid *cluuid, struct obd_connect_data *data,
+                       void *localdata)
 {
         struct obd_export *exp;
         struct mds_export_data *med;
         struct mds_client_data *mcd = NULL;
+        lnet_nid_t *client_nid = (lnet_nid_t *)localdata;
         int rc, abort_recovery;
         ENTRY;
 
@@ -368,7 +370,7 @@ static int mds_connect(struct lustre_handle *conn, struct obd_device *obd,
         memcpy(mcd->mcd_uuid, cluuid, sizeof(mcd->mcd_uuid));
         med->med_mcd = mcd;
 
-        rc = mds_client_add(obd, exp, -1);
+        rc = mds_client_add(obd, exp, -1, *client_nid);
         GOTO(out, rc);
 
 out:
@@ -1884,6 +1886,38 @@ static void fsoptions_to_mds_flags(struct mds_obd *mds, char *options)
         }
 }
 
+static int mds_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");
+}
+
+static int mds_nid_stats_clear_write(struct file *file, const char *buffer,
+                                     unsigned long count, void *data)
+{
+        struct obd_device *obd = (struct obd_device *)data;
+        struct list_head *nids= &obd->obd_proc_nid_list;
+        nid_stat_t *client_stat = NULL, *nxt;
+
+        spin_lock(&obd->nid_lock);
+
+        list_for_each_entry_safe (client_stat, nxt, nids, nid_chain) {
+                if (!client_stat->nid_exp_ref_count)
+                        lprocfs_free_client_stats(client_stat);
+                else if (client_stat->nid_stats) {
+                        lprocfs_clear_stats(client_stat->nid_stats);
+                }
+        }
+
+        spin_unlock(&obd->nid_lock);
+
+        return count;
+}
+
+
 /* mount the file system (secretly).  lustre_cfg parameters are:
  * 1 = device
  * 2 = fstype
@@ -1957,8 +1991,8 @@ static int mds_setup(struct obd_device *obd, obd_count len, void *buf)
             lprocfs_alloc_obd_stats(obd, LPROC_MDS_LAST) == 0) {
                 /* Init private stats here */
                 mds_stats_counter_init(obd->obd_stats);
-                obd->obd_proc_exports = proc_mkdir("exports",
-                                                   obd->obd_proc_entry);
+                obd->obd_proc_exports_entry = proc_mkdir("exports",
+                                                         obd->obd_proc_entry);
         }
 
         rc = mds_fs_setup(obd, mnt);
@@ -1968,6 +2002,11 @@ static int mds_setup(struct obd_device *obd, obd_count len, void *buf)
                 GOTO(err_ns, rc);
         }
 
+        if (obd->obd_proc_exports_entry)
+                lprocfs_add_simple(obd->obd_proc_exports_entry,
+                                   "clear", mds_nid_stats_clear_read,
+                                   mds_nid_stats_clear_write, obd);
+
         if (lcfg->lcfg_bufcount >= 4 && LUSTRE_CFG_BUFLEN(lcfg, 3) > 0) {
                 class_uuid_t uuid;
 
@@ -2234,6 +2273,8 @@ static int mds_cleanup(struct obd_device *obd)
                    we just need to drop our ref */
                 class_export_put(mds->mds_osc_exp);
 
+        lprocfs_free_per_client_stats(obd);
+        remove_proc_entry("clear", obd->obd_proc_exports_entry);
         lprocfs_obd_cleanup(obd);
         lprocfs_free_obd_stats(obd);
 
diff --git a/lustre/mds/lproc_mds.c b/lustre/mds/lproc_mds.c
index 231d541ca084362de1263a898b38009a21cc7af4..d932c977f158b408843abbaac5741bdd08372b42 100644
--- a/lustre/mds/lproc_mds.c
+++ b/lustre/mds/lproc_mds.c
@@ -356,8 +356,11 @@ struct lprocfs_vars lprocfs_mdt_module_vars[] = {
 
 void mds_counter_incr(struct obd_export *exp, int opcode)
 {
-        lprocfs_counter_incr(exp->exp_obd->obd_stats, opcode);
-        lprocfs_counter_incr(exp->exp_ops_stats, opcode);
+        if (exp->exp_obd && exp->exp_obd->obd_stats)
+                lprocfs_counter_incr(exp->exp_obd->obd_stats, opcode);
+        if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
+                lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
+
 }
 
 void mds_stats_counter_init(struct lprocfs_stats *stats)
diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c
index 5082548b3e32b82932e5d1c63a5bdbe1ed506cd8..b5214c2a414d48f29d5bf356240a2652d4d14d8e 100644
--- a/lustre/mds/mds_fs.c
+++ b/lustre/mds/mds_fs.c
@@ -50,22 +50,36 @@
 #include "mds_internal.h"
 
 
-static int mds_export_stats_init(struct obd_device *obd, struct obd_export *exp)
-{
-        int rc, num_stats;
+static int mds_export_stats_init(struct obd_device *obd,
+                                 struct obd_export *exp,
+                                 lnet_nid_t client_nid)
+  {
+        int rc, num_stats, newnid;
 
-        rc = lprocfs_exp_setup(exp);
+        rc = lprocfs_exp_setup(exp, client_nid, &newnid);
         if (rc)
                 return rc;
-        num_stats = (sizeof(*obd->obd_type->typ_ops) / sizeof(void *)) +
-                     LPROC_MDS_LAST - 1;
-        exp->exp_ops_stats = lprocfs_alloc_stats(num_stats,
-                                                 LPROCFS_STATS_FLAG_NOPERCPU);
-        if (exp->exp_ops_stats == NULL)
-                return -ENOMEM;
-        lprocfs_init_ops_stats(LPROC_MDS_LAST, exp->exp_ops_stats);
-        mds_stats_counter_init(exp->exp_ops_stats);
-        lprocfs_register_stats(exp->exp_proc, "stats", exp->exp_ops_stats);
+
+        if (client_nid && newnid) {
+                struct nid_stat *tmp = exp->exp_nid_stats;
+                LASSERT(tmp != NULL);
+
+                num_stats = (sizeof(*obd->obd_type->typ_ops) / sizeof(void *)) +
+                             LPROC_MDS_LAST - 1;
+                tmp->nid_stats = lprocfs_alloc_stats(num_stats,
+                                                     LPROCFS_STATS_FLAG_NOPERCPU);
+                if (tmp->nid_stats == NULL)
+                        return -ENOMEM;
+
+                lprocfs_init_ops_stats(LPROC_MDS_LAST, tmp->nid_stats);
+                rc = lprocfs_register_stats(tmp->nid_proc, "stats",
+                                            tmp->nid_stats);
+                if (rc)
+                        return rc;
+
+                mds_stats_counter_init(tmp->nid_stats);
+        }
+
         return 0;
 }
 
@@ -78,7 +92,7 @@ static int mds_export_stats_init(struct obd_device *obd, struct obd_export *exp)
  * mds_init_server_data() callsite needs to be fixed.
  */
 int mds_client_add(struct obd_device *obd, struct obd_export *exp,
-                   int cl_idx)
+                   int cl_idx, lnet_nid_t client_nid)
 {
         struct mds_obd *mds = &obd->u.mds;
         struct mds_export_data *med = &exp->exp_mds_data;
@@ -126,7 +140,7 @@ int mds_client_add(struct obd_device *obd, struct obd_export *exp,
         med->med_lr_off = le32_to_cpu(mds->mds_server_data->lsd_client_start) +
                 (cl_idx * le16_to_cpu(mds->mds_server_data->lsd_client_size));
         LASSERTF(med->med_lr_off > 0, "med_lr_off = %llu\n", med->med_lr_off);
-        mds_export_stats_init(obd, exp);
+        mds_export_stats_init(obd, exp, client_nid);
 
         if (new_client) {
                 struct lvfs_run_ctxt saved;
@@ -411,7 +425,7 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
                 } else {
                         med = &exp->exp_mds_data;
                         med->med_mcd = mcd;
-                        rc = mds_client_add(obd, exp, cl_idx);
+                        rc = mds_client_add(obd, exp, cl_idx, 0);
                         /* can't fail for existing client */
                         LASSERTF(rc == 0, "rc = %d\n", rc);
 
@@ -630,7 +644,6 @@ err_fid:
         goto err_pop;
 }
 
-
 int mds_fs_cleanup(struct obd_device *obd)
 {
         struct mds_obd *mds = &obd->u.mds;
diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h
index d7c0db5e8085a187d5ac401ee9a0fb2f0767a77b..789a14da09383a31328f16c51714c81ebbc8c89e 100644
--- a/lustre/mds/mds_internal.h
+++ b/lustre/mds/mds_internal.h
@@ -230,7 +230,8 @@ int mds_join_file(struct mds_update_record *rec, struct ptlrpc_request *req,
                   struct dentry *dchild, struct lustre_handle *lockh);
 
 /* mds/mds_fs.c */
-int mds_client_add(struct obd_device *obd, struct obd_export *exp, int cl_off);
+int mds_client_add(struct obd_device *obd, struct obd_export *exp,
+                   int cl_off, lnet_nid_t client_nid);
 int mds_client_free(struct obd_export *exp);
 int mds_obd_create(struct obd_export *exp, struct obdo *oa,
                    struct lov_stripe_md **ea, struct obd_trans_info *oti);
diff --git a/lustre/mds/mds_lov.c b/lustre/mds/mds_lov.c
index 6e82859180621659585f8fbc6acc93c7dd76d586..269c418c9c90cbda80d3b81a659806ae7e060f9e 100644
--- a/lustre/mds/mds_lov.c
+++ b/lustre/mds/mds_lov.c
@@ -343,7 +343,7 @@ int mds_lov_connect(struct obd_device *obd, char * lov_name)
 #endif
         data->ocd_version = LUSTRE_VERSION_CODE;
         /* NB: lov_connect() needs to fill in .ocd_index for each OST */
-        rc = obd_connect(&conn, mds->mds_osc_obd, &obd->obd_uuid, data);
+        rc = obd_connect(&conn, mds->mds_osc_obd, &obd->obd_uuid, data, NULL);
         OBD_FREE(data, sizeof(*data));
         if (rc) {
                 CERROR("MDS cannot connect to LOV %s (%d)\n", lov_name, rc);
diff --git a/lustre/mgs/mgs_handler.c b/lustre/mgs/mgs_handler.c
index 14b7ac35af4b8bf1c44c4f62a1b190133ffc3eec..95227e407e47941a9097e90b6a73e0183ee9085a 100644
--- a/lustre/mgs/mgs_handler.c
+++ b/lustre/mgs/mgs_handler.c
@@ -49,7 +49,8 @@
 
 /* Establish a connection to the MGS.*/
 static int mgs_connect(struct lustre_handle *conn, struct obd_device *obd,
-                       struct obd_uuid *cluuid, struct obd_connect_data *data)
+                       struct obd_uuid *cluuid, struct obd_connect_data *data,
+                       void *localdata)
 {
         struct obd_export *exp;
         int rc;
diff --git a/lustre/obdclass/class_hash.c b/lustre/obdclass/class_hash.c
index 766e16d1d1c7c74a850e8bee31d205f9d6d774c3..e7aeeddae719b69b70e1a9691f1cf592f691ab5b 100644
--- a/lustre/obdclass/class_hash.c
+++ b/lustre/obdclass/class_hash.c
@@ -286,6 +286,35 @@ int lustre_hash_delitem(struct lustre_class_hash_body *hash_body,
 }
 EXPORT_SYMBOL(lustre_hash_delitem);
 
+void lustre_hash_bucket_iterate(struct lustre_class_hash_body *hash_body,
+                                void *key, hash_item_iterate_cb func, void *data)
+{
+        int hashent, find = 0;
+        struct lustre_hash_bucket *bucket = NULL;
+        struct hlist_node *hash_item_node = NULL;
+        struct lustre_hash_operations *hop = hash_body->lchb_hash_operations;
+        struct obd_export *tmp = NULL;
+
+        ENTRY;
+
+        hashent = hop->lustre_hashfn(hash_body, key);
+        bucket = &hash_body->lchb_hash_tables[hashent];
+
+        spin_lock(&bucket->lhb_lock);
+        hlist_for_each(hash_item_node, &(bucket->lhb_head)) {
+                find = hop->lustre_hash_key_compare(key, hash_item_node);
+                if (find) {
+                        tmp = (struct obd_export *)hop->lustre_hash_object_refcount_get(
+                                                                        hash_item_node);
+                        ((struct exp_uuid_cb_data *)data)->exp = tmp;
+                        func(data);
+                        hop->lustre_hash_object_refcount_put(hash_item_node);
+                }
+        }
+        spin_unlock(&bucket->lhb_lock);
+}
+EXPORT_SYMBOL(lustre_hash_bucket_iterate);
+
 void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
                                      void *key)
 {
diff --git a/lustre/obdclass/llog_test.c b/lustre/obdclass/llog_test.c
index c98223a4e52fca4a26c638f0fce3abe712f80166..fbd151e41adea2234fccd82de3874f2fa2cbc661 100644
--- a/lustre/obdclass/llog_test.c
+++ b/lustre/obdclass/llog_test.c
@@ -469,7 +469,8 @@ static int llog_test_6(struct obd_device *obd, char *name)
                 GOTO(ctxt_release, rc = -ENOENT);
         }
 
-        rc = obd_connect(&exph, mdc_obd, &uuid, NULL /* obd_connect_data */);
+        rc = obd_connect(&exph, mdc_obd, &uuid, NULL /* obd_connect_data */,
+                         NULL);
         if (rc) {
                 CERROR("6: failed to connect to MDC: %s\n", mdc_obd->obd_name);
                 GOTO(ctxt_release, rc);
diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c
index 8ed0960896324b279a0d7f159d8e92976f08f78b..2dee5d4c1a5c3ef9bd75c48c76d524083858fe7d 100644
--- a/lustre/obdclass/lprocfs_status.c
+++ b/lustre/obdclass/lprocfs_status.c
@@ -735,15 +735,52 @@ int lprocfs_obd_cleanup(struct obd_device *obd)
 {
         if (!obd) 
                 return -EINVAL;
-        if (obd->obd_proc_exports) {
+        if (obd->obd_proc_exports_entry) {
                 /* Should be no exports left */
-                LASSERT(obd->obd_proc_exports->subdir == NULL);
-                lprocfs_remove(&obd->obd_proc_exports);
+                LASSERT(obd->obd_proc_exports_entry->subdir == NULL);
+                lprocfs_remove(&obd->obd_proc_exports_entry);
         }
         lprocfs_remove(&obd->obd_proc_entry);
         return 0;
 }
 
+void lprocfs_free_client_stats(nid_stat_t *client_stat)
+{
+        LASSERT(client_stat->nid_exp_ref_count == 0);
+
+        list_del(&client_stat->nid_chain);
+
+        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_brw_stats)
+                OBD_FREE(client_stat->nid_brw_stats, sizeof(struct brw_stats));
+
+        OBD_FREE(client_stat, sizeof(struct nid_stat));
+        return;
+
+}
+
+void lprocfs_free_per_client_stats(struct obd_device *obd)
+{
+
+        struct list_head *nids= &obd->obd_proc_nid_list;
+        nid_stat_t *client_stat = NULL, *nxt;
+        ENTRY;
+
+        spin_lock(&obd->nid_lock);
+
+        list_for_each_entry_safe (client_stat, nxt, nids, nid_chain)
+                lprocfs_free_client_stats(client_stat);
+
+        spin_unlock(&obd->nid_lock);
+        return;
+
+}
+
 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
                                           enum lprocfs_stats_flags flags)
 {
@@ -1137,93 +1174,110 @@ int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
         return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
 }
 
+void lprocfs_exp_print_uuid(void *cb_data)
+{
+        struct exp_uuid_cb_data *data = (struct exp_rd_uuid_cb_data *)cb_data;
+
+        if (data->exp->exp_nid_stats)
+                *data->len += snprintf((data->page + *data->len),
+                                       data->count, "%s\n",
+                                       obd_uuid2str(&data->exp->exp_client_uuid));
+}
+
 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
-                         int *eof,  void *data)
+                        int *eof,  void *data)
 {
-        struct obd_export *exp = (struct obd_export*)data;
-        LASSERT(exp != NULL);
+        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;
-        return snprintf(page, count, "%s\n", 
-                        obd_uuid2str(&exp->exp_client_uuid));
+        page[0] = '\0';
+        LASSERT(obd != NULL);
+
+        cb_data.page = page;
+        cb_data.count = count;
+        cb_data.eof = eof;
+        cb_data.len = &len;
+        cb_data.exp = NULL;
+        lustre_hash_bucket_iterate(obd->obd_nid_hash_body,
+                                   &stats->nid, lprocfs_exp_print_uuid,
+                                   &cb_data);
+        return (*cb_data.len);
 }
 
-int lprocfs_exp_setup(struct obd_export *exp)
+int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t nid, int *newnid)
 {
-        char name[sizeof (exp->exp_client_uuid.uuid) + 3];
-        int i = 1, rc;
+        int rc = 0;
+        struct nid_stat *tmp = NULL;
+        struct obd_device *obd = NULL;
+        struct obd_export *export = NULL;
         ENTRY;
 
-        if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports)
+        if (exp->exp_obd)
+                obd = exp->exp_obd;
+
+        if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
+            !obd->obd_nid_hash_body)
                 RETURN(-EINVAL);
 
-        mutex_down(&exp->exp_obd->obd_proc_exp_sem);
-        sprintf(name, "%s", (char *)exp->exp_client_uuid.uuid);
-        while (lprocfs_srch(exp->exp_obd->obd_proc_exports, name)) {
-                /* We might add a new export before deleting the old one during 
-                   an eviction (recovery-small 19a). Suckage. We
-                   could block, or come up with a new name, or just give up. */
-                if (++i > 9) 
-                        GOTO(out, rc = -EEXIST);
-                sprintf(name, "%s:%d", (char *)exp->exp_client_uuid.uuid, i);
-        }
+        *newnid = 0;
 
-        /* Create a proc entry for this export */
-        exp->exp_proc = proc_mkdir(name, exp->exp_obd->obd_proc_exports);
-        if (!exp->exp_proc) {
-                CERROR("Error making export directory for %s\n", name);
-                GOTO(out, rc = -ENOMEM);
-        }
+        if (!nid)
+                RETURN(rc);
 
-        /* Always add nid and uuid */
-        rc = lprocfs_add_simple(exp->exp_proc, "nid",
-                                lprocfs_exp_rd_nid, NULL, exp);
-        if (rc)
-                GOTO(out, rc);
-        rc = lprocfs_add_simple(exp->exp_proc, "uuid",
-                                lprocfs_exp_rd_uuid, NULL, exp);
-        if (rc)
-                GOTO(out, rc);
-
-        /* Always add ldlm stats */
-        exp->exp_ldlm_stats = lprocfs_alloc_stats(LDLM_LAST_OPC 
-                                                  - LDLM_FIRST_OPC, 0);
-        if (exp->exp_ldlm_stats == NULL) {
-                lprocfs_remove(&exp->exp_proc);
-                GOTO(out, rc = -ENOMEM);
-        }
+        export = lustre_hash_get_object_by_key(obd->obd_nid_hash_body,
+                                               &nid);
+        if (export) {
+                exp->exp_nid_stats = export->exp_nid_stats;
+                *newnid = 0;
+                class_export_put(export);
+        } else {
+                OBD_ALLOC(tmp, sizeof(struct nid_stat));
+                if (tmp == NULL)
+                        GOTO(out, rc = -ENOMEM);
+
+                tmp->nid = nid;
+                tmp->nid_obd = exp->exp_obd;
+                tmp->nid_exp_ref_count = 0;
+                tmp->nid_proc = proc_mkdir(libcfs_nid2str(nid),
+                                           exp->exp_obd->obd_proc_exports_entry);
+                if (!tmp->nid_proc) {
+                        CERROR("Error making export directory for"
+                               " nid %s\n", libcfs_nid2str(nid));
+                        OBD_FREE(tmp, sizeof(struct nid_stat));
+                        GOTO(out, rc = -ENOMEM);
+                }
+
+                rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
+                                        lprocfs_exp_rd_uuid, NULL, tmp);
+                if (rc)
+                        CERROR("Error adding the uuid file\n");
+
+                exp->exp_nid_stats = tmp;
+                *newnid = 1;
 
-        lprocfs_counter_init(exp->exp_ldlm_stats, 
-                             LDLM_ENQUEUE - LDLM_FIRST_OPC,
-                             0, "ldlm_enqueue", "reqs");
-        lprocfs_counter_init(exp->exp_ldlm_stats, 
-                             LDLM_CONVERT - LDLM_FIRST_OPC,
-                             0, "ldlm_convert", "reqs");
-        lprocfs_counter_init(exp->exp_ldlm_stats, 
-                             LDLM_CANCEL - LDLM_FIRST_OPC,
-                             0, "ldlm_cancel", "reqs");
-        lprocfs_counter_init(exp->exp_ldlm_stats, 
-                             LDLM_BL_CALLBACK - LDLM_FIRST_OPC,
-                             0, "ldlm_bl_callback", "reqs");
-        lprocfs_counter_init(exp->exp_ldlm_stats, 
-                             LDLM_CP_CALLBACK - LDLM_FIRST_OPC,
-                             0, "ldlm_cp_callback", "reqs");
-        lprocfs_counter_init(exp->exp_ldlm_stats, 
-                             LDLM_GL_CALLBACK - LDLM_FIRST_OPC,
-                             0, "ldlm_gl_callback", "reqs");
-        lprocfs_register_stats(exp->exp_proc, "ldlm_stats",
-                               exp->exp_ldlm_stats);
+                spin_lock(&obd->nid_lock);
+
+                list_add_tail(&tmp->nid_chain,
+                              &exp->exp_obd->obd_proc_nid_list);
+
+                spin_unlock(&obd->nid_lock);
+
+        }
+        if (exp->exp_nid_stats)
+                exp->exp_nid_stats->nid_exp_ref_count++;
 out:
-        mutex_up(&exp->exp_obd->obd_proc_exp_sem);
         RETURN(rc);
 }
 
 int lprocfs_exp_cleanup(struct obd_export *exp)
 {
-        mutex_down(&exp->exp_obd->obd_proc_exp_sem);
-        lprocfs_remove(&exp->exp_proc);
-        lprocfs_free_stats(&exp->exp_ops_stats);
-        lprocfs_free_stats(&exp->exp_ldlm_stats);
-        mutex_up(&exp->exp_obd->obd_proc_exp_sem);
+        if (exp->exp_nid_stats) {
+                exp->exp_nid_stats->nid_exp_ref_count--;
+                exp->exp_nid_stats = NULL;
+        }
         return 0;
 }
 
@@ -1563,6 +1617,9 @@ EXPORT_SYMBOL(lprocfs_remove);
 EXPORT_SYMBOL(lprocfs_add_vars);
 EXPORT_SYMBOL(lprocfs_obd_setup);
 EXPORT_SYMBOL(lprocfs_obd_cleanup);
+EXPORT_SYMBOL(lprocfs_add_simple);
+EXPORT_SYMBOL(lprocfs_free_client_stats);
+EXPORT_SYMBOL(lprocfs_free_per_client_stats);
 EXPORT_SYMBOL(lprocfs_alloc_stats);
 EXPORT_SYMBOL(lprocfs_free_stats);
 EXPORT_SYMBOL(lprocfs_clear_stats);
diff --git a/lustre/obdclass/obd_config.c b/lustre/obdclass/obd_config.c
index be4f5afef6f7544c7454355180947d4243d2e002..cfa973fd128961956c0edee5b94c8100588c11d9 100644
--- a/lustre/obdclass/obd_config.c
+++ b/lustre/obdclass/obd_config.c
@@ -190,9 +190,10 @@ int class_attach(struct lustre_cfg *lcfg)
 
         CFS_INIT_LIST_HEAD(&obd->obd_exports);
         CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
+        INIT_LIST_HEAD(&obd->obd_proc_nid_list);
+        spin_lock_init(&obd->nid_lock);
         spin_lock_init(&obd->obd_dev_lock);
         sema_init(&obd->obd_dev_sem, 1);
-        sema_init(&obd->obd_proc_exp_sem, 1);
         spin_lock_init(&obd->obd_osfs_lock);
         /* obd->obd_osfs_age must be set to a value in the distant
          * past to guarantee a fresh statfs is fetched on mount. */
diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c
index f2c00c4a06072389e57ed9b3516268dd8f7b1f9d..b7b5c71d1ca9eedaa8411c41c61e69d918a6f6fb 100644
--- a/lustre/obdclass/obd_mount.c
+++ b/lustre/obdclass/obd_mount.c
@@ -707,7 +707,7 @@ static int lustre_start_mgc(struct super_block *sb)
         data->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_AT;
         data->ocd_version = LUSTRE_VERSION_CODE;
         /* We connect to the MGS at setup, and don't disconnect until cleanup */
-        rc = obd_connect(&mgc_conn, obd, &(obd->obd_uuid), data);
+        rc = obd_connect(&mgc_conn, obd, &(obd->obd_uuid), data, NULL);
         OBD_FREE_PTR(data);
         if (rc) {
                 CERROR("connect failed %d\n", rc);
diff --git a/lustre/obdecho/echo.c b/lustre/obdecho/echo.c
index 820e529454a521144c03c0d273f7dc3cc5e96a1a..e2f0a5ea84c8e613313d5cb962fe08b466f6c1b0 100644
--- a/lustre/obdecho/echo.c
+++ b/lustre/obdecho/echo.c
@@ -50,7 +50,8 @@ enum {
 };
 
 static int echo_connect(struct lustre_handle *conn, struct obd_device *obd,
-                        struct obd_uuid *cluuid, struct obd_connect_data *data)
+                        struct obd_uuid *cluuid, struct obd_connect_data *data,
+                        void *localdata)
 {
         data->ocd_connect_flags &= ECHO_CONNECT_SUPPORTED;
         return class_connect(conn, obd, cluuid);
diff --git a/lustre/obdecho/echo_client.c b/lustre/obdecho/echo_client.c
index e420c8449e8ee2ca21cc8bc0224d7bf11d51cbee..f0f4edea1a47f530b2e47afa68685245c6e608c1 100644
--- a/lustre/obdecho/echo_client.c
+++ b/lustre/obdecho/echo_client.c
@@ -1386,7 +1386,7 @@ echo_client_setup(struct obd_device *obddev, obd_count len, void *buf)
         ocd->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_REQPORTAL;
         ocd->ocd_version = LUSTRE_VERSION_CODE;
 
-        rc = obd_connect(&conn, tgt, &echo_uuid, ocd);
+        rc = obd_connect(&conn, tgt, &echo_uuid, ocd, NULL);
 
         OBD_FREE(ocd, sizeof(*ocd));
 
@@ -1433,7 +1433,7 @@ static int echo_client_cleanup(struct obd_device *obddev)
 
 static int echo_client_connect(struct lustre_handle *conn,
                                struct obd_device *src, struct obd_uuid *cluuid,
-                               struct obd_connect_data *data)
+                               struct obd_connect_data *data, void *localdata)
 {
         struct obd_export *exp;
         int                rc;
diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c
index 2356aa024157d29004fc674a5eb1a7754ae262cb..ac4363a1fab68968b2de52697dc9c396c16ffd07 100644
--- a/lustre/obdfilter/filter.c
+++ b/lustre/obdfilter/filter.c
@@ -158,14 +158,35 @@ static void init_brw_stats(struct brw_stats *brw_stats)
                 spin_lock_init(&brw_stats->hist[i].oh_lock);
 }
 
+static int lprocfs_init_rw_stats(struct obd_device *obd,
+                                 struct lprocfs_stats **stats)
+{
+        int num_stats;
+
+        num_stats = (sizeof(*obd->obd_type->typ_ops) / sizeof(void *)) +
+                                                        LPROC_FILTER_LAST - 1;
+        *stats = lprocfs_alloc_stats(num_stats, 0);
+        if (*stats == NULL)
+                return -ENOMEM;
+
+        lprocfs_init_ops_stats(LPROC_FILTER_LAST, *stats);
+        lprocfs_counter_init(*stats, LPROC_FILTER_READ_BYTES,
+                             LPROCFS_CNTR_AVGMINMAX, "read_bytes", "bytes");
+        lprocfs_counter_init(*stats, LPROC_FILTER_WRITE_BYTES,
+                             LPROCFS_CNTR_AVGMINMAX, "write_bytes", "bytes");
+
+        return(0);
+}
+
 /* brw_stats are 2128, ops are 3916, ldlm are 204, so 6248 bytes per client,
    plus the procfs overhead :( */
 static int filter_export_stats_init(struct obd_device *obd,
-                                    struct obd_export *exp)
+                                    struct obd_export *exp,
+                                    lnet_nid_t client_nid)
 {
         struct filter_export_data *fed = &exp->exp_filter_data;
         struct proc_dir_entry *brw_entry;
-        int rc, num_stats;
+        int rc, newnid = 0;
         ENTRY;
 
         init_brw_stats(&fed->fed_brw_stats);
@@ -173,31 +194,38 @@ static int filter_export_stats_init(struct obd_device *obd,
         if (obd_uuid_equals(&exp->exp_client_uuid, &obd->obd_uuid))
                 /* Self-export gets no proc entry */
                 RETURN(0);
-
-        rc = lprocfs_exp_setup(exp);
+        rc = lprocfs_exp_setup(exp, client_nid, &newnid);
         if (rc)
                 RETURN(rc);
 
-        /* Create a per export proc entry for brw_stats */
-        brw_entry = create_proc_entry("brw_stats", 0644, exp->exp_proc);
-        if (brw_entry == NULL)
-               RETURN(-ENOMEM);
-        brw_entry->proc_fops = &filter_per_export_stats_fops;
-        brw_entry->data = fed;
+        if (client_nid && newnid) {
+                struct nid_stat *tmp = exp->exp_nid_stats;
+                LASSERT(tmp != NULL);
+
+                OBD_ALLOC(tmp->nid_brw_stats, sizeof(struct brw_stats));
+                if (tmp->nid_brw_stats == NULL)
+                        RETURN(-ENOMEM);
+
+                init_brw_stats(tmp->nid_brw_stats);
+
+                brw_entry = create_proc_entry("brw_stats", 0644,
+                                              exp->exp_nid_stats->nid_proc);
+                if (brw_entry == NULL)
+                       RETURN(-ENOMEM);
+
+                brw_entry->proc_fops = &filter_per_nid_stats_fops;
+                brw_entry->data = exp->exp_nid_stats;
+
+                rc = lprocfs_init_rw_stats(obd, &exp->exp_nid_stats->nid_stats);
+                if (rc)
+                        RETURN(rc);
+
+                rc = lprocfs_register_stats(tmp->nid_proc, "stats",
+                                            tmp->nid_stats);
+                if (rc)
+                        RETURN(rc);
+        }
 
-        /* Create a per export proc entry for ops stats */
-        num_stats = (sizeof(*obd->obd_type->typ_ops) / sizeof(void *)) +
-                     LPROC_FILTER_LAST - 1;
-        exp->exp_ops_stats = lprocfs_alloc_stats(num_stats,
-                                                 LPROCFS_STATS_FLAG_NOPERCPU);
-        if (exp->exp_ops_stats == NULL)
-              RETURN(-ENOMEM);
-        lprocfs_init_ops_stats(LPROC_FILTER_LAST, exp->exp_ops_stats);
-        lprocfs_counter_init(exp->exp_ops_stats, LPROC_FILTER_READ_BYTES,
-                             LPROCFS_CNTR_AVGMINMAX, "read_bytes", "bytes");
-        lprocfs_counter_init(exp->exp_ops_stats, LPROC_FILTER_WRITE_BYTES,
-                             LPROCFS_CNTR_AVGMINMAX, "write_bytes", "bytes");
-        lprocfs_register_stats(exp->exp_proc, "stats", exp->exp_ops_stats);
         RETURN(0);
 }
 
@@ -206,7 +234,7 @@ static int filter_export_stats_init(struct obd_device *obd,
  * Otherwise, we have just read the data from the last_rcvd file and
  * we know its offset. */
 static int filter_client_add(struct obd_device *obd, struct obd_export *exp,
-                             int cl_idx)
+                             int cl_idx, lnet_nid_t client_nid)
 {
         struct filter_obd *filter = &obd->u.filter;
         struct filter_export_data *fed = &exp->exp_filter_data;
@@ -768,8 +796,8 @@ static int filter_init_server_data(struct obd_device *obd, struct file * filp)
                 } else {
                         fed = &exp->exp_filter_data;
                         fed->fed_fcd = fcd;
-                        filter_export_stats_init(obd, exp);
-                        rc = filter_client_add(obd, exp, cl_idx);
+                        filter_export_stats_init(obd, exp, 0);
+                        rc = filter_client_add(obd, exp, cl_idx, 0);
                         /* can't fail for existing client */
                         LASSERTF(rc == 0, "rc = %d\n", rc);
 
@@ -1764,6 +1792,42 @@ err_mntput:
         obd->u.obt.obt_sb = 0;
         return rc;
 }
+static int filter_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");
+}
+
+static int filter_nid_stats_clear_write(struct file *file, const char *buffer,
+                                        unsigned long count, void *data)
+{
+        struct obd_device *obd = (struct obd_device *)data;
+        struct list_head *nids = &obd->obd_proc_nid_list;
+        nid_stat_t *client_stat = NULL, *nxt;
+        int i;
+
+        spin_lock(&obd->nid_lock);
+
+        list_for_each_entry_safe (client_stat, nxt, nids, nid_chain) {
+                if (!client_stat->nid_exp_ref_count) {
+                        lprocfs_free_client_stats(client_stat);
+                } else {
+                        if (client_stat->nid_stats)
+                                lprocfs_clear_stats(client_stat->nid_stats);
+                        if (client_stat->nid_brw_stats)
+                                for (i = 0; i < BRW_LAST; i++)
+                                        lprocfs_oh_clear(
+                                        &client_stat->nid_brw_stats->hist[i]);
+                }
+        }
+
+        spin_unlock(&obd->nid_lock);
+
+        return count;
+}
 
 static int filter_setup(struct obd_device *obd, obd_count len, void *buf)
 {
@@ -1796,9 +1860,13 @@ static int filter_setup(struct obd_device *obd, obd_count len, void *buf)
                                      LPROCFS_CNTR_AVGMINMAX,
                                      "write_bytes", "bytes");
                 lproc_filter_attach_seqstat(obd);
-                obd->obd_proc_exports = proc_mkdir("exports",
-                                                   obd->obd_proc_entry);
+                obd->obd_proc_exports_entry = proc_mkdir("exports",
+                                                         obd->obd_proc_entry);
         }
+        if (obd->obd_proc_exports_entry)
+                lprocfs_add_simple(obd->obd_proc_exports_entry, "clear",
+                                   filter_nid_stats_clear_read,
+                                   filter_nid_stats_clear_write, obd);
 
         memcpy((void *)page, lustre_cfg_buf(lcfg, 4),
                LUSTRE_CFG_BUFLEN(lcfg, 4));
@@ -1935,6 +2003,8 @@ static int filter_cleanup(struct obd_device *obd)
                 }
         }
 
+        lprocfs_free_per_client_stats(obd);
+        remove_proc_entry("clear", obd->obd_proc_exports_entry);
         lprocfs_obd_cleanup(obd);
         lprocfs_free_obd_stats(obd);
 
@@ -2054,11 +2124,13 @@ static int filter_reconnect(struct obd_export *exp, struct obd_device *obd,
 /* nearly identical to mds_connect */
 static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
                           struct obd_uuid *cluuid,
-                          struct obd_connect_data *data)
+                          struct obd_connect_data *data,
+                          void *localdata)
 {
         struct obd_export *exp;
         struct filter_export_data *fed;
         struct filter_client_data *fcd = NULL;
+        lnet_nid_t *client_nid = (lnet_nid_t *)localdata;
         int rc;
         ENTRY;
 
@@ -2077,7 +2149,7 @@ static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
         if (rc)
                 GOTO(cleanup, rc);
 
-        filter_export_stats_init(obd, exp);
+        filter_export_stats_init(obd, exp, *client_nid);
 
         if (!obd->obd_replayable)
                 GOTO(cleanup, rc = 0);
@@ -2091,7 +2163,7 @@ static int filter_connect(struct lustre_handle *conn, struct obd_device *obd,
         memcpy(fcd->fcd_uuid, cluuid, sizeof(fcd->fcd_uuid));
         fed->fed_fcd = fcd;
 
-        rc = filter_client_add(obd, exp, -1);
+        rc = filter_client_add(obd, exp, -1, *client_nid);
 
         GOTO(cleanup, rc);
 
diff --git a/lustre/obdfilter/filter_internal.h b/lustre/obdfilter/filter_internal.h
index 03eabfe5e99c076a48832fb8b030d2616b944489..52398cfd52d3d4969a731b28bc830181d63a4f41 100644
--- a/lustre/obdfilter/filter_internal.h
+++ b/lustre/obdfilter/filter_internal.h
@@ -30,6 +30,7 @@
 #define GRANT_FOR_LLOG(obd) 16
 
 extern struct file_operations filter_per_export_stats_fops;
+extern struct file_operations filter_per_nid_stats_fops;
 
 /* Data stored per client in the last_rcvd file.  In le32 order. */
 struct filter_client_data {
diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c
index a21e34bcfb757406deeee811571b9716fdc94b67..a63983da6fb67b638b3f07105fbc477dcb06d01c 100644
--- a/lustre/obdfilter/filter_io.c
+++ b/lustre/obdfilter/filter_io.c
@@ -345,8 +345,9 @@ static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
                 GOTO(cleanup, rc);
 
         lprocfs_counter_add(obd->obd_stats, LPROC_FILTER_READ_BYTES, tot_bytes);
-        lprocfs_counter_add(exp->exp_ops_stats, LPROC_FILTER_READ_BYTES,
-                            tot_bytes);
+        if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats)
+                lprocfs_counter_add(exp->exp_nid_stats->nid_stats,
+                                    LPROC_FILTER_READ_BYTES, tot_bytes);
 
         EXIT;
 
@@ -663,8 +664,9 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
 
         lprocfs_counter_add(exp->exp_obd->obd_stats, LPROC_FILTER_WRITE_BYTES,
                             tot_bytes);
-        lprocfs_counter_add(exp->exp_ops_stats, LPROC_FILTER_WRITE_BYTES, 
-                            tot_bytes);
+        if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats)
+                lprocfs_counter_add(exp->exp_nid_stats->nid_stats,
+                                    LPROC_FILTER_WRITE_BYTES, tot_bytes);
         EXIT;
 cleanup:
         switch(cleanup_phase) {
diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c
index 29b12e2b18583bd99f9f8d759905e46162384349..538be1e3e25a38309bb63edeabac9467aaa8e4a7 100644
--- a/lustre/obdfilter/filter_io_26.c
+++ b/lustre/obdfilter/filter_io_26.c
@@ -394,6 +394,12 @@ int filter_do_bio(struct obd_export *exp, struct inode *inode,
                                       jiffies - start_time);
                 lprocfs_oh_tally_log2(&exp->exp_filter_data.fed_brw_stats.hist[BRW_R_IO_TIME],
                                  jiffies - start_time);
+                if (exp->exp_nid_stats && exp->exp_nid_stats->nid_brw_stats) {
+                        lprocfs_oh_tally(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_R_DIO_FRAGS],
+                                         frags);
+                        lprocfs_oh_tally_log2(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_R_IO_TIME],
+                                              jiffies - start_time);
+                }
         } else {
                 lprocfs_oh_tally(&obd->u.filter.fo_filter_stats.hist[BRW_W_DIO_FRAGS], frags);
                 lprocfs_oh_tally(&exp->exp_filter_data.fed_brw_stats.hist[BRW_W_DIO_FRAGS],
@@ -402,6 +408,12 @@ int filter_do_bio(struct obd_export *exp, struct inode *inode,
                                       jiffies - start_time);
                 lprocfs_oh_tally_log2(&exp->exp_filter_data.fed_brw_stats.hist[BRW_W_IO_TIME],
                                  jiffies - start_time);
+                if (exp->exp_nid_stats && exp->exp_nid_stats->nid_brw_stats) {
+                        lprocfs_oh_tally(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_W_DIO_FRAGS],
+                                         frags);
+                        lprocfs_oh_tally_log2(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_W_IO_TIME],
+                                              jiffies - start_time);
+                }
         }
 
         if (rc == 0)
diff --git a/lustre/obdfilter/lproc_obdfilter.c b/lustre/obdfilter/lproc_obdfilter.c
index 4793fd83675b0d634c0571ea957636e4c6a9f990..17e73ef8815c878af1eced85b4865cabbe8d9943 100644
--- a/lustre/obdfilter/lproc_obdfilter.c
+++ b/lustre/obdfilter/lproc_obdfilter.c
@@ -237,6 +237,9 @@ void filter_tally(struct obd_export *exp, struct page **pages, int nr_pages,
                               nr_pages);
         lprocfs_oh_tally_log2(&fed->fed_brw_stats.hist[BRW_R_PAGES + wr],
                               nr_pages);
+        if (exp->exp_nid_stats && exp->exp_nid_stats->nid_brw_stats)
+                lprocfs_oh_tally_log2(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_W_PAGES + wr],
+                                      nr_pages);
 
         while (nr_pages-- > 0) {
                 if (last_page && (*pages)->index != (last_page->index + 1))
@@ -258,6 +261,13 @@ void filter_tally(struct obd_export *exp, struct page **pages, int nr_pages,
                          discont_blocks);
         lprocfs_oh_tally(&fed->fed_brw_stats.hist[BRW_R_DISCONT_BLOCKS + wr],
                          discont_blocks);
+
+        if (exp->exp_nid_stats && exp->exp_nid_stats->nid_brw_stats) {
+                lprocfs_oh_tally_log2(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_W_DISCONT_PAGES + wr],
+                                      discont_pages);
+                lprocfs_oh_tally_log2(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_W_DISCONT_BLOCKS + wr],
+                                      discont_blocks);
+        }
 }
 
 #define pct(a,b) (b ? a * 100 / b : 0)
@@ -344,6 +354,8 @@ static void brw_stats_show(struct seq_file *seq, struct brw_stats *brw_stats)
 #endif
 }
 
+#undef pct
+
 static int filter_brw_stats_seq_show(struct seq_file *seq, void *v)
 {
         struct obd_device *dev = seq->private;
@@ -401,4 +413,32 @@ static ssize_t filter_per_export_stats_seq_write(struct file *file,
 LPROC_SEQ_FOPS(filter_per_export_stats);
 
 LPROCFS_INIT_VARS(filter, lprocfs_module_vars, lprocfs_obd_vars)
+
+static int filter_per_nid_stats_seq_show(struct seq_file *seq, void *v)
+{
+        nid_stat_t *tmp = seq->private;
+
+        if (tmp->nid_brw_stats)
+                brw_stats_show(seq, tmp->nid_brw_stats);
+
+        return 0;
+}
+
+static ssize_t filter_per_nid_stats_seq_write(struct file *file,
+                                              const char *buf, size_t len,
+                                              loff_t *off)
+{
+        struct seq_file *seq = file->private_data;
+        nid_stat_t *tmp = seq->private;
+        int i;
+
+        if (tmp->nid_brw_stats)
+                for (i = 0; i < BRW_LAST; i++)
+                        lprocfs_oh_clear(&tmp->nid_brw_stats->hist[i]);
+
+        return len;
+}
+
+LPROC_SEQ_FOPS(filter_per_nid_stats);
+
 #endif /* LPROCFS */