Whamcloud - gitweb
5bf49328a7866736d1f96590fcfe8a235c9534c0
[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 /* Copy of config active flag to avoid locking in mapping functions */
48 bool nodemap_active;
49
50 /* Lock protecting the active config, useful primarily when proc and
51  * nodemap_hash might be replaced when loading a new config
52  * Any time the active config is referenced, the lock should be held.
53  */
54 DEFINE_MUTEX(active_config_lock);
55 struct nodemap_config *active_config;
56
57 /**
58  * Nodemap destructor
59  *
60  * \param       nodemap         nodemap to destroy
61  */
62 static void nodemap_destroy(struct lu_nodemap *nodemap)
63 {
64         if (nodemap->nm_pde_data != NULL)
65                 lprocfs_nodemap_remove(nodemap->nm_pde_data);
66
67         mutex_lock(&active_config_lock);
68         down_read(&active_config->nmc_range_tree_lock);
69         nm_member_reclassify_nodemap(nodemap);
70         up_read(&active_config->nmc_range_tree_lock);
71         mutex_unlock(&active_config_lock);
72
73         if (!list_empty(&nodemap->nm_member_list))
74                 CWARN("nodemap_destroy failed to reclassify all members\n");
75
76         write_lock(&nodemap->nm_idmap_lock);
77         idmap_delete_tree(nodemap);
78         write_unlock(&nodemap->nm_idmap_lock);
79
80         nm_member_delete_list(nodemap);
81
82         OBD_FREE_PTR(nodemap);
83 }
84
85 /**
86  * Functions used for the cfs_hash
87  */
88 static void nodemap_getref(struct lu_nodemap *nodemap)
89 {
90         atomic_inc(&nodemap->nm_refcount);
91 }
92
93 /**
94  * Destroy nodemap if last reference is put. Should be called outside
95  * active_config_lock
96  */
97 void nodemap_putref(struct lu_nodemap *nodemap)
98 {
99         LASSERT(nodemap != NULL);
100         LASSERT(atomic_read(&nodemap->nm_refcount) > 0);
101
102         if (atomic_dec_and_test(&nodemap->nm_refcount))
103                 nodemap_destroy(nodemap);
104 }
105
106 static __u32 nodemap_hashfn(struct cfs_hash *hash_body,
107                             const void *key, unsigned mask)
108 {
109         return cfs_hash_djb2_hash(key, strlen(key), mask);
110 }
111
112 static void *nodemap_hs_key(struct hlist_node *hnode)
113 {
114         struct lu_nodemap *nodemap;
115
116         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
117
118         return nodemap->nm_name;
119 }
120
121 static int nodemap_hs_keycmp(const void *key,
122                              struct hlist_node *compared_hnode)
123 {
124         char *nodemap_name;
125
126         nodemap_name = nodemap_hs_key(compared_hnode);
127
128         return !strcmp(key, nodemap_name);
129 }
130
131 static void *nodemap_hs_hashobject(struct hlist_node *hnode)
132 {
133         return hlist_entry(hnode, struct lu_nodemap, nm_hash);
134 }
135
136 static void nodemap_hs_get(struct cfs_hash *hs, struct hlist_node *hnode)
137 {
138         struct lu_nodemap *nodemap;
139
140         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
141         nodemap_getref(nodemap);
142 }
143
144 static void nodemap_hs_put_locked(struct cfs_hash *hs,
145                                   struct hlist_node *hnode)
146 {
147         struct lu_nodemap *nodemap;
148
149         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
150         nodemap_putref(nodemap);
151 }
152
153 static struct cfs_hash_ops nodemap_hash_operations = {
154         .hs_hash        = nodemap_hashfn,
155         .hs_key         = nodemap_hs_key,
156         .hs_keycmp      = nodemap_hs_keycmp,
157         .hs_object      = nodemap_hs_hashobject,
158         .hs_get         = nodemap_hs_get,
159         .hs_put_locked  = nodemap_hs_put_locked,
160 };
161
162 /* end of cfs_hash functions */
163
164 /**
165  * Initialize nodemap_hash
166  *
167  * \retval      0               success
168  * \retval      -ENOMEM         cannot create hash
169  */
170 static int nodemap_init_hash(struct nodemap_config *nmc)
171 {
172         nmc->nmc_nodemap_hash = cfs_hash_create("NODEMAP",
173                                                 HASH_NODEMAP_CUR_BITS,
174                                                 HASH_NODEMAP_MAX_BITS,
175                                                 HASH_NODEMAP_BKT_BITS, 0,
176                                                 CFS_HASH_MIN_THETA,
177                                                 CFS_HASH_MAX_THETA,
178                                                 &nodemap_hash_operations,
179                                                 CFS_HASH_DEFAULT);
180
181         if (nmc->nmc_nodemap_hash == NULL) {
182                 CERROR("cannot create nodemap_hash table\n");
183                 return -ENOMEM;
184         }
185
186         return 0;
187 }
188
189 /**
190  * Check for valid nodemap name
191  *
192  * \param       name            nodemap name
193  * \retval      true            valid
194  * \retval      false           invalid
195  */
196 static bool nodemap_name_is_valid(const char *name)
197 {
198         if (strlen(name) > LUSTRE_NODEMAP_NAME_LENGTH ||
199             strlen(name) == 0)
200                 return false;
201
202         for (; *name != '\0'; name++) {
203                 if (!isalnum(*name) && *name != '_')
204                         return false;
205         }
206
207         return true;
208 }
209
210 /**
211  * Nodemap lookup
212  *
213  * Look nodemap up in the active_config nodemap hash. Caller should hold the
214  * active_config_lock.
215  *
216  * \param       name            name of nodemap
217  * \retval      nodemap         pointer set to found nodemap
218  * \retval      -EINVAL         name is not valid
219  * \retval      -ENOENT         nodemap not found
220  */
221 struct lu_nodemap *nodemap_lookup(const char *name)
222 {
223         struct lu_nodemap *nodemap = NULL;
224
225         if (!nodemap_name_is_valid(name))
226                 return ERR_PTR(-EINVAL);
227
228         nodemap = cfs_hash_lookup(active_config->nmc_nodemap_hash, name);
229         if (nodemap == NULL)
230                 return ERR_PTR(-ENOENT);
231
232         return nodemap;
233 }
234
235 /**
236  * Classify the nid into the proper nodemap. Caller must hold active config and
237  * nm_range_tree_lock, and call nodemap_putref when done with nodemap.
238  *
239  * \param       nid                     nid to classify
240  * \retval      nodemap                 nodemap containing the nid
241  * \retval      default_nodemap         default nodemap
242  */
243 struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid)
244 {
245         struct lu_nid_range     *range;
246         struct lu_nodemap       *nodemap;
247
248         range = range_search(&active_config->nmc_range_tree, nid);
249         if (range != NULL)
250                 nodemap = range->rn_nodemap;
251         else
252                 nodemap = active_config->nmc_default_nodemap;
253
254         nodemap_getref(nodemap);
255
256         return nodemap;
257 }
258
259 /**
260  * simple check for default nodemap
261  */
262 static bool is_default_nodemap(const struct lu_nodemap *nodemap)
263 {
264         return nodemap->nm_id == 0;
265 }
266
267 /**
268  * parse a nodemap range string into two nids
269  *
270  * \param       range_str               string to parse
271  * \param       range[2]                array of two nids
272  * \reyval      0 on success
273  */
274 int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
275 {
276         char    buf[LNET_NIDSTR_SIZE * 2 + 2];
277         char    *ptr = NULL;
278         char    *start_nidstr;
279         char    *end_nidstr;
280         int     rc = 0;
281
282         snprintf(buf, sizeof(buf), "%s", range_str);
283         ptr = buf;
284         start_nidstr = strsep(&ptr, ":");
285         end_nidstr = strsep(&ptr, ":");
286
287         if (start_nidstr == NULL || end_nidstr == NULL)
288                 GOTO(out, rc = -EINVAL);
289
290         range[0] = libcfs_str2nid(start_nidstr);
291         range[1] = libcfs_str2nid(end_nidstr);
292
293 out:
294         return rc;
295
296 }
297 EXPORT_SYMBOL(nodemap_parse_range);
298
299 /**
300  * parse a string containing an id map of form "client_id:filesystem_id"
301  * into an array of __u32 * for use in mapping functions
302  *
303  * \param       idmap_str               map string
304  * \param       idmap                   array[2] of __u32
305  *
306  * \retval      0 on success
307  * \retval      -EINVAL if idmap cannot be parsed
308  */
309 int nodemap_parse_idmap(char *idmap_str, __u32 idmap[2])
310 {
311         char                    *sep;
312         long unsigned int        idmap_buf;
313         int                      rc;
314
315         if (idmap_str == NULL)
316                 return -EINVAL;
317
318         sep = strchr(idmap_str, ':');
319         if (sep == NULL)
320                 return -EINVAL;
321         *sep = '\0';
322         sep++;
323
324         rc = kstrtoul(idmap_str, 10, &idmap_buf);
325         if (rc != 0)
326                 return -EINVAL;
327         idmap[0] = idmap_buf;
328
329         rc = kstrtoul(sep, 10, &idmap_buf);
330         if (rc != 0)
331                 return -EINVAL;
332         idmap[1] = idmap_buf;
333
334         return 0;
335 }
336 EXPORT_SYMBOL(nodemap_parse_idmap);
337
338 /**
339  * add a member to a nodemap
340  *
341  * \param       nid             nid to add to the members
342  * \param       exp             obd_export structure for the connection
343  *                              that is being added
344  * \retval      -EINVAL         export is NULL
345  * \retval      -EEXIST         export is already member of a nodemap
346  */
347 int nodemap_add_member(lnet_nid_t nid, struct obd_export *exp)
348 {
349         struct lu_nodemap       *nodemap;
350         int rc;
351
352         mutex_lock(&active_config_lock);
353         down_read(&active_config->nmc_range_tree_lock);
354
355         nodemap = nodemap_classify_nid(nid);
356         rc = nm_member_add(nodemap, exp);
357
358         up_read(&active_config->nmc_range_tree_lock);
359         mutex_unlock(&active_config_lock);
360
361         nodemap_putref(nodemap);
362
363         return rc;
364 }
365 EXPORT_SYMBOL(nodemap_add_member);
366
367 /**
368  * delete a member from a nodemap
369  *
370  * \param       exp             export to remove from a nodemap
371  */
372 void nodemap_del_member(struct obd_export *exp)
373 {
374         struct lu_nodemap       *nodemap = exp->exp_target_data.ted_nodemap;
375
376         if (nodemap != NULL)
377                 nm_member_del(nodemap, exp);
378 }
379 EXPORT_SYMBOL(nodemap_del_member);
380
381 /**
382  * add an idmap to the proper nodemap trees
383  *
384  * \param       name            name of nodemap
385  * \param       id_type         NODEMAP_UID or NODEMAP_GID
386  * \param       map             array[2] __u32 containing the map values
387  *                              map[0] is client id
388  *                              map[1] is the filesystem id
389  *
390  * \retval      0 on success
391  */
392 static int nodemap_add_idmap_helper(struct lu_nodemap *nodemap,
393                                     enum nodemap_id_type id_type,
394                                     const __u32 map[2])
395 {
396         struct lu_idmap         *idmap;
397         int                     rc = 0;
398
399         idmap = idmap_create(map[0], map[1]);
400         if (idmap == NULL)
401                 GOTO(out, rc = -ENOMEM);
402
403         write_lock(&nodemap->nm_idmap_lock);
404         idmap_insert(id_type, idmap, nodemap);
405         write_unlock(&nodemap->nm_idmap_lock);
406         nm_member_revoke_locks(nodemap);
407
408 out:
409         return rc;
410 }
411 int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
412                       const __u32 map[2])
413 {
414         struct lu_nodemap       *nodemap = NULL;
415         int                      rc;
416
417         mutex_lock(&active_config_lock);
418         nodemap = nodemap_lookup(name);
419         if (IS_ERR(nodemap)) {
420                 mutex_unlock(&active_config_lock);
421                 GOTO(out, rc = PTR_ERR(nodemap));
422         }
423
424         if (is_default_nodemap(nodemap))
425                 rc = -EINVAL;
426         else
427                 rc = nodemap_add_idmap_helper(nodemap, id_type, map);
428
429         mutex_unlock(&active_config_lock);
430
431         nodemap_putref(nodemap);
432
433 out:
434         return rc;
435 }
436 EXPORT_SYMBOL(nodemap_add_idmap);
437
438 /**
439  * delete idmap from proper nodemap tree
440  *
441  * \param       name            name of nodemap
442  * \param       id_type         NODEMAP_UID or NODEMAP_GID
443  * \param       map             array[2] __u32 containing the mapA values
444  *                              map[0] is client id
445  *                              map[1] is the filesystem id
446  *
447  * \retval      0 on success
448  */
449 int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
450                       const __u32 map[2])
451 {
452         struct lu_nodemap       *nodemap = NULL;
453         struct lu_idmap         *idmap = NULL;
454         int                     rc = 0;
455
456         mutex_lock(&active_config_lock);
457         nodemap = nodemap_lookup(name);
458         if (IS_ERR(nodemap)) {
459                 mutex_unlock(&active_config_lock);
460                 GOTO(out, rc = PTR_ERR(nodemap));
461         }
462
463         if (is_default_nodemap(nodemap))
464                 GOTO(out_putref, 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                 rc = -EINVAL;
471         else
472                 idmap_delete(id_type, idmap, nodemap);
473         write_unlock(&nodemap->nm_idmap_lock);
474
475 out_putref:
476         mutex_unlock(&active_config_lock);
477         if (rc == 0)
478                 nm_member_revoke_locks(nodemap);
479         nodemap_putref(nodemap);
480
481 out:
482         return rc;
483 }
484 EXPORT_SYMBOL(nodemap_del_idmap);
485
486 /**
487  * mapping function for nodemap idmaps
488  *
489  * \param       nodemap         lu_nodemap structure defining nodemap
490  * \param       node_type       NODEMAP_UID or NODEMAP_GID
491  * \param       tree_type       NODEMAP_CLIENT_TO_FS or
492  *                              NODEMAP_FS_TO_CLIENT
493  * \param       id              id to map
494  *
495  * \retval      mapped id according to the rules below.
496  *
497  * if the nodemap_active is false, just return the passed id without mapping
498  *
499  * if the id to be looked up is 0, check that root access is allowed and if it
500  * is, return 0. Otherwise, return the squash uid or gid.
501  *
502  * if the nodemap is configured to trusted the ids from the client system, just
503  * return the passwd id without mapping.
504  *
505  * if by this point, we haven't returned and the nodemap in question is the
506  * default nodemap, return the squash uid or gid.
507  *
508  * after these checks, search the proper tree for the mapping, and if found
509  * return the mapped value, otherwise return the squash uid or gid.
510  */
511 __u32 nodemap_map_id(struct lu_nodemap *nodemap,
512                      enum nodemap_id_type id_type,
513                      enum nodemap_tree_type tree_type, __u32 id)
514 {
515         struct lu_idmap         *idmap = NULL;
516         __u32                    found_id;
517
518         if (!nodemap_active)
519                 goto out;
520
521         if (unlikely(nodemap == NULL))
522                 goto out;
523
524         if (id == 0) {
525                 if (nodemap->nmf_allow_root_access)
526                         goto out;
527                 else
528                         goto squash;
529         }
530
531         if (nodemap->nmf_trust_client_ids)
532                 goto out;
533
534         if (is_default_nodemap(nodemap))
535                 goto squash;
536
537         read_lock(&nodemap->nm_idmap_lock);
538         idmap = idmap_search(nodemap, tree_type, id_type, id);
539         if (idmap == NULL) {
540                 read_unlock(&nodemap->nm_idmap_lock);
541                 goto squash;
542         }
543
544         if (tree_type == NODEMAP_FS_TO_CLIENT)
545                 found_id = idmap->id_client;
546         else
547                 found_id = idmap->id_fs;
548         read_unlock(&nodemap->nm_idmap_lock);
549         return found_id;
550
551 squash:
552         if (id_type == NODEMAP_UID)
553                 return nodemap->nm_squash_uid;
554         else
555                 return nodemap->nm_squash_gid;
556 out:
557         return id;
558 }
559 EXPORT_SYMBOL(nodemap_map_id);
560
561 /**
562  * Map posix ACL entries according to the nodemap membership. Removes any
563  * squashed ACLs.
564  *
565  * \param       lu_nodemap      nodemap
566  * \param       buf             buffer containing xattr encoded ACLs
567  * \param       size            size of ACLs in bytes
568  * \param       tree_type       direction of mapping
569  * \retval      size            new size of ACLs in bytes
570  * \retval      -EINVAL         bad \a size param, see posix_acl_xattr_count()
571  */
572 ssize_t nodemap_map_acl(struct lu_nodemap *nodemap, void *buf, size_t size,
573                         enum nodemap_tree_type tree_type)
574 {
575         posix_acl_xattr_header  *header = buf;
576         posix_acl_xattr_entry   *entry = &header->a_entries[0];
577         posix_acl_xattr_entry   *new_entry = entry;
578         posix_acl_xattr_entry   *end;
579         int                      count;
580
581         if (!nodemap_active)
582                 return size;
583
584         if (unlikely(nodemap == NULL))
585                 return size;
586
587         count = posix_acl_xattr_count(size);
588         if (count < 0)
589                 return -EINVAL;
590         if (count == 0)
591                 return 0;
592
593         for (end = entry + count; entry != end; entry++) {
594                 __u16 tag = le16_to_cpu(entry->e_tag);
595                 __u32 id = le32_to_cpu(entry->e_id);
596
597                 switch (tag) {
598                 case ACL_USER:
599                         id = nodemap_map_id(nodemap, NODEMAP_UID,
600                                             tree_type, id);
601                         if (id == nodemap->nm_squash_uid)
602                                 continue;
603                         entry->e_id = cpu_to_le32(id);
604                         break;
605                 case ACL_GROUP:
606                         id = nodemap_map_id(nodemap, NODEMAP_GID,
607                                             tree_type, id);
608                         if (id == nodemap->nm_squash_gid)
609                                 continue;
610                         entry->e_id = cpu_to_le32(id);
611                         break;
612                 }
613
614                 /* if we skip an ACL, copy the following ones over it */
615                 if (new_entry != entry)
616                         *new_entry = *entry;
617
618                 new_entry++;
619         }
620
621         return (void *)new_entry - (void *)header;
622 }
623 EXPORT_SYMBOL(nodemap_map_acl);
624
625 /*
626  * add nid range to nodemap
627  * \param       nodemap         nodemap to add range to
628  * \param       range_st        string containing nid range
629  * \retval      0 on success
630  *
631  * add an range to the global range tree and attached the
632  * range to the named nodemap.
633  */
634 static int nodemap_add_range_helper(struct nodemap_config *config,
635                                     struct lu_nodemap *nodemap,
636                                     const lnet_nid_t nid[2])
637 {
638         struct lu_nid_range     *range;
639         int rc;
640
641         down_write(&config->nmc_range_tree_lock);
642         range = range_create(&config->nmc_range_tree, nid[0], nid[1], nodemap);
643         if (range == NULL) {
644                 up_write(&config->nmc_range_tree_lock);
645                 GOTO(out, rc = -ENOMEM);
646         }
647
648         rc = range_insert(&config->nmc_range_tree, range);
649         if (rc != 0) {
650                 CERROR("cannot insert nodemap range into '%s': rc = %d\n",
651                       nodemap->nm_name, rc);
652                 up_write(&config->nmc_range_tree_lock);
653                 list_del(&range->rn_list);
654                 range_destroy(range);
655                 GOTO(out, rc = -ENOMEM);
656         }
657
658         list_add(&range->rn_list, &nodemap->nm_ranges);
659         nm_member_reclassify_nodemap(config->nmc_default_nodemap);
660         up_write(&config->nmc_range_tree_lock);
661
662         nm_member_revoke_locks(config->nmc_default_nodemap);
663         nm_member_revoke_locks(nodemap);
664
665 out:
666         return rc;
667 }
668 int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
669 {
670         struct lu_nodemap       *nodemap = NULL;
671         int                      rc;
672
673         mutex_lock(&active_config_lock);
674         nodemap = nodemap_lookup(name);
675         if (IS_ERR(nodemap)) {
676                 mutex_unlock(&active_config_lock);
677                 GOTO(out, rc = PTR_ERR(nodemap));
678         }
679
680         if (is_default_nodemap(nodemap))
681                 rc = -EINVAL;
682         else
683                 rc = nodemap_add_range_helper(active_config, nodemap, nid);
684         mutex_unlock(&active_config_lock);
685
686         nodemap_putref(nodemap);
687 out:
688         return rc;
689 }
690 EXPORT_SYMBOL(nodemap_add_range);
691
692 /**
693  * delete a range
694  * \param       name            nodemap name
695  * \param       range_str       string containing range
696  * \retval      0 on success
697  *
698  * Delete range from global range tree, and remove it
699  * from the list in the associated nodemap.
700  */
701 int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
702 {
703         struct lu_nodemap       *nodemap;
704         struct lu_nid_range     *range;
705         int                     rc = 0;
706
707         mutex_lock(&active_config_lock);
708         nodemap = nodemap_lookup(name);
709         if (IS_ERR(nodemap)) {
710                 mutex_unlock(&active_config_lock);
711                 GOTO(out, rc = PTR_ERR(nodemap));
712         }
713
714         if (is_default_nodemap(nodemap))
715                 GOTO(out_putref, rc = -EINVAL);
716
717         down_write(&active_config->nmc_range_tree_lock);
718         range = range_find(&active_config->nmc_range_tree, nid[0], nid[1]);
719         if (range == NULL) {
720                 up_write(&active_config->nmc_range_tree_lock);
721                 GOTO(out_putref, rc = -EINVAL);
722         }
723         range_delete(&active_config->nmc_range_tree, range);
724         nm_member_reclassify_nodemap(nodemap);
725         up_write(&active_config->nmc_range_tree_lock);
726
727         nm_member_revoke_locks(active_config->nmc_default_nodemap);
728         nm_member_revoke_locks(nodemap);
729
730 out_putref:
731         mutex_unlock(&active_config_lock);
732         nodemap_putref(nodemap);
733 out:
734         return rc;
735 }
736 EXPORT_SYMBOL(nodemap_del_range);
737
738 /**
739  * Nodemap constructor
740  *
741  * Creates an lu_nodemap structure and assigns sane default
742  * member values. If this is the default nodemap, the defaults
743  * are the most restictive in xterms of mapping behavior. Otherwise
744  * the default flags should be inherited from the default nodemap.
745  * The adds nodemap to nodemap_hash.
746  *
747  * Requires that the caller take the active_config_lock
748  *
749  * \param       name            name of nodemap
750  * \param       is_default      true if default nodemap
751  * \retval      nodemap         success
752  * \retval      -EINVAL         invalid nodemap name
753  * \retval      -EEXIST         nodemap already exists
754  * \retval      -ENOMEM         cannot allocate memory for nodemap
755  */
756 struct lu_nodemap *nodemap_create(const char *name,
757                                   struct nodemap_config *config,
758                                   bool is_default)
759 {
760         struct lu_nodemap       *nodemap = NULL;
761         struct cfs_hash         *hash = config->nmc_nodemap_hash;
762         int                      rc = 0;
763
764         if (!nodemap_name_is_valid(name))
765                 GOTO(out, rc = -EINVAL);
766
767         if (hash == NULL) {
768                 CERROR("Config nodemap hash is NULL, unable to add %s\n", name);
769                 GOTO(out, rc = -EINVAL);
770         }
771
772         OBD_ALLOC_PTR(nodemap);
773         if (nodemap == NULL) {
774                 CERROR("cannot allocate memory (%zu bytes)"
775                        "for nodemap '%s'\n", sizeof(*nodemap),
776                        name);
777                 GOTO(out, rc = -ENOMEM);
778         }
779
780         /*
781          * take an extra reference to prevent nodemap from being destroyed
782          * while it's being created.
783          */
784         atomic_set(&nodemap->nm_refcount, 2);
785         snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
786         rc = cfs_hash_add_unique(hash, name, &nodemap->nm_hash);
787         if (rc != 0) {
788                 OBD_FREE_PTR(nodemap);
789                 GOTO(out, rc = -EEXIST);
790         }
791
792         INIT_LIST_HEAD(&nodemap->nm_ranges);
793         INIT_LIST_HEAD(&nodemap->nm_list);
794         INIT_LIST_HEAD(&nodemap->nm_member_list);
795
796         mutex_init(&nodemap->nm_member_list_lock);
797         rwlock_init(&nodemap->nm_idmap_lock);
798         nodemap->nm_fs_to_client_uidmap = RB_ROOT;
799         nodemap->nm_client_to_fs_uidmap = RB_ROOT;
800         nodemap->nm_fs_to_client_gidmap = RB_ROOT;
801         nodemap->nm_client_to_fs_gidmap = RB_ROOT;
802
803         if (is_default) {
804                 nodemap->nm_id = LUSTRE_NODEMAP_DEFAULT_ID;
805                 nodemap->nmf_trust_client_ids = 0;
806                 nodemap->nmf_allow_root_access = 0;
807                 nodemap->nmf_block_lookups = 0;
808
809                 nodemap->nm_squash_uid = NODEMAP_NOBODY_UID;
810                 nodemap->nm_squash_gid = NODEMAP_NOBODY_GID;
811
812                 config->nmc_default_nodemap = nodemap;
813         } else {
814                 struct lu_nodemap *default_nodemap =
815                                         config->nmc_default_nodemap;
816
817                 config->nmc_nodemap_highest_id++;
818                 nodemap->nm_id = config->nmc_nodemap_highest_id;
819                 nodemap->nmf_trust_client_ids =
820                                 default_nodemap->nmf_trust_client_ids;
821                 nodemap->nmf_allow_root_access =
822                                 default_nodemap->nmf_allow_root_access;
823                 nodemap->nmf_block_lookups =
824                                 default_nodemap->nmf_block_lookups;
825
826                 nodemap->nm_squash_uid = default_nodemap->nm_squash_uid;
827                 nodemap->nm_squash_gid = default_nodemap->nm_squash_gid;
828         }
829
830         return nodemap;
831
832 out:
833         CERROR("cannot add nodemap: '%s': rc = %d\n", name, rc);
834         return ERR_PTR(rc);
835 }
836
837 /**
838  * update flag to turn on or off nodemap functions
839  * \param       name            nodemap name
840  * \param       admin_string    string containing updated value
841  * \retval      0 on success
842  *
843  * Update admin flag to turn on or off nodemap functions.
844  */
845 int nodemap_set_allow_root(const char *name, bool allow_root)
846 {
847         struct lu_nodemap       *nodemap = NULL;
848         int                     rc = 0;
849
850         mutex_lock(&active_config_lock);
851         nodemap = nodemap_lookup(name);
852         mutex_unlock(&active_config_lock);
853         if (IS_ERR(nodemap))
854                 GOTO(out, rc = PTR_ERR(nodemap));
855
856         nodemap->nmf_allow_root_access = allow_root;
857
858         nm_member_revoke_locks(nodemap);
859         nodemap_putref(nodemap);
860 out:
861         return rc;
862 }
863 EXPORT_SYMBOL(nodemap_set_allow_root);
864
865 /**
866  * updated trust_client_ids flag for nodemap
867  *
868  * \param       name            nodemap name
869  * \param       trust_string    new value for trust flag
870  * \retval      0 on success
871  *
872  * Update the trust_client_ids flag for a nodemap.
873  */
874 int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids)
875 {
876         struct lu_nodemap       *nodemap = NULL;
877         int                     rc = 0;
878
879         mutex_lock(&active_config_lock);
880         nodemap = nodemap_lookup(name);
881         mutex_unlock(&active_config_lock);
882         if (IS_ERR(nodemap))
883                 GOTO(out, rc = PTR_ERR(nodemap));
884
885         nodemap->nmf_trust_client_ids = trust_client_ids;
886
887         nm_member_revoke_locks(nodemap);
888         nodemap_putref(nodemap);
889 out:
890         return rc;
891 }
892 EXPORT_SYMBOL(nodemap_set_trust_client_ids);
893
894 /**
895  * update the squash_uid for a nodemap
896  *
897  * \param       name            nodemap name
898  * \param       uid_string      string containing new squash_uid value
899  * \retval      0 on success
900  *
901  * Update the squash_uid for a nodemap. The squash_uid is the uid
902  * that the all client uids are mapped to if nodemap is active,
903  * the trust_client_ids flag is not set, and the uid is not in
904  * the idmap tree.
905  */
906 int nodemap_set_squash_uid(const char *name, uid_t uid)
907 {
908         struct lu_nodemap       *nodemap = NULL;
909         int                     rc = 0;
910
911         mutex_lock(&active_config_lock);
912         nodemap = nodemap_lookup(name);
913         mutex_unlock(&active_config_lock);
914         if (IS_ERR(nodemap))
915                 GOTO(out, rc = PTR_ERR(nodemap));
916
917         nodemap->nm_squash_uid = uid;
918
919         nm_member_revoke_locks(nodemap);
920         nodemap_putref(nodemap);
921 out:
922         return rc;
923 }
924 EXPORT_SYMBOL(nodemap_set_squash_uid);
925
926 /**
927  * Update the squash_gid for a nodemap.
928  *
929  * \param       name            nodemap name
930  * \param       gid_string      string containing new squash_gid value
931  * \retval      0 on success
932  *
933  * Update the squash_gid for a nodemap. The squash_uid is the gid
934  * that the all client gids are mapped to if nodemap is active,
935  * the trust_client_ids flag is not set, and the gid is not in
936  * the idmap tree.
937  */
938 int nodemap_set_squash_gid(const char *name, gid_t gid)
939 {
940         struct lu_nodemap       *nodemap = NULL;
941         int                     rc = 0;
942
943         mutex_lock(&active_config_lock);
944         nodemap = nodemap_lookup(name);
945         mutex_unlock(&active_config_lock);
946         if (IS_ERR(nodemap))
947                 GOTO(out, rc = PTR_ERR(nodemap));
948
949         nodemap->nm_squash_gid = gid;
950
951         nm_member_revoke_locks(nodemap);
952         nodemap_putref(nodemap);
953 out:
954         return rc;
955 }
956 EXPORT_SYMBOL(nodemap_set_squash_gid);
957
958 /**
959  * Returns true if this nodemap has root user access. Always returns true if
960  * nodemaps are not active.
961  *
962  * \param       nodemap         nodemap to check access for
963  */
964 bool nodemap_can_setquota(const struct lu_nodemap *nodemap)
965 {
966         return !nodemap_active || nodemap->nmf_allow_root_access;
967 }
968 EXPORT_SYMBOL(nodemap_can_setquota);
969
970 /**
971  * Add a nodemap
972  *
973  * \param       name            name of nodemap
974  * \retval      0               success
975  * \retval      -EINVAL         invalid nodemap name
976  * \retval      -EEXIST         nodemap already exists
977  * \retval      -ENOMEM         cannot allocate memory for nodemap
978  */
979 int nodemap_add(const char *nodemap_name)
980 {
981         struct lu_nodemap *nodemap;
982         int rc;
983
984         mutex_lock(&active_config_lock);
985         nodemap = nodemap_create(nodemap_name, active_config, 0);
986         if (IS_ERR(nodemap)) {
987                 mutex_unlock(&active_config_lock);
988                 return PTR_ERR(nodemap);
989         }
990
991         rc = lprocfs_nodemap_register(nodemap, 0);
992         mutex_unlock(&active_config_lock);
993         nodemap_putref(nodemap);
994
995         return rc;
996 }
997 EXPORT_SYMBOL(nodemap_add);
998
999 /**
1000  * Delete a nodemap
1001  *
1002  * \param       name            name of nodemmap
1003  * \retval      0               success
1004  * \retval      -EINVAL         invalid input
1005  * \retval      -ENOENT         no existing nodemap
1006  */
1007 int nodemap_del(const char *nodemap_name)
1008 {
1009         struct lu_nodemap       *nodemap;
1010         struct lu_nid_range     *range;
1011         struct lu_nid_range     *range_temp;
1012         int                      rc = 0;
1013
1014         if (strcmp(nodemap_name, DEFAULT_NODEMAP) == 0)
1015                 RETURN(-EINVAL);
1016
1017         mutex_lock(&active_config_lock);
1018         nodemap = cfs_hash_del_key(active_config->nmc_nodemap_hash,
1019                                    nodemap_name);
1020         if (nodemap == NULL) {
1021                 mutex_unlock(&active_config_lock);
1022                 GOTO(out, rc = -ENOENT);
1023         }
1024
1025         /* erase nodemap from active ranges to prevent client assignment */
1026         down_write(&active_config->nmc_range_tree_lock);
1027         list_for_each_entry_safe(range, range_temp, &nodemap->nm_ranges,
1028                                  rn_list)
1029                 range_delete(&active_config->nmc_range_tree, range);
1030         up_write(&active_config->nmc_range_tree_lock);
1031
1032         /*
1033          * remove procfs here in case nodemap_create called with same name
1034          * before nodemap_destroy is run.
1035          */
1036         lprocfs_nodemap_remove(nodemap->nm_pde_data);
1037         nodemap->nm_pde_data = NULL;
1038         mutex_unlock(&active_config_lock);
1039
1040         nodemap_putref(nodemap);
1041
1042 out:
1043         return rc;
1044 }
1045 EXPORT_SYMBOL(nodemap_del);
1046
1047 /**
1048  * activate nodemap functions
1049  *
1050  * \param       value           1 for on, 0 for off
1051  */
1052 void nodemap_activate(const bool value)
1053 {
1054         mutex_lock(&active_config_lock);
1055         active_config->nmc_nodemap_is_active = value;
1056
1057         /* copy active value to global to avoid locking in map functions */
1058         nodemap_active = value;
1059         mutex_unlock(&active_config_lock);
1060         nm_member_revoke_all();
1061 }
1062 EXPORT_SYMBOL(nodemap_activate);
1063
1064 /**
1065  * Helper iterator to convert nodemap hash to list.
1066  *
1067  * \param       hs                      hash structure
1068  * \param       bd                      bucket descriptor
1069  * \param       hnode                   hash node
1070  * \param       nodemap_list_head       list head for list of nodemaps in hash
1071  */
1072 static int nodemap_cleanup_iter_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd,
1073                                    struct hlist_node *hnode,
1074                                    void *nodemap_list_head)
1075 {
1076         struct lu_nodemap *nodemap;
1077
1078         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
1079         list_add(&nodemap->nm_list, nodemap_list_head);
1080
1081         cfs_hash_bd_del_locked(hs, bd, hnode);
1082
1083         return 0;
1084 }
1085
1086 /**
1087  * Walk the nodemap_hash and remove all nodemaps.
1088  */
1089 void nodemap_config_cleanup(struct nodemap_config *config)
1090 {
1091         struct lu_nodemap       *nodemap = NULL;
1092         struct lu_nodemap       *nodemap_temp;
1093         struct lu_nid_range     *range;
1094         struct lu_nid_range     *range_temp;
1095         LIST_HEAD(nodemap_list_head);
1096
1097         cfs_hash_for_each_safe(config->nmc_nodemap_hash,
1098                                nodemap_cleanup_iter_cb, &nodemap_list_head);
1099         cfs_hash_putref(config->nmc_nodemap_hash);
1100
1101         /* Because nodemap_destroy might sleep, we can't destroy them
1102          * in cfs_hash_for_each, so we build a list there and destroy here
1103          */
1104         list_for_each_entry_safe(nodemap, nodemap_temp, &nodemap_list_head,
1105                                  nm_list) {
1106                 down_write(&config->nmc_range_tree_lock);
1107                 list_for_each_entry_safe(range, range_temp, &nodemap->nm_ranges,
1108                                          rn_list)
1109                         range_delete(&config->nmc_range_tree, range);
1110                 up_write(&config->nmc_range_tree_lock);
1111
1112                 nodemap_putref(nodemap);
1113         }
1114 }
1115
1116 struct nodemap_config *nodemap_config_alloc(void)
1117 {
1118         struct nodemap_config *config;
1119         int rc = 0;
1120
1121         OBD_ALLOC_PTR(config);
1122         if (config == NULL)
1123                 return ERR_PTR(-ENOMEM);
1124
1125         rc = nodemap_init_hash(config);
1126         if (rc != 0) {
1127                 OBD_FREE_PTR(config);
1128                 return ERR_PTR(rc);
1129         }
1130
1131         init_rwsem(&config->nmc_range_tree_lock);
1132
1133         return config;
1134 }
1135
1136 void nodemap_config_dealloc(struct nodemap_config *config)
1137 {
1138         nodemap_config_cleanup(config);
1139         OBD_FREE_PTR(config);
1140 }
1141
1142 static int nm_hash_list_cb(struct cfs_hash *hs, struct cfs_hash_bd *bd,
1143                            struct hlist_node *hnode,
1144                            void *nodemap_list_head)
1145 {
1146         struct lu_nodemap *nodemap;
1147
1148         nodemap = hlist_entry(hnode, struct lu_nodemap, nm_hash);
1149         list_add(&nodemap->nm_list, nodemap_list_head);
1150         return 0;
1151 }
1152
1153 void nodemap_config_set_active(struct nodemap_config *config)
1154 {
1155         struct nodemap_config   *old_config = active_config;
1156         struct lu_nodemap       *nodemap;
1157         struct lu_nodemap       *tmp;
1158         LIST_HEAD(nodemap_list_head);
1159
1160         ENTRY;
1161
1162         LASSERT(active_config != config);
1163
1164         mutex_lock(&active_config_lock);
1165
1166         /* move proc entries from already existing nms, create for new nms */
1167         cfs_hash_for_each_safe(config->nmc_nodemap_hash,
1168                                nm_hash_list_cb, &nodemap_list_head);
1169         list_for_each_entry_safe(nodemap, tmp, &nodemap_list_head, nm_list) {
1170                 struct lu_nodemap *old_nm = NULL;
1171
1172                 if (active_config != NULL)
1173                         old_nm = cfs_hash_lookup(
1174                                         active_config->nmc_nodemap_hash,
1175                                         nodemap->nm_name);
1176                 if (old_nm != NULL) {
1177                         nodemap->nm_pde_data = old_nm->nm_pde_data;
1178                         old_nm->nm_pde_data = NULL;
1179                         nodemap_putref(old_nm);
1180                 } else {
1181                         bool is_def = (nodemap == config->nmc_default_nodemap);
1182
1183                         lprocfs_nodemap_register(nodemap, is_def);
1184                 }
1185         }
1186
1187         /* if new config is inactive, deactivate live config before switching */
1188         if (!config->nmc_nodemap_is_active)
1189                 nodemap_active = false;
1190         active_config = config;
1191         if (config->nmc_nodemap_is_active)
1192                 nodemap_active = true;
1193
1194         mutex_unlock(&active_config_lock);
1195
1196         if (old_config != NULL)
1197                 nodemap_config_dealloc(old_config);
1198
1199         nm_member_revoke_all();
1200
1201         EXIT;
1202 }
1203
1204 /**
1205  * Cleanup nodemap module on exit
1206  */
1207 void nodemap_mod_exit(void)
1208 {
1209         nodemap_config_dealloc(active_config);
1210         nodemap_procfs_exit();
1211 }
1212
1213 /**
1214  * Initialize the nodemap module
1215  */
1216 int nodemap_mod_init(void)
1217 {
1218         struct nodemap_config   *new_config;
1219         struct lu_nodemap       *nodemap;
1220         int                      rc = 0;
1221
1222         rc = nodemap_procfs_init();
1223         if (rc != 0)
1224                 return rc;
1225
1226         new_config = nodemap_config_alloc();
1227         if (IS_ERR(new_config)) {
1228                 nodemap_procfs_exit();
1229                 GOTO(out, rc = PTR_ERR(new_config));
1230         }
1231
1232         nodemap = nodemap_create(DEFAULT_NODEMAP, new_config, 1);
1233         if (IS_ERR(nodemap)) {
1234                 nodemap_config_dealloc(new_config);
1235                 nodemap_procfs_exit();
1236                 GOTO(out, rc = PTR_ERR(nodemap));
1237         }
1238
1239         nodemap_config_set_active(new_config);
1240         nodemap_putref(nodemap);
1241
1242 out:
1243         return rc;
1244 }
1245
1246 /**
1247  * Revoke locks for all nodemaps.
1248  */
1249 void nm_member_revoke_all(void)
1250 {
1251         struct lu_nodemap *nodemap;
1252         struct lu_nodemap *tmp;
1253         LIST_HEAD(nodemap_list_head);
1254
1255         mutex_lock(&active_config_lock);
1256         cfs_hash_for_each_safe(active_config->nmc_nodemap_hash,
1257                                nm_hash_list_cb, &nodemap_list_head);
1258
1259         /* revoke_locks sleeps, so can't call in cfs hash cb */
1260         list_for_each_entry_safe(nodemap, tmp, &nodemap_list_head, nm_list)
1261                 nm_member_revoke_locks(nodemap);
1262         mutex_unlock(&active_config_lock);
1263 }
1264
1265 /**
1266  * Returns the nodemap classification for a given nid into an ioctl buffer.
1267  * Useful for testing the nodemap configuration to make sure it is working as
1268  * expected.
1269  *
1270  * \param       nid             nid to classify
1271  * \param[out]  name_buf        buffer to write the nodemap name to
1272  * \param       name_len        length of buffer
1273  */
1274 void nodemap_test_nid(lnet_nid_t nid, char *name_buf, size_t name_len)
1275 {
1276         struct lu_nodemap       *nodemap;
1277
1278         mutex_lock(&active_config_lock);
1279         down_read(&active_config->nmc_range_tree_lock);
1280         nodemap = nodemap_classify_nid(nid);
1281         up_read(&active_config->nmc_range_tree_lock);
1282         mutex_unlock(&active_config_lock);
1283
1284         strncpy(name_buf, nodemap->nm_name, name_len);
1285         if (name_len > 0)
1286                 name_buf[name_len - 1] = '\0';
1287
1288         nodemap_putref(nodemap);
1289 }
1290 EXPORT_SYMBOL(nodemap_test_nid);
1291
1292 /**
1293  * Returns the id mapping for a given nid/id pair. Useful for testing the
1294  * nodemap configuration to make sure it is working as expected.
1295  *
1296  * \param       nid             nid to classify
1297  * \param       idtype          uid or gid
1298  * \param       client_id       id to map to fs
1299  *
1300  * \retval      the mapped fs_id of the given client_id
1301  */
1302 __u32 nodemap_test_id(lnet_nid_t nid, enum nodemap_id_type idtype,
1303                       __u32 client_id)
1304 {
1305         struct lu_nodemap       *nodemap;
1306         __u32                    fs_id;
1307
1308         mutex_lock(&active_config_lock);
1309         down_read(&active_config->nmc_range_tree_lock);
1310         nodemap = nodemap_classify_nid(nid);
1311         up_read(&active_config->nmc_range_tree_lock);
1312         mutex_unlock(&active_config_lock);
1313
1314         fs_id = nodemap_map_id(nodemap, idtype, NODEMAP_CLIENT_TO_FS,
1315                                client_id);
1316         nodemap_putref(nodemap);
1317
1318         return fs_id;
1319 }
1320 EXPORT_SYMBOL(nodemap_test_id);