Whamcloud - gitweb
b=11089
authorkomaln <komaln>
Tue, 6 May 2008 07:58:44 +0000 (07:58 +0000)
committerkomaln <komaln>
Tue, 6 May 2008 07:58:44 +0000 (07:58 +0000)
r=Nathan Rutman, Alexey Lyashkov

Ported the patch 'to organize the stats on per-nid basis instead of the existing per-export basis' to HEAD.
This patch also includes all its related bug fixes(bug 14016, bug 14370, bug 14873).

34 files changed:
lustre/cmm/mdc_device.c
lustre/include/class_hash.h
lustre/include/lprocfs_status.h
lustre/include/lustre_export.h
lustre/include/lustre_net.h
lustre/include/obd.h
lustre/include/obd_class.h
lustre/ldlm/ldlm_lib.c
lustre/liblustre/llite_lib.c
lustre/liblustre/super.c
lustre/llite/llite_lib.c
lustre/lmv/lmv_obd.c
lustre/lov/lov_obd.c
lustre/mdc/mdc_request.c
lustre/mds/handler.c
lustre/mds/lproc_mds.c
lustre/mds/mds_fs.c
lustre/mds/mds_internal.h
lustre/mds/mds_lov.c
lustre/mdt/mdt_handler.c
lustre/mgs/lproc_mgs.c
lustre/mgs/mgs_handler.c
lustre/obdclass/class_hash.c
lustre/obdclass/llog_test.c
lustre/obdclass/lprocfs_status.c
lustre/obdclass/obd_config.c
lustre/obdclass/obd_mount.c
lustre/obdecho/echo.c
lustre/obdecho/echo_client.c
lustre/obdfilter/filter.c
lustre/obdfilter/filter_internal.h
lustre/obdfilter/filter_io.c
lustre/obdfilter/filter_io_26.c
lustre/obdfilter/lproc_obdfilter.c

index c81a6e7..2b04e87 100644 (file)
@@ -138,7 +138,7 @@ static int mdc_obd_add(const struct lu_env *env,
                                          OBD_CONNECT_IBITS |
                                          OBD_CONNECT_MDS_MDS |
                                          OBD_CONNECT_FID;
                                          OBD_CONNECT_IBITS |
                                          OBD_CONNECT_MDS_MDS |
                                          OBD_CONNECT_FID;
-                rc = obd_connect(env, conn, mdc, &mdc->obd_uuid, ocd);
+                rc = obd_connect(env, conn, mdc, &mdc->obd_uuid, ocd, NULL);
                 OBD_FREE_PTR(ocd);
                 if (rc) {
                         CERROR("target %s connect error %d\n",
                 OBD_FREE_PTR(ocd);
                 if (rc) {
                         CERROR("target %s connect error %d\n",
index 5e8a368..1be8c52 100644 (file)
@@ -7,6 +7,8 @@
 
 #include <lustre_lib.h>
 
 
 #include <lustre_lib.h>
 
+/* #define LUSTRE_HASH_DEBUG 1 */
+
 /* define the hash bucket*/
 struct lustre_hash_bucket { 
         struct hlist_head lhb_head;
 /* define the hash bucket*/
 struct lustre_hash_bucket { 
         struct hlist_head lhb_head;
@@ -16,7 +18,7 @@ struct lustre_hash_bucket {
          * it will help us to analyse the hash distribute 
          */
         int lhb_item_count; 
          * it will help us to analyse the hash distribute 
          */
         int lhb_item_count; 
-#endif      
+#endif
 };
 
 struct lustre_hash_operations;
 };
 
 struct lustre_hash_operations;
@@ -81,21 +83,34 @@ lustre_hash_delitem_nolock(struct lustre_class_hash_body *hash_body,
         RETURN(0);
 }
 
         RETURN(0);
 }
 
+typedef void (*hash_item_iterate_cb) (void *obj, void *data);
+
 int lustre_hash_init(struct lustre_class_hash_body **hash_body,
                      char *hashname, __u32 hashsize, 
                      struct lustre_hash_operations *hash_operations);
 void lustre_hash_exit(struct lustre_class_hash_body **hash_body);
 int lustre_hash_additem_unique(struct lustre_class_hash_body *hash_body, 
                                void *key, struct hlist_node *actual_hnode);
 int lustre_hash_init(struct lustre_class_hash_body **hash_body,
                      char *hashname, __u32 hashsize, 
                      struct lustre_hash_operations *hash_operations);
 void lustre_hash_exit(struct lustre_class_hash_body **hash_body);
 int lustre_hash_additem_unique(struct lustre_class_hash_body *hash_body, 
                                void *key, struct hlist_node *actual_hnode);
+void *lustre_hash_findadd_unique(struct lustre_class_hash_body *hash_body,
+                                 void *key, struct hlist_node *actual_hnode);
 int lustre_hash_additem(struct lustre_class_hash_body *hash_body, void *key, 
                         struct hlist_node *actual_hnode);
 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);
 int lustre_hash_additem(struct lustre_class_hash_body *hash_body, void *key, 
                         struct hlist_node *actual_hnode);
 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_iterate_all(struct lustre_class_hash_body *hash_body,
+                             hash_item_iterate_cb, void *data);
+
 void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
                                       void *key);
 
 void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
                                       void *key);
 
+__u32 djb2_hashfn(struct lustre_class_hash_body *hash_body, void* key,
+                  size_t size);
+
 /* ( uuid <-> export ) hash operations define */
 __u32 uuid_hashfn(struct lustre_class_hash_body *hash_body,  void * key);
 int uuid_hash_key_compare(void *key, struct hlist_node * compared_hnode);
 /* ( uuid <-> export ) hash operations define */
 __u32 uuid_hashfn(struct lustre_class_hash_body *hash_body,  void * key);
 int uuid_hash_key_compare(void *key, struct hlist_node * compared_hnode);
@@ -114,4 +129,10 @@ int conn_hash_key_compare(void *key, struct hlist_node * compared_hnode);
 void * conn_refcount_get(struct hlist_node * actual_hnode);
 void conn_refcount_put(struct hlist_node * actual_hnode);
 
 void * conn_refcount_get(struct hlist_node * actual_hnode);
 void conn_refcount_put(struct hlist_node * actual_hnode);
 
+/* ( nid <-> nidstats ) hash operations define. uses nid_hashfn */
+int nidstats_hash_key_compare(void *key, struct hlist_node * compared_hnode);
+void* nidstats_refcount_get(struct hlist_node * actual_hnode);
+void nidstats_refcount_put(struct hlist_node * actual_hnode);
+extern struct lustre_hash_operations nid_stat_hash_operations;
+
 #endif /* __CLASS_HASH_H */
 #endif /* __CLASS_HASH_H */
index 3dc9416..5b06fce 100644 (file)
@@ -355,8 +355,21 @@ 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;
                                  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_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_per_client_stats(struct obd_device *obd);
+extern int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
+                                         unsigned long count, void *data);
+extern int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
+                                        int count, int *eof,  void *data);
+
 extern int lprocfs_register_stats(cfs_proc_dir_entry_t *root, const char *name,
                                   struct lprocfs_stats *stats);
 
 extern int lprocfs_register_stats(cfs_proc_dir_entry_t *root, const char *name,
                                   struct lprocfs_stats *stats);
 
@@ -377,6 +390,10 @@ 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_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_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, 
 extern struct file_operations lprocfs_evict_client_fops;
 
 extern int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, 
