Commit 771e7e41 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'block-5.11-2020-12-23' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:
 "A few stragglers in here, but mostly just straight fixes. In
  particular:

   - Set of rnbd fixes for issues around changes for the merge window
     (Gioh, Jack, Md Haris Iqbal)

   - iocost tracepoint addition (Baolin)

   - Copyright/maintainers update (Christoph)

   - Remove old blk-mq fast path CPU warning (Daniel)

   - loop max_part fix (Josh)

   - Remote IPI threaded IRQ fix (Sebastian)

   - dasd stable fixes (Stefan)

   - bcache merge window fixup and style fixup (Yi, Zheng)"

* tag 'block-5.11-2020-12-23' of git://git.kernel.dk/linux-block:
  md/bcache: convert comma to semicolon
  bcache:remove a superfluous check in register_bcache
  block: update some copyrights
  block: remove a pointless self-reference in block_dev.c
  MAINTAINERS: add fs/block_dev.c to the block section
  blk-mq: Don't complete on a remote CPU in force threaded mode
  s390/dasd: fix list corruption of lcu list
  s390/dasd: fix list corruption of pavgroup group list
  s390/dasd: prevent inconsistent LCU device data
  s390/dasd: fix hanging device offline processing
  blk-iocost: Add iocg idle state tracepoint
  nbd: Respect max_part for all partition scans
  block/rnbd-clt: Does not request pdu to rtrs-clt
  block/rnbd-clt: Dynamically allocate sglist for rnbd_iu
  block/rnbd: Set write-back cache and fua same to the target device
  block/rnbd: Fix typos
  block/rnbd-srv: Protect dev session sysfs removal
  block/rnbd-clt: Fix possible memleak
  block/rnbd-clt: Get rid of warning regarding size argument in strlcpy
  blk-mq: Remove 'running from the wrong CPU' warning
