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 lprocfs_remove(&(nodemap->nm_proc_entry));
66 OBD_FREE_PTR(nodemap);
70 * Functions used for the cfs_hash
72 static void nodemap_getref(struct lu_nodemap *nodemap)
74 CDEBUG(D_INFO, "nodemap %p\n", nodemap);
75 atomic_inc(&nodemap->nm_refcount);
78 void nodemap_putref(struct lu_nodemap *nodemap)
80 LASSERT(nodemap != NULL);
81 LASSERT(cfs_atomic_read(&nodemap->nm_refcount) > 0);
83 if (atomic_dec_and_test(&nodemap->nm_refcount))
84 nodemap_destroy(nodemap);
87 static __u32 nodemap_hashfn(cfs_hash_t *hash_body,
88 const void *key, unsigned mask)
90 const struct lu_nodemap *nodemap = key;
92 return cfs_hash_djb2_hash(nodemap->nm_name, strlen(nodemap->nm_name),
96 static void *nodemap_hs_key(cfs_hlist_node_t *hnode)
98 struct lu_nodemap *nodemap;
100 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
101 return nodemap->nm_name;
104 static int nodemap_hs_keycmp(const void *key,
105 cfs_hlist_node_t *compared_hnode)
107 struct lu_nodemap *nodemap;
109 nodemap = nodemap_hs_key(compared_hnode);
110 return !strcmp(key, nodemap->nm_name);
113 static void *nodemap_hs_hashobject(cfs_hlist_node_t *hnode)
115 return cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
118 static void nodemap_hs_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
120 struct lu_nodemap *nodemap;
122 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
123 nodemap_getref(nodemap);
126 static void nodemap_hs_put_locked(cfs_hash_t *hs,
127 cfs_hlist_node_t *hnode)
129 struct lu_nodemap *nodemap;
131 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
132 nodemap_putref(nodemap);
135 static cfs_hash_ops_t nodemap_hash_operations = {
136 .hs_hash = nodemap_hashfn,
137 .hs_key = nodemap_hs_key,
138 .hs_keycmp = nodemap_hs_keycmp,
139 .hs_object = nodemap_hs_hashobject,
140 .hs_get = nodemap_hs_get,
141 .hs_put_locked = nodemap_hs_put_locked,
144 /* end of cfs_hash functions */
147 * Helper iterator to clean up nodemap on module exit.
149 * \param hs hash structure
150 * \param bd bucket descriptor
151 * \param hnode hash node
152 * \param data not used here
154 static int nodemap_cleanup_iter_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
155 cfs_hlist_node_t *hnode, void *data)
157 struct lu_nodemap *nodemap;
159 nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
160 nodemap_putref(nodemap);
166 * Walk the nodemap_hash and remove all nodemaps.
168 void nodemap_cleanup_all(void)
170 cfs_hash_for_each_safe(nodemap_hash, nodemap_cleanup_iter_cb, NULL);
171 cfs_hash_putref(nodemap_hash);
175 * Initialize nodemap_hash
178 * \retval -ENOMEM cannot create hash
180 static int nodemap_init_hash(void)
182 nodemap_hash = cfs_hash_create("NODEMAP", HASH_NODEMAP_CUR_BITS,
183 HASH_NODEMAP_MAX_BITS,
184 HASH_NODEMAP_BKT_BITS, 0,
187 &nodemap_hash_operations,
190 if (nodemap_hash == NULL) {
191 CERROR("cannot create nodemap_hash table\n");
199 * Check for valid nodemap name
201 * \param name nodemap name
203 * \retval false invalid
205 static bool nodemap_name_is_valid(const char *name)
207 for (; *name != '\0'; name++) {
208 if (!isalnum(*name) && *name != '_')
217 * Look nodemap up in the nodemap hash
219 * \param name name of nodemap
220 * \paramA nodemap found nodemap or NULL
221 * \retval lu_nodemap named nodemap
222 * \retval NULL nodemap doesn't exist
224 static int nodemap_lookup(const char *name, struct lu_nodemap **nodemap)
228 if (!nodemap_name_is_valid(name))
229 GOTO(out, rc = -EINVAL);
231 *nodemap = cfs_hash_lookup(nodemap_hash, name);
238 * Nodemap constructor
240 * Creates an lu_nodemap structure and assigns sane default
241 * member values. If this is the default nodemap, the defaults
242 * are the most restictive in xterms of mapping behavior. Otherwise
243 * the default flags should be inherited from the default nodemap.
244 * The adds nodemap to nodemap_hash.
246 * \param name name of nodemap
247 * \param is_default true if default nodemap
249 * \retval -EINVAL invalid nodemap name
250 * \retval -EEXIST nodemap already exists
251 * \retval -ENOMEM cannot allocate memory for nodemap
253 static int nodemap_create(const char *name, bool is_default)
255 struct lu_nodemap *nodemap = NULL;
258 rc = nodemap_lookup(name, &nodemap);
262 if (nodemap != NULL) {
263 nodemap_putref(nodemap);
264 GOTO(out, rc = -EEXIST);
267 OBD_ALLOC_PTR(nodemap);
269 if (nodemap == NULL) {
270 CERROR("cannot allocate memory (%zu bytes)"
271 "for nodemap '%s'\n", sizeof(*nodemap),
273 GOTO(out, rc = -ENOMEM);
276 snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
278 INIT_LIST_HEAD(&(nodemap->nm_ranges));
279 nodemap->nm_local_to_remote_uidmap = RB_ROOT;
280 nodemap->nm_remote_to_local_uidmap = RB_ROOT;
281 nodemap->nm_local_to_remote_gidmap = RB_ROOT;
282 nodemap->nm_remote_to_local_gidmap = RB_ROOT;
285 nodemap->nm_id = LUSTRE_NODEMAP_DEFAULT_ID;
286 nodemap->nmf_trust_client_ids = 0;
287 nodemap->nmf_allow_root_access = 0;
288 nodemap->nmf_block_lookups = 0;
290 nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
291 nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
293 lprocfs_nodemap_register(name, is_default, nodemap);
295 default_nodemap = nodemap;
297 nodemap->nm_id = atomic_inc_return(&nodemap_highest_id);
298 nodemap->nmf_trust_client_ids =
299 default_nodemap->nmf_trust_client_ids;
300 nodemap->nmf_allow_root_access =
301 default_nodemap->nmf_allow_root_access;
302 nodemap->nmf_block_lookups =
303 default_nodemap->nmf_block_lookups;
305 nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
306 nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
308 lprocfs_nodemap_register(name, is_default, nodemap);
311 atomic_set(&nodemap->nm_refcount, 1);
312 rc = cfs_hash_add_unique(nodemap_hash, name, &nodemap->nm_hash);
317 CERROR("cannot add nodemap: '%s': rc = %d\n", name, rc);
318 nodemap_destroy(nodemap);
327 * \param name name of nodemap
329 * \retval -EINVAL invalid nodemap name
330 * \retval -EEXIST nodemap already exists
331 * \retval -ENOMEM cannot allocate memory for nodemap
333 int nodemap_add(const char *name)
335 return nodemap_create(name, 0);
337 EXPORT_SYMBOL(nodemap_add);
342 * \param name name of nodemmap
344 * \retval -EINVAL invalid input
345 * \retval -ENOENT no existing nodemap
347 int nodemap_del(const char *name)
349 struct lu_nodemap *nodemap;
352 if (strcmp(name, DEFAULT_NODEMAP) == 0)
353 GOTO(out, rc = -EINVAL);
355 nodemap = cfs_hash_del_key(nodemap_hash, name);
357 GOTO(out, rc = -ENOENT);
359 nodemap_putref(nodemap);
363 EXPORT_SYMBOL(nodemap_del);
366 * Cleanup nodemap module on exit
368 static void nodemap_mod_exit(void)
370 nodemap_cleanup_all();
371 lprocfs_remove(&proc_lustre_nodemap_root);
375 * Initialize the nodemap module
377 static int __init nodemap_mod_init(void)
381 rc = nodemap_init_hash();
385 nodemap_procfs_init();
386 rc = nodemap_create(DEFAULT_NODEMAP, 1);
395 MODULE_LICENSE("GPL");
396 MODULE_DESCRIPTION("Lustre Client Nodemap Management Module");
397 MODULE_AUTHOR("Joshua Walgenbach <jjw@iu.edu>");
399 module_init(nodemap_mod_init);
400 module_exit(nodemap_mod_exit);