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
This commit is contained in:
François Revol 2007-05-03 03:37:04 +00:00
parent 82256564e2
commit 637cbfeeef

View File

@ -16,10 +16,13 @@
#include <ksocket.h>
#include <netinet/in.h>
#define DEBUG 1
/* locking support */
#ifdef __HAIKU__
#include <kernel/lock.h>
#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];