@@ -566,10 +583,28 @@ static inline void lprocfs_free_obd_stats(struct obd_device *obddev)
 { return; }
 
 struct obd_export;
 { 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_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_per_client_stats(struct obd_device *obd)
+{}
+static inline
+int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
+                                  unsigned long count, void *data)
+{return count;}
+static inline
+int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off,
+                                 int count, int *eof,  void *data)
+{return count;}
 
 static inline cfs_proc_dir_entry_t *
 lprocfs_register(const char *name, cfs_proc_dir_entry_t *parent,
 
 static inline cfs_proc_dir_entry_t *
 lprocfs_register(const char *name, cfs_proc_dir_entry_t *parent,
index 7e4c8b9..7446321 100644 (file)
@@ -77,6 +77,17 @@ struct filter_export_data {
         struct brw_stats           fed_brw_stats;
 };
 
         struct brw_stats           fed_brw_stats;
 };
 
+typedef struct nid_stat {
+        lnet_nid_t               nid;
+        struct hlist_node        nid_hash;
+        struct list_head         nid_list;
+        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;
 struct obd_export {
         struct portals_handle     exp_handle;
         atomic_t                  exp_refcount;
@@ -89,8 +100,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 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_md_stats;
         struct lprocfs_stats     *exp_ldlm_stats;
         struct ptlrpc_connection *exp_connection;
         struct lprocfs_stats     *exp_md_stats;
         struct lprocfs_stats     *exp_ldlm_stats;
         struct ptlrpc_connection *exp_connection;
index a5e0db1..f146ba4 100644 (file)
@@ -984,7 +984,8 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg);
 int client_obd_cleanup(struct obd_device *obddev);
 int client_connect_import(const struct lu_env *env,
                           struct lustre_handle *conn, struct obd_device *obd,
 int client_obd_cleanup(struct obd_device *obddev);
 int client_connect_import(const struct lu_env *env,
                           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);
 int client_disconnect_export(struct obd_export *exp);
 int client_import_add_conn(struct obd_import *imp, struct obd_uuid *uuid,
                            int priority);
index 0f55ecd..14f88ca 100644 (file)
@@ -883,11 +883,15 @@ struct obd_device {
         /* uuid-export hash body */
         struct lustre_class_hash_body *obd_uuid_hash_body;
         /* nid-export hash body */
         /* uuid-export hash body */
         struct lustre_class_hash_body *obd_uuid_hash_body;
         /* nid-export hash body */
-        struct lustre_class_hash_body *obd_nid_hash_body; 
-        atomic_t obd_refcount;
+        struct lustre_class_hash_body *obd_nid_hash_body;
+        /* nid stats body */
+        struct lustre_class_hash_body *obd_nid_stats_hash_body;
+        struct list_head        obd_nid_stats;
+        atomic_t                obd_refcount;
         cfs_waitq_t             obd_refcount_waitq;
         struct list_head        obd_exports;
         int                     obd_num_exports;
         cfs_waitq_t             obd_refcount_waitq;
         struct list_head        obd_exports;
         int                     obd_num_exports;
+        spinlock_t              obd_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 */
         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 */
@@ -956,10 +960,9 @@ struct obd_device {
         struct lprocfs_stats  *md_stats;
 
         cfs_proc_dir_entry_t  *obd_proc_entry;
         struct lprocfs_stats  *md_stats;
 
         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_svc_stats;
         cfs_proc_dir_entry_t  *obd_svc_procroot;
         struct lprocfs_stats  *obd_svc_stats;
-        struct semaphore       obd_proc_exp_sem;
         atomic_t               obd_evict_inprogress;
         cfs_waitq_t            obd_evict_inprogress_waitq;
 };
         atomic_t               obd_evict_inprogress;
         cfs_waitq_t            obd_evict_inprogress_waitq;
 };
@@ -1073,7 +1076,8 @@ struct obd_ops {
          * asked for. If @ocd == NULL, use default parameters. */
         int (*o_connect)(const struct lu_env *env,
                          struct lustre_handle *conn, struct obd_device *src,
          * asked for. If @ocd == NULL, use default parameters. */
         int (*o_connect)(const struct lu_env *env,
                          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)(const struct lu_env *env,
                            struct obd_export *exp, struct obd_device *src,
                            struct obd_uuid *cluuid,
         int (*o_reconnect)(const struct lu_env *env,
                            struct obd_export *exp, struct obd_device *src,
                            struct obd_uuid *cluuid,
index edf8899..76ce36b 100644 (file)
@@ -269,9 +269,10 @@ do {                                                            \
                         OBD_COUNTER_OFFSET(op);                              \
                 LASSERT(coffset < (export)->exp_obd->obd_stats->ls_num);     \
                 lprocfs_counter_incr((export)->exp_obd->obd_stats, coffset); \
                         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(                                \
                         lprocfs_counter_incr(                                \
-                                (export)->exp_ops_stats, coffset);           \
+                                (export)->exp_nid_stats->nid_stats, coffset);\
         }
 
 #define MD_COUNTER_OFFSET(op)                                   \
         }
 
 #define MD_COUNTER_OFFSET(op)                                   \
@@ -793,7 +794,8 @@ static inline int obd_del_conn(struct obd_import *imp, struct obd_uuid *uuid)
 static inline int obd_connect(const struct lu_env *env,
                               struct lustre_handle *conn,struct obd_device *obd,
                               struct obd_uuid *cluuid,
 static inline int obd_connect(const struct lu_env *env,
                               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;
 #ifdef LIBCFS_DEBUG
 {
         int rc;
 #ifdef LIBCFS_DEBUG
@@ -806,7 +808,7 @@ static inline int obd_connect(const struct lu_env *env,
         OBD_CHECK_DT_OP(obd, connect, -EOPNOTSUPP);
         OBD_COUNTER_INCREMENT(obd, connect);
 
         OBD_CHECK_DT_OP(obd, connect, -EOPNOTSUPP);
         OBD_COUNTER_INCREMENT(obd, connect);
 
-        rc = OBP(obd, connect)(env, conn, obd, cluuid, d);
+        rc = OBP(obd, connect)(env, conn, obd, cluuid, d, localdata);
         /* check that only subset is granted */
         LASSERT(ergo(d != NULL,
                      (d->ocd_connect_flags & ocf) == d->ocd_connect_flags));
         /* check that only subset is granted */
         LASSERT(ergo(d != NULL,
                      (d->ocd_connect_flags & ocf) == d->ocd_connect_flags));
index 14bbf0c..e188385 100644 (file)
@@ -372,7 +372,7 @@ int client_obd_cleanup(struct obd_device *obddev)
 int client_connect_import(const struct lu_env *env,
                           struct lustre_handle *dlm_handle,
                           struct obd_device *obd, struct obd_uuid *cluuid,
 int client_connect_import(const struct lu_env *env,
                           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;
 {
         struct client_obd *cli = &obd->u.cli;
         struct obd_import *imp = cli->cl_import;
@@ -591,6 +591,7 @@ int target_handle_connect(struct ptlrpc_request *req)
         int rc = 0;
         int initial_conn = 0;
         struct obd_connect_data *data, *tmpdata;
         int rc = 0;
         int initial_conn = 0;
         struct obd_connect_data *data, *tmpdata;
+        lnet_nid_t client_nid = 0;
         ENTRY;
 
         OBD_RACE(OBD_FAIL_TGT_CONN_RACE);
         ENTRY;
 
         OBD_RACE(OBD_FAIL_TGT_CONN_RACE);
@@ -790,6 +791,7 @@ int target_handle_connect(struct ptlrpc_request *req)
         /* Tell the client if we support replayable requests */
         if (target->obd_replayable)
                 lustre_msg_add_op_flags(req->rq_repmsg, MSG_CONNECT_REPLAYABLE);
         /* 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) {
 
         if (export == NULL) {
                 if (target->obd_recovering) {
@@ -807,7 +809,8 @@ int target_handle_connect(struct ptlrpc_request *req)
                 } else {
 dont_check_exports:
                         rc = obd_connect(req->rq_svc_thread->t_env,
                 } else {
 dont_check_exports:
                         rc = obd_connect(req->rq_svc_thread->t_env,
-                                         &conn, target, &cluuid, data);
+                                         &conn, target, &cluuid, data,
+                                         &client_nid);
                 }
         } else {
                 rc = obd_reconnect(req->rq_svc_thread->t_env,
                 }
         } else {
                 rc = obd_reconnect(req->rq_svc_thread->t_env,
index 3c7c3b0..9aa5498 100644 (file)
@@ -163,7 +163,7 @@ int liblustre_process_log(struct config_llog_instance *cfg,
 #endif
         ocd->ocd_version = LUSTRE_VERSION_CODE;
 
 #endif
         ocd->ocd_version = LUSTRE_VERSION_CODE;
 
-        rc = obd_connect(NULL, &mgc_conn, obd, &mgc_uuid, ocd);
+        rc = obd_connect(NULL, &mgc_conn, obd, &mgc_uuid, ocd, NULL);
         if (rc) {
                 CERROR("cannot connect to %s at %s: rc = %d\n",
                        LUSTRE_MGS_OBDNAME, mgsnid, rc);
         if (rc) {
                 CERROR("cannot connect to %s at %s: rc = %d\n",
                        LUSTRE_MGS_OBDNAME, mgsnid, rc);
index cb7284b..dc574f7 100644 (file)
@@ -2080,7 +2080,7 @@ llu_fsswop_mount(const char *source,
         ocd.ocd_version = LUSTRE_VERSION_CODE;
 
         /* setup mdc */
         ocd.ocd_version = LUSTRE_VERSION_CODE;
 
         /* setup mdc */
-        err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, &ocd);
+        err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, &ocd, NULL);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", mdc, err);
                 GOTO(out_free, err);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", mdc, err);
                 GOTO(out_free, err);
@@ -2111,7 +2111,7 @@ llu_fsswop_mount(const char *source,
                                 OBD_CONNECT_VERSION | OBD_CONNECT_TRUNCLOCK |
                                 OBD_CONNECT_FID;
         ocd.ocd_version = LUSTRE_VERSION_CODE;
                                 OBD_CONNECT_VERSION | OBD_CONNECT_TRUNCLOCK |
                                 OBD_CONNECT_FID;
         ocd.ocd_version = LUSTRE_VERSION_CODE;
-        err = obd_connect(NULL, &dt_conn, obd, &sbi->ll_sb_uuid, &ocd);
+        err = obd_connect(NULL, &dt_conn, obd, &sbi->ll_sb_uuid, &ocd, NULL);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", osc, err);
                 GOTO(out_md, err);
         if (err) {
                 CERROR("cannot connect to %s: rc = %d\n", osc, err);
                 GOTO(out_md, err);
index 52e89e9..dd9d7e8 100644 (file)
@@ -240,7 +240,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
                 data->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
         }
 
                 data->ocd_connect_flags |= OBD_CONNECT_LCL_CLIENT;
         }
 
-        err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, data);
+        err = obd_connect(NULL, &md_conn, obd, &sbi->ll_sb_uuid, data, NULL);
         if (err == -EBUSY) {
                 LCONSOLE_ERROR_MSG(0x14f, "An MDT (md %s) is performing "
                                    "recovery, of which this client is not a "
         if (err == -EBUSY) {
                 LCONSOLE_ERROR_MSG(0x14f, "An MDT (md %s) is performing "
                                    "recovery, of which this client is not a "
@@ -394,7 +394,7 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt)
         obd->obd_upcall.onu_upcall = ll_ocd_update;
         data->ocd_brw_size = PTLRPC_MAX_BRW_PAGES << CFS_PAGE_SHIFT;
 
         obd->obd_upcall.onu_upcall = ll_ocd_update;
         data->ocd_brw_size = PTLRPC_MAX_BRW_PAGES << CFS_PAGE_SHIFT;
 
-        err = obd_connect(NULL, &dt_conn, obd, &sbi->ll_sb_uuid, data);
+        err = obd_connect(NULL, &dt_conn, obd, &sbi->ll_sb_uuid, data, NULL);
         if (err == -EBUSY) {
                 LCONSOLE_ERROR_MSG(0x150, "An OST (dt %s) is performing "
                                    "recovery, of which this client is not a "
         if (err == -EBUSY) {
                 LCONSOLE_ERROR_MSG(0x150, "An OST (dt %s) is performing "
                                    "recovery, of which this client is not a "
index 8013d50..e482f4a 100644 (file)
@@ -219,7 +219,8 @@ static int lmv_notify(struct obd_device *obd, struct obd_device *watched,
  * caller that everything is okay. Real connection will be performed later. */
 static int lmv_connect(const struct lu_env *env,
                        struct lustre_handle *conn, struct obd_device *obd,
  * caller that everything is okay. Real connection will be performed later. */
 static int lmv_connect(const struct lu_env *env,
                        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)
 {
 #ifdef __KERNEL__
         struct proc_dir_entry *lmv_proc_dir;
 {
 #ifdef __KERNEL__
         struct proc_dir_entry *lmv_proc_dir;
@@ -388,7 +389,7 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt)
         }
 
         rc = obd_connect(NULL, &conn, mdc_obd, &lmv_mdc_uuid,
         }
 
         rc = obd_connect(NULL, &conn, mdc_obd, &lmv_mdc_uuid,
-                         &lmv->conn_data);
+                         &lmv->conn_data, NULL);
         if (rc) {
                 CERROR("target %s connect error %d\n", tgt->ltd_uuid.uuid, rc);
                 RETURN(rc);
         if (rc) {
                 CERROR("target %s connect error %d\n", tgt->ltd_uuid.uuid, rc);
                 RETURN(rc);
index 9a3c759..d594d20 100644 (file)
@@ -148,7 +148,7 @@ static int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
                 RETURN(0);
         }
 
                 RETURN(0);
         }
 
-        rc = obd_connect(NULL, &conn, tgt_obd, &lov_osc_uuid, data);
+        rc = obd_connect(NULL, &conn, tgt_obd, &lov_osc_uuid, data, NULL);
         if (rc) {
                 CERROR("Target %s connect error %d\n",
                        obd_uuid2str(&tgt_uuid), rc);
         if (rc) {
                 CERROR("Target %s connect error %d\n",
                        obd_uuid2str(&tgt_uuid), rc);
@@ -212,7 +212,8 @@ static int lov_connect_obd(struct obd_device *obd, __u32 index, int activate,
 
 static int lov_connect(const struct lu_env *env,
                        struct lustre_handle *conn, struct obd_device *obd,
 
 static int lov_connect(const struct lu_env *env,
                        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;
 {
         struct lov_obd *lov = &obd->u.lov;
         struct lov_tgt_desc *tgt;
index f1d65f4..4ab58bd 100644 (file)
@@ -1761,7 +1761,8 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc,
 static int mdc_connect(const struct lu_env *env,
                        struct lustre_handle *dlm_handle,
                        struct obd_device *obd, struct obd_uuid *cluuid,
 static int mdc_connect(const struct lu_env *env,
                        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 obd_import *imp = obd->u.cli.cl_import;
 
 {
         struct obd_import *imp = obd->u.cli.cl_import;
 
@@ -1775,7 +1776,7 @@ static int mdc_connect(const struct lu_env *env,
                        obd->obd_name);
         }
 
                        obd->obd_name);
         }
 
-        return client_connect_import(env, dlm_handle, obd, cluuid, data);
+        return client_connect_import(env, dlm_handle, obd, cluuid, data, NULL);
 }
 
 struct obd_ops mdc_obd_ops = {
 }
 
 struct obd_ops mdc_obd_ops = {
index fae6cd3..0f3fdf2 100644 (file)
@@ -313,11 +313,13 @@ static int mds_reconnect(const struct lu_env *env,
  */
 static int mds_connect(const struct lu_env *env,
                        struct lustre_handle *conn, struct obd_device *obd,
  */
 static int mds_connect(const struct lu_env *env,
                        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;
 {
         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;
         ENTRY;
 
         int rc;
         ENTRY;
 
@@ -354,7 +356,7 @@ static int mds_connect(const struct lu_env *env,
         memcpy(mcd->mcd_uuid, cluuid, sizeof(mcd->mcd_uuid));
         med->med_mcd = mcd;
 
         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:
         GOTO(out, rc);
 
 out:
@@ -2011,8 +2013,8 @@ static int mds_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
             lprocfs_alloc_obd_stats(obd, LPROC_MDS_LAST) == 0) {
                 /* Init private stats here */
                 mds_stats_counter_init(obd->obd_stats);
             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);
         }
 
         rc = mds_fs_setup(obd, mnt);
@@ -2022,6 +2024,11 @@ static int mds_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
                 GOTO(err_ns, rc);
         }
 
                 GOTO(err_ns, rc);
         }
 
+        if (obd->obd_proc_exports_entry)
+                lprocfs_add_simple(obd->obd_proc_exports_entry,
+                                   "clear", lprocfs_nid_stats_clear_read,
+                                   lprocfs_nid_stats_clear_write, obd);
+
         rc = mds_lov_presetup(mds, lcfg);
         if (rc < 0)
                 GOTO(err_fs, rc);
         rc = mds_lov_presetup(mds, lcfg);
         if (rc < 0)
                 GOTO(err_fs, rc);
@@ -2099,8 +2106,8 @@ err_fs:
         mds->mds_group_hash = NULL;
 #endif
 err_ns:
         mds->mds_group_hash = NULL;
 #endif
 err_ns:
-        lprocfs_obd_cleanup(obd);
         lprocfs_free_obd_stats(obd);
         lprocfs_free_obd_stats(obd);
+        lprocfs_obd_cleanup(obd);
         ldlm_namespace_free(obd->obd_namespace, 0);
         obd->obd_namespace = NULL;
 err_ops:
         ldlm_namespace_free(obd->obd_namespace, 0);
         obd->obd_namespace = NULL;
 err_ops:
@@ -2274,8 +2281,10 @@ static int mds_cleanup(struct obd_device *obd)
                    we just need to drop our ref */
                 class_export_put(mds->mds_osc_exp);
 
                    we just need to drop our ref */
                 class_export_put(mds->mds_osc_exp);
 
-        lprocfs_obd_cleanup(obd);
+        remove_proc_entry("clear", obd->obd_proc_exports_entry);
+        lprocfs_free_per_client_stats(obd);
         lprocfs_free_obd_stats(obd);
         lprocfs_free_obd_stats(obd);
+        lprocfs_obd_cleanup(obd);
 
         lquota_cleanup(mds_quota_interface_ref, obd);
 
 
         lquota_cleanup(mds_quota_interface_ref, obd);
 
index 3e9dd72..594e8e9 100644 (file)
@@ -361,8 +361,11 @@ struct lprocfs_vars lprocfs_mdt_module_vars[] = {
 
 void mds_counter_incr(struct obd_export *exp, int opcode)
 {
 
 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)
 }
 
 void mds_stats_counter_init(struct lprocfs_stats *stats)
index 0bed7d1..64549a3 100644 (file)
 #include "mds_internal.h"
 
 
 #include "mds_internal.h"
 
 
-static int mds_export_stats_init(struct obd_device *obd, struct obd_export *exp)
+static int mds_export_stats_init(struct obd_device *obd,
+                                 struct obd_export *exp,
+                                 lnet_nid_t client_nid)
 {
 {
-        int rc, num_stats;
-
-        rc = lprocfs_exp_setup(exp);
+        int rc, num_stats, newnid;
+        rc = lprocfs_exp_setup(exp, client_nid, &newnid);
         if (rc)
                 return rc;
         if (rc)
                 return rc;
-        num_stats = (sizeof(*obd->obd_type->typ_dt_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_dt_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;
 }
 
         return 0;
 }
 
@@ -76,7 +86,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,
  * 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;
 {
         struct mds_obd *mds = &obd->u.mds;
         struct mds_export_data *med = &exp->exp_mds_data;
@@ -123,7 +133,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);
         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;
 
         if (new_client) {
                 struct lvfs_run_ctxt saved;
@@ -403,7 +413,7 @@ static int mds_init_server_data(struct obd_device *obd, struct file *file)
                 } else {
                         med = &exp->exp_mds_data;
                         med->med_mcd = mcd;
                 } 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);
                         LASSERTF(rc == 0, "rc = %d\n", rc); /* can't fail existing */
 
                         mcd = NULL;
                         LASSERTF(rc == 0, "rc = %d\n", rc); /* can't fail existing */
 
                         mcd = NULL;
@@ -632,7 +642,6 @@ err_fid:
         goto err_pop;
 }
 
         goto err_pop;
 }
 
-
 int mds_fs_cleanup(struct obd_device *obd)
 {
         struct mds_obd *mds = &obd->u.mds;
 int mds_fs_cleanup(struct obd_device *obd)
 {
         struct mds_obd *mds = &obd->u.mds;
index 95efae2..4ed5035 100644 (file)
@@ -220,7 +220,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 */
                   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);
 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);
index 3d60faa..91dcd33 100644 (file)
@@ -518,7 +518,7 @@ int mds_lov_connect(struct obd_device *obd, char * lov_name)
         data->ocd_version = LUSTRE_VERSION_CODE;
         data->ocd_group = mds->mds_id +  FILTER_GROUP_MDS0;
         /* NB: lov_connect() needs to fill in .ocd_index for each OST */
         data->ocd_version = LUSTRE_VERSION_CODE;
         data->ocd_group = mds->mds_id +  FILTER_GROUP_MDS0;
         /* NB: lov_connect() needs to fill in .ocd_index for each OST */
-        rc = obd_connect(NULL, &conn, mds->mds_osc_obd, &obd->obd_uuid, data);
+        rc = obd_connect(NULL, &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);
         OBD_FREE(data, sizeof(*data));
         if (rc) {
                 CERROR("MDS cannot connect to LOV %s (%d)\n", lov_name, rc);
index 61a23b2..ce2e274 100644 (file)
@@ -4182,7 +4182,8 @@ static int mdt_connect_internal(struct obd_export *exp,
 static int mdt_obd_connect(const struct lu_env *env,
                            struct lustre_handle *conn, struct obd_device *obd,
                            struct obd_uuid *cluuid,
 static int mdt_obd_connect(const struct lu_env *env,
                            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 mdt_thread_info *info;
         struct mdt_client_data *mcd;
 {
         struct mdt_thread_info *info;
         struct mdt_client_data *mcd;
index 8ace822..f5586c2 100644 (file)
@@ -85,7 +85,7 @@ int lproc_mgs_setup(struct obd_device *obd)
         rc = lprocfs_obd_seq_create(obd, "filesystems", 0444,
                                     &mgs_fs_fops, obd);
         mgs->mgs_proc_live = proc_mkdir("live", obd->obd_proc_entry);
         rc = lprocfs_obd_seq_create(obd, "filesystems", 0444,
                                     &mgs_fs_fops, obd);
         mgs->mgs_proc_live = proc_mkdir("live", obd->obd_proc_entry);
-        obd->obd_proc_exports = proc_mkdir("exports", obd->obd_proc_entry);
+        obd->obd_proc_exports_entry = proc_mkdir("exports", obd->obd_proc_entry);
 
         return rc;
 }
 
         return rc;
 }
@@ -214,7 +214,8 @@ struct lprocfs_vars lprocfs_mgs_module_vars[] = {
 void mgs_counter_incr(struct obd_export *exp, int opcode)
 {
         lprocfs_counter_incr(exp->exp_obd->obd_stats, opcode);
 void mgs_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_nid_stats && exp->exp_nid_stats->nid_stats != NULL)
+                lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode);
 }
 
 void mgs_stats_counter_init(struct lprocfs_stats *stats)
 }
 
 void mgs_stats_counter_init(struct lprocfs_stats *stats)
index 4672540..582e55a 100644 (file)
@@ -50,7 +50,8 @@
 /* Establish a connection to the MGS.*/
 static int mgs_connect(const struct lu_env *env,
                        struct lustre_handle *conn, struct obd_device *obd,
 /* Establish a connection to the MGS.*/
 static int mgs_connect(const struct lu_env *env,
                        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;
 {
         struct obd_export *exp;
         int rc;
index 766e16d..a66bad5 100644 (file)
@@ -39,7 +39,7 @@ int lustre_hash_init(struct lustre_class_hash_body **hash_body_new,
                         n++;
                 i >>= 1;
         }
                         n++;
                 i >>= 1;
         }
-        
+
         LASSERTF(n == 1, "hashsize %u isn't 2^n\n", hashsize);
 
         /* alloc space for hash_body */   
         LASSERTF(n == 1, "hashsize %u isn't 2^n\n", hashsize);
 
         /* alloc space for hash_body */   
@@ -59,7 +59,7 @@ int lustre_hash_init(struct lustre_class_hash_body **hash_body_new,
 
         /* alloc space for the hash tables */
         OBD_ALLOC(hash_body->lchb_hash_tables, 
 
         /* alloc space for the hash tables */
         OBD_ALLOC(hash_body->lchb_hash_tables, 
-                  sizeof(*hash_body->lchb_hash_tables) * hash_body->lchb_hash_max_size);     
+                  sizeof(*hash_body->lchb_hash_tables) * hash_body->lchb_hash_max_size);
 
         if (hash_body->lchb_hash_tables == NULL) {
                 OBD_FREE(hash_body, sizeof(*hash_body)); 
 
         if (hash_body->lchb_hash_tables == NULL) {
                 OBD_FREE(hash_body, sizeof(*hash_body)); 
@@ -178,6 +178,53 @@ int lustre_hash_additem_unique(struct lustre_class_hash_body *hash_body,
 EXPORT_SYMBOL(lustre_hash_additem_unique);
 
 /*
 EXPORT_SYMBOL(lustre_hash_additem_unique);
 
 /*
+ * only allow unique @key in hashtables, if the same @key has existed
+ * in hashtables, it will return with fails.
+ */
+void* lustre_hash_findadd_unique(struct lustre_class_hash_body *hash_body,
+                                     void *key, struct hlist_node *actual_hnode)
+{
+        int hashent;
+        struct lustre_hash_bucket *bucket = NULL;
+        struct lustre_hash_operations *hop = hash_body->lchb_hash_operations;
+        struct hlist_node * hash_item_hnode = NULL;
+        void *obj;
+        ENTRY;
+
+        LASSERT(hlist_unhashed(actual_hnode));
+        hashent = hop->lustre_hashfn(hash_body, key);
+
+        /* get the hash-bucket and lock it */
+        bucket = &hash_body->lchb_hash_tables[hashent];
+        spin_lock(&bucket->lhb_lock);
+
+        hash_item_hnode = lustre_hash_getitem_in_bucket_nolock(hash_body,
+                                                               hashent, key);
+        if ( hash_item_hnode != NULL) {
+                /* the added-item exist in hashtables, so cannot add it again */
+                obj = hop->lustre_hash_object_refcount_get(hash_item_hnode);
+                spin_unlock(&bucket->lhb_lock);
+                RETURN(obj);
+        }
+
+        hlist_add_head(actual_hnode, &(bucket->lhb_head));
+
+#ifdef LUSTRE_HASH_DEBUG
+        /* hash distribute debug */
+        hash_body->lchb_hash_tables[hashent].lhb_item_count++;
+        CDEBUG(D_INFO, "hashname[%s] bucket[%d] has [%d] hashitem\n",
+                        hash_body->hashname, hashent,
+                        hash_body->lchb_hash_tables[hashent].lhb_item_count);
+#endif
+        obj = hop->lustre_hash_object_refcount_get(actual_hnode);
+
+        spin_unlock(&bucket->lhb_lock);
+
+        RETURN(obj);
+}
+EXPORT_SYMBOL(lustre_hash_findadd_unique);
+
+/*
  * this version of additem, it allow multi same @key <key, value> in hashtables. 
  * in this additem version, we don't need to check if exist same @key in hash 
  * tables, we only add it to related hashbucket.
  * this version of additem, it allow multi same @key <key, value> in hashtables. 
  * in this additem version, we don't need to check if exist same @key in hash 
  * tables, we only add it to related hashbucket.
@@ -286,6 +333,62 @@ int lustre_hash_delitem(struct lustre_class_hash_body *hash_body,
 }
 EXPORT_SYMBOL(lustre_hash_delitem);
 
 }
 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 = hop->lustre_hash_object_refcount_get(hash_item_node);
+                        func(tmp, data);
+                        hop->lustre_hash_object_refcount_put(hash_item_node);
+                }
+        }
+        spin_unlock(&bucket->lhb_lock);
+}
+EXPORT_SYMBOL(lustre_hash_bucket_iterate);
+
+void lustre_hash_iterate_all(struct lustre_class_hash_body *hash_body,
+                            hash_item_iterate_cb func, void *data)
+{
+        int i;
+        struct lustre_hash_operations *hop = hash_body->lchb_hash_operations;
+        ENTRY;
+
+        for( i = 0; i < hash_body->lchb_hash_max_size; i++ ) {
+                struct lustre_hash_bucket * bucket;
+                struct hlist_node * actual_hnode, *pos;
+                void *obj;
+
+                bucket = &hash_body->lchb_hash_tables[i];
+#ifdef LUSTRE_HASH_DEBUG
+                CDEBUG(D_INFO, "idx %d - bucket %p\n", i, bucket);
+#endif
+                spin_lock(&bucket->lhb_lock); /* lock the bucket */
+                hlist_for_each_safe(actual_hnode, pos, &(bucket->lhb_head)) {
+                        obj = hop->lustre_hash_object_refcount_get(actual_hnode);
+                        func(obj, data);
+                        hop->lustre_hash_object_refcount_put(actual_hnode);
+                }
+                spin_unlock(&bucket->lhb_lock);
+        }
+        EXIT;
+}
+EXPORT_SYMBOL(lustre_hash_iterate_all);
+
+
 void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
                                      void *key)
 {
 void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
                                      void *key)
 {
@@ -317,6 +420,24 @@ void * lustre_hash_get_object_by_key(struct lustre_class_hash_body *hash_body,
 }
 EXPORT_SYMBOL(lustre_hash_get_object_by_key);
 
 }
 EXPORT_SYMBOL(lustre_hash_get_object_by_key);
 
+/* string hashing using djb2 hash algorithm */
+__u32 djb2_hashfn(struct lustre_class_hash_body *hash_body,  void* key,
+                  size_t size)
+{
+        __u32 hash = 5381;
+        int i;
+        char *ptr = key;
+
+        LASSERT(key != NULL);
+
+        for( i = 0; i < size; i++ )
+                hash = hash * 33 + ptr[i];
+
+        hash &= (hash_body->lchb_hash_max_size - 1);
+
+        RETURN(hash);
+}
+
 /*
  * define (uuid <-> export) hash operations and function define
  */
 /*
  * define (uuid <-> export) hash operations and function define
  */
@@ -329,26 +450,11 @@ struct lustre_hash_operations uuid_hash_operations = {
         .lustre_hash_object_refcount_put = uuid_export_refcount_put,
 };
 
         .lustre_hash_object_refcount_put = uuid_export_refcount_put,
 };
 
-/* string hashing using djb2 hash algorithm */
 __u32 uuid_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
 __u32 uuid_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
-        __u32 hash = 5381;
-        struct obd_uuid * uuid_key = NULL;
-        int c;
-        char *ptr = NULL;
-
-        LASSERT(key != NULL); 
+        struct obd_uuid * uuid_key = key;
 
 
-        uuid_key = (struct obd_uuid*)key;
-        ptr = uuid_key->uuid;
-
-        while ((c = *ptr++)) {
-                hash = hash * 33 + c;
-        }
-
-        hash &= (hash_body->lchb_hash_max_size - 1);
-
-        RETURN(hash);             
+        return djb2_hashfn(hash_body, uuid_key->uuid, sizeof(uuid_key->uuid));
 }
 
 /* Note, it is impossible to find an export that is in failed state with
 }
 
 /* Note, it is impossible to find an export that is in failed state with
@@ -410,21 +516,9 @@ struct lustre_hash_operations nid_hash_operations = {
         .lustre_hash_object_refcount_put = nid_export_refcount_put,
 };
 
         .lustre_hash_object_refcount_put = nid_export_refcount_put,
 };
 
-/* string hashing using djb2 hash algorithm */
 __u32 nid_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
 __u32 nid_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
-        __u32 hash = 5381;
-        int i;
-        char *ptr = key;
-
-        LASSERT(key != NULL); 
-
-        for(i = 0 ; i < sizeof(lnet_nid_t) ; i ++)
-                hash = hash * 33 + ptr[i];
-
-        hash &= (hash_body->lchb_hash_max_size - 1);
-
-        RETURN(hash);             
+        return djb2_hashfn(hash_body, key, sizeof(lnet_nid_t));
 }
 
 /* Note, it is impossible to find an export that is in failed state with
 }
 
 /* Note, it is impossible to find an export that is in failed state with
@@ -485,21 +579,9 @@ struct lustre_hash_operations conn_hash_operations = {
 };
 EXPORT_SYMBOL(conn_hash_operations);
 
 };
 EXPORT_SYMBOL(conn_hash_operations);
 
-/* string hashing using djb2 hash algorithm */
 __u32 conn_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
 __u32 conn_hashfn(struct lustre_class_hash_body *hash_body,  void * key)
 {
-        __u32 hash = 5381;
-        char *ptr = key;
-        int i;
-
-        LASSERT(key != NULL); 
-
-        for(i = 0 ; i < sizeof(lnet_process_id_t) ; i ++)
-                hash = hash * 33 + ptr[i];
-
-        hash &= (hash_body->lchb_hash_max_size - 1);
-
-        RETURN(hash);             
+        return djb2_hashfn(hash_body, key, sizeof(lnet_process_id_t));
 }
 
 int conn_hash_key_compare(void *key, struct hlist_node *compared_hnode)
 }
 
 int conn_hash_key_compare(void *key, struct hlist_node *compared_hnode)
@@ -545,3 +627,47 @@ void conn_refcount_put(struct hlist_node *actual_hnode)
         atomic_dec(&c->c_refcount);
 }
 
         atomic_dec(&c->c_refcount);
 }
 
+/*******************************************************************************/
+/* ( nid<>nidstats ) hash operations define */
+
+struct lustre_hash_operations nid_stat_hash_operations = {
+        .lustre_hashfn = nid_hashfn,
+        .lustre_hash_key_compare = nidstats_hash_key_compare,
+        .lustre_hash_object_refcount_get = nidstats_refcount_get,
+        .lustre_hash_object_refcount_put = nidstats_refcount_put,
+};
+EXPORT_SYMBOL(nid_stat_hash_operations);
+
+int nidstats_hash_key_compare(void *key, struct hlist_node * compared_hnode)
+{
+        struct nid_stat *data;
+        lnet_nid_t *nid_key;
+
+        LASSERT( key != NULL);
+
+        nid_key = (lnet_nid_t*)key;
+        data = hlist_entry(compared_hnode, struct nid_stat, nid_hash);
+
+        return (data->nid == *nid_key);
+}
+
+void* nidstats_refcount_get(struct hlist_node * actual_hnode)
+{
+        struct nid_stat *data;
+
+        data = hlist_entry(actual_hnode, struct nid_stat, nid_hash);
+        data->nid_exp_ref_count++;
+
+        RETURN(data);
+}
+
+void nidstats_refcount_put(struct hlist_node * actual_hnode)
+{
+        struct nid_stat *data;
+
+        data = hlist_entry(actual_hnode, struct nid_stat, nid_hash);
+        data->nid_exp_ref_count--;
+
+}
+
+/*******************************************************************************/
index 3a839f1..efb1228 100644 (file)
@@ -469,8 +469,8 @@ static int llog_test_6(struct obd_device *obd, char *name)
                 GOTO(ctxt_release, rc = -ENOENT);
         }
 
                 GOTO(ctxt_release, rc = -ENOENT);
         }
 
-        rc = obd_connect(NULL,
-                         &exph, mdc_obd, &uuid, NULL /* obd_connect_data */);
+        rc = obd_connect(NULL, &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);
         if (rc) {
                 CERROR("6: failed to connect to MDC: %s\n", mdc_obd->obd_name);
                 GOTO(ctxt_release, rc);
index 3801243..8f0ba51 100644 (file)
@@ -288,13 +288,13 @@ void lprocfs_remove(struct proc_dir_entry **rooth)
         struct proc_dir_entry *rm_entry;
         struct proc_dir_entry *parent;
 
         struct proc_dir_entry *rm_entry;
         struct proc_dir_entry *parent;
 
-        if (!root) 
+        if (!root)
                 return;
         *rooth = NULL;
 
         parent = root->parent;
         LASSERT(parent != NULL);
                 return;
         *rooth = NULL;
 
         parent = root->parent;
         LASSERT(parent != NULL);
+
         while (1) {
                 while (temp->subdir != NULL)
                         temp = temp->subdir;
         while (1) {
                 while (temp->subdir != NULL)
                         temp = temp->subdir;
@@ -312,7 +312,7 @@ void lprocfs_remove(struct proc_dir_entry **rooth)
                  * by _lprocfs_lock. */
                 down_write(&_lprocfs_lock);
                 rm_entry->data = NULL;
                  * by _lprocfs_lock. */
                 down_write(&_lprocfs_lock);
                 rm_entry->data = NULL;
-                remove_proc_entry(rm_entry->name, rm_entry->parent);
+                remove_proc_entry(rm_entry->name, temp);
                 up_write(&_lprocfs_lock);
                 if (temp == parent)
                         break;
                 up_write(&_lprocfs_lock);
                 if (temp == parent)
                         break;
@@ -681,15 +681,58 @@ int lprocfs_obd_cleanup(struct obd_device *obd)
 {
         if (!obd) 
                 return -EINVAL;
 {
         if (!obd) 
                 return -EINVAL;
-        if (obd->obd_proc_exports) {
+        if (obd->obd_proc_exports_entry) {
                 /* Should be no exports left */
                 /* 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;
 }
 
         }
         lprocfs_remove(&obd->obd_proc_entry);
         return 0;
 }
 
+void lprocfs_free_client_stats(void *obj, void *data)
+{
+        struct nid_stat *client_stat = obj;
+
+        CDEBUG(D_CONFIG, "stat %p - data %p/%p/%p\n", client_stat,
+               client_stat->nid_proc, client_stat->nid_stats,
+               client_stat->nid_brw_stats);
+
+        LASSERTF(client_stat->nid_exp_ref_count == 0, "count %d\n",
+                 client_stat->nid_exp_ref_count);
+
+        hlist_del_init(&client_stat->nid_hash);
+        list_del(&client_stat->nid_list);
+
+        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(*client_stat));
+        return;
+
+}
+
+void lprocfs_free_per_client_stats(struct obd_device *obd)
+{
+        struct nid_stat *stat;
+        ENTRY;
+
+        /* we need extra list - because hash_exit called to early */
+        while(!list_empty(&obd->obd_nid_stats)) {
+                stat = list_entry(obd->obd_nid_stats.next,
+                                  struct nid_stat, nid_list);
+                lprocfs_free_client_stats(stat, NULL);
+        }
+
+        EXIT;
+}
+
 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
                                           enum lprocfs_stats_flags flags)
 {
 struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num,
                                           enum lprocfs_stats_flags flags)
 {
@@ -766,7 +809,7 @@ void lprocfs_clear_stats(struct lprocfs_stats *stats)
         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
 
         for (i = 0; i < num_cpu; i++) {
         num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU);
 
         for (i = 0; i < num_cpu; i++) {
-                for (j = 0; j < stats->ls_num; j++) {        
+                for (j = 0; j < stats->ls_num; j++) {
                         percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
                         atomic_inc(&percpu_cntr->lc_cntl.la_entry);
                         percpu_cntr->lc_count = 0;
                         percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j];
                         atomic_inc(&percpu_cntr->lc_cntl.la_entry);
                         percpu_cntr->lc_count = 0;
@@ -1166,90 +1209,167 @@ int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count,
         return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
 }
 
         return snprintf(page, count, "%s\n", obd_export_nid2str(exp));
 }
 
+struct exp_uuid_cb_data {
+        char                   *page;
+        int                     count;
+        int                    *eof;
+        int                    *len;
+};
+
+void lprocfs_exp_print_uuid(void *obj, void *cb_data)
+{
+        struct obd_export *exp = (struct obd_export *)obj;
+        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));
+}
+
 int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count,
 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;
         *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;
+        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_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);
+
+void lprocfs_nid_stats_clear_write_cb(void *obj, void *data)
+{
+        struct nid_stat *client_stat = obj;
+        int i;
+        if(client_stat->nid_exp_ref_count == 1) {
+                hlist_del_init(&client_stat->nid_hash);
+                lprocfs_free_client_stats(client_stat, data);
+                OBD_FREE(client_stat, sizeof(struct nid_stat));
+                EXIT;
+                return;
+        }
+
+        /* we has reference to object - only clear data*/
+        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]);
+        }
+        EXIT;
+        return;
+}
+
+int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer,
+                                         unsigned long count, void *data)
 {
 {
-        char name[sizeof (exp->exp_client_uuid.uuid) + 3];
-        int i = 1, rc;
+        struct obd_device *obd = (struct obd_device *)data;
+        lustre_hash_iterate_all(obd->obd_nid_stats_hash_body,
+                                lprocfs_free_client_stats, NULL);
+        return count;
+}
+EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);
+
+int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t nid, int *newnid)
+{
+        int rc = 0;
+        struct nid_stat *tmp = NULL, *tmp1;
+        struct obd_device *obd = NULL;
         ENTRY;
         ENTRY;
-        if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports)
+
+        *newnid = 0;
+
+        if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry ||
+            !exp->exp_obd->obd_nid_stats_hash_body)
                 RETURN(-EINVAL);
                 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);
-        }
 
 
-        /* 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(0);
+
+        obd = exp->exp_obd;
+
+        CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash_body);
+
+        OBD_ALLOC(tmp, sizeof(struct nid_stat));
+        if (tmp == NULL)
+                RETURN(-ENOMEM);
+
+        tmp->nid = nid;
+        tmp->nid_obd = exp->exp_obd;
+        tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */
+
+        tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, &nid,
+                                         &tmp->nid_hash);
+        CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n",
+               tmp1, libcfs_nid2str(nid), tmp->nid_exp_ref_count);
+
+        if (tmp1 != tmp) {
+                exp->exp_nid_stats = tmp1;
+                GOTO(destroy_new, rc = 0);
+        }
+        /* not found - create */
+        tmp->nid_proc = proc_mkdir(libcfs_nid2str(nid),
+                                   obd->obd_proc_exports_entry);
+        if (!tmp->nid_proc) {
+                CERROR("Error making export directory for"
+                       " nid %s\n", libcfs_nid2str(nid));
+                lustre_hash_delitem(obd->obd_nid_stats_hash_body, &nid,
+                                    &tmp->nid_hash);
+                GOTO(destroy_new, rc = -ENOMEM);
         }
 
         }
 
-        /* Always add nid and uuid */
-        rc = lprocfs_add_simple(exp->exp_proc, "nid",
-                                lprocfs_exp_rd_nid, NULL, exp);
+        rc = lprocfs_add_simple(tmp->nid_proc, "uuid",
+                                lprocfs_exp_rd_uuid, NULL, tmp);
         if (rc)
         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);
-        }
+                CWARN("Error adding the uuid file\n");
 
 
-        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);
-out:
-        mutex_up(&exp->exp_obd->obd_proc_exp_sem);
+        spin_lock(&obd->obd_nid_lock);
+        list_add(&tmp->nid_list, &obd->obd_nid_stats);
+        spin_unlock(&obd->obd_nid_lock);
+
+        exp->exp_nid_stats = tmp;
+        *newnid = 1;
+        RETURN(rc);
+
+destroy_new:
+        OBD_FREE(tmp, sizeof(struct nid_stat));
         RETURN(rc);
 }
 
 int lprocfs_exp_cleanup(struct obd_export *exp)
 {
         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);
+        struct nid_stat *stat = exp->exp_nid_stats;
+
+        if(!stat)
+                RETURN(0);
+
+        stat->nid_exp_ref_count--;
+        CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count);
+
+        exp->exp_nid_stats = NULL;
         return 0;
 }
 
         return 0;
 }
 
@@ -1625,6 +1745,8 @@ EXPORT_SYMBOL(lprocfs_remove);
 EXPORT_SYMBOL(lprocfs_add_vars);
 EXPORT_SYMBOL(lprocfs_obd_setup);
 EXPORT_SYMBOL(lprocfs_obd_cleanup);
 EXPORT_SYMBOL(lprocfs_add_vars);
 EXPORT_SYMBOL(lprocfs_obd_setup);
 EXPORT_SYMBOL(lprocfs_obd_cleanup);
+EXPORT_SYMBOL(lprocfs_add_simple);
+EXPORT_SYMBOL(lprocfs_free_per_client_stats);
 EXPORT_SYMBOL(lprocfs_alloc_stats);
 EXPORT_SYMBOL(lprocfs_free_stats);
 EXPORT_SYMBOL(lprocfs_clear_stats);
 EXPORT_SYMBOL(lprocfs_alloc_stats);
 EXPORT_SYMBOL(lprocfs_free_stats);
 EXPORT_SYMBOL(lprocfs_clear_stats);
index def7410..ccaa00d 100644 (file)
@@ -170,9 +170,10 @@ int class_attach(struct lustre_cfg *lcfg)
 
         CFS_INIT_LIST_HEAD(&obd->obd_exports);
         CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
 
         CFS_INIT_LIST_HEAD(&obd->obd_exports);
         CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
+        CFS_INIT_LIST_HEAD(&obd->obd_nid_stats);
+        spin_lock_init(&obd->obd_nid_lock);
         spin_lock_init(&obd->obd_dev_lock);
         sema_init(&obd->obd_dev_sem, 1);
         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. */
         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. */
@@ -264,9 +265,8 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         /* create an uuid-export hash body */
         err = lustre_hash_init(&obd->obd_uuid_hash_body, "UUID_HASH", 
                                128, &uuid_hash_operations);
         /* create an uuid-export hash body */
         err = lustre_hash_init(&obd->obd_uuid_hash_body, "UUID_HASH", 
                                128, &uuid_hash_operations);
-        if (err) {
+        if (err)
                 GOTO(err_hash, err);
                 GOTO(err_hash, err);
-        }
 
         /* create a nid-export hash body */
         err = lustre_hash_init(&obd->obd_nid_hash_body, "NID_HASH", 
 
         /* create a nid-export hash body */
         err = lustre_hash_init(&obd->obd_nid_hash_body, "NID_HASH", 
@@ -274,9 +274,16 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
         if (err)
                 GOTO(err_hash, err);
 
         if (err)
                 GOTO(err_hash, err);
 
+        /* create a nid-stats hash body */
+        err = lustre_hash_init(&obd->obd_nid_stats_hash_body, "NID_STATS",
+                               128, &nid_stat_hash_operations);
+        if (err)
+                GOTO(err_hash, err);
+
         exp = class_new_export(obd, &obd->obd_uuid);
         if (IS_ERR(exp))
                 RETURN(PTR_ERR(exp));
         exp = class_new_export(obd, &obd->obd_uuid);
         if (IS_ERR(exp))
                 RETURN(PTR_ERR(exp));
+
         obd->obd_self_export = exp;
         list_del_init(&exp->exp_obd_chain_timed);
         class_export_put(exp);
         obd->obd_self_export = exp;
         list_del_init(&exp->exp_obd_chain_timed);
         class_export_put(exp);
@@ -303,6 +310,7 @@ err_exp:
 err_hash:
         lustre_hash_exit(&obd->obd_uuid_hash_body);
         lustre_hash_exit(&obd->obd_nid_hash_body);
 err_hash:
         lustre_hash_exit(&obd->obd_uuid_hash_body);
         lustre_hash_exit(&obd->obd_nid_hash_body);
+        lustre_hash_exit(&obd->obd_nid_stats_hash_body);
         obd->obd_starting = 0;
         CERROR("setup %s failed (%d)\n", obd->obd_name, err);
         RETURN(err);
         obd->obd_starting = 0;
         CERROR("setup %s failed (%d)\n", obd->obd_name, err);
         RETURN(err);
@@ -439,6 +447,9 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
         /* destroy a nid-export hash body */
         lustre_hash_exit(&obd->obd_nid_hash_body);
 
         /* destroy a nid-export hash body */
         lustre_hash_exit(&obd->obd_nid_hash_body);
 
+        /* destroy a nid-stats hash body */
+        lustre_hash_exit(&obd->obd_nid_stats_hash_body);
+
         /* Precleanup stage 1, we must make sure all exports (other than the
            self-export) get destroyed. */
         err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
         /* Precleanup stage 1, we must make sure all exports (other than the
            self-export) get destroyed. */
         err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
index 5f3d6ff..db8ca47 100644 (file)
@@ -727,7 +727,7 @@ static int lustre_start_mgc(struct super_block *sb)
         ocd.ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_FID;
         ocd.ocd_version = LUSTRE_VERSION_CODE;
 
         ocd.ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_FID;
         ocd.ocd_version = LUSTRE_VERSION_CODE;
 
-        rc = obd_connect(NULL, &mgc_conn, obd, &(obd->obd_uuid), &ocd);
+        rc = obd_connect(NULL, &mgc_conn, obd, &(obd->obd_uuid), &ocd, NULL);
         if (rc) {
                 CERROR("connect failed %d\n", rc);
                 GOTO(out, rc);
         if (rc) {
                 CERROR("connect failed %d\n", rc);
                 GOTO(out, rc);
index 55828ec..2fe7c07 100644 (file)
@@ -51,7 +51,8 @@ enum {
 
 static int echo_connect(const struct lu_env *env,
                         struct lustre_handle *conn, struct obd_device *obd,
 
 static int echo_connect(const struct lu_env *env,
                         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);
 {
         data->ocd_connect_flags &= ECHO_CONNECT_SUPPORTED;
         return class_connect(conn, obd, cluuid);
index 142aef3..f0c6fb4 100644 (file)
@@ -1315,7 +1315,7 @@ static int echo_client_setup(struct obd_device *obddev, struct lustre_cfg *lcfg)
         ocd->ocd_version = LUSTRE_VERSION_CODE;
         ocd->ocd_group = FILTER_GROUP_ECHO;
 
         ocd->ocd_version = LUSTRE_VERSION_CODE;
         ocd->ocd_group = FILTER_GROUP_ECHO;
 
-        rc = obd_connect(NULL, &conn, tgt, &echo_uuid, ocd);
+        rc = obd_connect(NULL, &conn, tgt, &echo_uuid, ocd, NULL);
 
         OBD_FREE(ocd, sizeof(*ocd));
 
 
         OBD_FREE(ocd, sizeof(*ocd));
 
@@ -1363,7 +1363,7 @@ static int echo_client_cleanup(struct obd_device *obddev)
 static int echo_client_connect(const struct lu_env *env,
                                struct lustre_handle *conn,
                                struct obd_device *src, struct obd_uuid *cluuid,
 static int echo_client_connect(const struct lu_env *env,
                                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;
 {
         struct obd_export *exp;
         int                rc;
index 24d3ff9..a1597f3 100644 (file)
@@ -160,14 +160,35 @@ static void init_brw_stats(struct brw_stats *brw_stats)
                 spin_lock_init(&brw_stats->hist[i].oh_lock);
 }
 
                 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_dt_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,
 /* 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;
 {
         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);
         ENTRY;
 
         init_brw_stats(&fed->fed_brw_stats);
@@ -176,30 +197,38 @@ static int filter_export_stats_init(struct obd_device *obd,
                 /* Self-export gets no proc entry */
                 RETURN(0);
 
                 /* 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);
 
         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_dt_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);
 }
 
         RETURN(0);
 }
 
@@ -208,7 +237,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,
  * 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;
 {
         struct filter_obd *filter = &obd->u.filter;
         struct filter_export_data *fed = &exp->exp_filter_data;
@@ -772,8 +801,8 @@ static int filter_init_server_data(struct obd_device *obd, struct file * filp)
                         fed = &exp->exp_filter_data;
                         fed->fed_fcd = fcd;
                         fed->fed_group = le32_to_cpu(fcd->fcd_group);
                         fed = &exp->exp_filter_data;
                         fed->fed_fcd = fcd;
                         fed->fed_group = le32_to_cpu(fcd->fcd_group);
-                        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);
 
                         /* can't fail for existing client */
                         LASSERTF(rc == 0, "rc = %d\n", rc);
 
@@ -2083,9 +2112,13 @@ static int filter_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
                                      "write_bytes", "bytes");
 
                 lproc_filter_attach_seqstat(obd);
                                      "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",
+                                   lprocfs_nid_stats_clear_read,
+                                   lprocfs_nid_stats_clear_write, obd);
 
         memcpy((void *)addr, lustre_cfg_buf(lcfg, 4),
                LUSTRE_CFG_BUFLEN(lcfg, 4));
 
         memcpy((void *)addr, lustre_cfg_buf(lcfg, 4),
                LUSTRE_CFG_BUFLEN(lcfg, 4));
@@ -2093,8 +2126,10 @@ static int filter_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
         OBD_PAGE_FREE(page);
 
         if (rc) {
         OBD_PAGE_FREE(page);
 
         if (rc) {
-                lprocfs_obd_cleanup(obd);
+                remove_proc_entry("clear", obd->obd_proc_exports_entry);
+                lprocfs_free_per_client_stats(obd);
                 lprocfs_free_obd_stats(obd);
                 lprocfs_free_obd_stats(obd);
+                lprocfs_obd_cleanup(obd);
         }
 
         return rc;
         }
 
         return rc;
@@ -2354,8 +2389,10 @@ static int filter_cleanup(struct obd_device *obd)
                 }
         }
 
                 }
         }
 
-        lprocfs_obd_cleanup(obd);
+        remove_proc_entry("clear", obd->obd_proc_exports_entry);
+        lprocfs_free_per_client_stats(obd);
         lprocfs_free_obd_stats(obd);
         lprocfs_free_obd_stats(obd);
+        lprocfs_obd_cleanup(obd);
         lquota_cleanup(filter_quota_interface_ref, obd);
 
         /* Stop recovery before namespace cleanup. */
         lquota_cleanup(filter_quota_interface_ref, obd);
 
         /* Stop recovery before namespace cleanup. */
@@ -2511,12 +2548,13 @@ static int filter_reconnect(const struct lu_env *env,
 static int filter_connect(const struct lu_env *env,
                           struct lustre_handle *conn, struct obd_device *obd,
                           struct obd_uuid *cluuid,
 static int filter_connect(const struct lu_env *env,
                           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 lvfs_run_ctxt saved;
         struct obd_export *exp;
         struct filter_export_data *fed;
         struct filter_client_data *fcd = NULL;
 {
         struct lvfs_run_ctxt saved;
         struct obd_export *exp;
         struct filter_export_data *fed;
         struct filter_client_data *fcd = NULL;
+        lnet_nid_t client_nid;
         __u32 group;
         int rc;
         ENTRY;
         __u32 group;
         int rc;
         ENTRY;
@@ -2524,6 +2562,12 @@ static int filter_connect(const struct lu_env *env,
         if (conn == NULL || obd == NULL || cluuid == NULL)
                 RETURN(-EINVAL);
 
         if (conn == NULL || obd == NULL || cluuid == NULL)
                 RETURN(-EINVAL);
 
+        if (localdata != NULL)
+                client_nid = *(lnet_nid_t *)localdata;
+        else
+                client_nid = 0ULL;
+
+
         rc = class_connect(conn, obd, cluuid);
         if (rc)
                 RETURN(rc);
         rc = class_connect(conn, obd, cluuid);
         if (rc)
                 RETURN(rc);
@@ -2536,7 +2580,7 @@ static int filter_connect(const struct lu_env *env,
         if (rc)
                 GOTO(cleanup, rc);
 
         if (rc)
                 GOTO(cleanup, rc);
 
-        filter_export_stats_init(obd, exp);
+        filter_export_stats_init(obd, exp, client_nid);
         group = data->ocd_group;
         if (obd->obd_replayable) {
                 OBD_ALLOC(fcd, sizeof(*fcd));
         group = data->ocd_group;
         if (obd->obd_replayable) {
                 OBD_ALLOC(fcd, sizeof(*fcd));
@@ -2548,7 +2592,7 @@ static int filter_connect(const struct lu_env *env,
                 memcpy(fcd->fcd_uuid, cluuid, sizeof(fcd->fcd_uuid));
                 fed->fed_fcd = fcd;
                 fed->fed_fcd->fcd_group = group;
                 memcpy(fcd->fcd_uuid, cluuid, sizeof(fcd->fcd_uuid));
                 fed->fed_fcd = fcd;
                 fed->fed_fcd->fcd_group = group;
-                rc = filter_client_add(obd, exp, -1);
+                rc = filter_client_add(obd, exp, -1, client_nid);
                 if (rc)
                         GOTO(cleanup, rc);
         }
                 if (rc)
                         GOTO(cleanup, rc);
         }
index b0ef32e..2cdf177 100644 (file)
@@ -32,6 +32,7 @@
 #define FILTER_RECOVERY_TIMEOUT (obd_timeout * 5 * HZ / 2) /* *waves hands* */
 
 extern struct file_operations filter_per_export_stats_fops;
 #define FILTER_RECOVERY_TIMEOUT (obd_timeout * 5 * HZ / 2) /* *waves hands* */
 
 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 {
 
 /* Data stored per client in the last_rcvd file.  In le32 order. */
 struct filter_client_data {
index 1437ba7..380e4f6 100644 (file)
@@ -352,8 +352,9 @@ static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
 
         lprocfs_counter_add(obd->obd_stats, LPROC_FILTER_READ_BYTES, tot_bytes);
 
 
         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;
 
 
         EXIT;
 
@@ -649,8 +650,9 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
 
         fsfilt_check_slow(exp->exp_obd, now, obd_timeout, "start_page_write");
 
 
         fsfilt_check_slow(exp->exp_obd, now, obd_timeout, "start_page_write");
 
-        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) {
         EXIT;
 cleanup:
         switch(cleanup_phase) {
index 8c57fe7..c06c60b 100644 (file)
@@ -396,6 +396,12 @@ int filter_do_bio(struct obd_export *exp, struct inode *inode,
                 lprocfs_oh_tally_log2(&obd->u.filter.fo_filter_stats.hist[BRW_R_IO_TIME],
                                       jiffies - start_time);
                 lprocfs_oh_tally_log2(&exp->exp_filter_data.fed_brw_stats.hist[BRW_R_IO_TIME], jiffies - start_time);
                 lprocfs_oh_tally_log2(&obd->u.filter.fo_filter_stats.hist[BRW_R_IO_TIME],
                                       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);
         } else {
                 lprocfs_oh_tally(&obd->u.filter.fo_filter_stats.hist[BRW_W_DIO_FRAGS],
                                  frags);
@@ -404,6 +410,12 @@ int filter_do_bio(struct obd_export *exp, struct inode *inode,
                 lprocfs_oh_tally_log2(&obd->u.filter.fo_filter_stats.hist[BRW_W_IO_TIME],
                                       jiffies - start_time);
                 lprocfs_oh_tally_log2(&exp->exp_filter_data.fed_brw_stats.hist[BRW_W_IO_TIME], jiffies - start_time);
                 lprocfs_oh_tally_log2(&obd->u.filter.fo_filter_stats.hist[BRW_W_IO_TIME],
                                       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)
         }
 
         if (rc == 0)
index 22ef020..da15e8a 100644 (file)
@@ -295,6 +295,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);
                               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))
 
         while (nr_pages-- > 0) {
                 if (last_page && (*pages)->index != (last_page->index + 1))
@@ -316,6 +319,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);
                          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)
 }
 
 #define pct(a,b) (b ? a * 100 / b : 0)
@@ -400,6 +410,8 @@ static void brw_stats_show(struct seq_file *seq, struct brw_stats *brw_stats)
                           &brw_stats->hist[BRW_W_DISK_IOSIZE], 1);
 }
 
                           &brw_stats->hist[BRW_W_DISK_IOSIZE], 1);
 }
 
+#undef pct
+
 static int filter_brw_stats_seq_show(struct seq_file *seq, void *v)
 {
         struct obd_device *dev = seq->private;
 static int filter_brw_stats_seq_show(struct seq_file *seq, void *v)
 {
         struct obd_device *dev = seq->private;
@@ -461,4 +473,31 @@ void lprocfs_filter_init_vars(struct lprocfs_static_vars *lvars)
     lvars->module_vars  = lprocfs_filter_module_vars;
     lvars->obd_vars     = lprocfs_filter_obd_vars;
 }
     lvars->module_vars  = lprocfs_filter_module_vars;
     lvars->obd_vars     = lprocfs_filter_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 */
 #endif /* LPROCFS */