From 637cbfeeefd5633e5e2906c73e50657561605730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Thu, 3 May 2007 03:37:04 +0000 Subject: [PATCH] Add debug output. Implement connect/teardown. Added a workaround for BONE wanting to keep locked pages around when connect() fails (TCP teardown-> "trying to delete area in use!"). But doesn't seem to wait long enough. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20991 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/drivers/disk/virtual/nbd/nbd.c | 116 ++++++++++++++++-- 1 file changed, 108 insertions(+), 8 deletions(-) diff --git a/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c b/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c index 2b4a9d2eef..ff7e6774f0 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c +++ b/src/add-ons/kernel/drivers/disk/virtual/nbd/nbd.c @@ -16,10 +16,13 @@ #include #include +#define DEBUG 1 + +/* locking support */ #ifdef __HAIKU__ #include #else -/* wrappers */ +/* wrappers for R5 */ #ifndef _IMPEXP_KERNEL #define _IMPEXP_KERNEL #endif @@ -34,13 +37,21 @@ #include "nbd.h" #define DRV "nbd" -#define D "nbd:" +#define DP "nbd:" #define MAX_NBDS 4 #define DEVICE_PREFIX "disk/virtual/nbd/" -#define DEVICE_FMT DEVICE_PREFIX "%2d/raw" +#define DEVICE_FMT DEVICE_PREFIX "%d/raw" #define DEVICE_NAME_MAX 32 #define MAX_REQ_SIZE (32*1024*1024) +/* debugging */ +#if DEBUG +#define PRINT(a) dprintf a +#define WHICH(dev) ((int)(dev - nbd_devices)) +#else +#define PRINT(a) +#endif + struct nbd_request_entry { struct nbd_request_entry *next; struct nbd_request req; @@ -76,30 +87,100 @@ struct nbd_device *nbd_find_device(const char* name); KSOCKET_MODULE_DECL; +/* HACK: + * In BONE at least, if connect() fails (EINTR or ETIMEDOUT) + * keeps locked pages around (likely a bone_data, + * until TCP gets the last ACK). If that happens, we snooze() + * in unload_driver() to let TCP timeout before the kernel + * tries to delete the image. */ +bool gDelayUnload = false; +#define BONE_TEARDOWN_DELAY 60000000 + #pragma mark ==== request manager ==== #pragma mark ==== nbd handler ==== -int32 postoffice(void *arg) +int32 nbd_postoffice(void *arg) { struct nbd_device *dev = (struct nbd_device *)arg; int sock = dev->sock; + PRINT((DP ">%s()\n", __FUNCTION__)); + PRINT((DP "<%s\n", __FUNCTION__)); return 0; } status_t nbd_connect(struct nbd_device *dev) { + struct nbd_init_packet initpkt; + status_t err; + PRINT((DP ">%s()\n", __FUNCTION__)); + + PRINT((DP " %s: socket()\n", __FUNCTION__)); + err = dev->sock = ksocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (err == -1 && errno < 0) + err = errno; + if (err < 0) + goto err0; + PRINT((DP " %s: connect()\n", __FUNCTION__)); + err = kconnect(dev->sock, (struct sockaddr *)&dev->server, sizeof(dev->server)); + //err = ENOSYS; + if (err == -1 && errno < 0) + err = errno; + /* HACK: avoid the kernel unlading us with locked pages from TCP */ + if (err) + gDelayUnload = true; + if (err) + goto err1; + + PRINT((DP " %s: recv(initpkt)\n", __FUNCTION__)); + err = krecv(dev->sock, &initpkt, sizeof(initpkt), 0); + if (err == -1 && errno < 0) + err = errno; + if (err < sizeof(initpkt)) + goto err2; + err = EINVAL;//EPROTO; + if (memcmp(initpkt.passwd, NBD_INIT_PASSWD, sizeof(initpkt.passwd))) + goto err3; + if (B_BENDIAN_TO_HOST_INT64(initpkt.magic) != NBD_INIT_MAGIC) + goto err3; + + dev->size = B_BENDIAN_TO_HOST_INT64(initpkt.device_size); + + dprintf(DP " %s: connected, device size %Ld bytes.\n", __FUNCTION__, dev->size); + + err = dev->postoffice = spawn_kernel_thread(nbd_postoffice, "nbd postoffice", B_REAL_TIME_PRIORITY, dev); + if (err < B_OK) + goto err4; + resume_thread(dev->postoffice); + + PRINT((DP "<%s\n", __FUNCTION__)); return B_OK; + +err4: + dev->postoffice = -1; +err3: +err2: +err1: + kclosesocket(dev->sock); + dev->sock = -1; +err0: + dprintf(DP "<%s: error 0x%08lx\n", __FUNCTION__, err); + return err; } status_t nbd_teardown(struct nbd_device *dev) { - close(dev->sock); + status_t err, ret; + PRINT((DP ">%s()\n", __FUNCTION__)); + kshutdown(dev->sock, SHUTDOWN_BOTH); + kclosesocket(dev->sock); + dev->sock = -1; + err = wait_for_thread(dev->postoffice, &ret); return B_OK; } @@ -110,6 +191,7 @@ static struct nbd_device nbd_devices[MAX_NBDS]; status_t nbd_open(const char *name, uint32 flags, cookie_t **cookie) { status_t err; struct nbd_device *dev = NULL; + PRINT((DP ">%s(%s, %x, )\n", __FUNCTION__, name, flags)); (void)name; (void)flags; dev = nbd_find_device(name); if (!dev) @@ -137,13 +219,14 @@ err2: err1: free(*cookie); err0: - dprintf("nbd_open : error 0x%08lx\n", err); + dprintf(DP " %s: error 0x%08lx\n", __FUNCTION__, err); return err; } status_t nbd_close(cookie_t *cookie) { struct nbd_device *dev = cookie->dev; status_t err; + PRINT((DP ">%s(%d)\n", __FUNCTION__, WHICH(cookie->dev))); err = benaphore_lock(&dev->ben); if (err) @@ -158,6 +241,7 @@ status_t nbd_close(cookie_t *cookie) { status_t nbd_free(cookie_t *cookie) { struct nbd_device *dev = cookie->dev; status_t err; + PRINT((DP ">%s(%d)\n", __FUNCTION__, WHICH(cookie->dev))); err = benaphore_lock(&dev->ben); if (err) @@ -174,6 +258,7 @@ status_t nbd_free(cookie_t *cookie) { } status_t nbd_control(cookie_t *cookie, uint32 op, void *data, size_t len) { + PRINT((DP ">%s(%d, %ul, , %d)\n", __FUNCTION__, WHICH(cookie->dev), op, len)); switch (op) { case B_GET_DEVICE_SIZE: /* this one is broken anyway... */ if (data) { @@ -227,11 +312,13 @@ status_t nbd_control(cookie_t *cookie, uint32 op, void *data, size_t len) { } status_t nbd_read(cookie_t *cookie, off_t position, void *data, size_t *numbytes) { + PRINT((DP ">%s(%d, %Ld, , )\n", __FUNCTION__, WHICH(cookie->dev), position)); *numbytes = 0; return B_NOT_ALLOWED; } status_t nbd_write(cookie_t *cookie, off_t position, const void *data, size_t *numbytes) { + PRINT((DP ">%s(%d, %Ld, , )\n", __FUNCTION__, WHICH(cookie->dev), position)); (void)cookie; (void)position; (void)data; (void)numbytes; *numbytes = 0; return EIO; @@ -260,6 +347,7 @@ static const char *nbd_name[MAX_NBDS+1] = { status_t init_hardware (void) { + PRINT((DP ">%s()\n", __FUNCTION__)); return B_OK; } @@ -270,6 +358,7 @@ init_driver (void) int i, j; // XXX: load settings void *handle; + PRINT((DP ">%s()\n", __FUNCTION__)); err = ksocket_init(); if (err < B_OK) @@ -290,7 +379,11 @@ init_driver (void) if (nbd_name[i] == NULL) break; sprintf(nbd_name[i], DEVICE_FMT, i); - // XXX: init nbd_devices[i] + /* XXX: default init */ + nbd_devices[i].server.sin_len = sizeof(struct sockaddr_in); + nbd_devices[i].server.sin_family = AF_INET; + nbd_devices[i].server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + nbd_devices[i].server.sin_port = htons(1337 + i); } nbd_name[i] = NULL; @@ -303,7 +396,7 @@ init_driver (void) v = get_driver_parameter(handle, keyname, NULL, NULL); /* should be "ip:port" */ // XXX: test - if (v || 0) { + if (v || 1) { //strncpy(nbd_devices[i].target, v, 64); //XXX:TEST //strncpy(nbd_devices[i].target, "127.0.0.1:1337", 64); @@ -332,22 +425,28 @@ uninit_driver (void) { status_t err; int i; + PRINT((DP ">%s()\n", __FUNCTION__)); for (i = 0; i < MAX_NBDS; i++) { free(nbd_name[i]); err = benaphore_destroy(&nbd_devices[i].ben); } err = ksocket_cleanup(); + /* HACK */ + if (gDelayUnload) + snooze(BONE_TEARDOWN_DELAY); } const char** publish_devices() { + PRINT((DP ">%s()\n", __FUNCTION__)); return nbd_name; } device_hooks* find_device(const char* name) { + PRINT((DP ">%s(%s)\n", __FUNCTION__, name)); return &nbd_hooks; } @@ -355,6 +454,7 @@ struct nbd_device* nbd_find_device(const char* name) { int i; + PRINT((DP ">%s(%s)\n", __FUNCTION__, name)); for (i = 0; i < MAX_NBDS; i++) { if (!strcmp(nbd_name[i], name)) return &nbd_devices[i];