aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/bhyve
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2021-06-12 00:59:25 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2021-06-12 01:00:24 +0000
commit8794846a91c5429c612ba939c61ebf8f1ff1a628 (patch)
tree79c50bfd31e8b24862cda419318a0fc1da61c52e /usr.sbin/bhyve
parent67d60dcce62c08250dceedaf761cb48bc74c75a4 (diff)
downloadsrc-8794846a91c5429c612ba939c61ebf8f1ff1a628.tar.gz
src-8794846a91c5429c612ba939c61ebf8f1ff1a628.zip
bhyve: Add support for handling disk resize events to block_if.
Allow clients of blockif to register a resize callback handler. When a callback is registered, register an EVFILT_VNODE kevent watching the backing store for a change in the file's attributes. If the size has changed when the kevent fires, invoke the clients' callback. Currently resize detection is limited to backing stores that support EVFILT_VNODE kevents such as regular files. Reviewed by: grehan, markj MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D30504
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r--usr.sbin/bhyve/block_if.c63
-rw-r--r--usr.sbin/bhyve/block_if.h5
2 files changed, 67 insertions, 1 deletions
diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c
index ae09bc71d622..98c0f9f5f38b 100644
--- a/usr.sbin/bhyve/block_if.c
+++ b/usr.sbin/bhyve/block_if.c
@@ -115,6 +115,9 @@ struct blockif_ctxt {
pthread_cond_t bc_cond;
pthread_cond_t bc_paused_cond;
pthread_cond_t bc_work_done_cond;
+ blockif_resize_cb *bc_resize_cb;
+ void *bc_resize_cb_arg;
+ struct mevent *bc_resize_event;
/* Request elements and free/pending/busy queues */
TAILQ_HEAD(, blockif_elem) bc_freeq;
@@ -532,7 +535,7 @@ blockif_open(nvlist_t *nvl, const char *ident)
#ifndef WITHOUT_CAPSICUM
cap_rights_init(&rights, CAP_FSYNC, CAP_IOCTL, CAP_READ, CAP_SEEK,
- CAP_WRITE);
+ CAP_WRITE, CAP_FSTAT, CAP_EVENT);
if (ro)
cap_rights_clear(&rights, CAP_FSYNC, CAP_WRITE);
@@ -643,6 +646,62 @@ err:
return (NULL);
}
+static void
+blockif_resized(int fd, enum ev_type type, void *arg)
+{
+ struct blockif_ctxt *bc;
+ struct stat sb;
+
+ if (fstat(fd, &sb) != 0)
+ return;
+
+ bc = arg;
+ pthread_mutex_lock(&bc->bc_mtx);
+ if (sb.st_size != bc->bc_size) {
+ bc->bc_size = sb.st_size;
+ bc->bc_resize_cb(bc, bc->bc_resize_cb_arg, bc->bc_size);
+ }
+ pthread_mutex_unlock(&bc->bc_mtx);
+}
+
+int
+blockif_register_resize_callback(struct blockif_ctxt *bc, blockif_resize_cb *cb,
+ void *cb_arg)
+{
+ struct stat sb;
+ int err;
+
+ if (cb == NULL)
+ return (EINVAL);
+
+ pthread_mutex_lock(&bc->bc_mtx);
+ if (bc->bc_resize_cb != NULL) {
+ err = EBUSY;
+ goto out;
+ }
+
+ assert(bc->bc_closing == 0);
+
+ if (fstat(bc->bc_fd, &sb) != 0) {
+ err = errno;
+ goto out;
+ }
+
+ bc->bc_resize_event = mevent_add_flags(bc->bc_fd, EVF_VNODE,
+ EVFF_ATTRIB, blockif_resized, bc);
+ if (bc->bc_resize_event == NULL) {
+ err = ENXIO;
+ goto out;
+ }
+
+ bc->bc_resize_cb = cb;
+ bc->bc_resize_cb_arg = cb_arg;
+out:
+ pthread_mutex_unlock(&bc->bc_mtx);
+
+ return (err);
+}
+
static int
blockif_request(struct blockif_ctxt *bc, struct blockif_req *breq,
enum blockop op)
@@ -796,6 +855,8 @@ blockif_close(struct blockif_ctxt *bc)
*/
pthread_mutex_lock(&bc->bc_mtx);
bc->bc_closing = 1;
+ if (bc->bc_resize_event != NULL)
+ mevent_disable(bc->bc_resize_event);
pthread_mutex_unlock(&bc->bc_mtx);
pthread_cond_broadcast(&bc->bc_cond);
for (i = 0; i < BLOCKIF_NUMTHR; i++)
diff --git a/usr.sbin/bhyve/block_if.h b/usr.sbin/bhyve/block_if.h
index 87ae4d169969..0407ff43cf94 100644
--- a/usr.sbin/bhyve/block_if.h
+++ b/usr.sbin/bhyve/block_if.h
@@ -63,8 +63,13 @@ struct blockif_req {
};
struct blockif_ctxt;
+
+typedef void blockif_resize_cb(struct blockif_ctxt *, void *, size_t);
+
int blockif_legacy_config(nvlist_t *nvl, const char *opts);
struct blockif_ctxt *blockif_open(nvlist_t *nvl, const char *ident);
+int blockif_register_resize_callback(struct blockif_ctxt *bc,
+ blockif_resize_cb *cb, void *cb_arg);
off_t blockif_size(struct blockif_ctxt *bc);
void blockif_chs(struct blockif_ctxt *bc, uint16_t *c, uint8_t *h,
uint8_t *s);