- struct page *page;
- unsigned long index = 0;
- int rc;
- ENTRY;
-
- CDEBUG(D_INODE, "src: ino %Ld blocks %Ld, size %Ld, dst: ino %Ld\n",
- src->o_id, src->o_blocks, src->o_size, dst->o_id);
- page = alloc_page(GFP_USER);
- if ( !page ) {
- EXIT;
- return -ENOMEM;
- }
-
- lck_page(page);
-
- while (index < ((src->o_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
-
- page->index = index;
- rc = OBP(src_conn->oc_dev, brw)
- (READ, src_conn, src, (char *)page_address(page),
- PAGE_SIZE, (page->index) << PAGE_SHIFT, 0);
-
- if ( rc != PAGE_SIZE )
- break;
- CDEBUG(D_INODE, "Read page %ld ...\n", page->index);
-
- rc = OBP(dst_conn->oc_dev, brw)
- (WRITE, dst_conn, dst, (char *)page_address(page),
- PAGE_SIZE, (page->index) << PAGE_SHIFT, 1);
- if ( rc != PAGE_SIZE)
- break;
-
- CDEBUG(D_INODE, "Wrote page %ld ...\n", page->index);
-
- index ++;
- }
- dst->o_size = src->o_size;
- dst->o_blocks = src->o_blocks;
- UnlockPage(page);
- __free_page(page);
-
- EXIT;
- return 0;
+ struct page *page;
+ unsigned long index = 0;
+ int err = 0;
+
+ ENTRY;
+ CDEBUG(D_INFO, "src: ino %Ld blocks %Ld, size %Ld, dst: ino %Ld\n",
+ src->o_id, src->o_blocks, src->o_size, dst->o_id);
+ page = alloc_page(GFP_USER);
+ if ( !page ) {
+ EXIT;
+ return -ENOMEM;
+ }
+
+ lck_page(page);
+
+ /* XXX with brw vector I/O, we could batch up reads and writes here,
+ * all we need to do is allocate multiple pages to handle the I/Os
+ * and arrays to handle the request parameters.
+ */
+ while (index < ((src->o_size + PAGE_SIZE - 1) >> PAGE_SHIFT)) {
+ obd_count num_oa = 1;
+ obd_count num_buf = 1;
+ char *buf;
+ obd_size brw_count = PAGE_SIZE;
+ obd_off brw_offset = (page->index) << PAGE_SHIFT;
+ obd_flag flagr = 0;
+ obd_flag flagw = OBD_BRW_CREATE;
+
+ page->index = index;
+ buf = (char *)page_address(page);
+ err = OBP(src_conn->oc_dev, brw)(READ, src_conn, num_oa, &src,
+ &num_buf, &buf, &brw_count,
+ &brw_offset, &flagr);
+
+ if ( err ) {
+ EXIT;
+ break;
+ }
+ CDEBUG(D_INFO, "Read page %ld ...\n", page->index);
+
+ err = OBP(dst_conn->oc_dev, brw)(WRITE, dst_conn, num_oa, &dst,
+ &num_buf, &buf, &brw_count,
+ &brw_offset, &flagw);
+
+ /* XXX should handle dst->o_size, dst->o_blocks here */
+ if ( err ) {
+ EXIT;
+ break;
+ }
+
+ CDEBUG(D_INFO, "Wrote page %ld ...\n", page->index);
+
+ index++;
+ }
+ dst->o_size = src->o_size;
+ dst->o_blocks = src->o_blocks;
+ dst->o_valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
+ obd_unlock_page(page);
+ __free_page(page);
+
+ EXIT;
+ return err;