aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Grall <julien.grall@citrix.com>2015-07-01 09:10:38 -0400
committerDavid Vrabel <david.vrabel@citrix.com>2015-10-23 09:20:36 -0400
commit4f503fbdf319e4411aa48852b8922c93a9cc0c5d (patch)
tree9eb62475a83bc14c3b0090a2f2001cdaac6391fe
parenta7a6df222351de23791bb64165f14c21ff4d1653 (diff)
block/xen-blkfront: split get_grant in 2
Prepare the code to support 64KB page granularity. The first implementation will use a full Linux page per indirect and persistent grant. When non-persistent grant is used, each page of a bio request may be split in multiple grant. Furthermore, the field page of the grant structure is only used to copy data from persistent grant or indirect grant. Avoid to set it for other use case as it will have no meaning given the page will be split in multiple grant. Provide 2 functions, to setup indirect grant, the other for bio page. Signed-off-by: Julien Grall <julien.grall@citrix.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
-rw-r--r--drivers/block/xen-blkfront.c88
1 files changed, 59 insertions, 29 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 7552ca8f8ffe..f5dfc1694679 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -244,34 +244,77 @@ out_of_memory:
244 return -ENOMEM; 244 return -ENOMEM;
245} 245}
246 246
247static struct grant *get_grant(grant_ref_t *gref_head, 247static struct grant *get_free_grant(struct blkfront_info *info)
248 struct page *page,
249 struct blkfront_info *info)
250{ 248{
251 struct grant *gnt_list_entry; 249 struct grant *gnt_list_entry;
252 unsigned long buffer_gfn;
253 250
254 BUG_ON(list_empty(&info->grants)); 251 BUG_ON(list_empty(&info->grants));
255 gnt_list_entry = list_first_entry(&info->grants, struct grant, 252 gnt_list_entry = list_first_entry(&info->grants, struct grant,
256 node); 253 node);
257 list_del(&gnt_list_entry->node); 254 list_del(&gnt_list_entry->node);
258 255
259 if (gnt_list_entry->gref != GRANT_INVALID_REF) { 256 if (gnt_list_entry->gref != GRANT_INVALID_REF)
260 info->persistent_gnts_c--; 257 info->persistent_gnts_c--;
258
259 return gnt_list_entry;
260}
261
262static inline void grant_foreign_access(const struct grant *gnt_list_entry,
263 const struct blkfront_info *info)
264{
265 gnttab_page_grant_foreign_access_ref_one(gnt_list_entry->gref,
266 info->xbdev->otherend_id,
267 gnt_list_entry->page,
268 0);
269}
270
271static struct grant *get_grant(grant_ref_t *gref_head,
272 unsigned long gfn,
273 struct blkfront_info *info)
274{
275 struct grant *gnt_list_entry = get_free_grant(info);
276
277 if (gnt_list_entry->gref != GRANT_INVALID_REF)
261 return gnt_list_entry; 278 return gnt_list_entry;
279
280 /* Assign a gref to this page */
281 gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
282 BUG_ON(gnt_list_entry->gref == -ENOSPC);
283 if (info->feature_persistent)
284 grant_foreign_access(gnt_list_entry, info);
285 else {
286 /* Grant access to the GFN passed by the caller */
287 gnttab_grant_foreign_access_ref(gnt_list_entry->gref,
288 info->xbdev->otherend_id,
289 gfn, 0);
262 } 290 }
263 291
292 return gnt_list_entry;
293}
294
295static struct grant *get_indirect_grant(grant_ref_t *gref_head,
296 struct blkfront_info *info)
297{
298 struct grant *gnt_list_entry = get_free_grant(info);
299
300 if (gnt_list_entry->gref != GRANT_INVALID_REF)
301 return gnt_list_entry;
302
264 /* Assign a gref to this page */ 303 /* Assign a gref to this page */
265 gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head); 304 gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
266 BUG_ON(gnt_list_entry->gref == -ENOSPC); 305 BUG_ON(gnt_list_entry->gref == -ENOSPC);
267 if (!info->feature_persistent) { 306 if (!info->feature_persistent) {
268 BUG_ON(!page); 307 struct page *indirect_page;
269 gnt_list_entry->page = page; 308
309 /* Fetch a pre-allocated page to use for indirect grefs */
310 BUG_ON(list_empty(&info->indirect_pages));
311 indirect_page = list_first_entry(&info->indirect_pages,
312 struct page, lru);
313 list_del(&indirect_page->lru);
314 gnt_list_entry->page = indirect_page;
270 } 315 }
271 buffer_gfn = xen_page_to_gfn(gnt_list_entry->page); 316 grant_foreign_access(gnt_list_entry, info);
272 gnttab_grant_foreign_access_ref(gnt_list_entry->gref, 317
273 info->xbdev->otherend_id,
274 buffer_gfn, 0);
275 return gnt_list_entry; 318 return gnt_list_entry;
276} 319}
277 320
@@ -524,32 +567,19 @@ static int blkif_queue_rw_req(struct request *req)
524 567
525 if ((ring_req->operation == BLKIF_OP_INDIRECT) && 568 if ((ring_req->operation == BLKIF_OP_INDIRECT) &&
526 (i % SEGS_PER_INDIRECT_FRAME == 0)) { 569 (i % SEGS_PER_INDIRECT_FRAME == 0)) {
527 struct page *uninitialized_var(page);
528
529 if (segments) 570 if (segments)
530 kunmap_atomic(segments); 571 kunmap_atomic(segments);
531 572
532 n = i / SEGS_PER_INDIRECT_FRAME; 573 n = i / SEGS_PER_INDIRECT_FRAME;
533 if (!info->feature_persistent) { 574 gnt_list_entry = get_indirect_grant(&gref_head, info);
534 struct page *indirect_page;
535
536 /*
537 * Fetch a pre-allocated page to use for
538 * indirect grefs
539 */
540 BUG_ON(list_empty(&info->indirect_pages));
541 indirect_page = list_first_entry(&info->indirect_pages,
542 struct page, lru);
543 list_del(&indirect_page->lru);
544 page = indirect_page;
545 }
546 gnt_list_entry = get_grant(&gref_head, page, info);
547 info->shadow[id].indirect_grants[n] = gnt_list_entry; 575 info->shadow[id].indirect_grants[n] = gnt_list_entry;
548 segments = kmap_atomic(gnt_list_entry->page); 576 segments = kmap_atomic(gnt_list_entry->page);
549 ring_req->u.indirect.indirect_grefs[n] = gnt_list_entry->gref; 577 ring_req->u.indirect.indirect_grefs[n] = gnt_list_entry->gref;
550 } 578 }
551 579
552 gnt_list_entry = get_grant(&gref_head, sg_page(sg), info); 580 gnt_list_entry = get_grant(&gref_head,
581 xen_page_to_gfn(sg_page(sg)),
582 info);
553 ref = gnt_list_entry->gref; 583 ref = gnt_list_entry->gref;
554 584
555 info->shadow[id].grants_used[i] = gnt_list_entry; 585 info->shadow[id].grants_used[i] = gnt_list_entry;