X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fptlrpc%2Fnodemap_lproc.c;h=29ba26bb46273da141e0b9d32098ef9075fa50ac;hb=9321c8a3de6fe26b30a6eeac423e0407a8b1c564;hp=0f4cfe4dc0fd31c39e06c63fe714a4dbb22d4c26;hpb=0ad4f8a4227ed7dd93fec99d33c6bb25056473fc;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/nodemap_lproc.c b/lustre/ptlrpc/nodemap_lproc.c index 0f4cfe4..29ba26b 100644 --- a/lustre/ptlrpc/nodemap_lproc.c +++ b/lustre/ptlrpc/nodemap_lproc.c @@ -21,6 +21,9 @@ */ /* * Copyright (C) 2013, Trustees of Indiana University + * + * Copyright (c) 2014, 2017, Intel Corporation. + * * Author: Joshua Walgenbach */ @@ -34,11 +37,7 @@ #include #include "nodemap_internal.h" -/* Turn on proc debug interface to allow OSS and - * MDS nodes to configure nodemap independently of - * MGS (since the nodemap distribution is not written - * yet */ -#define NODEMAP_PROC_DEBUG 1 +static LIST_HEAD(nodemap_pde_list); /** * Reads and prints the idmap for the given nodemap. @@ -49,13 +48,24 @@ */ static int nodemap_idmap_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; struct lu_idmap *idmap; struct rb_node *node; bool cont = 0; + int rc; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } seq_printf(m, "[\n"); - read_lock(&nodemap->nm_idmap_lock); + down_read(&nodemap->nm_idmap_lock); for (node = rb_first(&nodemap->nm_client_to_fs_uidmap); node; node = rb_next(node)) { if (cont) @@ -77,10 +87,11 @@ static int nodemap_idmap_show(struct seq_file *m, void *data) "fs_id: %u }", idmap->id_client, idmap->id_fs); } - read_unlock(&nodemap->nm_idmap_lock); + up_read(&nodemap->nm_idmap_lock); seq_printf(m, "\n"); seq_printf(m, "]\n"); + nodemap_putref(nodemap); return 0; } @@ -93,9 +104,7 @@ static int nodemap_idmap_show(struct seq_file *m, void *data) */ static int nodemap_idmap_open(struct inode *inode, struct file *file) { - struct lu_nodemap *nodemap = PDE_DATA(inode); - - return single_open(file, nodemap_idmap_show, nodemap); + return single_open(file, nodemap_idmap_show, PDE_DATA(inode)); } /** @@ -107,27 +116,42 @@ static int nodemap_idmap_open(struct inode *inode, struct file *file) */ static int nodemap_ranges_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; struct lu_nid_range *range; struct interval_node_extent ext; + char start_nidstr[LNET_NIDSTR_SIZE]; + char end_nidstr[LNET_NIDSTR_SIZE]; bool cont = false; + int rc; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + if (IS_ERR(nodemap)) { + mutex_unlock(&active_config_lock); + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } seq_printf(m, "[\n"); - read_lock(&nm_range_tree_lock); + down_read(&active_config->nmc_range_tree_lock); list_for_each_entry(range, &nodemap->nm_ranges, rn_list) { if (cont) seq_printf(m, ",\n"); cont = 1; ext = range->rn_node.in_extent; - seq_printf(m, " { id: %u, start_nid: %s, " - "end_nid: %s }", - range->rn_id, libcfs_nid2str(ext.start), - libcfs_nid2str(ext.end)); + libcfs_nid2str_r(ext.start, start_nidstr, sizeof(start_nidstr)); + libcfs_nid2str_r(ext.end, end_nidstr, sizeof(end_nidstr)); + seq_printf(m, " { id: %u, start_nid: %s, end_nid: %s }", + range->rn_id, start_nidstr, end_nidstr); } - read_unlock(&nm_range_tree_lock); + up_read(&active_config->nmc_range_tree_lock); + mutex_unlock(&active_config_lock); seq_printf(m, "\n"); seq_printf(m, "]\n"); + nodemap_putref(nodemap); return 0; } @@ -140,55 +164,124 @@ static int nodemap_ranges_show(struct seq_file *m, void *data) */ static int nodemap_ranges_open(struct inode *inode, struct file *file) { - struct lu_nodemap *nodemap = PDE_DATA(inode); - - return single_open(file, nodemap_ranges_show, nodemap); + return single_open(file, nodemap_ranges_show, PDE_DATA(inode)); } /** - * Hash callback, reads and prints the exports attached to this nodemap. + * Reads and prints the fileset for the given nodemap. * - * \param hs nodemap member hash - * \param bd unused - * \param hnode current member in hash - * \param data seq_file to print to + * \param m seq file in proc fs + * \param data unused * \retval 0 success */ -static int nodemap_exports_show_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd, - struct hlist_node *hnode, void *data) +static int nodemap_fileset_seq_show(struct seq_file *m, void *data) { - struct seq_file *m = data; - struct obd_export *exp; - char *key; + struct lu_nodemap *nodemap; + int rc = 0; - exp = hlist_entry(hnode, struct obd_export, - exp_target_data.ted_nodemap_member); - key = cfs_hash_key(hs, hnode); - seq_printf(m, " { nid: %s, uuid: %s },", - obd_export_nid2str(exp), exp->exp_client_uuid.uuid); + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } - return 0; + seq_printf(m, "%s\n", nodemap->nm_fileset); + nodemap_putref(nodemap); + return rc; } /** - * Reads and prints the exports attached to the given nodemap via hash - * foreach callback. + * Set a fileset on a nodemap. * - * \param m seq file in proc fs + * \param[in] file proc file + * \param[in] buffer string, "" + * \param[in] count \a buffer length + * \param[in] off unused + * \retval \a count on success + * \retval negative number on error + */ +static ssize_t +nodemap_fileset_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) +{ + struct seq_file *m = file->private_data; + char *nm_fileset; + int rc = 0; + ENTRY; + + if (count == 0) + RETURN(0); + + if (count > PATH_MAX) + RETURN(-EINVAL); + + OBD_ALLOC(nm_fileset, count + 1); + /* OBD_ALLOC zero-fills the buffer */ + if (nm_fileset == NULL) + RETURN(-ENOMEM); + + if (copy_from_user(nm_fileset, buffer, count)) + GOTO(out, rc = -EFAULT); + + rc = nodemap_set_fileset(m->private, nm_fileset); + if (rc != 0) + GOTO(out, rc = -EINVAL); + + rc = count; +out: + OBD_FREE(nm_fileset, count + 1); + + return rc; +} +LPROC_SEQ_FOPS(nodemap_fileset); + +/** + * Reads and prints the exports attached to the given nodemap. + * + * \param m seq file in proc fs, stores nodemap * \param data unused * \retval 0 success */ static int nodemap_exports_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; + struct obd_export *exp; + char nidstr[LNET_NIDSTR_SIZE] = ""; + int rc; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } seq_printf(m, "[\n"); - cfs_hash_for_each(nodemap->nm_member_hash, nodemap_exports_show_cb, m); + mutex_lock(&nodemap->nm_member_list_lock); + list_for_each_entry(exp, &nodemap->nm_member_list, + exp_target_data.ted_nodemap_member) { + if (exp->exp_connection != NULL) + libcfs_nid2str_r(exp->exp_connection->c_peer.nid, + nidstr, sizeof(nidstr)); + + seq_printf(m, " { nid: %s, uuid: %s },", + nidstr, exp->exp_client_uuid.uuid); + } + mutex_unlock(&nodemap->nm_member_list_lock); seq_printf(m, "\n"); seq_printf(m, "]\n"); + nodemap_putref(nodemap); return 0; } @@ -201,9 +294,7 @@ static int nodemap_exports_show(struct seq_file *m, void *data) */ static int nodemap_exports_open(struct inode *inode, struct file *file) { - struct lu_nodemap *nodemap = PDE_DATA(inode); - - return single_open(file, nodemap_exports_show, nodemap); + return single_open(file, nodemap_exports_show, PDE_DATA(inode)); } /** @@ -215,7 +306,8 @@ static int nodemap_exports_open(struct inode *inode, struct file *file) */ static int nodemap_active_seq_show(struct seq_file *m, void *data) { - return seq_printf(m, "%u\n", (unsigned int)nodemap_active); + seq_printf(m, "%u\n", (unsigned int)nodemap_active); + return 0; } /** @@ -250,7 +342,7 @@ nodemap_active_seq_write(struct file *file, const char __user *buffer, if (rc != 0) return -EINVAL; - nodemap_active = active; + nodemap_activate(active); return count; } @@ -265,9 +357,21 @@ LPROC_SEQ_FOPS(nodemap_active); */ static int nodemap_id_seq_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + int rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } - return seq_printf(m, "%u\n", nodemap->nm_id); + seq_printf(m, "%u\n", nodemap->nm_id); + nodemap_putref(nodemap); + return 0; } LPROC_SEQ_FOPS_RO(nodemap_id); @@ -280,9 +384,21 @@ LPROC_SEQ_FOPS_RO(nodemap_id); */ static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + int rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } - return seq_printf(m, "%u\n", nodemap->nm_squash_uid); + seq_printf(m, "%u\n", nodemap->nm_squash_uid); + nodemap_putref(nodemap); + return 0; } /** @@ -294,9 +410,21 @@ static int nodemap_squash_uid_seq_show(struct seq_file *m, void *data) */ static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + int rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } - return seq_printf(m, "%u\n", nodemap->nm_squash_gid); + seq_printf(m, "%u\n", nodemap->nm_squash_gid); + nodemap_putref(nodemap); + return 0; } /** @@ -308,9 +436,22 @@ static int nodemap_squash_gid_seq_show(struct seq_file *m, void *data) */ static int nodemap_trusted_seq_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + int rc = PTR_ERR(nodemap); + + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } - return seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids); + seq_printf(m, "%d\n", (int)nodemap->nmf_trust_client_ids); + nodemap_putref(nodemap); + return 0; } /** @@ -322,9 +463,109 @@ static int nodemap_trusted_seq_show(struct seq_file *m, void *data) */ static int nodemap_admin_seq_show(struct seq_file *m, void *data) { - struct lu_nodemap *nodemap = m->private; + struct lu_nodemap *nodemap; + int rc; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } + + seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access); + nodemap_putref(nodemap); + return 0; +} + +/** + * Reads and prints the mapping mode for the given nodemap. + * + * \param m seq file in proc fs + * \param data unused + * \retval 0 success + */ +static int nodemap_map_mode_seq_show(struct seq_file *m, void *data) +{ + struct lu_nodemap *nodemap; + int rc; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } + + if (nodemap->nmf_map_uid_only) + seq_printf(m, "uid_only\n"); + else if (nodemap->nmf_map_gid_only) + seq_printf(m, "gid_only\n"); + else + seq_printf(m, "both\n"); + + nodemap_putref(nodemap); + return 0; +} + +/** + * Reads and prints the deny_unknown flag for the given nodemap. + * + * \param m seq file in proc fs + * \param data unused + * \retval 0 success + */ +static int nodemap_deny_unknown_seq_show(struct seq_file *m, void *data) +{ + struct lu_nodemap *nodemap; + int rc; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } - return seq_printf(m, "%d\n", (int)nodemap->nmf_allow_root_access); + seq_printf(m, "%d\n", (int)nodemap->nmf_deny_unknown); + nodemap_putref(nodemap); + return 0; +} + +/** + * Reads and prints the audit_mode flag for the given nodemap. + * + * \param m seq file in proc fs + * \param data unused + * \retval 0 success + */ +static int nodemap_audit_mode_seq_show(struct seq_file *m, void *data) +{ + struct lu_nodemap *nodemap; + int rc; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(m->private); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) { + rc = PTR_ERR(nodemap); + CERROR("cannot find nodemap '%s': rc = %d\n", + (char *)m->private, rc); + return rc; + } + + seq_printf(m, "%d\n", (int)nodemap->nmf_enable_audit); + nodemap_putref(nodemap); + return 0; } #ifdef NODEMAP_PROC_DEBUG @@ -379,7 +620,6 @@ nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer, { char squash[NODEMAP_LPROC_ID_LEN + 1]; struct seq_file *m = file->private_data; - struct lu_nodemap *nodemap = m->private; long unsigned int squash_uid; int rc; @@ -397,7 +637,9 @@ nodemap_squash_uid_seq_write(struct file *file, const char __user *buffer, if (rc != 0) return -EINVAL; - nodemap->nm_squash_uid = squash_uid; + rc = nodemap_set_squash_uid(m->private, squash_uid); + if (rc != 0) + return rc; return count; } @@ -418,7 +660,6 @@ nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer, { char squash[NODEMAP_LPROC_ID_LEN + 1]; struct seq_file *m = file->private_data; - struct lu_nodemap *nodemap = m->private; long unsigned int squash_gid; int rc; @@ -436,7 +677,9 @@ nodemap_squash_gid_seq_write(struct file *file, const char __user *buffer, if (rc != 0) return -EINVAL; - nodemap->nm_squash_gid = squash_gid; + rc = nodemap_set_squash_gid(m->private, squash_gid); + if (rc != 0) + return rc; return count; } @@ -456,17 +699,18 @@ nodemap_trusted_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct seq_file *m = file->private_data; - struct lu_nodemap *nodemap = m->private; int flags; int rc; rc = nodemap_proc_read_flag(buffer, count, &flags); - if (rc >= 0) { - nodemap->nmf_trust_client_ids = !!flags; - nm_member_revoke_locks(nodemap); - } + if (rc < 0) + return rc; - return rc; + rc = nodemap_set_trust_client_ids(m->private, flags); + if (rc != 0) + return rc; + + return count; } /** @@ -484,17 +728,18 @@ nodemap_admin_seq_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct seq_file *m = file->private_data; - struct lu_nodemap *nodemap = m->private; int flags; int rc; rc = nodemap_proc_read_flag(buffer, count, &flags); - if (rc >= 0) { - nodemap->nmf_allow_root_access = !!flags; - nm_member_revoke_locks(nodemap); - } + if (rc < 0) + return rc; - return rc; + rc = nodemap_set_allow_root(m->private, flags); + if (rc != 0) + return rc; + + return count; } /** @@ -538,7 +783,7 @@ lprocfs_add_nodemap_seq_write(struct file *file, const char __user *buffer, return rc; } -LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap); +LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap); /** * Delete a nodemap. @@ -582,7 +827,7 @@ lprocfs_del_nodemap_seq_write(struct file *file, const char __user *buffer, return rc; } -LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap); +LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap); /** * Helper function to parse a NID string. @@ -605,11 +850,11 @@ static int parse_nids(char *rangestr, lnet_nid_t nids[2]) &nidlist) <= 0) return -EINVAL; - if (!cfs_nidrange_is_contiguous(&nidlist)) - return -EINVAL; + rc = cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1], + LNET_NIDSTR_SIZE); + if (rc < 0) + return rc; - cfs_nidrange_find_min_max(&nidlist, nidstr[0], nidstr[1], - LNET_NIDSTR_SIZE); snprintf(nidrange_str, sizeof(nidrange_str), "%s:%s", nidstr[0], nidstr[1]); @@ -679,7 +924,7 @@ lprocfs_add_nodemap_range_seq_write(struct file *file, out: return rc; } -LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_range); +LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap_range); /** * Delete a NID range from nodemap. @@ -738,7 +983,7 @@ lprocfs_del_nodemap_range_seq_write(struct file *file, out: return rc; } -LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_range); +LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap_range); /** * Add an idmap to nodemap. @@ -807,7 +1052,7 @@ lprocfs_add_nodemap_idmap_seq_write(struct file *file, out: return rc; } -LPROC_SEQ_FOPS_WO_TYPE(nodemap, add_nodemap_idmap); +LPROC_SEQ_FOPS_WR_ONLY(nodemap, add_nodemap_idmap); /** * Delete an idmap from nodemap. @@ -876,7 +1121,7 @@ lprocfs_del_nodemap_idmap_seq_write(struct file *file, out: return rc; } -LPROC_SEQ_FOPS_WO_TYPE(nodemap, del_nodemap_idmap); +LPROC_SEQ_FOPS_WR_ONLY(nodemap, del_nodemap_idmap); #endif /* NODEMAP_PROC_DEBUG */ static struct lprocfs_vars lprocfs_nm_module_vars[] = { @@ -927,6 +1172,10 @@ LPROC_SEQ_FOPS_RO(nodemap_squash_uid); LPROC_SEQ_FOPS_RO(nodemap_squash_gid); #endif +LPROC_SEQ_FOPS_RO(nodemap_deny_unknown); +LPROC_SEQ_FOPS_RO(nodemap_map_mode); +LPROC_SEQ_FOPS_RO(nodemap_audit_mode); + const struct file_operations nodemap_ranges_fops = { .open = nodemap_ranges_open, .read = seq_read, @@ -962,6 +1211,18 @@ static struct lprocfs_vars lprocfs_nodemap_vars[] = { .fops = &nodemap_admin_fops, }, { + .name = "deny_unknown", + .fops = &nodemap_deny_unknown_fops, + }, + { + .name = "map_mode", + .fops = &nodemap_map_mode_fops, + }, + { + .name = "audit_mode", + .fops = &nodemap_audit_mode_fops, + }, + { .name = "squash_uid", .fops = &nodemap_squash_uid_fops, }, @@ -974,6 +1235,10 @@ static struct lprocfs_vars lprocfs_nodemap_vars[] = { .fops = &nodemap_ranges_fops, }, { + .name = "fileset", + .fops = &nodemap_fileset_fops, + }, + { .name = "exports", .fops = &nodemap_exports_fops, }, @@ -1008,10 +1273,18 @@ static struct lprocfs_vars lprocfs_default_nodemap_vars[] = { .fops = &nodemap_squash_gid_fops, }, { + .name = "fileset", + .fops = &nodemap_fileset_fops, + }, + { .name = "exports", .fops = &nodemap_exports_fops, }, { + .name = "audit_mode", + .fops = &nodemap_audit_mode_fops, + }, + { NULL } }; @@ -1029,46 +1302,89 @@ int nodemap_procfs_init(void) proc_lustre_root, lprocfs_nm_module_vars, NULL); - if (IS_ERR(proc_lustre_nodemap_root)) { rc = PTR_ERR(proc_lustre_nodemap_root); CERROR("cannot create 'nodemap' directory: rc = %d\n", rc); proc_lustre_nodemap_root = NULL; } - return rc; } /** + * Cleanup nodemap proc entry data structures. + */ +void nodemap_procfs_exit(void) +{ + struct nodemap_pde *nm_pde; + struct nodemap_pde *tmp; + + lprocfs_remove(&proc_lustre_nodemap_root); + list_for_each_entry_safe(nm_pde, tmp, &nodemap_pde_list, + npe_list_member) { + list_del(&nm_pde->npe_list_member); + OBD_FREE_PTR(nm_pde); + } +} + +/** + * Remove a nodemap's procfs entry and related data. + */ +void lprocfs_nodemap_remove(struct nodemap_pde *nm_pde) +{ + lprocfs_remove(&nm_pde->npe_proc_entry); + list_del(&nm_pde->npe_list_member); + OBD_FREE_PTR(nm_pde); +} + +/** * Register the proc directory for a nodemap * - * \param name name of nodemap + * \param nodemap nodemap to make the proc dir for * \param is_default: 1 if default nodemap * \retval 0 success */ -int lprocfs_nodemap_register(const char *name, - bool is_default, - struct lu_nodemap *nodemap) +int lprocfs_nodemap_register(struct lu_nodemap *nodemap, bool is_default) { - struct proc_dir_entry *nodemap_proc_entry; - struct lprocfs_vars *vars; - int rc = 0; - - if (is_default) - vars = lprocfs_default_nodemap_vars; + struct nodemap_pde *nm_entry; + int rc = 0; + + OBD_ALLOC_PTR(nm_entry); + if (nm_entry == NULL) + GOTO(out, rc = -ENOMEM); + + nm_entry->npe_proc_entry = proc_mkdir(nodemap->nm_name, + proc_lustre_nodemap_root); + if (IS_ERR(nm_entry->npe_proc_entry)) + GOTO(out, rc = PTR_ERR(nm_entry->npe_proc_entry)); + + snprintf(nm_entry->npe_name, sizeof(nm_entry->npe_name), "%s", + nodemap->nm_name); + + /* Use the nodemap name as stored on the PDE as the private data. This + * is so a nodemap struct can be replaced without updating the proc + * entries. + */ + rc = lprocfs_add_vars(nm_entry->npe_proc_entry, + (is_default ? lprocfs_default_nodemap_vars : + lprocfs_nodemap_vars), + nm_entry->npe_name); + if (rc != 0) + lprocfs_remove(&nm_entry->npe_proc_entry); else - vars = lprocfs_nodemap_vars; - - nodemap_proc_entry = lprocfs_register(name, proc_lustre_nodemap_root, - vars, nodemap); - if (IS_ERR(nodemap_proc_entry)) { - rc = PTR_ERR(nodemap_proc_entry); - CERROR("cannot create 'nodemap/%s': rc = %d\n", name, rc); - nodemap_proc_entry = NULL; + list_add(&nm_entry->npe_list_member, &nodemap_pde_list); + +out: + if (rc != 0) { + CERROR("cannot create 'nodemap/%s': rc = %d\n", + nodemap->nm_name, rc); + if (nm_entry != NULL) { + OBD_FREE_PTR(nm_entry); + nm_entry = NULL; + } } - nodemap->nm_proc_entry = nodemap_proc_entry; + nodemap->nm_pde_data = nm_entry; return rc; }