4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (C) 2013, Trustees of Indiana University
24 * Author: Joshua Walgenbach <jjw@iu.edu>
26 #include <linux/module.h>
27 #include <lustre_net.h>
28 #include "nodemap_internal.h"
30 #define HASH_NODEMAP_BKT_BITS 3
31 #define HASH_NODEMAP_CUR_BITS 3
32 #define HASH_NODEMAP_MAX_BITS 7
34 #define DEFAULT_NODEMAP "default"
36 /* nodemap proc root proc directory under fs/lustre */
37 struct proc_dir_entry *proc_lustre_nodemap_root;
39 /* Highest numerical lu_nodemap.nm_id defined */
40 static atomic_t nodemap_highest_id;
42 /* Simple flag to determine if nodemaps are active */
46 * pointer to default nodemap kept to keep from
47 * lookup it up in the hash since it is needed
50 static struct lu_nodemap *default_nodemap;
53 * Hash keyed on nodemap name containing all
56 static cfs_hash_t *nodemap_hash;
61 * \param nodemap nodemap to destroy
63 static void nodemap_destroy(struct lu_nodemap *nodemap)
65 struct lu_nid_range *range;
66 struct lu_nid_range *temp;
68 list_for_each_entry_safe(range, temp, &nodemap->nm_ranges,
73 idmap_delete_tree(nodemap);
75 lprocfs_remove(&nodemap->nm_proc_entry);
76 OBD_FREE_PTR(nodemap);
80 * Functions used for the cfs_hash
82 static void nodemap_getref(struct lu_nodemap *nodemap)
84 CDEBUG(D_INFO, "nodemap %p\n", nodemap);
85 atomic_inc(&nodemap->nm_refcount);
88 void nodemap_putref(struct lu_nodemap *nodemap)
90 LASSERT(nodemap != NULL);
91 LASSERT(atomic_read(&nodemap->nm_refcount) > 0);
93 if (atomic_dec_and_test(&nodemap->nm_refcount))
94 nodemap_destroy(nodemap);
97 static __u32 nodemap_hashfn(cfs_hash_t *hash_body,
98 const void *key, unsigned mask)
100 const struct lu_nodemap *nodemap = key;
102 return cfs_hash_djb2_hash(nodemap->nm_name, strlen(nodemap->nm_name),
106 static void *nodemap_hs_key(cfs_hlist_node_t *hnode)
108 struct lu_nodemap *nodemap;
110 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
112 return nodemap->nm_name;
115 static int nodemap_hs_keycmp(const void *key,
116 cfs_hlist_node_t *compared_hnode)
118 struct lu_nodemap *nodemap;
120 nodemap = nodemap_hs_key(compared_hnode);
122 return !strcmp(key, nodemap->nm_name);
125 static void *nodemap_hs_hashobject(cfs_hlist_node_t *hnode)
127 return cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
130 static void nodemap_hs_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
132 struct lu_nodemap *nodemap;
134 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
135 nodemap_getref(nodemap);
138 static void nodemap_hs_put_locked(cfs_hash_t *hs,
139 cfs_hlist_node_t *hnode)
141 struct lu_nodemap *nodemap;
143 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
144 nodemap_putref(nodemap);
147 static cfs_hash_ops_t nodemap_hash_operations = {
148 .hs_hash = nodemap_hashfn,
149 .hs_key = nodemap_hs_key,
150 .hs_keycmp = nodemap_hs_keycmp,
151 .hs_object = nodemap_hs_hashobject,
152 .hs_get = nodemap_hs_get,
153 .hs_put_locked = nodemap_hs_put_locked,
156 /* end of cfs_hash functions */
159 * Helper iterator to clean up nodemap on module exit.
161 * \param hs hash structure
162 * \param bd bucket descriptor
163 * \param hnode hash node
164 * \param data not used here
166 static int nodemap_cleanup_iter_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
167 cfs_hlist_node_t *hnode, void *data)
169 struct lu_nodemap *nodemap;
171 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
172 nodemap_putref(nodemap);
178 * Walk the nodemap_hash and remove all nodemaps.
180 void nodemap_cleanup_all(void)
182 cfs_hash_for_each_safe(nodemap_hash, nodemap_cleanup_iter_cb, NULL);
183 cfs_hash_putref(nodemap_hash);
187 * Initialize nodemap_hash
190 * \retval -ENOMEM cannot create hash
192 static int nodemap_init_hash(void)
194 nodemap_hash = cfs_hash_create("NODEMAP", HASH_NODEMAP_CUR_BITS,
195 HASH_NODEMAP_MAX_BITS,
196 HASH_NODEMAP_BKT_BITS, 0,
199 &nodemap_hash_operations,
202 if (nodemap_hash == NULL) {
203 CERROR("cannot create nodemap_hash table\n");
211 * Check for valid nodemap name
213 * \param name nodemap name
215 * \retval false invalid
217 static bool nodemap_name_is_valid(const char *name)
219 if (strlen(name) > LUSTRE_NODEMAP_NAME_LENGTH ||
223 for (; *name != '\0'; name++) {
224 if (!isalnum(*name) && *name != '_')
233 * Look nodemap up in the nodemap hash
235 * \param name name of nodemap
236 * \param nodemap found nodemap or NULL
237 * \retval lu_nodemap named nodemap
238 * \retval NULL nodemap doesn't exist
240 static int nodemap_lookup(const char *name, struct lu_nodemap **nodemap)
246 if (!nodemap_name_is_valid(name))
247 GOTO(out, rc = -EINVAL);
249 *nodemap = cfs_hash_lookup(nodemap_hash, name);
250 if (*nodemap == NULL)
258 * classify the nid into the proper nodemap
260 * \param nid nid to classify
261 * \retval nodemap nodemap containing the nid
262 * \retval default_nodemap default nodemap
264 struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid)
266 struct lu_nid_range *range;
268 range = range_search(nid);
270 return range->rn_nodemap;
272 return default_nodemap;
274 EXPORT_SYMBOL(nodemap_classify_nid);
277 * simple check for default nodemap
279 static bool is_default_nodemap(const struct lu_nodemap *nodemap)
281 return nodemap->nm_id == 0;
285 * parse a nodemap range string into two nids
287 * \param range_str string to parse
288 * \param range[2] array of two nids
289 * \reyval 0 on success
291 int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
293 char buf[LNET_NIDSTR_SIZE * 2 + 2];
299 snprintf(buf, sizeof(buf), "%s", range_str);
301 start_nidstr = strsep(&ptr, ":");
302 end_nidstr = strsep(&ptr, ":");
304 if (start_nidstr == NULL || end_nidstr == NULL)
305 GOTO(out, rc = -EINVAL);
307 range[0] = libcfs_str2nid(start_nidstr);
308 range[1] = libcfs_str2nid(end_nidstr);
314 EXPORT_SYMBOL(nodemap_parse_range);
317 * parse a string containing an id map of form "client_id:filesystem_id"
318 * into an array of __u32 * for use in mapping functions
320 * \param idmap_str map string
321 * \param idmap array[2] of __u32
323 * \retval 0 on success
325 int nodemap_parse_idmap(const char *idmap_str, __u32 idmap[2])
329 if (idmap_str == NULL)
332 idmap[0] = simple_strtoul(idmap_str, &end, 10);
333 if (end == idmap_str || *end != ':')
337 idmap[1] = simple_strtoul(idmap_str, &end, 10);
338 if (end == idmap_str)
343 EXPORT_SYMBOL(nodemap_parse_idmap);
346 * add an idmap to the proper nodemap trees
348 * \param name name of nodemap
349 * \param id_type NODEMAP_UID or NODEMAP_GID
350 * \param map array[2] __u32 containing the mapA values
351 * map[0] is client id
352 * map[1] is the filesystem id
354 * \retval 0 on success
356 int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
359 struct lu_nodemap *nodemap = NULL;
360 struct lu_idmap *idmap;
363 rc = nodemap_lookup(name, &nodemap);
364 if (nodemap == NULL || is_default_nodemap(nodemap))
365 GOTO(out, rc = -EINVAL);
367 idmap = idmap_create(map[0], map[1]);
369 GOTO(out_putref, rc = -ENOMEM);
371 idmap_insert(id_type, idmap, nodemap);
374 nodemap_putref(nodemap);
378 EXPORT_SYMBOL(nodemap_add_idmap);
381 * delete idmap from proper nodemap tree
383 * \param name name of nodemap
384 * \param id_type NODEMAP_UID or NODEMAP_GID
385 * \param map array[2] __u32 containing the mapA values
386 * map[0] is client id
387 * map[1] is the filesystem id
389 * \retval 0 on success
391 int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
394 struct lu_nodemap *nodemap = NULL;
395 struct lu_idmap *idmap = NULL;
398 rc = nodemap_lookup(name, &nodemap);
399 if (nodemap == NULL || is_default_nodemap(nodemap))
400 GOTO(out, rc = -EINVAL);
402 idmap = idmap_search(nodemap, NODEMAP_CLIENT_TO_FS, id_type,
405 GOTO(out_putref, rc = -EINVAL);
407 idmap_delete(id_type, idmap, nodemap);
410 nodemap_putref(nodemap);
414 EXPORT_SYMBOL(nodemap_del_idmap);
417 * mapping function for nodemap idmaps
419 * \param nodemap lu_nodemap structure defining nodemap
420 * \param node_type NODEMAP_UID or NODEMAP_GID
421 * \param tree_type NODEMAP_CLIENT_TO_FS or
422 * NODEMAP_FS_TO_CLIENT
423 * \param id id to map
425 * \retval mapped id according to the rules below.
427 * if the nodemap_active is false, just return the passed id without mapping
429 * if the id to be looked up in 0, check that root access is allowed and if it
430 * is, return 0. Otherwise, return the squash uid or gid.
432 * if the nodemap is configured to trusted the ids from the client system, just
433 * return the passwd id without mapping.
435 * if by this point, we haven't returned and the nodemap in question is the
436 * default nodemap, return the dquash uid or gid.
438 * after these checks, search the proper tree for the mapping, and if found
439 * return the mapped value, otherwise return the squash uid or gid.
441 __u32 nodemap_map_id(struct lu_nodemap *nodemap,
442 enum nodemap_id_type id_type,
443 enum nodemap_tree_type tree_type, __u32 id)
445 struct lu_idmap *idmap = NULL;
451 if (nodemap->nmf_allow_root_access)
457 if (nodemap->nmf_trust_client_ids)
460 if (is_default_nodemap(nodemap))
463 idmap = idmap_search(nodemap, tree_type, id_type, id);
467 if (tree_type == NODEMAP_FS_TO_CLIENT)
468 return idmap->id_client;
473 if (id_type == NODEMAP_UID)
474 return nodemap->nm_squash_uid;
476 return nodemap->nm_squash_gid;
480 EXPORT_SYMBOL(nodemap_map_id);
483 * add nid range to nodemap
484 * \param name nodemap name
485 * \param range_st string containing nid range
486 * \retval 0 on success
488 * add an range to the global range tree and attached the
489 * range to the named nodemap.
491 int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
493 struct lu_nodemap *nodemap = NULL;
494 struct lu_nid_range *range;
497 rc = nodemap_lookup(name, &nodemap);
498 if (nodemap == NULL || is_default_nodemap(nodemap))
499 GOTO(out, rc = -EINVAL);
501 range = range_create(nid[0], nid[1], nodemap);
503 GOTO(out_putref, rc = -ENOMEM);
505 rc = range_insert(range);
507 CERROR("cannot insert nodemap range into '%s': rc = %d\n",
508 nodemap->nm_name, rc);
509 list_del(&range->rn_list);
510 range_destroy(range);
511 GOTO(out_putref, rc = -ENOMEM);
514 list_add(&range->rn_list, &nodemap->nm_ranges);
517 nodemap_putref(nodemap);
521 EXPORT_SYMBOL(nodemap_add_range);
525 * \param name nodemap name
526 * \param range_str string containing range
527 * \retval 0 on success
529 * Delete range from global range tree, and remove it
530 * from the list in the associated nodemap.
532 int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
534 struct lu_nodemap *nodemap;
535 struct lu_nid_range *range;
538 rc = nodemap_lookup(name, &nodemap);
539 if (nodemap == NULL || is_default_nodemap(nodemap))
540 GOTO(out, rc = -EINVAL);
542 range = range_find(nid[0], nid[1]);
544 GOTO(out_putref, rc = -EINVAL);
549 nodemap_putref(nodemap);
553 EXPORT_SYMBOL(nodemap_del_range);
556 * Nodemap constructor
558 * Creates an lu_nodemap structure and assigns sane default
559 * member values. If this is the default nodemap, the defaults
560 * are the most restictive in xterms of mapping behavior. Otherwise
561 * the default flags should be inherited from the default nodemap.
562 * The adds nodemap to nodemap_hash.
564 * \param name name of nodemap
565 * \param is_default true if default nodemap
567 * \retval -EINVAL invalid nodemap name
568 * \retval -EEXIST nodemap already exists
569 * \retval -ENOMEM cannot allocate memory for nodemap
571 static int nodemap_create(const char *name, bool is_default)
573 struct lu_nodemap *nodemap = NULL;
576 rc = nodemap_lookup(name, &nodemap);
581 nodemap_putref(nodemap);
582 GOTO(out, rc = -EEXIST);
584 OBD_ALLOC_PTR(nodemap);
586 if (nodemap == NULL) {
587 CERROR("cannot allocate memory (%zu bytes)"
588 "for nodemap '%s'\n", sizeof(*nodemap),
590 GOTO(out, rc = -ENOMEM);
593 snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
595 INIT_LIST_HEAD(&(nodemap->nm_ranges));
596 nodemap->nm_fs_to_client_uidmap = RB_ROOT;
597 nodemap->nm_client_to_fs_uidmap = RB_ROOT;
598 nodemap->nm_fs_to_client_gidmap = RB_ROOT;
599 nodemap->nm_client_to_fs_gidmap = RB_ROOT;
602 nodemap->nm_id = LUSTRE_NODEMAP_DEFAULT_ID;
603 nodemap->nmf_trust_client_ids = 0;
604 nodemap->nmf_allow_root_access = 0;
605 nodemap->nmf_block_lookups = 0;
607 nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
608 nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
610 lprocfs_nodemap_register(name, is_default, nodemap);
612 default_nodemap = nodemap;
614 nodemap->nm_id = atomic_inc_return(&nodemap_highest_id);
615 nodemap->nmf_trust_client_ids =
616 default_nodemap->nmf_trust_client_ids;
617 nodemap->nmf_allow_root_access =
618 default_nodemap->nmf_allow_root_access;
619 nodemap->nmf_block_lookups =
620 default_nodemap->nmf_block_lookups;
622 nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
623 nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
625 lprocfs_nodemap_register(name, is_default, nodemap);
628 atomic_set(&nodemap->nm_refcount, 1);
629 rc = cfs_hash_add_unique(nodemap_hash, name, &nodemap->nm_hash);
634 CERROR("cannot add nodemap: '%s': rc = %d\n", name, rc);
635 nodemap_destroy(nodemap);
642 * update flag to turn on or off nodemap functions
643 * \param name nodemap name
644 * \param admin_string string containing updated value
645 * \retval 0 on success
647 * Update admin flag to turn on or off nodemap functions.
649 int nodemap_set_allow_root(const char *name, bool allow_root)
651 struct lu_nodemap *nodemap = NULL;
654 rc = nodemap_lookup(name, &nodemap);
656 GOTO(out, rc = -ENOENT);
658 nodemap->nmf_allow_root_access = allow_root;
659 nodemap_putref(nodemap);
663 EXPORT_SYMBOL(nodemap_set_allow_root);
666 * updated trust_client_ids flag for nodemap
668 * \param name nodemap name
669 * \param trust_string new value for trust flag
670 * \retval 0 on success
672 * Update the trust_client_ids flag for a nodemap.
674 int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids)
676 struct lu_nodemap *nodemap = NULL;
679 rc = nodemap_lookup(name, &nodemap);
681 GOTO(out, rc = -ENOENT);
683 nodemap->nmf_trust_client_ids = trust_client_ids;
684 nodemap_putref(nodemap);
688 EXPORT_SYMBOL(nodemap_set_trust_client_ids);
691 * update the squash_uid for a nodemap
693 * \param name nodemap name
694 * \param uid_string string containing new squash_uid value
695 * \retval 0 on success
697 * Update the squash_uid for a nodemap. The squash_uid is the uid
698 * that the all client uids are mapped to if nodemap is active,
699 * the trust_client_ids flag is not set, and the uid is not in
702 int nodemap_set_squash_uid(const char *name, uid_t uid)
704 struct lu_nodemap *nodemap = NULL;
707 rc = nodemap_lookup(name, &nodemap);
709 GOTO(out, rc = -ENOENT);
711 nodemap->nm_squash_uid = uid;
712 nodemap_putref(nodemap);
716 EXPORT_SYMBOL(nodemap_set_squash_uid);
719 * update the squash_gid for a nodemap
721 * \param name nodemap name
722 * \param gid_string string containing new squash_gid value
723 * \retval 0 on success
725 * Update the squash_gid for a nodemap. The squash_uid is the gid
726 * that the all client gids are mapped to if nodemap is active,
727 * the trust_client_ids flag is not set, and the gid is not in
730 int nodemap_set_squash_gid(const char *name, gid_t gid)
732 struct lu_nodemap *nodemap = NULL;
735 rc = nodemap_lookup(name, &nodemap);
737 GOTO(out, rc = -ENOENT);
739 nodemap->nm_squash_gid = gid;
740 nodemap_putref(nodemap);
744 EXPORT_SYMBOL(nodemap_set_squash_gid);
749 * \param name name of nodemap
751 * \retval -EINVAL invalid nodemap name
752 * \retval -EEXIST nodemap already exists
753 * \retval -ENOMEM cannot allocate memory for nodemap
755 int nodemap_add(const char *name)
757 return nodemap_create(name, 0);
759 EXPORT_SYMBOL(nodemap_add);
764 * \param name name of nodemmap
766 * \retval -EINVAL invalid input
767 * \retval -ENOENT no existing nodemap
769 int nodemap_del(const char *name)
771 struct lu_nodemap *nodemap;
774 if (strcmp(name, DEFAULT_NODEMAP) == 0)
775 GOTO(out, rc = -EINVAL);
777 nodemap = cfs_hash_del_key(nodemap_hash, name);
779 GOTO(out, rc = -ENOENT);
781 nodemap_putref(nodemap);
785 EXPORT_SYMBOL(nodemap_del);
788 * activate nodemap functions
790 * \param value 1 for on, 0 for off
792 void nodemap_activate(const bool value)
794 nodemap_active = value;
796 EXPORT_SYMBOL(nodemap_activate);
799 * Cleanup nodemap module on exit
801 static void nodemap_mod_exit(void)
803 nodemap_cleanup_all();
804 lprocfs_remove(&proc_lustre_nodemap_root);
808 * Initialize the nodemap module
810 static int __init nodemap_mod_init(void)
814 rc = nodemap_init_hash();
818 nodemap_procfs_init();
819 rc = nodemap_create(DEFAULT_NODEMAP, 1);
828 MODULE_LICENSE("GPL");
829 MODULE_DESCRIPTION("Lustre Client Nodemap Management Module");
830 MODULE_AUTHOR("Joshua Walgenbach <jjw@iu.edu>");
832 module_init(nodemap_mod_init);
833 module_exit(nodemap_mod_exit);