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