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:
parent
82256564e2
commit
637cbfeeef
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user