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