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 + -
显示快捷键?