From 25420c75e45a91c6131d52a674869d6d30ab36bf Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Fri, 5 Feb 2016 16:44:40 +0100 Subject: [PATCH] LU-7846 nodemap: add fileset info to nodemap Give the ability to set a fileset information on a nodemap. When set, a client pertaining to this nodemap will be allowed to mount only the subdirectory represented by this fileset. Fileset info of nodemap is stored permanently by using 'lctl set_param -P' commands. It means MDS and OSS will be able to retrieve fileset info of nodemap after a restart (when they read params llog). MGS will not see fileset info after restart, but this does not prevent the feature from working. Signed-off-by: Sebastien Buisson Signed-off-by: Kit Westneat Change-Id: Ic16abaeb0b2fe583a9a4745258a82bbd23fc259e Reviewed-on: http://review.whamcloud.com/18783 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Li Xi Reviewed-by: Oleg Drokin --- lustre/include/lustre_cfg.h | 1 + lustre/include/lustre_nodemap.h | 4 +++ lustre/mgs/mgs_handler.c | 1 + lustre/mgs/mgs_llog.c | 3 ++ lustre/ptlrpc/nodemap_handler.c | 67 +++++++++++++++++++++++++++++++++++++++++ lustre/ptlrpc/nodemap_lproc.c | 59 ++++++++++++++++++++++++++++++++++++ lustre/utils/lctl.c | 3 ++ lustre/utils/obd.c | 66 ++++++++++++++++++++++++++++++++++++++++ lustre/utils/obdctl.h | 1 + 9 files changed, 205 insertions(+) diff --git a/lustre/include/lustre_cfg.h b/lustre/include/lustre_cfg.h index 71c65c3..f635786 100644 --- a/lustre/include/lustre_cfg.h +++ b/lustre/include/lustre_cfg.h @@ -117,6 +117,7 @@ enum lcfg_command_type { LCFG_NODEMAP_DEL_SHKEY = 0x00ce054, /**< delete shared key from cluster */ LCFG_NODEMAP_TEST_NID = 0x00ce055, /**< test for nodemap membership */ LCFG_NODEMAP_TEST_ID = 0x00ce056, /**< test uid/gid mapping */ + LCFG_NODEMAP_SET_FILESET = 0x00ce057, /**< set fileset */ }; struct lustre_cfg_bufs { diff --git a/lustre/include/lustre_nodemap.h b/lustre/include/lustre_nodemap.h index b49774a..82931c0 100644 --- a/lustre/include/lustre_nodemap.h +++ b/lustre/include/lustre_nodemap.h @@ -91,6 +91,8 @@ struct lu_nodemap { /* access by nodemap name */ struct hlist_node nm_hash; struct nodemap_pde *nm_pde_data; + /* fileset the nodes of this nodemap are restricted to */ + char nm_fileset[PATH_MAX+1]; /* used when loading/unloading nodemaps */ struct list_head nm_list; @@ -123,6 +125,8 @@ int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type, const __u32 map[2]); int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type, const __u32 map[2]); +int nodemap_set_fileset(const char *name, const char *fileset); +char *nodemap_get_fileset(const struct lu_nodemap *nodemap); __u32 nodemap_map_id(struct lu_nodemap *nodemap, enum nodemap_id_type id_type, enum nodemap_tree_type tree_type, __u32 id); diff --git a/lustre/mgs/mgs_handler.c b/lustre/mgs/mgs_handler.c index b60aef9..d59a49b 100644 --- a/lustre/mgs/mgs_handler.c +++ b/lustre/mgs/mgs_handler.c @@ -752,6 +752,7 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env, case LCFG_NODEMAP_DEL_UIDMAP: case LCFG_NODEMAP_ADD_GIDMAP: case LCFG_NODEMAP_DEL_GIDMAP: + case LCFG_NODEMAP_SET_FILESET: if (lcfg->lcfg_bufcount != 3) GOTO(out_lcfg, rc = -EINVAL); nodemap_name = lustre_cfg_string(lcfg, 1); diff --git a/lustre/mgs/mgs_llog.c b/lustre/mgs/mgs_llog.c index 6ba85ca..70a83dc 100644 --- a/lustre/mgs/mgs_llog.c +++ b/lustre/mgs/mgs_llog.c @@ -4169,6 +4169,9 @@ int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs, rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID, idmap); break; + case LCFG_NODEMAP_SET_FILESET: + rc = nodemap_set_fileset(nodemap_name, param); + break; default: rc = -EINVAL; } diff --git a/lustre/ptlrpc/nodemap_handler.c b/lustre/ptlrpc/nodemap_handler.c index 5f82521..10bbc49 100644 --- a/lustre/ptlrpc/nodemap_handler.c +++ b/lustre/ptlrpc/nodemap_handler.c @@ -831,6 +831,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 @@ -923,6 +989,7 @@ struct lu_nodemap *nodemap_create(const char *name, 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; diff --git a/lustre/ptlrpc/nodemap_lproc.c b/lustre/ptlrpc/nodemap_lproc.c index ce47326..fa6a6a7 100644 --- a/lustre/ptlrpc/nodemap_lproc.c +++ b/lustre/ptlrpc/nodemap_lproc.c @@ -168,6 +168,61 @@ static int nodemap_ranges_open(struct inode *inode, struct file *file) } /** + * Reads and prints the fileset for the given nodemap. + * + * \param m seq file in proc fs + * \param data unused + * \retval 0 success + */ +static int nodemap_fileset_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; + } + + rc = seq_printf(m, "%s\n", nodemap->nm_fileset); + nodemap_putref(nodemap); + return rc; +} + +/** + * Set a fileset on a nodemap. + * + * \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; + int rc = 0; + + if (count > 0) + rc = nodemap_set_fileset(m->private, buffer); + + if (rc != 0) + return -EINVAL; + + return count; +} +LPROC_SEQ_FOPS(nodemap_fileset); + +/** * Reads and prints the exports attached to the given nodemap. * * \param m seq file in proc fs, stores nodemap @@ -1059,6 +1114,10 @@ static struct lprocfs_vars lprocfs_nodemap_vars[] = { .fops = &nodemap_ranges_fops, }, { + .name = "fileset", + .fops = &nodemap_fileset_fops, + }, + { .name = "exports", .fops = &nodemap_exports_fops, }, diff --git a/lustre/utils/lctl.c b/lustre/utils/lctl.c index fe9d273..3d5eef2 100644 --- a/lustre/utils/lctl.c +++ b/lustre/utils/lctl.c @@ -285,6 +285,9 @@ command_t cmdlist[] = { "add a UID or GID mapping to a nodemap"}, {"nodemap_del_idmap", jt_nodemap_del_idmap, 0, "delete a UID or GID mapping from a nodemap"}, + {"nodemap_set_fileset", jt_nodemap_set_fileset, 0, + "set a fileset on a nodemap\n" + "usage: nodemap_set_fileset "}, {"nodemap_test_nid", jt_nodemap_test_nid, 0, "usage: nodemap_test_nid "}, {"nodemap_test_id", jt_nodemap_test_id, 0, diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index 796140c..1ca0932 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -3673,6 +3673,72 @@ int jt_nodemap_del_range(int argc, char **argv) } /** + * set a fileset on a nodemap + * + * \param argc number of args + * \param argv[] variable string arguments + * + * --name nodemap name + * --fileset fileset name + * + * \retval 0 on success + */ +int jt_nodemap_set_fileset(int argc, char **argv) +{ + char *nodemap_name = NULL; + char *fileset_name = NULL; + int rc = 0; + int c; + + static struct option long_options[] = { + { + .name = "name", + .has_arg = required_argument, + .flag = 0, + .val = 'n', + }, + { + .name = "fileset", + .has_arg = required_argument, + .flag = 0, + .val = 'f', + }, + { + NULL + } + }; + + while ((c = getopt_long(argc, argv, "n:f:", + long_options, NULL)) != -1) { + switch (c) { + case 'n': + nodemap_name = optarg; + break; + case 'f': + fileset_name = optarg; + break; + } + } + + if (nodemap_name == NULL || fileset_name == NULL) { + fprintf(stderr, "usage: nodemap_set_fileset --name " + "--fileset \n"); + return -1; + } + + rc = nodemap_cmd(LCFG_NODEMAP_SET_FILESET, NULL, 0, argv[0], + nodemap_name, fileset_name, NULL); + if (rc != 0) { + errno = -rc; + fprintf(stderr, "error: %s: cannot set fileset '%s' on nodemap " + "'%s': rc = %d\n", + jt_cmdname(argv[0]), fileset_name, nodemap_name, rc); + } + + return rc; +} + +/** * modify a nodemap's behavior * * \param argc number of args diff --git a/lustre/utils/obdctl.h b/lustre/utils/obdctl.h index 189e8ef..cd75d1f 100644 --- a/lustre/utils/obdctl.h +++ b/lustre/utils/obdctl.h @@ -179,6 +179,7 @@ int jt_nodemap_del_range(int argc, char **argv); int jt_nodemap_add_idmap(int argc, char **argv); int jt_nodemap_del_idmap(int argc, char **argv); int jt_nodemap_test_id(int argc, char **argv); +int jt_nodemap_set_fileset(int argc, char **argv); int jt_nodemap_info(int argc, char **argv); int jt_changelog_register(int argc, char **argv); int jt_changelog_deregister(int argc, char **argv); -- 1.8.3.1