From dfc07b13dcacefda6ebdea14584ed8724dc980ef Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Mon, 18 Apr 2011 14:24:23 -0400 Subject: xen/blkback: Move it from drivers/xen to drivers/block .. and modify the Makefile and Kconfig files appropriately. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/Kconfig | 8 + drivers/block/Makefile | 1 + drivers/block/xen-blkback/Makefile | 3 + drivers/block/xen-blkback/blkback.c | 759 ++++++++++++++++++++++++++++++++++ drivers/block/xen-blkback/common.h | 142 +++++++ drivers/block/xen-blkback/interface.c | 185 +++++++++ drivers/block/xen-blkback/vbd.c | 162 ++++++++ drivers/block/xen-blkback/xenbus.c | 562 +++++++++++++++++++++++++ 8 files changed, 1822 insertions(+) create mode 100644 drivers/block/xen-blkback/Makefile create mode 100644 drivers/block/xen-blkback/blkback.c create mode 100644 drivers/block/xen-blkback/common.h create mode 100644 drivers/block/xen-blkback/interface.c create mode 100644 drivers/block/xen-blkback/vbd.c create mode 100644 drivers/block/xen-blkback/xenbus.c (limited to 'drivers/block') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 83c32cb72582..9abb64689712 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -470,6 +470,14 @@ config XEN_BLKDEV_FRONTEND block device driver. It communicates with a back-end driver in another domain which drives the actual block device. +config XEN_BLKDEV_BACKEND + tristate "Block-device backend driver" + depends on XEN_BACKEND + help + The block-device backend driver allows the kernel to export its + block devices to other guests via a high-performance shared-memory + interface. + config VIRTIO_BLK tristate "Virtio block driver (EXPERIMENTAL)" depends on EXPERIMENTAL && VIRTIO diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 40528ba56d1b..76646e9a1c91 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_BLK_DEV_UB) += ub.o obj-$(CONFIG_BLK_DEV_HD) += hd.o obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o +obj-$(CONFIG_XEN_BLKDEV_BACKEND) += xen-blkback/ obj-$(CONFIG_BLK_DEV_DRBD) += drbd/ obj-$(CONFIG_BLK_DEV_RBD) += rbd.o diff --git a/drivers/block/xen-blkback/Makefile b/drivers/block/xen-blkback/Makefile new file mode 100644 index 000000000000..f1ae1ff07a4d --- /dev/null +++ b/drivers/block/xen-blkback/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_XEN_BLKDEV_BACKEND) := xen-blkback.o + +xen-blkback-y := blkback.o xenbus.o interface.o vbd.o diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c new file mode 100644 index 000000000000..59a2bae0f35e --- /dev/null +++ b/drivers/block/xen-blkback/blkback.c @@ -0,0 +1,759 @@ +/****************************************************************************** + * + * Back-end of the driver for virtual block devices. This portion of the + * driver exports a 'unified' block-device interface that can be accessed + * by any operating system that implements a compatible front end. A + * reference front-end implementation can be found in: + * drivers/block/xen-blkfront.c + * + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand + * Copyright (c) 2005, Christopher Clark + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "common.h" + +#define WRITE_BARRIER (REQ_WRITE | REQ_FLUSH | REQ_FUA) + +/* + * These are rather arbitrary. They are fairly large because adjacent requests + * pulled from a communication ring are quite likely to end up being part of + * the same scatter/gather request at the disc. + * + * ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW ** + * + * This will increase the chances of being able to write whole tracks. + * 64 should be enough to keep us competitive with Linux. + */ +static int blkif_reqs = 64; +module_param_named(reqs, blkif_reqs, int, 0); +MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate"); + +/* Run-time switchable: /sys/module/blkback/parameters/ */ +static unsigned int log_stats; +static unsigned int debug_lvl; +module_param(log_stats, int, 0644); +module_param(debug_lvl, int, 0644); + +/* + * Each outstanding request that we've passed to the lower device layers has a + * 'pending_req' allocated to it. Each buffer_head that completes decrements + * the pendcnt towards zero. When it hits zero, the specified domain has a + * response queued for it, with the saved 'id' passed back. + */ +struct pending_req { + struct blkif_st *blkif; + u64 id; + int nr_pages; + atomic_t pendcnt; + unsigned short operation; + int status; + struct list_head free_list; +}; + +#define BLKBACK_INVALID_HANDLE (~0) + +struct xen_blkbk { + struct pending_req *pending_reqs; + /* List of all 'pending_req' available */ + struct list_head pending_free; + /* And its spinlock. */ + spinlock_t pending_free_lock; + wait_queue_head_t pending_free_wq; + /* The list of all pages that are available. */ + struct page **pending_pages; + /* And the grant handles that are available. */ + grant_handle_t *pending_grant_handles; +}; + +static struct xen_blkbk *blkbk; + +/* + * Little helpful macro to figure out the index and virtual address of the + * pending_pages[..]. For each 'pending_req' we have have up to + * BLKIF_MAX_SEGMENTS_PER_REQUEST (11) pages. The seg would be from 0 through + * 10 and would index in the pending_pages[..]. */ +static inline int vaddr_pagenr(struct pending_req *req, int seg) +{ + return (req - blkbk->pending_reqs) * + BLKIF_MAX_SEGMENTS_PER_REQUEST + seg; +} + +#define pending_page(req, seg) pending_pages[vaddr_pagenr(req, seg)] + +static inline unsigned long vaddr(struct pending_req *req, int seg) +{ + unsigned long pfn = page_to_pfn(blkbk->pending_page(req, seg)); + return (unsigned long)pfn_to_kaddr(pfn); +} + +#define pending_handle(_req, _seg) \ + (blkbk->pending_grant_handles[vaddr_pagenr(_req, _seg)]) + + +static int do_block_io_op(struct blkif_st *blkif); +static void dispatch_rw_block_io(struct blkif_st *blkif, + struct blkif_request *req, + struct pending_req *pending_req); +static void make_response(struct blkif_st *blkif, u64 id, + unsigned short op, int st); + +/* + * Retrieve from the 'pending_reqs' a free pending_req structure to be used. + */ +static struct pending_req *alloc_req(void) +{ + struct pending_req *req = NULL; + unsigned long flags; + + spin_lock_irqsave(&blkbk->pending_free_lock, flags); + if (!list_empty(&blkbk->pending_free)) { + req = list_entry(blkbk->pending_free.next, struct pending_req, + free_list); + list_del(&req->free_list); + } + spin_unlock_irqrestore(&blkbk->pending_free_lock, flags); + return req; +} + +/* + * Return the 'pending_req' structure back to the freepool. We also + * wake up the thread if it was waiting for a free page. + */ +static void free_req(struct pending_req *req) +{ + unsigned long flags; + int was_empty; + + spin_lock_irqsave(&blkbk->pending_free_lock, flags); + was_empty = list_empty(&blkbk->pending_free); + list_add(&req->free_list, &blkbk->pending_free); + spin_unlock_irqrestore(&blkbk->pending_free_lock, flags); + if (was_empty) + wake_up(&blkbk->pending_free_wq); +} + +/* + * Notification from the guest OS. + */ +static void blkif_notify_work(struct blkif_st *blkif) +{ + blkif->waiting_reqs = 1; + wake_up(&blkif->wq); +} + +irqreturn_t blkif_be_int(int irq, void *dev_id) +{ + blkif_notify_work(dev_id); + return IRQ_HANDLED; +} + +/* + * SCHEDULER FUNCTIONS + */ + +static void print_stats(struct blkif_st *blkif) +{ + printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d\n", + current->comm, blkif->st_oo_req, + blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req); + blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); + blkif->st_rd_req = 0; + blkif->st_wr_req = 0; + blkif->st_oo_req = 0; +} + +int blkif_schedule(void *arg) +{ + struct blkif_st *blkif = arg; + struct vbd *vbd = &blkif->vbd; + + blkif_get(blkif); + + if (debug_lvl) + printk(KERN_DEBUG "%s: started\n", current->comm); + + while (!kthread_should_stop()) { + if (try_to_freeze()) + continue; + if (unlikely(vbd->size != vbd_size(vbd))) + vbd_resize(blkif); + + wait_event_interruptible( + blkif->wq, + blkif->waiting_reqs || kthread_should_stop()); + wait_event_interruptible( + blkbk->pending_free_wq, + !list_empty(&blkbk->pending_free) || + kthread_should_stop()); + + blkif->waiting_reqs = 0; + smp_mb(); /* clear flag *before* checking for work */ + + if (do_block_io_op(blkif)) + blkif->waiting_reqs = 1; + + if (log_stats && time_after(jiffies, blkif->st_print)) + print_stats(blkif); + } + + if (log_stats) + print_stats(blkif); + if (debug_lvl) + printk(KERN_DEBUG "%s: exiting\n", current->comm); + + blkif->xenblkd = NULL; + blkif_put(blkif); + + return 0; +} + +struct seg_buf { + unsigned long buf; + unsigned int nsec; +}; +/* + * Unmap the grant references, and also remove the M2P over-rides + * used in the 'pending_req'. +*/ +static void xen_blkbk_unmap(struct pending_req *req) +{ + struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + unsigned int i, invcount = 0; + grant_handle_t handle; + int ret; + + for (i = 0; i < req->nr_pages; i++) { + handle = pending_handle(req, i); + if (handle == BLKBACK_INVALID_HANDLE) + continue; + gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i), + GNTMAP_host_map, handle); + pending_handle(req, i) = BLKBACK_INVALID_HANDLE; + invcount++; + } + + ret = HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, unmap, invcount); + BUG_ON(ret); + /* Note, we use invcount, so nr->pages, so we can't index + * using vaddr(req, i). + */ + for (i = 0; i < invcount; i++) { + ret = m2p_remove_override( + virt_to_page(unmap[i].host_addr), false); + if (ret) { + printk(KERN_ALERT "Failed to remove M2P override for " \ + "%lx\n", (unsigned long)unmap[i].host_addr); + continue; + } + } +} +static int xen_blkbk_map(struct blkif_request *req, struct pending_req *pending_req, + struct seg_buf seg[]) +{ + struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i; + int nseg = req->nr_segments; + int ret = 0; + /* Fill out preq.nr_sects with proper amount of sectors, and setup + * assign map[..] with the PFN of the page in our domain with the + * corresponding grant reference for each page. + */ + for (i = 0; i < nseg; i++) { + uint32_t flags; + + flags = GNTMAP_host_map; + if (pending_req->operation != BLKIF_OP_READ) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags, + req->u.rw.seg[i].gref, pending_req->blkif->domid); + } + + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); + BUG_ON(ret); + + /* Now swizzel the MFN in our domain with the MFN from the other domain + * so that when we access vaddr(pending_req,i) it has the contents of + * the page from the other domain. + */ + for (i = 0; i < nseg; i++) { + if (unlikely(map[i].status != 0)) { + DPRINTK("invalid buffer -- could not remap it\n"); + map[i].handle = BLKBACK_INVALID_HANDLE; + ret |= 1; + } + + pending_handle(pending_req, i) = map[i].handle; + + if (ret) + continue; + + ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr), + blkbk->pending_page(pending_req, i), false); + if (ret) { + printk(KERN_ALERT "Failed to install M2P override for"\ + " %lx (ret: %d)\n", (unsigned long) + map[i].dev_bus_addr, ret); + /* We could switch over to GNTTABOP_copy */ + continue; + } + + seg[i].buf = map[i].dev_bus_addr | + (req->u.rw.seg[i].first_sect << 9); + } + return ret; +} + +/* + * Completion callback on the bio's. Called as bh->b_end_io() + */ + +static void __end_block_io_op(struct pending_req *pending_req, int error) +{ + /* An error fails the entire request. */ + if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) && + (error == -EOPNOTSUPP)) { + DPRINTK("blkback: write barrier op failed, not supported\n"); + blkback_barrier(XBT_NIL, pending_req->blkif->be, 0); + pending_req->status = BLKIF_RSP_EOPNOTSUPP; + } else if (error) { + DPRINTK("Buffer not up-to-date at end of operation, " + "error=%d\n", error); + pending_req->status = BLKIF_RSP_ERROR; + } + + /* If all of the bio's have completed it is time to unmap + * the grant references associated with 'request' and provide + * the proper response on the ring. + */ + if (atomic_dec_and_test(&pending_req->pendcnt)) { + xen_blkbk_unmap(pending_req); + make_response(pending_req->blkif, pending_req->id, + pending_req->operation, pending_req->status); + blkif_put(pending_req->blkif); + free_req(pending_req); + } +} + +/* + * bio callback. + */ +static void end_block_io_op(struct bio *bio, int error) +{ + __end_block_io_op(bio->bi_private, error); + bio_put(bio); +} + + + +/* + * Function to copy the from the ring buffer the 'struct blkif_request' + * (which has the sectors we want, number of them, grant references, etc), + * and transmute it to the block API to hand it over to the proper block disk. + */ +static int do_block_io_op(struct blkif_st *blkif) +{ + union blkif_back_rings *blk_rings = &blkif->blk_rings; + struct blkif_request req; + struct pending_req *pending_req; + RING_IDX rc, rp; + int more_to_do = 0; + + rc = blk_rings->common.req_cons; + rp = blk_rings->common.sring->req_prod; + rmb(); /* Ensure we see queued requests up to 'rp'. */ + + while (rc != rp) { + + if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) + break; + + if (kthread_should_stop()) { + more_to_do = 1; + break; + } + + pending_req = alloc_req(); + if (NULL == pending_req) { + blkif->st_oo_req++; + more_to_do = 1; + break; + } + + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req)); + break; + case BLKIF_PROTOCOL_X86_32: + blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc)); + break; + case BLKIF_PROTOCOL_X86_64: + blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc)); + break; + default: + BUG(); + } + blk_rings->common.req_cons = ++rc; /* before make_response() */ + + /* Apply all sanity checks to /private copy/ of request. */ + barrier(); + + switch (req.operation) { + case BLKIF_OP_READ: + blkif->st_rd_req++; + dispatch_rw_block_io(blkif, &req, pending_req); + break; + case BLKIF_OP_WRITE_BARRIER: + blkif->st_br_req++; + /* fall through */ + case BLKIF_OP_WRITE: + blkif->st_wr_req++; + dispatch_rw_block_io(blkif, &req, pending_req); + break; + default: + /* A good sign something is wrong: sleep for a while to + * avoid excessive CPU consumption by a bad guest. */ + msleep(1); + DPRINTK("error: unknown block io operation [%d]\n", + req.operation); + make_response(blkif, req.id, req.operation, + BLKIF_RSP_ERROR); + free_req(pending_req); + break; + } + + /* Yield point for this unbounded loop. */ + cond_resched(); + } + + return more_to_do; +} + +/* + * Transumation of the 'struct blkif_request' to a proper 'struct bio' + * and call the 'submit_bio' to pass it to the underlaying storage. + */ +static void dispatch_rw_block_io(struct blkif_st *blkif, + struct blkif_request *req, + struct pending_req *pending_req) +{ + struct phys_req preq; + struct seg_buf seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + unsigned int nseg; + struct bio *bio = NULL; + struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + int i, nbio = 0; + int operation; + struct blk_plug plug; + + switch (req->operation) { + case BLKIF_OP_READ: + operation = READ; + break; + case BLKIF_OP_WRITE: + operation = WRITE; + break; + case BLKIF_OP_WRITE_BARRIER: + operation = WRITE_BARRIER; + break; + default: + operation = 0; /* make gcc happy */ + BUG(); + } + + /* Check that the number of segments is sane. */ + nseg = req->nr_segments; + if (unlikely(nseg == 0 && operation != WRITE_BARRIER) || + unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { + DPRINTK("Bad number of segments in request (%d)\n", nseg); + /* Haven't submitted any bio's yet. */ + goto fail_response; + } + + preq.dev = req->handle; + preq.sector_number = req->u.rw.sector_number; + preq.nr_sects = 0; + + pending_req->blkif = blkif; + pending_req->id = req->id; + pending_req->operation = req->operation; + pending_req->status = BLKIF_RSP_OKAY; + pending_req->nr_pages = nseg; + + for (i = 0; i < nseg; i++) { + seg[i].nsec = req->u.rw.seg[i].last_sect - + req->u.rw.seg[i].first_sect + 1; + if ((req->u.rw.seg[i].last_sect >= (PAGE_SIZE >> 9)) || + (req->u.rw.seg[i].last_sect < req->u.rw.seg[i].first_sect)) + goto fail_response; + preq.nr_sects += seg[i].nsec; + + } + + if (vbd_translate(&preq, blkif, operation) != 0) { + DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", + operation == READ ? "read" : "write", + preq.sector_number, + preq.sector_number + preq.nr_sects, preq.dev); + goto fail_response; + } + /* This check _MUST_ be done after vbd_translate as the preq.bdev + * is set there. */ + for (i = 0; i < nseg; i++) { + if (((int)preq.sector_number|(int)seg[i].nsec) & + ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) { + DPRINTK("Misaligned I/O request from domain %d", + blkif->domid); + goto fail_response; + } + } + /* If we have failed at this point, we need to undo the M2P override, + * set gnttab_set_unmap_op on all of the grant references and perform + * the hypercall to unmap the grants - that is all done in + * xen_blkbk_unmap. + */ + if (xen_blkbk_map(req, pending_req, seg)) + goto fail_flush; + + /* This corresponding blkif_put is done in __end_block_io_op */ + blkif_get(blkif); + + for (i = 0; i < nseg; i++) { + while ((bio == NULL) || + (bio_add_page(bio, + blkbk->pending_page(pending_req, i), + seg[i].nsec << 9, + seg[i].buf & ~PAGE_MASK) == 0)) { + + bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i); + if (unlikely(bio == NULL)) + goto fail_put_bio; + + bio->bi_bdev = preq.bdev; + bio->bi_private = pending_req; + bio->bi_end_io = end_block_io_op; + bio->bi_sector = preq.sector_number; + } + + preq.sector_number += seg[i].nsec; + } + + /* This will be hit if the operation was a barrier. */ + if (!bio) { + BUG_ON(operation != WRITE_BARRIER); + bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0); + if (unlikely(bio == NULL)) + goto fail_put_bio; + + bio->bi_bdev = preq.bdev; + bio->bi_private = pending_req; + bio->bi_end_io = end_block_io_op; + bio->bi_sector = -1; + } + + + /* We set it one so that the last submit_bio does not have to call + * atomic_inc. + */ + atomic_set(&pending_req->pendcnt, nbio); + + /* Get a reference count for the disk queue and start sending I/O */ + blk_start_plug(&plug); + + for (i = 0; i < nbio; i++) + submit_bio(operation, biolist[i]); + + blk_finish_plug(&plug); + /* Let the I/Os go.. */ + + if (operation == READ) + blkif->st_rd_sect += preq.nr_sects; + else if (operation == WRITE || operation == WRITE_BARRIER) + blkif->st_wr_sect += preq.nr_sects; + + return; + + fail_flush: + xen_blkbk_unmap(pending_req); + fail_response: + /* Haven't submitted any bio's yet. */ + make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); + free_req(pending_req); + msleep(1); /* back off a bit */ + return; + + fail_put_bio: + for (i = 0; i < (nbio-1); i++) + bio_put(biolist[i]); + __end_block_io_op(pending_req, -EINVAL); + msleep(1); /* back off a bit */ + return; +} + + + +/* + * Put a response on the ring on how the operation fared. + */ +static void make_response(struct blkif_st *blkif, u64 id, + unsigned short op, int st) +{ + struct blkif_response resp; + unsigned long flags; + union blkif_back_rings *blk_rings = &blkif->blk_rings; + int more_to_do = 0; + int notify; + + resp.id = id; + resp.operation = op; + resp.status = st; + + spin_lock_irqsave(&blkif->blk_ring_lock, flags); + /* Place on the response ring for the relevant domain. */ + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_32: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_64: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + default: + BUG(); + } + blk_rings->common.rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify); + if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) { + /* + * Tail check for pending requests. Allows frontend to avoid + * notifications if requests are already in flight (lower + * overheads and promotes batching). + */ + RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do); + + } else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) { + more_to_do = 1; + } + + spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); + + if (more_to_do) + blkif_notify_work(blkif); + if (notify) + notify_remote_via_irq(blkif->irq); +} + +static int __init blkif_init(void) +{ + int i, mmap_pages; + int rc = 0; + + if (!xen_pv_domain()) + return -ENODEV; + + blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL); + if (!blkbk) { + printk(KERN_ALERT "%s: out of memory!\n", __func__); + return -ENOMEM; + } + + mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST; + + blkbk->pending_reqs = kmalloc(sizeof(blkbk->pending_reqs[0]) * + blkif_reqs, GFP_KERNEL); + blkbk->pending_grant_handles = kzalloc(sizeof(blkbk->pending_grant_handles[0]) * + mmap_pages, GFP_KERNEL); + blkbk->pending_pages = kzalloc(sizeof(blkbk->pending_pages[0]) * + mmap_pages, GFP_KERNEL); + + if (!blkbk->pending_reqs || !blkbk->pending_grant_handles || + !blkbk->pending_pages) { + rc = -ENOMEM; + goto out_of_memory; + } + + for (i = 0; i < mmap_pages; i++) { + blkbk->pending_grant_handles[i] = BLKBACK_INVALID_HANDLE; + blkbk->pending_pages[i] = alloc_page(GFP_KERNEL); + if (blkbk->pending_pages[i] == NULL) { + rc = -ENOMEM; + goto out_of_memory; + } + } + rc = blkif_interface_init(); + if (rc) + goto failed_init; + + memset(blkbk->pending_reqs, 0, sizeof(blkbk->pending_reqs)); + + INIT_LIST_HEAD(&blkbk->pending_free); + spin_lock_init(&blkbk->pending_free_lock); + init_waitqueue_head(&blkbk->pending_free_wq); + + for (i = 0; i < blkif_reqs; i++) + list_add_tail(&blkbk->pending_reqs[i].free_list, + &blkbk->pending_free); + + rc = blkif_xenbus_init(); + if (rc) + goto failed_init; + + return 0; + + out_of_memory: + printk(KERN_ERR "%s: out of memory\n", __func__); + failed_init: + kfree(blkbk->pending_reqs); + kfree(blkbk->pending_grant_handles); + for (i = 0; i < mmap_pages; i++) { + if (blkbk->pending_pages[i]) + __free_page(blkbk->pending_pages[i]); + } + kfree(blkbk->pending_pages); + kfree(blkbk); + blkbk = NULL; + return rc; +} + +module_init(blkif_init); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h new file mode 100644 index 000000000000..6257c1106591 --- /dev/null +++ b/drivers/block/xen-blkback/common.h @@ -0,0 +1,142 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __BLKIF__BACKEND__COMMON_H__ +#define __BLKIF__BACKEND__COMMON_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DPRINTK(_f, _a...) \ + pr_debug("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a) + +struct vbd { + blkif_vdev_t handle; /* what the domain refers to this vbd as */ + unsigned char readonly; /* Non-zero -> read-only */ + unsigned char type; /* VDISK_xxx */ + u32 pdevice; /* phys device that this vbd maps to */ + struct block_device *bdev; + sector_t size; /* Cached size parameter */ +}; + +struct backend_info; + +struct blkif_st { + /* Unique identifier for this interface. */ + domid_t domid; + unsigned int handle; + /* Physical parameters of the comms window. */ + unsigned int irq; + /* Comms information. */ + enum blkif_protocol blk_protocol; + union blkif_back_rings blk_rings; + struct vm_struct *blk_ring_area; + /* The VBD attached to this interface. */ + struct vbd vbd; + /* Back pointer to the backend_info. */ + struct backend_info *be; + /* Private fields. */ + spinlock_t blk_ring_lock; + atomic_t refcnt; + + wait_queue_head_t wq; + /* One thread per one blkif. */ + struct task_struct *xenblkd; + unsigned int waiting_reqs; + + /* statistics */ + unsigned long st_print; + int st_rd_req; + int st_wr_req; + int st_oo_req; + int st_br_req; + int st_rd_sect; + int st_wr_sect; + + wait_queue_head_t waiting_to_free; + + grant_handle_t shmem_handle; + grant_ref_t shmem_ref; +}; + +struct blkif_st *blkif_alloc(domid_t domid); +void blkif_disconnect(struct blkif_st *blkif); +void blkif_free(struct blkif_st *blkif); +int blkif_map(struct blkif_st *blkif, unsigned long shared_page, + unsigned int evtchn); +void vbd_resize(struct blkif_st *blkif); + +#define blkif_get(_b) (atomic_inc(&(_b)->refcnt)) +#define blkif_put(_b) \ + do { \ + if (atomic_dec_and_test(&(_b)->refcnt)) \ + wake_up(&(_b)->waiting_to_free);\ + } while (0) + +/* Create a vbd. */ +int vbd_create(struct blkif_st *blkif, blkif_vdev_t vdevice, unsigned major, + unsigned minor, int readonly, int cdrom); +void vbd_free(struct vbd *vbd); + +unsigned long long vbd_size(struct vbd *vbd); +unsigned int vbd_info(struct vbd *vbd); +unsigned long vbd_secsize(struct vbd *vbd); + +struct phys_req { + unsigned short dev; + unsigned short nr_sects; + struct block_device *bdev; + blkif_sector_t sector_number; +}; + +int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation); + +int blkif_interface_init(void); + +int blkif_xenbus_init(void); + +irqreturn_t blkif_be_int(int irq, void *dev_id); +int blkif_schedule(void *arg); + +int blkback_barrier(struct xenbus_transaction xbt, + struct backend_info *be, int state); + +struct xenbus_device *blkback_xenbus(struct backend_info *be); + +#endif /* __BLKIF__BACKEND__COMMON_H__ */ diff --git a/drivers/block/xen-blkback/interface.c b/drivers/block/xen-blkback/interface.c new file mode 100644 index 000000000000..163aed41e825 --- /dev/null +++ b/drivers/block/xen-blkback/interface.c @@ -0,0 +1,185 @@ +/****************************************************************************** + * Block-device interface management. + * + * Copyright (c) 2004, Keir Fraser + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "common.h" +#include +#include +#include + +static struct kmem_cache *blkif_cachep; + +struct blkif_st *blkif_alloc(domid_t domid) +{ + struct blkif_st *blkif; + + blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL); + if (!blkif) + return ERR_PTR(-ENOMEM); + + memset(blkif, 0, sizeof(*blkif)); + blkif->domid = domid; + spin_lock_init(&blkif->blk_ring_lock); + atomic_set(&blkif->refcnt, 1); + init_waitqueue_head(&blkif->wq); + blkif->st_print = jiffies; + init_waitqueue_head(&blkif->waiting_to_free); + + return blkif; +} + +static int map_frontend_page(struct blkif_st *blkif, unsigned long shared_page) +{ + struct gnttab_map_grant_ref op; + + gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, shared_page, blkif->domid); + + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + + if (op.status) { + DPRINTK(" Grant table operation failure !\n"); + return op.status; + } + + blkif->shmem_ref = shared_page; + blkif->shmem_handle = op.handle; + + return 0; +} + +static void unmap_frontend_page(struct blkif_st *blkif) +{ + struct gnttab_unmap_grant_ref op; + + gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, blkif->shmem_handle); + + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); +} + +int blkif_map(struct blkif_st *blkif, unsigned long shared_page, + unsigned int evtchn) +{ + int err; + + /* Already connected through? */ + if (blkif->irq) + return 0; + + blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); + if (!blkif->blk_ring_area) + return -ENOMEM; + + err = map_frontend_page(blkif, shared_page); + if (err) { + free_vm_area(blkif->blk_ring_area); + return err; + } + + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + { + struct blkif_sring *sring; + sring = (struct blkif_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); + break; + } + case BLKIF_PROTOCOL_X86_32: + { + struct blkif_x86_32_sring *sring_x86_32; + sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + struct blkif_x86_64_sring *sring_x86_64; + sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); + break; + } + default: + BUG(); + } + + err = bind_interdomain_evtchn_to_irqhandler( + blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif); + if (err < 0) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + blkif->blk_rings.common.sring = NULL; + return err; + } + blkif->irq = err; + + return 0; +} + +void blkif_disconnect(struct blkif_st *blkif) +{ + if (blkif->xenblkd) { + kthread_stop(blkif->xenblkd); + blkif->xenblkd = NULL; + } + + atomic_dec(&blkif->refcnt); + wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); + atomic_inc(&blkif->refcnt); + + if (blkif->irq) { + unbind_from_irqhandler(blkif->irq, blkif); + blkif->irq = 0; + } + + if (blkif->blk_rings.common.sring) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + blkif->blk_rings.common.sring = NULL; + } +} + +void blkif_free(struct blkif_st *blkif) +{ + if (!atomic_dec_and_test(&blkif->refcnt)) + BUG(); + kmem_cache_free(blkif_cachep, blkif); +} + +int __init blkif_interface_init(void) +{ + blkif_cachep = kmem_cache_create("blkif_cache", sizeof(struct blkif_st), + 0, 0, NULL); + if (!blkif_cachep) + return -ENOMEM; + + return 0; +} diff --git a/drivers/block/xen-blkback/vbd.c b/drivers/block/xen-blkback/vbd.c new file mode 100644 index 000000000000..d0ff4cf91a34 --- /dev/null +++ b/drivers/block/xen-blkback/vbd.c @@ -0,0 +1,162 @@ +/****************************************************************************** + * Routines for managing virtual block devices (VBDs). + * + * Copyright (c) 2003-2005, Keir Fraser & Steve Hand + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "common.h" + +#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ + (_v)->bdev->bd_part->nr_sects : \ + get_capacity((_v)->bdev->bd_disk)) + +unsigned long long vbd_size(struct vbd *vbd) +{ + return vbd_sz(vbd); +} + +unsigned int vbd_info(struct vbd *vbd) +{ + return vbd->type | (vbd->readonly ? VDISK_READONLY : 0); +} + +unsigned long vbd_secsize(struct vbd *vbd) +{ + return bdev_logical_block_size(vbd->bdev); +} + +int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, unsigned major, + unsigned minor, int readonly, int cdrom) +{ + struct vbd *vbd; + struct block_device *bdev; + + vbd = &blkif->vbd; + vbd->handle = handle; + vbd->readonly = readonly; + vbd->type = 0; + + vbd->pdevice = MKDEV(major, minor); + + bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? + FMODE_READ : FMODE_WRITE, NULL); + + if (IS_ERR(bdev)) { + DPRINTK("vbd_creat: device %08x could not be opened.\n", + vbd->pdevice); + return -ENOENT; + } + + vbd->bdev = bdev; + vbd->size = vbd_size(vbd); + + if (vbd->bdev->bd_disk == NULL) { + DPRINTK("vbd_creat: device %08x doesn't exist.\n", + vbd->pdevice); + vbd_free(vbd); + return -ENOENT; + } + + if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) + vbd->type |= VDISK_CDROM; + if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) + vbd->type |= VDISK_REMOVABLE; + + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", + handle, blkif->domid); + return 0; +} + +void vbd_free(struct vbd *vbd) +{ + if (vbd->bdev) + blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); + vbd->bdev = NULL; +} + +int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation) +{ + struct vbd *vbd = &blkif->vbd; + int rc = -EACCES; + + if ((operation != READ) && vbd->readonly) + goto out; + + if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) + goto out; + + req->dev = vbd->pdevice; + req->bdev = vbd->bdev; + rc = 0; + + out: + return rc; +} + +void vbd_resize(struct blkif_st *blkif) +{ + struct vbd *vbd = &blkif->vbd; + struct xenbus_transaction xbt; + int err; + struct xenbus_device *dev = blkback_xenbus(blkif->be); + unsigned long long new_size = vbd_size(vbd); + + printk(KERN_INFO "VBD Resize: Domid: %d, Device: (%d, %d)\n", + blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice)); + printk(KERN_INFO "VBD Resize: new size %llu\n", new_size); + vbd->size = new_size; +again: + err = xenbus_transaction_start(&xbt); + if (err) { + printk(KERN_WARNING "Error starting transaction"); + return; + } + err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", + vbd_size(vbd)); + if (err) { + printk(KERN_WARNING "Error writing new size"); + goto abort; + } + /* + * Write the current state; we will use this to synchronize + * the front-end. If the current state is "connected" the + * front-end will get the new size information online. + */ + err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); + if (err) { + printk(KERN_WARNING "Error writing the state"); + goto abort; + } + + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + printk(KERN_WARNING "Error ending transaction"); +abort: + xenbus_transaction_end(xbt, 1); +} diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c new file mode 100644 index 000000000000..b41ed65db2d3 --- /dev/null +++ b/drivers/block/xen-blkback/xenbus.c @@ -0,0 +1,562 @@ +/* Xenbus code for blkif backend + Copyright (C) 2005 Rusty Russell + Copyright (C) 2005 XenSource Ltd + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include "common.h" + +#undef DPRINTK +#define DPRINTK(fmt, args...) \ + pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \ + __func__, __LINE__, ##args) + +struct backend_info { + struct xenbus_device *dev; + struct blkif_st *blkif; + struct xenbus_watch backend_watch; + unsigned major; + unsigned minor; + char *mode; +}; + +static void connect(struct backend_info *); +static int connect_ring(struct backend_info *); +static void backend_changed(struct xenbus_watch *, const char **, + unsigned int); + +struct xenbus_device *blkback_xenbus(struct backend_info *be) +{ + return be->dev; +} + +static int blkback_name(struct blkif_st *blkif, char *buf) +{ + char *devpath, *devname; + struct xenbus_device *dev = blkif->be->dev; + + devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL); + if (IS_ERR(devpath)) + return PTR_ERR(devpath); + + devname = strstr(devpath, "/dev/"); + if (devname != NULL) + devname += strlen("/dev/"); + else + devname = devpath; + + snprintf(buf, TASK_COMM_LEN, "blkback.%d.%s", blkif->domid, devname); + kfree(devpath); + + return 0; +} + +static void update_blkif_status(struct blkif_st *blkif) +{ + int err; + char name[TASK_COMM_LEN]; + + /* Not ready to connect? */ + if (!blkif->irq || !blkif->vbd.bdev) + return; + + /* Already connected? */ + if (blkif->be->dev->state == XenbusStateConnected) + return; + + /* Attempt to connect: exit if we fail to. */ + connect(blkif->be); + if (blkif->be->dev->state != XenbusStateConnected) + return; + + err = blkback_name(blkif, name); + if (err) { + xenbus_dev_error(blkif->be->dev, err, "get blkback dev name"); + return; + } + + err = filemap_write_and_wait(blkif->vbd.bdev->bd_inode->i_mapping); + if (err) { + xenbus_dev_error(blkif->be->dev, err, "block flush"); + return; + } + invalidate_inode_pages2(blkif->vbd.bdev->bd_inode->i_mapping); + + blkif->xenblkd = kthread_run(blkif_schedule, blkif, name); + if (IS_ERR(blkif->xenblkd)) { + err = PTR_ERR(blkif->xenblkd); + blkif->xenblkd = NULL; + xenbus_dev_error(blkif->be->dev, err, "start xenblkd"); + } +} + + +/* + * sysfs interface for VBD I/O requests + */ + +#define VBD_SHOW(name, format, args...) \ + static ssize_t show_##name(struct device *_dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + struct xenbus_device *dev = to_xenbus_device(_dev); \ + struct backend_info *be = dev_get_drvdata(&dev->dev); \ + \ + return sprintf(buf, format, ##args); \ + } \ + static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + +VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); +VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); +VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); +VBD_SHOW(br_req, "%d\n", be->blkif->st_br_req); +VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect); +VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect); + +static struct attribute *vbdstat_attrs[] = { + &dev_attr_oo_req.attr, + &dev_attr_rd_req.attr, + &dev_attr_wr_req.attr, + &dev_attr_br_req.attr, + &dev_attr_rd_sect.attr, + &dev_attr_wr_sect.attr, + NULL +}; + +static struct attribute_group vbdstat_group = { + .name = "statistics", + .attrs = vbdstat_attrs, +}; + +VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); +VBD_SHOW(mode, "%s\n", be->mode); + +int xenvbd_sysfs_addif(struct xenbus_device *dev) +{ + int error; + + error = device_create_file(&dev->dev, &dev_attr_physical_device); + if (error) + goto fail1; + + error = device_create_file(&dev->dev, &dev_attr_mode); + if (error) + goto fail2; + + error = sysfs_create_group(&dev->dev.kobj, &vbdstat_group); + if (error) + goto fail3; + + return 0; + +fail3: sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); +fail2: device_remove_file(&dev->dev, &dev_attr_mode); +fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); + return error; +} + +void xenvbd_sysfs_delif(struct xenbus_device *dev) +{ + sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); + device_remove_file(&dev->dev, &dev_attr_mode); + device_remove_file(&dev->dev, &dev_attr_physical_device); +} + +static int blkback_remove(struct xenbus_device *dev) +{ + struct backend_info *be = dev_get_drvdata(&dev->dev); + + DPRINTK(""); + + if (be->major || be->minor) + xenvbd_sysfs_delif(dev); + + if (be->backend_watch.node) { + unregister_xenbus_watch(&be->backend_watch); + kfree(be->backend_watch.node); + be->backend_watch.node = NULL; + } + + if (be->blkif) { + blkif_disconnect(be->blkif); + vbd_free(&be->blkif->vbd); + blkif_free(be->blkif); + be->blkif = NULL; + } + + kfree(be); + dev_set_drvdata(&dev->dev, NULL); + return 0; +} + +int blkback_barrier(struct xenbus_transaction xbt, + struct backend_info *be, int state) +{ + struct xenbus_device *dev = be->dev; + int err; + + err = xenbus_printf(xbt, dev->nodename, "feature-barrier", + "%d", state); + if (err) + xenbus_dev_fatal(dev, err, "writing feature-barrier"); + + return err; +} + +/** + * Entry point to this code when a new device is created. Allocate the basic + * structures, and watch the store waiting for the hotplug scripts to tell us + * the device's physical major and minor numbers. Switch to InitWait. + */ +static int blkback_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) +{ + int err; + struct backend_info *be = kzalloc(sizeof(struct backend_info), + GFP_KERNEL); + if (!be) { + xenbus_dev_fatal(dev, -ENOMEM, + "allocating backend structure"); + return -ENOMEM; + } + be->dev = dev; + dev_set_drvdata(&dev->dev, be); + + be->blkif = blkif_alloc(dev->otherend_id); + if (IS_ERR(be->blkif)) { + err = PTR_ERR(be->blkif); + be->blkif = NULL; + xenbus_dev_fatal(dev, err, "creating block interface"); + goto fail; + } + + /* setup back pointer */ + be->blkif->be = be; + + err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed, + "%s/%s", dev->nodename, "physical-device"); + if (err) + goto fail; + + err = xenbus_switch_state(dev, XenbusStateInitWait); + if (err) + goto fail; + + return 0; + +fail: + DPRINTK("failed"); + blkback_remove(dev); + return err; +} + + +/** + * Callback received when the hotplug scripts have placed the physical-device + * node. Read it and the mode node, and create a vbd. If the frontend is + * ready, connect. + */ +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + int err; + unsigned major; + unsigned minor; + struct backend_info *be + = container_of(watch, struct backend_info, backend_watch); + struct xenbus_device *dev = be->dev; + int cdrom = 0; + char *device_type; + + DPRINTK(""); + + err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x", + &major, &minor); + if (XENBUS_EXIST_ERR(err)) { + /* Since this watch will fire once immediately after it is + registered, we expect this. Ignore it, and wait for the + hotplug scripts. */ + return; + } + if (err != 2) { + xenbus_dev_fatal(dev, err, "reading physical-device"); + return; + } + + if ((be->major || be->minor) && + ((be->major != major) || (be->minor != minor))) { + printk(KERN_WARNING + "blkback: changing physical device (from %x:%x to " + "%x:%x) not supported.\n", be->major, be->minor, + major, minor); + return; + } + + be->mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL); + if (IS_ERR(be->mode)) { + err = PTR_ERR(be->mode); + be->mode = NULL; + xenbus_dev_fatal(dev, err, "reading mode"); + return; + } + + device_type = xenbus_read(XBT_NIL, dev->otherend, "device-type", NULL); + if (!IS_ERR(device_type)) { + cdrom = strcmp(device_type, "cdrom") == 0; + kfree(device_type); + } + + if (be->major == 0 && be->minor == 0) { + /* Front end dir is a number, which is used as the handle. */ + + char *p = strrchr(dev->otherend, '/') + 1; + long handle; + err = strict_strtoul(p, 0, &handle); + if (err) + return; + + be->major = major; + be->minor = minor; + + err = vbd_create(be->blkif, handle, major, minor, + (NULL == strchr(be->mode, 'w')), cdrom); + if (err) { + be->major = be->minor = 0; + xenbus_dev_fatal(dev, err, "creating vbd structure"); + return; + } + + err = xenvbd_sysfs_addif(dev); + if (err) { + vbd_free(&be->blkif->vbd); + be->major = be->minor = 0; + xenbus_dev_fatal(dev, err, "creating sysfs entries"); + return; + } + + /* We're potentially connected now */ + update_blkif_status(be->blkif); + } +} + + +/** + * Callback received when the frontend's state changes. + */ +static void frontend_changed(struct xenbus_device *dev, + enum xenbus_state frontend_state) +{ + struct backend_info *be = dev_get_drvdata(&dev->dev); + int err; + + DPRINTK("%s", xenbus_strstate(frontend_state)); + + switch (frontend_state) { + case XenbusStateInitialising: + if (dev->state == XenbusStateClosed) { + printk(KERN_INFO "%s: %s: prepare for reconnect\n", + __func__, dev->nodename); + xenbus_switch_state(dev, XenbusStateInitWait); + } + break; + + case XenbusStateInitialised: + case XenbusStateConnected: + /* Ensure we connect even when two watches fire in + close successsion and we miss the intermediate value + of frontend_state. */ + if (dev->state == XenbusStateConnected) + break; + + /* Enforce precondition before potential leak point. + * blkif_disconnect() is idempotent. + */ + blkif_disconnect(be->blkif); + + err = connect_ring(be); + if (err) + break; + update_blkif_status(be->blkif); + break; + + case XenbusStateClosing: + blkif_disconnect(be->blkif); + xenbus_switch_state(dev, XenbusStateClosing); + break; + + case XenbusStateClosed: + xenbus_switch_state(dev, XenbusStateClosed); + if (xenbus_dev_is_online(dev)) + break; + /* fall through if not online */ + case XenbusStateUnknown: + /* implies blkif_disconnect() via blkback_remove() */ + device_unregister(&dev->dev); + break; + + default: + xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend", + frontend_state); + break; + } +} + + +/* ** Connection ** */ + + +/** + * Write the physical details regarding the block device to the store, and + * switch to Connected state. + */ +static void connect(struct backend_info *be) +{ + struct xenbus_transaction xbt; + int err; + struct xenbus_device *dev = be->dev; + + DPRINTK("%s", dev->otherend); + + /* Supply the information about the device the frontend needs */ +again: + err = xenbus_transaction_start(&xbt); + if (err) { + xenbus_dev_fatal(dev, err, "starting transaction"); + return; + } + + err = blkback_barrier(xbt, be, 1); + if (err) + goto abort; + + err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", + vbd_size(&be->blkif->vbd)); + if (err) { + xenbus_dev_fatal(dev, err, "writing %s/sectors", + dev->nodename); + goto abort; + } + + /* FIXME: use a typename instead */ + err = xenbus_printf(xbt, dev->nodename, "info", "%u", + vbd_info(&be->blkif->vbd)); + if (err) { + xenbus_dev_fatal(dev, err, "writing %s/info", + dev->nodename); + goto abort; + } + err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", + vbd_secsize(&be->blkif->vbd)); + if (err) { + xenbus_dev_fatal(dev, err, "writing %s/sector-size", + dev->nodename); + goto abort; + } + + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + xenbus_dev_fatal(dev, err, "ending transaction"); + + err = xenbus_switch_state(dev, XenbusStateConnected); + if (err) + xenbus_dev_fatal(dev, err, "switching to Connected state", + dev->nodename); + + return; + abort: + xenbus_transaction_end(xbt, 1); +} + + +static int connect_ring(struct backend_info *be) +{ + struct xenbus_device *dev = be->dev; + unsigned long ring_ref; + unsigned int evtchn; + char protocol[64] = ""; + int err; + + DPRINTK("%s", dev->otherend); + + err = xenbus_gather(XBT_NIL, dev->otherend, "ring-ref", "%lu", + &ring_ref, "event-channel", "%u", &evtchn, NULL); + if (err) { + xenbus_dev_fatal(dev, err, + "reading %s/ring-ref and event-channel", + dev->otherend); + return err; + } + + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + err = xenbus_gather(XBT_NIL, dev->otherend, "protocol", + "%63s", protocol, NULL); + if (err) + strcpy(protocol, "unspecified, assuming native"); + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; + else { + xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); + return -1; + } + printk(KERN_INFO + "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + ring_ref, evtchn, be->blkif->blk_protocol, protocol); + + /* Map the shared frame, irq etc. */ + err = blkif_map(be->blkif, ring_ref, evtchn); + if (err) { + xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u", + ring_ref, evtchn); + return err; + } + + return 0; +} + + +/* ** Driver Registration ** */ + + +static const struct xenbus_device_id blkback_ids[] = { + { "vbd" }, + { "" } +}; + + +static struct xenbus_driver blkback = { + .name = "vbd", + .owner = THIS_MODULE, + .ids = blkback_ids, + .probe = blkback_probe, + .remove = blkback_remove, + .otherend_changed = frontend_changed +}; + + +int blkif_xenbus_init(void) +{ + return xenbus_register_backend(&blkback); +} -- cgit v1.2.3 From ee9ff8537eacb4383bf9146df6c21b9301c9baa2 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 20 Apr 2011 10:57:29 -0400 Subject: xen/blkback: Squash vbd.c,interface.c in blkback.c and xenbus.c respectivly. Daniel Stodden suggested to eliminate vbd.c and interface.c, inlining the critical bits where they belong, respectively. Leaving only blkback.c for the data- and xenbus.c for the control path. Suggested-by: Daniel Stodden Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/Makefile | 2 +- drivers/block/xen-blkback/blkback.c | 135 +++++++++++++++++++++++++ drivers/block/xen-blkback/interface.c | 185 ---------------------------------- drivers/block/xen-blkback/vbd.c | 162 ----------------------------- drivers/block/xen-blkback/xenbus.c | 151 +++++++++++++++++++++++++++ 5 files changed, 287 insertions(+), 348 deletions(-) delete mode 100644 drivers/block/xen-blkback/interface.c delete mode 100644 drivers/block/xen-blkback/vbd.c (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/Makefile b/drivers/block/xen-blkback/Makefile index f1ae1ff07a4d..e491c1b76878 100644 --- a/drivers/block/xen-blkback/Makefile +++ b/drivers/block/xen-blkback/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND) := xen-blkback.o -xen-blkback-y := blkback.o xenbus.o interface.o vbd.o +xen-blkback-y := blkback.o xenbus.o diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 59a2bae0f35e..63001fac9af2 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -166,6 +166,141 @@ static void free_req(struct pending_req *req) wake_up(&blkbk->pending_free_wq); } +/* + * Routines for managing virtual block devices (vbds). + */ + +#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ + (_v)->bdev->bd_part->nr_sects : \ + get_capacity((_v)->bdev->bd_disk)) + +unsigned long long vbd_size(struct vbd *vbd) +{ + return vbd_sz(vbd); +} + +unsigned int vbd_info(struct vbd *vbd) +{ + return vbd->type | (vbd->readonly ? VDISK_READONLY : 0); +} + +unsigned long vbd_secsize(struct vbd *vbd) +{ + return bdev_logical_block_size(vbd->bdev); +} + +int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, unsigned major, + unsigned minor, int readonly, int cdrom) +{ + struct vbd *vbd; + struct block_device *bdev; + + vbd = &blkif->vbd; + vbd->handle = handle; + vbd->readonly = readonly; + vbd->type = 0; + + vbd->pdevice = MKDEV(major, minor); + + bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? + FMODE_READ : FMODE_WRITE, NULL); + + if (IS_ERR(bdev)) { + DPRINTK("vbd_creat: device %08x could not be opened.\n", + vbd->pdevice); + return -ENOENT; + } + + vbd->bdev = bdev; + vbd->size = vbd_size(vbd); + + if (vbd->bdev->bd_disk == NULL) { + DPRINTK("vbd_creat: device %08x doesn't exist.\n", + vbd->pdevice); + vbd_free(vbd); + return -ENOENT; + } + + if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) + vbd->type |= VDISK_CDROM; + if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) + vbd->type |= VDISK_REMOVABLE; + + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", + handle, blkif->domid); + return 0; +} + +void vbd_free(struct vbd *vbd) +{ + if (vbd->bdev) + blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); + vbd->bdev = NULL; +} + +int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation) +{ + struct vbd *vbd = &blkif->vbd; + int rc = -EACCES; + + if ((operation != READ) && vbd->readonly) + goto out; + + if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) + goto out; + + req->dev = vbd->pdevice; + req->bdev = vbd->bdev; + rc = 0; + + out: + return rc; +} + +void vbd_resize(struct blkif_st *blkif) +{ + struct vbd *vbd = &blkif->vbd; + struct xenbus_transaction xbt; + int err; + struct xenbus_device *dev = blkback_xenbus(blkif->be); + unsigned long long new_size = vbd_size(vbd); + + printk(KERN_INFO "VBD Resize: Domid: %d, Device: (%d, %d)\n", + blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice)); + printk(KERN_INFO "VBD Resize: new size %llu\n", new_size); + vbd->size = new_size; +again: + err = xenbus_transaction_start(&xbt); + if (err) { + printk(KERN_WARNING "Error starting transaction"); + return; + } + err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", + vbd_size(vbd)); + if (err) { + printk(KERN_WARNING "Error writing new size"); + goto abort; + } + /* + * Write the current state; we will use this to synchronize + * the front-end. If the current state is "connected" the + * front-end will get the new size information online. + */ + err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); + if (err) { + printk(KERN_WARNING "Error writing the state"); + goto abort; + } + + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + printk(KERN_WARNING "Error ending transaction"); +abort: + xenbus_transaction_end(xbt, 1); +} + /* * Notification from the guest OS. */ diff --git a/drivers/block/xen-blkback/interface.c b/drivers/block/xen-blkback/interface.c deleted file mode 100644 index 163aed41e825..000000000000 --- a/drivers/block/xen-blkback/interface.c +++ /dev/null @@ -1,185 +0,0 @@ -/****************************************************************************** - * Block-device interface management. - * - * Copyright (c) 2004, Keir Fraser - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "common.h" -#include -#include -#include - -static struct kmem_cache *blkif_cachep; - -struct blkif_st *blkif_alloc(domid_t domid) -{ - struct blkif_st *blkif; - - blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL); - if (!blkif) - return ERR_PTR(-ENOMEM); - - memset(blkif, 0, sizeof(*blkif)); - blkif->domid = domid; - spin_lock_init(&blkif->blk_ring_lock); - atomic_set(&blkif->refcnt, 1); - init_waitqueue_head(&blkif->wq); - blkif->st_print = jiffies; - init_waitqueue_head(&blkif->waiting_to_free); - - return blkif; -} - -static int map_frontend_page(struct blkif_st *blkif, unsigned long shared_page) -{ - struct gnttab_map_grant_ref op; - - gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, - GNTMAP_host_map, shared_page, blkif->domid); - - if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) - BUG(); - - if (op.status) { - DPRINTK(" Grant table operation failure !\n"); - return op.status; - } - - blkif->shmem_ref = shared_page; - blkif->shmem_handle = op.handle; - - return 0; -} - -static void unmap_frontend_page(struct blkif_st *blkif) -{ - struct gnttab_unmap_grant_ref op; - - gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, - GNTMAP_host_map, blkif->shmem_handle); - - if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) - BUG(); -} - -int blkif_map(struct blkif_st *blkif, unsigned long shared_page, - unsigned int evtchn) -{ - int err; - - /* Already connected through? */ - if (blkif->irq) - return 0; - - blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); - if (!blkif->blk_ring_area) - return -ENOMEM; - - err = map_frontend_page(blkif, shared_page); - if (err) { - free_vm_area(blkif->blk_ring_area); - return err; - } - - switch (blkif->blk_protocol) { - case BLKIF_PROTOCOL_NATIVE: - { - struct blkif_sring *sring; - sring = (struct blkif_sring *)blkif->blk_ring_area->addr; - BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); - break; - } - case BLKIF_PROTOCOL_X86_32: - { - struct blkif_x86_32_sring *sring_x86_32; - sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; - BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); - break; - } - case BLKIF_PROTOCOL_X86_64: - { - struct blkif_x86_64_sring *sring_x86_64; - sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; - BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); - break; - } - default: - BUG(); - } - - err = bind_interdomain_evtchn_to_irqhandler( - blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif); - if (err < 0) { - unmap_frontend_page(blkif); - free_vm_area(blkif->blk_ring_area); - blkif->blk_rings.common.sring = NULL; - return err; - } - blkif->irq = err; - - return 0; -} - -void blkif_disconnect(struct blkif_st *blkif) -{ - if (blkif->xenblkd) { - kthread_stop(blkif->xenblkd); - blkif->xenblkd = NULL; - } - - atomic_dec(&blkif->refcnt); - wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); - atomic_inc(&blkif->refcnt); - - if (blkif->irq) { - unbind_from_irqhandler(blkif->irq, blkif); - blkif->irq = 0; - } - - if (blkif->blk_rings.common.sring) { - unmap_frontend_page(blkif); - free_vm_area(blkif->blk_ring_area); - blkif->blk_rings.common.sring = NULL; - } -} - -void blkif_free(struct blkif_st *blkif) -{ - if (!atomic_dec_and_test(&blkif->refcnt)) - BUG(); - kmem_cache_free(blkif_cachep, blkif); -} - -int __init blkif_interface_init(void) -{ - blkif_cachep = kmem_cache_create("blkif_cache", sizeof(struct blkif_st), - 0, 0, NULL); - if (!blkif_cachep) - return -ENOMEM; - - return 0; -} diff --git a/drivers/block/xen-blkback/vbd.c b/drivers/block/xen-blkback/vbd.c deleted file mode 100644 index d0ff4cf91a34..000000000000 --- a/drivers/block/xen-blkback/vbd.c +++ /dev/null @@ -1,162 +0,0 @@ -/****************************************************************************** - * Routines for managing virtual block devices (VBDs). - * - * Copyright (c) 2003-2005, Keir Fraser & Steve Hand - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "common.h" - -#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ - (_v)->bdev->bd_part->nr_sects : \ - get_capacity((_v)->bdev->bd_disk)) - -unsigned long long vbd_size(struct vbd *vbd) -{ - return vbd_sz(vbd); -} - -unsigned int vbd_info(struct vbd *vbd) -{ - return vbd->type | (vbd->readonly ? VDISK_READONLY : 0); -} - -unsigned long vbd_secsize(struct vbd *vbd) -{ - return bdev_logical_block_size(vbd->bdev); -} - -int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, unsigned major, - unsigned minor, int readonly, int cdrom) -{ - struct vbd *vbd; - struct block_device *bdev; - - vbd = &blkif->vbd; - vbd->handle = handle; - vbd->readonly = readonly; - vbd->type = 0; - - vbd->pdevice = MKDEV(major, minor); - - bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? - FMODE_READ : FMODE_WRITE, NULL); - - if (IS_ERR(bdev)) { - DPRINTK("vbd_creat: device %08x could not be opened.\n", - vbd->pdevice); - return -ENOENT; - } - - vbd->bdev = bdev; - vbd->size = vbd_size(vbd); - - if (vbd->bdev->bd_disk == NULL) { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", - vbd->pdevice); - vbd_free(vbd); - return -ENOENT; - } - - if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) - vbd->type |= VDISK_CDROM; - if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) - vbd->type |= VDISK_REMOVABLE; - - DPRINTK("Successful creation of handle=%04x (dom=%u)\n", - handle, blkif->domid); - return 0; -} - -void vbd_free(struct vbd *vbd) -{ - if (vbd->bdev) - blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); - vbd->bdev = NULL; -} - -int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation) -{ - struct vbd *vbd = &blkif->vbd; - int rc = -EACCES; - - if ((operation != READ) && vbd->readonly) - goto out; - - if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) - goto out; - - req->dev = vbd->pdevice; - req->bdev = vbd->bdev; - rc = 0; - - out: - return rc; -} - -void vbd_resize(struct blkif_st *blkif) -{ - struct vbd *vbd = &blkif->vbd; - struct xenbus_transaction xbt; - int err; - struct xenbus_device *dev = blkback_xenbus(blkif->be); - unsigned long long new_size = vbd_size(vbd); - - printk(KERN_INFO "VBD Resize: Domid: %d, Device: (%d, %d)\n", - blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice)); - printk(KERN_INFO "VBD Resize: new size %llu\n", new_size); - vbd->size = new_size; -again: - err = xenbus_transaction_start(&xbt); - if (err) { - printk(KERN_WARNING "Error starting transaction"); - return; - } - err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", - vbd_size(vbd)); - if (err) { - printk(KERN_WARNING "Error writing new size"); - goto abort; - } - /* - * Write the current state; we will use this to synchronize - * the front-end. If the current state is "connected" the - * front-end will get the new size information online. - */ - err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); - if (err) { - printk(KERN_WARNING "Error writing the state"); - goto abort; - } - - err = xenbus_transaction_end(xbt, 0); - if (err == -EAGAIN) - goto again; - if (err) - printk(KERN_WARNING "Error ending transaction"); -abort: - xenbus_transaction_end(xbt, 1); -} diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index b41ed65db2d3..0c263a248007 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "common.h" #undef DPRINTK @@ -36,6 +38,7 @@ struct backend_info { char *mode; }; +static struct kmem_cache *blkif_cachep; static void connect(struct backend_info *); static int connect_ring(struct backend_info *); static void backend_changed(struct xenbus_watch *, const char **, @@ -106,6 +109,154 @@ static void update_blkif_status(struct blkif_st *blkif) } } +struct blkif_st *blkif_alloc(domid_t domid) +{ + struct blkif_st *blkif; + + blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL); + if (!blkif) + return ERR_PTR(-ENOMEM); + + memset(blkif, 0, sizeof(*blkif)); + blkif->domid = domid; + spin_lock_init(&blkif->blk_ring_lock); + atomic_set(&blkif->refcnt, 1); + init_waitqueue_head(&blkif->wq); + blkif->st_print = jiffies; + init_waitqueue_head(&blkif->waiting_to_free); + + return blkif; +} + +static int map_frontend_page(struct blkif_st *blkif, unsigned long shared_page) +{ + struct gnttab_map_grant_ref op; + + gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, shared_page, blkif->domid); + + if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) + BUG(); + + if (op.status) { + DPRINTK(" Grant table operation failure !\n"); + return op.status; + } + + blkif->shmem_ref = shared_page; + blkif->shmem_handle = op.handle; + + return 0; +} + +static void unmap_frontend_page(struct blkif_st *blkif) +{ + struct gnttab_unmap_grant_ref op; + + gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr, + GNTMAP_host_map, blkif->shmem_handle); + + if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) + BUG(); +} + +int blkif_map(struct blkif_st *blkif, unsigned long shared_page, + unsigned int evtchn) +{ + int err; + + /* Already connected through? */ + if (blkif->irq) + return 0; + + blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE); + if (!blkif->blk_ring_area) + return -ENOMEM; + + err = map_frontend_page(blkif, shared_page); + if (err) { + free_vm_area(blkif->blk_ring_area); + return err; + } + + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + { + struct blkif_sring *sring; + sring = (struct blkif_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.native, sring, PAGE_SIZE); + break; + } + case BLKIF_PROTOCOL_X86_32: + { + struct blkif_x86_32_sring *sring_x86_32; + sring_x86_32 = (struct blkif_x86_32_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + struct blkif_x86_64_sring *sring_x86_64; + sring_x86_64 = (struct blkif_x86_64_sring *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); + break; + } + default: + BUG(); + } + + err = bind_interdomain_evtchn_to_irqhandler( + blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif); + if (err < 0) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + blkif->blk_rings.common.sring = NULL; + return err; + } + blkif->irq = err; + + return 0; +} + +void blkif_disconnect(struct blkif_st *blkif) +{ + if (blkif->xenblkd) { + kthread_stop(blkif->xenblkd); + blkif->xenblkd = NULL; + } + + atomic_dec(&blkif->refcnt); + wait_event(blkif->waiting_to_free, atomic_read(&blkif->refcnt) == 0); + atomic_inc(&blkif->refcnt); + + if (blkif->irq) { + unbind_from_irqhandler(blkif->irq, blkif); + blkif->irq = 0; + } + + if (blkif->blk_rings.common.sring) { + unmap_frontend_page(blkif); + free_vm_area(blkif->blk_ring_area); + blkif->blk_rings.common.sring = NULL; + } +} + +void blkif_free(struct blkif_st *blkif) +{ + if (!atomic_dec_and_test(&blkif->refcnt)) + BUG(); + kmem_cache_free(blkif_cachep, blkif); +} + +int __init blkif_interface_init(void) +{ + blkif_cachep = kmem_cache_create("blkif_cache", sizeof(struct blkif_st), + 0, 0, NULL); + if (!blkif_cachep) + return -ENOMEM; + + return 0; +} /* * sysfs interface for VBD I/O requests -- cgit v1.2.3 From 6cd0388cd600a51a8824dc5b34f1107b367b0cac Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 20 Apr 2011 11:01:47 -0400 Subject: xen-blkback: Remove from the copyright notice the address. There is no need for it, as the address is updated constatly in the root of the Linux kernel. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/xenbus.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 0c263a248007..c6c5286aa813 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -12,9 +12,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -- cgit v1.2.3 From 42c7841d171a2fe32005738dfebd724a90921496 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 20 Apr 2011 11:21:43 -0400 Subject: xen-blkback: Inline some of the functions that were moved from vbd/interface.c Shuffling code around. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 78 +++---------------------------------- drivers/block/xen-blkback/common.h | 22 ++--------- drivers/block/xen-blkback/xenbus.c | 58 +++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 93 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 63001fac9af2..806c2c947c63 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -170,75 +170,9 @@ static void free_req(struct pending_req *req) * Routines for managing virtual block devices (vbds). */ -#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ - (_v)->bdev->bd_part->nr_sects : \ - get_capacity((_v)->bdev->bd_disk)) -unsigned long long vbd_size(struct vbd *vbd) -{ - return vbd_sz(vbd); -} - -unsigned int vbd_info(struct vbd *vbd) -{ - return vbd->type | (vbd->readonly ? VDISK_READONLY : 0); -} - -unsigned long vbd_secsize(struct vbd *vbd) -{ - return bdev_logical_block_size(vbd->bdev); -} - -int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, unsigned major, - unsigned minor, int readonly, int cdrom) -{ - struct vbd *vbd; - struct block_device *bdev; - - vbd = &blkif->vbd; - vbd->handle = handle; - vbd->readonly = readonly; - vbd->type = 0; - - vbd->pdevice = MKDEV(major, minor); - - bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? - FMODE_READ : FMODE_WRITE, NULL); - - if (IS_ERR(bdev)) { - DPRINTK("vbd_creat: device %08x could not be opened.\n", - vbd->pdevice); - return -ENOENT; - } - - vbd->bdev = bdev; - vbd->size = vbd_size(vbd); - - if (vbd->bdev->bd_disk == NULL) { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", - vbd->pdevice); - vbd_free(vbd); - return -ENOENT; - } - - if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) - vbd->type |= VDISK_CDROM; - if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) - vbd->type |= VDISK_REMOVABLE; - - DPRINTK("Successful creation of handle=%04x (dom=%u)\n", - handle, blkif->domid); - return 0; -} - -void vbd_free(struct vbd *vbd) -{ - if (vbd->bdev) - blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); - vbd->bdev = NULL; -} - -int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation) +static int vbd_translate(struct phys_req *req, struct blkif_st *blkif, + int operation) { struct vbd *vbd = &blkif->vbd; int rc = -EACCES; @@ -257,13 +191,13 @@ int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation) return rc; } -void vbd_resize(struct blkif_st *blkif) +static void vbd_resize(struct blkif_st *blkif) { struct vbd *vbd = &blkif->vbd; struct xenbus_transaction xbt; int err; struct xenbus_device *dev = blkback_xenbus(blkif->be); - unsigned long long new_size = vbd_size(vbd); + unsigned long long new_size = vbd_sz(vbd); printk(KERN_INFO "VBD Resize: Domid: %d, Device: (%d, %d)\n", blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice)); @@ -276,7 +210,7 @@ again: return; } err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", - vbd_size(vbd)); + (unsigned long long)vbd_sz(vbd)); if (err) { printk(KERN_WARNING "Error writing new size"); goto abort; @@ -344,7 +278,7 @@ int blkif_schedule(void *arg) while (!kthread_should_stop()) { if (try_to_freeze()) continue; - if (unlikely(vbd->size != vbd_size(vbd))) + if (unlikely(vbd->size != vbd_sz(vbd))) vbd_resize(blkif); wait_event_interruptible( diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 6257c1106591..4b5acb3e8b24 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -95,12 +95,10 @@ struct blkif_st { grant_ref_t shmem_ref; }; -struct blkif_st *blkif_alloc(domid_t domid); -void blkif_disconnect(struct blkif_st *blkif); -void blkif_free(struct blkif_st *blkif); -int blkif_map(struct blkif_st *blkif, unsigned long shared_page, - unsigned int evtchn); -void vbd_resize(struct blkif_st *blkif); + +#define vbd_sz(_v) ((_v)->bdev->bd_part ? \ + (_v)->bdev->bd_part->nr_sects : \ + get_capacity((_v)->bdev->bd_disk)) #define blkif_get(_b) (atomic_inc(&(_b)->refcnt)) #define blkif_put(_b) \ @@ -109,24 +107,12 @@ void vbd_resize(struct blkif_st *blkif); wake_up(&(_b)->waiting_to_free);\ } while (0) -/* Create a vbd. */ -int vbd_create(struct blkif_st *blkif, blkif_vdev_t vdevice, unsigned major, - unsigned minor, int readonly, int cdrom); -void vbd_free(struct vbd *vbd); - -unsigned long long vbd_size(struct vbd *vbd); -unsigned int vbd_info(struct vbd *vbd); -unsigned long vbd_secsize(struct vbd *vbd); - struct phys_req { unsigned short dev; unsigned short nr_sects; struct block_device *bdev; blkif_sector_t sector_number; }; - -int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation); - int blkif_interface_init(void); int blkif_xenbus_init(void); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index c6c5286aa813..75bf49bd365c 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -327,6 +327,56 @@ void xenvbd_sysfs_delif(struct xenbus_device *dev) device_remove_file(&dev->dev, &dev_attr_physical_device); } + +static void vbd_free(struct vbd *vbd) +{ + if (vbd->bdev) + blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); + vbd->bdev = NULL; +} + +static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, + unsigned major, unsigned minor, int readonly, + int cdrom) +{ + struct vbd *vbd; + struct block_device *bdev; + + vbd = &blkif->vbd; + vbd->handle = handle; + vbd->readonly = readonly; + vbd->type = 0; + + vbd->pdevice = MKDEV(major, minor); + + bdev = blkdev_get_by_dev(vbd->pdevice, vbd->readonly ? + FMODE_READ : FMODE_WRITE, NULL); + + if (IS_ERR(bdev)) { + DPRINTK("vbd_creat: device %08x could not be opened.\n", + vbd->pdevice); + return -ENOENT; + } + + vbd->bdev = bdev; + vbd->size = vbd_sz(vbd); + + if (vbd->bdev->bd_disk == NULL) { + DPRINTK("vbd_creat: device %08x doesn't exist.\n", + vbd->pdevice); + vbd_free(vbd); + return -ENOENT; + } + + if (vbd->bdev->bd_disk->flags & GENHD_FL_CD || cdrom) + vbd->type |= VDISK_CDROM; + if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) + vbd->type |= VDISK_REMOVABLE; + + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", + handle, blkif->domid); + return 0; +} static int blkback_remove(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); @@ -595,7 +645,7 @@ again: goto abort; err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", - vbd_size(&be->blkif->vbd)); + (unsigned long long)vbd_sz(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sectors", dev->nodename); @@ -604,14 +654,16 @@ again: /* FIXME: use a typename instead */ err = xenbus_printf(xbt, dev->nodename, "info", "%u", - vbd_info(&be->blkif->vbd)); + be->blkif->vbd.type | + (be->blkif->vbd.readonly ? VDISK_READONLY : 0)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/info", dev->nodename); goto abort; } err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", - vbd_secsize(&be->blkif->vbd)); + (unsigned long) + bdev_logical_block_size(be->blkif->vbd.bdev)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sector-size", dev->nodename); -- cgit v1.2.3 From 8b6bf747d70e5bac1a34c8fd773230e1cfdd7546 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 20 Apr 2011 11:50:43 -0400 Subject: xen/blkback: Prefix exposed functions with xen_ And also shorten the name if it has blkback to blkbk. This results in the symbol table (if compiled in the kernel) to be much shorter, prettier, and also easier to search for. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 36 ++++++++--------- drivers/block/xen-blkback/common.h | 18 ++++----- drivers/block/xen-blkback/xenbus.c | 80 +++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 66 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 806c2c947c63..c4bc85e69d33 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -53,13 +53,13 @@ * pulled from a communication ring are quite likely to end up being part of * the same scatter/gather request at the disc. * - * ** TRY INCREASING 'blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW ** + * ** TRY INCREASING 'xen_blkif_reqs' IF WRITE SPEEDS SEEM TOO LOW ** * * This will increase the chances of being able to write whole tracks. * 64 should be enough to keep us competitive with Linux. */ -static int blkif_reqs = 64; -module_param_named(reqs, blkif_reqs, int, 0); +static int xen_blkif_reqs = 64; +module_param_named(reqs, xen_blkif_reqs, int, 0); MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate"); /* Run-time switchable: /sys/module/blkback/parameters/ */ @@ -196,7 +196,7 @@ static void vbd_resize(struct blkif_st *blkif) struct vbd *vbd = &blkif->vbd; struct xenbus_transaction xbt; int err; - struct xenbus_device *dev = blkback_xenbus(blkif->be); + struct xenbus_device *dev = xen_blkbk_xenbus(blkif->be); unsigned long long new_size = vbd_sz(vbd); printk(KERN_INFO "VBD Resize: Domid: %d, Device: (%d, %d)\n", @@ -244,7 +244,7 @@ static void blkif_notify_work(struct blkif_st *blkif) wake_up(&blkif->wq); } -irqreturn_t blkif_be_int(int irq, void *dev_id) +irqreturn_t xen_blkif_be_int(int irq, void *dev_id) { blkif_notify_work(dev_id); return IRQ_HANDLED; @@ -265,12 +265,12 @@ static void print_stats(struct blkif_st *blkif) blkif->st_oo_req = 0; } -int blkif_schedule(void *arg) +int xen_blkif_schedule(void *arg) { struct blkif_st *blkif = arg; struct vbd *vbd = &blkif->vbd; - blkif_get(blkif); + xen_blkif_get(blkif); if (debug_lvl) printk(KERN_DEBUG "%s: started\n", current->comm); @@ -305,7 +305,7 @@ int blkif_schedule(void *arg) printk(KERN_DEBUG "%s: exiting\n", current->comm); blkif->xenblkd = NULL; - blkif_put(blkif); + xen_blkif_put(blkif); return 0; } @@ -417,7 +417,7 @@ static void __end_block_io_op(struct pending_req *pending_req, int error) if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) && (error == -EOPNOTSUPP)) { DPRINTK("blkback: write barrier op failed, not supported\n"); - blkback_barrier(XBT_NIL, pending_req->blkif->be, 0); + xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0); pending_req->status = BLKIF_RSP_EOPNOTSUPP; } else if (error) { DPRINTK("Buffer not up-to-date at end of operation, " @@ -433,7 +433,7 @@ static void __end_block_io_op(struct pending_req *pending_req, int error) xen_blkbk_unmap(pending_req); make_response(pending_req->blkif, pending_req->id, pending_req->operation, pending_req->status); - blkif_put(pending_req->blkif); + xen_blkif_put(pending_req->blkif); free_req(pending_req); } } @@ -619,7 +619,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, goto fail_flush; /* This corresponding blkif_put is done in __end_block_io_op */ - blkif_get(blkif); + xen_blkif_get(blkif); for (i = 0; i < nseg; i++) { while ((bio == NULL) || @@ -751,7 +751,7 @@ static void make_response(struct blkif_st *blkif, u64 id, notify_remote_via_irq(blkif->irq); } -static int __init blkif_init(void) +static int __init xen_blkif_init(void) { int i, mmap_pages; int rc = 0; @@ -765,10 +765,10 @@ static int __init blkif_init(void) return -ENOMEM; } - mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST; + mmap_pages = xen_blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST; blkbk->pending_reqs = kmalloc(sizeof(blkbk->pending_reqs[0]) * - blkif_reqs, GFP_KERNEL); + xen_blkif_reqs, GFP_KERNEL); blkbk->pending_grant_handles = kzalloc(sizeof(blkbk->pending_grant_handles[0]) * mmap_pages, GFP_KERNEL); blkbk->pending_pages = kzalloc(sizeof(blkbk->pending_pages[0]) * @@ -788,7 +788,7 @@ static int __init blkif_init(void) goto out_of_memory; } } - rc = blkif_interface_init(); + rc = xen_blkif_interface_init(); if (rc) goto failed_init; @@ -798,11 +798,11 @@ static int __init blkif_init(void) spin_lock_init(&blkbk->pending_free_lock); init_waitqueue_head(&blkbk->pending_free_wq); - for (i = 0; i < blkif_reqs; i++) + for (i = 0; i < xen_blkif_reqs; i++) list_add_tail(&blkbk->pending_reqs[i].free_list, &blkbk->pending_free); - rc = blkif_xenbus_init(); + rc = xen_blkif_xenbus_init(); if (rc) goto failed_init; @@ -823,6 +823,6 @@ static int __init blkif_init(void) return rc; } -module_init(blkif_init); +module_init(xen_blkif_init); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 4b5acb3e8b24..16af388268e7 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -100,8 +100,8 @@ struct blkif_st { (_v)->bdev->bd_part->nr_sects : \ get_capacity((_v)->bdev->bd_disk)) -#define blkif_get(_b) (atomic_inc(&(_b)->refcnt)) -#define blkif_put(_b) \ +#define xen_blkif_get(_b) (atomic_inc(&(_b)->refcnt)) +#define xen_blkif_put(_b) \ do { \ if (atomic_dec_and_test(&(_b)->refcnt)) \ wake_up(&(_b)->waiting_to_free);\ @@ -113,16 +113,16 @@ struct phys_req { struct block_device *bdev; blkif_sector_t sector_number; }; -int blkif_interface_init(void); +int xen_blkif_interface_init(void); -int blkif_xenbus_init(void); +int xen_blkif_xenbus_init(void); -irqreturn_t blkif_be_int(int irq, void *dev_id); -int blkif_schedule(void *arg); +irqreturn_t xen_blkif_be_int(int irq, void *dev_id); +int xen_blkif_schedule(void *arg); -int blkback_barrier(struct xenbus_transaction xbt, - struct backend_info *be, int state); +int xen_blkbk_barrier(struct xenbus_transaction xbt, + struct backend_info *be, int state); -struct xenbus_device *blkback_xenbus(struct backend_info *be); +struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); #endif /* __BLKIF__BACKEND__COMMON_H__ */ diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 75bf49bd365c..64b0a1c760fb 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -35,13 +35,13 @@ struct backend_info { char *mode; }; -static struct kmem_cache *blkif_cachep; +static struct kmem_cache *xen_blkif_cachep; static void connect(struct backend_info *); static int connect_ring(struct backend_info *); static void backend_changed(struct xenbus_watch *, const char **, unsigned int); -struct xenbus_device *blkback_xenbus(struct backend_info *be) +struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be) { return be->dev; } @@ -67,7 +67,7 @@ static int blkback_name(struct blkif_st *blkif, char *buf) return 0; } -static void update_blkif_status(struct blkif_st *blkif) +static void xen_update_blkif_status(struct blkif_st *blkif) { int err; char name[TASK_COMM_LEN]; @@ -98,7 +98,7 @@ static void update_blkif_status(struct blkif_st *blkif) } invalidate_inode_pages2(blkif->vbd.bdev->bd_inode->i_mapping); - blkif->xenblkd = kthread_run(blkif_schedule, blkif, name); + blkif->xenblkd = kthread_run(xen_blkif_schedule, blkif, name); if (IS_ERR(blkif->xenblkd)) { err = PTR_ERR(blkif->xenblkd); blkif->xenblkd = NULL; @@ -106,11 +106,11 @@ static void update_blkif_status(struct blkif_st *blkif) } } -struct blkif_st *blkif_alloc(domid_t domid) +static struct blkif_st *xen_blkif_alloc(domid_t domid) { struct blkif_st *blkif; - blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL); + blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); if (!blkif) return ERR_PTR(-ENOMEM); @@ -157,8 +157,8 @@ static void unmap_frontend_page(struct blkif_st *blkif) BUG(); } -int blkif_map(struct blkif_st *blkif, unsigned long shared_page, - unsigned int evtchn) +static int xen_blkif_map(struct blkif_st *blkif, unsigned long shared_page, + unsigned int evtchn) { int err; @@ -202,8 +202,9 @@ int blkif_map(struct blkif_st *blkif, unsigned long shared_page, BUG(); } - err = bind_interdomain_evtchn_to_irqhandler( - blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif); + err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn, + xen_blkif_be_int, 0, + "blkif-backend", blkif); if (err < 0) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); @@ -215,7 +216,7 @@ int blkif_map(struct blkif_st *blkif, unsigned long shared_page, return 0; } -void blkif_disconnect(struct blkif_st *blkif) +static void xen_blkif_disconnect(struct blkif_st *blkif) { if (blkif->xenblkd) { kthread_stop(blkif->xenblkd); @@ -238,18 +239,19 @@ void blkif_disconnect(struct blkif_st *blkif) } } -void blkif_free(struct blkif_st *blkif) +void xen_blkif_free(struct blkif_st *blkif) { if (!atomic_dec_and_test(&blkif->refcnt)) BUG(); - kmem_cache_free(blkif_cachep, blkif); + kmem_cache_free(xen_blkif_cachep, blkif); } -int __init blkif_interface_init(void) +int __init xen_blkif_interface_init(void) { - blkif_cachep = kmem_cache_create("blkif_cache", sizeof(struct blkif_st), - 0, 0, NULL); - if (!blkif_cachep) + xen_blkif_cachep = kmem_cache_create("blkif_cache", + sizeof(struct blkif_st), + 0, 0, NULL); + if (!xen_blkif_cachep) return -ENOMEM; return 0; @@ -377,7 +379,7 @@ static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, handle, blkif->domid); return 0; } -static int blkback_remove(struct xenbus_device *dev) +static int xen_blkbk_remove(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); @@ -393,9 +395,9 @@ static int blkback_remove(struct xenbus_device *dev) } if (be->blkif) { - blkif_disconnect(be->blkif); + xen_blkif_disconnect(be->blkif); vbd_free(&be->blkif->vbd); - blkif_free(be->blkif); + xen_blkif_free(be->blkif); be->blkif = NULL; } @@ -404,8 +406,8 @@ static int blkback_remove(struct xenbus_device *dev) return 0; } -int blkback_barrier(struct xenbus_transaction xbt, - struct backend_info *be, int state) +int xen_blkbk_barrier(struct xenbus_transaction xbt, + struct backend_info *be, int state) { struct xenbus_device *dev = be->dev; int err; @@ -423,8 +425,8 @@ int blkback_barrier(struct xenbus_transaction xbt, * structures, and watch the store waiting for the hotplug scripts to tell us * the device's physical major and minor numbers. Switch to InitWait. */ -static int blkback_probe(struct xenbus_device *dev, - const struct xenbus_device_id *id) +static int xen_blkbk_probe(struct xenbus_device *dev, + const struct xenbus_device_id *id) { int err; struct backend_info *be = kzalloc(sizeof(struct backend_info), @@ -437,7 +439,7 @@ static int blkback_probe(struct xenbus_device *dev, be->dev = dev; dev_set_drvdata(&dev->dev, be); - be->blkif = blkif_alloc(dev->otherend_id); + be->blkif = xen_blkif_alloc(dev->otherend_id); if (IS_ERR(be->blkif)) { err = PTR_ERR(be->blkif); be->blkif = NULL; @@ -461,7 +463,7 @@ static int blkback_probe(struct xenbus_device *dev, fail: DPRINTK("failed"); - blkback_remove(dev); + xen_blkbk_remove(dev); return err; } @@ -550,7 +552,7 @@ static void backend_changed(struct xenbus_watch *watch, } /* We're potentially connected now */ - update_blkif_status(be->blkif); + xen_update_blkif_status(be->blkif); } } @@ -586,16 +588,16 @@ static void frontend_changed(struct xenbus_device *dev, /* Enforce precondition before potential leak point. * blkif_disconnect() is idempotent. */ - blkif_disconnect(be->blkif); + xen_blkif_disconnect(be->blkif); err = connect_ring(be); if (err) break; - update_blkif_status(be->blkif); + xen_update_blkif_status(be->blkif); break; case XenbusStateClosing: - blkif_disconnect(be->blkif); + xen_blkif_disconnect(be->blkif); xenbus_switch_state(dev, XenbusStateClosing); break; @@ -640,7 +642,7 @@ again: return; } - err = blkback_barrier(xbt, be, 1); + err = xen_blkbk_barrier(xbt, be, 1); if (err) goto abort; @@ -726,7 +728,7 @@ static int connect_ring(struct backend_info *be) ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ - err = blkif_map(be->blkif, ring_ref, evtchn); + err = xen_blkif_map(be->blkif, ring_ref, evtchn); if (err) { xenbus_dev_fatal(dev, err, "mapping ring-ref %lu port %u", ring_ref, evtchn); @@ -740,23 +742,23 @@ static int connect_ring(struct backend_info *be) /* ** Driver Registration ** */ -static const struct xenbus_device_id blkback_ids[] = { +static const struct xenbus_device_id xen_blkbk_ids[] = { { "vbd" }, { "" } }; -static struct xenbus_driver blkback = { +static struct xenbus_driver xen_blkbk = { .name = "vbd", .owner = THIS_MODULE, - .ids = blkback_ids, - .probe = blkback_probe, - .remove = blkback_remove, + .ids = xen_blkbk_ids, + .probe = xen_blkbk_probe, + .remove = xen_blkbk_remove, .otherend_changed = frontend_changed }; -int blkif_xenbus_init(void) +int xen_blkif_xenbus_init(void) { - return xenbus_register_backend(&blkback); + return xenbus_register_backend(&xen_blkbk); } -- cgit v1.2.3 From 97961ef46b9b5a6a7c918a38b898a7b3e49869f4 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 26 Apr 2011 12:57:59 -0400 Subject: xen/blkback: Move the plugging/unplugging to a higher level. We used to the plug/unplug on the submit_bio. But that means if within a stream of WRITE, WRITE, WRITE,...,WRITE we have one READ, it could stall the pipeline (as the 'submio_bio' could trigger the unplug_fnc to be called and stall/sync when doing the READ). Instead we want to move the unplugging when the whole (or as a much as possible) ring buffer has been processed. This also eliminates us doing plug/unplug for each request. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index c4bc85e69d33..ed85ba94b2e0 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -276,6 +276,8 @@ int xen_blkif_schedule(void *arg) printk(KERN_DEBUG "%s: started\n", current->comm); while (!kthread_should_stop()) { + struct blk_plug plug; + if (try_to_freeze()) continue; if (unlikely(vbd->size != vbd_sz(vbd))) @@ -292,9 +294,13 @@ int xen_blkif_schedule(void *arg) blkif->waiting_reqs = 0; smp_mb(); /* clear flag *before* checking for work */ + blk_start_plug(&plug); + if (do_block_io_op(blkif)) blkif->waiting_reqs = 1; + blk_finish_plug(&plug); + if (log_stats && time_after(jiffies, blkif->st_print)) print_stats(blkif); } @@ -547,7 +553,6 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int i, nbio = 0; int operation; - struct blk_plug plug; switch (req->operation) { case BLKIF_OP_READ: @@ -660,15 +665,9 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, */ atomic_set(&pending_req->pendcnt, nbio); - /* Get a reference count for the disk queue and start sending I/O */ - blk_start_plug(&plug); - for (i = 0; i < nbio; i++) submit_bio(operation, biolist[i]); - blk_finish_plug(&plug); - /* Let the I/Os go.. */ - if (operation == READ) blkif->st_rd_sect += preq.nr_sects; else if (operation == WRITE || operation == WRITE_BARRIER) -- cgit v1.2.3 From 013c3ca184851078b9c04744efd4d47e52c6ecf8 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Tue, 26 Apr 2011 16:24:18 -0400 Subject: xen/blkback: Stick REQ_SYNC on WRITEs to deal with CFQ I/O scheduler. If one runs a simple fio request with random read/write with a 20%/80% ratio, the numbers are incredibly bad when using the CFQ scheduler. IOmeter | | | | 64K, randrw | NOOP | CFQ | deadline | randrwmix=80 | | | | --------------+-------+------+----------+ blkback |103/27 |32/10 | 102/27 | --------------+-------+------+----------+ QEMU qdisk |103/27 |102/27| 102/27 | The problem as explained by Vivek Goyal was: ".. that difference is that sync vs async requests. In the case of a kernel thread submitting IO, [..] all the WRITES might be being considered as async and will go in a different queue. If you mix those with some READS, they are always sync and will go in differnet queue. In presence of sync queue, CFQ will idle and choke up WRITES in an attempt to improve latencies of READs. In case of AIO [note: this is what QEMU qdisk is doing] , [..] it is direct IO and both READS and WRITES will be considered SYNC and will go in a single queue and no choking of WRITES will take place." The solution is quite simple, tack on REQ_SYNC (which is what the WRITE_ODIRECT macro points to) and the numbers go back up. Suggested-by: Vivek Goyal --- drivers/block/xen-blkback/blkback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index ed85ba94b2e0..8583b130499a 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -559,7 +559,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, operation = READ; break; case BLKIF_OP_WRITE: - operation = WRITE; + operation = WRITE_ODIRECT; break; case BLKIF_OP_WRITE_BARRIER: operation = WRITE_BARRIER; -- cgit v1.2.3 From a19be5f0f073525306f6a4b000d90dc84065ed93 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 27 Apr 2011 12:40:11 -0400 Subject: Revert "xen/blkback: Move the plugging/unplugging to a higher level." This reverts commit 97961ef46b9b5a6a7c918a38b898a7b3e49869f4 b/c we lose about 15% performance if we do the unplugging and the end of the reading the ring buffer. --- drivers/block/xen-blkback/blkback.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 8583b130499a..eb068d0b47ea 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -276,8 +276,6 @@ int xen_blkif_schedule(void *arg) printk(KERN_DEBUG "%s: started\n", current->comm); while (!kthread_should_stop()) { - struct blk_plug plug; - if (try_to_freeze()) continue; if (unlikely(vbd->size != vbd_sz(vbd))) @@ -294,13 +292,9 @@ int xen_blkif_schedule(void *arg) blkif->waiting_reqs = 0; smp_mb(); /* clear flag *before* checking for work */ - blk_start_plug(&plug); - if (do_block_io_op(blkif)) blkif->waiting_reqs = 1; - blk_finish_plug(&plug); - if (log_stats && time_after(jiffies, blkif->st_print)) print_stats(blkif); } @@ -553,6 +547,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, struct bio *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int i, nbio = 0; int operation; + struct blk_plug plug; switch (req->operation) { case BLKIF_OP_READ: @@ -665,9 +660,15 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, */ atomic_set(&pending_req->pendcnt, nbio); + /* Get a reference count for the disk queue and start sending I/O */ + blk_start_plug(&plug); + for (i = 0; i < nbio; i++) submit_bio(operation, biolist[i]); + blk_finish_plug(&plug); + /* Let the I/Os go.. */ + if (operation == READ) blkif->st_rd_sect += preq.nr_sects; else if (operation == WRITE || operation == WRITE_BARRIER) -- cgit v1.2.3 From 24f567f952aa308c3352f3340b9d296fc72bd066 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 4 May 2011 17:07:27 -0400 Subject: xen/blkback: Add support for BLKIF_OP_FLUSH_DISKCACHE and drop BLKIF_OP_WRITE_BARRIER. We drop the support for 'feature-barrier' and add in the support for the 'feature-flush-cache' if the real backend storage supports flushing. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 33 ++++++++++++++++++--------------- drivers/block/xen-blkback/common.h | 7 ++++--- drivers/block/xen-blkback/xenbus.c | 19 ++++++++++++------- 3 files changed, 34 insertions(+), 25 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index eb068d0b47ea..72ede0bf2697 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -46,8 +46,6 @@ #include #include "common.h" -#define WRITE_BARRIER (REQ_WRITE | REQ_FLUSH | REQ_FUA) - /* * These are rather arbitrary. They are fairly large because adjacent requests * pulled from a communication ring are quite likely to end up being part of @@ -256,9 +254,9 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id) static void print_stats(struct blkif_st *blkif) { - printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d\n", + printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | f %4d\n", current->comm, blkif->st_oo_req, - blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req); + blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req); blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); blkif->st_rd_req = 0; blkif->st_wr_req = 0; @@ -414,10 +412,10 @@ static int xen_blkbk_map(struct blkif_request *req, struct pending_req *pending_ static void __end_block_io_op(struct pending_req *pending_req, int error) { /* An error fails the entire request. */ - if ((pending_req->operation == BLKIF_OP_WRITE_BARRIER) && + if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) && (error == -EOPNOTSUPP)) { - DPRINTK("blkback: write barrier op failed, not supported\n"); - xen_blkbk_barrier(XBT_NIL, pending_req->blkif->be, 0); + DPRINTK("blkback: flush diskcache op failed, not supported\n"); + xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0); pending_req->status = BLKIF_RSP_EOPNOTSUPP; } else if (error) { DPRINTK("Buffer not up-to-date at end of operation, " @@ -506,13 +504,14 @@ static int do_block_io_op(struct blkif_st *blkif) blkif->st_rd_req++; dispatch_rw_block_io(blkif, &req, pending_req); break; - case BLKIF_OP_WRITE_BARRIER: - blkif->st_br_req++; + case BLKIF_OP_FLUSH_DISKCACHE: + blkif->st_f_req++; /* fall through */ case BLKIF_OP_WRITE: blkif->st_wr_req++; dispatch_rw_block_io(blkif, &req, pending_req); break; + case BLKIF_OP_WRITE_BARRIER: default: /* A good sign something is wrong: sleep for a while to * avoid excessive CPU consumption by a bad guest. */ @@ -556,9 +555,14 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, case BLKIF_OP_WRITE: operation = WRITE_ODIRECT; break; - case BLKIF_OP_WRITE_BARRIER: - operation = WRITE_BARRIER; + case BLKIF_OP_FLUSH_DISKCACHE: + operation = WRITE_FLUSH; + /* The frontend likes to set this to -1, which vbd_translate + * is alergic too. */ + req->u.rw.sector_number = 0; break; + case BLKIF_OP_WRITE_BARRIER: + /* Should never get here. */ default: operation = 0; /* make gcc happy */ BUG(); @@ -566,7 +570,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, /* Check that the number of segments is sane. */ nseg = req->nr_segments; - if (unlikely(nseg == 0 && operation != WRITE_BARRIER) || + if (unlikely(nseg == 0 && operation != WRITE_FLUSH) || unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { DPRINTK("Bad number of segments in request (%d)\n", nseg); /* Haven't submitted any bio's yet. */ @@ -643,7 +647,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, /* This will be hit if the operation was a barrier. */ if (!bio) { - BUG_ON(operation != WRITE_BARRIER); + BUG_ON(operation != WRITE_FLUSH); bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0); if (unlikely(bio == NULL)) goto fail_put_bio; @@ -651,7 +655,6 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, bio->bi_bdev = preq.bdev; bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; - bio->bi_sector = -1; } @@ -671,7 +674,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, if (operation == READ) blkif->st_rd_sect += preq.nr_sects; - else if (operation == WRITE || operation == WRITE_BARRIER) + else if (operation == WRITE || operation == WRITE_FLUSH) blkif->st_wr_sect += preq.nr_sects; return; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 16af388268e7..af93837e1295 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -53,6 +53,7 @@ struct vbd { u32 pdevice; /* phys device that this vbd maps to */ struct block_device *bdev; sector_t size; /* Cached size parameter */ + bool flush_support; }; struct backend_info; @@ -85,7 +86,7 @@ struct blkif_st { int st_rd_req; int st_wr_req; int st_oo_req; - int st_br_req; + int st_f_req; int st_rd_sect; int st_wr_sect; @@ -120,8 +121,8 @@ int xen_blkif_xenbus_init(void); irqreturn_t xen_blkif_be_int(int irq, void *dev_id); int xen_blkif_schedule(void *arg); -int xen_blkbk_barrier(struct xenbus_transaction xbt, - struct backend_info *be, int state); +int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, + struct backend_info *be, int state); struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 64b0a1c760fb..9adcf806f83f 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -276,7 +276,7 @@ int __init xen_blkif_interface_init(void) VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); -VBD_SHOW(br_req, "%d\n", be->blkif->st_br_req); +VBD_SHOW(f_req, "%d\n", be->blkif->st_f_req); VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect); VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect); @@ -284,7 +284,7 @@ static struct attribute *vbdstat_attrs[] = { &dev_attr_oo_req.attr, &dev_attr_rd_req.attr, &dev_attr_wr_req.attr, - &dev_attr_br_req.attr, + &dev_attr_f_req.attr, &dev_attr_rd_sect.attr, &dev_attr_wr_sect.attr, NULL @@ -343,6 +343,7 @@ static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, { struct vbd *vbd; struct block_device *bdev; + struct request_queue *q; vbd = &blkif->vbd; vbd->handle = handle; @@ -375,6 +376,10 @@ static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE) vbd->type |= VDISK_REMOVABLE; + q = bdev_get_queue(bdev); + if (q && q->flush_flags) + vbd->flush_support = true; + DPRINTK("Successful creation of handle=%04x (dom=%u)\n", handle, blkif->domid); return 0; @@ -406,16 +411,16 @@ static int xen_blkbk_remove(struct xenbus_device *dev) return 0; } -int xen_blkbk_barrier(struct xenbus_transaction xbt, - struct backend_info *be, int state) +int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, + struct backend_info *be, int state) { struct xenbus_device *dev = be->dev; int err; - err = xenbus_printf(xbt, dev->nodename, "feature-barrier", + err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache", "%d", state); if (err) - xenbus_dev_fatal(dev, err, "writing feature-barrier"); + xenbus_dev_fatal(dev, err, "writing feature-flush-cache"); return err; } @@ -642,7 +647,7 @@ again: return; } - err = xen_blkbk_barrier(xbt, be, 1); + err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); if (err) goto abort; -- cgit v1.2.3 From fc53bf757ede292312eee10d64f4e691c8c8cebf Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 5 May 2011 13:37:23 -0400 Subject: xen/blkback: Squash the checking for operation into dispatch_rw_block_io We do a check for the operations right before calling dispatch_rw_block_io. And then we do the same check in dispatch_rw_block_io. This patch squashes those checks into the 'dispatch_rw_block_io' function. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 45 +++++++++++-------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 72ede0bf2697..5f4284729a3a 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -123,9 +123,9 @@ static inline unsigned long vaddr(struct pending_req *req, int seg) static int do_block_io_op(struct blkif_st *blkif); -static void dispatch_rw_block_io(struct blkif_st *blkif, - struct blkif_request *req, - struct pending_req *pending_req); +static int dispatch_rw_block_io(struct blkif_st *blkif, + struct blkif_request *req, + struct pending_req *pending_req); static void make_response(struct blkif_st *blkif, u64 id, unsigned short op, int st); @@ -499,30 +499,8 @@ static int do_block_io_op(struct blkif_st *blkif) /* Apply all sanity checks to /private copy/ of request. */ barrier(); - switch (req.operation) { - case BLKIF_OP_READ: - blkif->st_rd_req++; - dispatch_rw_block_io(blkif, &req, pending_req); - break; - case BLKIF_OP_FLUSH_DISKCACHE: - blkif->st_f_req++; - /* fall through */ - case BLKIF_OP_WRITE: - blkif->st_wr_req++; - dispatch_rw_block_io(blkif, &req, pending_req); + if (dispatch_rw_block_io(blkif, &req, pending_req)) break; - case BLKIF_OP_WRITE_BARRIER: - default: - /* A good sign something is wrong: sleep for a while to - * avoid excessive CPU consumption by a bad guest. */ - msleep(1); - DPRINTK("error: unknown block io operation [%d]\n", - req.operation); - make_response(blkif, req.id, req.operation, - BLKIF_RSP_ERROR); - free_req(pending_req); - break; - } /* Yield point for this unbounded loop. */ cond_resched(); @@ -535,7 +513,7 @@ static int do_block_io_op(struct blkif_st *blkif) * Transumation of the 'struct blkif_request' to a proper 'struct bio' * and call the 'submit_bio' to pass it to the underlaying storage. */ -static void dispatch_rw_block_io(struct blkif_st *blkif, +static int dispatch_rw_block_io(struct blkif_st *blkif, struct blkif_request *req, struct pending_req *pending_req) { @@ -550,22 +528,25 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, switch (req->operation) { case BLKIF_OP_READ: + blkif->st_rd_req++; operation = READ; break; case BLKIF_OP_WRITE: + blkif->st_wr_req++; operation = WRITE_ODIRECT; break; case BLKIF_OP_FLUSH_DISKCACHE: + blkif->st_f_req++; operation = WRITE_FLUSH; /* The frontend likes to set this to -1, which vbd_translate * is alergic too. */ req->u.rw.sector_number = 0; break; case BLKIF_OP_WRITE_BARRIER: - /* Should never get here. */ default: operation = 0; /* make gcc happy */ - BUG(); + goto fail_response; + break; } /* Check that the number of segments is sane. */ @@ -677,7 +658,7 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, else if (operation == WRITE || operation == WRITE_FLUSH) blkif->st_wr_sect += preq.nr_sects; - return; + return 0; fail_flush: xen_blkbk_unmap(pending_req); @@ -686,14 +667,14 @@ static void dispatch_rw_block_io(struct blkif_st *blkif, make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); free_req(pending_req); msleep(1); /* back off a bit */ - return; + return -EIO; fail_put_bio: for (i = 0; i < (nbio-1); i++) bio_put(biolist[i]); __end_block_io_op(pending_req, -EINVAL); msleep(1); /* back off a bit */ - return; + return -EIO; } -- cgit v1.2.3 From 3d68b39926b3b247d76cc4da0256e979b2b730e3 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 5 May 2011 13:42:10 -0400 Subject: xen/blkback: Fix up some of the comments. They had the wrong data or were in the wrong spot. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 5f4284729a3a..b9bdd9e43ab9 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -603,7 +603,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, if (xen_blkbk_map(req, pending_req, seg)) goto fail_flush; - /* This corresponding blkif_put is done in __end_block_io_op */ + /* This corresponding xen_blkif_put is done in __end_block_io_op */ xen_blkif_get(blkif); for (i = 0; i < nseg; i++) { @@ -626,7 +626,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, preq.sector_number += seg[i].nsec; } - /* This will be hit if the operation was a barrier. */ + /* This will be hit if the operation was a flush. */ if (!bio) { BUG_ON(operation != WRITE_FLUSH); bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0); @@ -650,8 +650,8 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, for (i = 0; i < nbio; i++) submit_bio(operation, biolist[i]); - blk_finish_plug(&plug); /* Let the I/Os go.. */ + blk_finish_plug(&plug); if (operation == READ) blkif->st_rd_sect += preq.nr_sects; -- cgit v1.2.3 From 01f37f2d53e14a05b7fc3601d182f31ac3b35847 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 11 May 2011 15:57:09 -0400 Subject: xen/blkback: Fixed up comments and converted spaces to tabs. Suggested-by: Ian Campbell Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 70 +++++++++++++++++++-------------- drivers/block/xen-blkback/common.h | 77 ++++++++++++++++++++----------------- drivers/block/xen-blkback/xenbus.c | 39 +++++++++++-------- 3 files changed, 105 insertions(+), 81 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index b9bdd9e43ab9..6808cc7d9c73 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -73,13 +73,13 @@ module_param(debug_lvl, int, 0644); * response queued for it, with the saved 'id' passed back. */ struct pending_req { - struct blkif_st *blkif; - u64 id; - int nr_pages; - atomic_t pendcnt; - unsigned short operation; - int status; - struct list_head free_list; + struct blkif_st *blkif; + u64 id; + int nr_pages; + atomic_t pendcnt; + unsigned short operation; + int status; + struct list_head free_list; }; #define BLKBACK_INVALID_HANDLE (~0) @@ -103,7 +103,8 @@ static struct xen_blkbk *blkbk; * Little helpful macro to figure out the index and virtual address of the * pending_pages[..]. For each 'pending_req' we have have up to * BLKIF_MAX_SEGMENTS_PER_REQUEST (11) pages. The seg would be from 0 through - * 10 and would index in the pending_pages[..]. */ + * 10 and would index in the pending_pages[..]. + */ static inline int vaddr_pagenr(struct pending_req *req, int seg) { return (req - blkbk->pending_reqs) * @@ -167,8 +168,6 @@ static void free_req(struct pending_req *req) /* * Routines for managing virtual block devices (vbds). */ - - static int vbd_translate(struct phys_req *req, struct blkif_st *blkif, int operation) { @@ -315,7 +314,7 @@ struct seg_buf { /* * Unmap the grant references, and also remove the M2P over-rides * used in the 'pending_req'. -*/ + */ static void xen_blkbk_unmap(struct pending_req *req) { struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; @@ -336,27 +335,32 @@ static void xen_blkbk_unmap(struct pending_req *req) ret = HYPERVISOR_grant_table_op( GNTTABOP_unmap_grant_ref, unmap, invcount); BUG_ON(ret); - /* Note, we use invcount, so nr->pages, so we can't index + /* + * Note, we use invcount, so nr->pages, so we can't index * using vaddr(req, i). */ for (i = 0; i < invcount; i++) { ret = m2p_remove_override( virt_to_page(unmap[i].host_addr), false); if (ret) { - printk(KERN_ALERT "Failed to remove M2P override for " \ - "%lx\n", (unsigned long)unmap[i].host_addr); + printk(KERN_ALERT "Failed to remove M2P override for %lx\n", + (unsigned long)unmap[i].host_addr); continue; } } } -static int xen_blkbk_map(struct blkif_request *req, struct pending_req *pending_req, + +static int xen_blkbk_map(struct blkif_request *req, + struct pending_req *pending_req, struct seg_buf seg[]) { struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST]; int i; int nseg = req->nr_segments; int ret = 0; - /* Fill out preq.nr_sects with proper amount of sectors, and setup + + /* + * Fill out preq.nr_sects with proper amount of sectors, and setup * assign map[..] with the PFN of the page in our domain with the * corresponding grant reference for each page. */ @@ -367,13 +371,15 @@ static int xen_blkbk_map(struct blkif_request *req, struct pending_req *pending_ if (pending_req->operation != BLKIF_OP_READ) flags |= GNTMAP_readonly; gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags, - req->u.rw.seg[i].gref, pending_req->blkif->domid); + req->u.rw.seg[i].gref, + pending_req->blkif->domid); } ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg); BUG_ON(ret); - /* Now swizzel the MFN in our domain with the MFN from the other domain + /* + * Now swizzle the MFN in our domain with the MFN from the other domain * so that when we access vaddr(pending_req,i) it has the contents of * the page from the other domain. */ @@ -423,7 +429,8 @@ static void __end_block_io_op(struct pending_req *pending_req, int error) pending_req->status = BLKIF_RSP_ERROR; } - /* If all of the bio's have completed it is time to unmap + /* + * If all of the bio's have completed it is time to unmap * the grant references associated with 'request' and provide * the proper response on the ring. */ @@ -510,8 +517,8 @@ static int do_block_io_op(struct blkif_st *blkif) } /* - * Transumation of the 'struct blkif_request' to a proper 'struct bio' - * and call the 'submit_bio' to pass it to the underlaying storage. + * Transmutation of the 'struct blkif_request' to a proper 'struct bio' + * and call the 'submit_bio' to pass it to the underlying storage. */ static int dispatch_rw_block_io(struct blkif_st *blkif, struct blkif_request *req, @@ -538,8 +545,10 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, case BLKIF_OP_FLUSH_DISKCACHE: blkif->st_f_req++; operation = WRITE_FLUSH; - /* The frontend likes to set this to -1, which vbd_translate - * is alergic too. */ + /* + * The frontend likes to set this to -1, which vbd_translate + * is alergic too. + */ req->u.rw.sector_number = 0; break; case BLKIF_OP_WRITE_BARRIER: @@ -585,8 +594,11 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, preq.sector_number + preq.nr_sects, preq.dev); goto fail_response; } - /* This check _MUST_ be done after vbd_translate as the preq.bdev - * is set there. */ + + /* + * This check _MUST_ be done after vbd_translate as the preq.bdev + * is set there. + */ for (i = 0; i < nseg; i++) { if (((int)preq.sector_number|(int)seg[i].nsec) & ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) { @@ -595,7 +607,9 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, goto fail_response; } } - /* If we have failed at this point, we need to undo the M2P override, + + /* + * If we have failed at this point, we need to undo the M2P override, * set gnttab_set_unmap_op on all of the grant references and perform * the hypercall to unmap the grants - that is all done in * xen_blkbk_unmap. @@ -638,8 +652,8 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, bio->bi_end_io = end_block_io_op; } - - /* We set it one so that the last submit_bio does not have to call + /* + * We set it one so that the last submit_bio does not have to call * atomic_inc. */ atomic_set(&pending_req->pendcnt, nbio); diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index af93837e1295..e37dcf7f6b8e 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -47,53 +47,58 @@ __FILE__ , __LINE__ , ## _a) struct vbd { - blkif_vdev_t handle; /* what the domain refers to this vbd as */ - unsigned char readonly; /* Non-zero -> read-only */ - unsigned char type; /* VDISK_xxx */ - u32 pdevice; /* phys device that this vbd maps to */ - struct block_device *bdev; - sector_t size; /* Cached size parameter */ - bool flush_support; + /* What the domain refers to this vbd as. */ + blkif_vdev_t handle; + /* Non-zero -> read-only */ + unsigned char readonly; + /* VDISK_xxx */ + unsigned char type; + /* phys device that this vbd maps to. */ + u32 pdevice; + struct block_device *bdev; + /* Cached size parameter. */ + sector_t size; + bool flush_support; }; struct backend_info; struct blkif_st { /* Unique identifier for this interface. */ - domid_t domid; - unsigned int handle; + domid_t domid; + unsigned int handle; /* Physical parameters of the comms window. */ - unsigned int irq; + unsigned int irq; /* Comms information. */ - enum blkif_protocol blk_protocol; - union blkif_back_rings blk_rings; - struct vm_struct *blk_ring_area; + enum blkif_protocol blk_protocol; + union blkif_back_rings blk_rings; + struct vm_struct *blk_ring_area; /* The VBD attached to this interface. */ - struct vbd vbd; + struct vbd vbd; /* Back pointer to the backend_info. */ - struct backend_info *be; + struct backend_info *be; /* Private fields. */ - spinlock_t blk_ring_lock; - atomic_t refcnt; + spinlock_t blk_ring_lock; + atomic_t refcnt; - wait_queue_head_t wq; + wait_queue_head_t wq; /* One thread per one blkif. */ - struct task_struct *xenblkd; - unsigned int waiting_reqs; + struct task_struct *xenblkd; + unsigned int waiting_reqs; /* statistics */ - unsigned long st_print; - int st_rd_req; - int st_wr_req; - int st_oo_req; - int st_f_req; - int st_rd_sect; - int st_wr_sect; - - wait_queue_head_t waiting_to_free; - - grant_handle_t shmem_handle; - grant_ref_t shmem_ref; + unsigned long st_print; + int st_rd_req; + int st_wr_req; + int st_oo_req; + int st_f_req; + int st_rd_sect; + int st_wr_sect; + + wait_queue_head_t waiting_to_free; + + grant_handle_t shmem_handle; + grant_ref_t shmem_ref; }; @@ -109,10 +114,10 @@ struct blkif_st { } while (0) struct phys_req { - unsigned short dev; - unsigned short nr_sects; - struct block_device *bdev; - blkif_sector_t sector_number; + unsigned short dev; + unsigned short nr_sects; + struct block_device *bdev; + blkif_sector_t sector_number; }; int xen_blkif_interface_init(void); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 9adcf806f83f..0cda406b4edb 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -27,12 +27,12 @@ __func__, __LINE__, ##args) struct backend_info { - struct xenbus_device *dev; - struct blkif_st *blkif; - struct xenbus_watch backend_watch; - unsigned major; - unsigned minor; - char *mode; + struct xenbus_device *dev; + struct blkif_st *blkif; + struct xenbus_watch backend_watch; + unsigned major; + unsigned minor; + char *mode; }; static struct kmem_cache *xen_blkif_cachep; @@ -425,7 +425,7 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, return err; } -/** +/* * Entry point to this code when a new device is created. Allocate the basic * structures, and watch the store waiting for the hotplug scripts to tell us * the device's physical major and minor numbers. Switch to InitWait. @@ -473,7 +473,7 @@ fail: } -/** +/* * Callback received when the hotplug scripts have placed the physical-device * node. Read it and the mode node, and create a vbd. If the frontend is * ready, connect. @@ -495,9 +495,11 @@ static void backend_changed(struct xenbus_watch *watch, err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x", &major, &minor); if (XENBUS_EXIST_ERR(err)) { - /* Since this watch will fire once immediately after it is - registered, we expect this. Ignore it, and wait for the - hotplug scripts. */ + /* + * Since this watch will fire once immediately after it is + * registered, we expect this. Ignore it, and wait for the + * hotplug scripts. + */ return; } if (err != 2) { @@ -562,7 +564,7 @@ static void backend_changed(struct xenbus_watch *watch, } -/** +/* * Callback received when the frontend's state changes. */ static void frontend_changed(struct xenbus_device *dev, @@ -584,13 +586,16 @@ static void frontend_changed(struct xenbus_device *dev, case XenbusStateInitialised: case XenbusStateConnected: - /* Ensure we connect even when two watches fire in - close successsion and we miss the intermediate value - of frontend_state. */ + /* + * Ensure we connect even when two watches fire in + * close successsion and we miss the intermediate value + * of frontend_state. + */ if (dev->state == XenbusStateConnected) break; - /* Enforce precondition before potential leak point. + /* + * Enforce precondition before potential leak point. * blkif_disconnect() is idempotent. */ xen_blkif_disconnect(be->blkif); @@ -627,7 +632,7 @@ static void frontend_changed(struct xenbus_device *dev, /* ** Connection ** */ -/** +/* * Write the physical details regarding the block device to the store, and * switch to Connected state. */ -- cgit v1.2.3 From ebe8190659244ec21b5f16950cf7b156f5b7eb01 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:42:31 -0400 Subject: xen/blkback: Change printk/DPRINTK to pr_.. type variant. And also make them uniform and prefix the message with 'xen-blkback'. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 58 ++++++++++++++++++------------------- drivers/block/xen-blkback/xenbus.c | 19 +++++------- 2 files changed, 37 insertions(+), 40 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 6808cc7d9c73..5c9568e39eab 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -196,20 +196,20 @@ static void vbd_resize(struct blkif_st *blkif) struct xenbus_device *dev = xen_blkbk_xenbus(blkif->be); unsigned long long new_size = vbd_sz(vbd); - printk(KERN_INFO "VBD Resize: Domid: %d, Device: (%d, %d)\n", + pr_info("xen-blkback: VBD Resize: Domid: %d, Device: (%d, %d)\n", blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice)); - printk(KERN_INFO "VBD Resize: new size %llu\n", new_size); + pr_info("xen-blkback: VBD Resize: new size %llu\n", new_size); vbd->size = new_size; again: err = xenbus_transaction_start(&xbt); if (err) { - printk(KERN_WARNING "Error starting transaction"); + pr_warn("xen-blkback: Error starting transaction"); return; } err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", (unsigned long long)vbd_sz(vbd)); if (err) { - printk(KERN_WARNING "Error writing new size"); + pr_warn("xen-blkback: Error writing new size"); goto abort; } /* @@ -219,7 +219,7 @@ again: */ err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); if (err) { - printk(KERN_WARNING "Error writing the state"); + pr_warn("xen-blkback: Error writing the state"); goto abort; } @@ -227,7 +227,7 @@ again: if (err == -EAGAIN) goto again; if (err) - printk(KERN_WARNING "Error ending transaction"); + pr_warn("xen-blkback: Error ending transaction"); abort: xenbus_transaction_end(xbt, 1); } @@ -253,9 +253,9 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id) static void print_stats(struct blkif_st *blkif) { - printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | f %4d\n", - current->comm, blkif->st_oo_req, - blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req); + pr_debug("xen-blkback (%s): oo %3d | rd %4d | wr %4d | f %4d\n", + current->comm, blkif->st_oo_req, + blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req); blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); blkif->st_rd_req = 0; blkif->st_wr_req = 0; @@ -270,7 +270,7 @@ int xen_blkif_schedule(void *arg) xen_blkif_get(blkif); if (debug_lvl) - printk(KERN_DEBUG "%s: started\n", current->comm); + pr_debug("xen-blkback: %s: started\n", current->comm); while (!kthread_should_stop()) { if (try_to_freeze()) @@ -299,7 +299,7 @@ int xen_blkif_schedule(void *arg) if (log_stats) print_stats(blkif); if (debug_lvl) - printk(KERN_DEBUG "%s: exiting\n", current->comm); + pr_debug("xen-blkback: %s: exiting\n", current->comm); blkif->xenblkd = NULL; xen_blkif_put(blkif); @@ -343,8 +343,8 @@ static void xen_blkbk_unmap(struct pending_req *req) ret = m2p_remove_override( virt_to_page(unmap[i].host_addr), false); if (ret) { - printk(KERN_ALERT "Failed to remove M2P override for %lx\n", - (unsigned long)unmap[i].host_addr); + pr_alert("xen-blkback: Failed to remove M2P override for %lx\n", + (unsigned long)unmap[i].host_addr); continue; } } @@ -385,7 +385,7 @@ static int xen_blkbk_map(struct blkif_request *req, */ for (i = 0; i < nseg; i++) { if (unlikely(map[i].status != 0)) { - DPRINTK("invalid buffer -- could not remap it\n"); + pr_debug("xen-blkback: invalid buffer -- could not remap it\n"); map[i].handle = BLKBACK_INVALID_HANDLE; ret |= 1; } @@ -398,9 +398,8 @@ static int xen_blkbk_map(struct blkif_request *req, ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr), blkbk->pending_page(pending_req, i), false); if (ret) { - printk(KERN_ALERT "Failed to install M2P override for"\ - " %lx (ret: %d)\n", (unsigned long) - map[i].dev_bus_addr, ret); + pr_alert("xen-blkback: Failed to install M2P override for %lx (ret: %d)\n", + (unsigned long)map[i].dev_bus_addr, ret); /* We could switch over to GNTTABOP_copy */ continue; } @@ -420,12 +419,12 @@ static void __end_block_io_op(struct pending_req *pending_req, int error) /* An error fails the entire request. */ if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) && (error == -EOPNOTSUPP)) { - DPRINTK("blkback: flush diskcache op failed, not supported\n"); + pr_debug("xen-blkback: flush diskcache op failed, not supported\n"); xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0); pending_req->status = BLKIF_RSP_EOPNOTSUPP; } else if (error) { - DPRINTK("Buffer not up-to-date at end of operation, " - "error=%d\n", error); + pr_debug("xen-blkback: Buffer not up-to-date at end of operation," + " error=%d\n", error); pending_req->status = BLKIF_RSP_ERROR; } @@ -562,7 +561,8 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, nseg = req->nr_segments; if (unlikely(nseg == 0 && operation != WRITE_FLUSH) || unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { - DPRINTK("Bad number of segments in request (%d)\n", nseg); + pr_debug("xen-blkback: Bad number of segments in request (%d)\n", + nseg); /* Haven't submitted any bio's yet. */ goto fail_response; } @@ -588,10 +588,10 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, } if (vbd_translate(&preq, blkif, operation) != 0) { - DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", - operation == READ ? "read" : "write", - preq.sector_number, - preq.sector_number + preq.nr_sects, preq.dev); + pr_debug("xen-blkback: access denied: %s of [%llu,%llu] on dev=%04x\n", + operation == READ ? "read" : "write", + preq.sector_number, + preq.sector_number + preq.nr_sects, preq.dev); goto fail_response; } @@ -602,8 +602,8 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, for (i = 0; i < nseg; i++) { if (((int)preq.sector_number|(int)seg[i].nsec) & ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) { - DPRINTK("Misaligned I/O request from domain %d", - blkif->domid); + pr_debug("xen-blkback: Misaligned I/O request from domain %d", + blkif->domid); goto fail_response; } } @@ -759,7 +759,7 @@ static int __init xen_blkif_init(void) blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL); if (!blkbk) { - printk(KERN_ALERT "%s: out of memory!\n", __func__); + pr_alert("xen-blkback: %s: out of memory!\n", __func__); return -ENOMEM; } @@ -807,7 +807,7 @@ static int __init xen_blkif_init(void) return 0; out_of_memory: - printk(KERN_ERR "%s: out of memory\n", __func__); + pr_alert("xen-blkback: %s: out of memory\n", __func__); failed_init: kfree(blkbk->pending_reqs); kfree(blkbk->pending_grant_handles); diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 0cda406b4edb..c86519c477f3 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -23,7 +23,7 @@ #undef DPRINTK #define DPRINTK(fmt, args...) \ - pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \ + pr_debug("xen-blkback: (%s:%d) " fmt ".\n", \ __func__, __LINE__, ##args) struct backend_info { @@ -136,7 +136,7 @@ static int map_frontend_page(struct blkif_st *blkif, unsigned long shared_page) BUG(); if (op.status) { - DPRINTK(" Grant table operation failure !\n"); + DPRINTK("Grant table operation failure !\n"); return op.status; } @@ -509,10 +509,8 @@ static void backend_changed(struct xenbus_watch *watch, if ((be->major || be->minor) && ((be->major != major) || (be->minor != minor))) { - printk(KERN_WARNING - "blkback: changing physical device (from %x:%x to " - "%x:%x) not supported.\n", be->major, be->minor, - major, minor); + pr_warn("xen-blkback: changing physical device (from %x:%x to %x:%x) not supported.\n", + be->major, be->minor, major, minor); return; } @@ -578,8 +576,8 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk(KERN_INFO "%s: %s: prepare for reconnect\n", - __func__, dev->nodename); + pr_info("xen-blkback: %s: prepare for reconnect\n", + dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } break; @@ -733,9 +731,8 @@ static int connect_ring(struct backend_info *be) xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); return -1; } - printk(KERN_INFO - "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", - ring_ref, evtchn, be->blkif->blk_protocol, protocol); + pr_info("xen-blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ err = xen_blkif_map(be->blkif, ring_ref, evtchn); -- cgit v1.2.3 From 1afbd730a33c6e4ca780a70351e8929dd4c40636 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 11 May 2011 16:15:24 -0400 Subject: xen/blkback: Make the DPRINTK uniform. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/common.h | 6 +++--- drivers/block/xen-blkback/xenbus.c | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index e37dcf7f6b8e..46e5d0630440 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -42,9 +42,9 @@ #include #include -#define DPRINTK(_f, _a...) \ - pr_debug("(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a) +#define DPRINTK(fmt, args...) \ + pr_debug("xen-blkback: (%s:%d) " fmt ".\n", \ + __func__, __LINE__, ##args) struct vbd { /* What the domain refers to this vbd as. */ diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index c86519c477f3..fa01dbbee0ad 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -21,11 +21,6 @@ #include #include "common.h" -#undef DPRINTK -#define DPRINTK(fmt, args...) \ - pr_debug("xen-blkback: (%s:%d) " fmt ".\n", \ - __func__, __LINE__, ##args) - struct backend_info { struct xenbus_device *dev; struct blkif_st *blkif; -- cgit v1.2.3 From 22b20f2dffd09edd66127f2022c26d0039bad88e Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:43:12 -0400 Subject: xen/blkback: Use the DRV_PFX in the pr_.. macros. To make it easier to read. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 36 ++++++++++++++++++------------------ drivers/block/xen-blkback/common.h | 3 ++- drivers/block/xen-blkback/xenbus.c | 6 +++--- 3 files changed, 23 insertions(+), 22 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 5c9568e39eab..09fe528dd088 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -196,20 +196,20 @@ static void vbd_resize(struct blkif_st *blkif) struct xenbus_device *dev = xen_blkbk_xenbus(blkif->be); unsigned long long new_size = vbd_sz(vbd); - pr_info("xen-blkback: VBD Resize: Domid: %d, Device: (%d, %d)\n", + pr_info(DRV_PFX "VBD Resize: Domid: %d, Device: (%d, %d)\n", blkif->domid, MAJOR(vbd->pdevice), MINOR(vbd->pdevice)); - pr_info("xen-blkback: VBD Resize: new size %llu\n", new_size); + pr_info(DRV_PFX "VBD Resize: new size %llu\n", new_size); vbd->size = new_size; again: err = xenbus_transaction_start(&xbt); if (err) { - pr_warn("xen-blkback: Error starting transaction"); + pr_warn(DRV_PFX "Error starting transaction"); return; } err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", (unsigned long long)vbd_sz(vbd)); if (err) { - pr_warn("xen-blkback: Error writing new size"); + pr_warn(DRV_PFX "Error writing new size"); goto abort; } /* @@ -219,7 +219,7 @@ again: */ err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); if (err) { - pr_warn("xen-blkback: Error writing the state"); + pr_warn(DRV_PFX "Error writing the state"); goto abort; } @@ -227,7 +227,7 @@ again: if (err == -EAGAIN) goto again; if (err) - pr_warn("xen-blkback: Error ending transaction"); + pr_warn(DRV_PFX "Error ending transaction"); abort: xenbus_transaction_end(xbt, 1); } @@ -270,7 +270,7 @@ int xen_blkif_schedule(void *arg) xen_blkif_get(blkif); if (debug_lvl) - pr_debug("xen-blkback: %s: started\n", current->comm); + pr_debug(DRV_PFX "%s: started\n", current->comm); while (!kthread_should_stop()) { if (try_to_freeze()) @@ -299,7 +299,7 @@ int xen_blkif_schedule(void *arg) if (log_stats) print_stats(blkif); if (debug_lvl) - pr_debug("xen-blkback: %s: exiting\n", current->comm); + pr_debug(DRV_PFX "%s: exiting\n", current->comm); blkif->xenblkd = NULL; xen_blkif_put(blkif); @@ -343,7 +343,7 @@ static void xen_blkbk_unmap(struct pending_req *req) ret = m2p_remove_override( virt_to_page(unmap[i].host_addr), false); if (ret) { - pr_alert("xen-blkback: Failed to remove M2P override for %lx\n", + pr_alert(DRV_PFX "Failed to remove M2P override for %lx\n", (unsigned long)unmap[i].host_addr); continue; } @@ -385,7 +385,7 @@ static int xen_blkbk_map(struct blkif_request *req, */ for (i = 0; i < nseg; i++) { if (unlikely(map[i].status != 0)) { - pr_debug("xen-blkback: invalid buffer -- could not remap it\n"); + pr_debug(DRV_PFX "invalid buffer -- could not remap it\n"); map[i].handle = BLKBACK_INVALID_HANDLE; ret |= 1; } @@ -398,7 +398,7 @@ static int xen_blkbk_map(struct blkif_request *req, ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr), blkbk->pending_page(pending_req, i), false); if (ret) { - pr_alert("xen-blkback: Failed to install M2P override for %lx (ret: %d)\n", + pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n", (unsigned long)map[i].dev_bus_addr, ret); /* We could switch over to GNTTABOP_copy */ continue; @@ -419,11 +419,11 @@ static void __end_block_io_op(struct pending_req *pending_req, int error) /* An error fails the entire request. */ if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) && (error == -EOPNOTSUPP)) { - pr_debug("xen-blkback: flush diskcache op failed, not supported\n"); + pr_debug(DRV_PFX "flush diskcache op failed, not supported\n"); xen_blkbk_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0); pending_req->status = BLKIF_RSP_EOPNOTSUPP; } else if (error) { - pr_debug("xen-blkback: Buffer not up-to-date at end of operation," + pr_debug(DRV_PFX "Buffer not up-to-date at end of operation," " error=%d\n", error); pending_req->status = BLKIF_RSP_ERROR; } @@ -561,7 +561,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, nseg = req->nr_segments; if (unlikely(nseg == 0 && operation != WRITE_FLUSH) || unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { - pr_debug("xen-blkback: Bad number of segments in request (%d)\n", + pr_debug(DRV_PFX "Bad number of segments in request (%d)\n", nseg); /* Haven't submitted any bio's yet. */ goto fail_response; @@ -588,7 +588,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, } if (vbd_translate(&preq, blkif, operation) != 0) { - pr_debug("xen-blkback: access denied: %s of [%llu,%llu] on dev=%04x\n", + pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n", operation == READ ? "read" : "write", preq.sector_number, preq.sector_number + preq.nr_sects, preq.dev); @@ -602,7 +602,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, for (i = 0; i < nseg; i++) { if (((int)preq.sector_number|(int)seg[i].nsec) & ((bdev_logical_block_size(preq.bdev) >> 9) - 1)) { - pr_debug("xen-blkback: Misaligned I/O request from domain %d", + pr_debug(DRV_PFX "Misaligned I/O request from domain %d", blkif->domid); goto fail_response; } @@ -759,7 +759,7 @@ static int __init xen_blkif_init(void) blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL); if (!blkbk) { - pr_alert("xen-blkback: %s: out of memory!\n", __func__); + pr_alert(DRV_PFX "%s: out of memory!\n", __func__); return -ENOMEM; } @@ -807,7 +807,7 @@ static int __init xen_blkif_init(void) return 0; out_of_memory: - pr_alert("xen-blkback: %s: out of memory\n", __func__); + pr_alert(DRV_PFX "%s: out of memory\n", __func__); failed_init: kfree(blkbk->pending_reqs); kfree(blkbk->pending_grant_handles); diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 46e5d0630440..da96e3eaa641 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -42,8 +42,9 @@ #include #include +#define DRV_PFX "xen-blkback:" #define DPRINTK(fmt, args...) \ - pr_debug("xen-blkback: (%s:%d) " fmt ".\n", \ + pr_debug(DRV_PFX "(%s:%d) " fmt ".\n", \ __func__, __LINE__, ##args) struct vbd { diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index fa01dbbee0ad..1c3fa6507e6d 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -504,7 +504,7 @@ static void backend_changed(struct xenbus_watch *watch, if ((be->major || be->minor) && ((be->major != major) || (be->minor != minor))) { - pr_warn("xen-blkback: changing physical device (from %x:%x to %x:%x) not supported.\n", + pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", be->major, be->minor, major, minor); return; } @@ -571,7 +571,7 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - pr_info("xen-blkback: %s: prepare for reconnect\n", + pr_info(DRV_PFX "%s: prepare for reconnect\n", dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } @@ -726,7 +726,7 @@ static int connect_ring(struct backend_info *be) xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); return -1; } - pr_info("xen-blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + pr_info(DRV_PFX "ring-ref %ld, event-channel %d, protocol %d (%s)\n", ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ -- cgit v1.2.3 From 72468bfcb815bc9875a870973469f68e20c78717 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 11 May 2011 16:21:08 -0400 Subject: xen/blkback: Removing the debug_lvl option. It is not really used for anything. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 09fe528dd088..453b51ac737f 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -62,9 +62,7 @@ MODULE_PARM_DESC(reqs, "Number of blkback requests to allocate"); /* Run-time switchable: /sys/module/blkback/parameters/ */ static unsigned int log_stats; -static unsigned int debug_lvl; module_param(log_stats, int, 0644); -module_param(debug_lvl, int, 0644); /* * Each outstanding request that we've passed to the lower device layers has a @@ -269,9 +267,6 @@ int xen_blkif_schedule(void *arg) xen_blkif_get(blkif); - if (debug_lvl) - pr_debug(DRV_PFX "%s: started\n", current->comm); - while (!kthread_should_stop()) { if (try_to_freeze()) continue; @@ -298,8 +293,6 @@ int xen_blkif_schedule(void *arg) if (log_stats) print_stats(blkif); - if (debug_lvl) - pr_debug(DRV_PFX "%s: exiting\n", current->comm); blkif->xenblkd = NULL; xen_blkif_put(blkif); -- cgit v1.2.3 From 68c88dd7d3caf1737112238fbe91cccd8e7a69fc Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 11 May 2011 16:23:39 -0400 Subject: xen/blkback: Move blkif_get_x86_[32|64]_req to common.h in block/xen-blkback dir. From the blkif.h header, which was exposed to the frontend. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/common.h | 32 ++++++++++++++++++++++++++++++++ include/xen/blkif.h | 30 ------------------------------ 2 files changed, 32 insertions(+), 30 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index da96e3eaa641..647d974da392 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -132,4 +132,36 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); +static void inline blkif_get_x86_32_req(struct blkif_request *dst, + struct blkif_x86_32_request *src) +{ + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; + dst->operation = src->operation; + dst->nr_segments = src->nr_segments; + dst->handle = src->handle; + dst->id = src->id; + dst->u.rw.sector_number = src->sector_number; + barrier(); + if (n > dst->nr_segments) + n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->u.rw.seg[i] = src->seg[i]; +} + +static void inline blkif_get_x86_64_req(struct blkif_request *dst, + struct blkif_x86_64_request *src) +{ + int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; + dst->operation = src->operation; + dst->nr_segments = src->nr_segments; + dst->handle = src->handle; + dst->id = src->id; + dst->u.rw.sector_number = src->sector_number; + barrier(); + if (n > dst->nr_segments) + n = dst->nr_segments; + for (i = 0; i < n; i++) + dst->u.rw.seg[i] = src->seg[i]; +} + #endif /* __BLKIF__BACKEND__COMMON_H__ */ diff --git a/include/xen/blkif.h b/include/xen/blkif.h index ab794269fc53..6ed7c01253b2 100644 --- a/include/xen/blkif.h +++ b/include/xen/blkif.h @@ -89,34 +89,4 @@ enum blkif_protocol { BLKIF_PROTOCOL_X86_64 = 3, }; -static void inline blkif_get_x86_32_req(struct blkif_request *dst, struct blkif_x86_32_request *src) -{ - int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; - dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; - dst->u.rw.sector_number = src->sector_number; - barrier(); - if (n > dst->nr_segments) - n = dst->nr_segments; - for (i = 0; i < n; i++) - dst->u.rw.seg[i] = src->seg[i]; -} - -static void inline blkif_get_x86_64_req(struct blkif_request *dst, struct blkif_x86_64_request *src) -{ - int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; - dst->operation = src->operation; - dst->nr_segments = src->nr_segments; - dst->handle = src->handle; - dst->id = src->id; - dst->u.rw.sector_number = src->sector_number; - barrier(); - if (n > dst->nr_segments) - n = dst->nr_segments; - for (i = 0; i < n; i++) - dst->u.rw.seg[i] = src->seg[i]; -} - #endif /* __XEN_BLKIF_H__ */ -- cgit v1.2.3 From b9fc02968c5dd3c0461b4bb126499a17b13fb86e Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 11 May 2011 16:26:59 -0400 Subject: xen/blkback: Fix spelling mistakes. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/xenbus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 1c3fa6507e6d..5d2bbf6240c8 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -351,7 +351,7 @@ static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, FMODE_READ : FMODE_WRITE, NULL); if (IS_ERR(bdev)) { - DPRINTK("vbd_creat: device %08x could not be opened.\n", + DPRINTK("vbd_create: device %08x could not be opened.\n", vbd->pdevice); return -ENOENT; } @@ -360,7 +360,7 @@ static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, vbd->size = vbd_sz(vbd); if (vbd->bdev->bd_disk == NULL) { - DPRINTK("vbd_creat: device %08x doesn't exist.\n", + DPRINTK("vbd_create: device %08x doesn't exist.\n", vbd->pdevice); vbd_free(vbd); return -ENOENT; -- cgit v1.2.3 From a4c348580e65c95d4b278bb6f154f622df12b893 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:10:55 -0400 Subject: xen/blkback: Flesh out the description in the Kconfig. with more details. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/block') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 9abb64689712..717d6e4e18d3 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -478,6 +478,19 @@ config XEN_BLKDEV_BACKEND block devices to other guests via a high-performance shared-memory interface. + The corresponding Linux frontend driver is enabled by the + CONFIG_XEN_BLKDEV_FRONTEND configuration option. + + The backend driver attaches itself to a any block device specified + in the XenBus configuration. There are no limits to what the block + device as long as it has a major and minor. + + If you are compiling a kernel to run in a Xen block backend driver + domain (often this is domain 0) you should say Y here. To + compile this driver as a module, chose M here: the module + will be called xen-blkback. + + config VIRTIO_BLK tristate "Virtio block driver (EXPERIMENTAL)" depends on EXPERIMENTAL && VIRTIO -- cgit v1.2.3 From 03e0edf946a08f498788bb6e8ab58453d98f25b9 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:19:23 -0400 Subject: xen/blkback: Checkpatch.pl recommend against multiple assigments. CHECK: multiple assignments should be avoided Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 9 ++++++--- drivers/block/xen-blkback/xenbus.c | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 453b51ac737f..362fbf6f656d 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -620,10 +620,11 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, seg[i].nsec << 9, seg[i].buf & ~PAGE_MASK) == 0)) { - bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i); + bio = bio_alloc(GFP_KERNEL, nseg-i); if (unlikely(bio == NULL)) goto fail_put_bio; + biolist[nbio++] = bio; bio->bi_bdev = preq.bdev; bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; @@ -636,10 +637,12 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, /* This will be hit if the operation was a flush. */ if (!bio) { BUG_ON(operation != WRITE_FLUSH); - bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, 0); + + bio = bio_alloc(GFP_KERNEL, 0); if (unlikely(bio == NULL)) goto fail_put_bio; + biolist[nbio++] = bio; bio->bi_bdev = preq.bdev; bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; @@ -677,7 +680,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, return -EIO; fail_put_bio: - for (i = 0; i < (nbio-1); i++) + for (i = 0; i < nbio; i++) bio_put(biolist[i]); __end_block_io_op(pending_req, -EINVAL); msleep(1); /* back off a bit */ diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 5d2bbf6240c8..ba8d30662d19 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -538,7 +538,8 @@ static void backend_changed(struct xenbus_watch *watch, err = vbd_create(be->blkif, handle, major, minor, (NULL == strchr(be->mode, 'w')), cdrom); if (err) { - be->major = be->minor = 0; + be->major = 0; + be->minor = 0; xenbus_dev_fatal(dev, err, "creating vbd structure"); return; } @@ -546,7 +547,8 @@ static void backend_changed(struct xenbus_watch *watch, err = xenvbd_sysfs_addif(dev); if (err) { vbd_free(&be->blkif->vbd); - be->major = be->minor = 0; + be->major = 0; + be->minor = 0; xenbus_dev_fatal(dev, err, "creating sysfs entries"); return; } -- cgit v1.2.3 From b0f801273f7359a7d91fc94f5c6bf216bc17aaa1 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:23:06 -0400 Subject: xen/blkback: Fixing some more of the cleanpatch.pl warnings. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 2 +- drivers/block/xen-blkback/common.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 362fbf6f656d..d06eb6a50d57 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -637,7 +637,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, /* This will be hit if the operation was a flush. */ if (!bio) { BUG_ON(operation != WRITE_FLUSH); - + bio = bio_alloc(GFP_KERNEL, 0); if (unlikely(bio == NULL)) goto fail_put_bio; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 647d974da392..629546558a47 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -132,7 +132,7 @@ int xen_blkbk_flush_diskcache(struct xenbus_transaction xbt, struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be); -static void inline blkif_get_x86_32_req(struct blkif_request *dst, +static inline void blkif_get_x86_32_req(struct blkif_request *dst, struct blkif_x86_32_request *src) { int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; @@ -148,7 +148,7 @@ static void inline blkif_get_x86_32_req(struct blkif_request *dst, dst->u.rw.seg[i] = src->seg[i]; } -static void inline blkif_get_x86_64_req(struct blkif_request *dst, +static inline void blkif_get_x86_64_req(struct blkif_request *dst, struct blkif_x86_64_request *src) { int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; -- cgit v1.2.3 From 452a6b2bb6de677acdd2ccb8b39cf6e8fe06f306 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:31:51 -0400 Subject: xen/blkback: Move include/xen/blkif.h into drivers/block/xen-blkback/common.h Not point of the blkif.h file. It is not used by the frontend. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/common.h | 72 ++++++++++++++++++++++++++++- include/xen/blkif.h | 95 -------------------------------------- 2 files changed, 71 insertions(+), 96 deletions(-) delete mode 100644 include/xen/blkif.h (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 629546558a47..b8856fe2568f 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -38,15 +38,85 @@ #include #include #include -#include #include #include +#include +#include +#include #define DRV_PFX "xen-blkback:" #define DPRINTK(fmt, args...) \ pr_debug(DRV_PFX "(%s:%d) " fmt ".\n", \ __func__, __LINE__, ##args) + +/* Not a real protocol. Used to generate ring structs which contain + * the elements common to all protocols only. This way we get a + * compiler-checkable way to use common struct elements, so we can + * avoid using switch(protocol) in a number of places. */ +struct blkif_common_request { + char dummy; +}; +struct blkif_common_response { + char dummy; +}; + +/* i386 protocol version */ +#pragma pack(push, 4) +struct blkif_x86_32_request { + uint8_t operation; /* BLKIF_OP_??? */ + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t id; /* private guest value, echoed in resp */ + blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; +struct blkif_x86_32_response { + uint64_t id; /* copied from request */ + uint8_t operation; /* copied from request */ + int16_t status; /* BLKIF_RSP_??? */ +}; +typedef struct blkif_x86_32_request blkif_x86_32_request_t; +typedef struct blkif_x86_32_response blkif_x86_32_response_t; +#pragma pack(pop) + +/* x86_64 protocol version */ +struct blkif_x86_64_request { + uint8_t operation; /* BLKIF_OP_??? */ + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t __attribute__((__aligned__(8))) id; + blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; +struct blkif_x86_64_response { + uint64_t __attribute__((__aligned__(8))) id; + uint8_t operation; /* copied from request */ + int16_t status; /* BLKIF_RSP_??? */ +}; +typedef struct blkif_x86_64_request blkif_x86_64_request_t; +typedef struct blkif_x86_64_response blkif_x86_64_response_t; + +DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, + struct blkif_common_response); +DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, + struct blkif_x86_32_response); +DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, + struct blkif_x86_64_response); + +union blkif_back_rings { + struct blkif_back_ring native; + struct blkif_common_back_ring common; + struct blkif_x86_32_back_ring x86_32; + struct blkif_x86_64_back_ring x86_64; +}; + +enum blkif_protocol { + BLKIF_PROTOCOL_NATIVE = 1, + BLKIF_PROTOCOL_X86_32 = 2, + BLKIF_PROTOCOL_X86_64 = 3, +}; + struct vbd { /* What the domain refers to this vbd as. */ blkif_vdev_t handle; diff --git a/include/xen/blkif.h b/include/xen/blkif.h deleted file mode 100644 index 3c9ca7a93ba4..000000000000 --- a/include/xen/blkif.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __XEN_BLKIF_H__ -#define __XEN_BLKIF_H__ - -#include -#include -#include - -/* Not a real protocol. Used to generate ring structs which contain - * the elements common to all protocols only. This way we get a - * compiler-checkable way to use common struct elements, so we can - * avoid using switch(protocol) in a number of places. */ -struct blkif_common_request { - char dummy; -}; -struct blkif_common_response { - char dummy; -}; - -/* i386 protocol version */ -#pragma pack(push, 4) -struct blkif_x86_32_request { - uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t id; /* private guest value, echoed in resp */ - blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; -struct blkif_x86_32_response { - uint64_t id; /* copied from request */ - uint8_t operation; /* copied from request */ - int16_t status; /* BLKIF_RSP_??? */ -}; -typedef struct blkif_x86_32_request blkif_x86_32_request_t; -typedef struct blkif_x86_32_response blkif_x86_32_response_t; -#pragma pack(pop) - -/* x86_64 protocol version */ -struct blkif_x86_64_request { - uint8_t operation; /* BLKIF_OP_??? */ - uint8_t nr_segments; /* number of segments */ - blkif_vdev_t handle; /* only for read/write requests */ - uint64_t __attribute__((__aligned__(8))) id; - blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -}; -struct blkif_x86_64_response { - uint64_t __attribute__((__aligned__(8))) id; - uint8_t operation; /* copied from request */ - int16_t status; /* BLKIF_RSP_??? */ -}; -typedef struct blkif_x86_64_request blkif_x86_64_request_t; -typedef struct blkif_x86_64_response blkif_x86_64_response_t; - -DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, - struct blkif_common_response); -DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, - struct blkif_x86_32_response); -DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, - struct blkif_x86_64_response); - -union blkif_back_rings { - struct blkif_back_ring native; - struct blkif_common_back_ring common; - struct blkif_x86_32_back_ring x86_32; - struct blkif_x86_64_back_ring x86_64; -}; - -enum blkif_protocol { - BLKIF_PROTOCOL_NATIVE = 1, - BLKIF_PROTOCOL_X86_32 = 2, - BLKIF_PROTOCOL_X86_64 = 3, -}; - -#endif /* __XEN_BLKIF_H__ */ -- cgit v1.2.3 From 325a64860472765ecaeaa0081e9ddd67671183d4 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:37:04 -0400 Subject: xen/blkback: Remove the unused typedefs. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/common.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index b8856fe2568f..b0db6aabb5b8 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -76,8 +76,6 @@ struct blkif_x86_32_response { uint8_t operation; /* copied from request */ int16_t status; /* BLKIF_RSP_??? */ }; -typedef struct blkif_x86_32_request blkif_x86_32_request_t; -typedef struct blkif_x86_32_response blkif_x86_32_response_t; #pragma pack(pop) /* x86_64 protocol version */ @@ -94,8 +92,6 @@ struct blkif_x86_64_response { uint8_t operation; /* copied from request */ int16_t status; /* BLKIF_RSP_??? */ }; -typedef struct blkif_x86_64_request blkif_x86_64_request_t; -typedef struct blkif_x86_64_response blkif_x86_64_response_t; DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response); -- cgit v1.2.3 From 30fd150202fb2d08a62f9c2966a4b1fcf2e861e7 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:47:48 -0400 Subject: xen/blkback: Change structure name blkif_st to xen_blkif. No need for that '_st' and xen_blkif is more apt. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 28 ++++++++++++++-------------- drivers/block/xen-blkback/common.h | 2 +- drivers/block/xen-blkback/xenbus.c | 24 ++++++++++++------------ 3 files changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index d06eb6a50d57..d438781ecc7c 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -71,7 +71,7 @@ module_param(log_stats, int, 0644); * response queued for it, with the saved 'id' passed back. */ struct pending_req { - struct blkif_st *blkif; + struct xen_blkif *blkif; u64 id; int nr_pages; atomic_t pendcnt; @@ -121,11 +121,11 @@ static inline unsigned long vaddr(struct pending_req *req, int seg) (blkbk->pending_grant_handles[vaddr_pagenr(_req, _seg)]) -static int do_block_io_op(struct blkif_st *blkif); -static int dispatch_rw_block_io(struct blkif_st *blkif, +static int do_block_io_op(struct xen_blkif *blkif); +static int dispatch_rw_block_io(struct xen_blkif *blkif, struct blkif_request *req, struct pending_req *pending_req); -static void make_response(struct blkif_st *blkif, u64 id, +static void make_response(struct xen_blkif *blkif, u64 id, unsigned short op, int st); /* @@ -166,7 +166,7 @@ static void free_req(struct pending_req *req) /* * Routines for managing virtual block devices (vbds). */ -static int vbd_translate(struct phys_req *req, struct blkif_st *blkif, +static int vbd_translate(struct phys_req *req, struct xen_blkif *blkif, int operation) { struct vbd *vbd = &blkif->vbd; @@ -186,7 +186,7 @@ static int vbd_translate(struct phys_req *req, struct blkif_st *blkif, return rc; } -static void vbd_resize(struct blkif_st *blkif) +static void vbd_resize(struct xen_blkif *blkif) { struct vbd *vbd = &blkif->vbd; struct xenbus_transaction xbt; @@ -233,7 +233,7 @@ abort: /* * Notification from the guest OS. */ -static void blkif_notify_work(struct blkif_st *blkif) +static void blkif_notify_work(struct xen_blkif *blkif) { blkif->waiting_reqs = 1; wake_up(&blkif->wq); @@ -249,7 +249,7 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id) * SCHEDULER FUNCTIONS */ -static void print_stats(struct blkif_st *blkif) +static void print_stats(struct xen_blkif *blkif) { pr_debug("xen-blkback (%s): oo %3d | rd %4d | wr %4d | f %4d\n", current->comm, blkif->st_oo_req, @@ -262,7 +262,7 @@ static void print_stats(struct blkif_st *blkif) int xen_blkif_schedule(void *arg) { - struct blkif_st *blkif = arg; + struct xen_blkif *blkif = arg; struct vbd *vbd = &blkif->vbd; xen_blkif_get(blkif); @@ -451,7 +451,7 @@ static void end_block_io_op(struct bio *bio, int error) * (which has the sectors we want, number of them, grant references, etc), * and transmute it to the block API to hand it over to the proper block disk. */ -static int do_block_io_op(struct blkif_st *blkif) +static int do_block_io_op(struct xen_blkif *blkif) { union blkif_back_rings *blk_rings = &blkif->blk_rings; struct blkif_request req; @@ -512,9 +512,9 @@ static int do_block_io_op(struct blkif_st *blkif) * Transmutation of the 'struct blkif_request' to a proper 'struct bio' * and call the 'submit_bio' to pass it to the underlying storage. */ -static int dispatch_rw_block_io(struct blkif_st *blkif, - struct blkif_request *req, - struct pending_req *pending_req) +static int dispatch_rw_block_io(struct xen_blkif *blkif, + struct blkif_request *req, + struct pending_req *pending_req) { struct phys_req preq; struct seg_buf seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; @@ -692,7 +692,7 @@ static int dispatch_rw_block_io(struct blkif_st *blkif, /* * Put a response on the ring on how the operation fared. */ -static void make_response(struct blkif_st *blkif, u64 id, +static void make_response(struct xen_blkif *blkif, u64 id, unsigned short op, int st) { struct blkif_response resp; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index b0db6aabb5b8..722c048663d6 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -130,7 +130,7 @@ struct vbd { struct backend_info; -struct blkif_st { +struct xen_blkif { /* Unique identifier for this interface. */ domid_t domid; unsigned int handle; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index ba8d30662d19..f355f7a5d52d 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -23,7 +23,7 @@ struct backend_info { struct xenbus_device *dev; - struct blkif_st *blkif; + struct xen_blkif *blkif; struct xenbus_watch backend_watch; unsigned major; unsigned minor; @@ -41,7 +41,7 @@ struct xenbus_device *xen_blkbk_xenbus(struct backend_info *be) return be->dev; } -static int blkback_name(struct blkif_st *blkif, char *buf) +static int blkback_name(struct xen_blkif *blkif, char *buf) { char *devpath, *devname; struct xenbus_device *dev = blkif->be->dev; @@ -62,7 +62,7 @@ static int blkback_name(struct blkif_st *blkif, char *buf) return 0; } -static void xen_update_blkif_status(struct blkif_st *blkif) +static void xen_update_blkif_status(struct xen_blkif *blkif) { int err; char name[TASK_COMM_LEN]; @@ -101,9 +101,9 @@ static void xen_update_blkif_status(struct blkif_st *blkif) } } -static struct blkif_st *xen_blkif_alloc(domid_t domid) +static struct xen_blkif *xen_blkif_alloc(domid_t domid) { - struct blkif_st *blkif; + struct xen_blkif *blkif; blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); if (!blkif) @@ -120,7 +120,7 @@ static struct blkif_st *xen_blkif_alloc(domid_t domid) return blkif; } -static int map_frontend_page(struct blkif_st *blkif, unsigned long shared_page) +static int map_frontend_page(struct xen_blkif *blkif, unsigned long shared_page) { struct gnttab_map_grant_ref op; @@ -141,7 +141,7 @@ static int map_frontend_page(struct blkif_st *blkif, unsigned long shared_page) return 0; } -static void unmap_frontend_page(struct blkif_st *blkif) +static void unmap_frontend_page(struct xen_blkif *blkif) { struct gnttab_unmap_grant_ref op; @@ -152,7 +152,7 @@ static void unmap_frontend_page(struct blkif_st *blkif) BUG(); } -static int xen_blkif_map(struct blkif_st *blkif, unsigned long shared_page, +static int xen_blkif_map(struct xen_blkif *blkif, unsigned long shared_page, unsigned int evtchn) { int err; @@ -211,7 +211,7 @@ static int xen_blkif_map(struct blkif_st *blkif, unsigned long shared_page, return 0; } -static void xen_blkif_disconnect(struct blkif_st *blkif) +static void xen_blkif_disconnect(struct xen_blkif *blkif) { if (blkif->xenblkd) { kthread_stop(blkif->xenblkd); @@ -234,7 +234,7 @@ static void xen_blkif_disconnect(struct blkif_st *blkif) } } -void xen_blkif_free(struct blkif_st *blkif) +void xen_blkif_free(struct xen_blkif *blkif) { if (!atomic_dec_and_test(&blkif->refcnt)) BUG(); @@ -244,7 +244,7 @@ void xen_blkif_free(struct blkif_st *blkif) int __init xen_blkif_interface_init(void) { xen_blkif_cachep = kmem_cache_create("blkif_cache", - sizeof(struct blkif_st), + sizeof(struct xen_blkif), 0, 0, NULL); if (!xen_blkif_cachep) return -ENOMEM; @@ -332,7 +332,7 @@ static void vbd_free(struct vbd *vbd) vbd->bdev = NULL; } -static int vbd_create(struct blkif_st *blkif, blkif_vdev_t handle, +static int vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, unsigned major, unsigned minor, int readonly, int cdrom) { -- cgit v1.2.3 From 3d814731ba67f9514bdf380c1b95dd852ac82a2f Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:53:56 -0400 Subject: xen/blkback: Prefix 'vbd' with 'xen' in structs and functions. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 20 ++++++++++---------- drivers/block/xen-blkback/common.h | 4 ++-- drivers/block/xen-blkback/xenbus.c | 34 +++++++++++++++++----------------- 3 files changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index d438781ecc7c..1e454a30e4e1 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -166,10 +166,10 @@ static void free_req(struct pending_req *req) /* * Routines for managing virtual block devices (vbds). */ -static int vbd_translate(struct phys_req *req, struct xen_blkif *blkif, - int operation) +static int xen_vbd_translate(struct phys_req *req, struct xen_blkif *blkif, + int operation) { - struct vbd *vbd = &blkif->vbd; + struct xen_vbd *vbd = &blkif->vbd; int rc = -EACCES; if ((operation != READ) && vbd->readonly) @@ -186,9 +186,9 @@ static int vbd_translate(struct phys_req *req, struct xen_blkif *blkif, return rc; } -static void vbd_resize(struct xen_blkif *blkif) +static void xen_vbd_resize(struct xen_blkif *blkif) { - struct vbd *vbd = &blkif->vbd; + struct xen_vbd *vbd = &blkif->vbd; struct xenbus_transaction xbt; int err; struct xenbus_device *dev = xen_blkbk_xenbus(blkif->be); @@ -263,7 +263,7 @@ static void print_stats(struct xen_blkif *blkif) int xen_blkif_schedule(void *arg) { struct xen_blkif *blkif = arg; - struct vbd *vbd = &blkif->vbd; + struct xen_vbd *vbd = &blkif->vbd; xen_blkif_get(blkif); @@ -271,7 +271,7 @@ int xen_blkif_schedule(void *arg) if (try_to_freeze()) continue; if (unlikely(vbd->size != vbd_sz(vbd))) - vbd_resize(blkif); + xen_vbd_resize(blkif); wait_event_interruptible( blkif->wq, @@ -538,7 +538,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, blkif->st_f_req++; operation = WRITE_FLUSH; /* - * The frontend likes to set this to -1, which vbd_translate + * The frontend likes to set this to -1, which xen_vbd_translate * is alergic too. */ req->u.rw.sector_number = 0; @@ -580,7 +580,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, } - if (vbd_translate(&preq, blkif, operation) != 0) { + if (xen_vbd_translate(&preq, blkif, operation) != 0) { pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n", operation == READ ? "read" : "write", preq.sector_number, @@ -589,7 +589,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, } /* - * This check _MUST_ be done after vbd_translate as the preq.bdev + * This check _MUST_ be done after xen_vbd_translate as the preq.bdev * is set there. */ for (i = 0; i < nseg; i++) { diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 722c048663d6..1e4ccdeadef3 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -113,7 +113,7 @@ enum blkif_protocol { BLKIF_PROTOCOL_X86_64 = 3, }; -struct vbd { +struct xen_vbd { /* What the domain refers to this vbd as. */ blkif_vdev_t handle; /* Non-zero -> read-only */ @@ -141,7 +141,7 @@ struct xen_blkif { union blkif_back_rings blk_rings; struct vm_struct *blk_ring_area; /* The VBD attached to this interface. */ - struct vbd vbd; + struct xen_vbd vbd; /* Back pointer to the backend_info. */ struct backend_info *be; /* Private fields. */ diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index f355f7a5d52d..e470d8869053 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -275,7 +275,7 @@ VBD_SHOW(f_req, "%d\n", be->blkif->st_f_req); VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect); VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect); -static struct attribute *vbdstat_attrs[] = { +static struct attribute *xen_vbdstat_attrs[] = { &dev_attr_oo_req.attr, &dev_attr_rd_req.attr, &dev_attr_wr_req.attr, @@ -285,9 +285,9 @@ static struct attribute *vbdstat_attrs[] = { NULL }; -static struct attribute_group vbdstat_group = { +static struct attribute_group xen_vbdstat_group = { .name = "statistics", - .attrs = vbdstat_attrs, + .attrs = xen_vbdstat_attrs, }; VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); @@ -305,13 +305,13 @@ int xenvbd_sysfs_addif(struct xenbus_device *dev) if (error) goto fail2; - error = sysfs_create_group(&dev->dev.kobj, &vbdstat_group); + error = sysfs_create_group(&dev->dev.kobj, &xen_vbdstat_group); if (error) goto fail3; return 0; -fail3: sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); +fail3: sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); fail2: device_remove_file(&dev->dev, &dev_attr_mode); fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); return error; @@ -319,24 +319,24 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); void xenvbd_sysfs_delif(struct xenbus_device *dev) { - sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); + sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); device_remove_file(&dev->dev, &dev_attr_mode); device_remove_file(&dev->dev, &dev_attr_physical_device); } -static void vbd_free(struct vbd *vbd) +static void xen_vbd_free(struct xen_vbd *vbd) { if (vbd->bdev) blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE); vbd->bdev = NULL; } -static int vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, - unsigned major, unsigned minor, int readonly, - int cdrom) +static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, + unsigned major, unsigned minor, int readonly, + int cdrom) { - struct vbd *vbd; + struct xen_vbd *vbd; struct block_device *bdev; struct request_queue *q; @@ -351,7 +351,7 @@ static int vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, FMODE_READ : FMODE_WRITE, NULL); if (IS_ERR(bdev)) { - DPRINTK("vbd_create: device %08x could not be opened.\n", + DPRINTK("xen_vbd_create: device %08x could not be opened.\n", vbd->pdevice); return -ENOENT; } @@ -360,9 +360,9 @@ static int vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, vbd->size = vbd_sz(vbd); if (vbd->bdev->bd_disk == NULL) { - DPRINTK("vbd_create: device %08x doesn't exist.\n", + DPRINTK("xen_vbd_create: device %08x doesn't exist.\n", vbd->pdevice); - vbd_free(vbd); + xen_vbd_free(vbd); return -ENOENT; } @@ -396,7 +396,7 @@ static int xen_blkbk_remove(struct xenbus_device *dev) if (be->blkif) { xen_blkif_disconnect(be->blkif); - vbd_free(&be->blkif->vbd); + xen_vbd_free(&be->blkif->vbd); xen_blkif_free(be->blkif); be->blkif = NULL; } @@ -535,7 +535,7 @@ static void backend_changed(struct xenbus_watch *watch, be->major = major; be->minor = minor; - err = vbd_create(be->blkif, handle, major, minor, + err = xen_vbd_create(be->blkif, handle, major, minor, (NULL == strchr(be->mode, 'w')), cdrom); if (err) { be->major = 0; @@ -546,7 +546,7 @@ static void backend_changed(struct xenbus_watch *watch, err = xenvbd_sysfs_addif(dev); if (err) { - vbd_free(&be->blkif->vbd); + xen_vbd_free(&be->blkif->vbd); be->major = 0; be->minor = 0; xenbus_dev_fatal(dev, err, "creating sysfs entries"); -- cgit v1.2.3 From 5a577e38724226e06337bc8361f492b6bb76b9a5 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 16:58:21 -0400 Subject: xen/blkback: Add the prefix XEN in the common.h. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/common.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 1e4ccdeadef3..9e40b283a468 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -24,8 +24,8 @@ * IN THE SOFTWARE. */ -#ifndef __BLKIF__BACKEND__COMMON_H__ -#define __BLKIF__BACKEND__COMMON_H__ +#ifndef __XEN_BLKIF__BACKEND__COMMON_H__ +#define __XEN_BLKIF__BACKEND__COMMON_H__ #include #include @@ -230,4 +230,4 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, dst->u.rw.seg[i] = src->seg[i]; } -#endif /* __BLKIF__BACKEND__COMMON_H__ */ +#endif /* __XEN_BLKIF__BACKEND__COMMON_H__ */ -- cgit v1.2.3 From cca537af7d6defe8001c2229da738f8a3c934fc0 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 17:23:30 -0400 Subject: xen/blkback: if log_stats is enabled print out the data. And not depend on the driver being built with -DDEBUG flag. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 1e454a30e4e1..9dee5454740f 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -251,7 +251,7 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id) static void print_stats(struct xen_blkif *blkif) { - pr_debug("xen-blkback (%s): oo %3d | rd %4d | wr %4d | f %4d\n", + pr_info("xen-blkback (%s): oo %3d | rd %4d | wr %4d | f %4d\n", current->comm, blkif->st_oo_req, blkif->st_rd_req, blkif->st_wr_req, blkif->st_f_req); blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); -- cgit v1.2.3 From 5185432277ddf5bd91ad5af29cd1945f25ed10fc Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 12 May 2011 18:02:28 -0400 Subject: xen/blkback: Align the tabs on the structure. The recent changes caused this field of the structure to be offset a bit. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/xenbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index e470d8869053..34570823355b 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -23,7 +23,7 @@ struct backend_info { struct xenbus_device *dev; - struct xen_blkif *blkif; + struct xen_blkif *blkif; struct xenbus_watch backend_watch; unsigned major; unsigned minor; -- cgit v1.2.3 From 496b318eb65558c1a3a4fe882cb9da6d1dc6493a Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Fri, 13 May 2011 09:45:40 -0400 Subject: xen/blkback: fix xenbus_transaction_start() hang caused by double xenbus_transaction_end() vbd_resize() up_read()'s xs_state.suspend_mutex twice in a row via double xenbus_transaction_end() calls. The next down_read() in xenbus_transaction_start() (at eg. the next resize attempt) hangs. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=618317 Acked-by: Jan Beulich Acked-by: Ian Campbell Signed-off-by: Laszlo Ersek Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 9dee5454740f..dba55e3a4a86 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -226,6 +226,7 @@ again: goto again; if (err) pr_warn(DRV_PFX "Error ending transaction"); + return; abort: xenbus_transaction_end(xbt, 1); } -- cgit v1.2.3 From 8ab521506c4dbb144f0c04c55e3d8bec42c1b2b9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 17 May 2011 11:07:05 +0100 Subject: xen/blkback: don't fail empty barrier requests The sector number on empty barrier requests may (will?) be -1, which, given that it's being treated as unsigned 64-bit quantity, will almost always exceed the actual (virtual) disk's size. Inspired by Konrad's "When writting barriers set the sector number to zero...". While at it also add overflow checking to the math in vbd_translate(). Signed-off-by: Jan Beulich Signed-off-by: Konrad Rzeszutek Wilk --- drivers/block/xen-blkback/blkback.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/block') diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index dba55e3a4a86..c73910cc28c9 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -175,8 +175,14 @@ static int xen_vbd_translate(struct phys_req *req, struct xen_blkif *blkif, if ((operation != READ) && vbd->readonly) goto out; - if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) - goto out; + if (likely(req->nr_sects)) { + blkif_sector_t end = req->sector_number + req->nr_sects; + + if (unlikely(end < req->sector_number)) + goto out; + if (unlikely(end > vbd_sz(vbd))) + goto out; + } req->dev = vbd->pdevice; req->bdev = vbd->bdev; @@ -538,11 +544,6 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, case BLKIF_OP_FLUSH_DISKCACHE: blkif->st_f_req++; operation = WRITE_FLUSH; - /* - * The frontend likes to set this to -1, which xen_vbd_translate - * is alergic too. - */ - req->u.rw.sector_number = 0; break; case BLKIF_OP_WRITE_BARRIER: default: -- cgit v1.2.3