+ return rc;
+}
+
+static int echo_map_nb_to_lb(struct obdo *oa, struct obd_ioobj *obj,
+ struct niobuf_remote *nb, int *pages,
+ struct niobuf_local *lb, int cmd, int *left)
+{
+ gfp_t gfp_mask = (ostid_id(&obj->ioo_oid) & 1) ?
+ GFP_HIGHUSER : GFP_IOFS;
+ int ispersistent = ostid_id(&obj->ioo_oid) == ECHO_PERSISTENT_OBJID;
+ int debug_setup = (!ispersistent &&
+ (oa->o_valid & OBD_MD_FLFLAGS) != 0 &&
+ (oa->o_flags & OBD_FL_DEBUG_CHECK) != 0);
+ struct niobuf_local *res = lb;
+ u64 offset = nb->rnb_offset;
+ int len = nb->rnb_len;
+
+ while (len > 0) {
+ int plen = PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1));
+ if (len < plen)
+ plen = len;
+
+ /* check for local buf overflow */
+ if (*left == 0)
+ return -EINVAL;
+
+ res->lnb_file_offset = offset;
+ res->lnb_len = plen;
+ LASSERT((res->lnb_file_offset & ~PAGE_MASK) +
+ res->lnb_len <= PAGE_CACHE_SIZE);
+
+ if (ispersistent &&
+ ((res->lnb_file_offset >> PAGE_CACHE_SHIFT) <
+ ECHO_PERSISTENT_PAGES)) {
+ res->lnb_page =
+ echo_persistent_pages[res->lnb_file_offset >>
+ PAGE_CACHE_SHIFT];
+ /* Take extra ref so __free_pages() can be called OK */
+ get_page(res->lnb_page);
+ } else {
+ res->lnb_page = alloc_page(gfp_mask);
+ if (res->lnb_page == NULL) {
+ CERROR("can't get page for id " DOSTID"\n",
+ POSTID(&obj->ioo_oid));
+ return -ENOMEM;
+ }
+ }
+
+ CDEBUG(D_PAGE, "$$$$ get page %p @ "LPU64" for %d\n",
+ res->lnb_page, res->lnb_file_offset, res->lnb_len);
+
+ if (cmd & OBD_BRW_READ)
+ res->lnb_rc = res->lnb_len;
+
+ if (debug_setup)
+ echo_page_debug_setup(res->lnb_page, cmd,
+ ostid_id(&obj->ioo_oid),
+ res->lnb_file_offset,
+ res->lnb_len);
+
+ offset += plen;
+ len -= plen;
+ res++;
+
+ (*left)--;
+ (*pages)++;
+ }
+
+ return 0;