X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fobdclass%2Flprocfs_status.c;h=eed7097d5b25e02904d796a6998737a18c66b223;hp=6a337c68f21cbc5562e3faa07d91f20064f68c0a;hb=04f2d8ab2524851477f0b6fbffbc115d0c82fdc6;hpb=9f463e30893138845eb571cc32426e8d1e04a9fa diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 6a337c6..eed7097 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -26,10 +26,13 @@ * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. */ /* + * Copyright (c) 2011 Whamcloud, Inc. + */ +/* * This file is part of Lustre, http://www.lustre.org/ * Lustre is a trademark of Sun Microsystems, Inc. * @@ -58,7 +61,7 @@ #define MAX_STRING_SIZE 128 /* for bug 10866, global variable */ -DECLARE_RWSEM(_lprocfs_lock); +CFS_DECLARE_RWSEM(_lprocfs_lock); EXPORT_SYMBOL(_lprocfs_lock); int lprocfs_seq_release(struct inode *inode, struct file *file) @@ -68,28 +71,36 @@ int lprocfs_seq_release(struct inode *inode, struct file *file) } EXPORT_SYMBOL(lprocfs_seq_release); -struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head, - const char *name) +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; - LPROCFS_ENTRY(); temp = head->subdir; while (temp != NULL) { if (strcmp(temp->name, name) == 0) { - LPROCFS_EXIT(); return temp; } temp = temp->next; } - LPROCFS_EXIT(); 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; +} + /* lprocfs API calls */ /* Function that emulates snprintf but also has the side effect of advancing @@ -131,9 +142,11 @@ cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root, mode |= 0200; if (fops) mode = 0644; + LPROCFS_WRITE_ENTRY(); proc = create_proc_entry(name, mode, root); if (!proc) { CERROR("LprocFS: No memory to create /proc entry %s", name); + LPROCFS_WRITE_EXIT(); return ERR_PTR(-ENOMEM); } proc->read_proc = read_proc; @@ -141,21 +154,34 @@ cfs_proc_dir_entry_t *lprocfs_add_simple(struct proc_dir_entry *root, proc->data = data; if (fops) proc->proc_fops = fops; + LPROCFS_WRITE_EXIT(); return proc; } struct proc_dir_entry *lprocfs_add_symlink(const char *name, - struct proc_dir_entry *parent, const char *dest) + struct proc_dir_entry *parent, const char *format, ...) { struct proc_dir_entry *entry; + char *dest; + va_list ap; - if (parent == NULL || dest == NULL) + if (parent == NULL || format == NULL) return NULL; + OBD_ALLOC_WAIT(dest, MAX_STRING_SIZE + 1); + if (dest == NULL) + return NULL; + + va_start(ap, format); + vsnprintf(dest, MAX_STRING_SIZE, format, ap); + va_end(ap); + entry = proc_symlink(name, parent, dest); if (entry == NULL) CERROR("LprocFS: Could not create symbolic link from %s to %s", name, dest); + + OBD_FREE(dest, MAX_STRING_SIZE + 1); return entry; } @@ -173,9 +199,13 @@ static ssize_t lprocfs_fops_read(struct file *f, char __user *buf, if (page == NULL) return -ENOMEM; - LPROCFS_ENTRY(); + if (LPROCFS_ENTRY_AND_CHECK(dp)) { + rc = -ENOENT; + goto out; + } + OBD_FAIL_TIMEOUT(OBD_FAIL_LPROC_REMOVE, 10); - if (!dp->deleted && dp->read_proc) + if (dp->read_proc) rc = dp->read_proc(page, &start, *ppos, CFS_PAGE_SIZE, &eof, dp->data); LPROCFS_EXIT(); @@ -197,7 +227,7 @@ static ssize_t lprocfs_fops_read(struct file *f, char __user *buf, } count = (rc < size) ? rc : size; - if (copy_to_user(buf, start, count)) { + if (cfs_copy_to_user(buf, start, count)) { rc = -EFAULT; goto out; } @@ -214,8 +244,9 @@ static ssize_t lprocfs_fops_write(struct file *f, const char __user *buf, struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode); int rc = -EIO; - LPROCFS_ENTRY(); - if (!dp->deleted && dp->write_proc) + if (LPROCFS_ENTRY_AND_CHECK(dp)) + return -ENOENT; + if (dp->write_proc) rc = dp->write_proc(f, buf, size, dp->data); LPROCFS_EXIT(); return rc; @@ -232,7 +263,7 @@ int lprocfs_evict_client_open(struct inode *inode, struct file *f) struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode); struct obd_device *obd = dp->data; - atomic_inc(&obd->obd_evict_inprogress); + cfs_atomic_inc(&obd->obd_evict_inprogress); return 0; } @@ -242,8 +273,8 @@ int lprocfs_evict_client_release(struct inode *inode, struct file *f) struct proc_dir_entry *dp = PDE(f->f_dentry->d_inode); struct obd_device *obd = dp->data; - atomic_dec(&obd->obd_evict_inprogress); - wake_up(&obd->obd_evict_inprogress_waitq); + cfs_atomic_dec(&obd->obd_evict_inprogress); + cfs_waitq_signal(&obd->obd_evict_inprogress_waitq); return 0; } @@ -271,9 +302,12 @@ EXPORT_SYMBOL(lprocfs_evict_client_fops); int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list, void *data) { + int rc = 0; + if (root == NULL || list == NULL) return -EINVAL; + LPROCFS_WRITE_ENTRY(); while (list->name != NULL) { struct proc_dir_entry *cur_root, *proc; char *pathcopy, *cur, *next, pathbuf[64]; @@ -286,7 +320,7 @@ int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list, if (strlen(list->name) > sizeof(pathbuf) - 1) { OBD_ALLOC(pathcopy, pathsize); if (pathcopy == NULL) - return -ENOMEM; + GOTO(out, rc = -ENOMEM); } else { pathcopy = pathbuf; } @@ -298,7 +332,7 @@ int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list, if (*cur =='\0') /* skip double/trailing "/" */ continue; - proc = lprocfs_srch(cur_root, cur); + proc = __lprocfs_srch(cur_root, cur); CDEBUG(D_OTHER, "cur_root=%s, cur=%s, next=%s, (%s)\n", cur_root->name, cur, next, (proc ? "exists" : "new")); @@ -325,7 +359,7 @@ int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list, if (cur_root == NULL || proc == NULL) { CERROR("LprocFS: No memory to create /proc entry %s", list->name); - return -ENOMEM; + GOTO(out, rc = -ENOMEM); } if (list->fops) @@ -337,7 +371,9 @@ int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list, proc->data = (list->data ? list->data : data); list++; } - return 0; +out: + LPROCFS_WRITE_EXIT(); + return rc; } void lprocfs_remove(struct proc_dir_entry **rooth) @@ -368,9 +404,23 @@ void lprocfs_remove(struct proc_dir_entry **rooth) "0x%p %s/%s len %d\n", rm_entry, temp->name, rm_entry->name, (int)strlen(rm_entry->name)); +#ifdef HAVE_PROCFS_USERS + /* if procfs uses user count to synchronize deletion of + * proc entry, there is no protection for rm_entry->data, + * then lprocfs_fops_read and lprocfs_fops_write maybe + * call proc_dir_entry->read_proc (or write_proc) with + * proc_dir_entry->data == NULL, then cause kernel Oops. + * see bug19706 for detailed information */ + + /* procfs won't free rm_entry->data if it isn't a LINK, + * and Lustre won't use rm_entry->data if it is a LINK */ + if (S_ISLNK(rm_entry->mode)) + rm_entry->data = NULL; +#else /* Now, the rm_entry->deleted flags is protected * by _lprocfs_lock. */ rm_entry->data = NULL; +#endif remove_proc_entry(rm_entry->name, temp); if (temp == parent) break; @@ -424,7 +474,7 @@ int lprocfs_wr_uint(struct file *file, const char *buffer, unsigned long tmp; dummy[MAX_STRING_SIZE] = '\0'; - if (copy_from_user(dummy, buffer, MAX_STRING_SIZE)) + if (cfs_copy_from_user(dummy, buffer, MAX_STRING_SIZE)) return -EFAULT; tmp = simple_strtoul(dummy, &end, 0); @@ -446,16 +496,16 @@ int lprocfs_rd_u64(char *page, char **start, off_t off, int lprocfs_rd_atomic(char *page, char **start, off_t off, int count, int *eof, void *data) { - atomic_t *atom = data; + cfs_atomic_t *atom = data; LASSERT(atom != NULL); *eof = 1; - return snprintf(page, count, "%d\n", atomic_read(atom)); + return snprintf(page, count, "%d\n", cfs_atomic_read(atom)); } int lprocfs_wr_atomic(struct file *file, const char *buffer, unsigned long count, void *data) { - atomic_t *atm = data; + cfs_atomic_t *atm = data; int val = 0; int rc; @@ -466,7 +516,7 @@ int lprocfs_wr_atomic(struct file *file, const char *buffer, if (val <= 0) return -ERANGE; - atomic_set(atm, val); + cfs_atomic_set(atm, val); return count; } @@ -506,7 +556,8 @@ int lprocfs_rd_blksize(char *page, char **start, off_t off, int count, int *eof, void *data) { struct obd_statfs osfs; - int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ, + int rc = obd_statfs(data, &osfs, + cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), OBD_STATFS_NODELAY); if (!rc) { *eof = 1; @@ -519,7 +570,8 @@ int lprocfs_rd_kbytestotal(char *page, char **start, off_t off, int count, int *eof, void *data) { struct obd_statfs osfs; - int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ, + int rc = obd_statfs(data, &osfs, + cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), OBD_STATFS_NODELAY); if (!rc) { __u32 blk_size = osfs.os_bsize >> 10; @@ -538,7 +590,8 @@ int lprocfs_rd_kbytesfree(char *page, char **start, off_t off, int count, int *eof, void *data) { struct obd_statfs osfs; - int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ, + int rc = obd_statfs(data, &osfs, + cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), OBD_STATFS_NODELAY); if (!rc) { __u32 blk_size = osfs.os_bsize >> 10; @@ -557,7 +610,8 @@ int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count, int *eof, void *data) { struct obd_statfs osfs; - int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ, + int rc = obd_statfs(data, &osfs, + cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), OBD_STATFS_NODELAY); if (!rc) { __u32 blk_size = osfs.os_bsize >> 10; @@ -576,7 +630,8 @@ int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count, int *eof, void *data) { struct obd_statfs osfs; - int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ, + int rc = obd_statfs(data, &osfs, + cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), OBD_STATFS_NODELAY); if (!rc) { *eof = 1; @@ -590,7 +645,8 @@ int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count, int *eof, void *data) { struct obd_statfs osfs; - int rc = obd_statfs(data, &osfs, cfs_time_current_64() - HZ, + int rc = obd_statfs(data, &osfs, + cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), OBD_STATFS_NODELAY); if (!rc) { *eof = 1; @@ -631,9 +687,8 @@ int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count, LPROCFS_CLIMP_CHECK(obd); conn = obd->u.cli.cl_import->imp_connection; - LASSERT(conn != NULL); *eof = 1; - if (obd->u.cli.cl_import) { + if (conn && obd->u.cli.cl_import) { rc = snprintf(page, count, "%s\n", conn->c_remote_uuid.uuid); } else { @@ -663,23 +718,23 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, cnt->lc_min = LC_MIN_INIT; - if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) - num_cpu = 1; - else - num_cpu = num_possible_cpus(); + num_cpu = lprocfs_stats_lock(stats, LPROCFS_GET_NUM_CPU); for (i = 0; i < num_cpu; i++) { percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[idx]; do { - centry = atomic_read(&percpu_cntr->lc_cntl.la_entry); + centry = cfs_atomic_read(&percpu_cntr-> \ + lc_cntl.la_entry); t.lc_count = percpu_cntr->lc_count; t.lc_sum = percpu_cntr->lc_sum; t.lc_min = percpu_cntr->lc_min; t.lc_max = percpu_cntr->lc_max; t.lc_sumsquare = percpu_cntr->lc_sumsquare; - } while (centry != atomic_read(&percpu_cntr->lc_cntl.la_entry) && - centry != atomic_read(&percpu_cntr->lc_cntl.la_exit)); + } while (centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \ + la_entry) && + centry != cfs_atomic_read(&percpu_cntr->lc_cntl. \ + la_exit)); cnt->lc_count += t.lc_count; cnt->lc_sum += t.lc_sum; if (t.lc_min < cnt->lc_min) @@ -690,6 +745,7 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, } cnt->lc_units = stats->ls_percpu[0]->lp_cntr[idx].lc_units; + lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU); } /** @@ -709,8 +765,6 @@ static int obd_import_flags2str(struct obd_import *imp, char *str, int max) flag2str(deactive); flag2str(replayable); flag2str(pingable); - flag2str(recon_bk); - flag2str(last_recon); return len; } #undef flags2str @@ -729,11 +783,11 @@ static const char *obd_connect_names[] = { "truncate_lock", "initial_transno", "inode_bit_locks", - "join_file", + "join_file(obsolete)", "getattr_by_fid", "no_oh_for_devices", - "local_client", "remote_client", + "remote_client_by_force", "max_byte_per_rpc", "64bit_qdata", "mds_capability", @@ -751,10 +805,15 @@ static const char *obd_connect_names[] = { "pools", "grant_shrink", "skip_orphan", + "large_ea", + "full20", + "layout_lock", + "64bithash", + "object_max_bytes", NULL }; -static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep) +int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep) { __u64 mask = 1; int i, ret = 0; @@ -770,6 +829,7 @@ static int obd_connect_flags2str(char *page, int count, __u64 flags, char *sep) ret ? sep : "", flags & ~(mask - 1)); return ret; } +EXPORT_SYMBOL(obd_connect_flags2str); int lprocfs_rd_import(char *page, char **start, off_t off, int count, int *eof, void *data) @@ -777,6 +837,7 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count, struct lprocfs_counter ret; struct obd_device *obd = (struct obd_device *)data; struct obd_import *imp; + struct obd_import_conn *conn; int i, j, k, rw = 0; LASSERT(obd != NULL); @@ -788,12 +849,10 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count, "import:\n" " name: %s\n" " target: %s\n" - " current_connection: %s\n" " state: %s\n" " connect_flags: [", obd->obd_name, obd2cli_tgt(obd), - imp->imp_connection->c_remote_uuid.uuid, ptlrpc_import_state_name(imp->imp_state)); i += obd_connect_flags2str(page + i, count - i, imp->imp_connect_data.ocd_connect_flags, @@ -806,24 +865,43 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count, i += snprintf(page + i, count - i, "]\n" " connection:\n" + " failover_nids: ["); + cfs_spin_lock(&imp->imp_lock); + j = 0; + cfs_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++; + } + cfs_spin_unlock(&imp->imp_lock); + i += snprintf(page + i, count - i, + "]\n" + " current_connection: %s\n" " connection_attempts: %u\n" " generation: %u\n" " in-progress_invalidations: %u\n", + libcfs_nid2str(imp->imp_connection->c_peer.nid), imp->imp_conn_cnt, imp->imp_generation, - atomic_read(&imp->imp_inval_count)); + cfs_atomic_read(&imp->imp_inval_count)); lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_REQWAIT_CNTR, &ret); - do_div(ret.lc_sum, ret.lc_count); + if (ret.lc_count != 0) { + /* first argument to do_div MUST be __u64 */ + __u64 sum = ret.lc_sum; + do_div(sum, ret.lc_count); + ret.lc_sum = sum; + } else + ret.lc_sum = 0; i += snprintf(page + i, count - i, " rpcs:\n" " inflight: %u\n" " unregistering: %u\n" " timeouts: %u\n" " avg_waittime: "LPU64" %s\n", - atomic_read(&imp->imp_inflight), - atomic_read(&imp->imp_unregistering), - atomic_read(&imp->imp_timeouts), + cfs_atomic_read(&imp->imp_inflight), + cfs_atomic_read(&imp->imp_unregistering), + cfs_atomic_read(&imp->imp_timeouts), ret.lc_sum, ret.lc_units); k = 0; @@ -854,8 +932,11 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count, lprocfs_stats_collect(obd->obd_svc_stats, PTLRPC_LAST_CNTR + BRW_READ_BYTES + rw, &ret); - if (ret.lc_sum > 0) { - do_div(ret.lc_sum, ret.lc_count); + if (ret.lc_sum > 0 && ret.lc_count > 0) { + /* first argument to do_div MUST be __u64 */ + __u64 sum = ret.lc_sum; + do_div(sum, ret.lc_count); + ret.lc_sum = sum; i += snprintf(page + i, count - i, " %s_data_averages:\n" " bytes_per_rpc: "LPU64"\n", @@ -865,8 +946,11 @@ int lprocfs_rd_import(char *page, char **start, off_t off, int count, k = (int)ret.lc_sum; j = opcode_offset(OST_READ + rw) + EXTRA_MAX_OPCODES; lprocfs_stats_collect(obd->obd_svc_stats, j, &ret); - if (ret.lc_sum > 0) { - do_div(ret.lc_sum, ret.lc_count); + if (ret.lc_sum > 0 && ret.lc_count != 0) { + /* first argument to do_div MUST be __u64 */ + __u64 sum = ret.lc_sum; + do_div(sum, ret.lc_count); + ret.lc_sum = sum; i += snprintf(page + i, count - i, " %s_per_rpc: "LPU64"\n", ret.lc_units, ret.lc_sum); @@ -1055,10 +1139,11 @@ static void lprocfs_free_client_stats(struct nid_stat *client_stat) client_stat->nid_proc, client_stat->nid_stats, client_stat->nid_brw_stats); - LASSERTF(atomic_read(&client_stat->nid_exp_ref_count) == 0, - "count %d\n", atomic_read(&client_stat->nid_exp_ref_count)); + LASSERTF(cfs_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)); - hlist_del_init(&client_stat->nid_hash); + cfs_hlist_del_init(&client_stat->nid_hash); if (client_stat->nid_proc) lprocfs_remove(&client_stat->nid_proc); @@ -1084,10 +1169,10 @@ void lprocfs_free_per_client_stats(struct obd_device *obd) /* 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); + 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); lprocfs_free_client_stats(stat); } @@ -1108,7 +1193,7 @@ struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num, if (flags & LPROCFS_STATS_FLAG_NOPERCPU) num_cpu = 1; else - num_cpu = num_possible_cpus(); + num_cpu = cfs_num_possible_cpus(); OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_cpu])); if (stats == NULL) @@ -1116,7 +1201,7 @@ struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num, if (flags & LPROCFS_STATS_FLAG_NOPERCPU) { stats->ls_flags = flags; - spin_lock_init(&stats->ls_lock); + cfs_spin_lock_init(&stats->ls_lock); /* Use this lock only if there are no percpu areas */ } else { stats->ls_flags = 0; @@ -1124,7 +1209,7 @@ struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num, percpusize = offsetof(struct lprocfs_percpu, lp_cntr[num]); if (num_cpu > 1) - percpusize = L1_CACHE_ALIGN(percpusize); + percpusize = CFS_L1_CACHE_ALIGN(percpusize); for (i = 0; i < num_cpu; i++) { OBD_ALLOC(stats->ls_percpu[i], percpusize); @@ -1160,11 +1245,11 @@ void lprocfs_free_stats(struct lprocfs_stats **statsh) if (stats->ls_flags & LPROCFS_STATS_FLAG_NOPERCPU) num_cpu = 1; else - num_cpu = num_possible_cpus(); + num_cpu = cfs_num_possible_cpus(); percpusize = offsetof(struct lprocfs_percpu, lp_cntr[stats->ls_num]); if (num_cpu > 1) - percpusize = L1_CACHE_ALIGN(percpusize); + percpusize = CFS_L1_CACHE_ALIGN(percpusize); for (i = 0; i < num_cpu; i++) OBD_FREE(stats->ls_percpu[i], percpusize); OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_cpu])); @@ -1181,17 +1266,17 @@ void lprocfs_clear_stats(struct lprocfs_stats *stats) for (i = 0; i < num_cpu; i++) { for (j = 0; j < stats->ls_num; j++) { percpu_cntr = &(stats->ls_percpu[i])->lp_cntr[j]; - atomic_inc(&percpu_cntr->lc_cntl.la_entry); + cfs_atomic_inc(&percpu_cntr->lc_cntl.la_entry); percpu_cntr->lc_count = 0; percpu_cntr->lc_sum = 0; percpu_cntr->lc_min = LC_MIN_INIT; percpu_cntr->lc_max = 0; percpu_cntr->lc_sumsquare = 0; - atomic_inc(&percpu_cntr->lc_cntl.la_exit); + cfs_atomic_inc(&percpu_cntr->lc_cntl.la_exit); } } - lprocfs_stats_unlock(stats); + lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU); } static ssize_t lprocfs_stats_seq_write(struct file *file, const char *buf, @@ -1235,7 +1320,7 @@ static int lprocfs_stats_seq_show(struct seq_file *p, void *v) if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) { struct timeval now; - do_gettimeofday(&now); + cfs_gettimeofday(&now); rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n", "snapshot_time", now.tv_sec, now.tv_usec); if (rc < 0) @@ -1282,7 +1367,9 @@ static int lprocfs_stats_seq_open(struct inode *inode, struct file *file) struct seq_file *seq; int rc; - LPROCFS_ENTRY_AND_CHECK(dp); + if (LPROCFS_ENTRY_AND_CHECK(dp)) + return -ENOENT; + rc = seq_open(file, &lprocfs_stats_seq_sops); if (rc) { LPROCFS_EXIT(); @@ -1308,11 +1395,18 @@ int lprocfs_register_stats(struct proc_dir_entry *root, const char *name, struct proc_dir_entry *entry; LASSERT(root != NULL); + LPROCFS_WRITE_ENTRY(); entry = create_proc_entry(name, 0644, root); + if (entry) { + entry->proc_fops = &lprocfs_stats_seq_fops; + entry->data = stats; + } + + LPROCFS_WRITE_EXIT(); + if (entry == NULL) return -ENOMEM; - entry->proc_fops = &lprocfs_stats_seq_fops; - entry->data = stats; + return 0; } @@ -1338,7 +1432,7 @@ void lprocfs_counter_init(struct lprocfs_stats *stats, int index, c->lc_units = units; } - lprocfs_stats_unlock(stats); + lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU); } EXPORT_SYMBOL(lprocfs_counter_init); @@ -1374,10 +1468,10 @@ void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats) 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, checkmd); LPROCFS_OBD_OP_INIT(num_private_stats, stats, preallocate); LPROCFS_OBD_OP_INIT(num_private_stats, stats, precreate); 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); @@ -1395,6 +1489,7 @@ void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats) LPROCFS_OBD_OP_INIT(num_private_stats, stats, commitrw); LPROCFS_OBD_OP_INIT(num_private_stats, stats, enqueue); 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, cancel); LPROCFS_OBD_OP_INIT(num_private_stats, stats, cancel_unused); LPROCFS_OBD_OP_INIT(num_private_stats, stats, init_export); @@ -1472,25 +1567,11 @@ do { \ lprocfs_counter_init(stats, coffset, 0, #op, "reqs"); \ } while (0) -int lprocfs_alloc_md_stats(struct obd_device *obd, - unsigned num_private_stats) +void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats) { - struct lprocfs_stats *stats; - unsigned int num_stats; - int rc, i; - - LASSERT(obd->md_stats == NULL); - LASSERT(obd->obd_proc_entry != NULL); - LASSERT(obd->md_cntr_base == 0); - - num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) + - num_private_stats; - stats = lprocfs_alloc_stats(num_stats, 0); - if (stats == NULL) - return -ENOMEM; - LPROCFS_MD_OP_INIT(num_private_stats, stats, getstatus); LPROCFS_MD_OP_INIT(num_private_stats, stats, change_cbdata); + LPROCFS_MD_OP_INIT(num_private_stats, stats, find_cbdata); LPROCFS_MD_OP_INIT(num_private_stats, stats, close); LPROCFS_MD_OP_INIT(num_private_stats, stats, create); LPROCFS_MD_OP_INIT(num_private_stats, stats, done_writing); @@ -1520,6 +1601,26 @@ int lprocfs_alloc_md_stats(struct obd_device *obd, LPROCFS_MD_OP_INIT(num_private_stats, stats, get_remote_perm); LPROCFS_MD_OP_INIT(num_private_stats, stats, intent_getattr_async); LPROCFS_MD_OP_INIT(num_private_stats, stats, revalidate_lock); +} + +int lprocfs_alloc_md_stats(struct obd_device *obd, + unsigned num_private_stats) +{ + struct lprocfs_stats *stats; + unsigned int num_stats; + int rc, i; + + LASSERT(obd->md_stats == NULL); + LASSERT(obd->obd_proc_entry != NULL); + LASSERT(obd->md_cntr_base == 0); + + num_stats = 1 + MD_COUNTER_OFFSET(revalidate_lock) + + num_private_stats; + stats = lprocfs_alloc_stats(num_stats, 0); + if (stats == NULL) + return -ENOMEM; + + lprocfs_init_mps_stats(num_private_stats, stats); for (i = num_private_stats; i < num_stats; i++) { if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) { @@ -1598,15 +1699,18 @@ lprocfs_exp_rd_cb_data_init(struct exp_uuid_cb_data *cb_data, char *page, cb_data->len = len; } -void lprocfs_exp_print_uuid(void *obj, void *cb_data) +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 = (struct obd_export *)obj; + 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, @@ -1620,26 +1724,28 @@ int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count, *eof = 1; page[0] = '\0'; lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len); - lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid, - lprocfs_exp_print_uuid, &cb_data); + cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid, + lprocfs_exp_print_uuid, &cb_data); return (*cb_data.len); } -void lprocfs_exp_print_hash(void *obj, void *cb_data) +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 = obj; - lustre_hash_t *lh; - - lh = exp->exp_lock_hash; - if (lh) { - if (!*data->len) - *data->len += lustre_hash_debug_header(data->page, - data->count); + struct obd_export *exp = cfs_hash_object(hs, hnode); - *data->len += lustre_hash_debug_str(lh, data->page + *data->len, - data->count); + 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, @@ -1654,8 +1760,8 @@ int lprocfs_exp_rd_hash(char *page, char **start, off_t off, int count, page[0] = '\0'; lprocfs_exp_rd_cb_data_init(&cb_data, page, count, eof, &len); - lustre_hash_for_each_key(obd->obd_nid_hash, &stats->nid, - lprocfs_exp_print_hash, &cb_data); + cfs_hash_for_each_key(obd->obd_nid_hash, &stats->nid, + lprocfs_exp_print_hash, &cb_data); return (*cb_data.len); } @@ -1669,22 +1775,19 @@ int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off, } EXPORT_SYMBOL(lprocfs_nid_stats_clear_read); -void lprocfs_nid_stats_clear_write_cb(void *obj, void *data) +int lprocfs_nid_stats_clear_write_cb(void *obj, void *data) { struct nid_stat *stat = obj; int i; ENTRY; - /* object has only hash + iterate_all references. - * add/delete blocked by hash bucket lock */ - CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count)); - if (atomic_read(&stat->nid_exp_ref_count) == 2) { - hlist_del_init(&stat->nid_hash); - nidstat_putref(stat); - spin_lock(&stat->nid_obd->obd_nid_lock); - list_move(&stat->nid_list, data); - spin_unlock(&stat->nid_obd->obd_nid_lock); - EXIT; - return; + + CDEBUG(D_INFO,"refcnt %d\n", cfs_atomic_read(&stat->nid_exp_ref_count)); + if (cfs_atomic_read(&stat->nid_exp_ref_count) == 1) { + /* object has only hash references. */ + cfs_spin_lock(&stat->nid_obd->obd_nid_lock); + cfs_list_move(&stat->nid_list, data); + cfs_spin_unlock(&stat->nid_obd->obd_nid_lock); + RETURN(1); } /* we has reference to object - only clear data*/ if (stat->nid_stats) @@ -1694,24 +1797,23 @@ void lprocfs_nid_stats_clear_write_cb(void *obj, void *data) for (i = 0; i < BRW_LAST; i++) lprocfs_oh_clear(&stat->nid_brw_stats->hist[i]); } - EXIT; - return; + RETURN(0); } int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { struct obd_device *obd = (struct obd_device *)data; struct nid_stat *client_stat; CFS_LIST_HEAD(free_list); - lustre_hash_for_each(obd->obd_nid_stats_hash, - lprocfs_nid_stats_clear_write_cb, &free_list); + 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); + 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); } @@ -1724,6 +1826,7 @@ 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; @@ -1749,36 +1852,39 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid) new_stat->nid = *nid; new_stat->nid_obd = exp->exp_obd; - atomic_set(&new_stat->nid_exp_ref_count, 0); + /* we need set default refcount to 1 to balance obd_disconnect */ + cfs_atomic_set(&new_stat->nid_exp_ref_count, 1); - old_stat = lustre_hash_findadd_unique(obd->obd_nid_stats_hash, - nid, &new_stat->nid_hash); + 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)); + cfs_atomic_read(&new_stat->nid_exp_ref_count)); + + /* We need to release old stats because lprocfs_exp_cleanup() hasn't + * been and will never be called. */ + if (exp->exp_nid_stats) { + nidstat_putref(exp->exp_nid_stats); + exp->exp_nid_stats = NULL; + } /* Return -EALREADY here so that we know that the /proc * entry already has been created */ if (old_stat != new_stat) { - spin_lock(&obd->obd_nid_lock); - if (exp->exp_nid_stats != old_stat) { - if (exp->exp_nid_stats) - nidstat_putref(exp->exp_nid_stats); - exp->exp_nid_stats = old_stat; - } else { - /* lustre_hash_findadd_unique() has added - * old_stat's refcount */ - nidstat_putref(old_stat); - } - - spin_unlock(&obd->obd_nid_lock); - + exp->exp_nid_stats = old_stat; GOTO(destroy_new, rc = -EALREADY); } /* not found - create */ - new_stat->nid_proc = lprocfs_register(libcfs_nid2str(*nid), + OBD_ALLOC(buffer, LNET_NIDSTR_SIZE); + if (buffer == NULL) + GOTO(destroy_new, rc = -ENOMEM); + + memcpy(buffer, libcfs_nid2str(*nid), LNET_NIDSTR_SIZE); + new_stat->nid_proc = lprocfs_register(buffer, obd->obd_proc_exports_entry, NULL, NULL); + OBD_FREE(buffer, LNET_NIDSTR_SIZE); + if (new_stat->nid_proc == NULL) { CERROR("Error making export directory for nid %s\n", libcfs_nid2str(*nid)); @@ -1801,24 +1907,22 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid) GOTO(destroy_new_ns, rc); } - if (exp->exp_nid_stats) - nidstat_putref(exp->exp_nid_stats); - nidstat_getref(new_stat); exp->exp_nid_stats = new_stat; *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); + cfs_spin_lock(&obd->obd_nid_lock); + cfs_list_add(&new_stat->nid_list, &obd->obd_nid_stats); + cfs_spin_unlock(&obd->obd_nid_lock); RETURN(rc); destroy_new_ns: if (new_stat->nid_proc != NULL) lprocfs_remove(&new_stat->nid_proc); - lustre_hash_del(obd->obd_nid_stats_hash, nid, &new_stat->nid_hash); + 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); } @@ -1832,7 +1936,6 @@ int lprocfs_exp_cleanup(struct obd_export *exp) nidstat_putref(exp->exp_nid_stats); exp->exp_nid_stats = NULL; - lprocfs_free_md_stats(exp->exp_obd); return 0; } @@ -1851,7 +1954,7 @@ int lprocfs_write_frac_helper(const char *buffer, unsigned long count, if (count > (sizeof(kernbuf) - 1)) return -EINVAL; - if (copy_from_user(kernbuf, buffer, count)) + if (cfs_copy_from_user(kernbuf, buffer, count)) return -EFAULT; kernbuf[count] = '\0'; @@ -1954,7 +2057,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, if (count > (sizeof(kernbuf) - 1)) return -EINVAL; - if (copy_from_user(kernbuf, buffer, count)) + if (cfs_copy_from_user(kernbuf, buffer, count)) return -EFAULT; kernbuf[count] = '\0'; @@ -2011,11 +2114,16 @@ int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode, struct proc_dir_entry *entry; ENTRY; + LPROCFS_WRITE_ENTRY(); entry = create_proc_entry(name, mode, parent); + if (entry) { + entry->proc_fops = seq_fops; + entry->data = data; + } + LPROCFS_WRITE_EXIT(); + if (entry == NULL) RETURN(-ENOMEM); - entry->proc_fops = seq_fops; - entry->data = data; RETURN(0); } @@ -2036,9 +2144,9 @@ void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value) if (value >= OBD_HIST_MAX) value = OBD_HIST_MAX - 1; - spin_lock(&oh->oh_lock); + cfs_spin_lock(&oh->oh_lock); oh->oh_buckets[value]++; - spin_unlock(&oh->oh_lock); + cfs_spin_unlock(&oh->oh_lock); } EXPORT_SYMBOL(lprocfs_oh_tally); @@ -2066,9 +2174,9 @@ EXPORT_SYMBOL(lprocfs_oh_sum); void lprocfs_oh_clear(struct obd_histogram *oh) { - spin_lock(&oh->oh_lock); + cfs_spin_lock(&oh->oh_lock); memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets)); - spin_unlock(&oh->oh_lock); + cfs_spin_unlock(&oh->oh_lock); } EXPORT_SYMBOL(lprocfs_oh_clear); @@ -2081,10 +2189,15 @@ int lprocfs_obd_rd_hash(char *page, char **start, off_t off, if (obd == NULL) return 0; - c += lustre_hash_debug_header(page, count); - c += lustre_hash_debug_str(obd->obd_uuid_hash, page + c, count - c); - c += lustre_hash_debug_str(obd->obd_nid_hash, page + c, count - c); - c += lustre_hash_debug_str(obd->obd_nid_stats_hash, page+c, count-c); + 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); +#ifdef HAVE_QUOTA_SUPPORT + if (obd->u.obt.obt_qctxt.lqc_lqs_hash) + c += cfs_hash_debug_str(obd->u.obt.obt_qctxt.lqc_lqs_hash, + page + c, count - c); +#endif return c; } @@ -2140,7 +2253,7 @@ int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off, if (lprocfs_obd_snprintf(&page, size, &len, "completed_clients: %d/%d\n", obd->obd_max_recoverable_clients - - obd->obd_recoverable_clients, + obd->obd_stale_clients, obd->obd_max_recoverable_clients) <= 0) goto out; if (lprocfs_obd_snprintf(&page, size, &len, @@ -2151,6 +2264,9 @@ int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off, "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 ? "ON" : "OFF")<=0) + goto out; goto fclose; } @@ -2168,12 +2284,23 @@ int lprocfs_obd_rd_recovery_status(char *page, char **start, off_t off, obd->obd_max_recoverable_clients) <= 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_recoverable_clients, - obd->obd_max_recoverable_clients) <= 0) + if (lprocfs_obd_snprintf(&page, size, &len,"req_replay_clients: %d\n", + cfs_atomic_read(&obd->obd_req_replay_clients)) + <= 0) + goto out; + if (lprocfs_obd_snprintf(&page, size, &len,"lock_repay_clients: %d\n", + cfs_atomic_read(&obd->obd_lock_replay_clients)) + <=0) goto out; - if (lprocfs_obd_snprintf(&page, size, &len,"replayed_requests: %d/??\n", + if (lprocfs_obd_snprintf(&page, size, &len,"completed_clients: %d\n", + obd->obd_connected_clients - + cfs_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", @@ -2191,20 +2318,21 @@ out: } EXPORT_SYMBOL(lprocfs_obd_rd_recovery_status); -int lprocfs_obd_rd_recovery_maxtime(char *page, char **start, off_t off, - int count, int *eof, void *data) +int lprocfs_obd_rd_recovery_time_soft(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct obd_device *obd = data; + struct obd_device *obd = (struct obd_device *)data; LASSERT(obd != NULL); - return snprintf(page, count, "%lu\n", obd->obd_recovery_max_time); + return snprintf(page, count, "%d\n", + obd->obd_recovery_timeout); } -EXPORT_SYMBOL(lprocfs_obd_rd_recovery_maxtime); +EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_soft); -int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer, - unsigned long count, void *data) +int lprocfs_obd_wr_recovery_time_soft(struct file *file, const char *buffer, + unsigned long count, void *data) { - struct obd_device *obd = data; + struct obd_device *obd = (struct obd_device *)data; int val, rc; LASSERT(obd != NULL); @@ -2212,267 +2340,89 @@ int lprocfs_obd_wr_recovery_maxtime(struct file *file, const char *buffer, if (rc) return rc; - obd->obd_recovery_max_time = val; + obd->obd_recovery_timeout = val; return count; } -EXPORT_SYMBOL(lprocfs_obd_wr_recovery_maxtime); - - -/**** Changelogs *****/ -#define D_CHANGELOG 0 - -DECLARE_CHANGELOG_NAMES; - -/* How many records per seq_show. Too small, we spawn llog_process threads - too often; too large, we run out of buffer space */ -#define CHANGELOG_CHUNK_SIZE 100 - -static int changelog_show_cb(struct llog_handle *llh, struct llog_rec_hdr *hdr, - void *data) -{ - struct seq_file *seq = (struct seq_file *)data; - struct changelog_seq_iter *csi = seq->private; - struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr; - int rc; - ENTRY; - - if ((rec->cr_hdr.lrh_type != CHANGELOG_REC) || - (rec->cr_type >= CL_LAST)) { - CERROR("Not a changelog rec %d/%d\n", rec->cr_hdr.lrh_type, - rec->cr_type); - RETURN(-EINVAL); - } - - CDEBUG(D_CHANGELOG, "rec="LPU64" start="LPU64" cat=%d:%d start=%d:%d\n", - rec->cr_index, csi->csi_startrec, - llh->lgh_hdr->llh_cat_idx, llh->lgh_cur_idx, - csi->csi_startcat, csi->csi_startidx); - - if (rec->cr_index < csi->csi_startrec) - /* Skip entries earlier than what we are interested in */ - RETURN(0); - if (rec->cr_index == csi->csi_startrec) { - /* Remember where we started, since seq_read will re-read - * the data when it reallocs space. Sigh, if only there was - * a way to tell seq_file how big the buf should be in the - * first place... - */ - csi->csi_startcat = llh->lgh_hdr->llh_cat_idx; - csi->csi_startidx = rec->cr_hdr.lrh_index - 1; - } - if (csi->csi_wrote > CHANGELOG_CHUNK_SIZE) { - /* Stop at some point with a reasonable seq_file buffer size. - * Start from here the next time. - */ - csi->csi_endrec = rec->cr_index - 1; - csi->csi_startcat = llh->lgh_hdr->llh_cat_idx; - csi->csi_startidx = rec->cr_hdr.lrh_index - 1; - csi->csi_wrote = 0; - RETURN(LLOG_PROC_BREAK); - } - - rc = seq_printf(seq, LPU64" %02d%-5s "LPU64" 0x%x t="DFID, - rec->cr_index, rec->cr_type, - changelog_str[rec->cr_type], rec->cr_time, - rec->cr_flags & CLF_FLAGMASK, PFID(&rec->cr_tfid)); - - if (rec->cr_namelen) - /* namespace rec includes parent and filename */ - rc += seq_printf(seq, " p="DFID" %.*s\n", PFID(&rec->cr_pfid), - rec->cr_namelen, rec->cr_name); - else - rc += seq_puts(seq, "\n"); - - if (rc < 0) { - /* Ran out of room in the seq buffer. seq_read will dump - * the whole buffer and re-seq_start with a larger one; - * no point in continuing the llog_process */ - CDEBUG(D_CHANGELOG, "rec="LPU64" overflow "LPU64"<-"LPU64"\n", - rec->cr_index, csi->csi_startrec, csi->csi_endrec); - csi->csi_endrec = csi->csi_startrec - 1; - csi->csi_wrote = 0; - RETURN(LLOG_PROC_BREAK); - } - - csi->csi_wrote++; - csi->csi_endrec = rec->cr_index; - - RETURN(0); -} +EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_soft); -static int changelog_seq_show(struct seq_file *seq, void *v) +int lprocfs_obd_rd_recovery_time_hard(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct changelog_seq_iter *csi = seq->private; - int rc; - ENTRY; - - if (csi->csi_fill) { - /* seq_read wants more data to fill his buffer. But we already - filled the buf as much as we cared to; force seq_read to - accept that by padding with 0's */ - while (seq_putc(seq, 0) == 0); - RETURN(0); - } - - /* Since we have to restart the llog_cat_process for each chunk of the - seq_ functions, start from where we left off. */ - rc = llog_cat_process(csi->csi_llh, changelog_show_cb, seq, - csi->csi_startcat, csi->csi_startidx); - - CDEBUG(D_CHANGELOG,"seq_show "LPU64"-"LPU64" cat=%d:%d wrote=%d rc=%d\n", - csi->csi_startrec, csi->csi_endrec, csi->csi_startcat, - csi->csi_startidx, csi->csi_wrote, rc); + struct obd_device *obd = data; + LASSERT(obd != NULL); - if (rc == 0) - csi->csi_done = 1; - if (rc == LLOG_PROC_BREAK) - /* more records left, but seq_show must return 0 */ - rc = 0; - RETURN(rc); + return snprintf(page, count, "%lu\n", obd->obd_recovery_time_hard); } +EXPORT_SYMBOL(lprocfs_obd_rd_recovery_time_hard); -static void *changelog_seq_start(struct seq_file *seq, loff_t *pos) +int lprocfs_obd_wr_recovery_time_hard(struct file *file, const char *buffer, + unsigned long count, void *data) { - struct changelog_seq_iter *csi = seq->private; - LASSERT(csi); - - CDEBUG(D_CHANGELOG, "start "LPU64"-"LPU64" pos="LPU64"\n", - csi->csi_startrec, csi->csi_endrec, *pos); - - csi->csi_fill = 0; - - if (csi->csi_done) - /* no more records, seq_read should return 0 if buffer - is empty */ - return NULL; - - if (*pos > csi->csi_pos) { - /* The seq_read implementation sucks. It may call start - multiple times, using pos to indicate advances, if any, - by arbitrarily increasing it by 1. So ignore the actual - value of pos, and just register any increase as - "seq_read wants the next values". */ - csi->csi_startrec = csi->csi_endrec + 1; - csi->csi_pos = *pos; - } - /* else use old startrec/startidx */ - - return csi; -} + struct obd_device *obd = data; + int val, rc; + LASSERT(obd != NULL); -static void changelog_seq_stop(struct seq_file *seq, void *v) -{ - struct changelog_seq_iter *csi = seq->private; + rc = lprocfs_write_helper(buffer, count, &val); + if (rc) + return rc; - CDEBUG(D_CHANGELOG, "stop "LPU64"-"LPU64"\n", - csi->csi_startrec, csi->csi_endrec); + obd->obd_recovery_time_hard = val; + return count; } +EXPORT_SYMBOL(lprocfs_obd_wr_recovery_time_hard); -static void *changelog_seq_next(struct seq_file *seq, void *v, loff_t *pos) +int lprocfs_obd_rd_mntdev(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct changelog_seq_iter *csi = seq->private; - - CDEBUG(D_CHANGELOG, "next "LPU64"-"LPU64" pos="LPU64"\n", - csi->csi_startrec, csi->csi_endrec, *pos); - - csi->csi_fill = 1; + struct obd_device *obd = (struct obd_device *)data; - return csi; + LASSERT(obd != NULL); + LASSERT(obd->u.obt.obt_vfsmnt->mnt_devname); + *eof = 1; + return snprintf(page, count, "%s\n", + obd->u.obt.obt_vfsmnt->mnt_devname); } +EXPORT_SYMBOL(lprocfs_obd_rd_mntdev); -static struct seq_operations changelog_sops = { - .start = changelog_seq_start, - .stop = changelog_seq_stop, - .next = changelog_seq_next, - .show = changelog_seq_show, -}; - -int changelog_seq_open(struct inode *inode, struct file *file, - struct changelog_seq_iter **csih) +int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct changelog_seq_iter *csi; - struct proc_dir_entry *dp = PDE(inode); - struct seq_file *seq; + struct obd_device *dev = data; + struct client_obd *cli = &dev->u.cli; int rc; - LPROCFS_ENTRY_AND_CHECK(dp); - - rc = seq_open(file, &changelog_sops); - if (rc) { - LPROCFS_EXIT(); - return rc; - } - - OBD_ALLOC_PTR(csi); - if (csi == NULL) { - lprocfs_seq_release(inode, file); - return -ENOMEM; - } - - csi->csi_dev = dp->data; - seq = file->private_data; - seq->private = csi; - *csih = csi; - + client_obd_list_lock(&cli->cl_loi_list_lock); + rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc); + client_obd_list_unlock(&cli->cl_loi_list_lock); return rc; } -EXPORT_SYMBOL(changelog_seq_open); +EXPORT_SYMBOL(lprocfs_obd_rd_max_pages_per_rpc); -int changelog_seq_release(struct inode *inode, struct file *file) +int lprocfs_obd_wr_max_pages_per_rpc(struct file *file, const char *buffer, + unsigned long count, void *data) { - struct seq_file *seq = file->private_data; - struct changelog_seq_iter *csi = seq->private; - - if (csi) - OBD_FREE_PTR(csi); - - return lprocfs_seq_release(inode, file); -} -EXPORT_SYMBOL(changelog_seq_release); - -#ifndef SEEK_CUR /* SLES10 needs this */ -#define SEEK_CUR 1 -#define SEEK_END 2 -#endif - -loff_t changelog_seq_lseek(struct file *file, loff_t offset, int origin) -{ - struct seq_file *seq = (struct seq_file *)file->private_data; - struct changelog_seq_iter *csi = seq->private; - - CDEBUG(D_CHANGELOG,"seek "LPU64"-"LPU64" off="LPU64":%d fpos="LPU64"\n", - csi->csi_startrec, csi->csi_endrec, offset, origin, file->f_pos); - - LL_SEQ_LOCK(seq); - - switch (origin) { - case SEEK_CUR: - offset += csi->csi_endrec; - break; - case SEEK_END: - /* we don't know the last rec */ - offset = -1; - } + struct obd_device *dev = data; + struct client_obd *cli = &dev->u.cli; + struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data; + int val, rc; - /* SEEK_SET */ + rc = lprocfs_write_helper(buffer, count, &val); + if (rc) + return rc; - if (offset < 0) { - LL_SEQ_UNLOCK(seq); - return -EINVAL; + LPROCFS_CLIMP_CHECK(dev); + if (val < 1 || val > ocd->ocd_brw_size >> CFS_PAGE_SHIFT) { + LPROCFS_CLIMP_EXIT(dev); + return -ERANGE; } + client_obd_list_lock(&cli->cl_loi_list_lock); + cli->cl_max_pages_per_rpc = val; + client_obd_list_unlock(&cli->cl_loi_list_lock); - csi->csi_startrec = offset; - csi->csi_endrec = offset ? offset - 1 : 0; - - /* drop whatever is left in sucky seq_read's buffer */ - seq->count = 0; - seq->from = 0; - seq->index++; - LL_SEQ_UNLOCK(seq); - file->f_pos = csi->csi_startrec; - return csi->csi_startrec; + LPROCFS_CLIMP_EXIT(dev); + return count; } -EXPORT_SYMBOL(changelog_seq_lseek); +EXPORT_SYMBOL(lprocfs_obd_wr_max_pages_per_rpc); EXPORT_SYMBOL(lprocfs_register); EXPORT_SYMBOL(lprocfs_srch); @@ -2489,10 +2439,12 @@ EXPORT_SYMBOL(lprocfs_free_stats); EXPORT_SYMBOL(lprocfs_clear_stats); EXPORT_SYMBOL(lprocfs_register_stats); EXPORT_SYMBOL(lprocfs_init_ops_stats); +EXPORT_SYMBOL(lprocfs_init_mps_stats); EXPORT_SYMBOL(lprocfs_init_ldlm_stats); EXPORT_SYMBOL(lprocfs_alloc_obd_stats); EXPORT_SYMBOL(lprocfs_alloc_md_stats); EXPORT_SYMBOL(lprocfs_free_obd_stats); +EXPORT_SYMBOL(lprocfs_free_md_stats); EXPORT_SYMBOL(lprocfs_exp_setup); EXPORT_SYMBOL(lprocfs_exp_cleanup);