nbd: move initialization out of kernel thread

Send all of the initialization ioctls from the SPDK thread running
spdk_nbd_start(), rather than in the pthread spawned to handle the
blocking NBD_DO_IT ioctl.

This allows the parameter to the pthread to be a single value (dev_fd),
rather than a pointer to the whole spdk_nbd_disk, which fixes a race on
shutdown where the main thread is freeing the spdk_nbd_disk while the
kernel thread is accessing nbd->dev_fd to send the cleanup ioctls.

Change-Id: Ibe5ca4abac97ac567b294da1f8a92f12eece45b8
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/391021
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Daniel Verkamp 2017-12-08 12:32:13 -07:00 committed by Jim Harris
parent fcccf16767
commit 6bf92c33e5

View File

@ -501,32 +501,14 @@ spdk_nbd_poll(void *arg)
static void *
nbd_start_kernel(void *arg)
{
struct spdk_nbd_disk *nbd = arg;
int rc;
char buf[64];
int dev_fd = (int)(intptr_t)arg;
spdk_unaffinitize_thread();
rc = ioctl(nbd->dev_fd, NBD_SET_SOCK, nbd->kernel_sp_fd);
if (rc == -1) {
spdk_strerror_r(errno, buf, sizeof(buf));
SPDK_ERRLOG("ioctl(NBD_SET_SOCK) failed: %s\n", buf);
pthread_exit(NULL);
}
#ifdef NBD_FLAG_SEND_TRIM
rc = ioctl(nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM);
if (rc == -1) {
spdk_strerror_r(errno, buf, sizeof(buf));
SPDK_ERRLOG("ioctl(NBD_SET_FLAGS) failed: %s\n", buf);
pthread_exit(NULL);
}
#endif
/* This will block in the kernel until we close the spdk_sp_fd. */
ioctl(nbd->dev_fd, NBD_DO_IT);
ioctl(nbd->dev_fd, NBD_CLEAR_QUE);
ioctl(nbd->dev_fd, NBD_CLEAR_SOCK);
ioctl(dev_fd, NBD_DO_IT);
ioctl(dev_fd, NBD_CLEAR_QUE);
ioctl(dev_fd, NBD_CLEAR_SOCK);
pthread_exit(NULL);
}
@ -616,7 +598,23 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path)
printf("Enabling kernel access to bdev %s via %s\n", spdk_bdev_get_name(bdev), nbd_path);
rc = pthread_create(&tid, NULL, &nbd_start_kernel, nbd);
rc = ioctl(nbd->dev_fd, NBD_SET_SOCK, nbd->kernel_sp_fd);
if (rc == -1) {
spdk_strerror_r(errno, buf, sizeof(buf));
SPDK_ERRLOG("ioctl(NBD_SET_SOCK) failed: %s\n", buf);
goto err;
}
#ifdef NBD_FLAG_SEND_TRIM
rc = ioctl(nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM);
if (rc == -1) {
spdk_strerror_r(errno, buf, sizeof(buf));
SPDK_ERRLOG("ioctl(NBD_SET_FLAGS) failed: %s\n", buf);
goto err;
}
#endif
rc = pthread_create(&tid, NULL, nbd_start_kernel, (void *)(intptr_t)nbd->dev_fd);
if (rc != 0) {
spdk_strerror_r(rc, buf, sizeof(buf));
SPDK_ERRLOG("could not create thread: %s\n", buf);