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