Whamcloud - gitweb
LU-5092 nodemap: convert member hash to a list
[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 (!list_empty(&nodemap->nm_member_list))
93                 CWARN("nodemap_destroy failed to reclassify all members\n");
94
95         nm_member_delete_list(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. Caller must hold
291  * nm_range_tree_lock, and call nodemap_putref when done with nodemap.
292  *
293  * \param       nid                     nid to classify
294  * \retval      nodemap                 nodemap containing the nid
295  * \retval      default_nodemap         default nodemap
296  */
297 struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid)
298 {
299         struct lu_nid_range     *range;
300         struct lu_nodemap       *nodemap;
301
302         range = range_search(nid);
303         if (range != NULL)
304                 nodemap = range->rn_nodemap;
305         else
306                 nodemap = default_nodemap;
307         nodemap_getref(nodemap);
308
309         return nodemap;
310 }
311
312 /**
313  * simple check for default nodemap
314  */
315 static bool is_default_nodemap(const struct lu_nodemap *nodemap)
316 {
317         return nodemap->nm_id == 0;
318 }
319
320 /**
321  * parse a nodemap range string into two nids
322  *
323  * \param       range_str               string to parse
324  * \param       range[2]                array of two nids
325  * \reyval      0 on success
326  */
327 int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
328 {
329         char    buf[LNET_NIDSTR_SIZE * 2 + 2];
330         char    *ptr = NULL;
331         char    *start_nidstr;
332         char    *end_nidstr;
333         int     rc = 0;
334
335         snprintf(buf, sizeof(buf), "%s", range_str);
336         ptr = buf;
337         start_nidstr = strsep(&ptr, ":");
338         end_nidstr = strsep(&ptr, ":");
339
340         if (start_nidstr == NULL || end_nidstr == NULL)
341                 GOTO(out, rc = -EINVAL);
342
343         range[0] = libcfs_str2nid(start_nidstr);
344         range[1] = libcfs_str2nid(end_nidstr);
345
346 out:
347         return rc;
348
349 }
350 EXPORT_SYMBOL(nodemap_parse_range);
351
352 /**
353  * parse a string containing an id map of form "client_id:filesystem_id"
354  * into an array of __u32 * for use in mapping functions
355  *
356  * \param       idmap_str               map string
357  * \param       idmap                   array[2] of __u32
358  *
359  * \retval      0 on success
360  * \retval      -EINVAL if idmap cannot be parsed
361  */
362 int nodemap_parse_idmap(char *idmap_str, __u32 idmap[2])
363 {
364         char                    *sep;
365         long unsigned int        idmap_buf;
366         int                      rc;
367
368         if (idmap_str == NULL)
369                 return -EINVAL;
370
371         sep = strchr(idmap_str, ':');
372         if (sep == NULL)
373                 return -EINVAL;
374         *sep = '\0';
375         sep++;
376
377         rc = kstrtoul(idmap_str, 10, &idmap_buf);
378         if (rc != 0)
379                 return -EINVAL;
380         idmap[0] = idmap_buf;
381
382         rc = kstrtoul(sep, 10, &idmap_buf);
383         if (rc != 0)
384                 return -EINVAL;
385         idmap[1] = idmap_buf;
386
387         return 0;
388 }
389 EXPORT_SYMBOL(nodemap_parse_idmap);
390
391 /**
392  * add a member to a nodemap
393  *
394  * \param       nid             nid to add to the members
395  * \param       exp             obd_export structure for the connection
396  *                              that is being added
397  * \retval      -EINVAL         export is NULL
398  * \retval      -EEXIST         export is already member of a nodemap
399  */
400 int nodemap_add_member(lnet_nid_t nid, struct obd_export *exp)
401 {
402         struct lu_nodemap       *nodemap;
403         int rc;
404
405         read_lock(&nm_range_tree_lock);
406         nodemap = nodemap_classify_nid(nid);
407         rc = nm_member_add(nodemap, exp);
408         read_unlock(&nm_range_tree_lock);
409         nodemap_putref(nodemap);
410         return rc;
411 }
412 EXPORT_SYMBOL(nodemap_add_member);
413
414 /**
415  * delete a member from a nodemap
416  *
417  * \param       exp             export to remove from a nodemap
418  */
419 void nodemap_del_member(struct obd_export *exp)
420 {
421         struct lu_nodemap       *nodemap = exp->exp_target_data.ted_nodemap;
422
423         if (nodemap != NULL)
424                 nm_member_del(nodemap, exp);
425 }
426 EXPORT_SYMBOL(nodemap_del_member);
427
428 /**
429  * add an idmap to the proper nodemap trees
430  *
431  * \param       name            name of nodemap
432  * \param       id_type         NODEMAP_UID or NODEMAP_GID
433  * \param       map             array[2] __u32 containing the map values
434  *                              map[0] is client id
435  *                              map[1] is the filesystem id
436  *
437  * \retval      0 on success
438  */
439 int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
440                       const __u32 map[2])
441 {
442         struct lu_nodemap       *nodemap = NULL;
443         struct lu_idmap         *idmap;
444         int                     rc = 0;
445
446         rc = nodemap_lookup(name, &nodemap);
447         if (nodemap == NULL || is_default_nodemap(nodemap))
448                 GOTO(out, rc = -EINVAL);
449
450         idmap = idmap_create(map[0], map[1]);
451         if (idmap == NULL)
452                 GOTO(out_putref, rc = -ENOMEM);
453
454         write_lock(&nodemap->nm_idmap_lock);
455         idmap_insert(id_type, idmap, nodemap);
456         write_unlock(&nodemap->nm_idmap_lock);
457         nm_member_revoke_locks(nodemap);
458
459 out_putref:
460         nodemap_putref(nodemap);
461 out:
462         return rc;
463 }
464 EXPORT_SYMBOL(nodemap_add_idmap);
465
466 /**
467  * delete idmap from proper nodemap tree
468  *
469  * \param       name            name of nodemap
470  * \param       id_type         NODEMAP_UID or NODEMAP_GID
471  * \param       map             array[2] __u32 containing the mapA values
472  *                              map[0] is client id
473  *                              map[1] is the filesystem id
474  *
475  * \retval      0 on success
476  */
477 int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
478                       const __u32 map[2])
479 {
480         struct lu_nodemap       *nodemap = NULL;
481         struct lu_idmap         *idmap = NULL;
482         int                     rc = 0;
483
484         rc = nodemap_lookup(name, &nodemap);
485         if (nodemap == NULL || is_default_nodemap(nodemap))
486                 GOTO(out, rc = -EINVAL);
487
488         write_lock(&nodemap->nm_idmap_lock);
489         idmap = idmap_search(nodemap, NODEMAP_CLIENT_TO_FS, id_type,
490                              map[0]);
491         if (idmap == NULL) {
492                 write_unlock(&nodemap->nm_idmap_lock);
493                 GOTO(out_putref, rc = -EINVAL);
494         }
495
496         idmap_delete(id_type, idmap, nodemap);
497         write_unlock(&nodemap->nm_idmap_lock);
498         nm_member_revoke_locks(nodemap);
499
500 out_putref:
501         nodemap_putref(nodemap);
502 out:
503         return rc;
504 }
505 EXPORT_SYMBOL(nodemap_del_idmap);
506
507 /**
508  * mapping function for nodemap idmaps
509  *
510  * \param       nodemap         lu_nodemap structure defining nodemap
511  * \param       node_type       NODEMAP_UID or NODEMAP_GID
512  * \param       tree_type       NODEMAP_CLIENT_TO_FS or
513  *                              NODEMAP_FS_TO_CLIENT
514  * \param       id              id to map
515  *
516  * \retval      mapped id according to the rules below.
517  *
518  * if the nodemap_active is false, just return the passed id without mapping
519  *
520  * if the id to be looked up is 0, check that root access is allowed and if it
521  * is, return 0. Otherwise, return the squash uid or gid.
522  *
523  * if the nodemap is configured to trusted the ids from the client system, just
524  * return the passwd id without mapping.
525  *
526  * if by this point, we haven't returned and the nodemap in question is the
527  * default nodemap, return the squash uid or gid.
528  *
529  * after these checks, search the proper tree for the mapping, and if found
530  * return the mapped value, otherwise return the squash uid or gid.
531  */
532 __u32 nodemap_map_id(struct lu_nodemap *nodemap,
533                      enum nodemap_id_type id_type,
534                      enum nodemap_tree_type tree_type, __u32 id)
535 {
536         struct lu_idmap         *idmap = NULL;
537         __u32                    found_id;
538
539         if (!nodemap_active)
540                 goto out;
541
542         if (unlikely(nodemap == NULL))
543                 goto out;
544
545         if (id == 0) {
546                 if (nodemap->nmf_allow_root_access)
547                         goto out;
548                 else
549                         goto squash;
550         }
551
552         if (nodemap->nmf_trust_client_ids)
553                 goto out;
554
555         if (is_default_nodemap(nodemap))
556                 goto squash;
557
558         read_lock(&nodemap->nm_idmap_lock);
559         idmap = idmap_search(nodemap, tree_type, id_type, id);
560         if (idmap == NULL) {
561                 read_unlock(&nodemap->nm_idmap_lock);
562                 goto squash;
563         }
564
565         if (tree_type == NODEMAP_FS_TO_CLIENT)
566                 found_id = idmap->id_client;
567         else
568                 found_id = idmap->id_fs;
569         read_unlock(&nodemap->nm_idmap_lock);
570         return found_id;
571
572 squash:
573         if (id_type == NODEMAP_UID)
574                 return nodemap->nm_squash_uid;
575         else
576                 return nodemap->nm_squash_gid;
577 out:
578         return id;
579 }
580 EXPORT_SYMBOL(nodemap_map_id);
581
582 /**
583  * Map posix ACL entries according to the nodemap membership. Removes any
584  * squashed ACLs.
585  *
586  * \param       lu_nodemap      nodemap
587  * \param       buf             buffer containing xattr encoded ACLs
588  * \param       size            size of ACLs in bytes
589  * \param       tree_type       direction of mapping
590  * \retval      size            new size of ACLs in bytes
591  * \retval      -EINVAL         bad \a size param, see posix_acl_xattr_count()
592  */
593 ssize_t nodemap_map_acl(struct lu_nodemap *nodemap, void *buf, size_t size,
594                         enum nodemap_tree_type tree_type)
595 {
596         posix_acl_xattr_header  *header = buf;
597         posix_acl_xattr_entry   *entry = &header->a_entries[0];
598         posix_acl_xattr_entry   *new_entry = entry;
599         posix_acl_xattr_entry   *end;
600         int                      count;
601
602         if (!nodemap_active)
603                 return size;
604
605         if (unlikely(nodemap == NULL))
606                 return size;
607
608         count = posix_acl_xattr_count(size);
609         if (count < 0)
610                 return -EINVAL;
611         if (count == 0)
612                 return 0;
613
614         for (end = entry + count; entry != end; entry++) {
615                 __u16 tag = le16_to_cpu(entry->e_tag);
616                 __u32 id = le32_to_cpu(entry->e_id);
617
618                 switch (tag) {
619                 case ACL_USER:
620                         id = nodemap_map_id(nodemap, NODEMAP_UID,
621                                             tree_type, id);
622                         if (id == nodemap->nm_squash_uid)
623                                 continue;
624                         entry->e_id = cpu_to_le32(id);
625                         break;
626                 case ACL_GROUP:
627                         id = nodemap_map_id(nodemap, NODEMAP_GID,
628                                             tree_type, id);
629                         if (id == nodemap->nm_squash_gid)
630                                 continue;
631                         entry->e_id = cpu_to_le32(id);
632                         break;
633                 }
634
635                 /* if we skip an ACL, copy the following ones over it */
636                 if (new_entry != entry)
637                         *new_entry = *entry;
638
639                 new_entry++;
640         }
641
642         return (void *)new_entry - (void *)header;
643 }
644 EXPORT_SYMBOL(nodemap_map_acl);
645
646 /*
647  * add nid range to nodemap
648  * \param       name            nodemap name
649  * \param       range_st        string containing nid range
650  * \retval      0 on success
651  *
652  * add an range to the global range tree and attached the
653  * range to the named nodemap.
654  */
655 int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
656 {
657         struct lu_nodemap       *nodemap = NULL;
658         struct lu_nid_range     *range;
659         int rc;
660
661         rc = nodemap_lookup(name, &nodemap);
662         if (nodemap == NULL || is_default_nodemap(nodemap))
663                 GOTO(out, rc = -EINVAL);
664
665         range = range_create(nid[0], nid[1], nodemap);
666         if (range == NULL)
667                 GOTO(out_putref, rc = -ENOMEM);
668
669         write_lock(&nm_range_tree_lock);
670         rc = range_insert(range);
671         if (rc != 0) {
672                 CERROR("cannot insert nodemap range into '%s': rc = %d\n",
673                       nodemap->nm_name, rc);
674                 write_unlock(&nm_range_tree_lock);
675                 list_del(&range->rn_list);
676                 range_destroy(range);
677                 GOTO(out_putref, rc = -ENOMEM);
678         }
679
680         list_add(&range->rn_list, &nodemap->nm_ranges);
681         write_unlock(&nm_range_tree_lock);
682
683         nm_member_reclassify_nodemap(default_nodemap);
684         nm_member_revoke_locks(default_nodemap);
685         nm_member_revoke_locks(nodemap);
686
687 out_putref:
688         nodemap_putref(nodemap);
689 out:
690         return rc;
691 }
692 EXPORT_SYMBOL(nodemap_add_range);
693
694 /**
695  * delete a range
696  * \param       name            nodemap name
697  * \param       range_str       string containing range
698  * \retval      0 on success
699  *
700  * Delete range from global range tree, and remove it
701  * from the list in the associated nodemap.
702  */
703 int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
704 {
705         struct lu_nodemap       *nodemap;
706         struct lu_nid_range     *range;
707         int                     rc = 0;
708
709         rc = nodemap_lookup(name, &nodemap);
710         if (nodemap == NULL || is_default_nodemap(nodemap))
711                 GOTO(out, rc = -EINVAL);
712
713         write_lock(&nm_range_tree_lock);
714         range = range_find(nid[0], nid[1]);
715         if (range == NULL) {
716                 write_unlock(&nm_range_tree_lock);
717                 GOTO(out_putref, rc = -EINVAL);
718         }
719
720         range_delete(range);
721         write_unlock(&nm_range_tree_lock);
722         nm_member_reclassify_nodemap(nodemap);
723         nm_member_revoke_locks(default_nodemap);
724         nm_member_revoke_locks(nodemap);
725
726 out_putref:
727         nodemap_putref(nodemap);
728 out:
729         return rc;
730 }
731 EXPORT_SYMBOL(nodemap_del_range);
732
733 /**
734  * Nodemap constructor
735  *
736  * Creates an lu_nodemap structure and assigns sane default
737  * member values. If this is the default nodemap, the defaults
738  * are the most restictive in xterms of mapping behavior. Otherwise
739  * the default flags should be inherited from the default nodemap.
740  * The adds nodemap to nodemap_hash.
741  *
742  * \param       name            name of nodemap
743  * \param       is_default      true if default nodemap
744  * \retval      0               success
745  * \retval      -EINVAL         invalid nodemap name
746  * \retval      -EEXIST         nodemap already exists
747  * \retval      -ENOMEM         cannot allocate memory for nodemap
748  */
749 static int nodemap_create(const char *name, bool is_default)
750 {
751         struct lu_nodemap       *nodemap = NULL;
752         int                     rc = 0;
753
754         if (!nodemap_name_is_valid(name))
755                 GOTO(out, rc = -EINVAL);
756
757         OBD_ALLOC_PTR(nodemap);
758         if (nodemap == NULL) {
759                 CERROR("cannot allocate memory (%zu bytes)"
760                        "for nodemap '%s'\n", sizeof(*nodemap),
761                        name);
762                 GOTO(out, rc = -ENOMEM);
763         }
764
765         /*
766          * take an extra reference to prevent nodemap from being destroyed
767          * while its being created.
768          */
769         atomic_set(&nodemap->nm_refcount, 2);
770         snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
771         rc = cfs_hash_add_unique(nodemap_hash, name, &nodemap->nm_hash);
772         if (rc != 0) {
773                 OBD_FREE_PTR(nodemap);
774                 GOTO(out, rc = -EEXIST);
775         }
776
777         INIT_LIST_HEAD(&nodemap->nm_ranges);
778         INIT_LIST_HEAD(&nodemap->nm_list);
779         INIT_LIST_HEAD(&nodemap->nm_member_list);
780
781         mutex_init(&nodemap->nm_member_list_lock);
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
1055 /**
1056  * Returns the nodemap classification for a given nid into an ioctl buffer.
1057  * Useful for testing the nodemap configuration to make sure it is working as
1058  * expected.
1059  *
1060  * \param       nid             nid to classify
1061  * \param[out]  name_buf        buffer to write the nodemap name to
1062  * \param       name_len        length of buffer
1063  */
1064 void nodemap_test_nid(lnet_nid_t nid, char *name_buf, size_t name_len)
1065 {
1066         struct lu_nodemap       *nodemap;
1067
1068         read_lock(&nm_range_tree_lock);
1069         nodemap = nodemap_classify_nid(nid);
1070         read_unlock(&nm_range_tree_lock);
1071
1072         strncpy(name_buf, nodemap->nm_name, name_len);
1073         if (name_len > 0)
1074                 name_buf[name_len - 1] = '\0';
1075
1076         nodemap_putref(nodemap);
1077 }
1078 EXPORT_SYMBOL(nodemap_test_nid);
1079
1080 /**
1081  * Returns the id mapping for a given nid/id pair. Useful for testing the
1082  * nodemap configuration to make sure it is working as expected.
1083  *
1084  * \param       nid             nid to classify
1085  * \param       idtype          uid or gid
1086  * \param       client_id       id to map to fs
1087  *
1088  * \retval      the mapped fs_id of the given client_id
1089  */
1090 __u32 nodemap_test_id(lnet_nid_t nid, enum nodemap_id_type idtype,
1091                       __u32 client_id)
1092 {
1093         struct lu_nodemap       *nodemap;
1094         __u32                    fs_id;
1095
1096         read_lock(&nm_range_tree_lock);
1097         nodemap = nodemap_classify_nid(nid);
1098         read_unlock(&nm_range_tree_lock);
1099
1100         fs_id = nodemap_map_id(nodemap, idtype, NODEMAP_CLIENT_TO_FS,
1101                                client_id);
1102         nodemap_putref(nodemap);
1103
1104         return fs_id;
1105 }
1106 EXPORT_SYMBOL(nodemap_test_id);