parents 1f13d2f7 46926127
...@@ -3199,6 +3199,7 @@ S: Maintained ...@@ -3199,6 +3199,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
F: block/ F: block/
F: drivers/block/ F: drivers/block/
F: fs/block_dev.c
F: include/linux/blk* F: include/linux/blk*
F: kernel/trace/blktrace.c F: kernel/trace/blktrace.c
F: lib/sbitmap.c F: lib/sbitmap.c
......
...@@ -2185,6 +2185,9 @@ static int ioc_check_iocgs(struct ioc *ioc, struct ioc_now *now) ...@@ -2185,6 +2185,9 @@ static int ioc_check_iocgs(struct ioc *ioc, struct ioc_now *now)
WEIGHT_ONE); WEIGHT_ONE);
} }
TRACE_IOCG_PATH(iocg_idle, iocg, now,
atomic64_read(&iocg->active_period),
atomic64_read(&ioc->cur_period), vtime);
__propagate_weights(iocg, 0, 0, false, now); __propagate_weights(iocg, 0, 0, false, now);
list_del_init(&iocg->active_list); list_del_init(&iocg->active_list);
} }
......
...@@ -650,6 +650,14 @@ static inline bool blk_mq_complete_need_ipi(struct request *rq) ...@@ -650,6 +650,14 @@ static inline bool blk_mq_complete_need_ipi(struct request *rq)
if (!IS_ENABLED(CONFIG_SMP) || if (!IS_ENABLED(CONFIG_SMP) ||
!test_bit(QUEUE_FLAG_SAME_COMP, &rq->q->queue_flags)) !test_bit(QUEUE_FLAG_SAME_COMP, &rq->q->queue_flags))
return false; return false;
/*
* With force threaded interrupts enabled, raising softirq from an SMP
* function call will always result in waking the ksoftirqd thread.
* This is probably worse than completing the request on a different
* cache domain.
*/
if (force_irqthreads)
return false;
/* same CPU or cache domain? Complete locally */ /* same CPU or cache domain? Complete locally */
if (cpu == rq->mq_ctx->cpu || if (cpu == rq->mq_ctx->cpu ||
...@@ -1495,31 +1503,6 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) ...@@ -1495,31 +1503,6 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
{ {
int srcu_idx; int srcu_idx;
/*
* We should be running this queue from one of the CPUs that
* are mapped to it.
*
* There are at least two related races now between setting
* hctx->next_cpu from blk_mq_hctx_next_cpu() and running
* __blk_mq_run_hw_queue():
*
* - hctx->next_cpu is found offline in blk_mq_hctx_next_cpu(),
* but later it becomes online, then this warning is harmless
* at all
*
* - hctx->next_cpu is found online in blk_mq_hctx_next_cpu(),
* but later it becomes offline, then the warning can't be
* triggered, and we depend on blk-mq timeout handler to
* handle dispatched requests to this hctx
*/
if (!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) &&
cpu_online(hctx->next_cpu)) {
printk(KERN_WARNING "run queue from wrong CPU %d, hctx %s\n",
raw_smp_processor_id(),
cpumask_empty(hctx->cpumask) ? "inactive": "active");
dump_stack();
}
/* /*
* We can't run the queue inline with ints disabled. Ensure that * We can't run the queue inline with ints disabled. Ensure that
* we catch bad users of this early. * we catch bad users of this early.
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* gendisk handling * gendisk handling
*
* Portions Copyright (C) 2020 Christoph Hellwig
*/ */
#include <linux/module.h> #include <linux/module.h>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* /*
* Copyright (C) 1991-1998 Linus Torvalds * Copyright (C) 1991-1998 Linus Torvalds
* Re-organised Feb 1998 Russell King * Re-organised Feb 1998 Russell King
* Copyright (C) 2020 Christoph Hellwig
*/ */
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/slab.h> #include <linux/slab.h>
......
...@@ -318,7 +318,8 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, ...@@ -318,7 +318,8 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize,
blk_queue_logical_block_size(nbd->disk->queue, blksize); blk_queue_logical_block_size(nbd->disk->queue, blksize);
blk_queue_physical_block_size(nbd->disk->queue, blksize); blk_queue_physical_block_size(nbd->disk->queue, blksize);
set_bit(GD_NEED_PART_SCAN, &nbd->disk->state); if (max_part)
set_bit(GD_NEED_PART_SCAN, &nbd->disk->state);
if (!set_capacity_and_notify(nbd->disk, bytesize >> 9)) if (!set_capacity_and_notify(nbd->disk, bytesize >> 9))
kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE);
return 0; return 0;
...@@ -1476,9 +1477,11 @@ static int nbd_open(struct block_device *bdev, fmode_t mode) ...@@ -1476,9 +1477,11 @@ static int nbd_open(struct block_device *bdev, fmode_t mode)
refcount_set(&nbd->config_refs, 1); refcount_set(&nbd->config_refs, 1);
refcount_inc(&nbd->refs); refcount_inc(&nbd->refs);
mutex_unlock(&nbd->config_lock); mutex_unlock(&nbd->config_lock);
set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); if (max_part)
set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
} else if (nbd_disconnected(nbd->config)) { } else if (nbd_disconnected(nbd->config)) {
set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); if (max_part)
set_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
} }
out: out:
mutex_unlock(&nbd_index_mutex); mutex_unlock(&nbd_index_mutex);
......
...@@ -432,7 +432,7 @@ void rnbd_clt_remove_dev_symlink(struct rnbd_clt_dev *dev) ...@@ -432,7 +432,7 @@ void rnbd_clt_remove_dev_symlink(struct rnbd_clt_dev *dev)
* i.e. rnbd_clt_unmap_dev_store() leading to a sysfs warning because * i.e. rnbd_clt_unmap_dev_store() leading to a sysfs warning because
* of sysfs link already was removed already. * of sysfs link already was removed already.
*/ */
if (strlen(dev->blk_symlink_name) && try_module_get(THIS_MODULE)) { if (dev->blk_symlink_name && try_module_get(THIS_MODULE)) {
sysfs_remove_link(rnbd_devs_kobj, dev->blk_symlink_name); sysfs_remove_link(rnbd_devs_kobj, dev->blk_symlink_name);
kfree(dev->blk_symlink_name); kfree(dev->blk_symlink_name);
module_put(THIS_MODULE); module_put(THIS_MODULE);
...@@ -521,7 +521,8 @@ static int rnbd_clt_add_dev_symlink(struct rnbd_clt_dev *dev) ...@@ -521,7 +521,8 @@ static int rnbd_clt_add_dev_symlink(struct rnbd_clt_dev *dev)
return 0; return 0;
out_err: out_err:
dev->blk_symlink_name[0] = '\0'; kfree(dev->blk_symlink_name);
dev->blk_symlink_name = NULL ;
return ret; return ret;
} }
......
...@@ -88,6 +88,8 @@ static int rnbd_clt_set_dev_attr(struct rnbd_clt_dev *dev, ...@@ -88,6 +88,8 @@ static int rnbd_clt_set_dev_attr(struct rnbd_clt_dev *dev,
dev->discard_alignment = le32_to_cpu(rsp->discard_alignment); dev->discard_alignment = le32_to_cpu(rsp->discard_alignment);
dev->secure_discard = le16_to_cpu(rsp->secure_discard); dev->secure_discard = le16_to_cpu(rsp->secure_discard);
dev->rotational = rsp->rotational; dev->rotational = rsp->rotational;
dev->wc = !!(rsp->cache_policy & RNBD_WRITEBACK);
dev->fua = !!(rsp->cache_policy & RNBD_FUA);
dev->max_hw_sectors = sess->max_io_size / SECTOR_SIZE; dev->max_hw_sectors = sess->max_io_size / SECTOR_SIZE;
dev->max_segments = BMAX_SEGMENTS; dev->max_segments = BMAX_SEGMENTS;
...@@ -347,19 +349,26 @@ static struct rnbd_iu *rnbd_get_iu(struct rnbd_clt_session *sess, ...@@ -347,19 +349,26 @@ static struct rnbd_iu *rnbd_get_iu(struct rnbd_clt_session *sess,
struct rnbd_iu *iu; struct rnbd_iu *iu;
struct rtrs_permit *permit; struct rtrs_permit *permit;
iu = kzalloc(sizeof(*iu), GFP_KERNEL);
if (!iu) {
return NULL;
}
permit = rnbd_get_permit(sess, con_type, permit = rnbd_get_permit(sess, con_type,
wait ? RTRS_PERMIT_WAIT : wait ? RTRS_PERMIT_WAIT :
RTRS_PERMIT_NOWAIT); RTRS_PERMIT_NOWAIT);
if (unlikely(!permit)) if (unlikely(!permit)) {
kfree(iu);
return NULL; return NULL;
iu = rtrs_permit_to_pdu(permit); }
iu->permit = permit; iu->permit = permit;
/* /*
* 1st reference is dropped after finishing sending a "user" message, * 1st reference is dropped after finishing sending a "user" message,
* 2nd reference is dropped after confirmation with the response is * 2nd reference is dropped after confirmation with the response is
* returned. * returned.
* 1st and 2nd can happen in any order, so the rnbd_iu should be * 1st and 2nd can happen in any order, so the rnbd_iu should be
* released (rtrs_permit returned to ibbtrs) only leased after both * released (rtrs_permit returned to rtrs) only after both
* are finished. * are finished.
*/ */
atomic_set(&iu->refcount, 2); atomic_set(&iu->refcount, 2);
...@@ -371,8 +380,10 @@ static struct rnbd_iu *rnbd_get_iu(struct rnbd_clt_session *sess, ...@@ -371,8 +380,10 @@ static struct rnbd_iu *rnbd_get_iu(struct rnbd_clt_session *sess,
static void rnbd_put_iu(struct rnbd_clt_session *sess, struct rnbd_iu *iu) static void rnbd_put_iu(struct rnbd_clt_session *sess, struct rnbd_iu *iu)
{ {
if (atomic_dec_and_test(&iu->refcount)) if (atomic_dec_and_test(&iu->refcount)) {
rnbd_put_permit(sess, iu->permit); rnbd_put_permit(sess, iu->permit);
kfree(iu);
}
} }
static void rnbd_softirq_done_fn(struct request *rq) static void rnbd_softirq_done_fn(struct request *rq)
...@@ -382,6 +393,7 @@ static void rnbd_softirq_done_fn(struct request *rq) ...@@ -382,6 +393,7 @@ static void rnbd_softirq_done_fn(struct request *rq)
struct rnbd_iu *iu; struct rnbd_iu *iu;
iu = blk_mq_rq_to_pdu(rq); iu = blk_mq_rq_to_pdu(rq);
sg_free_table_chained(&iu->sgt, RNBD_INLINE_SG_CNT);
rnbd_put_permit(sess, iu->permit); rnbd_put_permit(sess, iu->permit);
blk_mq_end_request(rq, errno_to_blk_status(iu->errno)); blk_mq_end_request(rq, errno_to_blk_status(iu->errno));
} }
...@@ -475,7 +487,7 @@ static int send_msg_close(struct rnbd_clt_dev *dev, u32 device_id, bool wait) ...@@ -475,7 +487,7 @@ static int send_msg_close(struct rnbd_clt_dev *dev, u32 device_id, bool wait)
iu->buf = NULL; iu->buf = NULL;
iu->dev = dev; iu->dev = dev;
sg_mark_end(&iu->sglist[0]); sg_alloc_table(&iu->sgt, 1, GFP_KERNEL);
msg.hdr.type = cpu_to_le16(RNBD_MSG_CLOSE); msg.hdr.type = cpu_to_le16(RNBD_MSG_CLOSE);
msg.device_id = cpu_to_le32(device_id); msg.device_id = cpu_to_le32(device_id);
...@@ -490,6 +502,7 @@ static int send_msg_close(struct rnbd_clt_dev *dev, u32 device_id, bool wait) ...@@ -490,6 +502,7 @@ static int send_msg_close(struct rnbd_clt_dev *dev, u32 device_id, bool wait)
err = errno; err = errno;
} }
sg_free_table(&iu->sgt);
rnbd_put_iu(sess, iu); rnbd_put_iu(sess, iu);
return err; return err;
} }
...@@ -562,7 +575,8 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait) ...@@ -562,7 +575,8 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait)
iu->buf = rsp; iu->buf = rsp;
iu->dev = dev; iu->dev = dev;
sg_init_one(iu->sglist, rsp, sizeof(*rsp)); sg_alloc_table(&iu->sgt, 1, GFP_KERNEL);
sg_init_one(iu->sgt.sgl, rsp, sizeof(*rsp));
msg.hdr.type = cpu_to_le16(RNBD_MSG_OPEN); msg.hdr.type = cpu_to_le16(RNBD_MSG_OPEN);
msg.access_mode = dev->access_mode; msg.access_mode = dev->access_mode;
...@@ -570,7 +584,7 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait) ...@@ -570,7 +584,7 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait)
WARN_ON(!rnbd_clt_get_dev(dev)); WARN_ON(!rnbd_clt_get_dev(dev));
err = send_usr_msg(sess->rtrs, READ, iu, err = send_usr_msg(sess->rtrs, READ, iu,
&vec, sizeof(*rsp), iu->sglist, 1, &vec, sizeof(*rsp), iu->sgt.sgl, 1,
msg_open_conf, &errno, wait); msg_open_conf, &errno, wait);
if (err) { if (err) {
rnbd_clt_put_dev(dev); rnbd_clt_put_dev(dev);
...@@ -580,6 +594,7 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait) ...@@ -580,6 +594,7 @@ static int send_msg_open(struct rnbd_clt_dev *dev, bool wait)
err = errno; err = errno;
} }
sg_free_table(&iu->sgt);
rnbd_put_iu(sess, iu); rnbd_put_iu(sess, iu);
return err; return err;
} }
...@@ -608,7 +623,8 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait) ...@@ -608,7 +623,8 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait)
iu->buf = rsp; iu->buf = rsp;
iu->sess = sess; iu->sess = sess;
sg_init_one(iu->sglist, rsp, sizeof(*rsp)); sg_alloc_table(&iu->sgt, 1, GFP_KERNEL);
sg_init_one(iu->sgt.sgl, rsp, sizeof(*rsp));
msg.hdr.type = cpu_to_le16(RNBD_MSG_SESS_INFO); msg.hdr.type = cpu_to_le16(RNBD_MSG_SESS_INFO);
msg.ver = RNBD_PROTO_VER_MAJOR; msg.ver = RNBD_PROTO_VER_MAJOR;
...@@ -624,7 +640,7 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait) ...@@ -624,7 +640,7 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait)
goto put_iu; goto put_iu;
} }
err = send_usr_msg(sess->rtrs, READ, iu, err = send_usr_msg(sess->rtrs, READ, iu,
&vec, sizeof(*rsp), iu->sglist, 1, &vec, sizeof(*rsp), iu->sgt.sgl, 1,
msg_sess_info_conf, &errno, wait); msg_sess_info_conf, &errno, wait);
if (err) { if (err) {
rnbd_clt_put_sess(sess); rnbd_clt_put_sess(sess);
...@@ -634,7 +650,7 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait) ...@@ -634,7 +650,7 @@ static int send_msg_sess_info(struct rnbd_clt_session *sess, bool wait)
} else { } else {
err = errno; err = errno;
} }
sg_free_table(&iu->sgt);
rnbd_put_iu(sess, iu); rnbd_put_iu(sess, iu);
return err; return err;
} }
...@@ -803,7 +819,7 @@ static struct rnbd_clt_session *alloc_sess(const char *sessname) ...@@ -803,7 +819,7 @@ static struct rnbd_clt_session *alloc_sess(const char *sessname)
rnbd_init_cpu_qlists(sess->cpu_queues); rnbd_init_cpu_qlists(sess->cpu_queues);
/* /*
* That is simple percpu variable which stores cpu indeces, which are * That is simple percpu variable which stores cpu indices, which are
* incremented on each access. We need that for the sake of fairness * incremented on each access. We need that for the sake of fairness
* to wake up queues in a round-robin manner. * to wake up queues in a round-robin manner.
*/ */
...@@ -1014,11 +1030,10 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev, ...@@ -1014,11 +1030,10 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
* See queue limits. * See queue limits.
*/ */
if (req_op(rq) != REQ_OP_DISCARD) if (req_op(rq) != REQ_OP_DISCARD)
sg_cnt = blk_rq_map_sg(dev->queue, rq, iu->sglist); sg_cnt = blk_rq_map_sg(dev->queue, rq, iu->sgt.sgl);
if (sg_cnt == 0) if (sg_cnt == 0)
/* Do not forget to mark the end */ sg_mark_end(&iu->sgt.sgl[0]);
sg_mark_end(&iu->sglist[0]);
msg.hdr.type = cpu_to_le16(RNBD_MSG_IO); msg.hdr.type = cpu_to_le16(RNBD_MSG_IO);
msg.device_id = cpu_to_le32(dev->device_id); msg.device_id = cpu_to_le32(dev->device_id);
...@@ -1027,13 +1042,13 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev, ...@@ -1027,13 +1042,13 @@ static int rnbd_client_xfer_request(struct rnbd_clt_dev *dev,
.iov_base = &msg, .iov_base = &msg,
.iov_len = sizeof(msg) .iov_len = sizeof(msg)
}; };
size = rnbd_clt_get_sg_size(iu->sglist, sg_cnt); size = rnbd_clt_get_sg_size(iu->sgt.sgl, sg_cnt);
req_ops = (struct rtrs_clt_req_ops) { req_ops = (struct rtrs_clt_req_ops) {
.priv = iu, .priv = iu,
.conf_fn = msg_io_conf, .conf_fn = msg_io_conf,
}; };
err = rtrs_clt_request(rq_data_dir(rq), &req_ops, rtrs, permit, err = rtrs_clt_request(rq_data_dir(rq), &req_ops, rtrs, permit,
&vec, 1, size, iu->sglist, sg_cnt); &vec, 1, size, iu->sgt.sgl, sg_cnt);
if (unlikely(err)) { if (unlikely(err)) {
rnbd_clt_err_rl(dev, "RTRS failed to transfer IO, err: %d\n", rnbd_clt_err_rl(dev, "RTRS failed to transfer IO, err: %d\n",
err); err);
...@@ -1120,6 +1135,7 @@ static blk_status_t rnbd_queue_rq(struct blk_mq_hw_ctx *hctx, ...@@ -1120,6 +1135,7 @@ static blk_status_t rnbd_queue_rq(struct blk_mq_hw_ctx *hctx,
struct rnbd_clt_dev *dev = rq->rq_disk->private_data; struct rnbd_clt_dev *dev = rq->rq_disk->private_data;
struct rnbd_iu *iu = blk_mq_rq_to_pdu(rq); struct rnbd_iu *iu = blk_mq_rq_to_pdu(rq);
int err; int err;
blk_status_t ret = BLK_STS_IOERR;
if (unlikely(dev->dev_state != DEV_STATE_MAPPED)) if (unlikely(dev->dev_state != DEV_STATE_MAPPED))
return BLK_STS_IOERR; return BLK_STS_IOERR;
...@@ -1131,32 +1147,35 @@ static blk_status_t rnbd_queue_rq(struct blk_mq_hw_ctx *hctx, ...@@ -1131,32 +1147,35 @@ static blk_status_t rnbd_queue_rq(struct blk_mq_hw_ctx *hctx,
return BLK_STS_RESOURCE; return BLK_STS_RESOURCE;
} }
iu->sgt.sgl = iu->first_sgl;
err = sg_alloc_table_chained(&iu->sgt,
/* Even-if the request has no segment,
* sglist must have one entry at least */
blk_rq_nr_phys_segments(rq) ? : 1,
iu->sgt.sgl,
RNBD_INLINE_SG_CNT);
if (err) {
rnbd_clt_err_rl(dev, "sg_alloc_table_chained ret=%d\n", err);
rnbd_clt_dev_kick_mq_queue(dev, hctx, 10/*ms*/);
rnbd_put_permit(dev->sess, iu->permit);
return BLK_STS_RESOURCE;
}
blk_mq_start_request(rq); blk_mq_start_request(rq);
err = rnbd_client_xfer_request(dev, rq, iu); err = rnbd_client_xfer_request(dev, rq, iu);
if (likely(err == 0)) if (likely(err == 0))
return BLK_STS_OK; return BLK_STS_OK;
if (unlikely(err == -EAGAIN || err == -ENOMEM)) { if (unlikely(err == -EAGAIN || err == -ENOMEM)) {
rnbd_clt_dev_kick_mq_queue(dev, hctx, 10/*ms*/); rnbd_clt_dev_kick_mq_queue(dev, hctx, 10/*ms*/);
rnbd_put_permit(dev->sess, iu->permit); ret = BLK_STS_RESOURCE;
return BLK_STS_RESOURCE;
} }
sg_free_table_chained(&iu->sgt, RNBD_INLINE_SG_CNT);
rnbd_put_permit(dev->sess, iu->permit); rnbd_put_permit(dev->sess, iu->permit);
return BLK_STS_IOERR; return ret;
}
static int rnbd_init_request(struct blk_mq_tag_set *set, struct request *rq,
unsigned int hctx_idx, unsigned int numa_node)
{
struct rnbd_iu *iu = blk_mq_rq_to_pdu(rq);
sg_init_table(iu->sglist, BMAX_SEGMENTS);
return 0;
} }
static struct blk_mq_ops rnbd_mq_ops = { static struct blk_mq_ops rnbd_mq_ops = {
.queue_rq = rnbd_queue_rq, .queue_rq = rnbd_queue_rq,
.init_request = rnbd_init_request,
.complete = rnbd_softirq_done_fn, .complete = rnbd_softirq_done_fn,
}; };
...@@ -1170,7 +1189,7 @@ static int setup_mq_tags(struct rnbd_clt_session *sess) ...@@ -1170,7 +1189,7 @@ static int setup_mq_tags(struct rnbd_clt_session *sess)
tag_set->numa_node = NUMA_NO_NODE; tag_set->numa_node = NUMA_NO_NODE;
tag_set->flags = BLK_MQ_F_SHOULD_MERGE | tag_set->flags = BLK_MQ_F_SHOULD_MERGE |
BLK_MQ_F_TAG_QUEUE_SHARED; BLK_MQ_F_TAG_QUEUE_SHARED;
tag_set->cmd_size = sizeof(struct rnbd_iu); tag_set->cmd_size = sizeof(struct rnbd_iu) + RNBD_RDMA_SGL_SIZE;
tag_set->nr_hw_queues = num_online_cpus(); tag_set->nr_hw_queues = num_online_cpus();
return blk_mq_alloc_tag_set(tag_set); return blk_mq_alloc_tag_set(tag_set);
...@@ -1208,7 +1227,7 @@ find_and_get_or_create_sess(const char *sessname, ...@@ -1208,7 +1227,7 @@ find_and_get_or_create_sess(const char *sessname,
*/ */
sess->rtrs = rtrs_clt_open(&rtrs_ops, sessname, sess->rtrs = rtrs_clt_open(&rtrs_ops, sessname,
paths, path_cnt, port_nr, paths, path_cnt, port_nr,
sizeof(struct rnbd_iu), 0, /* Do not use pdu of rtrs */
RECONNECT_DELAY, BMAX_SEGMENTS, RECONNECT_DELAY, BMAX_SEGMENTS,
BLK_MAX_SEGMENT_SIZE, BLK_MAX_SEGMENT_SIZE,
MAX_RECONNECTS); MAX_RECONNECTS);
...@@ -1305,7 +1324,7 @@ static void setup_request_queue(struct rnbd_clt_dev *dev) ...@@ -1305,7 +1324,7 @@ static void setup_request_queue(struct rnbd_clt_dev *dev)
blk_queue_max_segments(dev->queue, dev->max_segments); blk_queue_max_segments(dev->queue, dev->max_segments);
blk_queue_io_opt(dev->queue, dev->sess->max_io_size); blk_queue_io_opt(dev->queue, dev->sess->max_io_size);
blk_queue_virt_boundary(dev->queue, SZ_4K - 1); blk_queue_virt_boundary(dev->queue, SZ_4K - 1);
blk_queue_write_cache(dev->queue, true, true); blk_queue_write_cache(dev->queue, dev->wc, dev->fua);
dev->queue->queuedata = dev; dev->queue->queuedata = dev;
} }
...@@ -1388,12 +1407,11 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess, ...@@ -1388,12 +1407,11 @@ static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
goto out_queues; goto out_queues;
} }
dev->pathname = kzalloc(strlen(pathname) + 1, GFP_KERNEL); dev->pathname = kstrdup(pathname, GFP_KERNEL);
if (!dev->pathname) { if (!dev->pathname) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_queues; goto out_queues;
} }
strlcpy(dev->pathname, pathname, strlen(pathname) + 1);
dev->clt_device_id = ret; dev->clt_device_id = ret;
dev->sess = sess; dev->sess = sess;
...@@ -1529,13 +1547,13 @@ struct rnbd_clt_dev *rnbd_clt_map_device(const char *sessname, ...@@ -1529,13 +1547,13 @@ struct rnbd_clt_dev *rnbd_clt_map_device(const char *sessname,
} }
rnbd_clt_info(dev, rnbd_clt_info(dev,
"map_device: Device mapped as %s (nsectors: %zu, logical_block_size: %d, physical_block_size: %d, max_write_same_sectors: %d, max_discard_sectors: %d, discard_granularity: %d, discard_alignment: %d, secure_discard: %d, max_segments: %d, max_hw_sectors: %d, rotational: %d)\n", "map_device: Device mapped as %s (nsectors: %zu, logical_block_size: %d, physical_block_size: %d, max_write_same_sectors: %d, max_discard_sectors: %d, discard_granularity: %d, discard_alignment: %d, secure_discard: %d, max_segments: %d, max_hw_sectors: %d, rotational: %d, wc: %d, fua: %d)\n",
dev->gd->disk_name, dev->nsectors, dev->gd->disk_name, dev->nsectors,
dev->logical_block_size, dev->physical_block_size, dev->logical_block_size, dev->physical_block_size,
dev->max_write_same_sectors, dev->max_discard_sectors, dev->max_write_same_sectors, dev->max_discard_sectors,
dev->discard_granularity, dev->discard_alignment, dev->discard_granularity, dev->discard_alignment,
dev->secure_discard, dev->max_segments, dev->secure_discard, dev->max_segments,
dev->max_hw_sectors, dev->rotational); dev->max_hw_sectors, dev->rotational, dev->wc, dev->fua);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
...@@ -1667,7 +1685,7 @@ static void rnbd_destroy_sessions(void) ...@@ -1667,7 +1685,7 @@ static void rnbd_destroy_sessions(void)
/* /*
* Here at this point there is no any concurrent access to sessions * Here at this point there is no any concurrent access to sessions
* list and devices list: * list and devices list:
* 1. New session or device can'be be created - session sysfs files * 1. New session or device can't be created - session sysfs files
* are removed. * are removed.
* 2. Device or session can't be removed - module reference is taken * 2. Device or session can't be removed - module reference is taken
* into account in unmap device sysfs callback. * into account in unmap device sysfs callback.
......
...@@ -44,6 +44,13 @@ struct rnbd_iu_comp { ...@@ -44,6 +44,13 @@ struct rnbd_iu_comp {
int errno; int errno;
}; };
#ifdef CONFIG_ARCH_NO_SG_CHAIN
#define RNBD_INLINE_SG_CNT 0
#else
#define RNBD_INLINE_SG_CNT 2
#endif
#define RNBD_RDMA_SGL_SIZE (sizeof(struct scatterlist) * RNBD_INLINE_SG_CNT)
struct rnbd_iu { struct rnbd_iu {
union { union {
struct request *rq; /* for block io */ struct request *rq; /* for block io */
...@@ -56,11 +63,12 @@ struct rnbd_iu { ...@@ -56,11 +63,12 @@ struct rnbd_iu {
/* use to send msg associated with a sess */ /* use to send msg associated with a sess */
struct rnbd_clt_session *sess; struct rnbd_clt_session *sess;
}; };
struct scatterlist sglist[BMAX_SEGMENTS]; struct sg_table sgt;
struct work_struct work; struct work_struct work;
int errno; int errno;
struct rnbd_iu_comp comp; struct rnbd_iu_comp comp;
atomic_t refcount; atomic_t refcount;
struct scatterlist first_sgl[]; /* must be the last one */
}; };
struct rnbd_cpu_qlist { struct rnbd_cpu_qlist {
...@@ -112,6 +120,8 @@ struct rnbd_clt_dev { ...@@ -112,6 +120,8 @@ struct rnbd_clt_dev {
enum rnbd_access_mode access_mode; enum rnbd_access_mode access_mode;
bool read_only; bool read_only;
bool rotational; bool rotational;
bool wc;
bool fua;
u32 max_hw_sectors; u32 max_hw_sectors;
u32 max_write_same_sectors; u32 max_write_same_sectors;
u32 max_discard_sectors; u32 max_discard_sectors;
......
...@@ -108,6 +108,11 @@ struct rnbd_msg_close { ...@@ -108,6 +108,11 @@ struct rnbd_msg_close {
__le32 device_id; __le32 device_id;
}; };
enum rnbd_cache_policy {
RNBD_FUA = 1 << 0,
RNBD_WRITEBACK = 1 << 1,
};
/** /**
* struct rnbd_msg_open_rsp - response message to RNBD_MSG_OPEN * struct rnbd_msg_open_rsp - response message to RNBD_MSG_OPEN
* @hdr: message header * @hdr: message header
...@@ -124,6 +129,7 @@ struct rnbd_msg_close { ...@@ -124,6 +129,7 @@ struct rnbd_msg_close {
* @max_segments: max segments hardware support in one transfer * @max_segments: max segments hardware support in one transfer
* @secure_discard: supports secure discard * @secure_discard: supports secure discard
* @rotation: is a rotational disc? * @rotation: is a rotational disc?
* @cache_policy: support write-back caching or FUA?
*/ */
struct rnbd_msg_open_rsp { struct rnbd_msg_open_rsp {
struct rnbd_msg_hdr hdr; struct rnbd_msg_hdr hdr;
...@@ -139,7 +145,8 @@ struct rnbd_msg_open_rsp { ...@@ -139,7 +145,8 @@ struct rnbd_msg_open_rsp {
__le16 max_segments; __le16 max_segments;
__le16 secure_discard; __le16 secure_discard;
u8 rotational; u8 rotational;
u8 reserved[11]; u8 cache_policy;
u8 reserved[10];
}; };
/** /**
......
...@@ -338,9 +338,10 @@ static int rnbd_srv_link_ev(struct rtrs_srv *rtrs, ...@@ -338,9 +338,10 @@ static int rnbd_srv_link_ev(struct rtrs_srv *rtrs,
void rnbd_srv_sess_dev_force_close(struct rnbd_srv_sess_dev *sess_dev) void rnbd_srv_sess_dev_force_close(struct rnbd_srv_sess_dev *sess_dev)
{ {
mutex_lock(&sess_dev->sess->lock);
rnbd_srv_destroy_dev_session_sysfs(sess_dev); rnbd_srv_destroy_dev_session_sysfs(sess_dev);
mutex_unlock(&sess_dev->sess->lock);
sess_dev->keep_id = true; sess_dev->keep_id = true;
} }
static int process_msg_close(struct rtrs_srv *rtrs, static int process_msg_close(struct rtrs_srv *rtrs,
...@@ -549,6 +550,7 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp, ...@@ -549,6 +550,7 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp,
struct rnbd_srv_sess_dev *sess_dev) struct rnbd_srv_sess_dev *sess_dev)
{ {
struct rnbd_dev *rnbd_dev = sess_dev->rnbd_dev; struct rnbd_dev *rnbd_dev = sess_dev->rnbd_dev;
struct request_queue *q = bdev_get_queue(rnbd_dev->bdev);
rsp->hdr.type = cpu_to_le16(RNBD_MSG_OPEN_RSP); rsp->hdr.type = cpu_to_le16(RNBD_MSG_OPEN_RSP);
rsp->device_id = rsp->device_id =
...@@ -573,8 +575,12 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp, ...@@ -573,8 +575,12 @@ static void rnbd_srv_fill_msg_open_rsp(struct rnbd_msg_open_rsp *rsp,
cpu_to_le32(rnbd_dev_get_discard_alignment(rnbd_dev)); cpu_to_le32(rnbd_dev_get_discard_alignment(rnbd_dev));
rsp->secure_discard = rsp->secure_discard =
cpu_to_le16(rnbd_dev_get_secure_discard(rnbd_dev)); cpu_to_le16(rnbd_dev_get_secure_discard(rnbd_dev));
rsp->rotational = rsp->rotational = !blk_queue_nonrot(q);
!blk_queue_nonrot(bdev_get_queue(rnbd_dev->bdev)); rsp->cache_policy = 0;
if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
rsp->cache_policy |= RNBD_WRITEBACK;
if (blk_queue_fua(q))
rsp->cache_policy |= RNBD_FUA;
} }
static struct rnbd_srv_sess_dev * static struct rnbd_srv_sess_dev *
......
...@@ -157,12 +157,6 @@ void rtrs_clt_put_permit(struct rtrs_clt *clt, struct rtrs_permit *permit) ...@@ -157,12 +157,6 @@ void rtrs_clt_put_permit(struct rtrs_clt *clt, struct rtrs_permit *permit)
} }
EXPORT_SYMBOL(rtrs_clt_put_permit); EXPORT_SYMBOL(rtrs_clt_put_permit);
void *rtrs_permit_to_pdu(struct rtrs_permit *permit)
{
return permit + 1;
}
EXPORT_SYMBOL(rtrs_permit_to_pdu);
/** /**
* rtrs_permit_to_clt_con() - returns RDMA connection pointer by the permit * rtrs_permit_to_clt_con() - returns RDMA connection pointer by the permit
* @sess: client session pointer * @sess: client session pointer
......
...@@ -63,13 +63,6 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops, ...@@ -63,13 +63,6 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops,
void rtrs_clt_close(struct rtrs_clt *sess); void rtrs_clt_close(struct rtrs_clt *sess);
/**
* rtrs_permit_to_pdu() - converts rtrs_permit to opaque pdu pointer
* @permit: RTRS permit pointer, it associates the memory allocation for future
* RDMA operation.
*/
void *rtrs_permit_to_pdu(struct rtrs_permit *permit);
enum { enum {
RTRS_PERMIT_NOWAIT = 0, RTRS_PERMIT_NOWAIT = 0,
RTRS_PERMIT_WAIT = 1, RTRS_PERMIT_WAIT = 1,
......
...@@ -2535,8 +2535,6 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr, ...@@ -2535,8 +2535,6 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
else else
err = "device busy"; err = "device busy";
mutex_unlock(&bch_register_lock); mutex_unlock(&bch_register_lock);
if (!IS_ERR(bdev))
bdput(bdev);
if (attr == &ksysfs_register_quiet) if (attr == &ksysfs_register_quiet)
goto done; goto done;
} }
......
...@@ -404,7 +404,7 @@ STORE(__cached_dev) ...@@ -404,7 +404,7 @@ STORE(__cached_dev)
if (!env) if (!env)
return -ENOMEM; return -ENOMEM;
add_uevent_var(env, "DRIVER=bcache"); add_uevent_var(env, "DRIVER=bcache");
add_uevent_var(env, "CACHED_UUID=%pU", dc->sb.uuid), add_uevent_var(env, "CACHED_UUID=%pU", dc->sb.uuid);
add_uevent_var(env, "CACHED_LABEL=%s", buf); add_uevent_var(env, "CACHED_LABEL=%s", buf);
kobject_uevent_env(&disk_to_dev(dc->disk.disk)->kobj, kobject_uevent_env(&disk_to_dev(dc->disk.disk)->kobj,
KOBJ_CHANGE, KOBJ_CHANGE,
......
...@@ -256,7 +256,6 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) ...@@ -256,7 +256,6 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
return; return;
device->discipline->get_uid(device, &uid); device->discipline->get_uid(device, &uid);
spin_lock_irqsave(&lcu->lock, flags); spin_lock_irqsave(&lcu->lock, flags);
list_del_init(&device->alias_list);
/* make sure that the workers don't use this device */ /* make sure that the workers don't use this device */
if (device == lcu->suc_data.device) { if (device == lcu->suc_data.device) {
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
...@@ -283,6 +282,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) ...@@ -283,6 +282,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
spin_lock_irqsave(&aliastree.lock, flags); spin_lock_irqsave(&aliastree.lock, flags);
spin_lock(&lcu->lock); spin_lock(&lcu->lock);
list_del_init(&device->alias_list);
if (list_empty(&lcu->grouplist) && if (list_empty(&lcu->grouplist) &&
list_empty(&lcu->active_devices) && list_empty(&lcu->active_devices) &&
list_empty(&lcu->inactive_devices)) { list_empty(&lcu->inactive_devices)) {
...@@ -462,11 +462,19 @@ static int read_unit_address_configuration(struct dasd_device *device, ...@@ -462,11 +462,19 @@ static int read_unit_address_configuration(struct dasd_device *device,
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
rc = dasd_sleep_on(cqr); rc = dasd_sleep_on(cqr);
if (rc && !suborder_not_supported(cqr)) { if (!rc)
goto out;
if (suborder_not_supported(cqr)) {
/* suborder not supported or device unusable for IO */
rc = -EOPNOTSUPP;
} else {
/* IO failed but should be retried */
spin_lock_irqsave(&lcu->lock, flags); spin_lock_irqsave(&lcu->lock, flags);
lcu->flags |= NEED_UAC_UPDATE; lcu->flags |= NEED_UAC_UPDATE;
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
} }
out:
dasd_sfree_request(cqr, cqr->memdev); dasd_sfree_request(cqr, cqr->memdev);
return rc; return rc;
} }
...@@ -503,6 +511,14 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) ...@@ -503,6 +511,14 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)
return rc; return rc;
spin_lock_irqsave(&lcu->lock, flags); spin_lock_irqsave(&lcu->lock, flags);
/*
* there is another update needed skip the remaining handling
* the data might already be outdated
* but especially do not add the device to an LCU with pending
* update
*/
if (lcu->flags & NEED_UAC_UPDATE)
goto out;
lcu->pav = NO_PAV; lcu->pav = NO_PAV;
for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) {
switch (lcu->uac->unit[i].ua_type) { switch (lcu->uac->unit[i].ua_type) {
...@@ -521,6 +537,7 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) ...@@ -521,6 +537,7 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)
alias_list) { alias_list) {
_add_device_to_lcu(lcu, device, refdev); _add_device_to_lcu(lcu, device, refdev);
} }
out:
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
return 0; return 0;
} }
...@@ -625,6 +642,7 @@ int dasd_alias_add_device(struct dasd_device *device) ...@@ -625,6 +642,7 @@ int dasd_alias_add_device(struct dasd_device *device)
} }
if (lcu->flags & UPDATE_PENDING) { if (lcu->flags & UPDATE_PENDING) {
list_move(&device->alias_list, &lcu->active_devices); list_move(&device->alias_list, &lcu->active_devices);
private->pavgroup = NULL;
_schedule_lcu_update(lcu, device); _schedule_lcu_update(lcu, device);
} }
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
......
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* linux/fs/block_dev.c
*
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
* Copyright (C) 2016 - 2020 Christoph Hellwig
*/ */
#include <linux/init.h> #include <linux/init.h>
......
...@@ -11,7 +11,7 @@ struct ioc_gq; ...@@ -11,7 +11,7 @@ struct ioc_gq;
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
TRACE_EVENT(iocost_iocg_activate, DECLARE_EVENT_CLASS(iocost_iocg_state,
TP_PROTO(struct ioc_gq *iocg, const char *path, struct ioc_now *now, TP_PROTO(struct ioc_gq *iocg, const char *path, struct ioc_now *now,
u64 last_period, u64 cur_period, u64 vtime), u64 last_period, u64 cur_period, u64 vtime),
...@@ -59,6 +59,20 @@ TRACE_EVENT(iocost_iocg_activate, ...@@ -59,6 +59,20 @@ TRACE_EVENT(iocost_iocg_activate,
) )
); );
DEFINE_EVENT(iocost_iocg_state, iocost_iocg_activate,
TP_PROTO(struct ioc_gq *iocg, const char *path, struct ioc_now *now,
u64 last_period, u64 cur_period, u64 vtime),
TP_ARGS(iocg, path, now, last_period, cur_period, vtime)
);
DEFINE_EVENT(iocost_iocg_state, iocost_iocg_idle,
TP_PROTO(struct ioc_gq *iocg, const char *path, struct ioc_now *now,
u64 last_period, u64 cur_period, u64 vtime),
TP_ARGS(iocg, path, now, last_period, cur_period, vtime)
);
DECLARE_EVENT_CLASS(iocg_inuse_update, DECLARE_EVENT_CLASS(iocg_inuse_update,
TP_PROTO(struct ioc_gq *iocg, const char *path, struct ioc_now *now, TP_PROTO(struct ioc_gq *iocg, const char *path, struct ioc_now *now,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment