summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve/block_if.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-03-23 14:36:53 +0000
committermav <mav@FreeBSD.org>2015-03-23 14:36:53 +0000
commit3ce68975f29c670c2a6b0d08841ef28de5d3d3c7 (patch)
treece5213af54c42bdb3c3600f5a6f985c6bf3dff82 /usr.sbin/bhyve/block_if.c
parent571ee1f33d97441d9d5b852dbc727c3d6121fa35 (diff)
downloadFreeBSD-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.c43
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, &sectsz)) {
@@ -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);
+}
OpenPOWER on IntegriCloud