diff --git a/lustre/cmm/mdc_device.c b/lustre/cmm/mdc_device.c index c81a6e7e6e827a8311ecde037d55f069e334fd95..2b04e872c7b147c9ae2cd8a251aa8984d2e010cc 100644 --- a/lustre/cmm/mdc_device.c +++ b/lustre/cmm/mdc_device.c @@ -138,7 +138,7 @@ static int mdc_obd_add(const struct lu_env *env, 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", diff --git a/lustre/include/class_hash.h b/lustre/include/class_hash.h index 5e8a3686e90b063118b0f870253ffb23cc200a35..1be8c525074f0a53c5b4bd93643732c6d7caa2b2 100644 --- a/lustre/include/class_hash.h +++ b/lustre/include/class_hash.h @@ -7,6 +7,8 @@ #include <lustre_lib.h> +/* #define LUSTRE_HASH_DEBUG 1 */ + /* 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; -#endif +#endif }; struct lustre_hash_operations; @@ -81,21 +83,34 @@ lustre_hash_delitem_nolock(struct lustre_class_hash_body *hash_body, 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); +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); +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); +__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); @@ -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); +/* ( 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 */ diff --git a/lustre/include/lprocfs_status.h b/lustre/include/lprocfs_status.h index 3dc941628a20320049e0957129822a4d4a97c430..5b06fcee001fe04dd9e75f6720303a8a8a7f3d0e 100644 --- a/lustre/include/lprocfs_status.h +++ b/lustre/include/lprocfs_status.h @@ -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; -extern int lprocfs_exp_setup(struct obd_export *exp); +struct nid_stat; +extern int lprocfs_add_clear_entry(struct obd_device * obd, + cfs_proc_dir_entry_t *entry); +extern int lprocfs_exp_setup(struct obd_export *exp, + lnet_nid_t peer_nid, int *newnid); extern int lprocfs_exp_cleanup(struct obd_export *exp); +extern int lprocfs_add_simple(struct proc_dir_entry *root, + char *name, read_proc_t *read_proc, + write_proc_t *write_proc, void *data); +extern void lprocfs_free_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); @@ -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_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, @@ -566,10 +583,28 @@ static inline void lprocfs_free_obd_stats(struct obd_device *obddev) { return; } struct obd_export; +static inline int lprocfs_add_clear_entry(struct obd_export *exp) +{ return 0; } static inline int lprocfs_exp_setup(struct obd_export *exp) { return 0; } static inline int lprocfs_exp_cleanup(struct obd_export *exp) { return 0; } +static inline int lprocfs_add_simple(struct proc_dir_entry *root, + char *name, + read_proc_t *read_proc, + write_proc_t *write_proc, + void *data) +{return 0; } +static inline void lprocfs_free_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, diff --git a/lustre/include/lustre_export.h b/lustre/include/lustre_export.h index 7e4c8b9804f369fdca934be91730df3610ab871b..74463218daf830d6cc29b29f3aa0eccb369d04aa 100644 --- a/lustre/include/lustre_export.h +++ b/lustre/include/lustre_export.h @@ -77,6 +77,17 @@ struct filter_export_data { 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; @@ -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 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; diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h index a5e0db18870d525c3b61fb91ad1c1c9981dc82a7..f146ba418cc085a180fb91d53500a6b8c69aeec0 100644 --- a/lustre/include/lustre_net.h +++ b/lustre/include/lustre_net.h @@ -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, - struct obd_uuid *cluuid, struct obd_connect_data *); + struct obd_uuid *cluuid, struct obd_connect_data *, + void *localdata); int client_disconnect_export(struct obd_export *exp); int client_import_add_conn(struct obd_import *imp, struct obd_uuid *uuid, int priority); diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 0f55ecd6ebc2b1d1b2b49b6909376e25770e3912..14f88ca8c948e44887e56f06aff2a658b54b836c 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -883,11 +883,15 @@ struct obd_device { /* 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; + 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 */ @@ -956,10 +960,9 @@ struct obd_device { 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; - struct semaphore obd_proc_exp_sem; 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, - 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, diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h index edf8899fcac4760d93099cdefd4f7da4d5ee4522..76ce36bf271c9d7e489f279ea3296ec2155ade2f 100644 --- a/lustre/include/obd_class.h +++ b/lustre/include/obd_class.h @@ -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); \ - if ((export)->exp_ops_stats != NULL) \ + if ((export)->exp_nid_stats != NULL && \ + (export)->exp_nid_stats->nid_stats != NULL) \ lprocfs_counter_incr( \ - (export)->exp_ops_stats, coffset); \ + (export)->exp_nid_stats->nid_stats, coffset);\ } #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, - struct obd_connect_data *d) + struct obd_connect_data *d, + void *localdata) { 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); - 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)); diff --git a/lustre/ldlm/ldlm_lib.c b/lustre/ldlm/ldlm_lib.c index 14bbf0cc31e36bbce4e2bdf94d38d3554930f507..e188385e2ed6cdb0542d048706e20ce27c3b2619 100644 --- a/lustre/ldlm/ldlm_lib.c +++ b/lustre/ldlm/ldlm_lib.c @@ -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, - 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; @@ -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; + lnet_nid_t client_nid = 0; 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); + client_nid = req->rq_peer.nid; 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, - &conn, target, &cluuid, data); + &conn, target, &cluuid, data, + &client_nid); } } else { rc = obd_reconnect(req->rq_svc_thread->t_env, diff --git a/lustre/liblustre/llite_lib.c b/lustre/liblustre/llite_lib.c index 3c7c3b09bf2300827362de3ac3850808237e8a9a..9aa549802702b009b3f42a6f90f76fa2f3403186 100644 --- a/lustre/liblustre/llite_lib.c +++ b/lustre/liblustre/llite_lib.c @@ -163,7 +163,7 @@ int liblustre_process_log(struct config_llog_instance *cfg, #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); diff --git a/lustre/liblustre/super.c b/lustre/liblustre/super.c index cb7284b7b37d14e23092c4ab27aa11142c255a79..dc574f7f14cbd0bb9ab261e09e0bcb1f88b1a715 100644 --- a/lustre/liblustre/super.c +++ b/lustre/liblustre/super.c @@ -2080,7 +2080,7 @@ llu_fsswop_mount(const char *source, 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); @@ -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; - 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); diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 52e89e97a66e0134f4d429f9eb6fce008767d775..dd9d7e895ad64064c6bffaebeaa33bea7364f71e 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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; } - 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 " @@ -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; - 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 " diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index 8013d500afe54cf7dfd09bfd571b6b4cd6393b94..e482f4a6c2158a5015eea17996f9fe7d09f5cfbc 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -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, - 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; @@ -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, - &lmv->conn_data); + &lmv->conn_data, NULL); if (rc) { CERROR("target %s connect error %d\n", tgt->ltd_uuid.uuid, rc); RETURN(rc); diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 9a3c7595eca14ab26fb8363047a16fb4bf2745f9..d594d203f007402fb0254e3ed852bb509999f74e 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -148,7 +148,7 @@ static int lov_connect_obd(struct obd_device *obd, __u32 index, int activate, 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); @@ -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, - struct obd_uuid *cluuid, struct obd_connect_data *data) + struct obd_uuid *cluuid, struct obd_connect_data *data, + void *localdata) { struct lov_obd *lov = &obd->u.lov; struct lov_tgt_desc *tgt; diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index f1d65f4870770f73e11acabe3f2d5e4a87d80364..4ab58bdbe119855017b694e6ea62ea4ef308c8dc 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -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, - struct obd_connect_data *data) + struct obd_connect_data *data, + void *localdata) { 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); } - 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 = { diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index fae6cd38ae0467e4572fdf382173e8826af2e945..0f3fdf2b76a96d10cd8a84c547e40b6f8f55456f 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -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, - struct obd_uuid *cluuid, struct obd_connect_data *data) + struct obd_uuid *cluuid, struct obd_connect_data *data, + void *localdata) { struct obd_export *exp; struct mds_export_data *med; struct mds_client_data *mcd = NULL; + lnet_nid_t *client_nid = (lnet_nid_t *)localdata; int rc; 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; - rc = mds_client_add(obd, exp, -1); + rc = mds_client_add(obd, exp, -1, *client_nid); 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); - 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); @@ -2022,6 +2024,11 @@ static int mds_setup(struct obd_device *obd, struct lustre_cfg* lcfg) 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); @@ -2099,8 +2106,8 @@ err_fs: mds->mds_group_hash = NULL; #endif err_ns: - lprocfs_obd_cleanup(obd); lprocfs_free_obd_stats(obd); + lprocfs_obd_cleanup(obd); 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); - 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_obd_cleanup(obd); lquota_cleanup(mds_quota_interface_ref, obd); diff --git a/lustre/mds/lproc_mds.c b/lustre/mds/lproc_mds.c index 3e9dd72b58dbd663ddcfc64079567660672d414f..594e8e93847b81ebf7c0c197c2790979103ba036 100644 --- a/lustre/mds/lproc_mds.c +++ b/lustre/mds/lproc_mds.c @@ -361,8 +361,11 @@ struct lprocfs_vars lprocfs_mdt_module_vars[] = { void mds_counter_incr(struct obd_export *exp, int opcode) { - lprocfs_counter_incr(exp->exp_obd->obd_stats, opcode); - lprocfs_counter_incr(exp->exp_ops_stats, opcode); + if (exp->exp_obd && exp->exp_obd->obd_stats) + lprocfs_counter_incr(exp->exp_obd->obd_stats, opcode); + if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats != NULL) + lprocfs_counter_incr(exp->exp_nid_stats->nid_stats, opcode); + } void mds_stats_counter_init(struct lprocfs_stats *stats) diff --git a/lustre/mds/mds_fs.c b/lustre/mds/mds_fs.c index 0bed7d15b47abbd2923bb891686614e248e10f6d..64549a3a6bafa9fbceb1af87b98a205c9043164f 100644 --- a/lustre/mds/mds_fs.c +++ b/lustre/mds/mds_fs.c @@ -48,22 +48,32 @@ #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; - 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; } @@ -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, - 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; @@ -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); - mds_export_stats_init(obd, exp); + mds_export_stats_init(obd, exp, client_nid); 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; - 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; @@ -632,7 +642,6 @@ err_fid: goto err_pop; } - int mds_fs_cleanup(struct obd_device *obd) { struct mds_obd *mds = &obd->u.mds; diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 95efae2b53fb1dac0e01b2b137d9778e9a31a2cd..4ed503597130214359ee6a969fcafeddc7d5b578 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -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 */ -int mds_client_add(struct obd_device *obd, struct obd_export *exp, int cl_off); +int mds_client_add(struct obd_device *obd, struct obd_export *exp, + int cl_off, lnet_nid_t client_nid); int mds_client_free(struct obd_export *exp); int mds_obd_create(struct obd_export *exp, struct obdo *oa, struct lov_stripe_md **ea, struct obd_trans_info *oti); diff --git a/lustre/mds/mds_lov.c b/lustre/mds/mds_lov.c index 3d60faaab4be922f12705c0a3abf1ec151e43fb5..91dcd339d474f00f6f012e9120d21eb0b27afea0 100644 --- a/lustre/mds/mds_lov.c +++ b/lustre/mds/mds_lov.c @@ -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 */ - 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); diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 61a23b2f6650a0608d513de976fd78cae238b3a5..ce2e274838a3345044fdec45b70b238347ff6959 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -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, - struct obd_connect_data *data) + struct obd_connect_data *data, + void *localdata) { struct mdt_thread_info *info; struct mdt_client_data *mcd; diff --git a/lustre/mgs/lproc_mgs.c b/lustre/mgs/lproc_mgs.c index 8ace822be3f7ecda5857795b3ba5ea5f96c9f2f7..f5586c26a2ce14cca7b8e9cd8b40eaf36001fc5d 100644 --- a/lustre/mgs/lproc_mgs.c +++ b/lustre/mgs/lproc_mgs.c @@ -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); - 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; } @@ -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); - 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) diff --git a/lustre/mgs/mgs_handler.c b/lustre/mgs/mgs_handler.c index 46725405403a495a5c22af49a388d269dd3dbfe2..582e55a41178d1be8d544271bb79c4a2fc54d723 100644 --- a/lustre/mgs/mgs_handler.c +++ b/lustre/mgs/mgs_handler.c @@ -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, - struct obd_uuid *cluuid, struct obd_connect_data *data) + struct obd_uuid *cluuid, struct obd_connect_data *data, + void *localdata) { struct obd_export *exp; int rc; diff --git a/lustre/obdclass/class_hash.c b/lustre/obdclass/class_hash.c index 766e16d1d1c7c74a850e8bee31d205f9d6d774c3..a66bad5dc37414bd2c54300e7fcf2ba07b35a857 100644 --- a/lustre/obdclass/class_hash.c +++ b/lustre/obdclass/class_hash.c @@ -39,7 +39,7 @@ int lustre_hash_init(struct lustre_class_hash_body **hash_body_new, n++; i >>= 1; } - + 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, - 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)); @@ -177,6 +177,53 @@ int lustre_hash_additem_unique(struct lustre_class_hash_body *hash_body, } 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 @@ -286,6 +333,62 @@ int lustre_hash_delitem(struct lustre_class_hash_body *hash_body, } EXPORT_SYMBOL(lustre_hash_delitem); +void lustre_hash_bucket_iterate(struct lustre_class_hash_body *hash_body, + void *key, hash_item_iterate_cb func, void *data) +{ + int hashent, find = 0; + struct lustre_hash_bucket *bucket = NULL; + struct hlist_node *hash_item_node = NULL; + struct lustre_hash_operations *hop = hash_body->lchb_hash_operations; + struct obd_export *tmp = NULL; + + ENTRY; + + hashent = hop->lustre_hashfn(hash_body, key); + bucket = &hash_body->lchb_hash_tables[hashent]; + + spin_lock(&bucket->lhb_lock); + hlist_for_each(hash_item_node, &(bucket->lhb_head)) { + find = hop->lustre_hash_key_compare(key, hash_item_node); + if (find) { + tmp = 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) { @@ -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); +/* 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 */ @@ -329,26 +450,11 @@ struct lustre_hash_operations uuid_hash_operations = { .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 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 @@ -410,21 +516,9 @@ struct lustre_hash_operations nid_hash_operations = { .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 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 @@ -485,21 +579,9 @@ struct lustre_hash_operations 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 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) @@ -545,3 +627,47 @@ void conn_refcount_put(struct hlist_node *actual_hnode) 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--; + +} + +/*******************************************************************************/ diff --git a/lustre/obdclass/llog_test.c b/lustre/obdclass/llog_test.c index 3a839f1d9cc250df26adc995c91da094e1c55d40..efb1228175919fcfc3e759570286b504da358d3e 100644 --- a/lustre/obdclass/llog_test.c +++ b/lustre/obdclass/llog_test.c @@ -469,8 +469,8 @@ static int llog_test_6(struct obd_device *obd, char *name) 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); diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 38012437d60043f986dba5d549f26b63c2f4f362..8f0ba5147037ba5ab9db2bb236fefa68eb56fa7a 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -288,13 +288,13 @@ void lprocfs_remove(struct proc_dir_entry **rooth) struct proc_dir_entry *rm_entry; struct proc_dir_entry *parent; - if (!root) + if (!root) return; *rooth = NULL; parent = root->parent; LASSERT(parent != NULL); - + 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; - remove_proc_entry(rm_entry->name, rm_entry->parent); + remove_proc_entry(rm_entry->name, temp); 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->obd_proc_exports) { + if (obd->obd_proc_exports_entry) { /* Should be no exports left */ - LASSERT(obd->obd_proc_exports->subdir == NULL); - lprocfs_remove(&obd->obd_proc_exports); + LASSERT(obd->obd_proc_exports_entry->subdir == NULL); + lprocfs_remove(&obd->obd_proc_exports_entry); } lprocfs_remove(&obd->obd_proc_entry); return 0; } +void lprocfs_free_client_stats(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) { @@ -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++) { - 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; @@ -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)); } +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 *eof, void *data) + int *eof, void *data) { - struct obd_export *exp = (struct obd_export*)data; - LASSERT(exp != NULL); + struct nid_stat *stats = (struct nid_stat *)data; + struct exp_uuid_cb_data cb_data; + struct obd_device *obd = stats->nid_obd; + int len = 0; + *eof = 1; - return snprintf(page, count, "%s\n", - obd_uuid2str(&exp->exp_client_uuid)); + page[0] = '\0'; + LASSERT(obd != NULL); + + cb_data.page = page; + cb_data.count = count; + cb_data.eof = eof; + cb_data.len = &len; + 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; - 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); - 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) - 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) { - 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; } @@ -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_simple); +EXPORT_SYMBOL(lprocfs_free_per_client_stats); EXPORT_SYMBOL(lprocfs_alloc_stats); EXPORT_SYMBOL(lprocfs_free_stats); EXPORT_SYMBOL(lprocfs_clear_stats); diff --git a/lustre/obdclass/obd_config.c b/lustre/obdclass/obd_config.c index def741096a9ecb3bb0206a5d4eabee99b939549f..ccaa00de1cc2fb8e34dcc1268c1a1826cbe9553b 100644 --- a/lustre/obdclass/obd_config.c +++ b/lustre/obdclass/obd_config.c @@ -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_nid_stats); + spin_lock_init(&obd->obd_nid_lock); spin_lock_init(&obd->obd_dev_lock); sema_init(&obd->obd_dev_sem, 1); - sema_init(&obd->obd_proc_exp_sem, 1); spin_lock_init(&obd->obd_osfs_lock); /* obd->obd_osfs_age must be set to a value in the distant * past to guarantee a fresh statfs is fetched on mount. */ @@ -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); - if (err) { + if (err) GOTO(err_hash, err); - } /* 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); + /* 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)); + 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); + 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); @@ -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-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); diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index 5f3d6ffad873d933c677c382f00abfd281cd0653..db8ca47d066b7d195e76ecaa223438ccce6290b6 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -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; - 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); diff --git a/lustre/obdecho/echo.c b/lustre/obdecho/echo.c index 55828ec2d05b4c7750de2fefa84fecb5a02887ba..2fe7c079dfb6bebccda361c0f02418335987bf90 100644 --- a/lustre/obdecho/echo.c +++ b/lustre/obdecho/echo.c @@ -51,7 +51,8 @@ enum { 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); diff --git a/lustre/obdecho/echo_client.c b/lustre/obdecho/echo_client.c index 142aef3816057e010c2440a9284218bd79423cd3..f0c6fb4beead6370f621f8cdd7e0f186e7645727 100644 --- a/lustre/obdecho/echo_client.c +++ b/lustre/obdecho/echo_client.c @@ -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; - rc = obd_connect(NULL, &conn, tgt, &echo_uuid, ocd); + rc = obd_connect(NULL, &conn, tgt, &echo_uuid, ocd, NULL); 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, - struct obd_connect_data *data) + struct obd_connect_data *data, void *localdata) { struct obd_export *exp; int rc; diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 24d3ff96e1ba029781a49fc584f5b85b574c241d..a1597f3f22ea12d939666139caf115a402696b6d 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -160,14 +160,35 @@ static void init_brw_stats(struct brw_stats *brw_stats) spin_lock_init(&brw_stats->hist[i].oh_lock); } +static int lprocfs_init_rw_stats(struct obd_device *obd, + struct lprocfs_stats **stats) +{ + int num_stats; + + num_stats = (sizeof(*obd->obd_type->typ_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, - struct obd_export *exp) + struct obd_export *exp, + lnet_nid_t client_nid) { struct filter_export_data *fed = &exp->exp_filter_data; struct proc_dir_entry *brw_entry; - int rc, num_stats; + int rc, newnid = 0; ENTRY; init_brw_stats(&fed->fed_brw_stats); @@ -176,30 +197,38 @@ static int filter_export_stats_init(struct obd_device *obd, /* Self-export gets no proc entry */ RETURN(0); - rc = lprocfs_exp_setup(exp); + rc = lprocfs_exp_setup(exp, client_nid, &newnid); if (rc) RETURN(rc); - /* Create a per export proc entry for brw_stats */ - brw_entry = create_proc_entry("brw_stats", 0644, exp->exp_proc); - if (brw_entry == NULL) - RETURN(-ENOMEM); - brw_entry->proc_fops = &filter_per_export_stats_fops; - brw_entry->data = fed; + if (client_nid && newnid) { + struct nid_stat *tmp = exp->exp_nid_stats; + LASSERT(tmp != NULL); + + OBD_ALLOC(tmp->nid_brw_stats, sizeof(struct brw_stats)); + if (tmp->nid_brw_stats == NULL) + RETURN(-ENOMEM); + + init_brw_stats(tmp->nid_brw_stats); + + brw_entry = create_proc_entry("brw_stats", 0644, + exp->exp_nid_stats->nid_proc); + if (brw_entry == NULL) + RETURN(-ENOMEM); + + brw_entry->proc_fops = &filter_per_nid_stats_fops; + brw_entry->data = exp->exp_nid_stats; + + rc = lprocfs_init_rw_stats(obd, &exp->exp_nid_stats->nid_stats); + if (rc) + RETURN(rc); + + rc = lprocfs_register_stats(tmp->nid_proc, "stats", + tmp->nid_stats); + if (rc) + RETURN(rc); + } - /* Create a per export proc entry for ops stats */ - num_stats = (sizeof(*obd->obd_type->typ_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); } @@ -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, - 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; @@ -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); - 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); @@ -2083,9 +2112,13 @@ static int filter_setup(struct obd_device *obd, struct lustre_cfg* lcfg) "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)); @@ -2093,8 +2126,10 @@ static int filter_setup(struct obd_device *obd, struct lustre_cfg* lcfg) 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_obd_cleanup(obd); } 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_obd_cleanup(obd); 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, - 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; + lnet_nid_t client_nid; __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 (localdata != NULL) + client_nid = *(lnet_nid_t *)localdata; + else + client_nid = 0ULL; + + 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); - 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)); @@ -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; - rc = filter_client_add(obd, exp, -1); + rc = filter_client_add(obd, exp, -1, client_nid); if (rc) GOTO(cleanup, rc); } diff --git a/lustre/obdfilter/filter_internal.h b/lustre/obdfilter/filter_internal.h index b0ef32e0e85829f5e20a01e3f53a9882430997f3..2cdf17713c9bc441e608c21d601e224f0f81924e 100644 --- a/lustre/obdfilter/filter_internal.h +++ b/lustre/obdfilter/filter_internal.h @@ -32,6 +32,7 @@ #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 { diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c index 1437ba7d41ef3480e0430c8c9cf2b8d5504a3733..380e4f6c714ef74a85b6c17d8d3f757dea626b8f 100644 --- a/lustre/obdfilter/filter_io.c +++ b/lustre/obdfilter/filter_io.c @@ -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(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; @@ -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"); - lprocfs_counter_add(exp->exp_ops_stats, LPROC_FILTER_WRITE_BYTES, - tot_bytes); + if (exp->exp_nid_stats && exp->exp_nid_stats->nid_stats) + lprocfs_counter_add(exp->exp_nid_stats->nid_stats, + LPROC_FILTER_WRITE_BYTES, tot_bytes); EXIT; cleanup: switch(cleanup_phase) { diff --git a/lustre/obdfilter/filter_io_26.c b/lustre/obdfilter/filter_io_26.c index 8c57fe7c21aa58b6dfeed893bf4c9869c3474350..c06c60b8b9a2bb32043db9e8cea6685e0251a5c4 100644 --- a/lustre/obdfilter/filter_io_26.c +++ b/lustre/obdfilter/filter_io_26.c @@ -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); + 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); @@ -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); + if (exp->exp_nid_stats && exp->exp_nid_stats->nid_brw_stats) { + lprocfs_oh_tally(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_W_DIO_FRAGS], + frags); + lprocfs_oh_tally_log2(&exp->exp_nid_stats->nid_brw_stats->hist[BRW_W_IO_TIME], + jiffies - start_time); + } } if (rc == 0) diff --git a/lustre/obdfilter/lproc_obdfilter.c b/lustre/obdfilter/lproc_obdfilter.c index 22ef020f94195e0430cb76a11a6dc2ac92ac2138..da15e8ae61a318442fba967c5a2f1729f863ead5 100644 --- a/lustre/obdfilter/lproc_obdfilter.c +++ b/lustre/obdfilter/lproc_obdfilter.c @@ -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); + 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)) @@ -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); + + 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) @@ -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); } +#undef pct + 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; } + +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 */