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 */
43 bool nodemap_idmap_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 lprocfs_remove(&nodemap->nm_proc_entry);
74 OBD_FREE_PTR(nodemap);
78 * Functions used for the cfs_hash
80 static void nodemap_getref(struct lu_nodemap *nodemap)
82 CDEBUG(D_INFO, "nodemap %p\n", nodemap);
83 atomic_inc(&nodemap->nm_refcount);
86 void nodemap_putref(struct lu_nodemap *nodemap)
88 LASSERT(nodemap != NULL);
89 LASSERT(cfs_atomic_read(&nodemap->nm_refcount) > 0);
91 if (atomic_dec_and_test(&nodemap->nm_refcount))
92 nodemap_destroy(nodemap);
95 static __u32 nodemap_hashfn(cfs_hash_t *hash_body,
96 const void *key, unsigned mask)
98 const struct lu_nodemap *nodemap = key;
100 return cfs_hash_djb2_hash(nodemap->nm_name, strlen(nodemap->nm_name),
104 static void *nodemap_hs_key(cfs_hlist_node_t *hnode)
106 struct lu_nodemap *nodemap;
108 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
110 return nodemap->nm_name;
113 static int nodemap_hs_keycmp(const void *key,
114 cfs_hlist_node_t *compared_hnode)
116 struct lu_nodemap *nodemap;
118 nodemap = nodemap_hs_key(compared_hnode);
120 return !strcmp(key, nodemap->nm_name);
123 static void *nodemap_hs_hashobject(cfs_hlist_node_t *hnode)
125 return cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
128 static void nodemap_hs_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
130 struct lu_nodemap *nodemap;
132 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
133 nodemap_getref(nodemap);
136 static void nodemap_hs_put_locked(cfs_hash_t *hs,
137 cfs_hlist_node_t *hnode)
139 struct lu_nodemap *nodemap;
141 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
142 nodemap_putref(nodemap);
145 static cfs_hash_ops_t nodemap_hash_operations = {
146 .hs_hash = nodemap_hashfn,
147 .hs_key = nodemap_hs_key,
148 .hs_keycmp = nodemap_hs_keycmp,
149 .hs_object = nodemap_hs_hashobject,
150 .hs_get = nodemap_hs_get,
151 .hs_put_locked = nodemap_hs_put_locked,
154 /* end of cfs_hash functions */
157 * Helper iterator to clean up nodemap on module exit.
159 * \param hs hash structure
160 * \param bd bucket descriptor
161 * \param hnode hash node
162 * \param data not used here
164 static int nodemap_cleanup_iter_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
165 cfs_hlist_node_t *hnode, void *data)
167 struct lu_nodemap *nodemap;
169 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
170 nodemap_putref(nodemap);
176 * Walk the nodemap_hash and remove all nodemaps.
178 void nodemap_cleanup_all(void)
180 cfs_hash_for_each_safe(nodemap_hash, nodemap_cleanup_iter_cb, NULL);
181 cfs_hash_putref(nodemap_hash);
185 * Initialize nodemap_hash
188 * \retval -ENOMEM cannot create hash
190 static int nodemap_init_hash(void)
192 nodemap_hash = cfs_hash_create("NODEMAP", HASH_NODEMAP_CUR_BITS,
193 HASH_NODEMAP_MAX_BITS,
194 HASH_NODEMAP_BKT_BITS, 0,
197 &nodemap_hash_operations,
200 if (nodemap_hash == NULL) {
201 CERROR("cannot create nodemap_hash table\n");
209 * Check for valid nodemap name
211 * \param name nodemap name
213 * \retval false invalid
215 static bool nodemap_name_is_valid(const char *name)
217 if (strlen(name) > LUSTRE_NODEMAP_NAME_LENGTH ||
221 for (; *name != '\0'; name++) {
222 if (!isalnum(*name) && *name != '_')
231 * Look nodemap up in the nodemap hash
233 * \param name name of nodemap
234 * \param nodemap found nodemap or NULL
235 * \retval lu_nodemap named nodemap
236 * \retval NULL nodemap doesn't exist
238 static int nodemap_lookup(const char *name, struct lu_nodemap **nodemap)
244 if (!nodemap_name_is_valid(name))
245 GOTO(out, rc = -EINVAL);
247 *nodemap = cfs_hash_lookup(nodemap_hash, name);
248 if (*nodemap == NULL)
256 * classify the nid into the proper nodemap
258 * \param nid nid to classify
259 * \retval nodemap nodemap containing the nid
260 * \retval default_nodemap default nodemap
262 struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid)
264 struct lu_nid_range *range;
266 range = range_search(nid);
268 return range->rn_nodemap;
270 return default_nodemap;
272 EXPORT_SYMBOL(nodemap_classify_nid);
275 * simple check for default nodemap
277 static bool is_default_nodemap(const struct lu_nodemap *nodemap)
279 return nodemap->nm_id == 0;
283 * parse a nodemap range string into two nids
285 * \param range_str string to parse
286 * \param range[2] array of two nids
287 * \reyval 0 on success
289 int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
291 char buf[LNET_NIDSTR_SIZE * 2 + 2];
297 snprintf(buf, sizeof(buf), "%s", range_str);
299 start_nidstr = strsep(&ptr, ":");
300 end_nidstr = strsep(&ptr, ":");
302 if (start_nidstr == NULL || end_nidstr == NULL)
303 GOTO(out, rc = -EINVAL);
305 range[0] = libcfs_str2nid(start_nidstr);
306 range[1] = libcfs_str2nid(end_nidstr);
312 EXPORT_SYMBOL(nodemap_parse_range);
315 * add nid range to nodemap
316 * \param name nodemap name
317 * \param range_st string containing nid range
318 * \retval 0 on success
320 * add an range to the global range tree and attached the
321 * range to the named nodemap.
323 int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
325 struct lu_nodemap *nodemap = NULL;
326 struct lu_nid_range *range;
329 rc = nodemap_lookup(name, &nodemap);
330 if (nodemap == NULL || is_default_nodemap(nodemap))
331 GOTO(out, rc = -EINVAL);
333 range = range_create(nid[0], nid[1], nodemap);
335 GOTO(out_putref, rc = -ENOMEM);
337 rc = range_insert(range);
339 CERROR("cannot insert nodemap range into '%s': rc = %d\n",
340 nodemap->nm_name, rc);
341 list_del(&range->rn_list);
342 range_destroy(range);
343 GOTO(out_putref, rc = -ENOMEM);
346 list_add(&range->rn_list, &nodemap->nm_ranges);
349 nodemap_putref(nodemap);
353 EXPORT_SYMBOL(nodemap_add_range);
357 * \param name nodemap name
358 * \param range_str string containing range
359 * \retval 0 on success
361 * Delete range from global range tree, and remove it
362 * from the list in the associated nodemap.
364 int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
366 struct lu_nodemap *nodemap;
367 struct lu_nid_range *range;
370 rc = nodemap_lookup(name, &nodemap);
371 if (nodemap == NULL || is_default_nodemap(nodemap))
372 GOTO(out, rc = -EINVAL);
374 range = range_find(nid[0], nid[1]);
376 GOTO(out_putref, rc = -EINVAL);
381 nodemap_putref(nodemap);
385 EXPORT_SYMBOL(nodemap_del_range);
388 * Nodemap constructor
390 * Creates an lu_nodemap structure and assigns sane default
391 * member values. If this is the default nodemap, the defaults
392 * are the most restictive in xterms of mapping behavior. Otherwise
393 * the default flags should be inherited from the default nodemap.
394 * The adds nodemap to nodemap_hash.
396 * \param name name of nodemap
397 * \param is_default true if default nodemap
399 * \retval -EINVAL invalid nodemap name
400 * \retval -EEXIST nodemap already exists
401 * \retval -ENOMEM cannot allocate memory for nodemap
403 static int nodemap_create(const char *name, bool is_default)
405 struct lu_nodemap *nodemap = NULL;
408 rc = nodemap_lookup(name, &nodemap);
413 nodemap_putref(nodemap);
414 GOTO(out, rc = -EEXIST);
416 OBD_ALLOC_PTR(nodemap);
418 if (nodemap == NULL) {
419 CERROR("cannot allocate memory (%zu bytes)"
420 "for nodemap '%s'\n", sizeof(*nodemap),
422 GOTO(out, rc = -ENOMEM);
425 snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
427 INIT_LIST_HEAD(&(nodemap->nm_ranges));
428 nodemap->nm_local_to_remote_uidmap = RB_ROOT;
429 nodemap->nm_remote_to_local_uidmap = RB_ROOT;
430 nodemap->nm_local_to_remote_gidmap = RB_ROOT;
431 nodemap->nm_remote_to_local_gidmap = RB_ROOT;
434 nodemap->nm_id = LUSTRE_NODEMAP_DEFAULT_ID;
435 nodemap->nmf_trust_client_ids = 0;
436 nodemap->nmf_allow_root_access = 0;
437 nodemap->nmf_block_lookups = 0;
439 nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
440 nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
442 lprocfs_nodemap_register(name, is_default, nodemap);
444 default_nodemap = nodemap;
446 nodemap->nm_id = atomic_inc_return(&nodemap_highest_id);
447 nodemap->nmf_trust_client_ids =
448 default_nodemap->nmf_trust_client_ids;
449 nodemap->nmf_allow_root_access =
450 default_nodemap->nmf_allow_root_access;
451 nodemap->nmf_block_lookups =
452 default_nodemap->nmf_block_lookups;
454 nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
455 nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
457 lprocfs_nodemap_register(name, is_default, nodemap);
460 atomic_set(&nodemap->nm_refcount, 1);
461 rc = cfs_hash_add_unique(nodemap_hash, name, &nodemap->nm_hash);
466 CERROR("cannot add nodemap: '%s': rc = %d\n", name, rc);
467 nodemap_destroy(nodemap);
474 * update flag to turn on or off nodemap functions
475 * \param name nodemap name
476 * \param admin_string string containing updated value
477 * \retval 0 on success
479 * Update admin flag to turn on or off nodemap functions.
481 int nodemap_set_allow_root(const char *name, bool allow_root)
483 struct lu_nodemap *nodemap = NULL;
486 rc = nodemap_lookup(name, &nodemap);
488 GOTO(out, rc = -ENOENT);
490 nodemap->nmf_allow_root_access = allow_root;
491 nodemap_putref(nodemap);
495 EXPORT_SYMBOL(nodemap_set_allow_root);
498 * updated trust_client_ids flag for nodemap
500 * \param name nodemap name
501 * \param trust_string new value for trust flag
502 * \retval 0 on success
504 * Update the trust_client_ids flag for a nodemap.
506 int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids)
508 struct lu_nodemap *nodemap = NULL;
511 rc = nodemap_lookup(name, &nodemap);
513 GOTO(out, rc = -ENOENT);
515 nodemap->nmf_trust_client_ids = trust_client_ids;
516 nodemap_putref(nodemap);
520 EXPORT_SYMBOL(nodemap_set_trust_client_ids);
523 * update the squash_uid for a nodemap
525 * \param name nodemap name
526 * \param uid_string string containing new squash_uid value
527 * \retval 0 on success
529 * Update the squash_uid for a nodemap. The squash_uid is the uid
530 * that the all client uids are mapped to if nodemap is active,
531 * the trust_client_ids flag is not set, and the uid is not in
534 int nodemap_set_squash_uid(const char *name, uid_t uid)
536 struct lu_nodemap *nodemap = NULL;
539 rc = nodemap_lookup(name, &nodemap);
541 GOTO(out, rc = -ENOENT);
543 nodemap->nm_squash_uid = uid;
544 nodemap_putref(nodemap);
548 EXPORT_SYMBOL(nodemap_set_squash_uid);
551 * update the squash_gid for a nodemap
553 * \param name nodemap name
554 * \param gid_string string containing new squash_gid value
555 * \retval 0 on success
557 * Update the squash_gid for a nodemap. The squash_uid is the gid
558 * that the all client gids are mapped to if nodemap is active,
559 * the trust_client_ids flag is not set, and the gid is not in
562 int nodemap_set_squash_gid(const char *name, gid_t gid)
564 struct lu_nodemap *nodemap = NULL;
567 rc = nodemap_lookup(name, &nodemap);
569 GOTO(out, rc = -ENOENT);
571 nodemap->nm_squash_gid = gid;
572 nodemap_putref(nodemap);
576 EXPORT_SYMBOL(nodemap_set_squash_gid);
581 * \param name name of nodemap
583 * \retval -EINVAL invalid nodemap name
584 * \retval -EEXIST nodemap already exists
585 * \retval -ENOMEM cannot allocate memory for nodemap
587 int nodemap_add(const char *name)
589 return nodemap_create(name, 0);
591 EXPORT_SYMBOL(nodemap_add);
596 * \param name name of nodemmap
598 * \retval -EINVAL invalid input
599 * \retval -ENOENT no existing nodemap
601 int nodemap_del(const char *name)
603 struct lu_nodemap *nodemap;
606 if (strcmp(name, DEFAULT_NODEMAP) == 0)
607 GOTO(out, rc = -EINVAL);
609 nodemap = cfs_hash_del_key(nodemap_hash, name);
611 GOTO(out, rc = -ENOENT);
613 nodemap_putref(nodemap);
617 EXPORT_SYMBOL(nodemap_del);
620 * Cleanup nodemap module on exit
622 static void nodemap_mod_exit(void)
624 nodemap_cleanup_all();
625 lprocfs_remove(&proc_lustre_nodemap_root);
629 * Initialize the nodemap module
631 static int __init nodemap_mod_init(void)
635 rc = nodemap_init_hash();
639 nodemap_procfs_init();
640 rc = nodemap_create(DEFAULT_NODEMAP, 1);
649 MODULE_LICENSE("GPL");
650 MODULE_DESCRIPTION("Lustre Client Nodemap Management Module");
651 MODULE_AUTHOR("Joshua Walgenbach <jjw@iu.edu>");
653 module_init(nodemap_mod_init);
654 module_exit(nodemap_mod_exit);