4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (C) 2015, Trustees of Indiana University
25 * Copyright (c) 2014, Intel Corporation.
27 * Author: Joshua Walgenbach <jjw@iu.edu>
28 * Author: Kit Westneat <cwestnea@iu.edu>
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.
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
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
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"
63 /* list of registered nodemap index files */
64 static LIST_HEAD(ncf_list_head);
65 static DEFINE_MUTEX(ncf_list_lock);
67 /* lu_nodemap flags */
69 NM_FL_ALLOW_ROOT_ACCESS = 0x1,
70 NM_FL_TRUST_CLIENT_IDS = 0x2,
73 static void nodemap_cluster_key_init(struct nodemap_key *nk, unsigned int nm_id)
75 nk->nk_nodemap_id = cpu_to_le32(nm_idx_set_type(nm_id,
76 NODEMAP_CLUSTER_IDX));
80 static void nodemap_cluster_rec_init(union nodemap_rec *nr,
81 const struct lu_nodemap *nodemap)
83 CLASSERT(sizeof(nr->ncr.ncr_name) == sizeof(nodemap->nm_name));
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));
93 static void nodemap_idmap_key_init(struct nodemap_key *nk, unsigned int nm_id,
94 enum nodemap_id_type id_type,
97 enum nodemap_idx_type idx_type;
99 if (id_type == NODEMAP_UID)
100 idx_type = NODEMAP_UIDMAP_IDX;
102 idx_type = NODEMAP_GIDMAP_IDX;
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);
108 static void nodemap_idmap_rec_init(union nodemap_rec *nr, u32 id_fs)
110 nr->nir.nir_id_fs = cpu_to_le32(id_fs);
113 static void nodemap_range_key_init(struct nodemap_key *nk, unsigned int nm_id,
116 nk->nk_nodemap_id = cpu_to_le32(nm_idx_set_type(nm_id,
118 nk->nk_range_id = cpu_to_le32(rn_id);
121 static void nodemap_range_rec_init(union nodemap_rec *nr,
122 const lnet_nid_t nid[2])
124 nr->nrr.nrr_start_nid = cpu_to_le64(nid[0]);
125 nr->nrr.nrr_end_nid = cpu_to_le64(nid[1]);
128 static void nodemap_global_key_init(struct nodemap_key *nk)
130 nk->nk_nodemap_id = cpu_to_le32(nm_idx_set_type(0, NODEMAP_GLOBAL_IDX));
134 static void nodemap_global_rec_init(union nodemap_rec *nr, bool active)
136 nr->ngr.ngr_is_active = active;
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,
144 u64 ver = dt_version_get(env, nodemap_idx);
145 dt_version_set(env, nodemap_idx, ver + 1, th);
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)
154 struct dt_device *dev = lu2dt_dev(idx->do_lu.lo_dev);
157 CLASSERT(sizeof(union nodemap_rec) == 32);
159 th = dt_trans_create(env, dev);
162 GOTO(out, rc = PTR_ERR(th));
164 rc = dt_declare_insert(env, idx,
165 (const struct dt_rec *)nr,
166 (const struct dt_key *)nk, th);
170 rc = dt_declare_version_set(env, idx, th);
174 rc = dt_trans_start_local(env, dev, th);
178 dt_write_lock(env, idx, 0);
180 rc = dt_insert(env, idx, (const struct dt_rec *)nr,
181 (const struct dt_key *)nk, th, 1);
183 nodemap_inc_version(env, idx, th);
184 dt_write_unlock(env, idx);
186 dt_trans_stop(env, dev, th);
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)
197 struct dt_device *dev = lu2dt_dev(idx->do_lu.lo_dev);
200 th = dt_trans_create(env, dev);
203 GOTO(out, rc = PTR_ERR(th));
205 rc = dt_declare_delete(env, idx, (const struct dt_key *)nk, th);
209 rc = dt_declare_insert(env, idx, (const struct dt_rec *)nr,
210 (const struct dt_key *)nk, th);
214 rc = dt_declare_version_set(env, idx, th);
218 rc = dt_trans_start_local(env, dev, th);
222 dt_write_lock(env, idx, 0);
224 rc = dt_delete(env, idx, (const struct dt_key *)nk, th);
228 rc = dt_insert(env, idx, (const struct dt_rec *)nr,
229 (const struct dt_key *)nk, th, 1);
233 nodemap_inc_version(env, idx, th);
235 dt_write_unlock(env, idx);
237 dt_trans_stop(env, dev, th);
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)
248 struct dt_device *dev = lu2dt_dev(idx->do_lu.lo_dev);
251 th = dt_trans_create(env, dev);
254 GOTO(out, rc = PTR_ERR(th));
256 rc = dt_declare_delete(env, idx, (const struct dt_key *)nk, th);
260 rc = dt_declare_version_set(env, idx, th);
264 rc = dt_trans_start_local(env, dev, th);
268 dt_write_lock(env, idx, 0);
270 rc = dt_delete(env, idx, (const struct dt_key *)nk, th);
272 nodemap_inc_version(env, idx, th);
274 dt_write_unlock(env, idx);
276 dt_trans_stop(env, dev, th);
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);
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.
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
294 static int nodemap_idx_action(nm_idx_cb_t cb_f, struct nodemap_key *nk,
295 union nodemap_rec *nr)
297 struct nm_config_file *ncf;
302 rc = lu_env_init(&env, LCT_LOCAL);
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);
310 CWARN("%s: error writing to nodemap config: rc = %d\n",
311 ncf->ncf_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
315 mutex_unlock(&ncf_list_lock);
326 static int nodemap_idx_nodemap_add_update(const struct lu_nodemap *nodemap,
327 enum nm_add_update update)
329 struct nodemap_key nk;
330 union nodemap_rec nr;
335 nodemap_cluster_key_init(&nk, nodemap->nm_id);
336 nodemap_cluster_rec_init(&nr, nodemap);
338 if (update == NM_UPDATE)
339 rc = nodemap_idx_action(nodemap_idx_update, &nk, &nr);
341 rc = nodemap_idx_action(nodemap_idx_insert, &nk, &nr);
346 int nodemap_idx_nodemap_add(const struct lu_nodemap *nodemap)
348 return nodemap_idx_nodemap_add_update(nodemap, NM_ADD);
351 int nodemap_idx_nodemap_update(const struct lu_nodemap *nodemap)
353 return nodemap_idx_nodemap_add_update(nodemap, NM_UPDATE);
356 int nodemap_idx_nodemap_del(const struct lu_nodemap *nodemap)
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;
369 root = nodemap->nm_fs_to_client_uidmap;
370 nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
372 nodemap_idmap_key_init(&nk, nodemap->nm_id, NODEMAP_UID,
374 rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
379 root = nodemap->nm_client_to_fs_gidmap;
380 nm_rbtree_postorder_for_each_entry_safe(idmap, temp, &root,
382 nodemap_idmap_key_init(&nk, nodemap->nm_id, NODEMAP_GID,
384 rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
389 list_for_each_entry_safe(range, range_temp, &nodemap->nm_ranges,
391 nodemap_range_key_init(&nk, nodemap->nm_id, range->rn_id);
392 rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
397 nodemap_cluster_key_init(&nk, nodemap->nm_id);
398 rc2 = nodemap_idx_action(nodemap_idx_delete, &nk, NULL);
405 int nodemap_idx_range_add(const struct lu_nid_range *range,
406 const lnet_nid_t nid[2])
408 struct nodemap_key nk;
409 union nodemap_rec nr;
412 nodemap_range_key_init(&nk, range->rn_nodemap->nm_id, range->rn_id);
413 nodemap_range_rec_init(&nr, nid);
415 RETURN(nodemap_idx_action(nodemap_idx_insert, &nk, &nr));
418 int nodemap_idx_range_del(const struct lu_nid_range *range)
420 struct nodemap_key nk;
423 nodemap_range_key_init(&nk, range->rn_nodemap->nm_id, range->rn_id);
425 RETURN(nodemap_idx_action(nodemap_idx_delete, &nk, NULL));
428 int nodemap_idx_idmap_add(const struct lu_nodemap *nodemap,
429 enum nodemap_id_type id_type,
432 struct nodemap_key nk;
433 union nodemap_rec nr;
436 nodemap_idmap_key_init(&nk, nodemap->nm_id, id_type, map[0]);
437 nodemap_idmap_rec_init(&nr, map[1]);
439 RETURN(nodemap_idx_action(nodemap_idx_insert, &nk, &nr));
442 int nodemap_idx_idmap_del(const struct lu_nodemap *nodemap,
443 enum nodemap_id_type id_type,
446 struct nodemap_key nk;
449 nodemap_idmap_key_init(&nk, nodemap->nm_id, id_type, map[0]);
451 RETURN(nodemap_idx_action(nodemap_idx_delete, &nk, NULL));
454 static int nodemap_idx_global_add_update(bool value, enum nm_add_update update)
456 struct nodemap_key nk;
457 union nodemap_rec nr;
460 nodemap_global_key_init(&nk);
461 nodemap_global_rec_init(&nr, value);
463 if (update == NM_UPDATE)
464 RETURN(nodemap_idx_action(nodemap_idx_update, &nk, &nr));
466 RETURN(nodemap_idx_action(nodemap_idx_insert, &nk, &nr));
469 int nodemap_idx_nodemap_activate(bool value)
471 return nodemap_idx_global_add_update(value, NM_UPDATE);
475 * Process a key/rec pair and modify the new configuration.
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
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)
492 struct lu_nodemap *nodemap = NULL;
493 enum nodemap_idx_type type;
494 enum nodemap_id_type id_type;
501 CLASSERT(sizeof(union nodemap_rec) == 32);
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);
507 CDEBUG(D_INFO, "found config entry, nm_id %d type %d\n",
510 /* find the correct nodemap in the load list */
511 if (type == NODEMAP_RANGE_IDX || type == NODEMAP_UIDMAP_IDX ||
512 type == NODEMAP_GIDMAP_IDX) {
513 struct lu_nodemap *tmp = NULL;
515 nodemap = *recent_nodemap;
518 GOTO(out, rc = -ENOENT);
520 if (nodemap->nm_id != nodemap_id) {
521 list_for_each_entry(tmp, &nodemap->nm_list, nm_list)
522 if (tmp->nm_id == nodemap_id) {
527 if (nodemap->nm_id != nodemap_id)
528 GOTO(out, rc = -ENOENT);
531 /* update most recently used nodemap if necessay */
532 if (nodemap != *recent_nodemap)
533 *recent_nodemap = nodemap;
537 case NODEMAP_EMPTY_IDX:
539 CWARN("Found nodemap config record without type field, "
540 " nodemap_id=%d. nodemap config file corrupt?\n",
543 case NODEMAP_CLUSTER_IDX:
544 nodemap = cfs_hash_lookup(config->nmc_nodemap_hash,
546 if (nodemap == NULL) {
547 if (nodemap_id == LUSTRE_NODEMAP_DEFAULT_ID) {
548 nodemap = nodemap_create(rec->ncr.ncr_name,
550 config->nmc_default_nodemap = nodemap;
552 nodemap = nodemap_create(rec->ncr.ncr_name,
556 GOTO(out, rc = PTR_ERR(nodemap));
558 /* we need to override the local ID with the saved ID */
559 nodemap->nm_id = nodemap_id;
560 if (nodemap_id > config->nmc_nodemap_highest_id)
561 config->nmc_nodemap_highest_id = nodemap_id;
563 } else if (nodemap->nm_id != nodemap_id) {
564 nodemap_putref(nodemap);
565 GOTO(out, rc = -EINVAL);
568 nodemap->nm_squash_uid =
569 le32_to_cpu(rec->ncr.ncr_squash_uid);
570 nodemap->nm_squash_gid =
571 le32_to_cpu(rec->ncr.ncr_squash_gid);
573 flags = le32_to_cpu(rec->ncr.ncr_flags);
574 nodemap->nmf_allow_root_access =
575 flags & NM_FL_ALLOW_ROOT_ACCESS;
576 nodemap->nmf_trust_client_ids =
577 flags & NM_FL_TRUST_CLIENT_IDS;
579 if (*recent_nodemap == NULL) {
580 *recent_nodemap = nodemap;
581 INIT_LIST_HEAD(&nodemap->nm_list);
583 list_add(&nodemap->nm_list,
584 &(*recent_nodemap)->nm_list);
586 nodemap_putref(nodemap);
588 case NODEMAP_RANGE_IDX:
589 nid[0] = le64_to_cpu(rec->nrr.nrr_start_nid);
590 nid[1] = le64_to_cpu(rec->nrr.nrr_end_nid);
592 rc = nodemap_add_range_helper(config, nodemap, nid,
593 le32_to_cpu(key->nk_range_id));
597 case NODEMAP_UIDMAP_IDX:
598 case NODEMAP_GIDMAP_IDX:
599 map[0] = le32_to_cpu(key->nk_id_client);
600 map[1] = le32_to_cpu(rec->nir.nir_id_fs);
602 if (type == NODEMAP_UIDMAP_IDX)
603 id_type = NODEMAP_UID;
605 id_type = NODEMAP_GID;
607 rc = nodemap_add_idmap_helper(nodemap, id_type, map);
611 case NODEMAP_GLOBAL_IDX:
612 config->nmc_nodemap_is_active = rec->ngr.ngr_is_active;
615 CERROR("got keyrec pair for unknown type %d\n", type);
624 static int nodemap_load_entries(const struct lu_env *env,
625 struct dt_object *nodemap_idx)
627 const struct dt_it_ops *iops;
629 struct lu_nodemap *recent_nodemap = NULL;
630 struct nodemap_config *new_config = NULL;
632 bool activate_nodemap = false;
633 bool loaded_global_idx = false;
638 iops = &nodemap_idx->do_index_ops->dio_it;
640 dt_read_lock(env, nodemap_idx, 0);
641 it = iops->init(env, nodemap_idx, 0);
643 GOTO(out, rc = PTR_ERR(it));
645 rc = iops->load(env, it, hash);
647 rc = iops->next(env, it);
649 GOTO(out_iops, rc = 0);
652 /* acquires active config lock */
653 new_config = nodemap_config_alloc();
654 if (IS_ERR(new_config)) {
655 rc = PTR_ERR(new_config);
661 struct nodemap_key *key;
662 union nodemap_rec rec;
664 key = (struct nodemap_key *)iops->key(env, it);
665 rc = iops->rec(env, it, (struct dt_rec *)&rec, 0);
669 rc = nodemap_process_keyrec(new_config, key, &rec,
673 if (rc == NODEMAP_GLOBAL_IDX)
674 loaded_global_idx = true;
678 rc = iops->next(env, it);
679 while (rc == -ESTALE);
687 nodemap_config_dealloc(new_config);
689 /* creating new default needs to be done outside dt read lock */
690 activate_nodemap = true;
695 dt_read_unlock(env, nodemap_idx);
698 CWARN("%s: failed to load nodemap configuration: rc = %d\n",
699 nodemap_idx->do_lu.lo_dev->ld_obd->obd_name, rc);
701 if (!activate_nodemap)
704 if (new_config->nmc_default_nodemap == NULL) {
705 /* new MGS won't have a default nm on disk, so create it here */
706 new_config->nmc_default_nodemap =
707 nodemap_create(DEFAULT_NODEMAP, new_config, 1);
708 if (IS_ERR(new_config->nmc_default_nodemap)) {
709 rc = PTR_ERR(new_config->nmc_default_nodemap);
711 rc = nodemap_idx_nodemap_add_update(
712 new_config->nmc_default_nodemap,
714 nodemap_putref(new_config->nmc_default_nodemap);
718 /* new nodemap config won't have an active/inactive record */
719 if (rc == 0 && loaded_global_idx == false)
720 rc = nodemap_idx_global_add_update(false, NM_ADD);
723 nodemap_config_set_active(new_config);
725 nodemap_config_dealloc(new_config);
731 * Register a dt_object representing the config index file. This should be
732 * called by targets in order to load the nodemap configuration from disk. The
733 * dt_object should be created with local_index_find_or_create and the index
734 * features should be enabled with do_index_try.
736 * \param obj dt_object returned by local_index_find_or_create
738 * \retval on success: nm_config_file handle for later deregistration
739 * \retval -ENOMEM memory allocation failure
740 * \retval -ENOENT error loading nodemap config
741 * \retval -EINVAL error loading nodemap config
743 struct nm_config_file *nm_config_file_register(const struct lu_env *env,
744 struct dt_object *obj)
746 struct nm_config_file *ncf;
747 bool load_entries = false;
753 RETURN(ERR_PTR(-ENOMEM));
756 mutex_lock(&ncf_list_lock);
758 /* if this is first config file, we load it from disk */
759 if (list_empty(&ncf_list_head))
762 list_add(&ncf->ncf_list, &ncf_list_head);
763 mutex_unlock(&ncf_list_lock);
766 rc = nodemap_load_entries(env, obj);
768 mutex_lock(&ncf_list_lock);
769 list_del(&ncf->ncf_list);
770 mutex_unlock(&ncf_list_lock);
778 EXPORT_SYMBOL(nm_config_file_register);
781 * Deregister a nm_config_file. Should be called by targets during cleanup.
783 * \param ncf config file to deregister
785 void nm_config_file_deregister(const struct lu_env *env,
786 struct nm_config_file *ncf)
790 lu_object_put(env, &ncf->ncf_obj->do_lu);
792 mutex_lock(&ncf_list_lock);
793 list_del(&ncf->ncf_list);
794 mutex_unlock(&ncf_list_lock);
799 EXPORT_SYMBOL(nm_config_file_deregister);
801 int nodemap_process_idx_pages(struct nodemap_config *config, union lu_page *lip,
802 struct lu_nodemap **recent_nodemap)
804 struct nodemap_key *key;
805 union nodemap_rec *rec;
810 int size = dt_nodemap_features.dif_keysize_max +
811 dt_nodemap_features.dif_recsize_max;
813 for (j = 0; j < LU_PAGE_COUNT; j++) {
814 if (lip->lp_idx.lip_magic != LIP_MAGIC)
817 /* get and process keys and records from page */
818 for (k = 0; k < lip->lp_idx.lip_nr; k++) {
819 entry = lip->lp_idx.lip_entries + k * size;
820 key = (struct nodemap_key *)entry;
822 entry += dt_nodemap_features.dif_keysize_max;
823 rec = (union nodemap_rec *)entry;
825 rc = nodemap_process_keyrec(config, key, rec,
834 EXPORT_SYMBOL(nodemap_process_idx_pages);
836 int nodemap_index_read(struct lu_env *env,
837 struct nm_config_file *ncf,
839 const struct lu_rdpg *rdpg)
841 struct dt_object *nodemap_idx = ncf->ncf_obj;
844 ii->ii_keysize = dt_nodemap_features.dif_keysize_max;
845 ii->ii_recsize = dt_nodemap_features.dif_recsize_max;
847 dt_read_lock(env, nodemap_idx, 0);
848 rc = dt_index_walk(env, nodemap_idx, rdpg, NULL, ii);
849 CDEBUG(D_INFO, "walked index, hashend %llx\n", ii->ii_hash_end);
851 dt_read_unlock(env, nodemap_idx);
854 EXPORT_SYMBOL(nodemap_index_read);
857 * Returns the current nodemap configuration to MGC by walking the nodemap
858 * config index and storing it in the response buffer.
860 * \param req incoming MGS_CONFIG_READ request
862 * \retval -EINVAL malformed request
863 * \retval -ENOTCONN client evicted/reconnected already
864 * \retval -ETIMEDOUT client timeout or network error
867 int nodemap_get_config_req(struct obd_device *mgs_obd,
868 struct ptlrpc_request *req)
870 struct mgs_config_body *body;
871 struct mgs_config_res *res;
873 struct idx_info nodemap_ii;
874 struct ptlrpc_bulk_desc *desc;
875 struct l_wait_info lwi;
881 body = req_capsule_client_get(&req->rq_pill, &RMF_MGS_CONFIG_BODY);
885 if (body->mcb_type != CONFIG_T_NODEMAP)
888 rdpg.rp_count = (body->mcb_units << body->mcb_bits);
889 rdpg.rp_npages = (rdpg.rp_count + PAGE_CACHE_SIZE - 1) >>
891 if (rdpg.rp_npages > PTLRPC_MAX_BRW_PAGES)
894 CDEBUG(D_INFO, "reading nodemap log, name '%s', size = %u\n",
895 body->mcb_name, rdpg.rp_count);
897 /* allocate pages to store the containers */
898 OBD_ALLOC(rdpg.rp_pages, sizeof(*rdpg.rp_pages) * rdpg.rp_npages);
899 if (rdpg.rp_pages == NULL)
901 for (i = 0; i < rdpg.rp_npages; i++) {
902 rdpg.rp_pages[i] = alloc_page(GFP_IOFS);
903 if (rdpg.rp_pages[i] == NULL)
904 GOTO(out, rc = -ENOMEM);
907 rdpg.rp_hash = body->mcb_offset;
908 nodemap_ii.ii_magic = IDX_INFO_MAGIC;
909 nodemap_ii.ii_flags = II_FL_NOHASH;
911 bytes = nodemap_index_read(req->rq_svc_thread->t_env,
912 mgs_obd->u.obt.obt_nodemap_config_file,
915 GOTO(out, rc = bytes);
917 res = req_capsule_server_get(&req->rq_pill, &RMF_MGS_CONFIG_RES);
919 GOTO(out, rc = -EINVAL);
920 res->mcr_offset = nodemap_ii.ii_hash_end;
921 res->mcr_size = bytes;
923 page_count = (bytes + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
924 LASSERT(page_count <= rdpg.rp_count);
925 desc = ptlrpc_prep_bulk_exp(req, page_count, 1,
926 PTLRPC_BULK_PUT_SOURCE |
927 PTLRPC_BULK_BUF_KIOV,
929 &ptlrpc_bulk_kiov_pin_ops);
931 GOTO(out, rc = -ENOMEM);
933 for (i = 0; i < page_count && bytes > 0; i++) {
934 ptlrpc_prep_bulk_page_pin(desc, rdpg.rp_pages[i], 0,
935 min_t(int, bytes, PAGE_CACHE_SIZE));
936 bytes -= PAGE_CACHE_SIZE;
939 rc = target_bulk_io(req->rq_export, desc, &lwi);
940 ptlrpc_free_bulk(desc);
943 if (rdpg.rp_pages != NULL) {
944 for (i = 0; i < rdpg.rp_npages; i++)
945 if (rdpg.rp_pages[i] != NULL)
946 __free_page(rdpg.rp_pages[i]);
947 OBD_FREE(rdpg.rp_pages,
948 rdpg.rp_npages * sizeof(rdpg.rp_pages[0]));
952 EXPORT_SYMBOL(nodemap_get_config_req);