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