@@ -219,7 +219,7 @@ typedef void (*rbd_obj_callback_t)(struct rbd_obj_request *);
219
219
enum obj_request_type {
220
220
OBJ_REQUEST_NODATA = 1 ,
221
221
OBJ_REQUEST_BIO , /* pointer into provided bio (list) */
222
- OBJ_REQUEST_PAGES ,
222
+ OBJ_REQUEST_BVECS , /* pointer into provided bio_vec array */
223
223
};
224
224
225
225
enum obj_operation_type {
@@ -272,12 +272,12 @@ struct rbd_obj_request {
272
272
union {
273
273
struct ceph_bio_iter bio_pos ;
274
274
struct {
275
- struct page * * pages ;
276
- u32 page_count ;
275
+ struct ceph_bvec_iter bvec_pos ;
276
+ u32 bvec_count ;
277
277
};
278
278
};
279
- struct page * * copyup_pages ;
280
- u32 copyup_page_count ;
279
+ struct bio_vec * copyup_bvecs ;
280
+ u32 copyup_bvec_count ;
281
281
282
282
struct ceph_osd_request * osd_req ;
283
283
@@ -1272,36 +1272,14 @@ static void zero_bios(struct ceph_bio_iter *bio_pos, u32 off, u32 bytes)
1272
1272
}));
1273
1273
}
1274
1274
1275
- /*
1276
- * similar to zero_bio_chain(), zeros data defined by a page array,
1277
- * starting at the given byte offset from the start of the array and
1278
- * continuing up to the given end offset. The pages array is
1279
- * assumed to be big enough to hold all bytes up to the end.
1280
- */
1281
- static void zero_pages (struct page * * pages , u64 offset , u64 end )
1275
+ static void zero_bvecs (struct ceph_bvec_iter * bvec_pos , u32 off , u32 bytes )
1282
1276
{
1283
- struct page * * page = & pages [offset >> PAGE_SHIFT ];
1284
-
1285
- rbd_assert (end > offset );
1286
- rbd_assert (end - offset <= (u64 )SIZE_MAX );
1287
- while (offset < end ) {
1288
- size_t page_offset ;
1289
- size_t length ;
1290
- unsigned long flags ;
1291
- void * kaddr ;
1292
-
1293
- page_offset = offset & ~PAGE_MASK ;
1294
- length = min_t (size_t , PAGE_SIZE - page_offset , end - offset );
1295
- local_irq_save (flags );
1296
- kaddr = kmap_atomic (* page );
1297
- memset (kaddr + page_offset , 0 , length );
1298
- flush_dcache_page (* page );
1299
- kunmap_atomic (kaddr );
1300
- local_irq_restore (flags );
1277
+ struct ceph_bvec_iter it = * bvec_pos ;
1301
1278
1302
- offset += length ;
1303
- page ++ ;
1304
- }
1279
+ ceph_bvec_iter_advance (& it , off );
1280
+ ceph_bvec_iter_advance_step (& it , bytes , ({
1281
+ zero_bvec (& bv );
1282
+ }));
1305
1283
}
1306
1284
1307
1285
/*
@@ -1461,7 +1439,7 @@ static bool obj_request_type_valid(enum obj_request_type type)
1461
1439
switch (type ) {
1462
1440
case OBJ_REQUEST_NODATA :
1463
1441
case OBJ_REQUEST_BIO :
1464
- case OBJ_REQUEST_PAGES :
1442
+ case OBJ_REQUEST_BVECS :
1465
1443
return true;
1466
1444
default :
1467
1445
return false;
@@ -1611,14 +1589,15 @@ rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
1611
1589
if (obj_request -> type == OBJ_REQUEST_BIO )
1612
1590
zero_bios (& obj_request -> bio_pos , 0 , length );
1613
1591
else
1614
- zero_pages ( obj_request -> pages , 0 , length );
1592
+ zero_bvecs ( & obj_request -> bvec_pos , 0 , length );
1615
1593
obj_request -> result = 0 ;
1616
1594
} else if (xferred < length && !obj_request -> result ) {
1617
1595
if (obj_request -> type == OBJ_REQUEST_BIO )
1618
1596
zero_bios (& obj_request -> bio_pos , xferred ,
1619
1597
length - xferred );
1620
1598
else
1621
- zero_pages (obj_request -> pages , xferred , length );
1599
+ zero_bvecs (& obj_request -> bvec_pos , xferred ,
1600
+ length - xferred );
1622
1601
}
1623
1602
obj_request -> xferred = length ;
1624
1603
obj_request_done_set (obj_request );
@@ -1913,6 +1892,7 @@ rbd_obj_request_create(enum obj_request_type type)
1913
1892
static void rbd_obj_request_destroy (struct kref * kref )
1914
1893
{
1915
1894
struct rbd_obj_request * obj_request ;
1895
+ u32 i ;
1916
1896
1917
1897
obj_request = container_of (kref , struct rbd_obj_request , kref );
1918
1898
@@ -1924,22 +1904,22 @@ static void rbd_obj_request_destroy(struct kref *kref)
1924
1904
if (obj_request -> osd_req )
1925
1905
rbd_osd_req_destroy (obj_request -> osd_req );
1926
1906
1927
- rbd_assert (obj_request_type_valid (obj_request -> type ));
1928
1907
switch (obj_request -> type ) {
1929
1908
case OBJ_REQUEST_NODATA :
1930
1909
case OBJ_REQUEST_BIO :
1910
+ case OBJ_REQUEST_BVECS :
1931
1911
break ; /* Nothing to do */
1932
- case OBJ_REQUEST_PAGES :
1933
- /* img_data requests don't own their page array */
1934
- if (obj_request -> pages &&
1935
- !obj_request_img_data_test (obj_request ))
1936
- ceph_release_page_vector (obj_request -> pages ,
1937
- obj_request -> page_count );
1938
- break ;
1912
+ default :
1913
+ rbd_assert (0 );
1939
1914
}
1940
1915
1941
- ceph_release_page_vector (obj_request -> copyup_pages ,
1942
- obj_request -> copyup_page_count );
1916
+ if (obj_request -> copyup_bvecs ) {
1917
+ for (i = 0 ; i < obj_request -> copyup_bvec_count ; i ++ ) {
1918
+ if (obj_request -> copyup_bvecs [i ].bv_page )
1919
+ __free_page (obj_request -> copyup_bvecs [i ].bv_page );
1920
+ }
1921
+ kfree (obj_request -> copyup_bvecs );
1922
+ }
1943
1923
1944
1924
kmem_cache_free (rbd_obj_request_cache , obj_request );
1945
1925
}
@@ -2260,10 +2240,9 @@ static void rbd_img_obj_request_fill(struct rbd_obj_request *obj_request,
2260
2240
if (obj_request -> type == OBJ_REQUEST_BIO )
2261
2241
osd_req_op_extent_osd_data_bio (osd_request , num_ops ,
2262
2242
& obj_request -> bio_pos , length );
2263
- else if (obj_request -> type == OBJ_REQUEST_PAGES )
2264
- osd_req_op_extent_osd_data_pages (osd_request , num_ops ,
2265
- obj_request -> pages , length ,
2266
- offset & ~PAGE_MASK , false, false);
2243
+ else if (obj_request -> type == OBJ_REQUEST_BVECS )
2244
+ osd_req_op_extent_osd_data_bvec_pos (osd_request , num_ops ,
2245
+ & obj_request -> bvec_pos );
2267
2246
2268
2247
/* Discards are also writes */
2269
2248
if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD )
@@ -2288,7 +2267,7 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
2288
2267
struct rbd_obj_request * obj_request = NULL ;
2289
2268
struct rbd_obj_request * next_obj_request ;
2290
2269
struct ceph_bio_iter bio_it ;
2291
- struct page * * pages = NULL ;
2270
+ struct ceph_bvec_iter bvec_it ;
2292
2271
enum obj_operation_type op_type ;
2293
2272
u64 img_offset ;
2294
2273
u64 resid ;
@@ -2305,8 +2284,8 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
2305
2284
bio_it = * (struct ceph_bio_iter * )data_desc ;
2306
2285
rbd_assert (img_offset ==
2307
2286
bio_it .iter .bi_sector << SECTOR_SHIFT );
2308
- } else if (type == OBJ_REQUEST_PAGES ) {
2309
- pages = data_desc ;
2287
+ } else if (type == OBJ_REQUEST_BVECS ) {
2288
+ bvec_it = * ( struct ceph_bvec_iter * ) data_desc ;
2310
2289
}
2311
2290
2312
2291
while (resid ) {
@@ -2332,15 +2311,10 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
2332
2311
if (type == OBJ_REQUEST_BIO ) {
2333
2312
obj_request -> bio_pos = bio_it ;
2334
2313
ceph_bio_iter_advance (& bio_it , length );
2335
- } else if (type == OBJ_REQUEST_PAGES ) {
2336
- unsigned int page_count ;
2337
-
2338
- obj_request -> pages = pages ;
2339
- page_count = (u32 )calc_pages_for (offset , length );
2340
- obj_request -> page_count = page_count ;
2341
- if ((offset + length ) & ~PAGE_MASK )
2342
- page_count -- ; /* more on last page */
2343
- pages += page_count ;
2314
+ } else if (type == OBJ_REQUEST_BVECS ) {
2315
+ obj_request -> bvec_pos = bvec_it ;
2316
+ ceph_bvec_iter_shorten (& obj_request -> bvec_pos , length );
2317
+ ceph_bvec_iter_advance (& bvec_it , length );
2344
2318
}
2345
2319
2346
2320
osd_req = rbd_osd_req_create (rbd_dev , op_type ,
@@ -2452,8 +2426,8 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
2452
2426
/* Initialize the copyup op */
2453
2427
2454
2428
osd_req_op_cls_init (osd_req , 0 , CEPH_OSD_OP_CALL , "rbd" , "copyup" );
2455
- osd_req_op_cls_request_data_pages (osd_req , 0 , orig_request -> copyup_pages ,
2456
- parent_length , 0 , false, false );
2429
+ osd_req_op_cls_request_data_bvecs (osd_req , 0 , orig_request -> copyup_bvecs ,
2430
+ parent_length );
2457
2431
2458
2432
/* Add the other op(s) */
2459
2433
@@ -2469,6 +2443,8 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
2469
2443
rbd_obj_request_error (orig_request , img_result );
2470
2444
}
2471
2445
2446
+ static int setup_copyup_bvecs (struct rbd_obj_request * obj_req , u64 obj_overlap );
2447
+
2472
2448
/*
2473
2449
* Read from the parent image the range of data that covers the
2474
2450
* entire target of the given object request. This is used for
@@ -2487,10 +2463,9 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
2487
2463
{
2488
2464
struct rbd_device * rbd_dev = obj_request -> img_request -> rbd_dev ;
2489
2465
struct rbd_img_request * parent_request = NULL ;
2466
+ struct ceph_bvec_iter bvec_it = { 0 };
2490
2467
u64 img_offset ;
2491
2468
u64 length ;
2492
- struct page * * pages = NULL ;
2493
- u32 page_count ;
2494
2469
int result ;
2495
2470
2496
2471
rbd_assert (rbd_dev -> parent != NULL );
@@ -2516,24 +2491,20 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
2516
2491
* Allocate a page array big enough to receive the data read
2517
2492
* from the parent.
2518
2493
*/
2519
- page_count = (u32 )calc_pages_for (0 , length );
2520
- pages = ceph_alloc_page_vector (page_count , GFP_NOIO );
2521
- if (IS_ERR (pages )) {
2522
- result = PTR_ERR (pages );
2494
+ result = setup_copyup_bvecs (obj_request , length );
2495
+ if (result )
2523
2496
goto out_err ;
2524
- }
2525
-
2526
- rbd_assert (!obj_request -> copyup_pages );
2527
- obj_request -> copyup_pages = pages ;
2528
- obj_request -> copyup_page_count = page_count ;
2529
2497
2530
2498
result = - ENOMEM ;
2531
2499
parent_request = rbd_parent_request_create (obj_request ,
2532
2500
img_offset , length );
2533
2501
if (!parent_request )
2534
2502
goto out_err ;
2535
2503
2536
- result = rbd_img_request_fill (parent_request , OBJ_REQUEST_PAGES , pages );
2504
+ bvec_it .bvecs = obj_request -> copyup_bvecs ;
2505
+ bvec_it .iter .bi_size = length ;
2506
+ result = rbd_img_request_fill (parent_request , OBJ_REQUEST_BVECS ,
2507
+ & bvec_it );
2537
2508
if (result )
2538
2509
goto out_err ;
2539
2510
@@ -2751,6 +2722,34 @@ static int rbd_img_request_submit(struct rbd_img_request *img_request)
2751
2722
return ret ;
2752
2723
}
2753
2724
2725
+ static int setup_copyup_bvecs (struct rbd_obj_request * obj_req , u64 obj_overlap )
2726
+ {
2727
+ u32 i ;
2728
+
2729
+ rbd_assert (!obj_req -> copyup_bvecs );
2730
+ obj_req -> copyup_bvec_count = calc_pages_for (0 , obj_overlap );
2731
+ obj_req -> copyup_bvecs = kcalloc (obj_req -> copyup_bvec_count ,
2732
+ sizeof (* obj_req -> copyup_bvecs ),
2733
+ GFP_NOIO );
2734
+ if (!obj_req -> copyup_bvecs )
2735
+ return - ENOMEM ;
2736
+
2737
+ for (i = 0 ; i < obj_req -> copyup_bvec_count ; i ++ ) {
2738
+ unsigned int len = min (obj_overlap , (u64 )PAGE_SIZE );
2739
+
2740
+ obj_req -> copyup_bvecs [i ].bv_page = alloc_page (GFP_NOIO );
2741
+ if (!obj_req -> copyup_bvecs [i ].bv_page )
2742
+ return - ENOMEM ;
2743
+
2744
+ obj_req -> copyup_bvecs [i ].bv_offset = 0 ;
2745
+ obj_req -> copyup_bvecs [i ].bv_len = len ;
2746
+ obj_overlap -= len ;
2747
+ }
2748
+
2749
+ rbd_assert (!obj_overlap );
2750
+ return 0 ;
2751
+ }
2752
+
2754
2753
static void rbd_img_parent_read_callback (struct rbd_img_request * img_request )
2755
2754
{
2756
2755
struct rbd_obj_request * obj_request ;
@@ -2832,8 +2831,8 @@ static void rbd_img_parent_read(struct rbd_obj_request *obj_request)
2832
2831
result = rbd_img_request_fill (img_request , OBJ_REQUEST_BIO ,
2833
2832
& obj_request -> bio_pos );
2834
2833
else
2835
- result = rbd_img_request_fill (img_request , OBJ_REQUEST_PAGES ,
2836
- obj_request -> pages );
2834
+ result = rbd_img_request_fill (img_request , OBJ_REQUEST_BVECS ,
2835
+ & obj_request -> bvec_pos );
2837
2836
if (result )
2838
2837
goto out_err ;
2839
2838
0 commit comments