aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/bhyve/block_if.c
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2015-03-13 16:43:52 +0000
committerAlexander Motin <mav@FreeBSD.org>2015-03-13 16:43:52 +0000
commit0b9d25c935136f0e5ea84b3de19633e42c8ef04e (patch)
tree871341493753f8126d7e9a503771a3a64a8d5d77 /usr.sbin/bhyve/block_if.c
parentdc9fa19b3b9d6ce5cdca1083f7d1e558805c9121 (diff)
Notes
Diffstat (limited to 'usr.sbin/bhyve/block_if.c')
-rw-r--r--usr.sbin/bhyve/block_if.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c
index e765987afaf4..de4302046789 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,17 @@ 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_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 +290,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 +347,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 +359,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 +375,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 +455,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 +663,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);
+}