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
This commit is contained in:
John Baldwin 2021-06-11 17:59:25 -07:00
parent 67d60dcce6
commit 8794846a91
2 changed files with 67 additions and 1 deletions

View File

@ -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 @@ blockif_open(nvlist_t *nvl, const char *ident)
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++)

View File

@ -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);