Whamcloud - gitweb
LU-4969 nodemap: nodemap key hash comparison
[fs/lustre-release.git] / lustre / nodemap / nodemap_handler.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (C) 2013, Trustees of Indiana University
24  * Author: Joshua Walgenbach <jjw@iu.edu>
25  */
26 #include <linux/module.h>
27 #include <lustre_net.h>
28 #include "nodemap_internal.h"
29
30 #define HASH_NODEMAP_BKT_BITS 3
31 #define HASH_NODEMAP_CUR_BITS 3
32 #define HASH_NODEMAP_MAX_BITS 7
33
34 #define DEFAULT_NODEMAP "default"
35
36 /* nodemap proc root proc directory under fs/lustre */
37 struct proc_dir_entry *proc_lustre_nodemap_root;
38
39 /* Highest numerical lu_nodemap.nm_id defined */
40 static atomic_t nodemap_highest_id;
41
42 /* Simple flag to determine if nodemaps are active */
43 bool nodemap_active;
44
45 /**
46  * pointer to default nodemap kept to keep from
47  * lookup it up in the hash since it is needed
48  * more often
49  */
50 static struct lu_nodemap *default_nodemap;
51
52 /**
53  * Hash keyed on nodemap name containing all
54  * nodemaps
55  */
56 static cfs_hash_t *nodemap_hash;
57
58 /**
59  * Nodemap destructor
60  *
61  * \param       nodemap         nodemap to destroy
62  */
63 static void nodemap_destroy(struct lu_nodemap *nodemap)
64 {
65         struct lu_nid_range *range;
66         struct lu_nid_range *temp;
67
68         list_for_each_entry_safe(range, temp, &nodemap->nm_ranges,
69                                  rn_list) {
70                 range_delete(range);
71         }
72
73         idmap_delete_tree(nodemap);
74
75         lprocfs_remove(&nodemap->nm_proc_entry);
76         OBD_FREE_PTR(nodemap);
77 }
78
79 /**
80  * Functions used for the cfs_hash
81  */
82 static void nodemap_getref(struct lu_nodemap *nodemap)
83 {
84         CDEBUG(D_INFO, "nodemap %p\n", nodemap);
85         atomic_inc(&nodemap->nm_refcount);
86 }
87
88 void nodemap_putref(struct lu_nodemap *nodemap)
89 {
90         LASSERT(nodemap != NULL);
91         LASSERT(atomic_read(&nodemap->nm_refcount) > 0);
92
93         if (atomic_dec_and_test(&nodemap->nm_refcount))
94                 nodemap_destroy(nodemap);
95 }
96
97 static __u32 nodemap_hashfn(cfs_hash_t *hash_body,
98                             const void *key, unsigned mask)
99 {
100         const struct lu_nodemap *nodemap = key;
101
102         return cfs_hash_djb2_hash(nodemap->nm_name, strlen(nodemap->nm_name),
103                                   mask);
104 }
105
106 static void *nodemap_hs_key(cfs_hlist_node_t *hnode)
107 {
108         struct lu_nodemap *nodemap;
109
110         nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
111
112         return nodemap->nm_name;
113 }
114
115 static int nodemap_hs_keycmp(const void *key,
116                              cfs_hlist_node_t *compared_hnode)
117 {
118         char *nodemap_name;
119
120         nodemap_name = nodemap_hs_key(compared_hnode);
121
122         return !strcmp(key, nodemap_name);
123 }
124
125 static void *nodemap_hs_hashobject(cfs_hlist_node_t *hnode)
126 {
127         return cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
128 }
129
130 static void nodemap_hs_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode)
131 {
132         struct lu_nodemap *nodemap;
133
134         nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
135         nodemap_getref(nodemap);
136 }
137
138 static void nodemap_hs_put_locked(cfs_hash_t *hs,
139                                   cfs_hlist_node_t *hnode)
140 {
141         struct lu_nodemap *nodemap;
142
143         nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
144         nodemap_putref(nodemap);
145 }
146
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,
154 };
155
156 /* end of cfs_hash functions */
157
158 /**
159  * Helper iterator to clean up nodemap on module exit.
160  *
161  * \param       hs              hash structure
162  * \param       bd              bucket descriptor
163  * \param       hnode           hash node
164  * \param       data            not used here
165  */
166 static int nodemap_cleanup_iter_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
167                                    cfs_hlist_node_t *hnode, void *data)
168 {
169         struct lu_nodemap *nodemap;
170
171         nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
172         nodemap_putref(nodemap);
173
174         return 0;
175 }
176
177 /**
178  * Walk the nodemap_hash and remove all nodemaps.
179  */
180 void nodemap_cleanup_all(void)
181 {
182         cfs_hash_for_each_safe(nodemap_hash, nodemap_cleanup_iter_cb, NULL);
183         cfs_hash_putref(nodemap_hash);
184 }
185
186 /**
187  * Initialize nodemap_hash
188  *
189  * \retval      0               success
190  * \retval      -ENOMEM         cannot create hash
191  */
192 static int nodemap_init_hash(void)
193 {
194         nodemap_hash = cfs_hash_create("NODEMAP", HASH_NODEMAP_CUR_BITS,
195                                        HASH_NODEMAP_MAX_BITS,
196                                        HASH_NODEMAP_BKT_BITS, 0,
197                                        CFS_HASH_MIN_THETA,
198                                        CFS_HASH_MAX_THETA,
199                                        &nodemap_hash_operations,
200                                        CFS_HASH_DEFAULT);
201
202         if (nodemap_hash == NULL) {
203                 CERROR("cannot create nodemap_hash table\n");
204                 return -ENOMEM;
205         }
206
207         return 0;
208 }
209
210 /**
211  * Check for valid nodemap name
212  *
213  * \param       name            nodemap name
214  * \retval      true            valid
215  * \retval      false           invalid
216  */
217 static bool nodemap_name_is_valid(const char *name)
218 {
219         if (strlen(name) > LUSTRE_NODEMAP_NAME_LENGTH ||
220             strlen(name) == 0)
221                 return false;
222
223         for (; *name != '\0'; name++) {
224                 if (!isalnum(*name) && *name != '_')
225                         return false;
226         }
227         return true;
228 }
229
230 /**
231  * Nodemap lookup
232  *
233  * Look nodemap up in the nodemap hash
234  *
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
239  */
240 static int nodemap_lookup(const char *name, struct lu_nodemap **nodemap)
241 {
242         int rc = 0;
243
244         *nodemap = NULL;
245
246         if (!nodemap_name_is_valid(name))
247                 GOTO(out, rc = -EINVAL);
248
249         *nodemap = cfs_hash_lookup(nodemap_hash, name);
250         if (*nodemap == NULL)
251                 rc = -ENOENT;
252
253 out:
254         return rc;
255 }
256
257 /**
258  * classify the nid into the proper nodemap
259  *
260  * \param       nid                     nid to classify
261  * \retval      nodemap                 nodemap containing the nid
262  * \retval      default_nodemap         default nodemap
263  */
264 struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid)
265 {
266         struct lu_nid_range     *range;
267
268         range = range_search(nid);
269         if (range != NULL)
270                 return range->rn_nodemap;
271
272         return default_nodemap;
273 }
274 EXPORT_SYMBOL(nodemap_classify_nid);
275
276 /**
277  * simple check for default nodemap
278  */
279 static bool is_default_nodemap(const struct lu_nodemap *nodemap)
280 {
281         return nodemap->nm_id == 0;
282 }
283
284 /**
285  * parse a nodemap range string into two nids
286  *
287  * \param       range_str               string to parse
288  * \param       range[2]                array of two nids
289  * \reyval      0 on success
290  */
291 int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
292 {
293         char    buf[LNET_NIDSTR_SIZE * 2 + 2];
294         char    *ptr = NULL;
295         char    *start_nidstr;
296         char    *end_nidstr;
297         int     rc = 0;
298
299         snprintf(buf, sizeof(buf), "%s", range_str);
300         ptr = buf;
301         start_nidstr = strsep(&ptr, ":");
302         end_nidstr = strsep(&ptr, ":");
303
304         if (start_nidstr == NULL || end_nidstr == NULL)
305                 GOTO(out, rc = -EINVAL);
306
307         range[0] = libcfs_str2nid(start_nidstr);
308         range[1] = libcfs_str2nid(end_nidstr);
309
310 out:
311         return rc;
312
313 }
314 EXPORT_SYMBOL(nodemap_parse_range);
315
316 /**
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
319  *
320  * \param       idmap_str               map string
321  * \param       idmap                   array[2] of __u32
322  *
323  * \retval      0 on success
324  */
325 int nodemap_parse_idmap(const char *idmap_str, __u32 idmap[2])
326 {
327         char    *end;
328
329         if (idmap_str == NULL)
330                 return -EINVAL;
331
332         idmap[0] = simple_strtoul(idmap_str, &end, 10);
333         if (end == idmap_str || *end != ':')
334                 return -EINVAL;
335
336         idmap_str = end + 1;
337         idmap[1] = simple_strtoul(idmap_str, &end, 10);
338         if (end == idmap_str)
339                 return -EINVAL;
340
341         return 0;
342 }
343 EXPORT_SYMBOL(nodemap_parse_idmap);
344
345 /**
346  * add an idmap to the proper nodemap trees
347  *
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
353  *
354  * \retval      0 on success
355  */
356 int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
357                       const __u32 map[2])
358 {
359         struct lu_nodemap       *nodemap = NULL;
360         struct lu_idmap         *idmap;
361         int                     rc = 0;
362
363         rc = nodemap_lookup(name, &nodemap);
364         if (nodemap == NULL || is_default_nodemap(nodemap))
365                 GOTO(out, rc = -EINVAL);
366
367         idmap = idmap_create(map[0], map[1]);
368         if (idmap == NULL)
369                 GOTO(out_putref, rc = -ENOMEM);
370
371         idmap_insert(id_type, idmap, nodemap);
372
373 out_putref:
374         nodemap_putref(nodemap);
375 out:
376         return rc;
377 }
378 EXPORT_SYMBOL(nodemap_add_idmap);
379
380 /**
381  * delete idmap from proper nodemap tree
382  *
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
388  *
389  * \retval      0 on success
390  */
391 int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
392                       const __u32 map[2])
393 {
394         struct lu_nodemap       *nodemap = NULL;
395         struct lu_idmap         *idmap = NULL;
396         int                     rc = 0;
397
398         rc = nodemap_lookup(name, &nodemap);
399         if (nodemap == NULL || is_default_nodemap(nodemap))
400                 GOTO(out, rc = -EINVAL);
401
402         idmap = idmap_search(nodemap, NODEMAP_CLIENT_TO_FS, id_type,
403                              map[0]);
404         if (idmap == NULL)
405                 GOTO(out_putref, rc = -EINVAL);
406
407         idmap_delete(id_type, idmap, nodemap);
408
409 out_putref:
410         nodemap_putref(nodemap);
411 out:
412         return rc;
413 }
414 EXPORT_SYMBOL(nodemap_del_idmap);
415
416 /**
417  * mapping function for nodemap idmaps
418  *
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
424  *
425  * \retval      mapped id according to the rules below.
426  *
427  * if the nodemap_active is false, just return the passed id without mapping
428  *
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.
431  *
432  * if the nodemap is configured to trusted the ids from the client system, just
433  * return the passwd id without mapping.
434  *
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.
437  *
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.
440  */
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)
444 {
445         struct lu_idmap         *idmap = NULL;
446
447         if (!nodemap_active)
448                 goto out;
449
450         if (id == 0) {
451                 if (nodemap->nmf_allow_root_access)
452                         goto out;
453                 else
454                         goto squash;
455         }
456
457         if (nodemap->nmf_trust_client_ids)
458                 goto out;
459
460         if (is_default_nodemap(nodemap))
461                 goto squash;
462
463         idmap = idmap_search(nodemap, tree_type, id_type, id);
464         if (idmap == NULL)
465                 goto squash;
466
467         if (tree_type == NODEMAP_FS_TO_CLIENT)
468                 return idmap->id_client;
469
470         return idmap->id_fs;
471
472 squash:
473         if (id_type == NODEMAP_UID)
474                 return nodemap->nm_squash_uid;
475         else
476                 return nodemap->nm_squash_gid;
477 out:
478         return id;
479 }
480 EXPORT_SYMBOL(nodemap_map_id);
481
482 /*
483  * add nid range to nodemap
484  * \param       name            nodemap name
485  * \param       range_st        string containing nid range
486  * \retval      0 on success
487  *
488  * add an range to the global range tree and attached the
489  * range to the named nodemap.
490  */
491 int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
492 {
493         struct lu_nodemap       *nodemap = NULL;
494         struct lu_nid_range     *range;
495         int rc;
496
497         rc = nodemap_lookup(name, &nodemap);
498         if (nodemap == NULL || is_default_nodemap(nodemap))
499                 GOTO(out, rc = -EINVAL);
500
501         range = range_create(nid[0], nid[1], nodemap);
502         if (range == NULL)
503                 GOTO(out_putref, rc = -ENOMEM);
504
505         rc = range_insert(range);
506         if (rc != 0) {
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);
512         }
513
514         list_add(&range->rn_list, &nodemap->nm_ranges);
515
516 out_putref:
517         nodemap_putref(nodemap);
518 out:
519         return rc;
520 }
521 EXPORT_SYMBOL(nodemap_add_range);
522
523 /**
524  * delete a range
525  * \param       name            nodemap name
526  * \param       range_str       string containing range
527  * \retval      0 on success
528  *
529  * Delete range from global range tree, and remove it
530  * from the list in the associated nodemap.
531  */
532 int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
533 {
534         struct lu_nodemap       *nodemap;
535         struct lu_nid_range     *range;
536         int                     rc = 0;
537
538         rc = nodemap_lookup(name, &nodemap);
539         if (nodemap == NULL || is_default_nodemap(nodemap))
540                 GOTO(out, rc = -EINVAL);
541
542         range = range_find(nid[0], nid[1]);
543         if (range == NULL)
544                 GOTO(out_putref, rc = -EINVAL);
545
546         range_delete(range);
547
548 out_putref:
549         nodemap_putref(nodemap);
550 out:
551         return rc;
552 }
553 EXPORT_SYMBOL(nodemap_del_range);
554
555 /**
556  * Nodemap constructor
557  *
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.
563  *
564  * \param       name            name of nodemap
565  * \param       is_default      true if default nodemap
566  * \retval      0               success
567  * \retval      -EINVAL         invalid nodemap name
568  * \retval      -EEXIST         nodemap already exists
569  * \retval      -ENOMEM         cannot allocate memory for nodemap
570  */
571 static int nodemap_create(const char *name, bool is_default)
572 {
573         struct  lu_nodemap *nodemap = NULL;
574         int     rc = 0;
575
576         rc = nodemap_lookup(name, &nodemap);
577         if (rc == -EINVAL)
578                 goto out;
579
580         if (rc != -ENOENT) {
581                 nodemap_putref(nodemap);
582                 GOTO(out, rc = -EEXIST);
583         }
584         OBD_ALLOC_PTR(nodemap);
585
586         if (nodemap == NULL) {
587                 CERROR("cannot allocate memory (%zu bytes)"
588                        "for nodemap '%s'\n", sizeof(*nodemap),
589                        name);
590                 GOTO(out, rc = -ENOMEM);
591         }
592
593         snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
594
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;
600
601         if (is_default) {
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;
606
607                 nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
608                 nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
609
610                 lprocfs_nodemap_register(name, is_default, nodemap);
611
612                 default_nodemap = nodemap;
613         } else {
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;
621
622                 nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
623                 nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
624
625                 lprocfs_nodemap_register(name, is_default, nodemap);
626         }
627
628         atomic_set(&nodemap->nm_refcount, 1);
629         rc = cfs_hash_add_unique(nodemap_hash, name, &nodemap->nm_hash);
630
631         if (rc == 0)
632                 goto out;
633
634         CERROR("cannot add nodemap: '%s': rc = %d\n", name, rc);
635         nodemap_destroy(nodemap);
636
637 out:
638         return rc;
639 }
640
641 /**
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
646  *
647  * Update admin flag to turn on or off nodemap functions.
648  */
649 int nodemap_set_allow_root(const char *name, bool allow_root)
650 {
651         struct lu_nodemap       *nodemap = NULL;
652         int                     rc = 0;
653
654         rc = nodemap_lookup(name, &nodemap);
655         if (nodemap == NULL)
656                 GOTO(out, rc = -ENOENT);
657
658         nodemap->nmf_allow_root_access = allow_root;
659         nodemap_putref(nodemap);
660 out:
661         return rc;
662 }
663 EXPORT_SYMBOL(nodemap_set_allow_root);
664
665 /**
666  * updated trust_client_ids flag for nodemap
667  *
668  * \param       name            nodemap name
669  * \param       trust_string    new value for trust flag
670  * \retval      0 on success
671  *
672  * Update the trust_client_ids flag for a nodemap.
673  */
674 int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids)
675 {
676         struct lu_nodemap       *nodemap = NULL;
677         int                     rc = 0;
678
679         rc = nodemap_lookup(name, &nodemap);
680         if (nodemap == NULL)
681                 GOTO(out, rc = -ENOENT);
682
683         nodemap->nmf_trust_client_ids = trust_client_ids;
684         nodemap_putref(nodemap);
685 out:
686         return rc;
687 }
688 EXPORT_SYMBOL(nodemap_set_trust_client_ids);
689
690 /**
691  * update the squash_uid for a nodemap
692  *
693  * \param       name            nodemap name
694  * \param       uid_string      string containing new squash_uid value
695  * \retval      0 on success
696  *
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
700  * the idmap tree.
701  */
702 int nodemap_set_squash_uid(const char *name, uid_t uid)
703 {
704         struct lu_nodemap       *nodemap = NULL;
705         int                     rc = 0;
706
707         rc = nodemap_lookup(name, &nodemap);
708         if (nodemap == NULL)
709                 GOTO(out, rc = -ENOENT);
710
711         nodemap->nm_squash_uid = uid;
712         nodemap_putref(nodemap);
713 out:
714         return rc;
715 }
716 EXPORT_SYMBOL(nodemap_set_squash_uid);
717
718 /**
719  * update the squash_gid for a nodemap
720  *
721  * \param       name            nodemap name
722  * \param       gid_string      string containing new squash_gid value
723  * \retval      0 on success
724  *
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
728  * the idmap tree.
729  */
730 int nodemap_set_squash_gid(const char *name, gid_t gid)
731 {
732         struct lu_nodemap       *nodemap = NULL;
733         int                     rc = 0;
734
735         rc = nodemap_lookup(name, &nodemap);
736         if (nodemap == NULL)
737                 GOTO(out, rc = -ENOENT);
738
739         nodemap->nm_squash_gid = gid;
740         nodemap_putref(nodemap);
741 out:
742         return rc;
743 }
744 EXPORT_SYMBOL(nodemap_set_squash_gid);
745
746 /**
747  * Add a nodemap
748  *
749  * \param       name            name of nodemap
750  * \retval      0               success
751  * \retval      -EINVAL         invalid nodemap name
752  * \retval      -EEXIST         nodemap already exists
753  * \retval      -ENOMEM         cannot allocate memory for nodemap
754  */
755 int nodemap_add(const char *name)
756 {
757         return nodemap_create(name, 0);
758 }
759 EXPORT_SYMBOL(nodemap_add);
760
761 /**
762  * Delete a nodemap
763  *
764  * \param       name            name of nodemmap
765  * \retval      0               success
766  * \retval      -EINVAL         invalid input
767  * \retval      -ENOENT         no existing nodemap
768  */
769 int nodemap_del(const char *name)
770 {
771         struct  lu_nodemap *nodemap;
772         int     rc = 0;
773
774         if (strcmp(name, DEFAULT_NODEMAP) == 0)
775                 GOTO(out, rc = -EINVAL);
776
777         nodemap = cfs_hash_del_key(nodemap_hash, name);
778         if (nodemap == NULL)
779                 GOTO(out, rc = -ENOENT);
780
781         nodemap_putref(nodemap);
782 out:
783         return rc;
784 }
785 EXPORT_SYMBOL(nodemap_del);
786
787 /**
788  * activate nodemap functions
789  *
790  * \param       value           1 for on, 0 for off
791  */
792 void nodemap_activate(const bool value)
793 {
794         nodemap_active = value;
795 }
796 EXPORT_SYMBOL(nodemap_activate);
797
798 /**
799  * Cleanup nodemap module on exit
800  */
801 static void nodemap_mod_exit(void)
802 {
803         nodemap_cleanup_all();
804         lprocfs_remove(&proc_lustre_nodemap_root);
805 }
806
807 /**
808  * Initialize the nodemap module
809  */
810 static int __init nodemap_mod_init(void)
811 {
812         int rc = 0;
813
814         rc = nodemap_init_hash();
815         if (rc != 0)
816                 goto cleanup;
817
818         nodemap_procfs_init();
819         rc = nodemap_create(DEFAULT_NODEMAP, 1);
820
821 cleanup:
822         if (rc != 0)
823                 nodemap_mod_exit();
824
825         return rc;
826 }
827
828 MODULE_LICENSE("GPL");
829 MODULE_DESCRIPTION("Lustre Client Nodemap Management Module");
830 MODULE_AUTHOR("Joshua Walgenbach <jjw@iu.edu>");
831
832 module_init(nodemap_mod_init);
833 module_exit(nodemap_mod_exit);