diff --git a/control/tap-ctl-info.c b/control/tap-ctl-info.c index 813de389..276b7d7e 100644 --- a/control/tap-ctl-info.c +++ b/control/tap-ctl-info.c @@ -25,7 +25,8 @@ #include "tap-ctl.h" int tap_ctl_info(pid_t pid, unsigned long long *sectors, - unsigned int *sector_size, unsigned int *info, const int minor) + unsigned int *sector_size, unsigned int *info, + bool * discard_supported, const int minor) { tapdisk_message_t message; int err; @@ -49,6 +50,7 @@ int tap_ctl_info(pid_t pid, unsigned long long *sectors, *sectors = message.u.image.sectors; *sector_size = message.u.image.sector_size; *info = message.u.image.info; + *discard_supported = message.u.image.discard_supported; return 0; } else if (TAPDISK_MESSAGE_ERROR == message.type) { return -message.u.response.error; diff --git a/drivers/block-aio.c b/drivers/block-aio.c index 4488c0dd..426d8e48 100644 --- a/drivers/block-aio.c +++ b/drivers/block-aio.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "tapdisk.h" #include "tapdisk-driver.h" @@ -82,6 +83,11 @@ static int tdaio_get_image_info(int fd, td_disk_info_t *info) /*Local file? try fstat instead*/ info->size = (stat.st_size >> SECTOR_SHIFT); info->sector_size = DEFAULT_SECTOR_SIZE; + + if(is_hole_punching_supported_for_fd(fd)) { + info->discard_supported = true; + } + DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " "sector_shift [%llu]\n", (long long unsigned)(info->size << SECTOR_SHIFT), @@ -212,6 +218,33 @@ void tdaio_queue_write(td_driver_t *driver, td_request_t treq) td_complete_request(treq, -EBUSY); } +void tdaio_discard(td_driver_t *driver, td_request_t treq) +{ + int rc; + off64_t size; + off64_t offset; + struct tdaio_state *prv; + + if (driver->info.discard_supported != true) { + td_complete_request(treq, -EOPNOTSUPP); + return; + } + + prv = (struct tdaio_state *)driver->data; + size = treq.vreq->discard_nr_sectors * driver->info.sector_size; + offset = treq.vreq->sec * driver->info.sector_size; + + rc = fallocate64(prv->fd, (FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE), offset, size); + // Upper layers will retry on EINTR + + // ToDo: Remove the following debug statement after feeling confident + DPRINTF("fallocate64(%d, %d, %" PRIu64 ", %" PRIu64 ") returned %d", prv->fd, + (FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE), offset, size, rc); + + td_complete_request(treq, rc); + return; +} + int tdaio_close(td_driver_t *driver) { struct tdaio_state *prv = (struct tdaio_state *)driver->data; @@ -253,6 +286,7 @@ struct tap_disk tapdisk_aio = { .td_close = tdaio_close, .td_queue_read = tdaio_queue_read, .td_queue_write = tdaio_queue_write, + .td_queue_discard = tdaio_discard, .td_get_parent_id = tdaio_get_parent_id, .td_validate_parent = tdaio_validate_parent, .td_debug = NULL, diff --git a/drivers/tapdisk-control.c b/drivers/tapdisk-control.c index 70bcb67e..8f11564c 100644 --- a/drivers/tapdisk-control.c +++ b/drivers/tapdisk-control.c @@ -1193,6 +1193,7 @@ tapdisk_control_disk_info( image->sectors = vbd->disk_info.size; image->sector_size = vbd->disk_info.sector_size; image->info = vbd->disk_info.info; + image->discard_supported = vbd->disk_info.discard_supported; } return err; } diff --git a/drivers/tapdisk-image.c b/drivers/tapdisk-image.c index 448555d9..b9732037 100644 --- a/drivers/tapdisk-image.c +++ b/drivers/tapdisk-image.c @@ -94,15 +94,17 @@ tapdisk_image_check_td_request(td_image_t *image, td_request_t treq) info = &image->info; rdonly = td_flag_test(image->flags, TD_OPEN_RDONLY); - if (treq.op != TD_OP_READ && treq.op != TD_OP_WRITE) + if (treq.op != TD_OP_READ && treq.op != TD_OP_WRITE && + treq.op != TD_OP_DISCARD) goto fail; - if (treq.op == TD_OP_WRITE && rdonly) { + if ((treq.op == TD_OP_WRITE || treq.op == TD_OP_DISCARD) && rdonly) { err = -EPERM; goto fail; } - if (treq.secs <= 0 || treq.sec + treq.secs > info->size) + if ((treq.secs <= 0 || treq.sec + treq.secs > info->size) && + treq.op != TD_OP_DISCARD) goto fail; return 0; @@ -140,6 +142,9 @@ tapdisk_image_check_request(td_image_t *image, td_vbd_request_t *vreq) secs += vreq->iov[i].secs; switch (vreq->op) { + case TD_OP_DISCARD: + secs = vreq->discard_nr_sectors; + /* fall through */ case TD_OP_WRITE: if (rdonly) { err = -EPERM; diff --git a/drivers/tapdisk-interface.c b/drivers/tapdisk-interface.c index 96ef2dfb..7ba14de6 100644 --- a/drivers/tapdisk-interface.c +++ b/drivers/tapdisk-interface.c @@ -236,6 +236,42 @@ td_queue_read(td_image_t *image, td_request_t treq) td_complete_request(treq, err); } + +void +td_queue_discard(td_image_t *image, td_request_t treq) +{ + int err; + td_driver_t *driver; + + driver = image->driver; + if (!driver) { + err = -ENODEV; + goto fail; + } + + if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) { + err = -EBADF; + goto fail; + } + + if (!driver->ops->td_queue_discard) { + err = -EOPNOTSUPP; + goto fail; + } + + err = tapdisk_image_check_td_request(image, treq); + if (err) + goto fail; + + driver->ops->td_queue_discard(driver, treq); + + return; + +fail: + td_complete_request(treq, err); +} + + void td_forward_request(td_request_t treq) { diff --git a/drivers/tapdisk-interface.h b/drivers/tapdisk-interface.h index 458d74aa..8103b4fa 100644 --- a/drivers/tapdisk-interface.h +++ b/drivers/tapdisk-interface.h @@ -33,6 +33,7 @@ int td_set_quantum(td_image_t *, int); void td_queue_write(td_image_t *, td_request_t); void td_queue_read(td_image_t *, td_request_t); +void td_queue_discard(td_image_t *, td_request_t); void td_forward_request(td_request_t); void td_complete_request(td_request_t, int); diff --git a/drivers/tapdisk-utils.c b/drivers/tapdisk-utils.c index 768e6379..9a588bcb 100644 --- a/drivers/tapdisk-utils.c +++ b/drivers/tapdisk-utils.c @@ -25,11 +25,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #ifdef __linux__ @@ -431,3 +433,39 @@ inline long long timeval_to_us(struct timeval *tv) { return ((long long)tv->tv_sec * USEC_PER_SEC) + tv->tv_usec; } + +bool is_hole_punching_supported_for_fd(int fd) { + int rc; + int kernel_version; + struct statfs statfs_buf; + + rc = fstatfs(fd, &statfs_buf); + if (rc) + return false; + kernel_version = tapdisk_linux_version(); + if (-ENOSYS == kernel_version) + return false; + + // Support matrix according to man fallocate(2) + switch (statfs_buf.f_type) { +#ifdef BTRFS_SUPER_MAGIC + case BTRFS_SUPER_MAGIC: + return (kernel_version >= KERNEL_VERSION(3, 7, 0)); +#endif +#ifdef EXT4_SUPER_MAGIC + case EXT4_SUPER_MAGIC: + return (kernel_version >= KERNEL_VERSION(3, 0, 0)); +#endif +#ifdef TMPFS_SUPER_MAGIC + case TMPFS_SUPER_MAGIC: + return (kernel_version >= KERNEL_VERSION(3, 5, 0)); +#endif +#ifdef XFS_SUPER_MAGIC + case XFS_SUPER_MAGIC: + return (kernel_version >= KERNEL_VERSION(2, 6, 38)); +#endif + default: + break; + } + return false; +} diff --git a/drivers/tapdisk-utils.h b/drivers/tapdisk-utils.h index c3594f21..657728d9 100644 --- a/drivers/tapdisk-utils.h +++ b/drivers/tapdisk-utils.h @@ -19,6 +19,7 @@ #define _TAPDISK_UTILS_H_ #include +#include #include #include #include @@ -89,4 +90,10 @@ shm_destroy(struct shm *shm); inline long long timeval_to_us(struct timeval *tv); +/** + * Returns true if the filesystem that hosts the specified path is known to + * allow hole punching and thereby discard. + */ +bool is_hole_punching_supported_for_fd(int fd); + #endif diff --git a/drivers/tapdisk-vbd.c b/drivers/tapdisk-vbd.c index 99574700..718ada30 100644 --- a/drivers/tapdisk-vbd.c +++ b/drivers/tapdisk-vbd.c @@ -1363,6 +1363,10 @@ __tapdisk_vbd_reissue_td_request(td_vbd_t *vbd, case TD_OP_READ: td_queue_read(parent, treq); break; + + case TD_OP_DISCARD: + td_queue_discard(parent, treq); + break; } done: @@ -1485,6 +1489,19 @@ tapdisk_vbd_issue_request(td_vbd_t *vbd, td_vbd_request_t *vreq) goto fail; } + if(vreq->op==TD_OP_DISCARD) { + treq.sidx = 1; + treq.sec = sec; + treq.image = image; + treq.cb = tapdisk_vbd_complete_td_request; + treq.cb_data = NULL; + treq.vreq = vreq; + treq.op = TD_OP_DISCARD; + td_queue_discard(treq.image, treq); + err = 0; + goto out; + } + for (i = 0; i < vreq->iovcnt; i++) { struct td_iovec *iov = &vreq->iov[i]; @@ -1529,6 +1546,11 @@ tapdisk_vbd_issue_request(td_vbd_t *vbd, td_vbd_request_t *vreq) vbd->vdi_stats.stats->read_reqs_submitted++; td_queue_read(treq.image, treq); break; + + case TD_OP_DISCARD: + treq.op = TD_OP_DISCARD; + td_queue_discard(treq.image, treq); + break; } DBG(TLOG_DBG, "%s: req %s seg %d sec 0x%08"PRIx64" secs 0x%04x " diff --git a/drivers/tapdisk.h b/drivers/tapdisk.h index 40944a83..faaae69e 100644 --- a/drivers/tapdisk.h +++ b/drivers/tapdisk.h @@ -49,6 +49,7 @@ #include #include +#include #include "list.h" #include "compiler.h" @@ -74,6 +75,7 @@ extern unsigned int PAGE_SHIFT; #define TD_OP_READ 0 #define TD_OP_WRITE 1 +#define TD_OP_DISCARD 2 #define TD_OPEN_QUIET 0x00001 #define TD_OPEN_QUERY 0x00002 @@ -126,6 +128,7 @@ struct td_disk_info { td_sector_t size; long sector_size; uint32_t info; + bool discard_supported; }; struct td_iovec { @@ -155,6 +158,8 @@ struct td_vbd_request { td_vbd_t *vbd; struct list_head next; struct list_head *list_head; + + uint64_t discard_nr_sectors; }; struct td_request { @@ -188,6 +193,7 @@ struct tap_disk { int (*td_validate_parent) (td_driver_t *, td_driver_t *, td_flag_t); void (*td_queue_read) (td_driver_t *, td_request_t); void (*td_queue_write) (td_driver_t *, td_request_t); + void (*td_queue_discard) (td_driver_t *, td_request_t); void (*td_debug) (td_driver_t *); void (*td_stats) (td_driver_t *, td_stats_t *); diff --git a/drivers/td-ctx.c b/drivers/td-ctx.c index 2b340875..7c43ff41 100644 --- a/drivers/td-ctx.c +++ b/drivers/td-ctx.c @@ -125,6 +125,17 @@ xenio_pending_blkif(struct td_xenio_ctx * const ctx) dst->seg[i] = src->seg[i]; \ } +#define blkif_get_req_discard(dst, discard_src) \ +{ \ + /* assert(sizeof(blkif_request_discard_t)operation = src->operation; \ + discard_dst->flag = discard_src->flag; \ + discard_dst->id = discard_src->id; \ + discard_dst->sector_number = discard_src->sector_number; \ + discard_dst->nr_sectors = discard_src->nr_sectors; \ +} + /** * Utility function that retrieves a request using @idx as the ring index, * copying it to the @dst in a H/W independent way. @@ -149,6 +160,7 @@ xenio_blkif_get_request(struct td_xenblkif * const blkif, { blkif_request_t *src; src = RING_GET_REQUEST(&rings->native, idx); + // sizeof(blkif_request_t)>sizeof(blkif_request_discard_t) memcpy(dst, src, sizeof(blkif_request_t)); break; } @@ -157,7 +169,13 @@ xenio_blkif_get_request(struct td_xenblkif * const blkif, { blkif_x86_32_request_t *src; src = RING_GET_REQUEST(&rings->x86_32, idx); - blkif_get_req(dst, src); + if (src->operation==BLKIF_OP_DISCARD) { + blkif_x86_32_request_discard_t * discard_src; + discard_src = (blkif_x86_32_request_discard_t *) src; + blkif_get_req_discard(dst, discard_src); + } else { + blkif_get_req(dst, src); + } break; } @@ -165,7 +183,13 @@ xenio_blkif_get_request(struct td_xenblkif * const blkif, { blkif_x86_64_request_t *src; src = RING_GET_REQUEST(&rings->x86_64, idx); - blkif_get_req(dst, src); + if (src->operation==BLKIF_OP_DISCARD) { + blkif_x86_64_request_discard_t * discard_src; + discard_src = (blkif_x86_64_request_discard_t *) src; + blkif_get_req_discard(dst, discard_src); + } else { + blkif_get_req(dst, src); + } break; } diff --git a/drivers/td-req.c b/drivers/td-req.c index aea1a068..82c076e6 100644 --- a/drivers/td-req.c +++ b/drivers/td-req.c @@ -670,6 +670,37 @@ tapdisk_xenblkif_parse_request(struct td_xenblkif * const blkif, return err; } +static inline int +tapdisk_xenblkif_parse_request_discard(struct td_xenblkif * const blkif, + struct td_xenblkif_req * const req) +{ + int err = 0; + td_vbd_request_t *vreq; + blkif_request_discard_t * request_discard_msg; + + vreq = &req->vreq; + ASSERT(vreq); + + vreq->iov = 0; + vreq->iovcnt = 0; + vreq->sec = 0; + + request_discard_msg = (blkif_request_discard_t*)&req->msg; + vreq->discard_nr_sectors = request_discard_msg->nr_sectors; + vreq->sec = request_discard_msg->sector_number; + + /* + * TODO Isn't this kind of expensive to do for each requests? Why does + * the tapdisk need this in the first place? + */ + snprintf(req->name, sizeof(req->name), "xenvbd-%d-%d.%"SCNx64"", + blkif->domid, blkif->devid, request_discard_msg->id); + vreq->name = req->name; + vreq->token = blkif; + vreq->cb = __tapdisk_xenblkif_request_cb; + + return err; +} /** * Initialises the standard tapdisk request (td_vbd_request_t) from the @@ -710,6 +741,11 @@ tapdisk_xenblkif_make_vbd_request(struct td_xenblkif * const blkif, tapreq->prot = PROT_READ; vreq->op = TD_OP_WRITE; break; + case BLKIF_OP_DISCARD: + blkif->stats.xenvbd->st_ds_req++; + tapreq->prot = PROT_WRITE; + vreq->op = TD_OP_DISCARD; + break; default: RING_ERR(blkif, "req %lu: invalid request type %d\n", tapreq->msg.id, tapreq->msg.operation); @@ -723,7 +759,8 @@ tapdisk_xenblkif_make_vbd_request(struct td_xenblkif * const blkif, * Check that the number of segments is sane. */ if (unlikely((tapreq->msg.nr_segments == 0 && - tapreq->msg.operation != BLKIF_OP_WRITE_BARRIER) || + tapreq->msg.operation != BLKIF_OP_WRITE_BARRIER && + tapreq->msg.operation != BLKIF_OP_DISCARD) || tapreq->msg.nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { RING_ERR(blkif, "req %lu: bad number of segments in request (%d)\n", tapreq->msg.id, tapreq->msg.nr_segments); @@ -731,7 +768,9 @@ tapdisk_xenblkif_make_vbd_request(struct td_xenblkif * const blkif, goto out; } - if (likely(tapreq->msg.nr_segments)) + if (unlikely(tapreq->msg.operation == BLKIF_OP_DISCARD)) + err = tapdisk_xenblkif_parse_request_discard(blkif, tapreq); + else if (likely(tapreq->msg.nr_segments)) err = tapdisk_xenblkif_parse_request(blkif, tapreq); /* * If we only got one request from the ring and that was a barrier one, @@ -781,7 +820,8 @@ tapdisk_xenblkif_queue_request(struct td_xenblkif * const blkif, return err; } - if (likely(tapreq->msg.nr_segments)) { + if (likely(tapreq->msg.nr_segments || + tapreq->msg.operation == BLKIF_OP_DISCARD )) { err = tapdisk_vbd_queue_request(blkif->vbd, &tapreq->vreq); if (unlikely(err)) { /* TODO log error */ diff --git a/include/blktap3.h b/include/blktap3.h index 1e442448..d7f0f9ae 100644 --- a/include/blktap3.h +++ b/include/blktap3.h @@ -39,8 +39,7 @@ */ struct blkback_stats { /** - * BLKIF_OP_DISCARD, not currently supported in blktap3, should always - * be zero + * Received BLKIF_OP_DISCARD requests. */ unsigned long long st_ds_req; diff --git a/include/tap-ctl.h b/include/tap-ctl.h index b4248ffa..8d6db30b 100644 --- a/include/tap-ctl.h +++ b/include/tap-ctl.h @@ -176,7 +176,8 @@ int tap_ctl_disconnect_xenblkif(const pid_t pid, const domid_t domid, * */ int tap_ctl_info(pid_t pid, unsigned long long *sectors, unsigned int - *sector_size, unsigned int *info, const int minor); + *sector_size, unsigned int *info, bool *discard_supported, + const int minor); /** * Parses a type:/path/to/file string, storing the type and path to the output diff --git a/include/tapdisk-message.h b/include/tapdisk-message.h index 7d9bda77..388bd613 100644 --- a/include/tapdisk-message.h +++ b/include/tapdisk-message.h @@ -19,6 +19,7 @@ #define _TAPDISK_MESSAGE_H_ #include +#include #include /* @@ -70,6 +71,7 @@ struct tapdisk_message_image { uint64_t sectors; uint32_t sector_size; uint32_t info; + bool discard_supported; }; struct tapdisk_message_string { diff --git a/include/xen_blkif.h b/include/xen_blkif.h index ca3a65b1..5b67b9bf 100644 --- a/include/xen_blkif.h +++ b/include/xen_blkif.h @@ -26,12 +26,21 @@ struct blkif_x86_32_request { 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_request_discard { + uint8_t operation; /* BLKIF_OP_DISCARD */ + uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */ + blkif_vdev_t handle; /* was "handle" 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) */ + uint64_t nr_sectors; +}; 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_request_discard blkif_x86_32_request_discard_t; typedef struct blkif_x86_32_response blkif_x86_32_response_t; #pragma pack(pop) @@ -44,12 +53,22 @@ struct blkif_x86_64_request { 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_request_discard { + uint8_t operation; /* BLKIF_OP_DISCARD */ + uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */ + blkif_vdev_t _pad1; /* was "handle" for read/write requests */ + uint32_t _pad2; + uint64_t id; /* private guest value, echoed in resp */ + blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ + uint64_t nr_sectors; +}; 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_request_discard blkif_x86_64_request_discard_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); diff --git a/tapback/backend.c b/tapback/backend.c index 516fc430..426d284e 100644 --- a/tapback/backend.c +++ b/tapback/backend.c @@ -344,7 +344,7 @@ physical_device_changed(vbd_t *device) { * get the VBD parameters from the tapdisk */ if ((err = tap_ctl_info(device->tap->pid, &device->sectors, - &device->sector_size, &info, + &device->sector_size, &info, &device->discard_supported, device->minor))) { WARN(device, "error retrieving disk characteristics: %s\n", strerror(-err)); diff --git a/tapback/frontend.c b/tapback/frontend.c index 204687de..08c8767d 100644 --- a/tapback/frontend.c +++ b/tapback/frontend.c @@ -259,6 +259,10 @@ connect_frontend(vbd_t *device) { int err = 0; xs_transaction_t xst = XBT_NULL; bool abort_transaction = false; + unsigned int discard_granularity = 0; + unsigned int discard_alignment = 0; + int discard_secure = 0; + int feature_discard = 0; ASSERT(device); @@ -272,9 +276,47 @@ connect_frontend(vbd_t *device) { abort_transaction = true; /* - * FIXME blkback writes discard-granularity, discard-alignment, - * discard-secure, feature-discard but we don't. + * Prepare for discard */ + if (device->discard_supported == true && /* backing driver supports */ + device->backend->discard == true && /* discard enabled */ + device->mode == true && /* writable vbd */ + device->cdrom == false) { /* not a CD */ + INFO(device, "Discard enabled."); + discard_granularity = device->sector_size; + discard_alignment = 0; + discard_secure = 0; + feature_discard = 1; + } else + INFO(device, "Discard disabled."); + if ((err = tapback_device_printf(device, xst, "discard-granularity", + true, "%u", discard_granularity ))) { + WARN(device, "failed to write discard_granularity: %s\n", + strerror(-err)); + break; + } + + if ((err = tapback_device_printf(device, xst, "discard-alignment", + true, "%u", discard_alignment ))) { + WARN(device, "failed to write discard_alignment: %s\n", + strerror(-err)); + break; + } + + if ((err = tapback_device_printf(device, xst, "discard-secure", + true, "%d", discard_secure ))) { + WARN(device, "failed to write discard-secure: %s\n", + strerror(-err)); + break; + } + + if ((err = tapback_device_printf(device, xst, "feature-discard", + true, "%d", feature_discard ))) { + WARN(device, "failed to write feature_discard: %s\n", + strerror(-err)); + break; + } + /* * Write the number of sectors, sector size, info, and barrier support diff --git a/tapback/tapback.c b/tapback/tapback.c index 4cfd3217..8335e40c 100644 --- a/tapback/tapback.c +++ b/tapback/tapback.c @@ -219,7 +219,8 @@ tapback_write_pid(const char *pidfile) */ static inline backend_t * tapback_backend_create(const char *name, const char *pidfile, - const domid_t domid, const bool barrier) + const domid_t domid, const bool barrier, + const bool discard) { int err; int len; @@ -254,7 +255,8 @@ tapback_backend_create(const char *name, const char *pidfile, goto out; } - backend->barrier = barrier; + backend->barrier = barrier; + backend->discard = discard; backend->path = NULL; @@ -501,7 +503,8 @@ usage(FILE * const stream, const char * const prog) "\t[-d|--debug]\n" "\t[-h|--help]\n" "\t[-v|--verbose]\n" - "\t[-b]--nobarrier]\n" + "\t[-b]--nobarrier]\n" + "\t[-s]--nodiscard]\n" "\t[-n|--name]\n", prog); } @@ -567,7 +570,8 @@ int main(int argc, char **argv) int err = 0; backend_t *backend = NULL; domid_t opt_domid = 0; - bool opt_barrier = true; + bool opt_barrier = true; + bool opt_discard = true; if (access("/dev/xen/gntdev", F_OK ) == -1) { WARN(NULL, "grant device does not exist\n"); @@ -594,12 +598,13 @@ int main(int argc, char **argv) {"name", 0, NULL, 'n'}, {"pidfile", 0, NULL, 'p'}, {"domain", 0, NULL, 'x'}, - {"nobarrier", 0, NULL, 'b'}, + {"nobarrier", 0, NULL, 'b'}, + {"nodiscard", 0, NULL, 's'}, }; int c; - c = getopt_long(argc, argv, "hdvn:p:x:b", longopts, NULL); + c = getopt_long(argc, argv, "hdvn:p:x:b:s", longopts, NULL); if (c < 0) break; @@ -636,9 +641,14 @@ int main(int argc, char **argv) } INFO(NULL, "only serving domain %d\n", opt_domid); break; - case 'b': - opt_barrier = false; - break; + case 'b': + /* nobarrier */ + opt_barrier = false; + break; + case 's': + /* nodiscard */ + opt_discard = false; + break; case '?': goto usage; } @@ -673,7 +683,7 @@ int main(int argc, char **argv) } backend = tapback_backend_create(opt_name, opt_pidfile, opt_domid, - opt_barrier); + opt_barrier, opt_discard); if (!backend) { err = errno; WARN(NULL, "error creating back-end: %s\n", strerror(err)); diff --git a/tapback/tapback.h b/tapback/tapback.h index c28117e2..8659b3ef 100644 --- a/tapback/tapback.h +++ b/tapback/tapback.h @@ -195,6 +195,12 @@ typedef struct backend { * Tells whether we support write I/O barriers. */ bool barrier; + + /** + * Whether discard is supposed to be enabled if supported by the + * tapdisk. + */ + bool discard; } backend_t; /** @@ -271,6 +277,11 @@ typedef struct vbd { */ unsigned long long sectors; + /** + * Whether the backing driver supports discard, supplied by the tapdisk. + */ + bool discard_supported; + /** * VDISK_???, defined in include/xen/interface/io/blkif.h. */