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