Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Julien Grall and committed by
David Vrabel
4f503fbd a7a6df22

+59 -29
+59 -29
drivers/block/xen-blkfront.c
··· 244 244 return -ENOMEM; 245 245 } 246 246 247 - static struct grant *get_grant(grant_ref_t *gref_head, 248 - struct page *page, 249 - struct blkfront_info *info) 247 + static struct grant *get_free_grant(struct blkfront_info *info) 250 248 { 251 249 struct grant *gnt_list_entry; 252 - unsigned long buffer_gfn; 253 250 254 251 BUG_ON(list_empty(&info->grants)); 255 252 gnt_list_entry = list_first_entry(&info->grants, struct grant, 256 - node); 253 + node); 257 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 257 info->persistent_gnts_c--; 258 + 259 + return gnt_list_entry; 260 + } 261 + 262 + static 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 + 271 + static 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 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 } 291 + 292 + return gnt_list_entry; 293 + } 294 + 295 + static 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; 263 302 264 303 /* Assign a gref to this page */ 265 304 gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head); 266 305 BUG_ON(gnt_list_entry->gref == -ENOSPC); 267 306 if (!info->feature_persistent) { 268 - BUG_ON(!page); 269 - gnt_list_entry->page = page; 307 + struct page *indirect_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); 272 - gnttab_grant_foreign_access_ref(gnt_list_entry->gref, 273 - info->xbdev->otherend_id, 274 - buffer_gfn, 0); 316 + grant_foreign_access(gnt_list_entry, info); 317 + 275 318 return gnt_list_entry; 276 319 } 277 320 ··· 567 524 568 525 if ((ring_req->operation == BLKIF_OP_INDIRECT) && 569 526 (i % SEGS_PER_INDIRECT_FRAME == 0)) { 570 - struct page *uninitialized_var(page); 571 - 572 527 if (segments) 573 528 kunmap_atomic(segments); 574 529 575 530 n = i / SEGS_PER_INDIRECT_FRAME; 576 - if (!info->feature_persistent) { 577 - struct page *indirect_page; 578 - 579 - /* 580 - * Fetch a pre-allocated page to use for 581 - * indirect grefs 582 - */ 583 - BUG_ON(list_empty(&info->indirect_pages)); 584 - indirect_page = list_first_entry(&info->indirect_pages, 585 - struct page, lru); 586 - list_del(&indirect_page->lru); 587 - page = indirect_page; 588 - } 589 - gnt_list_entry = get_grant(&gref_head, page, info); 531 + gnt_list_entry = get_indirect_grant(&gref_head, info); 590 532 info->shadow[id].indirect_grants[n] = gnt_list_entry; 591 533 segments = kmap_atomic(gnt_list_entry->page); 592 534 ring_req->u.indirect.indirect_grefs[n] = gnt_list_entry->gref; 593 535 } 594 536 595 - gnt_list_entry = get_grant(&gref_head, sg_page(sg), info); 537 + gnt_list_entry = get_grant(&gref_head, 538 + xen_page_to_gfn(sg_page(sg)), 539 + info); 596 540 ref = gnt_list_entry->gref; 597 541 598 542 info->shadow[id].grants_used[i] = gnt_list_entry;