/*
* Copyright (C) 2013, Trustees of Indiana University
*
- * Copyright (c) 2014, Intel Corporation.
+ * Copyright (c) 2017, Intel Corporation.
*
* Author: Joshua Walgenbach <jjw@iu.edu>
*/
#include <uapi/linux/lnet/nidstr.h>
#include <lustre_net.h>
#include <lustre_acl.h>
-#include <lustre_eacl.h>
#include <obd_class.h>
+
#include "nodemap_internal.h"
+#include "ptlrpc_internal.h"
#define HASH_NODEMAP_BKT_BITS 3
#define HASH_NODEMAP_CUR_BITS 3
nm_member_reclassify_nodemap(nodemap);
up_read(&active_config->nmc_range_tree_lock);
- write_lock(&nodemap->nm_idmap_lock);
+ down_write(&nodemap->nm_idmap_lock);
idmap_delete_tree(nodemap);
- write_unlock(&nodemap->nm_idmap_lock);
+ up_write(&nodemap->nm_idmap_lock);
mutex_unlock(&active_config_lock);
}
EXPORT_SYMBOL(nodemap_putref);
-static __u32 nodemap_hashfn(struct cfs_hash *hash_body,
- const void *key, unsigned mask)
+static unsigned int
+nodemap_hashfn(struct cfs_hash *hash_body,
+ const void *key, const unsigned int bits)
{
- return cfs_hash_djb2_hash(key, strlen(key), mask);
+ return cfs_hash_djb2_hash(key, strlen(key), bits);
}
static void *nodemap_hs_key(struct hlist_node *hnode)
* \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_nodemap *nodemap_classify_nid(struct lnet_nid *nid)
{
- struct lu_nid_range *range;
- struct lu_nodemap *nodemap;
+ 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) {
- struct lnet_process_id id;
+ if (nid_is_lo0(nid)) {
+ struct lnet_processid id;
int i = 0;
do {
- rc = LNetGetId(i++, &id);
+ rc = LNetGetId(i++, &id, true);
if (rc < 0)
RETURN(ERR_PTR(-EINVAL));
- } while (LNET_NETTYP(LNET_NIDNET(id.nid)) == LOLND);
+ } while (nid_is_lo0(&id.nid));
- nid = id.nid;
- CDEBUG(D_INFO, "found nid %s\n", libcfs_nid2str(nid));
+ nid = &id.nid;
+ CDEBUG(D_INFO, "found nid %s\n", libcfs_nidstr(nid));
}
- range = range_search(&active_config->nmc_range_tree, nid);
+ range = range_search(active_config, nid);
if (range != NULL)
nodemap = range->rn_nodemap;
else
* \param range[2] array of two nids
* \reyval 0 on success
*/
-int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
+int nodemap_parse_range(const char *range_str, struct lnet_nid range[2],
+ u8 *netmask)
{
char buf[LNET_NIDSTR_SIZE * 2 + 2];
char *ptr = NULL;
snprintf(buf, sizeof(buf), "%s", range_str);
ptr = buf;
- start_nidstr = strsep(&ptr, ":");
- end_nidstr = strsep(&ptr, ":");
+
+ /* For large NID we use netmasks. Currently we only
+ * support /128 which is a single NID.
+ */
+ if (strchr(ptr, '/')) {
+ start_nidstr = strsep(&ptr, "/");
+
+ rc = kstrtou8(ptr, 10, netmask);
+ if (rc < 0)
+ GOTO(out, rc);
+ if (*netmask != 128)
+ GOTO(out, rc = -ERANGE);
+ end_nidstr = start_nidstr;
+ } else {
+ start_nidstr = strsep(&ptr, ":");
+ end_nidstr = strsep(&ptr, ":");
+ }
if (start_nidstr == NULL || end_nidstr == NULL)
GOTO(out, rc = -EINVAL);
- range[0] = libcfs_str2nid(start_nidstr);
- range[1] = libcfs_str2nid(end_nidstr);
+ rc = libcfs_strnid(&range[0], start_nidstr);
+ if (rc < 0)
+ GOTO(out, rc);
+ rc = libcfs_strnid(&range[1], end_nidstr);
out:
return rc;
* \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)
+int nodemap_add_member(struct lnet_nid *nid, struct obd_export *exp)
{
struct lu_nodemap *nodemap;
int rc = 0;
- ENTRY;
+ ENTRY;
mutex_lock(&active_config_lock);
down_read(&active_config->nmc_range_tree_lock);
nodemap = nodemap_classify_nid(nid);
-
if (IS_ERR(nodemap)) {
CWARN("%s: error adding to nodemap, no valid NIDs found\n",
- exp->exp_obd->obd_name);
+ exp->exp_obd->obd_name);
rc = -EINVAL;
} else {
rc = nm_member_add(nodemap, exp);
/**
* add an idmap to the proper nodemap trees
*
- * \param name name of nodemap
+ * \param nodemap nodemap to add idmap to
* \param id_type NODEMAP_UID or NODEMAP_GID
* \param map array[2] __u32 containing the map values
* map[0] is client id
* map[1] is the filesystem id
*
- * \retval 0 on success
+ * \retval 0 on success
+ * \retval < 0 if error occurs
*/
int nodemap_add_idmap_helper(struct lu_nodemap *nodemap,
enum nodemap_id_type id_type,
const __u32 map[2])
{
struct lu_idmap *idmap;
+ struct lu_idmap *temp;
int rc = 0;
idmap = idmap_create(map[0], map[1]);
if (idmap == NULL)
GOTO(out, rc = -ENOMEM);
- write_lock(&nodemap->nm_idmap_lock);
- idmap_insert(id_type, idmap, nodemap);
- write_unlock(&nodemap->nm_idmap_lock);
+ down_write(&nodemap->nm_idmap_lock);
+ temp = idmap_insert(id_type, idmap, nodemap);
+ /* If the new id_client or id_fs is matched, the old idmap and its
+ * index should be deleted according to its id_client before the new
+ * idmap is added again.
+ */
+ if (IS_ERR(temp))
+ GOTO(out_insert, rc = PTR_ERR(temp));
+ if (temp) {
+ __u32 del_map[2];
+
+ del_map[0] = temp->id_client;
+ idmap_delete(id_type, temp, nodemap);
+ rc = nodemap_idx_idmap_del(nodemap, id_type, del_map);
+ /* In case there is any corrupted idmap */
+ if (!rc || unlikely(rc == -ENOENT)) {
+ temp = idmap_insert(id_type, idmap, nodemap);
+ if (IS_ERR(temp))
+ rc = PTR_ERR(temp);
+ else if (!temp)
+ rc = 0;
+ else
+ rc = -EPERM;
+ }
+ }
+out_insert:
+ if (rc)
+ OBD_FREE_PTR(idmap);
+ up_write(&nodemap->nm_idmap_lock);
nm_member_revoke_locks(nodemap);
out:
struct lu_nodemap *nodemap = NULL;
int rc;
+ ENTRY;
+
mutex_lock(&active_config_lock);
nodemap = nodemap_lookup(name);
if (IS_ERR(nodemap)) {
nodemap_putref(nodemap);
out:
- return rc;
+ RETURN(rc);
}
EXPORT_SYMBOL(nodemap_add_idmap);
struct lu_idmap *idmap = NULL;
int rc = 0;
+ ENTRY;
+
mutex_lock(&active_config_lock);
nodemap = nodemap_lookup(name);
if (IS_ERR(nodemap)) {
if (is_default_nodemap(nodemap))
GOTO(out_putref, rc = -EINVAL);
- write_lock(&nodemap->nm_idmap_lock);
+ down_write(&nodemap->nm_idmap_lock);
idmap = idmap_search(nodemap, NODEMAP_CLIENT_TO_FS, id_type,
map[0]);
if (idmap == NULL) {
idmap_delete(id_type, idmap, nodemap);
rc = nodemap_idx_idmap_del(nodemap, id_type, map);
}
- write_unlock(&nodemap->nm_idmap_lock);
+ up_write(&nodemap->nm_idmap_lock);
out_putref:
mutex_unlock(&active_config_lock);
nodemap_putref(nodemap);
out:
- return rc;
+ RETURN(rc);
}
EXPORT_SYMBOL(nodemap_del_idmap);
* mapping function for nodemap idmaps
*
* \param nodemap lu_nodemap structure defining nodemap
- * \param node_type NODEMAP_UID or NODEMAP_GID
+ * \param node_type NODEMAP_UID or NODEMAP_GID or NODEMAP_PROJID
* \param tree_type NODEMAP_CLIENT_TO_FS or
* NODEMAP_FS_TO_CLIENT
* \param id id to map
* if the nodemap_active is false, just return the passed id without mapping
*
* if the id to be looked up is 0, check that root access is allowed and if it
- * is, return 0. Otherwise, return the squash uid or gid.
+ * is, return 0. Otherwise, return the mapped uid or gid if any.
+ * Otherwise, return the squash uid or gid.
*
* if the nodemap is configured to trusted the ids from the client system, just
- * return the passwd id without mapping.
+ * return the passed id without mapping.
*
* if by this point, we haven't returned and the nodemap in question is the
* default nodemap, return the squash uid or gid.
if (unlikely(nodemap == NULL))
goto out;
- if (nodemap->nmf_map_uid_only && id_type == NODEMAP_GID)
- goto out;
-
- if (nodemap->nmf_map_gid_only && id_type == NODEMAP_UID)
- goto out;
-
if (id == 0) {
if (nodemap->nmf_allow_root_access)
goto out;
- else
- goto squash;
+ goto map;
}
+ if (id_type == NODEMAP_UID &&
+ !(nodemap->nmf_map_mode & NODEMAP_MAP_UID))
+ goto out;
+
+ if (id_type == NODEMAP_GID &&
+ !(nodemap->nmf_map_mode & NODEMAP_MAP_GID))
+ goto out;
+
+ if (id_type == NODEMAP_PROJID &&
+ !(nodemap->nmf_map_mode & NODEMAP_MAP_PROJID))
+ goto out;
+
if (nodemap->nmf_trust_client_ids)
goto out;
+map:
if (is_default_nodemap(nodemap))
goto squash;
- read_lock(&nodemap->nm_idmap_lock);
+ down_read(&nodemap->nm_idmap_lock);
idmap = idmap_search(nodemap, tree_type, id_type, id);
if (idmap == NULL) {
- read_unlock(&nodemap->nm_idmap_lock);
+ up_read(&nodemap->nm_idmap_lock);
goto squash;
}
found_id = idmap->id_client;
else
found_id = idmap->id_fs;
- read_unlock(&nodemap->nm_idmap_lock);
+ up_read(&nodemap->nm_idmap_lock);
RETURN(found_id);
squash:
if (id_type == NODEMAP_UID)
RETURN(nodemap->nm_squash_uid);
- else
+ if (id_type == NODEMAP_GID)
RETURN(nodemap->nm_squash_gid);
+ if (id_type == NODEMAP_PROJID)
+ RETURN(nodemap->nm_squash_projid);
out:
RETURN(id);
}
if (count < 0)
RETURN(-EINVAL);
if (count == 0)
- RETURN(0);
+ /* if not proper ACL, do nothing and return initial size */
+ RETURN(size);
for (end = entry + count; entry != end; entry++) {
__u16 tag = le16_to_cpu(entry->e_tag);
*/
int nodemap_add_range_helper(struct nodemap_config *config,
struct lu_nodemap *nodemap,
- const lnet_nid_t nid[2],
- unsigned int range_id)
+ const struct lnet_nid nid[2],
+ u8 netmask, unsigned int range_id)
{
- struct lu_nid_range *range;
+ struct lu_nid_range *range;
int rc;
down_write(&config->nmc_range_tree_lock);
- range = range_create(&config->nmc_range_tree, nid[0], nid[1],
- nodemap, range_id);
+ range = range_create(config, &nid[0], &nid[1], netmask, nodemap,
+ range_id);
if (range == NULL) {
up_write(&config->nmc_range_tree_lock);
GOTO(out, rc = -ENOMEM);
}
- rc = range_insert(&config->nmc_range_tree, range);
- if (rc != 0) {
- CERROR("cannot insert nodemap range into '%s': rc = %d\n",
- nodemap->nm_name, rc);
+ rc = range_insert(config, range);
+ if (rc) {
+ CDEBUG_LIMIT(rc == -EEXIST ? D_INFO : D_ERROR,
+ "cannot insert nodemap range into '%s': rc = %d\n",
+ nodemap->nm_name, rc);
up_write(&config->nmc_range_tree_lock);
list_del(&range->rn_list);
range_destroy(range);
- GOTO(out, rc = -ENOMEM);
+ GOTO(out, rc);
}
list_add(&range->rn_list, &nodemap->nm_ranges);
/* if range_id is non-zero, we are loading from disk */
if (range_id == 0)
- rc = nodemap_idx_range_add(range, nid);
+ rc = nodemap_idx_range_add(range);
if (config == active_config) {
nm_member_revoke_locks(config->nmc_default_nodemap);
out:
return rc;
}
-int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
+
+int nodemap_add_range(const char *name, const struct lnet_nid nid[2],
+ u8 netmask)
{
struct lu_nodemap *nodemap = NULL;
int rc;
if (is_default_nodemap(nodemap))
rc = -EINVAL;
else
- rc = nodemap_add_range_helper(active_config, nodemap, nid, 0);
+ rc = nodemap_add_range_helper(active_config, nodemap, nid,
+ netmask, 0);
mutex_unlock(&active_config_lock);
nodemap_putref(nodemap);
out:
* Delete range from global range tree, and remove it
* from the list in the associated nodemap.
*/
-int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
+int nodemap_del_range(const char *name, const struct lnet_nid nid[2],
+ u8 netmask)
{
struct lu_nodemap *nodemap;
struct lu_nid_range *range;
GOTO(out_putref, rc = -EINVAL);
down_write(&active_config->nmc_range_tree_lock);
- range = range_find(&active_config->nmc_range_tree, nid[0], nid[1]);
+ range = range_find(active_config, &nid[0], &nid[1], netmask);
if (range == NULL) {
up_write(&active_config->nmc_range_tree_lock);
GOTO(out_putref, rc = -EINVAL);
GOTO(out_putref, rc = -EINVAL);
}
rc = nodemap_idx_range_del(range);
- range_delete(&active_config->nmc_range_tree, range);
+ range_delete(active_config, range);
nm_member_reclassify_nodemap(nodemap);
up_write(&active_config->nmc_range_tree_lock);
{
int rc = 0;
- /* we allow fileset = "" which means clear fileset info */
- if (fileset == NULL || (fileset[0] != 0 && fileset[0] != '/'))
+ /* Allow 'fileset=clear' in addition to 'fileset=""' to clear fileset
+ * because either command 'lctl set_param -P *.*.fileset=""' or
+ * 'lctl nodemap_set_fileset --fileset ""' can only work correctly
+ * on MGS, while on other servers, both commands will invoke upcall
+ * "/usr/sbin/lctl set_param nodemap.default.fileset=" by function
+ * process_param2_config(), which will cause "no value" error and
+ * won't clear fileset.
+ * 'fileset=""' is still kept for compatibility reason.
+ */
+ if (fileset == NULL)
+ rc = -EINVAL;
+ else if (fileset[0] == '\0' || strcmp(fileset, "clear") == 0)
+ nodemap->nm_fileset[0] = '\0';
+ else if (fileset[0] != '/')
rc = -EINVAL;
- else if (strlcpy(nodemap->nm_fileset, fileset,
- sizeof(nodemap->nm_fileset)) >=
- sizeof(nodemap->nm_fileset))
+ else if (strscpy(nodemap->nm_fileset, fileset,
+ sizeof(nodemap->nm_fileset)) < 0)
rc = -ENAMETOOLONG;
return rc;
GOTO(out, rc = PTR_ERR(nodemap));
}
- rc = nodemap_set_fileset_helper(active_config, nodemap,
- fileset);
+ rc = nodemap_set_fileset_helper(active_config, nodemap, fileset);
mutex_unlock(&active_config_lock);
nodemap_putref(nodemap);
}
EXPORT_SYMBOL(nodemap_get_fileset);
+static int nodemap_validate_sepol(const char *sepol)
+{
+ char buf[LUSTRE_NODEMAP_SEPOL_LENGTH + 1];
+ char *p = (char *)sepol;
+ char *q = buf;
+ char polname[NAME_MAX + 1] = "";
+ char hash[SELINUX_POLICY_HASH_LEN + 1] = "";
+ unsigned char mode;
+ unsigned short ver;
+
+ BUILD_BUG_ON(sizeof(buf) != sizeof(((struct lu_nodemap *)0)->nm_sepol));
+
+ if (sepol == NULL)
+ return -EINVAL;
+
+ /* we allow sepol = "" which means clear SELinux policy info */
+ if (sepol[0] == '\0')
+ return 0;
+
+ /* make a copy of sepol, by replacing ':' with space
+ * so that we can use sscanf over the string
+ */
+ while (p-sepol < sizeof(buf)) {
+ if (*p == ':')
+ *q = ' ';
+ else
+ *q = *p;
+ if (*p == '\0')
+ break;
+ p++;
+ q++;
+ }
+ if (p-sepol == sizeof(buf))
+ return -ENAMETOOLONG;
+
+ if (sscanf(buf, "%1hhu %s %hu %s", &mode, polname, &ver, hash) != 4)
+ return -EINVAL;
+
+ if (mode != 0 && mode != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * set SELinux policy on nodemap
+ * \param name nodemap to set SELinux policy info on
+ * \param sepol string containing SELinux policy info
+ * \retval 0 on success
+ *
+ * set SELinux policy info on the named nodemap
+ */
+int nodemap_set_sepol(const char *name, const char *sepol)
+{
+ struct lu_nodemap *nodemap = NULL;
+ int rc;
+
+ rc = nodemap_validate_sepol(sepol);
+ if (rc < 0)
+ GOTO(out, rc);
+
+ 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)) {
+ /* We do not want nodes in the default nodemap to have
+ * SELinux restrictions. Sec admin should create dedicated
+ * nodemap entries for this.
+ */
+ GOTO(out_putref, rc = -EINVAL);
+ }
+
+ /* truncation cannot happen, as string length was checked in
+ * nodemap_validate_sepol()
+ */
+ strscpy(nodemap->nm_sepol, sepol, sizeof(nodemap->nm_sepol));
+
+out_putref:
+ mutex_unlock(&active_config_lock);
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_set_sepol);
+
+/**
+ * get SELinux policy info defined on nodemap
+ * \param nodemap nodemap to get SELinux policy info from
+ * \retval SELinux policy info, or NULL if not defined or not activated
+ *
+ * get the SELinux policy info defined on the nodemap
+ */
+const char *nodemap_get_sepol(const struct lu_nodemap *nodemap)
+{
+ if (is_default_nodemap(nodemap))
+ return NULL;
+ else
+ return (char *)nodemap->nm_sepol;
+}
+EXPORT_SYMBOL(nodemap_get_sepol);
+
/**
* Nodemap constructor
*
* Creates an lu_nodemap structure and assigns sane default
* member values. If this is the default nodemap, the defaults
- * are the most restictive in xterms of mapping behavior. Otherwise
+ * are the most restrictive in terms of mapping behavior. Otherwise
* the default flags should be inherited from the default nodemap.
* The adds nodemap to nodemap_hash.
*
struct lu_nodemap *default_nodemap;
struct cfs_hash *hash = config->nmc_nodemap_hash;
int rc = 0;
+ ENTRY;
default_nodemap = config->nmc_default_nodemap;
OBD_ALLOC_PTR(nodemap);
if (nodemap == NULL) {
- CERROR("cannot allocate memory (%zu bytes)"
- "for nodemap '%s'\n", sizeof(*nodemap),
- name);
+ CERROR("cannot allocate memory (%zu bytes) for nodemap '%s'\n",
+ sizeof(*nodemap), name);
GOTO(out, rc = -ENOMEM);
}
INIT_LIST_HEAD(&nodemap->nm_member_list);
mutex_init(&nodemap->nm_member_list_lock);
- rwlock_init(&nodemap->nm_idmap_lock);
+ init_rwsem(&nodemap->nm_idmap_lock);
nodemap->nm_fs_to_client_uidmap = RB_ROOT;
nodemap->nm_client_to_fs_uidmap = RB_ROOT;
nodemap->nm_fs_to_client_gidmap = RB_ROOT;
nodemap->nm_client_to_fs_gidmap = RB_ROOT;
+ nodemap->nm_fs_to_client_projidmap = RB_ROOT;
+ nodemap->nm_client_to_fs_projidmap = RB_ROOT;
if (is_default) {
nodemap->nm_id = LUSTRE_NODEMAP_DEFAULT_ID;
nodemap->nmf_trust_client_ids = 0;
nodemap->nmf_allow_root_access = 0;
nodemap->nmf_deny_unknown = 0;
- nodemap->nmf_map_uid_only = 0;
- nodemap->nmf_map_gid_only = 0;
+ nodemap->nmf_map_mode = NODEMAP_MAP_ALL;
+ nodemap->nmf_enable_audit = 1;
+ nodemap->nmf_forbid_encryption = 0;
+ nodemap->nmf_readonly_mount = 0;
+ nodemap->nmf_rbac = NODEMAP_RBAC_ALL;
nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
+ nodemap->nm_squash_projid = NODEMAP_NOBODY_PROJID;
nodemap->nm_fileset[0] = '\0';
+ nodemap->nm_sepol[0] = '\0';
if (!is_default)
CWARN("adding nodemap '%s' to config without"
" default nodemap\n", nodemap->nm_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->nmf_map_uid_only =
- default_nodemap->nmf_map_uid_only;
- nodemap->nmf_map_gid_only =
- default_nodemap->nmf_map_gid_only;
+ nodemap->nmf_deny_unknown = default_nodemap->nmf_deny_unknown;
+ nodemap->nmf_map_mode = default_nodemap->nmf_map_mode;
+ nodemap->nmf_enable_audit = default_nodemap->nmf_enable_audit;
+ nodemap->nmf_forbid_encryption =
+ default_nodemap->nmf_forbid_encryption;
+ nodemap->nmf_readonly_mount =
+ default_nodemap->nmf_readonly_mount;
+ nodemap->nmf_rbac = default_nodemap->nmf_rbac;
nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
+ nodemap->nm_squash_projid = default_nodemap->nm_squash_projid;
nodemap->nm_fileset[0] = '\0';
+ nodemap->nm_sepol[0] = '\0';
}
- return nodemap;
+ RETURN(nodemap);
out:
CERROR("cannot add nodemap: '%s': rc = %d\n", name, rc);
- return ERR_PTR(rc);
+ RETURN(ERR_PTR(rc));
}
/**
}
EXPORT_SYMBOL(nodemap_set_trust_client_ids);
-int nodemap_set_mapping_mode(const char *name, enum nodemap_mapping_modes mode)
+int nodemap_set_mapping_mode(const char *name,
+ enum nodemap_mapping_modes map_mode)
{
struct lu_nodemap *nodemap = NULL;
int rc = 0;
if (IS_ERR(nodemap))
GOTO(out, rc = PTR_ERR(nodemap));
- switch (mode) {
- case NODEMAP_MAP_BOTH:
- nodemap->nmf_map_uid_only = 0;
- nodemap->nmf_map_gid_only = 0;
- break;
- case NODEMAP_MAP_UID_ONLY:
- nodemap->nmf_map_uid_only = 1;
- nodemap->nmf_map_gid_only = 0;
- break;
- case NODEMAP_MAP_GID_ONLY:
- nodemap->nmf_map_uid_only = 0;
- nodemap->nmf_map_gid_only = 1;
- break;
- default:
- CWARN("cannot set unknown mapping mode, mode = %d\n", mode);
- }
+ nodemap->nmf_map_mode = map_mode;
rc = nodemap_idx_nodemap_update(nodemap);
nm_member_revoke_locks(nodemap);
}
EXPORT_SYMBOL(nodemap_set_mapping_mode);
+int nodemap_set_rbac(const char *name, enum nodemap_rbac_roles rbac)
+{
+ struct lu_nodemap *nodemap = NULL;
+ enum nodemap_rbac_roles old_rbac;
+ 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));
+
+ if (is_default_nodemap(nodemap))
+ GOTO(put, rc = -EINVAL);
+
+ old_rbac = nodemap->nmf_rbac;
+ /* if value does not change, do nothing */
+ if (rbac == old_rbac)
+ GOTO(put, rc = 0);
+
+ nodemap->nmf_rbac = rbac;
+ if (rbac == NODEMAP_RBAC_ALL)
+ /* if new value is ALL (default), just delete
+ * NODEMAP_CLUSTER_ROLES idx
+ */
+ rc = nodemap_idx_cluster_roles_del(nodemap);
+ else if (old_rbac == NODEMAP_RBAC_ALL)
+ /* if old value is ALL (default), need to insert
+ * NODEMAP_CLUSTER_ROLES idx
+ */
+ rc = nodemap_idx_cluster_roles_add(nodemap);
+ else
+ /* otherwise just update existing NODEMAP_CLUSTER_ROLES idx */
+ rc = nodemap_idx_cluster_roles_update(nodemap);
+
+ nm_member_revoke_locks(nodemap);
+put:
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_set_rbac);
+
/**
* Update the squash_uid for a nodemap.
*
* \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
+ * Update the squash_gid for a nodemap. The squash_gid is the gid
* that the all client gids are mapped to if nodemap is active,
* the trust_client_ids flag is not set, and the gid is not in
* the idmap tree.
EXPORT_SYMBOL(nodemap_set_squash_gid);
/**
- * Returns true if this nodemap has root user access. Always returns true if
- * nodemaps are not active.
+ * Update the squash_projid for a nodemap.
+ *
+ * \param name nodemap name
+ * \param gid the new projid to squash unknown projids to
+ * \retval 0 on success
+ *
+ * Update the squash_projid for a nodemap. The squash_projid is the projid
+ * that the all client projids are mapped to if nodemap is active,
+ * the trust_client_ids flag is not set, and the projid is not in
+ * the idmap tree.
+ */
+int nodemap_set_squash_projid(const char *name, projid_t projid)
+{
+ 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->nm_squash_projid = projid;
+ rc = nodemap_idx_nodemap_update(nodemap);
+
+ nm_member_revoke_locks(nodemap);
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_set_squash_projid);
+
+/**
+ * Check if nodemap allows setting quota.
+ *
+ * If nodemap is not active, always allow.
+ * For user and group quota, allow if the nodemap allows root access.
+ * For project quota, allow if project id is not squashed or deny_unknown
+ * is not set.
*
* \param nodemap nodemap to check access for
+ * \param qc_type quota type
+ * \param id client id to map
+ * \retval true is setquota is allowed, false otherwise
*/
-bool nodemap_can_setquota(const struct lu_nodemap *nodemap)
+bool nodemap_can_setquota(struct lu_nodemap *nodemap, __u32 qc_type, __u32 id)
{
- return !nodemap_active || (nodemap && nodemap->nmf_allow_root_access);
+ if (!nodemap_active)
+ return true;
+
+ if (!nodemap || !nodemap->nmf_allow_root_access ||
+ !(nodemap->nmf_rbac & NODEMAP_RBAC_QUOTA_OPS))
+ return false;
+
+ if (qc_type == PRJQUOTA) {
+ id = nodemap_map_id(nodemap, NODEMAP_PROJID,
+ NODEMAP_CLIENT_TO_FS, id);
+
+ if (id == nodemap->nm_squash_projid &&
+ nodemap->nmf_deny_unknown)
+ return false;
+ }
+
+ return true;
}
EXPORT_SYMBOL(nodemap_can_setquota);
/**
+ * Set the nmf_enable_audit flag to true or false.
+ * \param name nodemap name
+ * \param audit_mode if true, allow audit
+ * \retval 0 on success
+ *
+ */
+int nodemap_set_audit_mode(const char *name, bool enable_audit)
+{
+ 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_enable_audit = enable_audit;
+ rc = nodemap_idx_nodemap_update(nodemap);
+
+ nm_member_revoke_locks(nodemap);
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_set_audit_mode);
+
+/**
+ * Set the nmf_forbid_encryption flag to true or false.
+ * \param name nodemap name
+ * \param forbid_encryption if true, forbid encryption
+ * \retval 0 on success
+ *
+ */
+int nodemap_set_forbid_encryption(const char *name, bool forbid_encryption)
+{
+ 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_forbid_encryption = forbid_encryption;
+ rc = nodemap_idx_nodemap_update(nodemap);
+
+ nm_member_revoke_locks(nodemap);
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_set_forbid_encryption);
+
+/**
+ * Set the nmf_readonly_mount flag to true or false.
+ * \param name nodemap name
+ * \param readonly_mount if true, forbid rw mount
+ * \retval 0 on success
+ *
+ */
+int nodemap_set_readonly_mount(const char *name, bool readonly_mount)
+{
+ 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_readonly_mount = readonly_mount;
+ rc = nodemap_idx_nodemap_update(nodemap);
+
+ nm_member_revoke_locks(nodemap);
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_set_readonly_mount);
+
+/**
* Add a nodemap
*
* \param name name of nodemap
if (rc2 < 0)
rc = rc2;
- range_delete(&active_config->nmc_range_tree, range);
+ range_delete(active_config, range);
}
up_write(&active_config->nmc_range_tree_lock);
init_rwsem(&config->nmc_range_tree_lock);
+ INIT_LIST_HEAD(&config->nmc_netmask_setup);
+ config->nmc_range_tree.nmrt_range_interval_root = INTERVAL_TREE_ROOT;
+
return config;
}
EXPORT_SYMBOL(nodemap_config_alloc);
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);
+ range_delete(config, range);
up_write(&config->nmc_range_tree_lock);
mutex_unlock(&active_config_lock);
*/
int nodemap_mod_init(void)
{
- struct nodemap_config *new_config;
- struct lu_nodemap *nodemap;
- int rc = 0;
+ struct nodemap_config *new_config;
+ struct lu_nodemap *nodemap;
+ int rc = 0;
rc = nodemap_procfs_init();
if (rc != 0)
* \param[out] name_buf buffer to write the nodemap name to
* \param name_len length of buffer
*/
-void nodemap_test_nid(lnet_nid_t nid, char *name_buf, size_t name_len)
+void nodemap_test_nid(struct lnet_nid *nid, char *name_buf, size_t name_len)
{
- struct lu_nodemap *nodemap;
+ struct lu_nodemap *nodemap;
mutex_lock(&active_config_lock);
down_read(&active_config->nmc_range_tree_lock);
* \retval 0 success
* \retval -EINVAL invalid NID
*/
-int nodemap_test_id(lnet_nid_t nid, enum nodemap_id_type idtype,
- __u32 client_id, __u32 *fs_id)
+int nodemap_test_id(struct lnet_nid *nid, enum nodemap_id_type idtype,
+ u32 client_id, u32 *fs_id)
{
- struct lu_nodemap *nodemap;
+ struct lu_nodemap *nodemap;
mutex_lock(&active_config_lock);
down_read(&active_config->nmc_range_tree_lock);