summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Robra2019-08-23 12:09:03 +0200
committerFrederic Robra2019-08-23 12:09:03 +0200
commitf6c99126c9df1cae6a8d9b51998760a5896f4e9d (patch)
tree7cb2032c6e2960eed328dcff9903ae41886a18c8
parentchanged strategy to connect to diffrent sockets (diff)
downloaddnbd3-ng-f6c99126c9df1cae6a8d9b51998760a5896f4e9d.tar.gz
dnbd3-ng-f6c99126c9df1cae6a8d9b51998760a5896f4e9d.tar.xz
dnbd3-ng-f6c99126c9df1cae6a8d9b51998760a5896f4e9d.zip
moved mq part to new file
fixed various bugs
-rw-r--r--Kbuild.in2
-rw-r--r--src/clientconfig.h1
-rw-r--r--src/kernel/core.c163
-rw-r--r--src/kernel/dnbd3.h11
-rw-r--r--src/kernel/mq.c251
-rw-r--r--src/kernel/mq.h52
-rw-r--r--src/kernel/net.c58
7 files changed, 352 insertions, 186 deletions
diff --git a/Kbuild.in b/Kbuild.in
index 68c1d02..cb559b9 100644
--- a/Kbuild.in
+++ b/Kbuild.in
@@ -1,2 +1,2 @@
obj-m := ${MODULE_NAME}.o
-${MODULE_NAME}-objs += core.o sysfs.o net.o utils.o serialize_kmod.o
+${MODULE_NAME}-objs += core.o sysfs.o net.o mq.o utils.o serialize_kmod.o
diff --git a/src/clientconfig.h b/src/clientconfig.h
index f35f673..ab1cff8 100644
--- a/src/clientconfig.h
+++ b/src/clientconfig.h
@@ -11,6 +11,7 @@
#define RTT_THRESHOLD_FACTOR(us) (((us) * 2) / 3) // 2/3 = current to best must be 33% worse
#define RTT_ABSOLUTE_THRESHOLD (80000) // Or 80ms worse
#define RTT_UNREACHABLE 0x7FFFFFFul // Use this value for timeout/unreachable as RTT. Don't set too high or you might get overflows. 0x7FFFFFF = 134 seconds
+#define RTT_UNKNOWN (RTT_UNREACHABLE / 2)
// This must be a power of two:
#define RTT_BLOCK_SIZE 4096
diff --git a/src/kernel/core.c b/src/kernel/core.c
index 6f0dab4..19f4bac 100644
--- a/src/kernel/core.c
+++ b/src/kernel/core.c
@@ -51,6 +51,7 @@
#include "sysfs.h"
#include "clientconfig.h"
#include "net.h"
+#include "mq.h"
@@ -63,159 +64,6 @@ static struct dnbd3_device *device;
int major;
/**
- * dnbd3_requeue_cmd - requeue a command once
- * @cmd: the command to requeue
- */
-static void dnbd3_requeue_cmd(struct dnbd3_cmd *cmd)
-{
- struct request *req = blk_mq_rq_from_pdu(cmd);
- if (!cmd->requed) {
- cmd->requed = true;
- blk_mq_requeue_request(req, true);
- } else {
- blk_mq_end_request(req, BLK_STS_IOERR);
- }
-}
-
-/**
- * dnbd3_handle_cmd - handles a mq command
- * @cmd: the cmd to send
- * @index: the index of the queue
- */
-static int dnbd3_handle_cmd(struct dnbd3_cmd *cmd, int index)
-{
- struct request *req = blk_mq_rq_from_pdu(cmd);
- struct dnbd3_device *dev = cmd->dnbd3;
- struct dnbd3_sock *sock = &dev->socks[index];
- int ret = -1;
-
-// debug_dev(dev, "handle request at position %lu, size %d, index %d",
-// blk_rq_pos(req), blk_rq_bytes(req), index);
-
-
- if (!(sock->server && sock->sock && !sock->panic)) {
-// warn_dev(dev, "attempted send on invalid socket %d", index);
- msleep(SOCKET_TIMEOUT_CLIENT_DATA * 1000);
-
- dnbd3_requeue_cmd(cmd);
- ret = 0;
- goto out;
- }
-
- cmd->status = BLK_STS_OK;
-
- mutex_lock(&sock->tx_lock);
- if (unlikely(!sock->sock)) {
- mutex_unlock(&sock->tx_lock);
- warn_sock(sock, "not connected");
- return -EIO;
- }
-
- blk_mq_start_request(req);
- if (unlikely(sock->pending && sock->pending != req)) {
- dnbd3_requeue_cmd(cmd);
- ret = 0;
- goto out;
- }
-
- ret = dnbd3_send_request(sock, blk_mq_rq_from_pdu(cmd), cmd);
- if (ret == -EAGAIN) {
- dev_err_ratelimited(disk_to_dev(dev->disk), "request send failed, requeueing\n");
- dnbd3_requeue_cmd(cmd);
- ret = 0;
- }
-out:
- mutex_unlock(&sock->tx_lock);
- return ret;
-}
-
-/**
- * dnbd3_queue_rq - queue request
- * @hctx: state for a hardware queue facing the hardware block device
- * @bd: the queue data including the request
- */
-static blk_status_t dnbd3_queue_rq(struct blk_mq_hw_ctx *hctx,
- const struct blk_mq_queue_data *bd)
-{
- struct dnbd3_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
- int ret;
-
- mutex_lock(&cmd->lock);
-// cmd->requed = false;
-
- ret = dnbd3_handle_cmd(cmd, hctx->queue_num);
- if (ret < 0) {
- ret = BLK_STS_IOERR;
- } else if (ret >= 0) {
- ret = BLK_STS_OK;
- }
- mutex_unlock(&cmd->lock);
-
- return ret;
-}
-
-/**
- * dnbd3_init_request - init a mq request
- * @set: the mq tag set
- * @rq: the request
- * @hctx_idx:
- * @numa_node:
- */
-static int dnbd3_init_request(struct blk_mq_tag_set *set, struct request *rq,
- unsigned int hctx_idx, unsigned int numa_node)
-{
- struct dnbd3_cmd *cmd = blk_mq_rq_to_pdu(rq);
- cmd->dnbd3 = set->driver_data;
- cmd->requed = false;
- mutex_init(&cmd->lock);
- return 0;
-}
-
-/**
- * dnbd3_xmit_timeout - timeout function for mq
- * @req: the timedout request
- * @reserved:
- */
-static enum blk_eh_timer_return dnbd3_xmit_timeout(struct request *req,
- bool reserved)
-{
- struct dnbd3_cmd *cmd = blk_mq_rq_to_pdu(req);
- struct dnbd3_device *dev = cmd->dnbd3;
- int i;
- warn_dev(dev, "received timeout");
-
- if (!mutex_trylock(&cmd->lock)) {
- return BLK_EH_RESET_TIMER;
- }
-
- for (i = 0; i < NUMBER_CONNECTIONS; i++) {
- if (dnbd3_is_sock_alive(dev->socks[i])) {
- info_sock(&dev->socks[i], "reset request to new socket");
- dnbd3_requeue_cmd(cmd);
- return BLK_EH_DONE;
- }
- }
-
- dev_err_ratelimited(disk_to_dev(dev->disk), "connection timed out\n");
- cmd->status = BLK_STS_IOERR;
- blk_mq_complete_request(req);
- blk_mq_end_request(req, BLK_STS_TIMEOUT);
- return BLK_EH_DONE;
-}
-
-/**
- * struct blk_mq_ops - dnbd3_mq_ops
- * multiqueue operations
- */
-static struct blk_mq_ops dnbd3_mq_ops = {
- .queue_rq = dnbd3_queue_rq,
- .init_request = dnbd3_init_request,
- .timeout = dnbd3_xmit_timeout,
-};
-
-
-
-/**
* dnbd3_ioctl - the ioctl function of the dnbd3 kernel modul
* @bdev: the block device
* @mode:
@@ -301,6 +149,12 @@ static int dnbd3_ioctl(struct block_device *bdev, fmode_t mode,
mutex_unlock(&dev->device_lock);
result = dnbd3_net_connect(dev);
+ if (result) {
+ if (dev->imgname) {
+ kfree(dev->imgname);
+ dev->imgname = NULL;
+ }
+ }
imgname = NULL;
}
break;
@@ -392,6 +246,7 @@ int dnbd3_add_device(struct dnbd3_device *dev, int minor)
mutex_init(&dev->device_lock);
mutex_lock(&dev->device_lock);
+// atomic_set(&dev->mq_requests, 0);
for (i = 0; i < NUMBER_CONNECTIONS; i++) {
dev->socks[i].device = dev;
dev->socks[i].sock_nr = i;
@@ -421,7 +276,7 @@ int dnbd3_add_device(struct dnbd3_device *dev, int minor)
dev->tag_set.numa_node = NUMA_NO_NODE;
dev->tag_set.cmd_size = sizeof(struct dnbd3_cmd);
dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE |
- BLK_MQ_F_SG_MERGE | BLK_MQ_F_BLOCKING;
+ BLK_MQ_F_SG_MERGE; // | BLK_MQ_F_BLOCKING;
dev->tag_set.driver_data = dev;
err = blk_mq_alloc_tag_set(&dev->tag_set);
diff --git a/src/kernel/dnbd3.h b/src/kernel/dnbd3.h
index 8fabc35..1cf302f 100644
--- a/src/kernel/dnbd3.h
+++ b/src/kernel/dnbd3.h
@@ -39,14 +39,11 @@
-
-#define RTT_FACTOR(rtt) (((rtt) * 3) / 2)
-
/**
- * limit to which the other connected servers are only allowed to be that worser
- * then the best rtt
+ * factor to which the next server is choosen or the same
*/
-#define RTT_THRESOULD_LIMIT(best_rtt) ((best_rtt) * 10)
+#define RTT_FACTOR(rtt) (((rtt) * 3) / 2)
+
/**
* turn on/off debug information (1/0)
@@ -219,7 +216,7 @@ struct dnbd3_cmd {
#define dnbd3_set_rtt_unknown(server) \
(server)->rtts[0] = (server)->rtts[1] = (server)->rtts[2] \
= (server)->rtts[3] = (server)->avg_rtt = \
- RTT_UNREACHABLE / 2;
+ RTT_UNKNOWN;
/**
diff --git a/src/kernel/mq.c b/src/kernel/mq.c
new file mode 100644
index 0000000..0a99817
--- /dev/null
+++ b/src/kernel/mq.c
@@ -0,0 +1,251 @@
+/*
+ * This file is part of the Distributed Network Block Device 3
+ *
+ * Copyright(c) 2019 Frederic Robra <frederic@robra.org>
+ *
+ * This file may be licensed under the terms of of the
+ * GNU General Public License Version 2 (the ``GPL'').
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the GPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the GPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mq.h"
+#include "net.h"
+
+#include <linux/wait.h>
+#include <linux/blk-mq.h>
+
+/**
+ * dnbd3_busy_iter - iterator for blk_mq_tagset_busy_iter
+ * @req: the request
+ * @priv: the passed argument from blk_mq_tagset_busy_iter
+ * @arg2: unknown
+ */
+static void dnbd3_busy_iter(struct request *req, void *priv, bool arg2)
+{
+ bool *is_busy = (bool *) priv;
+ *is_busy = true;
+}
+
+/**
+ * dnbd3_is_mq_busy - check if mq is busy
+ * @dev: the device
+ */
+bool dnbd3_is_mq_busy(struct dnbd3_device *dev)
+{
+ struct blk_mq_tag_set *set = &dev->tag_set;
+ bool is_busy = false;
+
+ blk_mq_tagset_busy_iter(set, dnbd3_busy_iter, &is_busy);
+
+ /*
+ * just for demonstration
+ * with this it is possible to iterate through the hardware queues
+ *
+ int i = 0;
+ struct request_queue *q;
+ struct blk_mq_hw_ctx *hctx;
+ list_for_each_entry(q, &set->tag_list, tag_set_list) {
+
+ for (i = 0; i < NUMBER_CONNECTIONS; i++) {
+ hctx = q->queue_hw_ctx[i];
+ debug_dev(dev, "%i %lu", i, hctx->queued);
+ }
+ }
+ */
+
+ return is_busy;
+}
+
+
+/**
+ * dnbd3_requeue_cmd - requeue a command once
+ * @cmd: the command to requeue
+ */
+void dnbd3_requeue_cmd(struct dnbd3_cmd *cmd)
+{
+ struct request *req = blk_mq_rq_from_pdu(cmd);
+ if (!cmd->requed) {
+ cmd->requed = true;
+ blk_mq_requeue_request(req, true);
+ }
+}
+
+/**
+ * dnbd3_end_cmd - end a blk request
+ * @cmd: the command to end the request with
+ * @error: the status
+ */
+void dnbd3_end_cmd(struct dnbd3_cmd *cmd, blk_status_t error)
+{
+ struct request *req = blk_mq_rq_from_pdu(cmd);
+ blk_mq_end_request(req, error);
+}
+
+/**
+ * dnbd3_is_any_sock_alive - check if any socket is alive
+ * @cmd: the command
+ */
+static bool dnbd3_is_any_sock_alive(struct dnbd3_cmd *cmd) {
+ int i;
+ for (i = 0; i < NUMBER_CONNECTIONS; i++) {
+ if (dnbd3_is_sock_alive(cmd->dnbd3->socks[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * dnbd3_handle_cmd - handles a mq command
+ * @cmd: the cmd to send
+ * @index: the index of the queue
+ */
+static int dnbd3_handle_cmd(struct dnbd3_cmd *cmd, int index)
+{
+ struct request *req = blk_mq_rq_from_pdu(cmd);
+ struct dnbd3_device *dev = cmd->dnbd3;
+ struct dnbd3_sock *sock = &dev->socks[index];
+ int ret = -1;
+
+// debug_dev(dev, "handle request at position %lu, size %d, index %d",
+// blk_rq_pos(req), blk_rq_bytes(req), index);
+
+
+ if (!(sock->server && sock->sock && !sock->panic)) {
+ warn_dev(dev, "attempted send on invalid socket %d", index);
+// msleep(SOCKET_TIMEOUT_CLIENT_DATA * 1000);
+
+ if (dnbd3_is_any_sock_alive(cmd)) {
+ info_dev(dev, "reset request to new socket");
+ dnbd3_requeue_cmd(cmd);
+ ret = 0;
+ goto out;
+ } else {
+ error_dev(dev, "ending request, no socket found");
+ dnbd3_end_cmd(cmd, BLK_STS_IOERR);
+ ret = -EIO;
+ goto out;
+ }
+ }
+
+ cmd->status = BLK_STS_OK;
+
+ mutex_lock(&sock->tx_lock);
+ if (unlikely(!sock->sock)) {
+ mutex_unlock(&sock->tx_lock);
+ warn_sock(sock, "not connected");
+ return -EIO;
+ }
+
+ blk_mq_start_request(req);
+ if (unlikely(sock->pending && sock->pending != req)) {
+ dnbd3_requeue_cmd(cmd);
+ ret = 0;
+ goto out;
+ }
+
+ ret = dnbd3_send_request(sock, blk_mq_rq_from_pdu(cmd), cmd);
+ if (ret == -EAGAIN) {
+ dev_err_ratelimited(disk_to_dev(dev->disk), "request send failed, requeueing\n");
+ dnbd3_requeue_cmd(cmd);
+ ret = 0;
+ }
+out:
+ mutex_unlock(&sock->tx_lock);
+ return ret;
+}
+
+/**
+ * dnbd3_queue_rq - queue request
+ * @hctx: state for a hardware queue facing the hardware block device
+ * @bd: the queue data including the request
+ */
+static blk_status_t dnbd3_queue_rq(struct blk_mq_hw_ctx *hctx,
+ const struct blk_mq_queue_data *bd)
+{
+ struct dnbd3_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
+ int ret;
+
+ mutex_lock(&cmd->lock);
+
+ cmd->requed = false;
+
+ ret = dnbd3_handle_cmd(cmd, hctx->queue_num);
+ if (ret < 0) {
+ ret = BLK_STS_IOERR;
+ } else if (ret >= 0) {
+ ret = BLK_STS_OK;
+ }
+ mutex_unlock(&cmd->lock);
+
+ return ret;
+}
+
+/**
+ * dnbd3_init_request - init a mq request
+ * @set: the mq tag set
+ * @rq: the request
+ * @hctx_idx:
+ * @numa_node:
+ */
+static int dnbd3_init_request(struct blk_mq_tag_set *set, struct request *rq,
+ unsigned int hctx_idx, unsigned int numa_node)
+{
+ struct dnbd3_cmd *cmd = blk_mq_rq_to_pdu(rq);
+ cmd->dnbd3 = set->driver_data;
+ cmd->requed = false;
+ mutex_init(&cmd->lock);
+ return 0;
+}
+
+/**
+ * dnbd3_xmit_timeout - timeout function for mq
+ * @req: the timedout request
+ * @reserved:
+ */
+static enum blk_eh_timer_return dnbd3_xmit_timeout(struct request *req,
+ bool reserved)
+{
+ struct dnbd3_cmd *cmd = blk_mq_rq_to_pdu(req);
+ struct dnbd3_device *dev = cmd->dnbd3;
+ warn_dev(dev, "received timeout");
+
+ if (!mutex_trylock(&cmd->lock)) {
+ return BLK_EH_RESET_TIMER;
+ }
+
+ if (dnbd3_is_any_sock_alive(cmd)) {
+ info_dev(dev, "reset request to new socket");
+ dnbd3_requeue_cmd(cmd);
+ return BLK_EH_DONE;
+ }
+
+ dev_err_ratelimited(disk_to_dev(dev->disk), "connection timed out\n");
+ cmd->status = BLK_STS_IOERR;
+// blk_mq_complete_request(req);
+ dnbd3_end_cmd(cmd, BLK_STS_TIMEOUT);
+ return BLK_EH_DONE;
+}
+
+/**
+ * struct blk_mq_ops - dnbd3_mq_ops
+ * multiqueue operations
+ */
+struct blk_mq_ops dnbd3_mq_ops = {
+ .queue_rq = dnbd3_queue_rq,
+ .init_request = dnbd3_init_request,
+ .timeout = dnbd3_xmit_timeout,
+};
+
+
+
diff --git a/src/kernel/mq.h b/src/kernel/mq.h
new file mode 100644
index 0000000..74f4f68
--- /dev/null
+++ b/src/kernel/mq.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the Distributed Network Block Device 3
+ *
+ * Copyright(c) 2019 Frederic Robra <frederic@robra.org>
+ *
+ * This file may be licensed under the terms of of the
+ * GNU General Public License Version 2 (the ``GPL'').
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the GPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the GPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/gpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MQ_H_
+#define MQ_H_
+
+#include "dnbd3.h"
+
+/**
+ * dnbd3_is_mq_busy - check if mq is busy
+ * @dev: the device
+ */
+bool dnbd3_is_mq_busy(struct dnbd3_device *dev);
+
+/**
+ * dnbd3_requeue_cmd - requeue a command once
+ * @cmd: the command to requeue
+ */
+void dnbd3_requeue_cmd(struct dnbd3_cmd *cmd);
+
+
+/**
+ * dnbd3_end_request - end a blk request
+ * @cmd: the command to end the request with
+ * @error: the status
+ */
+void dnbd3_end_cmd(struct dnbd3_cmd *cmd, blk_status_t error);
+
+/**
+ * struct blk_mq_ops - dnbd3_mq_ops
+ * multiqueue operations
+ */
+extern struct blk_mq_ops dnbd3_mq_ops;
+
+#endif /* MQ_H_ */
diff --git a/src/kernel/net.c b/src/kernel/net.c
index 35c49b5..07f350e 100644
--- a/src/kernel/net.c
+++ b/src/kernel/net.c
@@ -27,6 +27,7 @@
#include "net.h"
#include "utils.h"
#include "clientconfig.h"
+#include "mq.h"
#define DNBD3_REQ_OP_SPECIAL REQ_OP_DRV_IN
@@ -175,7 +176,7 @@ int dnbd3_send_request(struct dnbd3_sock *sock, struct request *req,
if (result != lng) {
error_sock(sock, "connection to server lost");
if (cmd) {
- blk_mq_requeue_request(req, true);
+ dnbd3_requeue_cmd(cmd);
}
sock->panic = true;
sock->server->failures++;
@@ -223,10 +224,6 @@ static int dnbd3_send_request_cmd(struct dnbd3_sock *sock, uint16_t dnbd3_cmd)
mutex_lock(&sock->tx_lock);
sock->pending = req;
result = dnbd3_send_request(sock, req, NULL);
- if (result <= 0) {
- mutex_unlock(&sock->tx_lock);
- goto error;
- }
mutex_unlock(&sock->tx_lock);
error:
@@ -336,15 +333,16 @@ static int dnbd3_receive_cmd_get_block_mq(struct dnbd3_sock *sock,
kunmap(bvec->bv_page);
sigprocmask(SIG_SETMASK, &oldset, NULL );
error_sock(sock, "could not receive from net to block layer");
+ dnbd3_requeue_cmd(cmd);
mutex_unlock(&cmd->lock);
- return result;
+ return -EIO;
}
kunmap(bvec->bv_page);
sigprocmask(SIG_SETMASK, &oldset, NULL );
}
mutex_unlock(&cmd->lock);
- blk_mq_end_request(req, 0);
+ dnbd3_end_cmd(cmd, 0);
return result;
}
@@ -424,6 +422,7 @@ static int dnbd3_receive_cmd_get_servers(struct dnbd3_sock *sock,
if (result <= 0) {
error_sock(sock, "failed to receive get servers %d",
result);
+ mutex_unlock(&dev->device_lock);
return result;
} else if (result != (count * sizeof(dnbd3_server_entry_t))) {
error_sock(sock, "failed to get servers");
@@ -587,20 +586,22 @@ static void dnbd3_timer(struct timer_list *arg)
dev = container_of(arg, struct dnbd3_device, timer);
queue_work(dnbd3_wq, &dev->panic_worker);
- if (dev->timer_count % TIMER_INTERVAL_KEEPALIVE_PACKET == 0) {
- for (i = 0; i < NUMBER_CONNECTIONS; i++) {
- if (dnbd3_is_sock_alive(dev->socks[i])) {
- queue_work(dnbd3_wq, &dev->socks[i].keepalive_worker);
+ if (!dnbd3_is_mq_busy(dev)) {
+ if (dev->timer_count % TIMER_INTERVAL_KEEPALIVE_PACKET == 0) {
+ for (i = 0; i < NUMBER_CONNECTIONS; i++) {
+ if (dnbd3_is_sock_alive(dev->socks[i])) {
+ queue_work(dnbd3_wq, &dev->socks[i].keepalive_worker);
+ }
}
}
- }
- /* start after 4 seconds */
- if (dev->timer_count % TIMER_INTERVAL_PROBE_NORMAL == 4) {
- queue_work(dnbd3_wq, &dev->discovery_worker);
- }
+ /* start after 4 seconds */
+ if (dev->timer_count % TIMER_INTERVAL_PROBE_NORMAL == 4) {
+ queue_work(dnbd3_wq, &dev->discovery_worker);
+ }
- dev->timer_count++;
+ dev->timer_count++;
+ }
dev->timer.expires = jiffies + HZ;
add_timer(&dev->timer);
}
@@ -623,6 +624,7 @@ static void dnbd3_receive_worker(struct work_struct *work)
result = dnbd3_receive_cmd(sock, &reply);
if (result == -EAGAIN) {
continue;
+
} else if (result <= 0) {
error_sock(sock, "connection to server lost %d", result);
goto error;
@@ -759,9 +761,8 @@ static int dnbd3_adjust_connections(struct dnbd3_device *dev) {
int i, j, fallback;
struct dnbd3_server *plan[NUMBER_CONNECTIONS];
struct dnbd3_server **servers = dnbd3_sort_server(dev);
-
+//TODO don't connect to anyting bader then rtt unknown
if (servers && servers[0]->host.type != 0) {
- mutex_lock(&dev->device_lock);
plan[0] = servers[0];
fallback = 0;
j = 1;
@@ -769,7 +770,8 @@ static int dnbd3_adjust_connections(struct dnbd3_device *dev) {
debug_server(dev, plan[0], "server 0 with rtt %llu:",
plan[0]->avg_rtt);
for (i = 1; i < NUMBER_CONNECTIONS; i++) {
- if (servers[j]->host.type != 0) {
+ if (servers[j]->host.type != 0 &&
+ servers[j]->avg_rtt < RTT_UNKNOWN) {
if (RTT_FACTOR(plan[i - 1]->avg_rtt) >
servers[j]->avg_rtt) {
plan[i] = servers[j];
@@ -786,16 +788,17 @@ static int dnbd3_adjust_connections(struct dnbd3_device *dev) {
i, plan[i]->avg_rtt);
}
kfree(servers);
-
for (i = 0; i < NUMBER_CONNECTIONS; i++) {
if (plan[i] != dev->socks[i].server) {
if (dnbd3_is_sock_alive(dev->socks[i])) {
dnbd3_socket_disconnect(&dev->socks[i]);
}
- dnbd3_socket_connect(&dev->socks[i], plan[i]);
+ j = dnbd3_socket_connect(&dev->socks[i], plan[i]);
+ if (j) {
+ return j;
+ }
}
}
- mutex_unlock(&dev->device_lock);
return 0;
} else { /* there is nothing to connect */
if (servers) {
@@ -838,7 +841,9 @@ static void dnbd3_panic_worker(struct work_struct *work)
warn_dev(dev, "panicked, connections still alive %d",
sock_alive);
+ mutex_lock(&dev->device_lock);
dnbd3_adjust_connections(dev);
+ mutex_unlock(&dev->device_lock);
}
}
@@ -1009,12 +1014,12 @@ static void dnbd3_discovery_worker(struct work_struct *work)
dnbd3_server_entry_t *new_server;
dev = container_of(work, struct dnbd3_device, discovery_worker);
+
debug_dev(dev, "starting discovery worker new server num is %d",
dev->new_servers_num);
if (dev->new_servers_num) {
mutex_lock(&dev->device_lock);
-
for (i = 0; i < dev->new_servers_num; i++) {
new_server = &dev->new_servers[i];
if (new_server->host.type != 0) {
@@ -1036,7 +1041,10 @@ static void dnbd3_discovery_worker(struct work_struct *work)
}
}
+
+ mutex_lock(&dev->device_lock);
dnbd3_adjust_connections(dev);
+ mutex_unlock(&dev->device_lock);
dev->discovery_count++;
}
@@ -1140,6 +1148,7 @@ static int dnbd3_socket_connect(struct dnbd3_sock *sock,
result = __dnbd3_socket_connect(sock, server);
if (result) {
error_sock(sock, "connection to socket failed");
+ mutex_unlock(&sock->tx_lock);
result = -EIO;
goto error;
}
@@ -1271,6 +1280,7 @@ int dnbd3_net_connect(struct dnbd3_device *dev)
result = dnbd3_adjust_connections(dev);
if (result) {
error_dev(dev, "failed to connect to initial server");
+ dnbd3_net_disconnect(dev);
return -ENOENT;
}