X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fptlrpc%2Fnodemap_handler.c;h=59b17349259b351e66e55a0829fe4b015070f74f;hp=5f82521d72886647db8c0ab2f4fa757b53fbe3e4;hb=be7efb4ce06996444c08914305a73833a7123eeb;hpb=685b0943eb4fe55720458326a5d6c4949457bf7a diff --git a/lustre/ptlrpc/nodemap_handler.c b/lustre/ptlrpc/nodemap_handler.c index 5f82521..59b1734 100644 --- a/lustre/ptlrpc/nodemap_handler.c +++ b/lustre/ptlrpc/nodemap_handler.c @@ -70,15 +70,16 @@ static void nodemap_destroy(struct lu_nodemap *nodemap) down_read(&active_config->nmc_range_tree_lock); nm_member_reclassify_nodemap(nodemap); up_read(&active_config->nmc_range_tree_lock); - mutex_unlock(&active_config_lock); - - if (!list_empty(&nodemap->nm_member_list)) - CWARN("nodemap_destroy failed to reclassify all members\n"); write_lock(&nodemap->nm_idmap_lock); idmap_delete_tree(nodemap); write_unlock(&nodemap->nm_idmap_lock); + mutex_unlock(&active_config_lock); + + if (!list_empty(&nodemap->nm_member_list)) + CWARN("nodemap_destroy failed to reclassify all members\n"); + nm_member_delete_list(nodemap); OBD_FREE_PTR(nodemap); @@ -252,11 +253,30 @@ struct lu_nodemap *nodemap_lookup(const char *name) * \param nid nid to classify * \retval nodemap nodemap containing the nid * \retval default_nodemap default nodemap + * \retval -EINVAL LO nid given without other local nid */ struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid) { struct lu_nid_range *range; struct lu_nodemap *nodemap; + int rc; + + ENTRY; + + /* don't use 0@lo, use the first non-lo local NID instead */ + if (LNET_NETTYP(LNET_NIDNET(nid)) == LOLND) { + lnet_process_id_t id; + int i = 0; + + do { + rc = LNetGetId(i++, &id); + if (rc < 0) + RETURN(ERR_PTR(-EINVAL)); + } while (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND); + + nid = id.nid; + CDEBUG(D_INFO, "found nid %s\n", libcfs_nid2str(nid)); + } range = range_search(&active_config->nmc_range_tree, nid); if (range != NULL) @@ -264,9 +284,10 @@ struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid) else nodemap = active_config->nmc_default_nodemap; + LASSERT(nodemap != NULL); nodemap_getref(nodemap); - return nodemap; + RETURN(nodemap); } /** @@ -354,26 +375,35 @@ EXPORT_SYMBOL(nodemap_parse_idmap); * \param nid nid to add to the members * \param exp obd_export structure for the connection * that is being added - * \retval -EINVAL export is NULL + * \retval -EINVAL export is NULL, or has invalid NID * \retval -EEXIST export is already member of a nodemap */ int nodemap_add_member(lnet_nid_t nid, struct obd_export *exp) { struct lu_nodemap *nodemap; - int rc; + int rc = 0; + ENTRY; mutex_lock(&active_config_lock); down_read(&active_config->nmc_range_tree_lock); nodemap = nodemap_classify_nid(nid); - rc = nm_member_add(nodemap, exp); + + if (IS_ERR(nodemap)) { + CWARN("%s: error adding to nodemap, no valid NIDs found\n", + exp->exp_obd->obd_name); + rc = -EINVAL; + } else { + rc = nm_member_add(nodemap, exp); + } up_read(&active_config->nmc_range_tree_lock); mutex_unlock(&active_config_lock); - nodemap_putref(nodemap); + if (!IS_ERR(nodemap)) + nodemap_putref(nodemap); - return rc; + RETURN(rc); } EXPORT_SYMBOL(nodemap_add_member); @@ -747,15 +777,21 @@ int nodemap_add_range_helper(struct nodemap_config *config, } list_add(&range->rn_list, &nodemap->nm_ranges); - nm_member_reclassify_nodemap(config->nmc_default_nodemap); + + /* nodemaps have no members if they aren't on the active config */ + if (config == active_config) + nm_member_reclassify_nodemap(config->nmc_default_nodemap); + up_write(&config->nmc_range_tree_lock); /* if range_id is non-zero, we are loading from disk */ if (range_id == 0) rc = nodemap_idx_range_add(range, nid); - nm_member_revoke_locks(config->nmc_default_nodemap); - nm_member_revoke_locks(nodemap); + if (config == active_config) { + nm_member_revoke_locks(config->nmc_default_nodemap); + nm_member_revoke_locks(nodemap); + } out: return rc; @@ -831,6 +867,72 @@ out: EXPORT_SYMBOL(nodemap_del_range); /** + * set fileset on nodemap + * \param name nodemap to set fileset on + * \param fileset string containing fileset + * \retval 0 on success + * + * set a fileset on the named nodemap + */ +static int nodemap_set_fileset_helper(struct nodemap_config *config, + struct lu_nodemap *nodemap, + const char *fileset) +{ + int rc = 0; + + /* we allow fileset = "" which means clear fileset info */ + if (fileset == NULL || (fileset[0] != 0 && fileset[0] != '/')) + rc = -EINVAL; + else if (strlcpy(nodemap->nm_fileset, fileset, + sizeof(nodemap->nm_fileset)) >= + sizeof(nodemap->nm_fileset)) + rc = -ENAMETOOLONG; + + return rc; +} + +int nodemap_set_fileset(const char *name, const char *fileset) +{ + struct lu_nodemap *nodemap = NULL; + int rc = 0; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(name); + if (IS_ERR(nodemap)) { + mutex_unlock(&active_config_lock); + GOTO(out, rc = PTR_ERR(nodemap)); + } + + if (is_default_nodemap(nodemap)) + rc = -EINVAL; + else + rc = nodemap_set_fileset_helper(active_config, nodemap, + fileset); + mutex_unlock(&active_config_lock); + + nodemap_putref(nodemap); +out: + return rc; +} +EXPORT_SYMBOL(nodemap_set_fileset); + +/** + * get fileset defined on nodemap + * \param nodemap nodemap to get fileset from + * \retval fileset name, or NULL if not defined or not activated + * + * get the fileset defined on the nodemap + */ +char *nodemap_get_fileset(const struct lu_nodemap *nodemap) +{ + if (!nodemap_active || is_default_nodemap(nodemap)) + return NULL; + else + return (char *)nodemap->nm_fileset; +} +EXPORT_SYMBOL(nodemap_get_fileset); + +/** * Nodemap constructor * * Creates an lu_nodemap structure and assigns sane default @@ -909,6 +1011,7 @@ struct lu_nodemap *nodemap_create(const char *name, if (is_default || default_nodemap == NULL) { nodemap->nmf_trust_client_ids = 0; nodemap->nmf_allow_root_access = 0; + nodemap->nmf_deny_unknown = 0; nodemap->nm_squash_uid = NODEMAP_NOBODY_UID; nodemap->nm_squash_gid = NODEMAP_NOBODY_GID; @@ -920,9 +1023,12 @@ struct lu_nodemap *nodemap_create(const char *name, default_nodemap->nmf_trust_client_ids; nodemap->nmf_allow_root_access = default_nodemap->nmf_allow_root_access; + nodemap->nmf_deny_unknown = + default_nodemap->nmf_deny_unknown; nodemap->nm_squash_uid = default_nodemap->nm_squash_uid; nodemap->nm_squash_gid = default_nodemap->nm_squash_gid; + nodemap->nm_fileset[0] = 0; } return nodemap; @@ -933,12 +1039,39 @@ out: } /** - * update flag to turn on or off nodemap functions + * Set the nmf_deny_unknown flag to true or false. + * \param name nodemap name + * \param deny_unknown if true, squashed users will get EACCES + * \retval 0 on success + * + */ +int nodemap_set_deny_unknown(const char *name, bool deny_unknown) +{ + struct lu_nodemap *nodemap = NULL; + int rc = 0; + + mutex_lock(&active_config_lock); + nodemap = nodemap_lookup(name); + mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) + GOTO(out, rc = PTR_ERR(nodemap)); + + nodemap->nmf_deny_unknown = deny_unknown; + rc = nodemap_idx_nodemap_update(nodemap); + + nm_member_revoke_locks(nodemap); + nodemap_putref(nodemap); +out: + return rc; +} +EXPORT_SYMBOL(nodemap_set_deny_unknown); + +/** + * Set the nmf_allow_root_access flag to true or false. * \param name nodemap name - * \param admin_string string containing updated value + * \param allow_root if true, nodemap will not squash the root user * \retval 0 on success * - * Update admin flag to turn on or off nodemap functions. */ int nodemap_set_allow_root(const char *name, bool allow_root) { @@ -962,13 +1095,12 @@ out: EXPORT_SYMBOL(nodemap_set_allow_root); /** - * updated trust_client_ids flag for nodemap + * Set the nmf_trust_client_ids flag to true or false. * - * \param name nodemap name - * \param trust_string new value for trust flag + * \param name nodemap name + * \param trust_client_ids if true, nodemap will not map its IDs * \retval 0 on success * - * Update the trust_client_ids flag for a nodemap. */ int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids) { @@ -992,10 +1124,10 @@ out: EXPORT_SYMBOL(nodemap_set_trust_client_ids); /** - * update the squash_uid for a nodemap + * Update the squash_uid for a nodemap. * * \param name nodemap name - * \param uid_string string containing new squash_uid value + * \param uid the new uid to squash unknown users to * \retval 0 on success * * Update the squash_uid for a nodemap. The squash_uid is the uid @@ -1028,7 +1160,7 @@ EXPORT_SYMBOL(nodemap_set_squash_uid); * Update the squash_gid for a nodemap. * * \param name nodemap name - * \param gid_string string containing new squash_gid value + * \param gid the new gid to squash unknown gids to * \retval 0 on success * * Update the squash_gid for a nodemap. The squash_uid is the gid @@ -1249,24 +1381,31 @@ void nodemap_config_dealloc(struct nodemap_config *config) */ list_for_each_entry_safe(nodemap, nodemap_temp, &nodemap_list_head, nm_list) { + mutex_lock(&active_config_lock); down_write(&config->nmc_range_tree_lock); - /* move members to new config */ + /* move members to new config, requires ac lock */ nm_member_reclassify_nodemap(nodemap); list_for_each_entry_safe(range, range_temp, &nodemap->nm_ranges, rn_list) range_delete(&config->nmc_range_tree, range); up_write(&config->nmc_range_tree_lock); + mutex_unlock(&active_config_lock); + /* putref must be outside of ac lock if nm could be destroyed */ nodemap_putref(nodemap); } OBD_FREE_PTR(config); } EXPORT_SYMBOL(nodemap_config_dealloc); -static int nm_hash_list_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd, - struct hlist_node *hnode, - void *nodemap_list_head) +/* + * callback for cfs_hash_for_each_safe used to convert a nodemap hash to a + * nodemap list, generally for locking purposes as a hash cb can't sleep. + */ +int nm_hash_list_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd, + struct hlist_node *hnode, + void *nodemap_list_head) { struct lu_nodemap *nodemap; @@ -1280,11 +1419,13 @@ void nodemap_config_set_active(struct nodemap_config *config) struct nodemap_config *old_config = active_config; struct lu_nodemap *nodemap; struct lu_nodemap *tmp; + bool revoke_locks; LIST_HEAD(nodemap_list_head); ENTRY; LASSERT(active_config != config); + LASSERT(config->nmc_default_nodemap); mutex_lock(&active_config_lock); @@ -1309,6 +1450,14 @@ void nodemap_config_set_active(struct nodemap_config *config) } } + /* + * We only need to revoke locks if old nodemap was active, and new + * config is now nodemap inactive. nodemap_config_dealloc will + * reclassify exports, triggering a lock revoke if and only if new + * nodemap is active. + */ + revoke_locks = !config->nmc_nodemap_is_active && nodemap_active; + /* if new config is inactive, deactivate live config before switching */ if (!config->nmc_nodemap_is_active) nodemap_active = false; @@ -1321,11 +1470,11 @@ void nodemap_config_set_active(struct nodemap_config *config) if (old_config != NULL) nodemap_config_dealloc(old_config); - nm_member_revoke_all(); + if (revoke_locks) + nm_member_revoke_all(); EXIT; } -EXPORT_SYMBOL(nodemap_config_set_active); /** * Cleanup nodemap module on exit @@ -1384,7 +1533,7 @@ void nm_member_revoke_all(void) /* revoke_locks sleeps, so can't call in cfs hash cb */ list_for_each_entry_safe(nodemap, tmp, &nodemap_list_head, nm_list) - nm_member_revoke_locks(nodemap); + nm_member_revoke_locks_always(nodemap); mutex_unlock(&active_config_lock); } @@ -1407,6 +1556,9 @@ void nodemap_test_nid(lnet_nid_t nid, char *name_buf, size_t name_len) up_read(&active_config->nmc_range_tree_lock); mutex_unlock(&active_config_lock); + if (IS_ERR(nodemap)) + return; + strncpy(name_buf, nodemap->nm_name, name_len); if (name_len > 0) name_buf[name_len - 1] = '\0'; @@ -1416,20 +1568,21 @@ void nodemap_test_nid(lnet_nid_t nid, char *name_buf, size_t name_len) EXPORT_SYMBOL(nodemap_test_nid); /** - * Returns the id mapping for a given nid/id pair. Useful for testing the + * Passes back the id mapping for a given nid/id pair. Useful for testing the * nodemap configuration to make sure it is working as expected. * * \param nid nid to classify * \param idtype uid or gid * \param client_id id to map to fs + * \param fs_id_buf pointer to save mapped fs_id to * - * \retval the mapped fs_id of the given client_id + * \retval 0 success + * \retval -EINVAL invalid NID */ -__u32 nodemap_test_id(lnet_nid_t nid, enum nodemap_id_type idtype, - __u32 client_id) +int nodemap_test_id(lnet_nid_t nid, enum nodemap_id_type idtype, + __u32 client_id, __u32 *fs_id) { struct lu_nodemap *nodemap; - __u32 fs_id; mutex_lock(&active_config_lock); down_read(&active_config->nmc_range_tree_lock); @@ -1437,10 +1590,13 @@ __u32 nodemap_test_id(lnet_nid_t nid, enum nodemap_id_type idtype, up_read(&active_config->nmc_range_tree_lock); mutex_unlock(&active_config_lock); - fs_id = nodemap_map_id(nodemap, idtype, NODEMAP_CLIENT_TO_FS, + if (IS_ERR(nodemap)) + return PTR_ERR(nodemap); + + *fs_id = nodemap_map_id(nodemap, idtype, NODEMAP_CLIENT_TO_FS, client_id); nodemap_putref(nodemap); - return fs_id; + return 0; } EXPORT_SYMBOL(nodemap_test_id);