mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-19 11:57:44 +07:00
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull block fixes from Jens Axboe: "Five fixes for this series: - a fix from me to ensure that blk-mq drivers that terminate IO in their ->queue_rq() handler by returning QUEUE_ERROR don't stall with a scheduler enabled. - four nbd fixes from Josef and Ratna, fixing various problems that are critical enough to go in for this cycle. They have been well tested" * 'for-linus' of git://git.kernel.dk/linux-block: nbd: replace kill_bdev() with __invalidate_device() nbd: set queue timeout properly nbd: set rq->errors to actual error code nbd: handle ERESTARTSYS properly blk-mq: include errors in did_work calculation
This commit is contained in:
commit
806276b7f0
@ -969,7 +969,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
|
||||
struct request *rq;
|
||||
LIST_HEAD(driver_list);
|
||||
struct list_head *dptr;
|
||||
int queued, ret = BLK_MQ_RQ_QUEUE_OK;
|
||||
int errors, queued, ret = BLK_MQ_RQ_QUEUE_OK;
|
||||
|
||||
/*
|
||||
* Start off with dptr being NULL, so we start the first request
|
||||
@ -980,7 +980,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
|
||||
/*
|
||||
* Now process all the entries, sending them to the driver.
|
||||
*/
|
||||
queued = 0;
|
||||
errors = queued = 0;
|
||||
while (!list_empty(list)) {
|
||||
struct blk_mq_queue_data bd;
|
||||
|
||||
@ -1037,6 +1037,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
|
||||
default:
|
||||
pr_err("blk-mq: bad return on queue: %d\n", ret);
|
||||
case BLK_MQ_RQ_QUEUE_ERROR:
|
||||
errors++;
|
||||
rq->errors = -EIO;
|
||||
blk_mq_end_request(rq, rq->errors);
|
||||
break;
|
||||
@ -1088,7 +1089,7 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
|
||||
blk_mq_run_hw_queue(hctx, true);
|
||||
}
|
||||
|
||||
return queued != 0;
|
||||
return (queued + errors) != 0;
|
||||
}
|
||||
|
||||
static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
|
||||
|
@ -47,6 +47,8 @@ static DEFINE_MUTEX(nbd_index_mutex);
|
||||
struct nbd_sock {
|
||||
struct socket *sock;
|
||||
struct mutex tx_lock;
|
||||
struct request *pending;
|
||||
int sent;
|
||||
};
|
||||
|
||||
#define NBD_TIMEDOUT 0
|
||||
@ -124,7 +126,8 @@ static const char *nbdcmd_to_ascii(int cmd)
|
||||
|
||||
static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev)
|
||||
{
|
||||
bd_set_size(bdev, 0);
|
||||
if (bdev->bd_openers <= 1)
|
||||
bd_set_size(bdev, 0);
|
||||
set_capacity(nbd->disk, 0);
|
||||
kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
|
||||
|
||||
@ -190,7 +193,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
|
||||
|
||||
dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
|
||||
set_bit(NBD_TIMEDOUT, &nbd->runtime_flags);
|
||||
req->errors++;
|
||||
req->errors = -EIO;
|
||||
|
||||
mutex_lock(&nbd->config_lock);
|
||||
sock_shutdown(nbd);
|
||||
@ -202,7 +205,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
|
||||
* Send or receive packet.
|
||||
*/
|
||||
static int sock_xmit(struct nbd_device *nbd, int index, int send,
|
||||
struct iov_iter *iter, int msg_flags)
|
||||
struct iov_iter *iter, int msg_flags, int *sent)
|
||||
{
|
||||
struct socket *sock = nbd->socks[index]->sock;
|
||||
int result;
|
||||
@ -237,6 +240,8 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
|
||||
result = -EPIPE; /* short read */
|
||||
break;
|
||||
}
|
||||
if (sent)
|
||||
*sent += result;
|
||||
} while (msg_data_left(&msg));
|
||||
|
||||
tsk_restore_flags(current, pflags, PF_MEMALLOC);
|
||||
@ -248,6 +253,7 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
|
||||
static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
|
||||
{
|
||||
struct request *req = blk_mq_rq_from_pdu(cmd);
|
||||
struct nbd_sock *nsock = nbd->socks[index];
|
||||
int result;
|
||||
struct nbd_request request = {.magic = htonl(NBD_REQUEST_MAGIC)};
|
||||
struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)};
|
||||
@ -256,6 +262,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
|
||||
struct bio *bio;
|
||||
u32 type;
|
||||
u32 tag = blk_mq_unique_tag(req);
|
||||
int sent = nsock->sent, skip = 0;
|
||||
|
||||
iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request));
|
||||
|
||||
@ -283,6 +290,17 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* We did a partial send previously, and we at least sent the whole
|
||||
* request struct, so just go and send the rest of the pages in the
|
||||
* request.
|
||||
*/
|
||||
if (sent) {
|
||||
if (sent >= sizeof(request)) {
|
||||
skip = sent - sizeof(request);
|
||||
goto send_pages;
|
||||
}
|
||||
iov_iter_advance(&from, sent);
|
||||
}
|
||||
request.type = htonl(type);
|
||||
if (type != NBD_CMD_FLUSH) {
|
||||
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
|
||||
@ -294,15 +312,27 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
|
||||
cmd, nbdcmd_to_ascii(type),
|
||||
(unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req));
|
||||
result = sock_xmit(nbd, index, 1, &from,
|
||||
(type == NBD_CMD_WRITE) ? MSG_MORE : 0);
|
||||
(type == NBD_CMD_WRITE) ? MSG_MORE : 0, &sent);
|
||||
if (result <= 0) {
|
||||
if (result == -ERESTARTSYS) {
|
||||
/* If we havne't sent anything we can just return BUSY,
|
||||
* however if we have sent something we need to make
|
||||
* sure we only allow this req to be sent until we are
|
||||
* completely done.
|
||||
*/
|
||||
if (sent) {
|
||||
nsock->pending = req;
|
||||
nsock->sent = sent;
|
||||
}
|
||||
return BLK_MQ_RQ_QUEUE_BUSY;
|
||||
}
|
||||
dev_err_ratelimited(disk_to_dev(nbd->disk),
|
||||
"Send control failed (result %d)\n", result);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
send_pages:
|
||||
if (type != NBD_CMD_WRITE)
|
||||
return 0;
|
||||
goto out;
|
||||
|
||||
bio = req->bio;
|
||||
while (bio) {
|
||||
@ -318,8 +348,25 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
|
||||
cmd, bvec.bv_len);
|
||||
iov_iter_bvec(&from, ITER_BVEC | WRITE,
|
||||
&bvec, 1, bvec.bv_len);
|
||||
result = sock_xmit(nbd, index, 1, &from, flags);
|
||||
if (skip) {
|
||||
if (skip >= iov_iter_count(&from)) {
|
||||
skip -= iov_iter_count(&from);
|
||||
continue;
|
||||
}
|
||||
iov_iter_advance(&from, skip);
|
||||
skip = 0;
|
||||
}
|
||||
result = sock_xmit(nbd, index, 1, &from, flags, &sent);
|
||||
if (result <= 0) {
|
||||
if (result == -ERESTARTSYS) {
|
||||
/* We've already sent the header, we
|
||||
* have no choice but to set pending and
|
||||
* return BUSY.
|
||||
*/
|
||||
nsock->pending = req;
|
||||
nsock->sent = sent;
|
||||
return BLK_MQ_RQ_QUEUE_BUSY;
|
||||
}
|
||||
dev_err(disk_to_dev(nbd->disk),
|
||||
"Send data failed (result %d)\n",
|
||||
result);
|
||||
@ -336,6 +383,9 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
|
||||
}
|
||||
bio = next;
|
||||
}
|
||||
out:
|
||||
nsock->pending = NULL;
|
||||
nsock->sent = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -353,7 +403,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
|
||||
|
||||
reply.magic = 0;
|
||||
iov_iter_kvec(&to, READ | ITER_KVEC, &iov, 1, sizeof(reply));
|
||||
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL);
|
||||
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
|
||||
if (result <= 0) {
|
||||
if (!test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) &&
|
||||
!test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
|
||||
@ -383,7 +433,7 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
|
||||
if (ntohl(reply.error)) {
|
||||
dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
|
||||
ntohl(reply.error));
|
||||
req->errors++;
|
||||
req->errors = -EIO;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
@ -395,11 +445,11 @@ static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
|
||||
rq_for_each_segment(bvec, req, iter) {
|
||||
iov_iter_bvec(&to, ITER_BVEC | READ,
|
||||
&bvec, 1, bvec.bv_len);
|
||||
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL);
|
||||
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
|
||||
if (result <= 0) {
|
||||
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
|
||||
result);
|
||||
req->errors++;
|
||||
req->errors = -EIO;
|
||||
return cmd;
|
||||
}
|
||||
dev_dbg(nbd_to_dev(nbd), "request %p: got %d bytes data\n",
|
||||
@ -469,7 +519,7 @@ static void nbd_clear_req(struct request *req, void *data, bool reserved)
|
||||
if (!blk_mq_request_started(req))
|
||||
return;
|
||||
cmd = blk_mq_rq_to_pdu(req);
|
||||
req->errors++;
|
||||
req->errors = -EIO;
|
||||
nbd_end_request(cmd);
|
||||
}
|
||||
|
||||
@ -482,22 +532,23 @@ static void nbd_clear_que(struct nbd_device *nbd)
|
||||
}
|
||||
|
||||
|
||||
static void nbd_handle_cmd(struct nbd_cmd *cmd, int index)
|
||||
static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
|
||||
{
|
||||
struct request *req = blk_mq_rq_from_pdu(cmd);
|
||||
struct nbd_device *nbd = cmd->nbd;
|
||||
struct nbd_sock *nsock;
|
||||
int ret;
|
||||
|
||||
if (index >= nbd->num_connections) {
|
||||
dev_err_ratelimited(disk_to_dev(nbd->disk),
|
||||
"Attempted send on invalid socket\n");
|
||||
goto error_out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (test_bit(NBD_DISCONNECTED, &nbd->runtime_flags)) {
|
||||
dev_err_ratelimited(disk_to_dev(nbd->disk),
|
||||
"Attempted send on closed socket\n");
|
||||
goto error_out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req->errors = 0;
|
||||
@ -508,29 +559,30 @@ static void nbd_handle_cmd(struct nbd_cmd *cmd, int index)
|
||||
mutex_unlock(&nsock->tx_lock);
|
||||
dev_err_ratelimited(disk_to_dev(nbd->disk),
|
||||
"Attempted send on closed socket\n");
|
||||
goto error_out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (nbd_send_cmd(nbd, cmd, index) != 0) {
|
||||
dev_err_ratelimited(disk_to_dev(nbd->disk),
|
||||
"Request send failed\n");
|
||||
req->errors++;
|
||||
nbd_end_request(cmd);
|
||||
/* Handle the case that we have a pending request that was partially
|
||||
* transmitted that _has_ to be serviced first. We need to call requeue
|
||||
* here so that it gets put _after_ the request that is already on the
|
||||
* dispatch list.
|
||||
*/
|
||||
if (unlikely(nsock->pending && nsock->pending != req)) {
|
||||
blk_mq_requeue_request(req, true);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = nbd_send_cmd(nbd, cmd, index);
|
||||
out:
|
||||
mutex_unlock(&nsock->tx_lock);
|
||||
|
||||
return;
|
||||
|
||||
error_out:
|
||||
req->errors++;
|
||||
nbd_end_request(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
const struct blk_mq_queue_data *bd)
|
||||
{
|
||||
struct nbd_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Since we look at the bio's to send the request over the network we
|
||||
@ -543,10 +595,20 @@ static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
*/
|
||||
init_completion(&cmd->send_complete);
|
||||
blk_mq_start_request(bd->rq);
|
||||
nbd_handle_cmd(cmd, hctx->queue_num);
|
||||
|
||||
/* We can be called directly from the user space process, which means we
|
||||
* could possibly have signals pending so our sendmsg will fail. In
|
||||
* this case we need to return that we are busy, otherwise error out as
|
||||
* appropriate.
|
||||
*/
|
||||
ret = nbd_handle_cmd(cmd, hctx->queue_num);
|
||||
if (ret < 0)
|
||||
ret = BLK_MQ_RQ_QUEUE_ERROR;
|
||||
if (!ret)
|
||||
ret = BLK_MQ_RQ_QUEUE_OK;
|
||||
complete(&cmd->send_complete);
|
||||
|
||||
return BLK_MQ_RQ_QUEUE_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nbd_add_socket(struct nbd_device *nbd, struct block_device *bdev,
|
||||
@ -581,6 +643,8 @@ static int nbd_add_socket(struct nbd_device *nbd, struct block_device *bdev,
|
||||
|
||||
mutex_init(&nsock->tx_lock);
|
||||
nsock->sock = sock;
|
||||
nsock->pending = NULL;
|
||||
nsock->sent = 0;
|
||||
socks[nbd->num_connections++] = nsock;
|
||||
|
||||
if (max_part)
|
||||
@ -602,6 +666,8 @@ static void nbd_reset(struct nbd_device *nbd)
|
||||
|
||||
static void nbd_bdev_reset(struct block_device *bdev)
|
||||
{
|
||||
if (bdev->bd_openers > 1)
|
||||
return;
|
||||
set_device_ro(bdev, false);
|
||||
bdev->bd_inode->i_size = 0;
|
||||
if (max_part > 0) {
|
||||
@ -634,7 +700,7 @@ static void send_disconnects(struct nbd_device *nbd)
|
||||
|
||||
for (i = 0; i < nbd->num_connections; i++) {
|
||||
iov_iter_kvec(&from, WRITE | ITER_KVEC, &iov, 1, sizeof(request));
|
||||
ret = sock_xmit(nbd, i, 1, &from, 0);
|
||||
ret = sock_xmit(nbd, i, 1, &from, 0, NULL);
|
||||
if (ret <= 0)
|
||||
dev_err(disk_to_dev(nbd->disk),
|
||||
"Send disconnect failed %d\n", ret);
|
||||
@ -665,7 +731,8 @@ static int nbd_clear_sock(struct nbd_device *nbd, struct block_device *bdev)
|
||||
{
|
||||
sock_shutdown(nbd);
|
||||
nbd_clear_que(nbd);
|
||||
kill_bdev(bdev);
|
||||
|
||||
__invalidate_device(bdev, true);
|
||||
nbd_bdev_reset(bdev);
|
||||
/*
|
||||
* We want to give the run thread a chance to wait for everybody
|
||||
@ -781,7 +848,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||
nbd_size_set(nbd, bdev, nbd->blksize, arg);
|
||||
return 0;
|
||||
case NBD_SET_TIMEOUT:
|
||||
nbd->tag_set.timeout = arg * HZ;
|
||||
if (arg) {
|
||||
nbd->tag_set.timeout = arg * HZ;
|
||||
blk_queue_rq_timeout(nbd->disk->queue, arg * HZ);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case NBD_SET_FLAGS:
|
||||
|
Loading…
Reference in New Issue
Block a user