Whamcloud - gitweb
LU-5092 nodemap: save id maps to targets in new index file
[fs/lustre-release.git] / lustre / ptlrpc / nodemap_storage.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) 2015, Trustees of Indiana University
24  *
25  * Copyright (c) 2014, Intel Corporation.
26  *
27  * Author: Joshua Walgenbach <jjw@iu.edu>
28  * Author: Kit Westneat <cwestnea@iu.edu>
29  *
30  * Implements the storage functionality for the nodemap configuration. Functions
31  * in this file prepare, store, and load nodemap configuration data. Targets
32  * using nodemap services should register a configuration file object. Nodemap
33  * configuration changes that need to persist should call the appropriate
34  * storage function for the data being modified.
35  *
36  * There are several index types as defined in enum nodemap_idx_type:
37  *      NODEMAP_CLUSTER_IDX     stores the data found on the lu_nodemap struct,
38  *                              like root squash and config flags, as well as
39  *                              the name.
40  *      NODEMAP_RANGE_IDX       stores NID range information for a nodemap
41  *      NODEMAP_UIDMAP_IDX      stores a fs/client UID mapping pair
42  *      NODEMAP_GIDMAP_IDX      stores a fs/client GID mapping pair
43  *      NODEMAP_GLOBAL_IDX      stores whether or not nodemaps are active
44  */
45
46 #include <libcfs/libcfs.h>
47 #include <linux/err.h>
48 #include <linux/kernel.h>
49 #include <linux/list.h>
50 #include <linux/mutex.h>
51 #include <linux/string.h>
52 #include <linux/types.h>
53 #include <lnet/types.h>
54 #include <lustre/lustre_idl.h>
55 #include <dt_object.h>
56 #include <lu_object.h>
57 #include <lustre_net.h>
58 #include <lustre_nodemap.h>
59 #include <obd_class.h>
60 #include <obd_support.h>
61 #include "nodemap_internal.h"
62
63 /* list of registered nodemap index files */
64 static LIST_HEAD(ncf_list_head);
65 static DEFINE_MUTEX(ncf_list_lock);
66
67 /* lu_nodemap flags */
68 enum nm_flag_shifts {
69         NM_FL_ALLOW_ROOT_ACCESS = 0x1,
70         NM_FL_TRUST_CLIENT_IDS = 0x2,
71 };
72
73 static void nodemap_cluster_key_init(struct nodemap_key *nk, unsigned int nm_id)
74 {
75         nk->nk_nodemap_id = cpu_to_le32(nm_idx_set_type(nm_id,
76                                                         NODEMAP_CLUSTER_IDX));
77         nk->nk_unused = 0;
78 }
79
80 static void nodemap_cluster_rec_init(union nodemap_rec *nr,
81                                      const struct lu_nodemap *nodemap)
82 {
83         CLASSERT(sizeof(nr->ncr.ncr_name) == sizeof(nodemap->nm_name));
84
85         strncpy(nr->ncr.ncr_name, nodemap->nm_name, sizeof(nodemap->nm_name));
86         nr->ncr.ncr_squash_uid = cpu_to_le32(nodemap->nm_squash_uid);
87         nr->ncr.ncr_squash_gid = cpu_to_le32(nodemap->nm_squash_gid);
88         nr->ncr.ncr_flags = cpu_to_le32(
89                 (nodemap->nmf_trust_client_ids ? NM_FL_TRUST_CLIENT_IDS : 0) |
90                 (nodemap->nmf_allow_root_access ? NM_FL_ALLOW_ROOT_ACCESS : 0));
91 }
92
93 static void nodemap_idmap_key_init(struct nodemap_key *nk, unsigned int nm_id,
94                                    enum nodemap_id_type id_type,
95                                    u32 id_client)
96 {
97         enum nodemap_idx_type idx_type;
98
99         if (id_type == NODEMAP_UID)
100                 idx_type = NODEMAP_UIDMAP_IDX;
101         else
102                 idx_type = NODEMAP_GIDMAP_IDX;
103
104         nk->nk_nodemap_id = cpu_to_le32(nm_idx_set_type(nm_id, idx_type));
105         nk->nk_id_client = cpu_to_le32(id_client);
106 }
107
108 static void nodemap_idmap_rec_init(union nodemap_rec *nr, u32 id_fs)
109 {
110         nr->nir.nir_id_fs = cpu_to_le32(id_fs);
111 }
112
113 static void nodemap_range_key_init(struct nodemap_key *nk, unsigned int nm_id,
114                                    unsigned int rn_id)
115 {
116         nk->nk_nodemap_id = cpu_to_le32(nm_idx_set_type(nm_id,
117                                                         NODEMAP_RANGE_IDX));
118         nk->nk_range_id = cpu_to_le32(rn_id);
119 }
120
121 static void nodemap_range_rec_init(union nodemap_rec *nr,
122                                    const lnet_nid_t nid[2])
123 {
124         nr->nrr.nrr_start_nid = cpu_to_le64(nid[0]);
125         nr->nrr.nrr_end_nid = cpu_to_le64(nid[1]);
126 }
127
128 static void nodemap_global_key_init(struct nodemap_key *nk)
129 {
130         nk->nk_nodemap_id = cpu_to_le32(nm_idx_set_type(0, NODEMAP_GLOBAL_IDX));
131         nk->nk_unused = 0;
132 }
133
134 static void nodemap_global_rec_init(union nodemap_rec *nr, bool active)
135 {
136         nr->ngr.ngr_is_active = active;
137 }
138
139 /* should be called with dt_write lock */
140 static void nodemap_inc_version(const struct lu_env *env,
141                                 struct dt_object *nodemap_idx,
142                                 struct thandle *th)
143 {
144         u64 ver = dt_version_get(env, nodemap_idx);
145         dt_version_set(env, nodemap_idx, ver + 1, th);
146 }
147
148 static int nodemap_idx_insert(struct lu_env *env,
149                               struct dt_object *idx,
150                               const struct nodemap_key *nk,
151                               const union nodemap_rec *nr)
152 {
153         struct thandle          *th;
154         struct dt_device        *dev = lu2dt_dev(idx->do_lu.lo_dev);
155         int                      rc;
156
157         CLASSERT(sizeof(union nodemap_rec) == 32);
158
159         th = dt_trans_create(env, dev);
160
161         if (IS_ERR(th))
162                 GOTO(out, rc = PTR_ERR(th));
163
164         rc = dt_declare_insert(env, idx,
165                                (const struct dt_rec *)nr,
166                                (const struct dt_key *)nk, th);
167         if (rc != 0)
168                 GOTO(out, rc);
169
170         rc = dt_declare_version_set(env, idx, th);
171         if (rc != 0)
172                 GOTO(out, rc);
173
174         rc = dt_trans_start_local(env, dev, th);
175         if (rc != 0)
176                 GOTO(out, rc);
177
178         dt_write_lock(env, idx, 0);
179
180         rc = dt_insert(env, idx, (const struct dt_rec *)nr,
181                        (const struct dt_key *)nk, th, 1);
182
183         nodemap_inc_version(env, idx, th);
184         dt_write_unlock(env, idx);
185 out:
186         dt_trans_stop(env, dev, th);
187
188         return rc;
189 }
190
191 static int nodemap_idx_update(struct lu_env *env,
192                               struct dt_object *idx,
193                               const struct nodemap_key *nk,
194                               const union nodemap_rec *nr)
195 {
196         struct thandle          *th;
197         struct dt_device        *dev = lu2dt_dev(idx->do_lu.lo_dev);
198         int                      rc = 0;
199
200         th = dt_trans_create(env, dev);
201
202         if (IS_ERR(th))
203                 GOTO(out, rc = PTR_ERR(th));
204
205         rc = dt_declare_delete(env, idx, (const struct dt_key *)nk, th);
206         if (rc != 0)
207                 GOTO(out, rc);
208
209         rc = dt_declare_insert(env, idx, (const struct dt_rec *)nr,
210                                (const struct dt_key *)nk, th);
211         if (rc != 0)
212                 GOTO(out, rc);
213
214         rc = dt_declare_version_set(env, idx, th);
215         if (rc != 0)
216                 GOTO(out, rc);
217
218         rc = dt_trans_start_local(env, dev, th);
219         if (rc != 0)
220                 GOTO(out, rc);
221
222         dt_write_lock(env, idx, 0);
223
224         rc = dt_delete(env, idx, (const struct dt_key *)nk, th);
225         if (rc != 0)
226                 GOTO(out_lock, rc);
227
228         rc = dt_insert(env, idx, (const struct dt_rec *)nr,
229                        (const struct dt_key *)nk, th, 1);
230         if (rc != 0)
231                 GOTO(out_lock, rc);
232
233         nodemap_inc_version(env, idx, th);
234 out_lock:
235         dt_write_unlock(env, idx);
236 out:
237         dt_trans_stop(env, dev, th);
238
239         return rc;
240 }
241
242 static int nodemap_idx_delete(struct lu_env *env,
243                               struct dt_object *idx,
244                               const struct nodemap_key *nk,
245                               const union nodemap_rec *unused)
246 {
247         struct thandle          *th;
248         struct dt_device        *dev = lu2dt_dev(idx->do_lu.lo_dev);
249         int                      rc = 0;
250
251         th = dt_trans_create(env, dev);
252
253         if (IS_ERR(th))
254                 GOTO(out, rc = PTR_ERR(th));
255
256         rc = dt_declare_delete(env, idx, (const struct dt_key *)nk, th);
257         if (rc != 0)
258                 GOTO(out, rc);
259
260         rc = dt_declare_version_set(env, idx, th);
261         if (rc != 0)
262                 GOTO(out, rc);
263
264         rc = dt_trans_start_local(env, dev, th);
265         if (rc != 0)
266                 GOTO(out, rc);
267
268         dt_write_lock(env, idx, 0);
269
270         rc = dt_delete(env, idx, (const struct dt_key *)nk, th);
271
272         nodemap_inc_version(env, idx, th);
273
274         dt_write_unlock(env, idx);
275 out:
276         dt_trans_stop(env, dev, th);
277
278         return rc;
279 }
280
281 typedef int (*nm_idx_cb_t)(struct lu_env *env,
282                            struct dt_object *idx,
283                            const struct nodemap_key *nk,
284                            const union nodemap_rec *nr);
285
286 /**
287  * Iterates through all the registered nodemap_config_files and calls the
288  * given callback with the ncf as a parameter, as well as the given key and rec.
289  *
290  * \param       cb_f            callback function to call
291  * \param       nk              key of the record to act upon
292  * \param       nr              record to act upon, NULL for the delete action
293  */
294 static int nodemap_idx_action(nm_idx_cb_t cb_f, struct nodemap_key *nk,
295                               union nodemap_rec *nr)
296 {
297         struct nm_config_file   *ncf;
298         struct lu_env            env;
299         int                      rc = 0;
300         int                      rc2 = 0;
301
302         rc = lu_env_init(&env, LCT_LOCAL);
303         if (rc != 0)
304                 return rc;
305
306         mutex_lock(&ncf_list_lock);
307         list_for_each_entry(ncf, &ncf_list_head, ncf_list) {
308                 rc2 = cb_f(&env, ncf->ncf_obj, nk, nr);
309                 if (rc2 < 0) {
310                         CWARN("%s: error writing to nodemap config: rc = %d\n",
311                               ncf->ncf_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
312                         rc = rc2;
313                 }
314         }
315         mutex_unlock(&ncf_list_lock);
316         lu_env_fini(&env);
317
318         return 0;
319 }
320
321 enum nm_add_update {
322         NM_ADD = 0,
323         NM_UPDATE = 1,
324 };
325
326 static int nodemap_idx_nodemap_add_update(const struct lu_nodemap *nodemap,
327                                           enum nm_add_update update)
328 {
329         struct nodemap_key       nk;
330         union nodemap_rec        nr;
331         int rc = 0;
332
333         ENTRY;
334
335         nodemap_cluster_key_init(&nk, nodemap->nm_id);
336         nodemap_cluster_rec_init(&nr, nodemap);
337
338         if (update == NM_UPDATE)
339                 rc = nodemap_idx_action(nodemap_idx_update, &nk, &nr);
340         else
341                 rc = nodemap_idx_action(nodemap_idx_insert, &nk, &nr);
342
343         RETURN(rc);
344 }
345
346 int nodemap_idx_nodemap_add(const struct lu_nodemap *nodemap)
347 {
348         return nodemap_idx_nodemap_add_update(nodemap, NM_ADD);
349 }
350
351 int nodemap_idx_nodemap_update(const struct lu_nodemap *nodemap)
352 {
353         return nodemap_idx_nodemap_add_update(nodemap, NM_UPDATE);
354 }
355
356 int nodemap_idx_nodemap_del(const struct lu_nodemap *nodemap)
357 {
358         struct rb_root           root;
359         struct lu_idmap         *idmap;
360         struct lu_idmap         *temp;
361         struct lu_nid_range     *range;
362         struct lu_nid_range     *range_temp;
363         struct nodemap_key       nk;
364         int                      rc = 0;
365         int                      rc2 = 0;
366
367         ENTRY;
368
369         root = nodemap->nm_fs_to_client_uidmap;
370         nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
371                                                 id_fs_to_client) {
372                 nodemap_idmap_key_init(&nk, nodemap->nm_id, NODEMAP_UID,
373                                        idmap->id_client);
374                 rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
375                 if (rc2 < 0)
376                         rc = rc2;
377         }
378
379         root = nodemap->nm_client_to_fs_gidmap;
380         nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
381                                                 id_client_to_fs) {
382                 nodemap_idmap_key_init(&nk, nodemap->nm_id, NODEMAP_GID,
383                                        idmap->id_client);
384                 rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
385                 if (rc2 < 0)
386                         rc = rc2;
387         }
388
389         list_for_each_entry_safe(range, range_temp, &nodemap->nm_ranges,
390                                  rn_list) {
391                 nodemap_range_key_init(&nk, nodemap->nm_id, range->rn_id);
392                 rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
393                 if (rc2 < 0)
394                         rc = rc2;
395         }
396
397         nodemap_cluster_key_init(&nk, nodemap->nm_id);
398         rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
399         if (rc2 < 0)
400                 rc = rc2;
401
402         RETURN(rc);
403 }
404
405 int nodemap_idx_range_add(const struct lu_nid_range *range,
406                           const lnet_nid_t nid[2])
407 {
408         struct nodemap_key       nk;
409         union nodemap_rec        nr;
410         ENTRY;
411
412         nodemap_range_key_init(&nk, range->rn_nodemap->nm_id, range->rn_id);
413         nodemap_range_rec_init(&nr, nid);
414
415         RETURN(nodemap_idx_action(nodemap_idx_insert, &nk, &nr));
416 }
417
418 int nodemap_idx_range_del(const struct lu_nid_range *range)
419 {
420         struct nodemap_key       nk;
421         ENTRY;
422
423         nodemap_range_key_init(&nk, range->rn_nodemap->nm_id, range->rn_id);
424
425         RETURN(nodemap_idx_action(nodemap_idx_delete, &nk, NULL));
426 }
427
428 int nodemap_idx_idmap_add(const struct lu_nodemap *nodemap,
429                           enum nodemap_id_type id_type,
430                           const u32 map[2])
431 {
432         struct nodemap_key       nk;
433         union nodemap_rec        nr;
434         ENTRY;
435
436         nodemap_idmap_key_init(&nk, nodemap->nm_id, id_type, map[0]);
437         nodemap_idmap_rec_init(&nr, map[1]);
438
439         RETURN(nodemap_idx_action(nodemap_idx_insert, &nk, &nr));
440 }
441
442 int nodemap_idx_idmap_del(const struct lu_nodemap *nodemap,
443                           enum nodemap_id_type id_type,
444                           const u32 map[2])
445 {
446         struct nodemap_key       nk;
447         ENTRY;
448
449         nodemap_idmap_key_init(&nk, nodemap->nm_id, id_type, map[0]);
450
451         RETURN(nodemap_idx_action(nodemap_idx_delete, &nk, NULL));
452 }
453
454 static int nodemap_idx_global_add_update(bool value, enum nm_add_update update)
455 {
456         struct nodemap_key       nk;
457         union nodemap_rec        nr;
458         ENTRY;
459
460         nodemap_global_key_init(&nk);
461         nodemap_global_rec_init(&nr, value);
462
463         if (update == NM_UPDATE)
464                 RETURN(nodemap_idx_action(nodemap_idx_update, &nk, &nr));
465         else
466                 RETURN(nodemap_idx_action(nodemap_idx_insert, &nk, &nr));
467 }
468
469 int nodemap_idx_nodemap_activate(bool value)
470 {
471         return nodemap_idx_global_add_update(value, NM_UPDATE);
472 }
473
474 /**
475  * Process a key/rec pair and modify the new configuration.
476  *
477  * \param       config          configuration to update with this key/rec data
478  * \param       key             key of the record that was loaded
479  * \param       rec             record that was loaded
480  * \param       recent_nodemap  last referenced nodemap
481  * \retval      type of record processed, see enum #nodemap_idx_type
482  * \retval      -ENOENT         range or map loaded before nodemap record
483  * \retval      -EINVAL         duplicate nodemap cluster records found with
484  *                              different IDs, or nodemap has invalid name
485  * \retval      -ENOMEM
486  */
487 static int nodemap_process_keyrec(struct nodemap_config *config,
488                                   const struct nodemap_key *key,
489                                   const union nodemap_rec *rec,
490                                   struct lu_nodemap **recent_nodemap)
491 {
492         struct lu_nodemap       *nodemap = NULL;
493         enum nodemap_idx_type    type;
494         enum nodemap_id_type     id_type;
495         u8                       flags;
496         u32                      nodemap_id;
497         lnet_nid_t               nid[2];
498         u32                      map[2];
499         int                      rc;
500
501         CLASSERT(sizeof(union nodemap_rec) == 32);
502
503         nodemap_id = le32_to_cpu(key->nk_nodemap_id);
504         type = nm_idx_get_type(nodemap_id);
505         nodemap_id = nm_idx_set_type(nodemap_id, 0);
506
507         /* find the correct nodemap in the load list */
508         if (type == NODEMAP_RANGE_IDX || type == NODEMAP_UIDMAP_IDX ||
509             type == NODEMAP_GIDMAP_IDX) {
510                 struct lu_nodemap *tmp = NULL;
511
512                 nodemap = *recent_nodemap;
513
514                 if (nodemap == NULL)
515                         GOTO(out, rc = -ENOENT);
516
517                 if (nodemap->nm_id != nodemap_id) {
518                         list_for_each_entry(tmp, &nodemap->nm_list, nm_list)
519                                 if (tmp->nm_id == nodemap_id) {
520                                         nodemap = tmp;
521                                         break;
522                                 }
523
524                         if (nodemap->nm_id != nodemap_id)
525                                 GOTO(out, rc = -ENOENT);
526                 }
527
528                 /* update most recently used nodemap if necessay */
529                 if (nodemap != *recent_nodemap)
530                         *recent_nodemap = nodemap;
531         }
532
533         switch (type) {
534         case NODEMAP_EMPTY_IDX:
535                 if (nodemap_id != 0)
536                         CWARN("Found nodemap config record without type field, "
537                               " nodemap_id=%d. nodemap config file corrupt?\n",
538                               nodemap_id);
539                 break;
540         case NODEMAP_CLUSTER_IDX:
541                 nodemap = cfs_hash_lookup(config->nmc_nodemap_hash,
542                                           rec->ncr.ncr_name);
543                 if (nodemap == NULL) {
544                         if (nodemap_id == LUSTRE_NODEMAP_DEFAULT_ID) {
545                                 nodemap = nodemap_create(rec->ncr.ncr_name,
546                                                          config, 1);
547                                 config->nmc_default_nodemap = nodemap;
548                         } else {
549                                 nodemap = nodemap_create(rec->ncr.ncr_name,
550                                                          config, 0);
551                         }
552                         if (IS_ERR(nodemap))
553                                 GOTO(out, rc = PTR_ERR(nodemap));
554
555                         /* we need to override the local ID with the saved ID */
556                         nodemap->nm_id = nodemap_id;
557                         if (nodemap_id > config->nmc_nodemap_highest_id)
558                                 config->nmc_nodemap_highest_id = nodemap_id;
559
560                 } else if (nodemap->nm_id != nodemap_id) {
561                         nodemap_putref(nodemap);
562                         GOTO(out, rc = -EINVAL);
563                 }
564
565                 nodemap->nm_squash_uid =
566                                 le32_to_cpu(rec->ncr.ncr_squash_uid);
567                 nodemap->nm_squash_gid =
568                                 le32_to_cpu(rec->ncr.ncr_squash_gid);
569
570                 flags = le32_to_cpu(rec->ncr.ncr_flags);
571                 nodemap->nmf_allow_root_access =
572                                         flags & NM_FL_ALLOW_ROOT_ACCESS;
573                 nodemap->nmf_trust_client_ids =
574                                         flags & NM_FL_TRUST_CLIENT_IDS;
575
576                 if (*recent_nodemap == NULL) {
577                         *recent_nodemap = nodemap;
578                         INIT_LIST_HEAD(&nodemap->nm_list);
579                 } else {
580                         list_add(&nodemap->nm_list,
581                                  &(*recent_nodemap)->nm_list);
582                 }
583                 nodemap_putref(nodemap);
584                 break;
585         case NODEMAP_RANGE_IDX:
586                 nid[0] = le64_to_cpu(rec->nrr.nrr_start_nid);
587                 nid[1] = le64_to_cpu(rec->nrr.nrr_end_nid);
588
589                 rc = nodemap_add_range_helper(config, nodemap, nid,
590                                         le32_to_cpu(key->nk_range_id));
591                 if (rc != 0)
592                         GOTO(out, rc);
593                 break;
594         case NODEMAP_UIDMAP_IDX:
595         case NODEMAP_GIDMAP_IDX:
596                 map[0] = le32_to_cpu(key->nk_id_client);
597                 map[1] = le32_to_cpu(rec->nir.nir_id_fs);
598
599                 if (type == NODEMAP_UIDMAP_IDX)
600                         id_type = NODEMAP_UID;
601                 else
602                         id_type = NODEMAP_GID;
603
604                 rc = nodemap_add_idmap_helper(nodemap, id_type, map);
605                 if (rc != 0)
606                         GOTO(out, rc);
607                 break;
608         case NODEMAP_GLOBAL_IDX:
609                 config->nmc_nodemap_is_active = rec->ngr.ngr_is_active;
610                 break;
611         default:
612                 CERROR("got keyrec pair for unknown type %d\n", type);
613                 break;
614         }
615         rc = type;
616
617 out:
618         return rc;
619 }
620
621 static int nodemap_load_entries(const struct lu_env *env,
622                                 struct dt_object *nodemap_idx)
623 {
624         const struct dt_it_ops  *iops;
625         struct dt_it            *it;
626         struct lu_nodemap       *recent_nodemap = NULL;
627         struct nodemap_config   *new_config = NULL;
628         u64                      hash = 0;
629         bool                     activate_nodemap = false;
630         bool                     loaded_global_idx = false;
631         int                      rc = 0;
632
633         ENTRY;
634
635         iops = &nodemap_idx->do_index_ops->dio_it;
636
637         dt_read_lock(env, nodemap_idx, 0);
638         it = iops->init(env, nodemap_idx, 0);
639         if (IS_ERR(it))
640                 GOTO(out, rc = PTR_ERR(it));
641
642         rc = iops->load(env, it, hash);
643         if (rc == 0) {
644                 rc = iops->next(env, it);
645                 if (rc != 0)
646                         GOTO(out_iops, rc = 0);
647         }
648
649         /* acquires active config lock */
650         new_config = nodemap_config_alloc();
651
652         if (IS_ERR(new_config)) {
653                 rc = PTR_ERR(new_config);
654                 new_config = NULL;
655                 GOTO(out_lock, rc);
656         }
657
658         do {
659                 struct nodemap_key *key;
660                 union nodemap_rec rec;
661
662                 key = (struct nodemap_key *)iops->key(env, it);
663                 rc = iops->rec(env, it, (struct dt_rec *)&rec, 0);
664                 if (rc != -ESTALE) {
665                         if (rc != 0)
666                                 GOTO(out_lock, rc);
667                         rc = nodemap_process_keyrec(new_config, key, &rec,
668                                                     &recent_nodemap);
669                         if (rc < 0)
670                                 GOTO(out_lock, rc);
671                         if (rc == NODEMAP_GLOBAL_IDX)
672                                 loaded_global_idx = true;
673                 }
674
675                 do
676                         rc = iops->next(env, it);
677                 while (rc == -ESTALE);
678         } while (rc == 0);
679
680         if (rc > 0)
681                 rc = 0;
682
683 out_lock:
684         if (rc != 0)
685                 nodemap_config_dealloc(new_config);
686         else
687                 /* creating new default needs to be done outside dt read lock */
688                 activate_nodemap = true;
689 out_iops:
690         iops->put(env, it);
691         iops->fini(env, it);
692 out:
693         dt_read_unlock(env, nodemap_idx);
694
695         if (rc != 0)
696                 CWARN("%s: failed to load nodemap configuration: rc = %d\n",
697                       nodemap_idx->do_lu.lo_dev->ld_obd->obd_name, rc);
698
699         if (!activate_nodemap)
700                 RETURN(rc);
701
702         if (new_config->nmc_default_nodemap == NULL) {
703                 /* new MGS won't have a default nm on disk, so create it here */
704                 new_config->nmc_default_nodemap =
705                         nodemap_create(DEFAULT_NODEMAP, new_config, 1);
706                 if (IS_ERR(new_config->nmc_default_nodemap)) {
707                         rc = PTR_ERR(new_config->nmc_default_nodemap);
708                 } else {
709                         rc = nodemap_idx_nodemap_add_update(
710                                         new_config->nmc_default_nodemap, 0);
711                         nodemap_putref(new_config->nmc_default_nodemap);
712                 }
713         }
714
715         /* new nodemap config won't have an active/inactive record */
716         if (rc == 0 && loaded_global_idx == false)
717                 rc = nodemap_idx_global_add_update(false, NM_ADD);
718
719         if (rc == 0)
720                 nodemap_config_set_active(new_config);
721         else
722                 nodemap_config_dealloc(new_config);
723
724         RETURN(rc);
725 }
726
727 /**
728  * Register a dt_object representing the config index file. This should be
729  * called by targets in order to load the nodemap configuration from disk. The
730  * dt_object should be created with local_index_find_or_create and the index
731  * features should be enabled with do_index_try.
732  *
733  * \param obj   dt_object returned by local_index_find_or_create
734  *
735  * \retval      on success: nm_config_file handle for later deregistration
736  * \retval      -ENOMEM         memory allocation failure
737  * \retval      -ENOENT         error loading nodemap config
738  * \retval      -EINVAL         error loading nodemap config
739  */
740 struct nm_config_file *nm_config_file_register(const struct lu_env *env,
741                                                struct dt_object *obj)
742 {
743         struct nm_config_file *ncf;
744         bool load_entries = false;
745         int rc;
746         ENTRY;
747
748         OBD_ALLOC_PTR(ncf);
749         if (ncf == NULL)
750                 RETURN(ERR_PTR(-ENOMEM));
751
752         ncf->ncf_obj = obj;
753         mutex_lock(&ncf_list_lock);
754
755         /* if this is first config file, we load it from disk */
756         if (list_empty(&ncf_list_head))
757                 load_entries = true;
758
759         list_add(&ncf->ncf_list, &ncf_list_head);
760         mutex_unlock(&ncf_list_lock);
761
762         if (load_entries) {
763                 rc = nodemap_load_entries(env, obj);
764                 if (rc < 0) {
765                         mutex_lock(&ncf_list_lock);
766                         list_del(&ncf->ncf_list);
767                         mutex_unlock(&ncf_list_lock);
768                         OBD_FREE_PTR(ncf);
769                         RETURN(ERR_PTR(rc));
770                 }
771         }
772
773         RETURN(ncf);
774 }
775 EXPORT_SYMBOL(nm_config_file_register);
776
777 /**
778  * Deregister a nm_config_file. Should be called by targets during cleanup.
779  *
780  * \param ncf   config file to deregister
781  */
782 void nm_config_file_deregister(const struct lu_env *env,
783                                struct nm_config_file *ncf)
784 {
785         ENTRY;
786
787         lu_object_put(env, &ncf->ncf_obj->do_lu);
788
789         mutex_lock(&ncf_list_lock);
790         list_del(&ncf->ncf_list);
791         mutex_unlock(&ncf_list_lock);
792         OBD_FREE_PTR(ncf);
793
794         EXIT;
795 }
796 EXPORT_SYMBOL(nm_config_file_deregister);