From f6c99126c9df1cae6a8d9b51998760a5896f4e9d Mon Sep 17 00:00:00 2001 From: Frederic Robra Date: Fri, 23 Aug 2019 12:09:03 +0200 Subject: moved mq part to new file fixed various bugs --- Kbuild.in | 2 +- src/clientconfig.h | 1 + src/kernel/core.c | 163 ++-------------------------------- src/kernel/dnbd3.h | 11 +-- src/kernel/mq.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel/mq.h | 52 +++++++++++ src/kernel/net.c | 58 ++++++++----- 7 files changed, 352 insertions(+), 186 deletions(-) create mode 100644 src/kernel/mq.c create mode 100644 src/kernel/mq.h 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" @@ -62,159 +63,6 @@ static unsigned int max_devs = NUMBER_DEVICES; 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 @@ -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 + * + * 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 +#include + +/** + * 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 + * + * 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; } -- cgit v1.2.3-55-g7522