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:
@@ -16,10 +16,13 @@
|
|||||||
#include <ksocket.h>
|
#include <ksocket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#define DEBUG 1
|
||||||
|
|
||||||
|
/* locking support */
|
||||||
#ifdef __HAIKU__
|
#ifdef __HAIKU__
|
||||||
#include <kernel/lock.h>
|
#include <kernel/lock.h>
|
||||||
#else
|
#else
|
||||||
/* wrappers */
|
/* wrappers for R5 */
|
||||||
#ifndef _IMPEXP_KERNEL
|
#ifndef _IMPEXP_KERNEL
|
||||||
#define _IMPEXP_KERNEL
|
#define _IMPEXP_KERNEL
|
||||||
#endif
|
#endif
|
||||||
@@ -34,13 +37,21 @@
|
|||||||
#include "nbd.h"
|
#include "nbd.h"
|
||||||
|
|
||||||
#define DRV "nbd"
|
#define DRV "nbd"
|
||||||
#define D "nbd:"
|
#define DP "nbd:"
|
||||||
#define MAX_NBDS 4
|
#define MAX_NBDS 4
|
||||||
#define DEVICE_PREFIX "disk/virtual/nbd/"
|
#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 DEVICE_NAME_MAX 32
|
||||||
#define MAX_REQ_SIZE (32*1024*1024)
|
#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 {
|
||||||
struct nbd_request_entry *next;
|
struct nbd_request_entry *next;
|
||||||
struct nbd_request req;
|
struct nbd_request req;
|
||||||
@@ -76,30 +87,100 @@ struct nbd_device *nbd_find_device(const char* name);
|
|||||||
|
|
||||||
KSOCKET_MODULE_DECL;
|
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 ==== request manager ====
|
||||||
|
|
||||||
|
|
||||||
#pragma mark ==== nbd handler ====
|
#pragma mark ==== nbd handler ====
|
||||||
|
|
||||||
int32 postoffice(void *arg)
|
int32 nbd_postoffice(void *arg)
|
||||||
{
|
{
|
||||||
struct nbd_device *dev = (struct nbd_device *)arg;
|
struct nbd_device *dev = (struct nbd_device *)arg;
|
||||||
int sock = dev->sock;
|
int sock = dev->sock;
|
||||||
|
PRINT((DP ">%s()\n", __FUNCTION__));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PRINT((DP "<%s\n", __FUNCTION__));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t nbd_connect(struct nbd_device *dev)
|
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;
|
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)
|
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;
|
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 nbd_open(const char *name, uint32 flags, cookie_t **cookie) {
|
||||||
status_t err;
|
status_t err;
|
||||||
struct nbd_device *dev = NULL;
|
struct nbd_device *dev = NULL;
|
||||||
|
PRINT((DP ">%s(%s, %x, )\n", __FUNCTION__, name, flags));
|
||||||
(void)name; (void)flags;
|
(void)name; (void)flags;
|
||||||
dev = nbd_find_device(name);
|
dev = nbd_find_device(name);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
@@ -137,13 +219,14 @@ err2:
|
|||||||
err1:
|
err1:
|
||||||
free(*cookie);
|
free(*cookie);
|
||||||
err0:
|
err0:
|
||||||
dprintf("nbd_open : error 0x%08lx\n", err);
|
dprintf(DP " %s: error 0x%08lx\n", __FUNCTION__, err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t nbd_close(cookie_t *cookie) {
|
status_t nbd_close(cookie_t *cookie) {
|
||||||
struct nbd_device *dev = cookie->dev;
|
struct nbd_device *dev = cookie->dev;
|
||||||
status_t err;
|
status_t err;
|
||||||
|
PRINT((DP ">%s(%d)\n", __FUNCTION__, WHICH(cookie->dev)));
|
||||||
|
|
||||||
err = benaphore_lock(&dev->ben);
|
err = benaphore_lock(&dev->ben);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -158,6 +241,7 @@ status_t nbd_close(cookie_t *cookie) {
|
|||||||
status_t nbd_free(cookie_t *cookie) {
|
status_t nbd_free(cookie_t *cookie) {
|
||||||
struct nbd_device *dev = cookie->dev;
|
struct nbd_device *dev = cookie->dev;
|
||||||
status_t err;
|
status_t err;
|
||||||
|
PRINT((DP ">%s(%d)\n", __FUNCTION__, WHICH(cookie->dev)));
|
||||||
|
|
||||||
err = benaphore_lock(&dev->ben);
|
err = benaphore_lock(&dev->ben);
|
||||||
if (err)
|
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) {
|
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) {
|
switch (op) {
|
||||||
case B_GET_DEVICE_SIZE: /* this one is broken anyway... */
|
case B_GET_DEVICE_SIZE: /* this one is broken anyway... */
|
||||||
if (data) {
|
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) {
|
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;
|
*numbytes = 0;
|
||||||
return B_NOT_ALLOWED;
|
return B_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t nbd_write(cookie_t *cookie, off_t position, const void *data, size_t *numbytes) {
|
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;
|
(void)cookie; (void)position; (void)data; (void)numbytes;
|
||||||
*numbytes = 0;
|
*numbytes = 0;
|
||||||
return EIO;
|
return EIO;
|
||||||
@@ -260,6 +347,7 @@ static const char *nbd_name[MAX_NBDS+1] = {
|
|||||||
status_t
|
status_t
|
||||||
init_hardware (void)
|
init_hardware (void)
|
||||||
{
|
{
|
||||||
|
PRINT((DP ">%s()\n", __FUNCTION__));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +358,7 @@ init_driver (void)
|
|||||||
int i, j;
|
int i, j;
|
||||||
// XXX: load settings
|
// XXX: load settings
|
||||||
void *handle;
|
void *handle;
|
||||||
|
PRINT((DP ">%s()\n", __FUNCTION__));
|
||||||
|
|
||||||
err = ksocket_init();
|
err = ksocket_init();
|
||||||
if (err < B_OK)
|
if (err < B_OK)
|
||||||
@@ -290,7 +379,11 @@ init_driver (void)
|
|||||||
if (nbd_name[i] == NULL)
|
if (nbd_name[i] == NULL)
|
||||||
break;
|
break;
|
||||||
sprintf(nbd_name[i], DEVICE_FMT, i);
|
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;
|
nbd_name[i] = NULL;
|
||||||
|
|
||||||
@@ -303,7 +396,7 @@ init_driver (void)
|
|||||||
v = get_driver_parameter(handle, keyname, NULL, NULL);
|
v = get_driver_parameter(handle, keyname, NULL, NULL);
|
||||||
/* should be "ip:port" */
|
/* should be "ip:port" */
|
||||||
// XXX: test
|
// XXX: test
|
||||||
if (v || 0) {
|
if (v || 1) {
|
||||||
//strncpy(nbd_devices[i].target, v, 64);
|
//strncpy(nbd_devices[i].target, v, 64);
|
||||||
//XXX:TEST
|
//XXX:TEST
|
||||||
//strncpy(nbd_devices[i].target, "127.0.0.1:1337", 64);
|
//strncpy(nbd_devices[i].target, "127.0.0.1:1337", 64);
|
||||||
@@ -332,22 +425,28 @@ uninit_driver (void)
|
|||||||
{
|
{
|
||||||
status_t err;
|
status_t err;
|
||||||
int i;
|
int i;
|
||||||
|
PRINT((DP ">%s()\n", __FUNCTION__));
|
||||||
for (i = 0; i < MAX_NBDS; i++) {
|
for (i = 0; i < MAX_NBDS; i++) {
|
||||||
free(nbd_name[i]);
|
free(nbd_name[i]);
|
||||||
err = benaphore_destroy(&nbd_devices[i].ben);
|
err = benaphore_destroy(&nbd_devices[i].ben);
|
||||||
}
|
}
|
||||||
err = ksocket_cleanup();
|
err = ksocket_cleanup();
|
||||||
|
/* HACK */
|
||||||
|
if (gDelayUnload)
|
||||||
|
snooze(BONE_TEARDOWN_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char**
|
const char**
|
||||||
publish_devices()
|
publish_devices()
|
||||||
{
|
{
|
||||||
|
PRINT((DP ">%s()\n", __FUNCTION__));
|
||||||
return nbd_name;
|
return nbd_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_hooks*
|
device_hooks*
|
||||||
find_device(const char* name)
|
find_device(const char* name)
|
||||||
{
|
{
|
||||||
|
PRINT((DP ">%s(%s)\n", __FUNCTION__, name));
|
||||||
return &nbd_hooks;
|
return &nbd_hooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,6 +454,7 @@ struct nbd_device*
|
|||||||
nbd_find_device(const char* name)
|
nbd_find_device(const char* name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
PRINT((DP ">%s(%s)\n", __FUNCTION__, name));
|
||||||
for (i = 0; i < MAX_NBDS; i++) {
|
for (i = 0; i < MAX_NBDS; i++) {
|
||||||
if (!strcmp(nbd_name[i], name))
|
if (!strcmp(nbd_name[i], name))
|
||||||
return &nbd_devices[i];
|
return &nbd_devices[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user