while (!done && index <= end) {
struct ceph_osd_req_op ops[2];
+ int num_ops = do_sync ? 2 : 1;
+ struct ceph_vino vino;
unsigned i;
int first;
pgoff_t next;
int pvec_pages, locked_pages;
+ struct page **pages = NULL;
+ mempool_t *pool = NULL; /* Becomes non-null if mempool used */
struct page *page;
int want;
u64 offset, len;
break;
}
- /* ok */
+ /*
+ * We have something to write. If this is
+ * the first locked page this time through,
+ * allocate an osd request and a page array
+ * that it will use.
+ */
if (locked_pages == 0) {
- struct ceph_vino vino;
- int num_ops = do_sync ? 2 : 1;
size_t size;
- struct page **pages;
- mempool_t *pool = NULL;
+
+ BUG_ON(pages);
/* prepare async write request */
- offset = (u64) page_offset(page);
+ offset = (u64)page_offset(page);
len = wsize;
req = ceph_writepages_osd_request(inode,
offset, &len, snapc,
break;
}
- vino = ceph_vino(inode);
- ceph_osdc_build_request(req, offset,
- num_ops, ops, snapc, vino.snap,
- &inode->i_mtime);
-
req->r_callback = writepages_finish;
req->r_inode = inode;
pages = kmalloc(size, GFP_NOFS);
if (!pages) {
pool = fsc->wb_pagevec_pool;
-
pages = mempool_alloc(pool, GFP_NOFS);
- WARN_ON(!pages);
+ BUG_ON(!pages);
}
-
- req->r_data_out.pages = pages;
- req->r_data_out.pages_from_pool = !!pool;
- req->r_data_out.type = CEPH_OSD_DATA_TYPE_PAGES;
- req->r_data_out.length = len;
- req->r_data_out.alignment = 0;
}
/* note position of first page in pvec */
}
set_page_writeback(page);
- req->r_data_out.pages[locked_pages] = page;
+ pages[locked_pages] = page;
locked_pages++;
next = page->index + 1;
}
pvec.nr -= i-first;
}
- /* submit the write */
- offset = page_offset(req->r_data_out.pages[0]);
+ /* Format the osd request message and submit the write */
+
+ offset = page_offset(pages[0]);
len = min((snap_size ? snap_size : i_size_read(inode)) - offset,
(u64)locked_pages << PAGE_CACHE_SHIFT);
dout("writepages got %d pages at %llu~%llu\n",
locked_pages, offset, len);
- /* revise final length, page count */
+ req->r_data_out.type = CEPH_OSD_DATA_TYPE_PAGES;
+ req->r_data_out.pages = pages;
req->r_data_out.length = len;
- req->r_request_ops[0].extent.length = cpu_to_le64(len);
- req->r_request_ops[0].payload_len = cpu_to_le32(len);
- req->r_request->hdr.data_len = cpu_to_le32(len);
+ req->r_data_out.alignment = 0;
+ req->r_data_out.pages_from_pool = !!pool;
+
+ pages = NULL; /* request message now owns the pages array */
+ pool = NULL;
+
+ /* Update the write op length in case we changed it */
+
+ osd_req_op_extent_update(&ops[0], len);
+
+ vino = ceph_vino(inode);
+ ceph_osdc_build_request(req, offset, num_ops, ops,
+ snapc, vino.snap, &inode->i_mtime);
rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
BUG_ON(rc);
}
EXPORT_SYMBOL(osd_req_op_extent_init);
+void osd_req_op_extent_update(struct ceph_osd_req_op *op, u64 length)
+{
+ u64 previous = op->extent.length;
+
+ if (length == previous)
+ return; /* Nothing to do */
+ BUG_ON(length > previous);
+
+ op->extent.length = length;
+ op->payload_len -= previous - length;
+}
+EXPORT_SYMBOL(osd_req_op_extent_update);
+
void osd_req_op_cls_init(struct ceph_osd_req_op *op, u16 opcode,
const char *class, const char *method,
const void *request_data, size_t request_data_size)