- LASSERT(cld_is_recover(cld));
- LASSERT(cfs_mutex_is_locked(&cld->cld_lock));
- req = ptlrpc_request_alloc(class_exp2cliimp(cld->cld_mgcexp),
- &RQF_MGS_CONFIG_READ);
- if (req == NULL)
- GOTO(out, rc = -ENOMEM);
-
- rc = ptlrpc_request_pack(req, LUSTRE_MGS_VERSION, MGS_CONFIG_READ);
- if (rc)
- GOTO(out, rc);
-
- /* pack request */
- body = req_capsule_client_get(&req->rq_pill, &RMF_MGS_CONFIG_BODY);
- LASSERT(body != NULL);
- LASSERT(sizeof(body->mcb_name) > strlen(cld->cld_logname));
- strncpy(body->mcb_name, cld->cld_logname, sizeof(body->mcb_name));
- body->mcb_offset = cfg->cfg_last_idx + 1;
- body->mcb_type = cld->cld_type;
- body->mcb_bits = CFS_PAGE_SHIFT;
- body->mcb_units = nrpages;
-
- /* allocate bulk transfer descriptor */
- desc = ptlrpc_prep_bulk_imp(req, nrpages, BULK_PUT_SINK,
- MGS_BULK_PORTAL);
- if (desc == NULL)
- GOTO(out, rc = -ENOMEM);
-
- for (i = 0; i < nrpages; i++)
- ptlrpc_prep_bulk_page(desc, pages[i], 0, CFS_PAGE_SIZE);
-
- ptlrpc_request_set_replen(req);
- rc = ptlrpc_queue_wait(req);
- if (rc)
- GOTO(out, rc);
-
- res = req_capsule_server_get(&req->rq_pill, &RMF_MGS_CONFIG_RES);
- if (res->mcr_size < res->mcr_offset)
- GOTO(out, rc = -EINVAL);
-
- /* always update the index even though it might have errors with
- * handling the recover logs */
- cfg->cfg_last_idx = res->mcr_offset;
- eof = res->mcr_offset == res->mcr_size;
-
- CDEBUG(D_INFO, "Latest version "LPD64", more %d.\n",
- res->mcr_offset, eof == false);
-
- ealen = sptlrpc_cli_unwrap_bulk_read(req, req->rq_bulk, 0);
- if (ealen < 0)
- GOTO(out, rc = ealen);
-
- if (ealen > nrpages << CFS_PAGE_SHIFT)
- GOTO(out, rc = -EINVAL);
-
- if (ealen == 0) { /* no logs transferred */
- if (!eof)
- rc = -EINVAL;
- GOTO(out, rc);
- }
+#ifdef HAVE_SERVER_SUPPORT
+ if (cld_is_nodemap(cld) && config_read_offset == 0) {
+ new_config = nodemap_config_alloc();
+ if (IS_ERR(new_config)) {
+ rc = PTR_ERR(new_config);
+ new_config = NULL;
+ GOTO(out, rc);
+ }
+ }
+#endif
+ LASSERT(cld_is_recover(cld) || cld_is_nodemap(cld));
+ LASSERT(mutex_is_locked(&cld->cld_lock));
+ req = ptlrpc_request_alloc(class_exp2cliimp(cld->cld_mgcexp),
+ &RQF_MGS_CONFIG_READ);
+ if (req == NULL)
+ GOTO(out, rc = -ENOMEM);
+
+ rc = ptlrpc_request_pack(req, LUSTRE_MGS_VERSION, MGS_CONFIG_READ);
+ if (rc)
+ GOTO(out, rc);
+
+ /* pack request */
+ body = req_capsule_client_get(&req->rq_pill, &RMF_MGS_CONFIG_BODY);
+ LASSERT(body != NULL);
+ LASSERT(sizeof(body->mcb_name) > strlen(cld->cld_logname));
+ if (strlcpy(body->mcb_name, cld->cld_logname, sizeof(body->mcb_name))
+ >= sizeof(body->mcb_name))
+ GOTO(out, rc = -E2BIG);
+ if (cld_is_nodemap(cld))
+ body->mcb_offset = config_read_offset;
+ else
+ body->mcb_offset = cfg->cfg_last_idx + 1;
+ body->mcb_type = cld->cld_type;
+ body->mcb_bits = PAGE_CACHE_SHIFT;
+ body->mcb_units = nrpages;
+
+ /* allocate bulk transfer descriptor */
+ desc = ptlrpc_prep_bulk_imp(req, nrpages, 1,
+ PTLRPC_BULK_PUT_SINK | PTLRPC_BULK_BUF_KIOV,
+ MGS_BULK_PORTAL,
+ &ptlrpc_bulk_kiov_pin_ops);
+ if (desc == NULL)
+ GOTO(out, rc = -ENOMEM);
+
+ for (i = 0; i < nrpages; i++)
+ desc->bd_frag_ops->add_kiov_frag(desc, pages[i], 0,
+ PAGE_CACHE_SIZE);
+
+ ptlrpc_request_set_replen(req);
+ rc = ptlrpc_queue_wait(req);
+ if (rc)
+ GOTO(out, rc);
+
+ res = req_capsule_server_get(&req->rq_pill, &RMF_MGS_CONFIG_RES);
+ if (!res)
+ GOTO(out, rc = -EPROTO);
+
+ if (cld_is_nodemap(cld)) {
+ config_read_offset = res->mcr_offset;
+ eof = config_read_offset == II_END_OFF;
+ } else {
+ if (res->mcr_size < res->mcr_offset)
+ GOTO(out, rc = -EINVAL);
+
+ /* always update the index even though it might have errors with
+ * handling the recover logs
+ */
+ cfg->cfg_last_idx = res->mcr_offset;
+ eof = res->mcr_offset == res->mcr_size;
+
+ CDEBUG(D_INFO, "Latest version "LPD64", more %d.\n",
+ res->mcr_offset, eof == false);
+ }
+
+ ealen = sptlrpc_cli_unwrap_bulk_read(req, req->rq_bulk, 0);
+ if (ealen < 0)
+ GOTO(out, rc = ealen);
+
+ if (ealen > nrpages << PAGE_CACHE_SHIFT)
+ GOTO(out, rc = -EINVAL);
+
+ if (ealen == 0) { /* no logs transferred */
+#ifdef HAVE_SERVER_SUPPORT
+ /* config changed since first read RPC */
+ if (cld_is_nodemap(cld) && config_read_offset == 0) {
+ recent_nodemap = NULL;
+ nodemap_config_dealloc(new_config);
+ new_config = NULL;
+
+ CDEBUG(D_INFO, "nodemap config changed in transit, retrying\n");
+
+ /* setting eof to false, we request config again */
+ eof = false;
+ GOTO(out, rc = 0);
+ }
+#endif
+ if (!eof)
+ rc = -EINVAL;
+ GOTO(out, rc);
+ }