diff options
author | mav <mav@FreeBSD.org> | 2015-03-23 14:36:53 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2015-03-23 14:36:53 +0000 |
commit | 3ce68975f29c670c2a6b0d08841ef28de5d3d3c7 (patch) | |
tree | ce5213af54c42bdb3c3600f5a6f985c6bf3dff82 /usr.sbin/bhyve/block_if.c | |
parent | 571ee1f33d97441d9d5b852dbc727c3d6121fa35 (diff) | |
download | FreeBSD-src-3ce68975f29c670c2a6b0d08841ef28de5d3d3c7.zip FreeBSD-src-3ce68975f29c670c2a6b0d08841ef28de5d3d3c7.tar.gz |
MFC r279957, r280017: Add DSM TRIM command support for virtual AHCI disks.
It works only for virtual disks backed by ZVOLs and raw devices supporting
BIO_DELETE. Virtual disks backed by files won't report this capability.
Relnotes: yes
Diffstat (limited to 'usr.sbin/bhyve/block_if.c')
-rw-r--r-- | usr.sbin/bhyve/block_if.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c index e765987..ffe2a47 100644 --- a/usr.sbin/bhyve/block_if.c +++ b/usr.sbin/bhyve/block_if.c @@ -59,7 +59,8 @@ __FBSDID("$FreeBSD$"); enum blockop { BOP_READ, BOP_WRITE, - BOP_FLUSH + BOP_FLUSH, + BOP_DELETE }; enum blockstat { @@ -81,6 +82,7 @@ struct blockif_ctxt { int bc_magic; int bc_fd; int bc_ischr; + int bc_candelete; int bc_rdonly; off_t bc_size; int bc_sectsz; @@ -172,6 +174,7 @@ static void blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be) { struct blockif_req *br; + off_t arg[2]; int err; br = be->be_req; @@ -197,6 +200,19 @@ blockif_proc(struct blockif_ctxt *bc, struct blockif_elem *be) } else if (fsync(bc->bc_fd)) err = errno; break; + case BOP_DELETE: + if (!bc->bc_candelete) + err = EOPNOTSUPP; + else if (bc->bc_rdonly) + err = EROFS; + else if (bc->bc_ischr) { + arg[0] = br->br_offset; + arg[1] = br->br_iov[0].iov_len; + if (ioctl(bc->bc_fd, DIOCGDELETE, arg)) + err = errno; + } else + err = EOPNOTSUPP; + break; default: err = EINVAL; break; @@ -276,9 +292,10 @@ blockif_open(const char *optstr, const char *ident) char *nopt, *xopts; struct blockif_ctxt *bc; struct stat sbuf; + struct diocgattr_arg arg; off_t size, psectsz, psectoff; int extra, fd, i, sectsz; - int nocache, sync, ro; + int nocache, sync, ro, candelete; pthread_once(&blockif_once, blockif_init); @@ -332,6 +349,7 @@ blockif_open(const char *optstr, const char *ident) size = sbuf.st_size; sectsz = DEV_BSIZE; psectsz = psectoff = 0; + candelete = 0; if (S_ISCHR(sbuf.st_mode)) { if (ioctl(fd, DIOCGMEDIASIZE, &size) < 0 || ioctl(fd, DIOCGSECTORSIZE, §sz)) { @@ -343,6 +361,10 @@ blockif_open(const char *optstr, const char *ident) assert(sectsz != 0); if (ioctl(fd, DIOCGSTRIPESIZE, &psectsz) == 0 && psectsz > 0) ioctl(fd, DIOCGSTRIPEOFFSET, &psectoff); + strlcpy(arg.name, "GEOM::candelete", sizeof(arg.name)); + arg.len = sizeof(arg.value.i); + if (ioctl(fd, DIOCGATTR, &arg) == 0) + candelete = arg.value.i; } else psectsz = sbuf.st_blksize; @@ -355,6 +377,7 @@ blockif_open(const char *optstr, const char *ident) bc->bc_magic = BLOCKIF_SIG; bc->bc_fd = fd; bc->bc_ischr = S_ISCHR(sbuf.st_mode); + bc->bc_candelete = candelete; bc->bc_rdonly = ro; bc->bc_size = size; bc->bc_sectsz = sectsz; @@ -434,6 +457,14 @@ blockif_flush(struct blockif_ctxt *bc, struct blockif_req *breq) } int +blockif_delete(struct blockif_ctxt *bc, struct blockif_req *breq) +{ + + assert(bc->bc_magic == BLOCKIF_SIG); + return (blockif_request(bc, breq, BOP_DELETE)); +} + +int blockif_cancel(struct blockif_ctxt *bc, struct blockif_req *breq) { struct blockif_elem *be; @@ -634,3 +665,11 @@ blockif_is_ro(struct blockif_ctxt *bc) assert(bc->bc_magic == BLOCKIF_SIG); return (bc->bc_rdonly); } + +int +blockif_candelete(struct blockif_ctxt *bc) +{ + + assert(bc->bc_magic == BLOCKIF_SIG); + return (bc->bc_candelete); +} |