X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdclass%2Flprocfs_status.c;h=d5ef04ca37fe67dcb6ea2443c6ed2bccdcd8aff3;hb=73107bf8aae7d4498de058d206319334ab8751d6;hp=6e6ebfb393dde1afe214469d59254b53718aba5a;hpb=05ea8d2b4ce1b6794bc12d78bae9cfe1608cb4d3;p=fs%2Flustre-release.git diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 6e6ebfb..d5ef04c 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -1,7 +1,8 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Copyright (C) 2002 Cluster File Systems, Inc. + * Copyright (C) 2002, 2003 Cluster File Systems, Inc. + * Author: Hariharan Thantry * * This file is part of Lustre, http://www.lustre.org. * @@ -17,335 +18,804 @@ * You should have received a copy of the GNU General Public License * along with Lustre; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * */ -#define EXPORT_SYMTAB -#include -#include -#include -#include -#include -#include - +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif #define DEBUG_SUBSYSTEM S_CLASS -#define MAX_STRING_SIZE 100 -#include +#ifdef __KERNEL__ +# include +# include +# include +# include +# include +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) +# include +# endif +# include +#else /* __KERNEL__ */ +# include +#endif + +#include #include +#include -#ifdef LPROC_SNMP - -#define DEFAULT_MODE 0444 -/* - * Tokenizer array. Change this array to include special - * characters for string tokenizing - */ -char tok[] = {'/', (char)0}; - -/* - * Externs - */ -extern struct proc_dir_entry proc_root; /* Defined in proc/root.c */ +#if defined(LPROCFS) && defined(__KERNEL__) -/* - * Globals - */ -struct proc_dir_entry *proc_lustre_root = 0; -struct proc_dir_entry *proc_lustre_dev_root = 0; -struct proc_dir_entry *proc_lustre_fs_root=0; - -struct proc_dir_entry* lprocfs_mkdir(const char* dname, - struct proc_dir_entry *parent) +struct proc_dir_entry *lprocfs_srch(struct proc_dir_entry *head, + const char *name) { - struct proc_dir_entry *child_dir_entry; - - child_dir_entry = proc_mkdir(dname, parent); + struct proc_dir_entry *temp; - if (!child_dir_entry) - CERROR("lustre: failed to create /proc entry %s\n", dname); + if (head == NULL) + return NULL; - return child_dir_entry; -} -struct proc_dir_entry* lprocfs_srch(struct proc_dir_entry* head, - const char* name) -{ - struct proc_dir_entry* temp; - - if (!head) - return 0; temp = head->subdir; while (temp != NULL) { - if (!strcmp(temp->name, name)) + if (strcmp(temp->name, name) == 0) return temp; + temp = temp->next; } - - return 0; + return NULL; } +/* lprocfs API calls */ -void lprocfs_remove_all(struct proc_dir_entry* root) +int lprocfs_add_vars(struct proc_dir_entry *root, struct lprocfs_vars *list, + void *data) { + if (root == NULL || list == NULL) + return -EINVAL; - struct proc_dir_entry *temp=root; - struct proc_dir_entry* rm_entry; - struct proc_dir_entry* parent=root->parent; + while (list->name != NULL) { + struct proc_dir_entry *cur_root, *proc; + char *pathcopy, *cur, *next, pathbuf[64]; + int pathsize = strlen(list->name) + 1; - while(1){ + proc = NULL; + cur_root = root; - while(temp->subdir){ - temp=temp->subdir; + /* need copy of path for strsep */ + if (strlen(list->name) > sizeof(pathbuf) - 1) { + OBD_ALLOC(pathcopy, pathsize); + if (pathcopy == NULL) + return -ENOMEM; + } else { + pathcopy = pathbuf; + } + + next = pathcopy; + strcpy(pathcopy, list->name); + + while (cur_root != NULL && (cur = strsep(&next, "/"))) { + if (*cur =='\0') /* skip double/trailing "/" */ + continue; + + 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")); + if (next != NULL) { + cur_root = (proc ? proc : + proc_mkdir(cur, cur_root)); + } else if (proc == NULL) { + mode_t mode = 0; + if (list->read_fptr) + mode = 0444; + if (list->write_fptr) + mode |= 0200; + proc = create_proc_entry(cur, mode, cur_root); + } } - rm_entry=temp; - temp=temp->parent; - remove_proc_entry(rm_entry->name, rm_entry->parent); - if(temp==parent) break; + if (pathcopy != pathbuf) + OBD_FREE(pathcopy, pathsize); + + if (cur_root == NULL || proc == NULL) { + CERROR("LprocFS: No memory to create /proc entry %s", + list->name); + return -ENOMEM; + } + + proc->read_proc = list->read_fptr; + proc->write_proc = list->write_fptr; + proc->data = (list->data ? list->data : data); + list++; } + return 0; +} +void lprocfs_remove(struct proc_dir_entry *root) +{ + struct proc_dir_entry *temp = root; + struct proc_dir_entry *rm_entry; + struct proc_dir_entry *parent; + + LASSERT(root != NULL); + parent = root->parent; + LASSERT(parent != NULL); + + while (1) { + while (temp->subdir != NULL) + temp = temp->subdir; + + rm_entry = temp; + temp = temp->parent; + + /* Memory corruption once caused this to fail, and + without this LASSERT we would loop here forever. */ + LASSERTF(strlen(rm_entry->name) == rm_entry->namelen, + "0x%p %s/%s len %d\n", rm_entry, temp->name, + rm_entry->name, (int)strlen(rm_entry->name)); + remove_proc_entry(rm_entry->name, rm_entry->parent); + if (temp == parent) + break; + } } -struct proc_dir_entry* lprocfs_new_dir(struct proc_dir_entry* root, - const char* string, - const char* tok) +struct proc_dir_entry *lprocfs_register(const char *name, + struct proc_dir_entry *parent, + struct lprocfs_vars *list, void *data) { - struct proc_dir_entry* new_root = 0; - struct proc_dir_entry* temp_entry = 0; - - char temp_string[MAX_STRING_SIZE]; - char* my_str; - char* mover_str; + struct proc_dir_entry *newchild; - - strncpy(temp_string, string, MAX_STRING_SIZE-1); - temp_string[strlen(string) + 1] = '\0'; - - new_root=root; - mover_str=temp_string; - while ((my_str = strsep(&mover_str, tok))) { - if(!*my_str) - continue; - CDEBUG(D_OTHER, "SEARCH= %s\t, ROOT=%s\n", my_str, - new_root->name); - temp_entry = lprocfs_srch(new_root, my_str); - if (temp_entry == 0) { - CDEBUG(D_OTHER, "Adding: %s\n", my_str); - temp_entry = lprocfs_mkdir(my_str, new_root); - if (temp_entry == 0) { - CDEBUG(D_OTHER, - "! Did not create new dir %s !!\n", - my_str); - return 0; - } + newchild = lprocfs_srch(parent, name); + if (newchild != NULL) { + CERROR(" Lproc: Attempting to register %s more than once \n", + name); + return ERR_PTR(-EALREADY); + } + + newchild = proc_mkdir(name, parent); + if (newchild != NULL && list != NULL) { + int rc = lprocfs_add_vars(newchild, list, data); + if (rc) { + lprocfs_remove(newchild); + return ERR_PTR(rc); } - new_root = temp_entry; } + return newchild; +} - return new_root; +/* Generic callbacks */ + +int lprocfs_rd_u64(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + LASSERT(data != NULL); + *eof = 1; + return snprintf(page, count, LPU64"\n", *(__u64 *)data); } -int lprocfs_new_vars(struct proc_dir_entry* root, - struct lprocfs_vars* list, - const char* tok, - void* data) +int lprocfs_rd_uuid(char *page, char **start, off_t off, int count, + int *eof, void *data) { - struct proc_dir_entry* temp_root=0; - struct proc_dir_entry* new_leaf=0; - struct proc_dir_entry* new_parent=0; - char temp_string[MAX_STRING_SIZE]; - - if(!list) - return 0; - - while(list->name){ - temp_root=lprocfs_new_dir(root, list->name, tok); - - if(!temp_root){ - CDEBUG(D_OTHER, "!LProcFS: Mods: No root!"); - return -EINVAL; - } - /* Convert the last element into a leaf-node */ - - strncpy(temp_string, temp_root->name, MAX_STRING_SIZE-1); - temp_string[strlen(temp_root->name) + 1] = '\0'; - new_parent=temp_root->parent; - if (new_parent != 0){ - remove_proc_entry(temp_root->name, new_parent); - } else { - remove_proc_entry(temp_root->name, NULL); - } - new_leaf = create_proc_entry(temp_string, DEFAULT_MODE, - new_parent); - new_leaf->read_proc = list->read_fptr; - new_leaf->write_proc = list->write_fptr; - new_leaf->data=data; - list++; - } - return 0; + struct obd_device *dev = (struct obd_device*)data; + LASSERT(dev != NULL); + *eof = 1; + return snprintf(page, count, "%s\n", dev->obd_uuid.uuid); } -/* - * API implementations - */ +int lprocfs_rd_name(char *page, char **start, off_t off, int count, + int *eof, void* data) +{ + struct obd_device *dev = (struct obd_device *)data; + + LASSERT(dev != NULL); + LASSERT(dev->obd_name != NULL); + *eof = 1; + return snprintf(page, count, "%s\n", dev->obd_name); +} -int lprocfs_add_vars(struct proc_dir_entry* root, - struct lprocfs_vars* var, - void* data) +int lprocfs_rd_fstype(char *page, char **start, off_t off, int count, int *eof, + void *data) { - - return lprocfs_new_vars(root, var, - (const char*) tok, data); + struct obd_device *obd = (struct obd_device *)data; - + LASSERT(obd != NULL); + LASSERT(obd->obd_fsops != NULL); + LASSERT(obd->obd_fsops->fs_type != NULL); + return snprintf(page, count, "%s\n", obd->obd_fsops->fs_type); } -int lprocfs_reg_obd(struct obd_device* device, - struct lprocfs_vars* list, - void* data) +int lprocfs_rd_blksize(char *page, char **start, off_t off, int count, + int *eof, void *data) { - - int retval = 0; - struct proc_dir_entry* this_dev_root=0; - - /* Obtain this device root */ - this_dev_root = lprocfs_mkdir(device->obd_name, - device->obd_type->typ_procroot); - - device->obd_proc_entry=this_dev_root; - retval=lprocfs_add_vars(this_dev_root, list, - data); - - return retval; + struct obd_statfs osfs; + int rc = obd_statfs(data, &osfs, jiffies - HZ); + if (!rc) { + *eof = 1; + rc = snprintf(page, count, "%u\n", osfs.os_bsize); + } + return rc; } -int lprocfs_dereg_obd(struct obd_device* device) +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, jiffies - HZ); + if (!rc) { + __u32 blk_size = osfs.os_bsize >> 10; + __u64 result = osfs.os_blocks; - CDEBUG(D_OTHER, "LPROCFS removing device = %s\n", device->obd_name); + while (blk_size >>= 1) + result <<= 1; - if (!device) { - CDEBUG(D_OTHER, "! LProcfs: Null pointer !\n"); - return 0; + *eof = 1; + rc = snprintf(page, count, LPU64"\n", result); } + return rc; +} - lprocfs_remove_all(device->obd_proc_entry); +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, jiffies - HZ); + if (!rc) { + __u32 blk_size = osfs.os_bsize >> 10; + __u64 result = osfs.os_bfree; - if (device->counters) - OBD_FREE(device->counters, device->cntr_mem_size); + while (blk_size >>= 1) + result <<= 1; - return 0; + *eof = 1; + rc = snprintf(page, count, LPU64"\n", result); + } + return rc; } -struct proc_dir_entry* lprocfs_reg_mnt(char* mnt_name) +int lprocfs_rd_kbytesavail(char *page, char **start, off_t off, int count, + int *eof, void *data) { - return lprocfs_mkdir(mnt_name, proc_lustre_fs_root); - + struct obd_statfs osfs; + int rc = obd_statfs(data, &osfs, jiffies - HZ); + if (!rc) { + __u32 blk_size = osfs.os_bsize >> 10; + __u64 result = osfs.os_bavail; + + while (blk_size >>= 1) + result <<= 1; + + *eof = 1; + rc = snprintf(page, count, LPU64"\n", result); + } + return rc; } -int lprocfs_dereg_mnt(struct proc_dir_entry* root) +int lprocfs_rd_filestotal(char *page, char **start, off_t off, int count, + int *eof, void *data) { - lprocfs_remove_all(root); - return 0; - + struct obd_statfs osfs; + int rc = obd_statfs(data, &osfs, jiffies - HZ); + if (!rc) { + *eof = 1; + rc = snprintf(page, count, LPU64"\n", osfs.os_files); + } + + return rc; } -int lprocfs_reg_class(struct obd_type* type, - struct lprocfs_vars* list, - void* data) +int lprocfs_rd_filesfree(char *page, char **start, off_t off, int count, + int *eof, void *data) { - struct proc_dir_entry* root; - int retval; + struct obd_statfs osfs; + int rc = obd_statfs(data, &osfs, jiffies - HZ); + if (!rc) { + *eof = 1; + rc = snprintf(page, count, LPU64"\n", osfs.os_ffree); + } + return rc; +} - root=lprocfs_mkdir(type->typ_name, proc_lustre_dev_root); - - type->typ_procroot=root; +int lprocfs_rd_server_uuid(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct obd_device *obd = (struct obd_device *)data; + struct obd_import *imp; + char *imp_state_name = NULL; + + LASSERT(obd != NULL); + imp = obd->u.cli.cl_import; + imp_state_name = ptlrpc_import_state_name(imp->imp_state); + *eof = 1; + return snprintf(page, count, "%s\t%s\n", + imp->imp_target_uuid.uuid, imp_state_name); +} + +int lprocfs_rd_conn_uuid(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct obd_device *obd = (struct obd_device*)data; + struct ptlrpc_connection *conn; + + LASSERT(obd != NULL); + conn = obd->u.cli.cl_import->imp_connection; + LASSERT(conn != NULL); + *eof = 1; + return snprintf(page, count, "%s\n", conn->c_remote_uuid.uuid); +} - retval=lprocfs_add_vars(root, list, data); +int lprocfs_rd_num_exports(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct obd_device *obd = (struct obd_device*)data; + + LASSERT(obd != NULL); + *eof = 1; + return snprintf(page, count, "%u\n", obd->obd_num_exports); +} + +int lprocfs_rd_numrefs(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct obd_type *class = (struct obd_type*) data; + + LASSERT(class != NULL); + *eof = 1; + return snprintf(page, count, "%d\n", class->typ_refcnt); +} + +int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list) +{ + int rc = 0; + + LASSERT(obd != NULL); + LASSERT(obd->obd_type != NULL); + LASSERT(obd->obd_type->typ_procroot != NULL); + + obd->obd_proc_entry = lprocfs_register(obd->obd_name, + obd->obd_type->typ_procroot, + list, obd); + if (IS_ERR(obd->obd_proc_entry)) { + rc = PTR_ERR(obd->obd_proc_entry); + CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name); + obd->obd_proc_entry = NULL; + } + return rc; +} - return retval; +int lprocfs_obd_cleanup(struct obd_device *obd) +{ + if (obd && obd->obd_proc_entry) { + lprocfs_remove(obd->obd_proc_entry); + obd->obd_proc_entry = NULL; + } + return 0; } -int lprocfs_dereg_class(struct obd_type* class) +struct lprocfs_stats *lprocfs_alloc_stats(unsigned int num) { - if(!class){ - CDEBUG(D_OTHER, "Non-existent class", - class->typ_name); - return 0; + struct lprocfs_stats *stats; + struct lprocfs_percpu *percpu; + unsigned int percpusize; + unsigned int i; + + if (num == 0) + return NULL; + + OBD_ALLOC(stats, offsetof(typeof(*stats), ls_percpu[num_online_cpus()])); + if (stats == NULL) + return NULL; + + percpusize = L1_CACHE_ALIGN(offsetof(typeof(*percpu), lp_cntr[num])); + stats->ls_percpu_size = num_online_cpus() * percpusize; + OBD_ALLOC(stats->ls_percpu[0], stats->ls_percpu_size); + if (stats->ls_percpu[0] == NULL) { + OBD_FREE(stats, offsetof(typeof(*stats), + ls_percpu[num_online_cpus()])); + return NULL; } - - lprocfs_remove_all(class->typ_procroot); - - CDEBUG(D_OTHER, "LPROCFS removed = %s\n", class->typ_name); + stats->ls_num = num; + for (i = 1; i < num_online_cpus(); i++) + stats->ls_percpu[i] = (void *)(stats->ls_percpu[i - 1]) + + percpusize; + + return stats; +} + +void lprocfs_free_stats(struct lprocfs_stats *stats) +{ + if (stats->ls_num == 0) + return; + + OBD_FREE(stats->ls_percpu[0], stats->ls_percpu_size); + OBD_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_online_cpus()])); +} + +/* Reset counter under lock */ +int lprocfs_counter_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + /* not supported */ return 0; +} +static void *lprocfs_stats_seq_start(struct seq_file *p, loff_t *pos) +{ + struct lprocfs_stats *stats = p->private; + /* return 1st cpu location */ + return (*pos >= stats->ls_num) ? NULL : + &(stats->ls_percpu[0]->lp_cntr[*pos]); } -int lprocfs_reg_main() + +static void lprocfs_stats_seq_stop(struct seq_file *p, void *v) { - proc_lustre_root = lprocfs_mkdir("lustre", &proc_root); - if (!proc_lustre_root) { - CERROR(" !! Cannot create /proc/lustre !! \n"); - return -EINVAL; +} + +static void *lprocfs_stats_seq_next(struct seq_file *p, void *v, loff_t *pos) +{ + struct lprocfs_stats *stats = p->private; + ++*pos; + return (*pos >= stats->ls_num) ? NULL : + &(stats->ls_percpu[0]->lp_cntr[*pos]); +} + +/* seq file export of one lprocfs counter */ +static int lprocfs_stats_seq_show(struct seq_file *p, void *v) +{ + struct lprocfs_stats *stats = p->private; + struct lprocfs_counter *cntr = v; + struct lprocfs_counter t, ret = { .lc_min = ~(__u64)0 }; + int i, idx, rc; + + if (cntr == &(stats->ls_percpu[0])->lp_cntr[0]) { + struct timeval now; + do_gettimeofday(&now); + rc = seq_printf(p, "%-25s %lu.%lu secs.usecs\n", + "snapshot_time", now.tv_sec, now.tv_usec); + if (rc < 0) + return rc; + } + idx = cntr - &(stats->ls_percpu[0])->lp_cntr[0]; + + for (i = 0; i < num_online_cpus(); i++) { + struct lprocfs_counter *percpu_cntr = + &(stats->ls_percpu[i])->lp_cntr[idx]; + int centry; + + do { + centry = 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)); + ret.lc_count += t.lc_count; + ret.lc_sum += t.lc_sum; + if (t.lc_min < ret.lc_min) + ret.lc_min = t.lc_min; + if (t.lc_max > ret.lc_max) + ret.lc_max = t.lc_max; + ret.lc_sumsquare += t.lc_sumsquare; + } + + rc = seq_printf(p, "%-25s "LPU64" samples [%s]", cntr->lc_name, + ret.lc_count, cntr->lc_units); + if (rc < 0) + goto out; + + if ((cntr->lc_config & LPROCFS_CNTR_AVGMINMAX) && (ret.lc_count > 0)) { + rc = seq_printf(p, " "LPU64" "LPU64" "LPU64, + ret.lc_min, ret.lc_max, ret.lc_sum); + if (rc < 0) + goto out; + if (cntr->lc_config & LPROCFS_CNTR_STDDEV) + rc = seq_printf(p, " "LPU64, ret.lc_sumsquare); + if (rc < 0) + goto out; + } + rc = seq_printf(p, "\n"); + out: + return (rc < 0) ? rc : 0; +} + +struct seq_operations lprocfs_stats_seq_sops = { + start: lprocfs_stats_seq_start, + stop: lprocfs_stats_seq_stop, + next: lprocfs_stats_seq_next, + show: lprocfs_stats_seq_show, +}; + +static int lprocfs_stats_seq_open(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(inode); + struct seq_file *seq; + int rc; + + rc = seq_open(file, &lprocfs_stats_seq_sops); + if (rc) + return rc; + seq = file->private_data; + seq->private = dp->data; + return 0; +} + +struct file_operations lprocfs_stats_seq_fops = { + .owner = THIS_MODULE, + .open = lprocfs_stats_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +int lprocfs_register_stats(struct proc_dir_entry *root, const char *name, + struct lprocfs_stats *stats) +{ + struct proc_dir_entry *entry; + LASSERT(root != NULL); + + entry = create_proc_entry(name, 0444, root); + if (entry == NULL) + return -ENOMEM; + entry->proc_fops = &lprocfs_stats_seq_fops; + entry->data = (void *)stats; + entry->write_proc = lprocfs_counter_write; + return 0; +} + +void lprocfs_counter_init(struct lprocfs_stats *stats, int index, + unsigned conf, const char *name, const char *units) +{ + struct lprocfs_counter *c; + int i; + + LASSERT(stats != NULL); + for (i = 0; i < num_online_cpus(); i++) { + c = &(stats->ls_percpu[i]->lp_cntr[index]); + c->lc_config = conf; + c->lc_min = ~(__u64)0; + c->lc_name = name; + c->lc_units = units; } - - proc_lustre_dev_root =lprocfs_mkdir("devices", proc_lustre_root); +} +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) + +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 = 1 + OBD_COUNTER_OFFSET(notify) + + num_private_stats; + stats = lprocfs_alloc_stats(num_stats); + if (stats == NULL) + return -ENOMEM; + + 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); + 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, postrecov); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, connect); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, disconnect); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, statfs); + 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, preallocate); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, create); + 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, getattr); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, getattr_async); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, brw_async); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, prep_async_page); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_async_io); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, set_async_flags); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, queue_group_io); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, trigger_group_io); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, teardown_async_page); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, punch); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, sync); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, migrate); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, copy); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, iterate); + 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, enqueue); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, match); + LPROCFS_OBD_OP_INIT(num_private_stats, stats, change_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, san_preprw); + 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_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); - if (!proc_lustre_dev_root) { - CERROR(" !! Cannot create /proc/lustre/devices !! \n"); - return -EINVAL; + 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. */ + if (stats->ls_percpu[0]->lp_cntr[i].lc_name == NULL) { + CERROR("Missing obd_stat initializer obd_op " + "operation at offset %d. Aborting.\n", + i - num_private_stats); + LBUG(); + } } - proc_lustre_fs_root=lprocfs_mkdir("mnt_pnt", proc_lustre_root); - - if (!proc_lustre_fs_root) { - CERROR(" !! Cannot create /proc/lustre/mnt_pnt !! \n"); - return -EINVAL; + 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 0; + return rc; +} + +void lprocfs_free_obd_stats(struct obd_device *obd) +{ + struct lprocfs_stats *stats = obd->obd_stats; + + if (stats != NULL) { + obd->obd_stats = NULL; + lprocfs_free_stats(stats); + } +} +int lprocfs_write_helper(const char *buffer, unsigned long count, + int *val) +{ + char kernbuf[20], *end; + + if (count > (sizeof(kernbuf) - 1)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + + kernbuf[count] = '\0'; + + *val = simple_strtol(kernbuf, &end, 0); + if (kernbuf == end) + return -EINVAL; + + return 0; } -int lprocfs_dereg_main() +int lprocfs_write_u64_helper(const char *buffer, unsigned long count, + __u64 *val) { - lprocfs_remove_all(proc_lustre_root); - proc_lustre_root=0; - proc_lustre_dev_root=0; - proc_lustre_fs_root=0; + char kernbuf[22], *end; + + if (count > (sizeof(kernbuf) - 1)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + + kernbuf[count] = '\0'; + + *val = simple_strtoull(kernbuf, &end, 0); + if (kernbuf == end) + return -EINVAL; + return 0; +} + +int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode, + struct file_operations *seq_fops, void *data) +{ + struct proc_dir_entry *entry; + ENTRY; + + entry = create_proc_entry(name, mode, dev->obd_proc_entry); + if (entry == NULL) + RETURN(-ENOMEM); + entry->proc_fops = seq_fops; + entry->data = data; + RETURN(0); } +EXPORT_SYMBOL(lprocfs_obd_seq_create); +void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value) +{ + unsigned long flags; -/* - * Needs to go... - */ + if (value >= OBD_HIST_MAX) + value = OBD_HIST_MAX - 1; -int lprocfs_ll_rd(char *page, char **start, off_t off, - int count, int *eof, void *data) + spin_lock_irqsave(&oh->oh_lock, flags); + oh->oh_buckets[value]++; + spin_unlock_irqrestore(&oh->oh_lock, flags); +} +EXPORT_SYMBOL(lprocfs_oh_tally); + +void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value) { - __u64 *temp = (__u64 *)data; - int len; + unsigned int val; - len = snprintf(page, count, LPU64"\n", *temp); + for (val = 0; ((1 << val) < value) && (val <= OBD_HIST_MAX); val++) + ; - return len; + lprocfs_oh_tally(oh, val); } +EXPORT_SYMBOL(lprocfs_oh_tally_log2); -#endif /* LPROC_SNMP */ +unsigned long lprocfs_oh_sum(struct obd_histogram *oh) +{ + unsigned long ret = 0; + int i; + for (i = 0; i < OBD_HIST_MAX; i++) + ret += oh->oh_buckets[i]; + return ret; +} +EXPORT_SYMBOL(lprocfs_oh_sum); -EXPORT_SYMBOL(lprocfs_reg_obd); -EXPORT_SYMBOL(lprocfs_dereg_obd); -EXPORT_SYMBOL(lprocfs_reg_main); -EXPORT_SYMBOL(lprocfs_dereg_main); -EXPORT_SYMBOL(lprocfs_reg_mnt); -EXPORT_SYMBOL(lprocfs_dereg_mnt); -EXPORT_SYMBOL(lprocfs_add_vars); -EXPORT_SYMBOL(lprocfs_reg_class); -EXPORT_SYMBOL(lprocfs_dereg_class); -EXPORT_SYMBOL(lprocfs_ll_rd); +void lprocfs_oh_clear(struct obd_histogram *oh) +{ + unsigned long flags; + spin_lock_irqsave(&oh->oh_lock, flags); + memset(oh->oh_buckets, 0, sizeof(oh->oh_buckets)); + spin_unlock_irqrestore(&oh->oh_lock, flags); +} +EXPORT_SYMBOL(lprocfs_oh_clear); +#endif /* LPROCFS*/ +EXPORT_SYMBOL(lprocfs_register); +EXPORT_SYMBOL(lprocfs_srch); +EXPORT_SYMBOL(lprocfs_remove); +EXPORT_SYMBOL(lprocfs_add_vars); +EXPORT_SYMBOL(lprocfs_obd_setup); +EXPORT_SYMBOL(lprocfs_obd_cleanup); +EXPORT_SYMBOL(lprocfs_alloc_stats); +EXPORT_SYMBOL(lprocfs_free_stats); +EXPORT_SYMBOL(lprocfs_register_stats); +EXPORT_SYMBOL(lprocfs_alloc_obd_stats); +EXPORT_SYMBOL(lprocfs_free_obd_stats); + +EXPORT_SYMBOL(lprocfs_rd_u64); +EXPORT_SYMBOL(lprocfs_rd_uuid); +EXPORT_SYMBOL(lprocfs_rd_name); +EXPORT_SYMBOL(lprocfs_rd_fstype); +EXPORT_SYMBOL(lprocfs_rd_server_uuid); +EXPORT_SYMBOL(lprocfs_rd_conn_uuid); +EXPORT_SYMBOL(lprocfs_rd_num_exports); +EXPORT_SYMBOL(lprocfs_rd_numrefs); + +EXPORT_SYMBOL(lprocfs_rd_blksize); +EXPORT_SYMBOL(lprocfs_rd_kbytestotal); +EXPORT_SYMBOL(lprocfs_rd_kbytesfree); +EXPORT_SYMBOL(lprocfs_rd_kbytesavail); +EXPORT_SYMBOL(lprocfs_rd_filestotal); +EXPORT_SYMBOL(lprocfs_rd_filesfree); + +EXPORT_SYMBOL(lprocfs_write_helper); +EXPORT_SYMBOL(lprocfs_write_u64_helper);