/* * Helper for nfs_pageio_add_request and nfs_pageio_complete */ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc) { if (!list_empty(&desc->pg_list)) { int error = desc->pg_doio(desc->pg_inode, &desc->pg_list, nfs_page_array_len(desc->pg_base, desc->pg_count), desc->pg_count, desc->pg_ioflags); if (error < 0) desc->pg_error = error; else desc->pg_bytes_written += desc->pg_count; } if (list_empty(&desc->pg_list)) { desc->pg_count = 0; desc->pg_base = 0; } }
/* * Create an RPC task for the given read or write request and kick it. * The page must have been locked by the caller. * * It may happen that the page we're passed is not marked dirty. * This is the case if nfs_updatepage detects a conflicting request * that has been written but not committed. */ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, struct nfs_pgio_header *hdr) { struct nfs_page *req; struct page **pages, *last_page; struct list_head *head = &desc->pg_list; struct nfs_commit_info cinfo; unsigned int pagecount, pageused; pagecount = nfs_page_array_len(desc->pg_base, desc->pg_count); if (!nfs_pgarray_set(&hdr->page_array, pagecount)) return nfs_pgio_error(desc, hdr); nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); pages = hdr->page_array.pagevec; last_page = NULL; pageused = 0; while (!list_empty(head)) { req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &hdr->pages); if (WARN_ON_ONCE(pageused >= pagecount)) return nfs_pgio_error(desc, hdr); if (!last_page || last_page != req->wb_page) { *pages++ = last_page = req->wb_page; pageused++; } } if (WARN_ON_ONCE(pageused != pagecount)) return nfs_pgio_error(desc, hdr); if ((desc->pg_ioflags & FLUSH_COND_STABLE) && (desc->pg_moreio || nfs_reqs_to_commit(&cinfo))) desc->pg_ioflags &= ~FLUSH_COND_STABLE; /* Set up the argument struct */ nfs_pgio_rpcsetup(hdr, desc->pg_count, 0, desc->pg_ioflags, &cinfo); desc->pg_rpc_callops = &nfs_pgio_common_ops; return 0; }