From a3d17a18e59a22c7be99d6e82910af29568d0057 Mon Sep 17 00:00:00 2001 From: Jake Wires Date: Fri, 23 Feb 2007 17:26:07 -0800 Subject: [TAPDISK] honor read-only attributes when creating tap-based VBDs Signed-off-by: Jake Wires --- tools/blktap/drivers/blktapctrl.c | 2 +- tools/blktap/drivers/block-qcow.c | 2 +- tools/blktap/drivers/tapdisk.c | 40 ++++++++++++++++++++++++++++----------- tools/blktap/drivers/tapdisk.h | 1 + tools/blktap/lib/blktaplib.h | 1 + tools/blktap/lib/xenbus.c | 7 +++++-- 6 files changed, 38 insertions(+), 15 deletions(-) (limited to 'tools/blktap') diff --git a/tools/blktap/drivers/blktapctrl.c b/tools/blktap/drivers/blktapctrl.c index f2022fcc97..5f78cede2a 100644 --- a/tools/blktap/drivers/blktapctrl.c +++ b/tools/blktap/drivers/blktapctrl.c @@ -303,6 +303,7 @@ static int write_msg(int fd, int msgtype, void *ptr, void *ptr2) msg->type = CTLMSG_PARAMS; msg->len = msglen; msg->drivertype = blkif->drivertype; + msg->readonly = blkif->readonly; gettimeofday(&timeout, NULL); msg->cookie = blkif->cookie; @@ -410,7 +411,6 @@ static int read_msg(int fd, int msgtype, void *ptr) if (select(fd+1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout) > 0) { ret = read(fd, buf, msglen); - } if (ret > 0) { msg = (msg_hdr_t *)buf; diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c index 185c670111..36f77e6f05 100644 --- a/tools/blktap/drivers/block-qcow.c +++ b/tools/blktap/drivers/block-qcow.c @@ -422,7 +422,7 @@ static int qtruncate(int fd, off_t length, int sparse) return -1; if (S_ISBLK(st.st_mode)) return 0; - + sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; rem = st.st_size % DEFAULT_SECTOR_SIZE; diff --git a/tools/blktap/drivers/tapdisk.c b/tools/blktap/drivers/tapdisk.c index 965dbd9b7d..954901b2a8 100644 --- a/tools/blktap/drivers/tapdisk.c +++ b/tools/blktap/drivers/tapdisk.c @@ -268,7 +268,8 @@ static int map_new_dev(struct td_state *s, int minor) } static struct disk_driver *disk_init(struct td_state *s, - struct tap_disk *drv, char *name) + struct tap_disk *drv, + char *name, td_flag_t flags) { struct disk_driver *dd; @@ -285,14 +286,17 @@ static struct disk_driver *disk_init(struct td_state *s, dd->drv = drv; dd->td_state = s; dd->name = name; + dd->flags = flags; return dd; } -static int open_disk(struct td_state *s, struct tap_disk *drv, char *path) +static int open_disk(struct td_state *s, + struct tap_disk *drv, char *path, td_flag_t flags) { int err; char *dup; + td_flag_t pflags; struct disk_id id; struct disk_driver *d; @@ -301,16 +305,17 @@ static int open_disk(struct td_state *s, struct tap_disk *drv, char *path) return -ENOMEM; memset(&id, 0, sizeof(struct disk_id)); - s->disks = d = disk_init(s, drv, dup); + s->disks = d = disk_init(s, drv, dup, flags); if (!d) return -ENOMEM; - err = drv->td_open(d, path, 0); + err = drv->td_open(d, path, flags); if (err) { free_driver(d); s->disks = NULL; return -ENOMEM; } + pflags = flags | TD_RDONLY; /* load backing files as necessary */ while ((err = d->drv->td_get_parent_id(d, &id)) == 0) { @@ -324,11 +329,11 @@ static int open_disk(struct td_state *s, struct tap_disk *drv, char *path) if (!dup) goto fail; - new = disk_init(s, get_driver(id.drivertype), dup); + new = disk_init(s, get_driver(id.drivertype), dup, pflags); if (!new) goto fail; - err = new->drv->td_open(new, new->name, TD_RDONLY); + err = new->drv->td_open(new, new->name, pflags); if (err) goto fail; @@ -342,6 +347,8 @@ static int open_disk(struct td_state *s, struct tap_disk *drv, char *path) free(id.name); } + s->info |= ((flags & TD_RDONLY) ? VDISK_READONLY : 0); + if (err >= 0) return 0; @@ -404,7 +411,8 @@ static int read_msg(char *buf) goto params_done; /*Open file*/ - ret = open_disk(s, drv, path); + ret = open_disk(s, drv, path, + ((msg->readonly) ? TD_RDONLY : 0)); if (ret) goto params_done; @@ -510,7 +518,8 @@ void io_done(struct disk_driver *dd, int sid) if (!run) return; /*We have received signal to close*/ - if (drv->td_do_callbacks(dd, sid) > 0) kick_responses(dd->td_state); + if (sid > MAX_IOFD || drv->td_do_callbacks(dd, sid) > 0) + kick_responses(dd->td_state); return; } @@ -661,6 +670,12 @@ static void get_io_request(struct td_state *s) sector_nr = req->sector_number; } + if ((dd->flags & TD_RDONLY) && + (req->operation == BLKIF_OP_WRITE)) { + blkif->pending_list[idx].status = BLKIF_RSP_ERROR; + goto send_response; + } + for (i = start_seg; i < req->nr_segments; i++) { nsects = req->seg[i].last_sect - req->seg[i].first_sect + 1; @@ -726,10 +741,12 @@ static void get_io_request(struct td_state *s) } sector_nr += nsects; } + send_response: blkif->pending_list[idx].submitting = 0; /* force write_rsp_to_ring for synchronous case */ if (blkif->pending_list[idx].secs_pending == 0) - dd->early += send_responses(dd, 0, 0, 0, idx, (void *)0); + dd->early += send_responses(dd, 0, 0, 0, idx, + (void *)(long)0); } out: @@ -737,7 +754,7 @@ static void get_io_request(struct td_state *s) td_for_each_disk(s, dd) { dd->early += dd->drv->td_submit(dd); if (dd->early > 0) { - io_done(dd, 10); + io_done(dd, MAX_IOFD + 1); dd->early = 0; } } @@ -820,7 +837,8 @@ int main(int argc, char *argv[]) dd->early += dd->drv->td_submit(dd); if (dd->early > 0) { - io_done(dd, 10); + io_done(dd, + MAX_IOFD + 1); dd->early = 0; } } diff --git a/tools/blktap/drivers/tapdisk.h b/tools/blktap/drivers/tapdisk.h index b76d46cce5..5c68a5e9c8 100644 --- a/tools/blktap/drivers/tapdisk.h +++ b/tools/blktap/drivers/tapdisk.h @@ -94,6 +94,7 @@ struct disk_driver { int early; char *name; void *private; + td_flag_t flags; int io_fd[MAX_IOFD]; struct tap_disk *drv; struct td_state *td_state; diff --git a/tools/blktap/lib/blktaplib.h b/tools/blktap/lib/blktaplib.h index 0ba3c04ec8..078a293185 100644 --- a/tools/blktap/lib/blktaplib.h +++ b/tools/blktap/lib/blktaplib.h @@ -173,6 +173,7 @@ typedef struct msg_hdr { uint16_t len; uint16_t drivertype; uint16_t cookie; + uint8_t readonly; } msg_hdr_t; typedef struct msg_newdev { diff --git a/tools/blktap/lib/xenbus.c b/tools/blktap/lib/xenbus.c index d50e492784..fb36e748fe 100644 --- a/tools/blktap/lib/xenbus.c +++ b/tools/blktap/lib/xenbus.c @@ -177,8 +177,11 @@ static void ueblktap_setup(struct xs_handle *h, char *bepath) } /* Check to see if device is to be opened read-only. */ - asprintf(&path, "%s/%s", bepath, "read-only"); - if (xs_exists(h, path)) + deverr = xs_gather(h, bepath, "mode", NULL, &path, NULL); + if (deverr) { + DPRINTF("ERROR: could not find read/write mode\n"); + goto fail; + } else if (path[0] == 'r') be->readonly = 1; if (be->blkif == NULL) { -- cgit v1.2.3