Whamcloud - gitweb
LU-4647 nodemap: add mapping functionality
[fs/lustre-release.git] / lustre / ptlrpc / 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 <linux/sort.h>
28 #include <lnet/nidstr.h>
29 #include <lustre_net.h>
30 #include <lustre_acl.h>
31 #include <lustre_eacl.h>
32 #include <obd_class.h>
33 #include "nodemap_internal.h"
34
35 #define HASH_NODEMAP_BKT_BITS 3
36 #define HASH_NODEMAP_CUR_BITS 3
37 #define HASH_NODEMAP_MAX_BITS 7
38
39 #define DEFAULT_NODEMAP "default"
40
41 /* nodemap proc root proc directory under fs/lustre */
42 struct proc_dir_entry *proc_lustre_nodemap_root;
43
44 /* Highest numerical lu_nodemap.nm_id defined */
45 static atomic_t nodemap_highest_id;
46
47 /* Simple flag to determine if nodemaps are active */
48 bool nodemap_active;
49
50 /**
51  * pointer to default nodemap kept to keep from
52  * lookup it up in the hash since it is needed
53  * more often
54  */
55 static struct lu_nodemap *default_nodemap;
56
57 /**
58  * Lock required to access the range tree.
59  */
60 rwlock_t nm_range_tree_lock;
61
62 /**
63  * Hash keyed on nodemap name containing all
64  * nodemaps
65  */
66 static cfs_hash_t *nodemap_hash;
67
68 /**
69  * Nodemap destructor
70  *
71  * \param       nodemap         nodemap to destroy
72  */
73 static void nodemap_destroy(struct lu_nodemap *nodemap)
74 {
75         struct lu_nid_range *range;
76         struct lu_nid_range *range_temp;
77
78         write_lock(&nm_range_tree_lock);
79         list_for_each_entry_safe(range, range_temp, &nodemap->nm_ranges,
80                                  rn_list) {
81                 range_delete(range);
82         }
83         write_unlock(&nm_range_tree_lock);
84
85         write_lock(&nodemap->nm_idmap_lock);
86         idmap_delete_tree(nodemap);
87         write_unlock(&nodemap->nm_idmap_lock);
88         nm_member_reclassify_nodemap(nodemap);
89         if (!cfs_hash_is_empty(nodemap->nm_member_hash))
90                 CWARN("nodemap_destroy failed to reclassify all members\n");
91
92         nm_member_delete_hash(nodemap);
93
94         OBD_FREE_PTR(nodemap);
95 }
96
97 /**
98  * Functions used for the cfs_hash
99  */
100 static void nodemap_getref(struct lu_nodemap *nodemap)
101 {
102         atomic_inc(&nodemap->nm_refcount);
103 }
104
105 void nodemap_putref(struct lu_nodemap *nodemap)
106 {
107         LASSERT(nodemap != NULL);
108         LASSERT(atomic_read(&nodemap->nm_refcount) > 0);
109
110         if (atomic_dec_and_test(&nodemap->nm_refcount))
111                 nodemap_destroy(nodemap);
112 }
113
114 static __u32 nodemap_hashfn(cfs_hash_t *hash_body,
115                             const void *key, unsigned mask)
116 {
117         return cfs_hash_djb2_hash(key, strlen(key), mask);
118 }
119
120 static void *nodemap_hs_key(struct hlist_node *hnode)
121 {
122         struct lu_nodemap *nodemap;
123
124         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
125
126         return nodemap->nm_name;
127 }
128
129 static int nodemap_hs_keycmp(const void *key,
130                              struct hlist_node *compared_hnode)
131 {
132         char *nodemap_name;
133
134         nodemap_name = nodemap_hs_key(compared_hnode);
135
136         return !strcmp(key, nodemap_name);
137 }
138
139 static void *nodemap_hs_hashobject(struct hlist_node *hnode)
140 {
141         return hlist_entry(hnode, struct lu_nodemap, nm_hash);
142 }
143
144 static void nodemap_hs_get(cfs_hash_t *hs, struct hlist_node *hnode)
145 {
146         struct lu_nodemap *nodemap;
147
148         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
149         nodemap_getref(nodemap);
150 }
151
152 static void nodemap_hs_put_locked(cfs_hash_t *hs,
153                                   struct hlist_node *hnode)
154 {
155         struct lu_nodemap *nodemap;
156
157         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
158         nodemap_putref(nodemap);
159 }
160
161 static cfs_hash_ops_t nodemap_hash_operations = {
162         .hs_hash        = nodemap_hashfn,
163         .hs_key         = nodemap_hs_key,
164         .hs_keycmp      = nodemap_hs_keycmp,
165         .hs_object      = nodemap_hs_hashobject,
166         .hs_get         = nodemap_hs_get,
167         .hs_put_locked  = nodemap_hs_put_locked,
168 };
169
170 /* end of cfs_hash functions */
171
172 /**
173  * Helper iterator to clean up nodemap on module exit.
174  *
175  * \param       hs              hash structure
176  * \param       bd              bucket descriptor
177  * \param       hnode           hash node
178  * \param       data            not used here
179  */
180 static int nodemap_cleanup_iter_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
181                                    struct hlist_node *hnode, void *data)
182 {
183         struct lu_nodemap *nodemap;
184
185         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
186         nodemap_putref(nodemap);
187
188         return 0;
189 }
190
191 /**
192  * Walk the nodemap_hash and remove all nodemaps.
193  */
194 void nodemap_cleanup_all(void)
195 {
196         cfs_hash_for_each_safe(nodemap_hash, nodemap_cleanup_iter_cb, NULL);
197         cfs_hash_putref(nodemap_hash);
198 }
199
200 /**
201  * Initialize nodemap_hash
202  *
203  * \retval      0               success
204  * \retval      -ENOMEM         cannot create hash
205  */
206 static int nodemap_init_hash(void)
207 {
208         nodemap_hash = cfs_hash_create("NODEMAP", HASH_NODEMAP_CUR_BITS,
209                                        HASH_NODEMAP_MAX_BITS,
210                                        HASH_NODEMAP_BKT_BITS, 0,
211                                        CFS_HASH_MIN_THETA,
212                                        CFS_HASH_MAX_THETA,
213                                        &nodemap_hash_operations,
214                                        CFS_HASH_DEFAULT);
215
216         if (nodemap_hash == NULL) {
217                 CERROR("cannot create nodemap_hash table\n");
218                 return -ENOMEM;
219         }
220
221         return 0;
222 }
223
224 /**
225  * Check for valid nodemap name
226  *
227  * \param       name            nodemap name
228  * \retval      true            valid
229  * \retval      false           invalid
230  */
231 static bool nodemap_name_is_valid(const char *name)
232 {
233         if (strlen(name) > LUSTRE_NODEMAP_NAME_LENGTH ||
234             strlen(name) == 0)
235                 return false;
236
237         for (; *name != '\0'; name++) {
238                 if (!isalnum(*name) && *name != '_')
239                         return false;
240         }
241
242         return true;
243 }
244
245 /**
246  * Nodemap lookup
247  *
248  * Look nodemap up in the nodemap hash
249  *
250  * \param       name            name of nodemap
251  * \param       nodemap         found nodemap or NULL
252  * \retval      lu_nodemap      named nodemap
253  * \retval      NULL            nodemap doesn't exist
254  */
255 static int nodemap_lookup(const char *name, struct lu_nodemap **nodemap)
256 {
257         int rc = 0;
258
259         *nodemap = NULL;
260
261         if (!nodemap_name_is_valid(name))
262                 GOTO(out, rc = -EINVAL);
263
264         *nodemap = cfs_hash_lookup(nodemap_hash, name);
265         if (*nodemap == NULL)
266                 rc = -ENOENT;
267
268 out:
269         return rc;
270 }
271
272 /**
273  * classify the nid into the proper nodemap
274  *
275  * \param       nid                     nid to classify
276  * \retval      nodemap                 nodemap containing the nid
277  * \retval      default_nodemap         default nodemap
278  */
279 struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid)
280 {
281         struct lu_nid_range     *range;
282
283         range = range_search(nid);
284         if (range != NULL)
285                 return range->rn_nodemap;
286
287         return default_nodemap;
288 }
289 EXPORT_SYMBOL(nodemap_classify_nid);
290
291 /**
292  * simple check for default nodemap
293  */
294 static bool is_default_nodemap(const struct lu_nodemap *nodemap)
295 {
296         return nodemap->nm_id == 0;
297 }
298
299 /**
300  * parse a nodemap range string into two nids
301  *
302  * \param       range_str               string to parse
303  * \param       range[2]                array of two nids
304  * \reyval      0 on success
305  */
306 int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
307 {
308         char    buf[LNET_NIDSTR_SIZE * 2 + 2];
309         char    *ptr = NULL;
310         char    *start_nidstr;
311         char    *end_nidstr;
312         int     rc = 0;
313
314         snprintf(buf, sizeof(buf), "%s", range_str);
315         ptr = buf;
316         start_nidstr = strsep(&ptr, ":");
317         end_nidstr = strsep(&ptr, ":");
318
319         if (start_nidstr == NULL || end_nidstr == NULL)
320                 GOTO(out, rc = -EINVAL);
321
322         range[0] = libcfs_str2nid(start_nidstr);
323         range[1] = libcfs_str2nid(end_nidstr);
324
325 out:
326         return rc;
327
328 }
329 EXPORT_SYMBOL(nodemap_parse_range);
330
331 /**
332  * parse a string containing an id map of form "client_id:filesystem_id"
333  * into an array of __u32 * for use in mapping functions
334  *
335  * \param       idmap_str               map string
336  * \param       idmap                   array[2] of __u32
337  *
338  * \retval      0 on success
339  * \retval      -EINVAL if idmap cannot be parsed
340  */
341 int nodemap_parse_idmap(char *idmap_str, __u32 idmap[2])
342 {
343         char                    *sep;
344         long unsigned int        idmap_buf;
345         int                      rc;
346
347         if (idmap_str == NULL)
348                 return -EINVAL;
349
350         sep = strchr(idmap_str, ':');
351         if (sep == NULL)
352                 return -EINVAL;
353         *sep = '\0';
354         sep++;
355
356         rc = kstrtoul(idmap_str, 10, &idmap_buf);
357         if (rc != 0)
358                 return -EINVAL;
359         idmap[0] = idmap_buf;
360
361         rc = kstrtoul(sep, 10, &idmap_buf);
362         if (rc != 0)
363                 return -EINVAL;
364         idmap[1] = idmap_buf;
365
366         return 0;
367 }
368 EXPORT_SYMBOL(nodemap_parse_idmap);
369
370 /**
371  * add a member to a nodemap
372  *
373  * \param       nid             nid to add to the members
374  * \param       exp             obd_export structure for the connection
375  *                              that is being added
376  * \retval      -EINVAL         export is NULL
377  * \retval      -EEXIST         export is already member of a nodemap
378  */
379 int nodemap_add_member(lnet_nid_t nid, struct obd_export *exp)
380 {
381         struct lu_nodemap       *nodemap;
382         int rc;
383
384         read_lock(&nm_range_tree_lock);
385         nodemap = nodemap_classify_nid(nid);
386         rc = nm_member_add(nodemap, exp);
387         read_unlock(&nm_range_tree_lock);
388         return rc;
389 }
390 EXPORT_SYMBOL(nodemap_add_member);
391
392 /**
393  * delete a member from a nodemap
394  *
395  * \param       exp             export to remove from a nodemap
396  */
397 void nodemap_del_member(struct obd_export *exp)
398 {
399         struct lu_nodemap       *nodemap = exp->exp_target_data.ted_nodemap;
400
401         if (nodemap != NULL)
402                 nm_member_del(nodemap, exp);
403 }
404 EXPORT_SYMBOL(nodemap_del_member);
405
406 /**
407  * add an idmap to the proper nodemap trees
408  *
409  * \param       name            name of nodemap
410  * \param       id_type         NODEMAP_UID or NODEMAP_GID
411  * \param       map             array[2] __u32 containing the map values
412  *                              map[0] is client id
413  *                              map[1] is the filesystem id
414  *
415  * \retval      0 on success
416  */
417 int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
418                       const __u32 map[2])
419 {
420         struct lu_nodemap       *nodemap = NULL;
421         struct lu_idmap         *idmap;
422         int                     rc = 0;
423
424         rc = nodemap_lookup(name, &nodemap);
425         if (nodemap == NULL || is_default_nodemap(nodemap))
426                 GOTO(out, rc = -EINVAL);
427
428         idmap = idmap_create(map[0], map[1]);
429         if (idmap == NULL)
430                 GOTO(out_putref, rc = -ENOMEM);
431
432         write_lock(&nodemap->nm_idmap_lock);
433         idmap_insert(id_type, idmap, nodemap);
434         write_unlock(&nodemap->nm_idmap_lock);
435         nm_member_revoke_locks(nodemap);
436
437 out_putref:
438         nodemap_putref(nodemap);
439 out:
440         return rc;
441 }
442 EXPORT_SYMBOL(nodemap_add_idmap);
443
444 /**
445  * delete idmap from proper nodemap tree
446  *
447  * \param       name            name of nodemap
448  * \param       id_type         NODEMAP_UID or NODEMAP_GID
449  * \param       map             array[2] __u32 containing the mapA values
450  *                              map[0] is client id
451  *                              map[1] is the filesystem id
452  *
453  * \retval      0 on success
454  */
455 int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
456                       const __u32 map[2])
457 {
458         struct lu_nodemap       *nodemap = NULL;
459         struct lu_idmap         *idmap = NULL;
460         int                     rc = 0;
461
462         rc = nodemap_lookup(name, &nodemap);
463         if (nodemap == NULL || is_default_nodemap(nodemap))
464                 GOTO(out, rc = -EINVAL);
465
466         write_lock(&nodemap->nm_idmap_lock);
467         idmap = idmap_search(nodemap, NODEMAP_CLIENT_TO_FS, id_type,
468                              map[0]);
469         if (idmap == NULL) {
470                 write_unlock(&nodemap->nm_idmap_lock);
471                 GOTO(out_putref, rc = -EINVAL);
472         }
473
474         idmap_delete(id_type, idmap, nodemap);
475         write_unlock(&nodemap->nm_idmap_lock);
476         nm_member_revoke_locks(nodemap);
477
478 out_putref:
479         nodemap_putref(nodemap);
480 out:
481         return rc;
482 }
483 EXPORT_SYMBOL(nodemap_del_idmap);
484
485 /**
486  * mapping function for nodemap idmaps
487  *
488  * \param       nodemap         lu_nodemap structure defining nodemap
489  * \param       node_type       NODEMAP_UID or NODEMAP_GID
490  * \param       tree_type       NODEMAP_CLIENT_TO_FS or
491  *                              NODEMAP_FS_TO_CLIENT
492  * \param       id              id to map
493  *
494  * \retval      mapped id according to the rules below.
495  *
496  * if the nodemap_active is false, just return the passed id without mapping
497  *
498  * if the id to be looked up is 0, check that root access is allowed and if it
499  * is, return 0. Otherwise, return the squash uid or gid.
500  *
501  * if the nodemap is configured to trusted the ids from the client system, just
502  * return the passwd id without mapping.
503  *
504  * if by this point, we haven't returned and the nodemap in question is the
505  * default nodemap, return the squash uid or gid.
506  *
507  * after these checks, search the proper tree for the mapping, and if found
508  * return the mapped value, otherwise return the squash uid or gid.
509  */
510 __u32 nodemap_map_id(struct lu_nodemap *nodemap,
511                      enum nodemap_id_type id_type,
512                      enum nodemap_tree_type tree_type, __u32 id)
513 {
514         struct lu_idmap         *idmap = NULL;
515         __u32                    found_id;
516
517         if (!nodemap_active)
518                 goto out;
519
520         if (unlikely(nodemap == NULL))
521                 goto out;
522
523         if (id == 0) {
524                 if (nodemap->nmf_allow_root_access)
525                         goto out;
526                 else
527                         goto squash;
528         }
529
530         if (nodemap->nmf_trust_client_ids)
531                 goto out;
532
533         if (is_default_nodemap(nodemap))
534                 goto squash;
535
536         read_lock(&nodemap->nm_idmap_lock);
537         idmap = idmap_search(nodemap, tree_type, id_type, id);
538         if (idmap == NULL) {
539                 read_unlock(&nodemap->nm_idmap_lock);
540                 goto squash;
541         }
542
543         if (tree_type == NODEMAP_FS_TO_CLIENT)
544                 found_id = idmap->id_client;
545         else
546                 found_id = idmap->id_fs;
547         read_unlock(&nodemap->nm_idmap_lock);
548         return found_id;
549
550 squash:
551         if (id_type == NODEMAP_UID)
552                 return nodemap->nm_squash_uid;
553         else
554                 return nodemap->nm_squash_gid;
555 out:
556         return id;
557 }
558 EXPORT_SYMBOL(nodemap_map_id);
559
560 /**
561  * Map posix ACL entries according to the nodemap membership. Removes any
562  * squashed ACLs.
563  *
564  * \param       lu_nodemap      nodemap
565  * \param       buf             buffer containing xattr encoded ACLs
566  * \param       size            size of ACLs in bytes
567  * \param       tree_type       direction of mapping
568  * \retval      size            new size of ACLs in bytes
569  * \retval      -EINVAL         bad \a size param, see posix_acl_xattr_count()
570  */
571 ssize_t nodemap_map_acl(struct lu_nodemap *nodemap, void *buf, size_t size,
572                         enum nodemap_tree_type tree_type)
573 {
574         posix_acl_xattr_header  *header = buf;
575         posix_acl_xattr_entry   *entry = &header->a_entries[0];
576         posix_acl_xattr_entry   *new_entry = entry;
577         posix_acl_xattr_entry   *end;
578         int                      count;
579
580         if (!nodemap_active)
581                 return size;
582
583         if (unlikely(nodemap == NULL))
584                 return size;
585
586         count = posix_acl_xattr_count(size);
587         if (count < 0)
588                 return -EINVAL;
589         if (count == 0)
590                 return 0;
591
592         for (end = entry + count; entry != end; entry++) {
593                 __u16 tag = le16_to_cpu(entry->e_tag);
594                 __u32 id = le32_to_cpu(entry->e_id);
595
596                 switch (tag) {
597                 case ACL_USER:
598                         id = nodemap_map_id(nodemap, NODEMAP_UID,
599                                             tree_type, id);
600                         if (id == nodemap->nm_squash_uid)
601                                 continue;
602                         entry->e_id = cpu_to_le32(id);
603                         break;
604                 case ACL_GROUP:
605                         id = nodemap_map_id(nodemap, NODEMAP_GID,
606                                             tree_type, id);
607                         if (id == nodemap->nm_squash_gid)
608                                 continue;
609                         entry->e_id = cpu_to_le32(id);
610                         break;
611                 }
612
613                 /* if we skip an ACL, copy the following ones over it */
614                 if (new_entry != entry)
615                         *new_entry = *entry;
616
617                 new_entry++;
618         }
619
620         return (void *)new_entry - (void *)header;
621 }
622 EXPORT_SYMBOL(nodemap_map_acl);
623
624 /*
625  * add nid range to nodemap
626  * \param       name            nodemap name
627  * \param       range_st        string containing nid range
628  * \retval      0 on success
629  *
630  * add an range to the global range tree and attached the
631  * range to the named nodemap.
632  */
633 int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
634 {
635         struct lu_nodemap       *nodemap = NULL;
636         struct lu_nid_range     *range;
637         int rc;
638
639         rc = nodemap_lookup(name, &nodemap);
640         if (nodemap == NULL || is_default_nodemap(nodemap))
641                 GOTO(out, rc = -EINVAL);
642
643         range = range_create(nid[0], nid[1], nodemap);
644         if (range == NULL)
645                 GOTO(out_putref, rc = -ENOMEM);
646
647         write_lock(&nm_range_tree_lock);
648         rc = range_insert(range);
649         if (rc != 0) {
650                 CERROR("cannot insert nodemap range into '%s': rc = %d\n",
651                       nodemap->nm_name, rc);
652                 write_unlock(&nm_range_tree_lock);
653                 list_del(&range->rn_list);
654                 range_destroy(range);
655                 GOTO(out_putref, rc = -ENOMEM);
656         }
657
658         list_add(&range->rn_list, &nodemap->nm_ranges);
659         write_unlock(&nm_range_tree_lock);
660
661         nm_member_reclassify_nodemap(default_nodemap);
662         nm_member_revoke_locks(default_nodemap);
663         nm_member_revoke_locks(nodemap);
664
665 out_putref:
666         nodemap_putref(nodemap);
667 out:
668         return rc;
669 }
670 EXPORT_SYMBOL(nodemap_add_range);
671
672 /**
673  * delete a range
674  * \param       name            nodemap name
675  * \param       range_str       string containing range
676  * \retval      0 on success
677  *
678  * Delete range from global range tree, and remove it
679  * from the list in the associated nodemap.
680  */
681 int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
682 {
683         struct lu_nodemap       *nodemap;
684         struct lu_nid_range     *range;
685         int                     rc = 0;
686
687         rc = nodemap_lookup(name, &nodemap);
688         if (nodemap == NULL || is_default_nodemap(nodemap))
689                 GOTO(out, rc = -EINVAL);
690
691         write_lock(&nm_range_tree_lock);
692         range = range_find(nid[0], nid[1]);
693         if (range == NULL) {
694                 write_unlock(&nm_range_tree_lock);
695                 GOTO(out_putref, rc = -EINVAL);
696         }
697
698         range_delete(range);
699         write_unlock(&nm_range_tree_lock);
700         nm_member_reclassify_nodemap(nodemap);
701         nm_member_revoke_locks(default_nodemap);
702         nm_member_revoke_locks(nodemap);
703
704 out_putref:
705         nodemap_putref(nodemap);
706 out:
707         return rc;
708 }
709 EXPORT_SYMBOL(nodemap_del_range);
710
711 /**
712  * Nodemap constructor
713  *
714  * Creates an lu_nodemap structure and assigns sane default
715  * member values. If this is the default nodemap, the defaults
716  * are the most restictive in xterms of mapping behavior. Otherwise
717  * the default flags should be inherited from the default nodemap.
718  * The adds nodemap to nodemap_hash.
719  *
720  * \param       name            name of nodemap
721  * \param       is_default      true if default nodemap
722  * \retval      0               success
723  * \retval      -EINVAL         invalid nodemap name
724  * \retval      -EEXIST         nodemap already exists
725  * \retval      -ENOMEM         cannot allocate memory for nodemap
726  */
727 static int nodemap_create(const char *name, bool is_default)
728 {
729         struct lu_nodemap       *nodemap = NULL;
730         int                     rc = 0;
731
732         if (!nodemap_name_is_valid(name))
733                 GOTO(out, rc = -EINVAL);
734
735         OBD_ALLOC_PTR(nodemap);
736         if (nodemap == NULL) {
737                 CERROR("cannot allocate memory (%zu bytes)"
738                        "for nodemap '%s'\n", sizeof(*nodemap),
739                        name);
740                 GOTO(out, rc = -ENOMEM);
741         }
742
743         /*
744          * take an extra reference to prevent nodemap from being destroyed
745          * while its being created.
746          */
747         atomic_set(&nodemap->nm_refcount, 2);
748         snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
749         rc = cfs_hash_add_unique(nodemap_hash, name, &nodemap->nm_hash);
750         if (rc != 0) {
751                 OBD_FREE_PTR(nodemap);
752                 GOTO(out, rc = -EEXIST);
753         }
754
755
756         rc = nm_member_init_hash(nodemap);
757         if (rc != 0) {
758                 OBD_FREE_PTR(nodemap);
759                 goto out;
760         }
761
762         INIT_LIST_HEAD(&nodemap->nm_ranges);
763
764         rwlock_init(&nodemap->nm_idmap_lock);
765         nodemap->nm_fs_to_client_uidmap = RB_ROOT;
766         nodemap->nm_client_to_fs_uidmap = RB_ROOT;
767         nodemap->nm_fs_to_client_gidmap = RB_ROOT;
768         nodemap->nm_client_to_fs_gidmap = RB_ROOT;
769
770         if (is_default) {
771                 nodemap->nm_id = LUSTRE_NODEMAP_DEFAULT_ID;
772                 nodemap->nmf_trust_client_ids = 0;
773                 nodemap->nmf_allow_root_access = 0;
774                 nodemap->nmf_block_lookups = 0;
775
776                 nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
777                 nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
778
779                 lprocfs_nodemap_register(name, is_default, nodemap);
780
781                 default_nodemap = nodemap;
782         } else {
783                 nodemap->nm_id = atomic_inc_return(&nodemap_highest_id);
784                 nodemap->nmf_trust_client_ids =
785                                 default_nodemap->nmf_trust_client_ids;
786                 nodemap->nmf_allow_root_access =
787                                 default_nodemap->nmf_allow_root_access;
788                 nodemap->nmf_block_lookups =
789                                 default_nodemap->nmf_block_lookups;
790
791                 nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
792                 nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
793
794                 lprocfs_nodemap_register(name, is_default, nodemap);
795         }
796
797         if (rc == 0) {
798                 nodemap_putref(nodemap);
799                 goto out;
800         }
801
802         CERROR("cannot add nodemap: '%s': rc = %d\n", name, rc);
803         nodemap_destroy(nodemap);
804
805 out:
806         return rc;
807 }
808
809 /**
810  * update flag to turn on or off nodemap functions
811  * \param       name            nodemap name
812  * \param       admin_string    string containing updated value
813  * \retval      0 on success
814  *
815  * Update admin flag to turn on or off nodemap functions.
816  */
817 int nodemap_set_allow_root(const char *name, bool allow_root)
818 {
819         struct lu_nodemap       *nodemap = NULL;
820         int                     rc = 0;
821
822         rc = nodemap_lookup(name, &nodemap);
823         if (nodemap == NULL)
824                 GOTO(out, rc = -ENOENT);
825
826         nodemap->nmf_allow_root_access = allow_root;
827         nm_member_revoke_locks(nodemap);
828         nodemap_putref(nodemap);
829 out:
830         return rc;
831 }
832 EXPORT_SYMBOL(nodemap_set_allow_root);
833
834 /**
835  * updated trust_client_ids flag for nodemap
836  *
837  * \param       name            nodemap name
838  * \param       trust_string    new value for trust flag
839  * \retval      0 on success
840  *
841  * Update the trust_client_ids flag for a nodemap.
842  */
843 int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids)
844 {
845         struct lu_nodemap       *nodemap = NULL;
846         int                     rc = 0;
847
848         rc = nodemap_lookup(name, &nodemap);
849         if (nodemap == NULL)
850                 GOTO(out, rc = -ENOENT);
851
852         nodemap->nmf_trust_client_ids = trust_client_ids;
853         nm_member_revoke_locks(nodemap);
854         nodemap_putref(nodemap);
855 out:
856         return rc;
857 }
858 EXPORT_SYMBOL(nodemap_set_trust_client_ids);
859
860 /**
861  * update the squash_uid for a nodemap
862  *
863  * \param       name            nodemap name
864  * \param       uid_string      string containing new squash_uid value
865  * \retval      0 on success
866  *
867  * Update the squash_uid for a nodemap. The squash_uid is the uid
868  * that the all client uids are mapped to if nodemap is active,
869  * the trust_client_ids flag is not set, and the uid is not in
870  * the idmap tree.
871  */
872 int nodemap_set_squash_uid(const char *name, uid_t uid)
873 {
874         struct lu_nodemap       *nodemap = NULL;
875         int                     rc = 0;
876
877         rc = nodemap_lookup(name, &nodemap);
878         if (nodemap == NULL)
879                 GOTO(out, rc = -ENOENT);
880
881         nodemap->nm_squash_uid = uid;
882         nm_member_revoke_locks(nodemap);
883         nodemap_putref(nodemap);
884 out:
885         return rc;
886 }
887 EXPORT_SYMBOL(nodemap_set_squash_uid);
888
889 /**
890  * Update the squash_gid for a nodemap.
891  *
892  * \param       name            nodemap name
893  * \param       gid_string      string containing new squash_gid value
894  * \retval      0 on success
895  *
896  * Update the squash_gid for a nodemap. The squash_uid is the gid
897  * that the all client gids are mapped to if nodemap is active,
898  * the trust_client_ids flag is not set, and the gid is not in
899  * the idmap tree.
900  */
901 int nodemap_set_squash_gid(const char *name, gid_t gid)
902 {
903         struct lu_nodemap       *nodemap = NULL;
904         int                     rc = 0;
905
906         rc = nodemap_lookup(name, &nodemap);
907         if (nodemap == NULL)
908                 GOTO(out, rc = -ENOENT);
909
910         nodemap->nm_squash_gid = gid;
911         nm_member_revoke_locks(nodemap);
912         nodemap_putref(nodemap);
913 out:
914         return rc;
915 }
916 EXPORT_SYMBOL(nodemap_set_squash_gid);
917
918 /**
919  * Returns true if this nodemap has root user access. Always returns true if
920  * nodemaps are not active.
921  *
922  * \param       nodemap         nodemap to check access for
923  */
924 bool nodemap_can_setquota(const struct lu_nodemap *nodemap)
925 {
926         return !nodemap_active || nodemap->nmf_allow_root_access;
927 }
928 EXPORT_SYMBOL(nodemap_can_setquota);
929
930 /**
931  * Add a nodemap
932  *
933  * \param       name            name of nodemap
934  * \retval      0               success
935  * \retval      -EINVAL         invalid nodemap name
936  * \retval      -EEXIST         nodemap already exists
937  * \retval      -ENOMEM         cannot allocate memory for nodemap
938  */
939 int nodemap_add(const char *nodemap_name)
940 {
941         return nodemap_create(nodemap_name, 0);
942 }
943 EXPORT_SYMBOL(nodemap_add);
944
945 /**
946  * Delete a nodemap
947  *
948  * \param       name            name of nodemmap
949  * \retval      0               success
950  * \retval      -EINVAL         invalid input
951  * \retval      -ENOENT         no existing nodemap
952  */
953 int nodemap_del(const char *nodemap_name)
954 {
955         struct  lu_nodemap *nodemap;
956         int     rc = 0;
957
958         if (strcmp(nodemap_name, DEFAULT_NODEMAP) == 0)
959                 GOTO(out, rc = -EINVAL);
960
961         nodemap = cfs_hash_del_key(nodemap_hash, nodemap_name);
962         if (nodemap == NULL)
963                 GOTO(out, rc = -ENOENT);
964
965         /*
966          * remove procfs here in case nodemap_create called with same name
967          * before nodemap_destory is run.
968          */
969         lprocfs_remove(&nodemap->nm_proc_entry);
970         nodemap_putref(nodemap);
971 out:
972         return rc;
973 }
974 EXPORT_SYMBOL(nodemap_del);
975
976 /**
977  * activate nodemap functions
978  *
979  * \param       value           1 for on, 0 for off
980  */
981 void nodemap_activate(const bool value)
982 {
983         nodemap_active = value;
984         nm_member_revoke_all();
985 }
986 EXPORT_SYMBOL(nodemap_activate);
987
988 /**
989  * Cleanup nodemap module on exit
990  */
991 void nodemap_mod_exit(void)
992 {
993         nodemap_cleanup_all();
994         lprocfs_remove(&proc_lustre_nodemap_root);
995 }
996
997 /**
998  * Initialize the nodemap module
999  */
1000 int nodemap_mod_init(void)
1001 {
1002         int rc = 0;
1003
1004         rc = nodemap_init_hash();
1005         if (rc != 0)
1006                 goto cleanup;
1007
1008         rwlock_init(&nm_range_tree_lock);
1009         nodemap_procfs_init();
1010         rc = nodemap_create(DEFAULT_NODEMAP, 1);
1011
1012 cleanup:
1013         if (rc != 0)
1014                 nodemap_mod_exit();
1015
1016         return rc;
1017 }
1018
1019 static int nm_member_revoke_all_cb(cfs_hash_t *hs, cfs_hash_bd_t *bd,
1020                                    struct hlist_node *hnode, void *data)
1021 {
1022         struct lu_nodemap *nodemap;
1023
1024         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
1025         nm_member_revoke_locks(nodemap);
1026         return 0;
1027 }
1028
1029 /**
1030  * Revoke locks for all nodemaps.
1031  */
1032 void nm_member_revoke_all()
1033 {
1034         cfs_hash_for_each_safe(nodemap_hash, nm_member_revoke_all_cb, NULL);
1035 }
1036