/** * nfs_pageio_add_request - Attempt to coalesce a request into a page list. * @desc: destination io descriptor * @req: request * * Returns true if the request 'req' was successfully coalesced into the * existing list of pages 'desc'. */ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, struct nfs_page *req) { while (!nfs_pageio_do_add_request(desc, req)) { nfs_pageio_doio(desc); if (desc->pg_error < 0) return 0; } return 1; }
/** * nfs_pageio_add_request - Attempt to coalesce a request into a page list. * @desc: destination io descriptor * @req: request * * Returns true if the request 'req' was successfully coalesced into the * existing list of pages 'desc'. */ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, struct nfs_page *req) { while (!nfs_pageio_do_add_request(desc, req)) { desc->pg_moreio = 1; nfs_pageio_doio(desc); if (desc->pg_error < 0) return 0; desc->pg_moreio = 0; if (desc->pg_recoalesce) return 0; } return 1; }
/** * nfs_pageio_add_request - Attempt to coalesce a request into a page list. * @desc: destination io descriptor * @req: request * * This may split a request into subrequests which are all part of the * same page group. * * Returns true if the request 'req' was successfully coalesced into the * existing list of pages 'desc'. */ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, struct nfs_page *req) { struct nfs_page *subreq; unsigned int bytes_left = 0; unsigned int offset, pgbase; nfs_page_group_lock(req, false); subreq = req; bytes_left = subreq->wb_bytes; offset = subreq->wb_offset; pgbase = subreq->wb_pgbase; do { if (!nfs_pageio_do_add_request(desc, subreq)) { /* make sure pg_test call(s) did nothing */ WARN_ON_ONCE(subreq->wb_bytes != bytes_left); WARN_ON_ONCE(subreq->wb_offset != offset); WARN_ON_ONCE(subreq->wb_pgbase != pgbase); nfs_page_group_unlock(req); desc->pg_moreio = 1; nfs_pageio_doio(desc); if (desc->pg_error < 0) return 0; if (desc->pg_recoalesce) return 0; /* retry add_request for this subreq */ nfs_page_group_lock(req, false); continue; } /* check for buggy pg_test call(s) */ WARN_ON_ONCE(subreq->wb_bytes + subreq->wb_pgbase > PAGE_SIZE); WARN_ON_ONCE(subreq->wb_bytes > bytes_left); WARN_ON_ONCE(subreq->wb_bytes == 0); bytes_left -= subreq->wb_bytes; offset += subreq->wb_bytes; pgbase += subreq->wb_bytes; if (bytes_left) { subreq = nfs_create_request(req->wb_context, req->wb_page, subreq, pgbase, bytes_left); if (IS_ERR(subreq)) goto err_ptr; nfs_lock_request(subreq); subreq->wb_offset = offset; subreq->wb_index = req->wb_index; } } while (bytes_left > 0); nfs_page_group_unlock(req); return 1; err_ptr: desc->pg_error = PTR_ERR(subreq); nfs_page_group_unlock(req); return 0; }