lprocfs_status.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,933 行 · 第 1/5 页
C
1,933 行
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 * <obd.h>, and that the corresponding line item * LPROCFS_OBD_OP_INIT(.., .., opname) * is missing from the list above. */ LASSERTF(stats->ls_percpu[0]->lp_cntr[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;}void lprocfs_free_obd_stats(struct obd_device *obd){ if (obd->obd_stats) lprocfs_free_stats(&obd->obd_stats);}int lprocfs_exp_rd_nid(char *page, char **start, off_t off, int count, int *eof, void *data){ struct obd_export *exp = (struct obd_export*)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;};void lprocfs_exp_print_uuid(void *obj, void *cb_data){ struct obd_export *exp = (struct obd_export *)obj; struct exp_uuid_cb_data *data = (struct exp_uuid_cb_data *)cb_data; if (exp->exp_nid_stats) *data->len += snprintf((data->page + *data->len), data->count, "%s\n", obd_uuid2str(&exp->exp_client_uuid));}int lprocfs_exp_rd_uuid(char *page, char **start, off_t off, int count, int *eof, void *data){ 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'; LASSERT(obd != NULL); cb_data.page = page; cb_data.count = count; cb_data.eof = eof; cb_data.len = &len; lustre_hash_bucket_iterate(obd->obd_nid_hash_body, &stats->nid, lprocfs_exp_print_uuid, &cb_data); return (*cb_data.len);}int lprocfs_nid_stats_clear_read(char *page, char **start, off_t off, int count, int *eof, void *data){ *eof = 1; return snprintf(page, count, "%s\n", "Write into this file to clear all nid stats and " "stale nid entries");}EXPORT_SYMBOL(lprocfs_nid_stats_clear_read);void lprocfs_nid_stats_clear_write_cb(void *obj, void *data){ struct nid_stat *client_stat = obj; int i; if(client_stat->nid_exp_ref_count == 1) { hlist_del_init(&client_stat->nid_hash); lprocfs_free_client_stats(client_stat, data); OBD_FREE(client_stat, sizeof(struct nid_stat)); EXIT; return; } /* we has reference to object - only clear data*/ if (client_stat->nid_stats) { lprocfs_clear_stats(client_stat->nid_stats); } if (client_stat->nid_brw_stats) { for (i = 0; i < BRW_LAST; i++) lprocfs_oh_clear(&client_stat->nid_brw_stats->hist[i]); } EXIT; return;}int lprocfs_nid_stats_clear_write(struct file *file, const char *buffer, unsigned long count, void *data){ struct obd_device *obd = (struct obd_device *)data; lustre_hash_iterate_all(obd->obd_nid_stats_hash_body, lprocfs_free_client_stats, NULL); return count;}EXPORT_SYMBOL(lprocfs_nid_stats_clear_write);int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t nid, int *newnid){ int rc = 0; struct nid_stat *tmp = NULL, *tmp1; struct obd_device *obd = NULL; ENTRY; *newnid = 0; if (!exp || !exp->exp_obd || !exp->exp_obd->obd_proc_exports_entry || !exp->exp_obd->obd_nid_stats_hash_body) RETURN(-EINVAL); if (!nid) RETURN(0); obd = exp->exp_obd; CDEBUG(D_CONFIG, "using hash %p\n", obd->obd_nid_stats_hash_body); OBD_ALLOC(tmp, sizeof(struct nid_stat)); if (tmp == NULL) RETURN(-ENOMEM); tmp->nid = nid; tmp->nid_obd = exp->exp_obd; tmp->nid_exp_ref_count = 1; /* need live in hash after destroy export */ tmp1= lustre_hash_findadd_unique(obd->obd_nid_stats_hash_body, &nid, &tmp->nid_hash); CDEBUG(D_INFO, "Found stats %p for nid %s - ref %d\n", tmp1, libcfs_nid2str(nid), tmp->nid_exp_ref_count); if (tmp1 != tmp) { exp->exp_nid_stats = tmp1; GOTO(destroy_new, rc = 0); } /* not found - create */ tmp->nid_proc = proc_mkdir(libcfs_nid2str(nid), obd->obd_proc_exports_entry); if (!tmp->nid_proc) { CERROR("Error making export directory for" " nid %s\n", libcfs_nid2str(nid)); lustre_hash_delitem(obd->obd_nid_stats_hash_body, &nid, &tmp->nid_hash); GOTO(destroy_new, rc = -ENOMEM); } rc = lprocfs_add_simple(tmp->nid_proc, "uuid", lprocfs_exp_rd_uuid, NULL, tmp); if (rc) CWARN("Error adding the uuid file\n"); /* protect competitive add to list, not need locking on destroy */ spin_lock(&obd->nid_lock); list_add(&tmp->nid_list, &obd->obd_nid_stats); spin_unlock(&obd->nid_lock); exp->exp_nid_stats = tmp; *newnid = 1; RETURN(rc);destroy_new: OBD_FREE(tmp, sizeof(struct nid_stat)); RETURN(rc);}int lprocfs_exp_cleanup(struct obd_export *exp){ struct nid_stat *stat = exp->exp_nid_stats; if(!stat) RETURN(0); stat->nid_exp_ref_count--; CDEBUG(D_INFO, "Put stat %p - %d\n", stat, stat->nid_exp_ref_count); exp->exp_nid_stats = NULL; lprocfs_free_stats(&exp->exp_ldlm_stats); lprocfs_free_stats(&exp->exp_ops_stats); return 0;}int lprocfs_write_helper(const char *buffer, unsigned long count, int *val){ return lprocfs_write_frac_helper(buffer, count, val, 1);}int lprocfs_write_frac_helper(const char *buffer, unsigned long count, int *val, int mult){ char kernbuf[20], *end, *pbuf; if (count > (sizeof(kernbuf) - 1)) return -EINVAL; if (copy_from_user(kernbuf, buffer, count)) return -EFAULT; kernbuf[count] = '\0'; pbuf = kernbuf; if (*pbuf == '-') { mult = -mult; pbuf++; } *val = (int)simple_strtoul(pbuf, &end, 10) * mult; if (pbuf == end) return -EINVAL; if (end != NULL && *end == '.') { int temp_val, pow = 1; int i; pbuf = end + 1; if (strlen(pbuf) > 5) pbuf[5] = '\0'; /*only allow 5bits fractional*/ temp_val = (int)simple_strtoul(pbuf, &end, 10) * mult; if (pbuf < end) { for (i = 0; i < (end - pbuf); i++) pow *= 10; *val += temp_val / pow; } } return 0;}int lprocfs_read_frac_helper(char *buffer, unsigned long count, long val, int mult){ long decimal_val, frac_val; int prtn; if (count < 10) return -EINVAL; decimal_val = val / mult; prtn = snprintf(buffer, count, "%ld", decimal_val); frac_val = val % mult; if (prtn < (count - 4) && frac_val > 0) { long temp_frac; int i, temp_mult = 1, frac_bits = 0; temp_frac = frac_val * 10; buffer[prtn++] = '.'; while (frac_bits < 2 && (temp_frac / mult) < 1 ) { /*only reserved 2bits fraction*/ buffer[prtn++] ='0'; temp_frac *= 10; frac_bits++; } /* Need to think these cases : 1. #echo x.00 > /proc/xxx output result : x 2. #echo x.0x > /proc/xxx output result : x.0x 3. #echo x.x0 > /proc/xxx output result : x.x 4. #echo x.xx > /proc/xxx output result : x.xx Only reserved 2bits fraction. */ for (i = 0; i < (5 - prtn); i++) temp_mult *= 10; frac_bits = min((int)count - prtn, 3 - frac_bits); prtn += snprintf(buffer + prtn, frac_bits, "%ld", frac_val * temp_mult / mult); prtn--; while(buffer[prtn] < '1' || buffer[prtn] > '9') { prtn--; if (buffer[prtn] == '.') { prtn--; break; } } prtn++; } buffer[prtn++] ='\n'; return prtn;}int lprocfs_write_u64_helper(const char *buffer, unsigned long count,__u64 *val){ return lprocfs_write_frac_u64_helper(buffer, count, val, 1);}int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, __u64 *val, int mult){ char kernbuf[22], *end, *pbuf; __u64 whole, frac = 0, units; unsigned frac_d = 1; if (count > (sizeof(kernbuf) - 1) ) return -EINVAL; if (copy_from_user(kernbuf, buffer, count)) return -EFAULT; kernbuf[count] = '\0'; pbuf = kernbuf; if (*pbuf == '-') { mult = -mult; pbuf++; } whole = simple_strtoull(pbuf, &end, 10); if (pbuf == end) return -EINVAL; if (end != NULL && *end == '.') { int i; pbuf = end + 1; /* need to limit frac_d to a __u32 */ if (strlen(pbuf) > 10) pbuf[10] = '\0'; frac = simple_strtoull(pbuf, &end, 10); /* count decimal places */ for (i = 0; i < (end - pbuf); i++) frac_d *= 10; } units = 1; switch(*end) { case 'p': case 'P': units <<= 10; case 't': case 'T': units <<= 10; case 'g': case 'G': units <<= 10; case 'm': case 'M': units <<= 10; case 'k': case 'K': units <<= 10; } /* Specified units override the multiplier */ if (units) mult = mult < 0 ? -units : units; frac *= mult; do_div(frac, frac_d); *val = whole * mult + frac; return 0;}int lprocfs_seq_create(cfs_proc_dir_entry_t *parent, char *name, mode_t mode, struct file_operations *seq_fops, void *data){ struct proc_dir_entry *entry; ENTRY; entry = create_proc_entry(name, mode, parent); if (entry == NULL) RETURN(-ENOMEM); entry->proc_fops = seq_fops; entry->data = data; RETURN(0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?