* [PATCH 3/8] sd: remove write same support
From: Christoph Hellwig @ 2017-04-10 16:08 UTC (permalink / raw)
To: axboe, martin.petersen, philipp.reisner, lars.ellenberg,
target-devel
Cc: linux-block, linux-scsi, drbd-dev, dm-devel
In-Reply-To: <20170410160807.23674-1-hch@lst.de>
There are no more end-users of REQ_OP_WRITE_SAME left, so we can start
deleting it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/scsi/sd.c | 70 ---------------------------------------------------
drivers/scsi/sd_zbc.c | 1 -
2 files changed, 71 deletions(-)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8cf34a8e3eea..a905802e927e 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -878,77 +878,10 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
sdkp->zeroing_mode = SD_ZERO_WRITE;
out:
- blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks *
- (logical_block_size >> 9));
blk_queue_max_write_zeroes_sectors(q, sdkp->max_ws_blocks *
(logical_block_size >> 9));
}
-/**
- * sd_setup_write_same_cmnd - write the same data to multiple blocks
- * @cmd: command to prepare
- *
- * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
- * preference indicated by target device.
- **/
-static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd)
-{
- struct request *rq = cmd->request;
- struct scsi_device *sdp = cmd->device;
- struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
- struct bio *bio = rq->bio;
- sector_t sector = blk_rq_pos(rq);
- unsigned int nr_sectors = blk_rq_sectors(rq);
- unsigned int nr_bytes = blk_rq_bytes(rq);
- int ret;
-
- if (sdkp->device->no_write_same)
- return BLKPREP_INVALID;
-
- BUG_ON(bio_offset(bio) || bio_iovec(bio).bv_len != sdp->sector_size);
-
- if (sd_is_zoned(sdkp)) {
- ret = sd_zbc_setup_write_cmnd(cmd);
- if (ret != BLKPREP_OK)
- return ret;
- }
-
- sector >>= ilog2(sdp->sector_size) - 9;
- nr_sectors >>= ilog2(sdp->sector_size) - 9;
-
- rq->timeout = SD_WRITE_SAME_TIMEOUT;
-
- if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
- cmd->cmd_len = 16;
- cmd->cmnd[0] = WRITE_SAME_16;
- put_unaligned_be64(sector, &cmd->cmnd[2]);
- put_unaligned_be32(nr_sectors, &cmd->cmnd[10]);
- } else {
- cmd->cmd_len = 10;
- cmd->cmnd[0] = WRITE_SAME;
- put_unaligned_be32(sector, &cmd->cmnd[2]);
- put_unaligned_be16(nr_sectors, &cmd->cmnd[7]);
- }
-
- cmd->transfersize = sdp->sector_size;
- cmd->allowed = SD_MAX_RETRIES;
-
- /*
- * For WRITE SAME the data transferred via the DATA OUT buffer is
- * different from the amount of data actually written to the target.
- *
- * We set up __data_len to the amount of data transferred via the
- * DATA OUT buffer so that blk_rq_map_sg sets up the proper S/G list
- * to transfer a single sector of data first, but then reset it to
- * the amount of data to be written right after so that the I/O path
- * knows how much to actually write.
- */
- rq->__data_len = sdp->sector_size;
- ret = scsi_init_io(cmd);
- rq->__data_len = nr_bytes;
- return ret;
-}
-
static int sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
{
struct request *rq = cmd->request;
@@ -1232,8 +1165,6 @@ static int sd_init_command(struct scsi_cmnd *cmd)
}
case REQ_OP_WRITE_ZEROES:
return sd_setup_write_zeroes_cmnd(cmd);
- case REQ_OP_WRITE_SAME:
- return sd_setup_write_same_cmnd(cmd);
case REQ_OP_FLUSH:
return sd_setup_flush_cmnd(cmd);
case REQ_OP_READ:
@@ -1872,7 +1803,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
switch (req_op(req)) {
case REQ_OP_DISCARD:
case REQ_OP_WRITE_ZEROES:
- case REQ_OP_WRITE_SAME:
case REQ_OP_ZONE_RESET:
if (!result) {
good_bytes = blk_rq_bytes(req);
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 1994f7799fce..8af6c9cd30ca 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -330,7 +330,6 @@ void sd_zbc_complete(struct scsi_cmnd *cmd,
switch (req_op(rq)) {
case REQ_OP_WRITE:
case REQ_OP_WRITE_ZEROES:
- case REQ_OP_WRITE_SAME:
case REQ_OP_ZONE_RESET:
/* Unlock the zone */
--
2.11.0
^ permalink raw reply related
* [PATCH 4/8] md: drop WRITE_SAME support
From: Christoph Hellwig @ 2017-04-10 16:08 UTC (permalink / raw)
To: axboe, martin.petersen, philipp.reisner, lars.ellenberg,
target-devel
Cc: linux-block, linux-scsi, drbd-dev, dm-devel
In-Reply-To: <20170410160807.23674-1-hch@lst.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/md/linear.c | 1 -
drivers/md/md.h | 7 -------
drivers/md/multipath.c | 1 -
drivers/md/raid0.c | 2 --
drivers/md/raid1.c | 4 +---
drivers/md/raid10.c | 1 -
drivers/md/raid5.c | 1 -
7 files changed, 1 insertion(+), 16 deletions(-)
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 377a8a3672e3..da363f5d54b0 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -292,7 +292,6 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
trace_block_bio_remap(bdev_get_queue(split->bi_bdev),
split, disk_devt(mddev->gendisk),
bio_sector);
- mddev_check_writesame(mddev, split);
mddev_check_write_zeroes(mddev, split);
generic_make_request(split);
}
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 1e76d64ce180..d82b11b5ae5a 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -703,13 +703,6 @@ static inline void mddev_clear_unsupported_flags(struct mddev *mddev,
mddev->flags &= ~unsupported_flags;
}
-static inline void mddev_check_writesame(struct mddev *mddev, struct bio *bio)
-{
- if (bio_op(bio) == REQ_OP_WRITE_SAME &&
- !bdev_get_queue(bio->bi_bdev)->limits.max_write_same_sectors)
- mddev->queue->limits.max_write_same_sectors = 0;
-}
-
static inline void mddev_check_write_zeroes(struct mddev *mddev, struct bio *bio)
{
if (bio_op(bio) == REQ_OP_WRITE_ZEROES &&
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index e95d521d93e9..68d67a404aab 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -138,7 +138,6 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
mp_bh->bio.bi_opf |= REQ_FAILFAST_TRANSPORT;
mp_bh->bio.bi_end_io = multipath_end_request;
mp_bh->bio.bi_private = mp_bh;
- mddev_check_writesame(mddev, &mp_bh->bio);
mddev_check_write_zeroes(mddev, &mp_bh->bio);
generic_make_request(&mp_bh->bio);
return;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index ce7a6a56cf73..c094749c11e5 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -382,7 +382,6 @@ static int raid0_run(struct mddev *mddev)
bool discard_supported = false;
blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
- blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
blk_queue_max_write_zeroes_sectors(mddev->queue, mddev->chunk_sectors);
blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
@@ -504,7 +503,6 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
trace_block_bio_remap(bdev_get_queue(split->bi_bdev),
split, disk_devt(mddev->gendisk),
bio_sector);
- mddev_check_writesame(mddev, split);
mddev_check_write_zeroes(mddev, split);
generic_make_request(split);
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index b59cc100320a..ac9ef686e625 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -3177,10 +3177,8 @@ static int raid1_run(struct mddev *mddev)
if (IS_ERR(conf))
return PTR_ERR(conf);
- if (mddev->queue) {
- blk_queue_max_write_same_sectors(mddev->queue, 0);
+ if (mddev->queue)
blk_queue_max_write_zeroes_sectors(mddev->queue, 0);
- }
rdev_for_each(rdev, mddev) {
if (!mddev->gendisk)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 28ec3a93acee..79988908f862 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -3748,7 +3748,6 @@ static int raid10_run(struct mddev *mddev)
if (mddev->queue) {
blk_queue_max_discard_sectors(mddev->queue,
mddev->chunk_sectors);
- blk_queue_max_write_same_sectors(mddev->queue, 0);
blk_queue_max_write_zeroes_sectors(mddev->queue, 0);
blk_queue_io_min(mddev->queue, chunk_size);
if (conf->geo.raid_disks % conf->geo.near_copies)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2efdb0d67460..04fd6a946825 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -7262,7 +7262,6 @@ static int raid5_run(struct mddev *mddev)
blk_queue_max_discard_sectors(mddev->queue,
0xfffe * STRIPE_SECTORS);
- blk_queue_max_write_same_sectors(mddev->queue, 0);
blk_queue_max_write_zeroes_sectors(mddev->queue, 0);
rdev_for_each(rdev, mddev) {
--
2.11.0
^ permalink raw reply related
* [PATCH 5/8] dm: remove write same support
From: Christoph Hellwig @ 2017-04-10 16:08 UTC (permalink / raw)
To: axboe, martin.petersen, philipp.reisner, lars.ellenberg,
target-devel
Cc: linux-block, linux-scsi, drbd-dev, dm-devel
In-Reply-To: <20170410160807.23674-1-hch@lst.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/md/dm-core.h | 1 -
drivers/md/dm-io.c | 21 +--------------------
drivers/md/dm-linear.c | 1 -
drivers/md/dm-mpath.c | 1 -
drivers/md/dm-rq.c | 3 ---
drivers/md/dm-stripe.c | 4 +---
drivers/md/dm-table.c | 29 -----------------------------
drivers/md/dm.c | 23 -----------------------
include/linux/device-mapper.h | 6 ------
9 files changed, 2 insertions(+), 87 deletions(-)
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index fea5bd52ada8..d661801d72e7 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -131,7 +131,6 @@ struct mapped_device {
void dm_init_md_queue(struct mapped_device *md);
void dm_init_normal_md_queue(struct mapped_device *md);
int md_in_flight(struct mapped_device *md);
-void disable_write_same(struct mapped_device *md);
void disable_write_zeroes(struct mapped_device *md);
static inline struct completion *dm_get_completion_from_kobject(struct kobject *kobj)
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 3702e502466d..105e68dabd3e 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -303,7 +303,6 @@ static void do_region(int op, int op_flags, unsigned region,
unsigned num_bvecs;
sector_t remaining = where->count;
struct request_queue *q = bdev_get_queue(where->bdev);
- unsigned short logical_block_size = queue_logical_block_size(q);
sector_t num_sectors;
unsigned int uninitialized_var(special_cmd_max_sectors);
@@ -314,10 +313,7 @@ static void do_region(int op, int op_flags, unsigned region,
special_cmd_max_sectors = q->limits.max_discard_sectors;
else if (op == REQ_OP_WRITE_ZEROES)
special_cmd_max_sectors = q->limits.max_write_zeroes_sectors;
- else if (op == REQ_OP_WRITE_SAME)
- special_cmd_max_sectors = q->limits.max_write_same_sectors;
- if ((op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES ||
- op == REQ_OP_WRITE_SAME) &&
+ if ((op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES) &&
special_cmd_max_sectors == 0) {
dec_count(io, region, -EOPNOTSUPP);
return;
@@ -336,9 +332,6 @@ static void do_region(int op, int op_flags, unsigned region,
case REQ_OP_WRITE_ZEROES:
num_bvecs = 0;
break;
- case REQ_OP_WRITE_SAME:
- num_bvecs = 1;
- break;
default:
num_bvecs = min_t(int, BIO_MAX_PAGES,
dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT)));
@@ -355,18 +348,6 @@ static void do_region(int op, int op_flags, unsigned region,
num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
remaining -= num_sectors;
- } else if (op == REQ_OP_WRITE_SAME) {
- /*
- * WRITE SAME only uses a single page.
- */
- dp->get_page(dp, &page, &len, &offset);
- bio_add_page(bio, page, logical_block_size, offset);
- num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining);
- bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT;
-
- offset = 0;
- remaining -= num_sectors;
- dp->next_page(dp);
} else while (remaining) {
/*
* Try and add as many pages as possible.
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index e17fd44ceef5..f928f7e9ee4a 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -58,7 +58,6 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ti->num_flush_bios = 1;
ti->num_discard_bios = 1;
- ti->num_write_same_bios = 1;
ti->num_write_zeroes_bios = 1;
ti->private = lc;
return 0;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index ab55955ed704..ece53947b99d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1102,7 +1102,6 @@ static int multipath_ctr(struct dm_target *ti, unsigned argc, char **argv)
ti->num_flush_bios = 1;
ti->num_discard_bios = 1;
- ti->num_write_same_bios = 1;
ti->num_write_zeroes_bios = 1;
if (m->queue_mode == DM_TYPE_BIO_BASED)
ti->per_io_data_size = multipath_per_bio_data_size();
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index e60f1b6845be..6f8dc99685f2 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -299,9 +299,6 @@ static void dm_done(struct request *clone, int error, bool mapped)
}
if (unlikely(r == -EREMOTEIO)) {
- if (req_op(clone) == REQ_OP_WRITE_SAME &&
- !clone->q->limits.max_write_same_sectors)
- disable_write_same(tio->md);
if (req_op(clone) == REQ_OP_WRITE_ZEROES &&
!clone->q->limits.max_write_zeroes_sectors)
disable_write_zeroes(tio->md);
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 5ef49c121d99..cc5a00f2e2de 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -168,7 +168,6 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
ti->num_flush_bios = stripes;
ti->num_discard_bios = stripes;
- ti->num_write_same_bios = stripes;
ti->num_write_zeroes_bios = stripes;
sc->chunk_size = chunk_size;
@@ -294,8 +293,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_REMAPPED;
}
if (unlikely(bio_op(bio) == REQ_OP_DISCARD) ||
- unlikely(bio_op(bio) == REQ_OP_WRITE_ZEROES) ||
- unlikely(bio_op(bio) == REQ_OP_WRITE_SAME)) {
+ unlikely(bio_op(bio) == REQ_OP_WRITE_ZEROES)) {
target_bio_nr = dm_bio_get_target_bio_nr(bio);
BUG_ON(target_bio_nr >= sc->stripes);
return stripe_map_range(sc, bio, target_bio_nr);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 958275aca008..8bbc3d57fcc7 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1490,33 +1490,6 @@ static bool dm_table_all_devices_attribute(struct dm_table *t,
return true;
}
-static int device_not_write_same_capable(struct dm_target *ti, struct dm_dev *dev,
- sector_t start, sector_t len, void *data)
-{
- struct request_queue *q = bdev_get_queue(dev->bdev);
-
- return q && !q->limits.max_write_same_sectors;
-}
-
-static bool dm_table_supports_write_same(struct dm_table *t)
-{
- struct dm_target *ti;
- unsigned i = 0;
-
- while (i < dm_table_get_num_targets(t)) {
- ti = dm_table_get_target(t, i++);
-
- if (!ti->num_write_same_bios)
- return false;
-
- if (!ti->type->iterate_devices ||
- ti->type->iterate_devices(ti, device_not_write_same_capable, NULL))
- return false;
- }
-
- return true;
-}
-
static int device_not_write_zeroes_capable(struct dm_target *ti, struct dm_dev *dev,
sector_t start, sector_t len, void *data)
{
@@ -1610,8 +1583,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
else
queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
- if (!dm_table_supports_write_same(t))
- q->limits.max_write_same_sectors = 0;
if (!dm_table_supports_write_zeroes(t))
q->limits.max_write_zeroes_sectors = 0;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 8bf397729bbd..8259aa76839e 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -816,14 +816,6 @@ static void dec_pending(struct dm_io *io, int error)
}
}
-void disable_write_same(struct mapped_device *md)
-{
- struct queue_limits *limits = dm_get_queue_limits(md);
-
- /* device doesn't really support WRITE SAME, disable it */
- limits->max_write_same_sectors = 0;
-}
-
void disable_write_zeroes(struct mapped_device *md)
{
struct queue_limits *limits = dm_get_queue_limits(md);
@@ -859,9 +851,6 @@ static void clone_endio(struct bio *bio)
}
if (unlikely(r == -EREMOTEIO)) {
- if (bio_op(bio) == REQ_OP_WRITE_SAME &&
- !bdev_get_queue(bio->bi_bdev)->limits.max_write_same_sectors)
- disable_write_same(md);
if (bio_op(bio) == REQ_OP_WRITE_ZEROES &&
!bdev_get_queue(bio->bi_bdev)->limits.max_write_zeroes_sectors)
disable_write_zeroes(md);
@@ -1209,11 +1198,6 @@ static unsigned get_num_discard_bios(struct dm_target *ti)
return ti->num_discard_bios;
}
-static unsigned get_num_write_same_bios(struct dm_target *ti)
-{
- return ti->num_write_same_bios;
-}
-
static unsigned get_num_write_zeroes_bios(struct dm_target *ti)
{
return ti->num_write_zeroes_bios;
@@ -1268,11 +1252,6 @@ static int __send_discard(struct clone_info *ci)
is_split_required_for_discard);
}
-static int __send_write_same(struct clone_info *ci)
-{
- return __send_changing_extent_only(ci, get_num_write_same_bios, NULL);
-}
-
static int __send_write_zeroes(struct clone_info *ci)
{
return __send_changing_extent_only(ci, get_num_write_zeroes_bios, NULL);
@@ -1290,8 +1269,6 @@ static int __split_and_process_non_flush(struct clone_info *ci)
if (unlikely(bio_op(bio) == REQ_OP_DISCARD))
return __send_discard(ci);
- else if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
- return __send_write_same(ci);
else if (unlikely(bio_op(bio) == REQ_OP_WRITE_ZEROES))
return __send_write_zeroes(ci);
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index c7ea33e38fb9..58f451ba9b75 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -249,12 +249,6 @@ struct dm_target {
unsigned num_discard_bios;
/*
- * The number of WRITE SAME bios that will be submitted to the target.
- * The bio number can be accessed with dm_bio_get_target_bio_nr.
- */
- unsigned num_write_same_bios;
-
- /*
* The number of WRITE ZEROES bios that will be submitted to the target.
* The bio number can be accessed with dm_bio_get_target_bio_nr.
*/
--
2.11.0
^ permalink raw reply related
* [PATCH 6/8] block: remove REQ_OP_WRITE_SAME support
From: Christoph Hellwig @ 2017-04-10 16:08 UTC (permalink / raw)
To: axboe, martin.petersen, philipp.reisner, lars.ellenberg,
target-devel
Cc: linux-block, linux-scsi, drbd-dev, dm-devel
In-Reply-To: <20170410160807.23674-1-hch@lst.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/bio.c | 3 --
block/blk-core.c | 11 +-----
block/blk-lib.c | 90 ---------------------------------------------
block/blk-merge.c | 32 ----------------
block/blk-settings.c | 16 --------
block/blk-sysfs.c | 12 ------
include/linux/bio.h | 3 --
include/linux/blk_types.h | 4 +-
include/linux/blkdev.h | 26 -------------
include/trace/events/f2fs.h | 1 -
kernel/trace/blktrace.c | 1 -
11 files changed, 2 insertions(+), 197 deletions(-)
diff --git a/block/bio.c b/block/bio.c
index f4d207180266..b310e7ef3fbf 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -684,9 +684,6 @@ static struct bio *__bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
case REQ_OP_SECURE_ERASE:
case REQ_OP_WRITE_ZEROES:
break;
- case REQ_OP_WRITE_SAME:
- bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0];
- break;
default:
__bio_for_each_segment(bv, bio_src, iter, iter_src)
bio->bi_io_vec[bio->bi_vcnt++] = bv;
diff --git a/block/blk-core.c b/block/blk-core.c
index 8654aa0cef6d..92336bc8495c 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1929,10 +1929,6 @@ generic_make_request_checks(struct bio *bio)
if (!blk_queue_secure_erase(q))
goto not_supported;
break;
- case REQ_OP_WRITE_SAME:
- if (!bdev_write_same(bio->bi_bdev))
- goto not_supported;
- break;
case REQ_OP_ZONE_REPORT:
case REQ_OP_ZONE_RESET:
if (!bdev_is_zoned(bio->bi_bdev))
@@ -2100,12 +2096,7 @@ blk_qc_t submit_bio(struct bio *bio)
* go through the normal accounting stuff before submission.
*/
if (bio_has_data(bio)) {
- unsigned int count;
-
- if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
- count = bdev_logical_block_size(bio->bi_bdev) >> 9;
- else
- count = bio_sectors(bio);
+ unsigned int count = bio_sectors(bio);
if (op_is_write(bio_op(bio))) {
count_vm_events(PGPGOUT, count);
diff --git a/block/blk-lib.c b/block/blk-lib.c
index e8caecd71688..57c99b9b3b78 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -131,96 +131,6 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
}
EXPORT_SYMBOL(blkdev_issue_discard);
-/**
- * __blkdev_issue_write_same - generate number of bios with same page
- * @bdev: target blockdev
- * @sector: start sector
- * @nr_sects: number of sectors to write
- * @gfp_mask: memory allocation flags (for bio_alloc)
- * @page: page containing data to write
- * @biop: pointer to anchor bio
- *
- * Description:
- * Generate and issue number of bios(REQ_OP_WRITE_SAME) with same page.
- */
-static int __blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
- sector_t nr_sects, gfp_t gfp_mask, struct page *page,
- struct bio **biop)
-{
- struct request_queue *q = bdev_get_queue(bdev);
- unsigned int max_write_same_sectors;
- struct bio *bio = *biop;
- sector_t bs_mask;
-
- if (!q)
- return -ENXIO;
-
- bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
- if ((sector | nr_sects) & bs_mask)
- return -EINVAL;
-
- if (!bdev_write_same(bdev))
- return -EOPNOTSUPP;
-
- /* Ensure that max_write_same_sectors doesn't overflow bi_size */
- max_write_same_sectors = UINT_MAX >> 9;
-
- while (nr_sects) {
- bio = next_bio(bio, 1, gfp_mask);
- bio->bi_iter.bi_sector = sector;
- bio->bi_bdev = bdev;
- bio->bi_vcnt = 1;
- bio->bi_io_vec->bv_page = page;
- bio->bi_io_vec->bv_offset = 0;
- bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev);
- bio_set_op_attrs(bio, REQ_OP_WRITE_SAME, 0);
-
- if (nr_sects > max_write_same_sectors) {
- bio->bi_iter.bi_size = max_write_same_sectors << 9;
- nr_sects -= max_write_same_sectors;
- sector += max_write_same_sectors;
- } else {
- bio->bi_iter.bi_size = nr_sects << 9;
- nr_sects = 0;
- }
- cond_resched();
- }
-
- *biop = bio;
- return 0;
-}
-
-/**
- * blkdev_issue_write_same - queue a write same operation
- * @bdev: target blockdev
- * @sector: start sector
- * @nr_sects: number of sectors to write
- * @gfp_mask: memory allocation flags (for bio_alloc)
- * @page: page containing data
- *
- * Description:
- * Issue a write same request for the sectors in question.
- */
-int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
- sector_t nr_sects, gfp_t gfp_mask,
- struct page *page)
-{
- struct bio *bio = NULL;
- struct blk_plug plug;
- int ret;
-
- blk_start_plug(&plug);
- ret = __blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask, page,
- &bio);
- if (ret == 0 && bio) {
- ret = submit_bio_wait(bio);
- bio_put(bio);
- }
- blk_finish_plug(&plug);
- return ret;
-}
-EXPORT_SYMBOL(blkdev_issue_write_same);
-
static int __blkdev_issue_write_zeroes(struct block_device *bdev,
sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
struct bio **biop, unsigned flags)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 3990ae406341..d6c86bfc5722 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -68,22 +68,6 @@ static struct bio *blk_bio_write_zeroes_split(struct request_queue *q,
return bio_split(bio, q->limits.max_write_zeroes_sectors, GFP_NOIO, bs);
}
-static struct bio *blk_bio_write_same_split(struct request_queue *q,
- struct bio *bio,
- struct bio_set *bs,
- unsigned *nsegs)
-{
- *nsegs = 1;
-
- if (!q->limits.max_write_same_sectors)
- return NULL;
-
- if (bio_sectors(bio) <= q->limits.max_write_same_sectors)
- return NULL;
-
- return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs);
-}
-
static inline unsigned get_max_io_size(struct request_queue *q,
struct bio *bio)
{
@@ -216,9 +200,6 @@ void blk_queue_split(struct request_queue *q, struct bio **bio,
case REQ_OP_WRITE_ZEROES:
split = blk_bio_write_zeroes_split(q, *bio, bs, &nsegs);
break;
- case REQ_OP_WRITE_SAME:
- split = blk_bio_write_same_split(q, *bio, bs, &nsegs);
- break;
default:
split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs);
break;
@@ -259,8 +240,6 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
case REQ_OP_SECURE_ERASE:
case REQ_OP_WRITE_ZEROES:
return 0;
- case REQ_OP_WRITE_SAME:
- return 1;
}
fbio = bio;
@@ -454,8 +433,6 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
nsegs = __blk_bvec_map_sg(q, rq->special_vec, sglist, &sg);
- else if (rq->bio && bio_op(rq->bio) == REQ_OP_WRITE_SAME)
- nsegs = __blk_bvec_map_sg(q, bio_iovec(rq->bio), sglist, &sg);
else if (rq->bio)
nsegs = __blk_bios_map_sg(q, rq->bio, sglist, &sg);
@@ -688,10 +665,6 @@ static struct request *attempt_merge(struct request_queue *q,
|| req_no_special_merge(next))
return NULL;
- if (req_op(req) == REQ_OP_WRITE_SAME &&
- !blk_write_same_mergeable(req->bio, next->bio))
- return NULL;
-
/*
* If we are allowed to merge, then append bio list
* from next to rq and release next. merge_requests_fn
@@ -806,11 +779,6 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
if (blk_integrity_merge_bio(rq->q, rq, bio) == false)
return false;
- /* must be using the same buffer */
- if (req_op(rq) == REQ_OP_WRITE_SAME &&
- !blk_write_same_mergeable(rq->bio, bio))
- return false;
-
return true;
}
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 4fa81ed383ca..aea05adfd6b4 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -96,7 +96,6 @@ void blk_set_default_limits(struct queue_limits *lim)
lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
lim->max_dev_sectors = 0;
lim->chunk_sectors = 0;
- lim->max_write_same_sectors = 0;
lim->max_write_zeroes_sectors = 0;
lim->max_discard_sectors = 0;
lim->max_hw_discard_sectors = 0;
@@ -132,7 +131,6 @@ void blk_set_stacking_limits(struct queue_limits *lim)
lim->max_segment_size = UINT_MAX;
lim->max_sectors = UINT_MAX;
lim->max_dev_sectors = UINT_MAX;
- lim->max_write_same_sectors = UINT_MAX;
lim->max_write_zeroes_sectors = UINT_MAX;
}
EXPORT_SYMBOL(blk_set_stacking_limits);
@@ -291,18 +289,6 @@ void blk_queue_max_discard_sectors(struct request_queue *q,
EXPORT_SYMBOL(blk_queue_max_discard_sectors);
/**
- * blk_queue_max_write_same_sectors - set max sectors for a single write same
- * @q: the request queue for the device
- * @max_write_same_sectors: maximum number of sectors to write per command
- **/
-void blk_queue_max_write_same_sectors(struct request_queue *q,
- unsigned int max_write_same_sectors)
-{
- q->limits.max_write_same_sectors = max_write_same_sectors;
-}
-EXPORT_SYMBOL(blk_queue_max_write_same_sectors);
-
-/**
* blk_queue_max_write_zeroes_sectors - set max sectors for a single
* write zeroes
* @q: the request queue for the device
@@ -557,8 +543,6 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors);
- t->max_write_same_sectors = min(t->max_write_same_sectors,
- b->max_write_same_sectors);
t->max_write_zeroes_sectors = min(t->max_write_zeroes_sectors,
b->max_write_zeroes_sectors);
t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index fc20489f0d2b..2ea4aca4ec1c 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -211,12 +211,6 @@ static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *pag
return queue_var_show(0, page);
}
-static ssize_t queue_write_same_max_show(struct request_queue *q, char *page)
-{
- return sprintf(page, "%llu\n",
- (unsigned long long)q->limits.max_write_same_sectors << 9);
-}
-
static ssize_t queue_write_zeroes_max_show(struct request_queue *q, char *page)
{
return sprintf(page, "%llu\n",
@@ -603,11 +597,6 @@ static struct queue_sysfs_entry queue_discard_zeroes_data_entry = {
.show = queue_discard_zeroes_data_show,
};
-static struct queue_sysfs_entry queue_write_same_max_entry = {
- .attr = {.name = "write_same_max_bytes", .mode = S_IRUGO },
- .show = queue_write_same_max_show,
-};
-
static struct queue_sysfs_entry queue_write_zeroes_max_entry = {
.attr = {.name = "write_zeroes_max_bytes", .mode = S_IRUGO },
.show = queue_write_zeroes_max_show,
@@ -705,7 +694,6 @@ static struct attribute *default_attrs[] = {
&queue_discard_max_entry.attr,
&queue_discard_max_hw_entry.attr,
&queue_discard_zeroes_data_entry.attr,
- &queue_write_same_max_entry.attr,
&queue_write_zeroes_max_entry.attr,
&queue_nonrot_entry.attr,
&queue_zoned_entry.attr,
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 4931756d86d9..96a20afb8575 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -87,7 +87,6 @@ static inline bool bio_no_advance_iter(struct bio *bio)
{
return bio_op(bio) == REQ_OP_DISCARD ||
bio_op(bio) == REQ_OP_SECURE_ERASE ||
- bio_op(bio) == REQ_OP_WRITE_SAME ||
bio_op(bio) == REQ_OP_WRITE_ZEROES;
}
@@ -199,8 +198,6 @@ static inline unsigned __bio_segments(struct bio *bio, struct bvec_iter *bvec)
case REQ_OP_SECURE_ERASE:
case REQ_OP_WRITE_ZEROES:
return 0;
- case REQ_OP_WRITE_SAME:
- return 1;
default:
break;
}
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 61339bc44400..fc4fc927dcc4 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -171,10 +171,8 @@ enum req_opf {
REQ_OP_SECURE_ERASE = 5,
/* seset a zone write pointer */
REQ_OP_ZONE_RESET = 6,
- /* write the same sector many times */
- REQ_OP_WRITE_SAME = 7,
/* write the zero filled sector many times */
- REQ_OP_WRITE_ZEROES = 9,
+ REQ_OP_WRITE_ZEROES = 7,
/* SCSI passthrough using struct scsi_request */
REQ_OP_SCSI_IN = 32,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index ec993573e0a8..1f066f246dd7 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -326,7 +326,6 @@ struct queue_limits {
unsigned int io_opt;
unsigned int max_discard_sectors;
unsigned int max_hw_discard_sectors;
- unsigned int max_write_same_sectors;
unsigned int max_write_zeroes_sectors;
unsigned int discard_granularity;
unsigned int discard_alignment;
@@ -806,14 +805,6 @@ static inline bool rq_mergeable(struct request *rq)
return true;
}
-static inline bool blk_write_same_mergeable(struct bio *a, struct bio *b)
-{
- if (bio_data(a) == bio_data(b))
- return true;
-
- return false;
-}
-
static inline unsigned int blk_queue_depth(struct request_queue *q)
{
if (q->queue_depth)
@@ -1035,9 +1026,6 @@ static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q,
if (unlikely(op == REQ_OP_DISCARD || op == REQ_OP_SECURE_ERASE))
return min(q->limits.max_discard_sectors, UINT_MAX >> 9);
- if (unlikely(op == REQ_OP_WRITE_SAME))
- return q->limits.max_write_same_sectors;
-
if (unlikely(op == REQ_OP_WRITE_ZEROES))
return q->limits.max_write_zeroes_sectors;
@@ -1157,8 +1145,6 @@ extern void blk_queue_max_discard_segments(struct request_queue *,
extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
extern void blk_queue_max_discard_sectors(struct request_queue *q,
unsigned int max_discard_sectors);
-extern void blk_queue_max_write_same_sectors(struct request_queue *q,
- unsigned int max_write_same_sectors);
extern void blk_queue_max_write_zeroes_sectors(struct request_queue *q,
unsigned int max_write_same_sectors);
extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
@@ -1336,8 +1322,6 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt,
}
extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *);
-extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
- sector_t nr_sects, gfp_t gfp_mask, struct page *page);
#define BLKDEV_DISCARD_SECURE (1 << 0) /* issue a secure erase */
@@ -1539,16 +1523,6 @@ static inline int bdev_discard_alignment(struct block_device *bdev)
return q->limits.discard_alignment;
}
-static inline unsigned int bdev_write_same(struct block_device *bdev)
-{
- struct request_queue *q = bdev_get_queue(bdev);
-
- if (q)
- return q->limits.max_write_same_sectors;
-
- return 0;
-}
-
static inline unsigned int bdev_write_zeroes_sectors(struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
index c80fcad0a6c9..da1b542ef8d6 100644
--- a/include/trace/events/f2fs.h
+++ b/include/trace/events/f2fs.h
@@ -71,7 +71,6 @@ TRACE_DEFINE_ENUM(CP_DISCARD);
{ REQ_OP_ZONE_REPORT, "ZONE_REPORT" }, \
{ REQ_OP_SECURE_ERASE, "SECURE_ERASE" }, \
{ REQ_OP_ZONE_RESET, "ZONE_RESET" }, \
- { REQ_OP_WRITE_SAME, "WRITE_SAME" }, \
{ REQ_OP_WRITE_ZEROES, "WRITE_ZEROES" })
#define show_bio_op_flags(flags) \
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index b2058a7f94bd..99060c96a4bd 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -1750,7 +1750,6 @@ void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes)
switch (op & REQ_OP_MASK) {
case REQ_OP_WRITE:
- case REQ_OP_WRITE_SAME:
rwbs[i++] = 'W';
break;
case REQ_OP_DISCARD:
--
2.11.0
^ permalink raw reply related
* [PATCH 7/8] block: remove bio_no_advance_iter
From: Christoph Hellwig @ 2017-04-10 16:08 UTC (permalink / raw)
To: axboe, martin.petersen, philipp.reisner, lars.ellenberg,
target-devel
Cc: linux-block, linux-scsi, drbd-dev, dm-devel
In-Reply-To: <20170410160807.23674-1-hch@lst.de>
Now that we don't have to support the odd Write Same special case
we can simply increment the iter if the bio has data, else just
manipulate bi_size directly.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/bio.h | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 96a20afb8575..7a24a1a24967 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -83,13 +83,6 @@ static inline bool bio_has_data(struct bio *bio)
return false;
}
-static inline bool bio_no_advance_iter(struct bio *bio)
-{
- return bio_op(bio) == REQ_OP_DISCARD ||
- bio_op(bio) == REQ_OP_SECURE_ERASE ||
- bio_op(bio) == REQ_OP_WRITE_ZEROES;
-}
-
static inline bool bio_mergeable(struct bio *bio)
{
if (bio->bi_opf & REQ_NOMERGE_FLAGS)
@@ -165,10 +158,10 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
{
iter->bi_sector += bytes >> 9;
- if (bio_no_advance_iter(bio))
- iter->bi_size -= bytes;
- else
+ if (bio_has_data(bio))
bvec_iter_advance(bio->bi_io_vec, iter, bytes);
+ else
+ iter->bi_size -= bytes;
}
#define __bio_for_each_segment(bvl, bio, iter, start) \
--
2.11.0
^ permalink raw reply related
* [PATCH 8/8] block: use bio_has_data to check if a bio has bvecs
From: Christoph Hellwig @ 2017-04-10 16:08 UTC (permalink / raw)
To: axboe, martin.petersen, philipp.reisner, lars.ellenberg,
target-devel
Cc: linux-block, linux-scsi, drbd-dev, dm-devel
In-Reply-To: <20170410160807.23674-1-hch@lst.de>
Now that Write Same is gone and discard bios never have a payload we
can simply use bio_has_data as an indicator that the bio has bvecs
that need to be handled.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/bio.c | 8 +-------
block/blk-merge.c | 9 +--------
include/linux/bio.h | 21 +++++----------------
3 files changed, 7 insertions(+), 31 deletions(-)
diff --git a/block/bio.c b/block/bio.c
index b310e7ef3fbf..1c9f04c30ba9 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -679,15 +679,9 @@ static struct bio *__bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector;
bio->bi_iter.bi_size = bio_src->bi_iter.bi_size;
- switch (bio_op(bio)) {
- case REQ_OP_DISCARD:
- case REQ_OP_SECURE_ERASE:
- case REQ_OP_WRITE_ZEROES:
- break;
- default:
+ if (bio_has_data(bio)) {
__bio_for_each_segment(bv, bio_src, iter, iter_src)
bio->bi_io_vec[bio->bi_vcnt++] = bv;
- break;
}
if (bio_integrity(bio_src)) {
diff --git a/block/blk-merge.c b/block/blk-merge.c
index d6c86bfc5722..549d060097f1 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -232,16 +232,9 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
struct bio *fbio, *bbio;
struct bvec_iter iter;
- if (!bio)
+ if (!bio || !bio_has_data(bio))
return 0;
- switch (bio_op(bio)) {
- case REQ_OP_DISCARD:
- case REQ_OP_SECURE_ERASE:
- case REQ_OP_WRITE_ZEROES:
- return 0;
- }
-
fbio = bio;
cluster = blk_queue_cluster(q);
seg_size = 0;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 7a24a1a24967..86bf531f97aa 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -178,26 +178,15 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
static inline unsigned __bio_segments(struct bio *bio, struct bvec_iter *bvec)
{
unsigned segs = 0;
- struct bio_vec bv;
- struct bvec_iter iter;
- /*
- * We special case discard/write same/write zeroes, because they
- * interpret bi_size differently:
- */
+ if (bio_has_data(bio)) {
+ struct bio_vec bv;
+ struct bvec_iter iter;
- switch (bio_op(bio)) {
- case REQ_OP_DISCARD:
- case REQ_OP_SECURE_ERASE:
- case REQ_OP_WRITE_ZEROES:
- return 0;
- default:
- break;
+ __bio_for_each_segment(bv, bio, iter, *bvec)
+ segs++;
}
- __bio_for_each_segment(bv, bio, iter, *bvec)
- segs++;
-
return segs;
}
--
2.11.0
^ permalink raw reply related
* Re: [PATCH 1/3] blk-mq: unify hctx delayed_run_work and run_work
From: Christoph Hellwig @ 2017-04-10 16:09 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, osandov, hch, bart.vanassche
In-Reply-To: <1491839696-24783-2-git-send-email-axboe@fb.com>
Looks good,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH 2/3] block: add kblock_mod_delayed_work_on()
From: Christoph Hellwig @ 2017-04-10 16:10 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block, osandov, hch, bart.vanassche
In-Reply-To: <1491839696-24783-3-git-send-email-axboe@fb.com>
Looks fine,
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH 1/3] blk-mq: unify hctx delayed_run_work and run_work
From: Bart Van Assche @ 2017-04-10 16:17 UTC (permalink / raw)
To: linux-block@vger.kernel.org, axboe@fb.com; +Cc: hch@lst.de, osandov@fb.com
In-Reply-To: <1491839696-24783-2-git-send-email-axboe@fb.com>
On Mon, 2017-04-10 at 09:54 -0600, Jens Axboe wrote:
> They serve the exact same purpose. Get rid of the non-delayed
> work variant, and just run it without delay for the normal case.
Reviewed-by: Bart Van Assche <Bart.VanAssche@sandisk.com>=
^ permalink raw reply
* Re: [PATCH 2/3] block: add kblock_mod_delayed_work_on()
From: Bart Van Assche @ 2017-04-10 16:17 UTC (permalink / raw)
To: linux-block@vger.kernel.org, axboe@fb.com; +Cc: hch@lst.de, osandov@fb.com
In-Reply-To: <1491839696-24783-3-git-send-email-axboe@fb.com>
On Mon, 2017-04-10 at 09:54 -0600, Jens Axboe wrote:
> This modifies (or adds, if not currently pending) an existing
> delayed work item.
Reviewed-by: Bart Van Assche <Bart.VanAssche@sandisk.com>=
^ permalink raw reply
* Re: [PATCH 3/3] blk-mq: unify hctx delay_work and run_work
From: Bart Van Assche @ 2017-04-10 16:21 UTC (permalink / raw)
To: linux-block@vger.kernel.org, axboe@fb.com; +Cc: hch@lst.de, osandov@fb.com
In-Reply-To: <1491839696-24783-4-git-send-email-axboe@fb.com>
On Mon, 2017-04-10 at 09:54 -0600, Jens Axboe wrote:
> @@ -1281,27 +1280,39 @@ static void blk_mq_run_work_fn(struct work_struct=
*work)
> struct blk_mq_hw_ctx *hctx;
> =20
> hctx =3D container_of(work, struct blk_mq_hw_ctx, run_work.work);
> - __blk_mq_run_hw_queue(hctx);
> -}
> =20
> -static void blk_mq_delay_work_fn(struct work_struct *work)
> -{
> - struct blk_mq_hw_ctx *hctx;
> + /*
> + * If we are stopped, don't run the queue. The exception is if
> + * BLK_MQ_S_START_ON_RUN is set. For that case, we auto-clear
> + * the STOPPED bit and run it.
> + */
> + if (test_bit(BLK_MQ_S_STOPPED, &hctx->state)) {
> + if (!test_bit(BLK_MQ_S_START_ON_RUN, &hctx->state))
> + return;
> =20
> - hctx =3D container_of(work, struct blk_mq_hw_ctx, delay_work.work);
> + clear_bit(BLK_MQ_S_START_ON_RUN, &hctx->state);
> + clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
> + }
> =20
> - if (test_and_clear_bit(BLK_MQ_S_STOPPED, &hctx->state))
> - __blk_mq_run_hw_queue(hctx);
> + __blk_mq_run_hw_queue(hctx);
> }
> =20
> +
> void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
> {
> if (unlikely(!blk_mq_hw_queue_mapped(hctx)))
> return;
> =20
> + /*
> + * Stop the hw queue, then modify currently delayed work.
> + * This should prevent us from running the queue prematurely.
> + * Mark the queue as auto-clearing STOPPED when it runs.
> + */
> blk_mq_stop_hw_queue(hctx);
> - kblockd_schedule_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
> - &hctx->delay_work, msecs_to_jiffies(msecs));
> + set_bit(BLK_MQ_S_START_ON_RUN, &hctx->state);
> + kblockd_mod_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
> + &hctx->run_work,
> + msecs_to_jiffies(msecs));
> }
> EXPORT_SYMBOL(blk_mq_delay_queue);
Hello Jens,
Is it possible for a block driver to call blk_mq_delay_queue() while
blk_mq_delay_work_fn() is running? Can that result in BLK_MQ_S_STOPPED
and=A0BLK_MQ_S_START_ON_RUN being checked by=A0blk_mq_delay_work_fn() after
blk_mq_delay_queue() has set BLK_MQ_S_STOPPED and before it has set
BLK_MQ_S_START_ON_RUN?
Thanks,
Bart.=
^ permalink raw reply
* Re: [PATCH 3/3] blk-mq: unify hctx delay_work and run_work
From: Jens Axboe @ 2017-04-10 16:53 UTC (permalink / raw)
To: Bart Van Assche, linux-block@vger.kernel.org; +Cc: hch@lst.de, osandov@fb.com
In-Reply-To: <1491841316.4199.12.camel@sandisk.com>
On 04/10/2017 10:21 AM, Bart Van Assche wrote:
> On Mon, 2017-04-10 at 09:54 -0600, Jens Axboe wrote:
>> @@ -1281,27 +1280,39 @@ static void blk_mq_run_work_fn(struct work_struct *work)
>> struct blk_mq_hw_ctx *hctx;
>>
>> hctx = container_of(work, struct blk_mq_hw_ctx, run_work.work);
>> - __blk_mq_run_hw_queue(hctx);
>> -}
>>
>> -static void blk_mq_delay_work_fn(struct work_struct *work)
>> -{
>> - struct blk_mq_hw_ctx *hctx;
>> + /*
>> + * If we are stopped, don't run the queue. The exception is if
>> + * BLK_MQ_S_START_ON_RUN is set. For that case, we auto-clear
>> + * the STOPPED bit and run it.
>> + */
>> + if (test_bit(BLK_MQ_S_STOPPED, &hctx->state)) {
>> + if (!test_bit(BLK_MQ_S_START_ON_RUN, &hctx->state))
>> + return;
>>
>> - hctx = container_of(work, struct blk_mq_hw_ctx, delay_work.work);
>> + clear_bit(BLK_MQ_S_START_ON_RUN, &hctx->state);
>> + clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
>> + }
>>
>> - if (test_and_clear_bit(BLK_MQ_S_STOPPED, &hctx->state))
>> - __blk_mq_run_hw_queue(hctx);
>> + __blk_mq_run_hw_queue(hctx);
>> }
>>
>> +
>> void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
>> {
>> if (unlikely(!blk_mq_hw_queue_mapped(hctx)))
>> return;
>>
>> + /*
>> + * Stop the hw queue, then modify currently delayed work.
>> + * This should prevent us from running the queue prematurely.
>> + * Mark the queue as auto-clearing STOPPED when it runs.
>> + */
>> blk_mq_stop_hw_queue(hctx);
>> - kblockd_schedule_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
>> - &hctx->delay_work, msecs_to_jiffies(msecs));
>> + set_bit(BLK_MQ_S_START_ON_RUN, &hctx->state);
>> + kblockd_mod_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
>> + &hctx->run_work,
>> + msecs_to_jiffies(msecs));
>> }
>> EXPORT_SYMBOL(blk_mq_delay_queue);
>
> Hello Jens,
>
> Is it possible for a block driver to call blk_mq_delay_queue() while
> blk_mq_delay_work_fn() is running? Can that result in BLK_MQ_S_STOPPED
> and BLK_MQ_S_START_ON_RUN being checked by blk_mq_delay_work_fn() after
> blk_mq_delay_queue() has set BLK_MQ_S_STOPPED and before it has set
> BLK_MQ_S_START_ON_RUN?
Yeah, I don't think it's bullet proof. I just looked at the in-kernel
users, and there's just one, nvme/fc.c. And it looks really buggy,
since it manually stops _all_ queues, then delays the one hw queue.
So we'll end up with potentially a bunch of stopped queues, and only
one getting restarted.
I think for blk_mq_delay_queue(), what we really care about is "this
queue has to run again sometime in the future". If that happens
much sooner than asked for, that's OK, the caller will just delay
again if it needs it. For most cases, we'll be close.
Obviously we can't have ordering issues and end up in a bad state,
we have to prevent that.
I'll fiddle with this a bit more.
--
Jens Axboe
^ permalink raw reply
* Re: [PATCH V2 00/16] Introduce the BFQ I/O scheduler
From: Bart Van Assche @ 2017-04-10 16:56 UTC (permalink / raw)
To: tj@kernel.org, paolo.valente@linaro.org, axboe@kernel.dk
Cc: ulf.hansson@linaro.org, linux-kernel@vger.kernel.org,
fchecconi@gmail.com, avanzini.arianna@gmail.com,
linux-block@vger.kernel.org, linus.walleij@linaro.org,
broonie@kernel.org
In-Reply-To: <20170331124743.3530-1-paolo.valente@linaro.org>
On Fri, 2017-03-31 at 14:47 +0200, Paolo Valente wrote:
> [ ... ]
Hello Paolo,
Is the git tree that is available at https://github.com/Algodev-github/bfq-=
mq
appropriate for testing BFQ? If I merge that tree with v4.11-rc6 and if I r=
un
the srp-test software against that tree as follows:
./run_tests -e bfq-mq -t 02-mq
then the following appears on the console:
[ 2748.650352] BUG: unable to handle kernel NULL pointer dereference at 000=
00000000000d0
[ 2748.650442] IP: __bfq_insert_request+0x26/0x650 [bfq_mq_iosched]
[ 2748.650509] PGD 0=A0
[ 2748.650511]=A0
[ 2748.650585] Oops: 0000 [#1] SMP
[ 2748.651107] CPU: 9 PID: 10772 Comm: kworker/9:2H Tainted: G=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0I=A0=A0=A0=A0=A04.11.0-rc6-dbg+ #1
[ 2748.651191] Workqueue: kblockd blk_mq_requeue_work
[ 2748.651228] task: ffff88037c808040 task.stack: ffffc90003b4c000
[ 2748.651268] RIP: 0010:__bfq_insert_request+0x26/0x650 [bfq_mq_iosched]
[ 2748.651307] RSP: 0018:ffffc90003b4f9d8 EFLAGS: 00010002
[ 2748.651345] RAX: 0000000000000001 RBX: 0000000000000000 RCX: 00000000000=
00001
[ 2748.651383] RDX: 0000000000000001 RSI: ffff880377f52e80 RDI: ffff880401f=
774e8
[ 2748.651423] RBP: ffffc90003b4fa80 R08: 9093955f00000000 R09: 00000000000=
00001
[ 2748.651464] R10: ffffc90003b4fa00 R11: ffffffffa06d0d53 R12: ffff880401f=
77840
[ 2748.651506] R13: ffff880401f774e8 R14: ffff880378a451e0 R15: 00000000000=
00000
[ 2748.651547] FS:=A0=A00000000000000000(0000) GS:ffff88046f040000(0000) kn=
lGS:0000000000000000
[ 2748.651588] CS:=A0=A00010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2748.651626] CR2: 00000000000000d0 CR3: 0000000001c0f000 CR4: 00000000001=
406e0
[ 2748.651664] Call Trace:
[ 2748.651778]=A0=A0bfq_insert_request+0x83/0x280 [bfq_mq_iosched]
[ 2748.651934]=A0=A0bfq_insert_requests+0x50/0x70 [bfq_mq_iosched]
[ 2748.651975]=A0=A0blk_mq_sched_insert_request+0x11e/0x170
[ 2748.652015]=A0=A0blk_insert_cloned_request+0xb6/0x1f0
[ 2748.652361]=A0=A0map_request+0x13c/0x290 [dm_mod]
[ 2748.652403]=A0=A0dm_mq_queue_rq+0x90/0x160 [dm_mod]
[ 2748.652441]=A0=A0blk_mq_dispatch_rq_list+0x1f2/0x3e0
[ 2748.652479]=A0=A0blk_mq_sched_dispatch_requests+0xf1/0x190
[ 2748.652516]=A0=A0__blk_mq_run_hw_queue+0x12d/0x1c0
[ 2748.652553]=A0=A0__blk_mq_delay_run_hw_queue+0xe3/0xf0
[ 2748.652593]=A0=A0blk_mq_run_hw_queues+0x5c/0x80
[ 2748.652632]=A0=A0blk_mq_requeue_work+0x132/0x150
[ 2748.652671]=A0=A0process_one_work+0x206/0x6a0
[ 2748.652709]=A0=A0worker_thread+0x49/0x4a0
[ 2748.652745]=A0=A0kthread+0x107/0x140
[ 2748.652854]=A0=A0ret_from_fork+0x2e/0x40
[ 2748.652891] Code: ff 0f 1f 40 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 =
48 83 c4 80 8b 87 58 03 00 00 48 8b 9e b0 00 00 00 85 c0 0f 84 8b 04 00 00 =
<48> 8b 83 d0 00 00 00 48 85 c0 0f 84 63 04 00 00
48 83 e8 10 48=A0
[ 2748.653049] RIP: __bfq_insert_request+0x26/0x650 [bfq_mq_iosched] RSP: f=
fffc90003b4f9d8
[ 2748.653090] CR2: 00000000000000d0
The crash address corresponds to the following source code according to gdb=
:
(gdb) list *(__bfq_insert_request+0x26)
0xd6f6 is in __bfq_insert_request (block/bfq-mq-iosched.c:4430).
4425
4426 =A0=A0=A0static void __bfq_insert_request(struct bfq_data *bfqd, struc=
t request *rq)
4427 =A0=A0=A0{
4428 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0struct bfq_queue *bfqq =3D RQ_BFQQ(rq=
), *new_bfqq;
4429
4430 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0assert_spin_locked(&bfqd->lock);
4431
4432 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0bfq_log_bfqq(bfqd, bfqq, "__insert_re=
q: rq %p bfqq %p", rq, bfqq);
4433
4434 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0/*
Bart.=
^ permalink raw reply
* Re: [PATCH 3/3] blk-mq: unify hctx delay_work and run_work
From: Jens Axboe @ 2017-04-10 17:23 UTC (permalink / raw)
To: Bart Van Assche, linux-block@vger.kernel.org; +Cc: hch@lst.de, osandov@fb.com
In-Reply-To: <54caf130-6a6c-ca81-1b58-dd413079fcf2@fb.com>
On 04/10/2017 10:53 AM, Jens Axboe wrote:
> On 04/10/2017 10:21 AM, Bart Van Assche wrote:
>> On Mon, 2017-04-10 at 09:54 -0600, Jens Axboe wrote:
>>> @@ -1281,27 +1280,39 @@ static void blk_mq_run_work_fn(struct work_struct *work)
>>> struct blk_mq_hw_ctx *hctx;
>>>
>>> hctx = container_of(work, struct blk_mq_hw_ctx, run_work.work);
>>> - __blk_mq_run_hw_queue(hctx);
>>> -}
>>>
>>> -static void blk_mq_delay_work_fn(struct work_struct *work)
>>> -{
>>> - struct blk_mq_hw_ctx *hctx;
>>> + /*
>>> + * If we are stopped, don't run the queue. The exception is if
>>> + * BLK_MQ_S_START_ON_RUN is set. For that case, we auto-clear
>>> + * the STOPPED bit and run it.
>>> + */
>>> + if (test_bit(BLK_MQ_S_STOPPED, &hctx->state)) {
>>> + if (!test_bit(BLK_MQ_S_START_ON_RUN, &hctx->state))
>>> + return;
>>>
>>> - hctx = container_of(work, struct blk_mq_hw_ctx, delay_work.work);
>>> + clear_bit(BLK_MQ_S_START_ON_RUN, &hctx->state);
>>> + clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
>>> + }
>>>
>>> - if (test_and_clear_bit(BLK_MQ_S_STOPPED, &hctx->state))
>>> - __blk_mq_run_hw_queue(hctx);
>>> + __blk_mq_run_hw_queue(hctx);
>>> }
>>>
>>> +
>>> void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs)
>>> {
>>> if (unlikely(!blk_mq_hw_queue_mapped(hctx)))
>>> return;
>>>
>>> + /*
>>> + * Stop the hw queue, then modify currently delayed work.
>>> + * This should prevent us from running the queue prematurely.
>>> + * Mark the queue as auto-clearing STOPPED when it runs.
>>> + */
>>> blk_mq_stop_hw_queue(hctx);
>>> - kblockd_schedule_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
>>> - &hctx->delay_work, msecs_to_jiffies(msecs));
>>> + set_bit(BLK_MQ_S_START_ON_RUN, &hctx->state);
>>> + kblockd_mod_delayed_work_on(blk_mq_hctx_next_cpu(hctx),
>>> + &hctx->run_work,
>>> + msecs_to_jiffies(msecs));
>>> }
>>> EXPORT_SYMBOL(blk_mq_delay_queue);
>>
>> Hello Jens,
>>
>> Is it possible for a block driver to call blk_mq_delay_queue() while
>> blk_mq_delay_work_fn() is running? Can that result in BLK_MQ_S_STOPPED
>> and BLK_MQ_S_START_ON_RUN being checked by blk_mq_delay_work_fn() after
>> blk_mq_delay_queue() has set BLK_MQ_S_STOPPED and before it has set
>> BLK_MQ_S_START_ON_RUN?
>
> Yeah, I don't think it's bullet proof. I just looked at the in-kernel
> users, and there's just one, nvme/fc.c. And it looks really buggy,
> since it manually stops _all_ queues, then delays the one hw queue.
> So we'll end up with potentially a bunch of stopped queues, and only
> one getting restarted.
>
> I think for blk_mq_delay_queue(), what we really care about is "this
> queue has to run again sometime in the future". If that happens
> much sooner than asked for, that's OK, the caller will just delay
> again if it needs it. For most cases, we'll be close.
>
> Obviously we can't have ordering issues and end up in a bad state,
> we have to prevent that.
>
> I'll fiddle with this a bit more.
Spent a bit of time looking at the workqueue code. Looks like we're
guaranteed that we'll have at least one run of the handler after
calling kblockd_mod_delayed_work_on(). If the handler is currently
running, the we will sucessfully queue a new invocation. That's the
troublesome case. If it's not currently running, we just push the run
sometime into the future. In both cases, we know it'll run _after_
setting BLK_MQ_S_START_ON_RUN, which is the important part.
Hence I think the patch is fine as-is. Let me know if you disagree!
--
Jens Axboe
^ permalink raw reply
* [PATCH for-4.4 15/16] blk-mq: Avoid memory reclaim when remapping queues
From: Sumit Semwal @ 2017-04-10 17:44 UTC (permalink / raw)
To: stable
Cc: Gabriel Krisman Bertazi, Brian King, Douglas Miller, linux-block,
linux-scsi, Jens Axboe, Sumit Semwal
In-Reply-To: <1491846272-14882-1-git-send-email-sumit.semwal@linaro.org>
From: Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com>
[ Upstream commit 36e1f3d107867b25c616c2fd294f5a1c9d4e5d09 ]
While stressing memory and IO at the same time we changed SMT settings,
we were able to consistently trigger deadlocks in the mm system, which
froze the entire machine.
I think that under memory stress conditions, the large allocations
performed by blk_mq_init_rq_map may trigger a reclaim, which stalls
waiting on the block layer remmaping completion, thus deadlocking the
system. The trace below was collected after the machine stalled,
waiting for the hotplug event completion.
The simplest fix for this is to make allocations in this path
non-reclaimable, with GFP_NOIO. With this patch, We couldn't hit the
issue anymore.
This should apply on top of Jens's for-next branch cleanly.
Changes since v1:
- Use GFP_NOIO instead of GFP_NOWAIT.
Call Trace:
[c000000f0160aaf0] [c000000f0160ab50] 0xc000000f0160ab50 (unreliable)
[c000000f0160acc0] [c000000000016624] __switch_to+0x2e4/0x430
[c000000f0160ad20] [c000000000b1a880] __schedule+0x310/0x9b0
[c000000f0160ae00] [c000000000b1af68] schedule+0x48/0xc0
[c000000f0160ae30] [c000000000b1b4b0] schedule_preempt_disabled+0x20/0x30
[c000000f0160ae50] [c000000000b1d4fc] __mutex_lock_slowpath+0xec/0x1f0
[c000000f0160aed0] [c000000000b1d678] mutex_lock+0x78/0xa0
[c000000f0160af00] [d000000019413cac] xfs_reclaim_inodes_ag+0x33c/0x380 [xfs]
[c000000f0160b0b0] [d000000019415164] xfs_reclaim_inodes_nr+0x54/0x70 [xfs]
[c000000f0160b0f0] [d0000000194297f8] xfs_fs_free_cached_objects+0x38/0x60 [xfs]
[c000000f0160b120] [c0000000003172c8] super_cache_scan+0x1f8/0x210
[c000000f0160b190] [c00000000026301c] shrink_slab.part.13+0x21c/0x4c0
[c000000f0160b2d0] [c000000000268088] shrink_zone+0x2d8/0x3c0
[c000000f0160b380] [c00000000026834c] do_try_to_free_pages+0x1dc/0x520
[c000000f0160b450] [c00000000026876c] try_to_free_pages+0xdc/0x250
[c000000f0160b4e0] [c000000000251978] __alloc_pages_nodemask+0x868/0x10d0
[c000000f0160b6f0] [c000000000567030] blk_mq_init_rq_map+0x160/0x380
[c000000f0160b7a0] [c00000000056758c] blk_mq_map_swqueue+0x33c/0x360
[c000000f0160b820] [c000000000567904] blk_mq_queue_reinit+0x64/0xb0
[c000000f0160b850] [c00000000056a16c] blk_mq_queue_reinit_notify+0x19c/0x250
[c000000f0160b8a0] [c0000000000f5d38] notifier_call_chain+0x98/0x100
[c000000f0160b8f0] [c0000000000c5fb0] __cpu_notify+0x70/0xe0
[c000000f0160b930] [c0000000000c63c4] notify_prepare+0x44/0xb0
[c000000f0160b9b0] [c0000000000c52f4] cpuhp_invoke_callback+0x84/0x250
[c000000f0160ba10] [c0000000000c570c] cpuhp_up_callbacks+0x5c/0x120
[c000000f0160ba60] [c0000000000c7cb8] _cpu_up+0xf8/0x1d0
[c000000f0160bac0] [c0000000000c7eb0] do_cpu_up+0x120/0x150
[c000000f0160bb40] [c0000000006fe024] cpu_subsys_online+0x64/0xe0
[c000000f0160bb90] [c0000000006f5124] device_online+0xb4/0x120
[c000000f0160bbd0] [c0000000006f5244] online_store+0xb4/0xc0
[c000000f0160bc20] [c0000000006f0a68] dev_attr_store+0x68/0xa0
[c000000f0160bc60] [c0000000003ccc30] sysfs_kf_write+0x80/0xb0
[c000000f0160bca0] [c0000000003cbabc] kernfs_fop_write+0x17c/0x250
[c000000f0160bcf0] [c00000000030fe6c] __vfs_write+0x6c/0x1e0
[c000000f0160bd90] [c000000000311490] vfs_write+0xd0/0x270
[c000000f0160bde0] [c0000000003131fc] SyS_write+0x6c/0x110
[c000000f0160be30] [c000000000009204] system_call+0x38/0xec
Signed-off-by: Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com>
Cc: Brian King <brking@linux.vnet.ibm.com>
Cc: Douglas Miller <dougmill@linux.vnet.ibm.com>
Cc: linux-block@vger.kernel.org
Cc: linux-scsi@vger.kernel.org
Signed-off-by: Jens Axboe <axboe@fb.com>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
---
block/blk-mq.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/block/blk-mq.c b/block/blk-mq.c
index d8d63c3..0d1af3e 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1470,7 +1470,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
INIT_LIST_HEAD(&tags->page_list);
tags->rqs = kzalloc_node(set->queue_depth * sizeof(struct request *),
- GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+ GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
set->numa_node);
if (!tags->rqs) {
blk_mq_free_tags(tags);
@@ -1496,7 +1496,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
do {
page = alloc_pages_node(set->numa_node,
- GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
+ GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
this_order);
if (page)
break;
@@ -1517,7 +1517,7 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
* Allow kmemleak to scan these pages as they contain pointers
* to additional allocations like via ops->init_request().
*/
- kmemleak_alloc(p, order_to_size(this_order), 1, GFP_KERNEL);
+ kmemleak_alloc(p, order_to_size(this_order), 1, GFP_NOIO);
entries_per_page = order_to_size(this_order) / rq_size;
to_do = min(entries_per_page, set->queue_depth - i);
left -= to_do * rq_size;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v3] lightnvm: physical block device (pblk) target
From: Matias Bjørling @ 2017-04-10 17:47 UTC (permalink / raw)
To: Bart Van Assche, jg@lightnvm.io
Cc: linux-kernel@vger.kernel.org, linux-block@vger.kernel.org
In-Reply-To: <1491839741.4199.7.camel@sandisk.com>
On 04/10/2017 05:55 PM, Bart Van Assche wrote:
> On Sun, 2017-04-09 at 11:15 +0200, Javier Gonz�lez wrote:
>> On 8 Apr 2017, at 22.56, Bart Van Assche <bart.vanassche@sandisk.com> wrote:
>>> On 04/07/17 11:50, Javier Gonz�lez wrote:
>> struct ppa_addr, which is the physical address format is not affected,
>> but pblk's internal L2P address representation (pblk_addr) is. You can
>> see that the type either represents struct ppa_addr or ppa_addr_32. How
>> would you define a type that can either be u64 or u32 with different bit
>> offsets at run-time? Note that address conversions to this type is in
>> the fast path and this format allows us to only use bit shifts.
>
> Selecting the appropriate representation at run-time would require to pass
> pblk_addr by reference instead of by value to any function that expects a
> pblk_addr. It would also require to have two versions of every data structure
> that depends on pblk_addr and to use casts to convert to the appropritate
> version. However, this approach is probably only worth to be implemented if
> it doesn't introduce too much additional complexity.
>
Hi Bart, thanks for the feedback!
I've spent the time today to implement it such that 32bit entries are
used if the device addressing can fit. We do see a slight overhead,
however not enough to be a deal-breaker. We'll post an updated version
with the flag removed.
>>>> +#ifdef CONFIG_NVM_DEBUG
>>>> + atomic_add(nr_entries, &pblk->inflight_writes);
>>>> + atomic_add(nr_entries, &pblk->req_writes);
>>>> +#endif
>>>
>>> Has it been considered to use the "static key" feature such that
>>> consistency checks can be enabled at run-time instead of having to
>>> rebuild the kernel to enable CONFIG_NVM_DEBUG?
>>
>> I haven't considered it. I'll look into it. I would like to have this
>> counters and the corresponding sysfs entry only available on debug mode
>> since it allows us to have a good picture of the FTL state.
>
> If there are sysfs entries that depend on CONFIG_NVM_DEBUG then the static
> key mechanism is probably not a good alternative for CONFIG_NVM_DEBUG.
>
>>> Has it been considered to add support for keeping a subset of the L2P
>>> translation table in memory instead of keeping it in memory in its entirety?
>>
>> Yes. L2P caching is on our roadmap and will be included in the future.
>
> That's great. This will also help with reducing the time between discovery of
> a lightnvm device and the time at which I/O can start since the L2P table must
> be available before I/O can start.
Definitely. I would love if one could jump in and implement it. We have
a bunch of features that we want in before implementing a translation cache.
>
> Bart.
>
^ permalink raw reply
* Re: [PATCH rfc 0/6] Automatic affinity settings for nvme over rdma
From: Steve Wise @ 2017-04-10 18:05 UTC (permalink / raw)
To: Sagi Grimberg, linux-rdma, linux-nvme, linux-block
Cc: netdev, Saeed Mahameed, Or Gerlitz, Christoph Hellwig
In-Reply-To: <1491140492-25703-1-git-send-email-sagi@grimberg.me>
On 4/2/2017 8:41 AM, Sagi Grimberg wrote:
> This patch set is aiming to automatically find the optimal
> queue <-> irq multi-queue assignments in storage ULPs (demonstrated
> on nvme-rdma) based on the underlying rdma device irq affinity
> settings.
>
> First two patches modify mlx5 core driver to use generic API
> to allocate array of irq vectors with automatic affinity
> settings instead of open-coding exactly what it does (and
> slightly worse).
>
> Then, in order to obtain an affinity map for a given completion
> vector, we expose a new RDMA core API, and implement it in mlx5.
>
> The third part is addition of a rdma-based queue mapping helper
> to blk-mq that maps the tagset hctx's according to the device
> affinity mappings.
>
> I'd happily convert some more drivers, but I'll need volunteers
> to test as I don't have access to any other devices.
I'll test cxgb4 if you convert it. :)
^ permalink raw reply
* Re: [PATCH 0/2] Export more queue state information through debugfs
From: Jens Axboe @ 2017-04-10 18:28 UTC (permalink / raw)
To: Bart Van Assche; +Cc: linux-block
In-Reply-To: <20170330182127.24288-1-bart.vanassche@sandisk.com>
On 03/30/2017 12:21 PM, Bart Van Assche wrote:
> Hello Jens,
>
> This is a short patch series with one patch that exports the queue state
> and another patch that shows symbolic names for hctx state and flags
> instead of a numerical bitmask.
>
> Please consider these patches for kernel v4.12.
Thanks, added for 4.12.
--
Jens Axboe
^ permalink raw reply
* [PATCH v4] lightnvm: pblk
From: Javier González @ 2017-04-10 18:36 UTC (permalink / raw)
To: mb; +Cc: linux-block, linux-kernel, Bart.VanAssche, Javier González
This patch introduces pblk, a new target for LightNVM implementing a
full host-based FTL. Details on the commit message.
Changes since v3:
* Apply Bart's feedback [1]
* Implement dynamic L2P optimizations for > 32-bit physical media
* geometry (from Matias Bjørling)
* Fix memory leak on GC (Reported by Simon A. F. Lund)
* 8064 is a perfectly round number of lines :)
[1] https://lkml.org/lkml/2017/4/8/172
Changes since v2:
* Rebase on top of Matias' for-4.12/core
* Implement L2P scan recovery to recover L2P table in case of power
failure.
* Re-design disk format to be more flexible in future versions (from
Matias Bjørling)
* Implement per-instance uuid to allow correct recovery without
forcing line erases (from Matias Bjørling)
* Re-design GC threading to have several GC readers and a single
writer that places data on the write buffer. This allows to maximize
the GC write buffer budget without having unnecessary GC writers
competing for the write buffer lock.
* Simplify sysfs interface.
* Refactoring and several code improvements (together with Matias
Bjørling)
Changes since v1:
* Rebase on top of Matias' for-4.12/core
* Move from per-LUN block allocation to a line model. This means that a
whole lines across all LUNs is allocated at a time. Data is still
stripped in a round-robin fashion at a page granurality.
* Implement new disk format scheme, where metadata is stored per line
instead of per LUN. This allows for space optimizations.
* Improvements on GC workqueue management and victim selection.
* Implement sysfs interface to query pblk's operation and statistics.
* Implement a user - GC I/O rate-limiter
* Various bug fixes
Javier González (1):
lightnvm: physical block device (pblk) target
Documentation/lightnvm/pblk.txt | 21 +
drivers/lightnvm/Kconfig | 9 +
drivers/lightnvm/Makefile | 5 +
drivers/lightnvm/pblk-cache.c | 114 +++
drivers/lightnvm/pblk-core.c | 1658 ++++++++++++++++++++++++++++++++++++++
drivers/lightnvm/pblk-gc.c | 555 +++++++++++++
drivers/lightnvm/pblk-init.c | 948 ++++++++++++++++++++++
drivers/lightnvm/pblk-map.c | 134 +++
drivers/lightnvm/pblk-rb.c | 856 ++++++++++++++++++++
drivers/lightnvm/pblk-read.c | 529 ++++++++++++
drivers/lightnvm/pblk-recovery.c | 1003 +++++++++++++++++++++++
drivers/lightnvm/pblk-rl.c | 182 +++++
drivers/lightnvm/pblk-sysfs.c | 502 ++++++++++++
drivers/lightnvm/pblk-write.c | 412 ++++++++++
drivers/lightnvm/pblk.h | 1136 ++++++++++++++++++++++++++
15 files changed, 8064 insertions(+)
create mode 100644 Documentation/lightnvm/pblk.txt
create mode 100644 drivers/lightnvm/pblk-cache.c
create mode 100644 drivers/lightnvm/pblk-core.c
create mode 100644 drivers/lightnvm/pblk-gc.c
create mode 100644 drivers/lightnvm/pblk-init.c
create mode 100644 drivers/lightnvm/pblk-map.c
create mode 100644 drivers/lightnvm/pblk-rb.c
create mode 100644 drivers/lightnvm/pblk-read.c
create mode 100644 drivers/lightnvm/pblk-recovery.c
create mode 100644 drivers/lightnvm/pblk-rl.c
create mode 100644 drivers/lightnvm/pblk-sysfs.c
create mode 100644 drivers/lightnvm/pblk-write.c
create mode 100644 drivers/lightnvm/pblk.h
--
2.7.4
^ permalink raw reply
* Re: [PATCH 0/2] Export more queue state information through debugfs
From: Bart Van Assche @ 2017-04-10 18:40 UTC (permalink / raw)
To: Jens Axboe; +Cc: linux-block@vger.kernel.org
In-Reply-To: <826af944-2316-8352-118c-91887d747eca@kernel.dk>
On 04/10/2017 11:28 AM, Jens Axboe wrote:
> On 03/30/2017 12:21 PM, Bart Van Assche wrote:
>> This is a short patch series with one patch that exports the queue state
>> and another patch that shows symbolic names for hctx state and flags
>> instead of a numerical bitmask.
>>
>> Please consider these patches for kernel v4.12.
>
> Thanks, added for 4.12.
Hello Jens,
Thanks! This infrastructure was essential while analyzing queue stalls.
After I had posted this series I improved and extended the blk-mq debugfs
functionality further. Please consider including the patch below in v4.12.
Thanks,
Bart.
From: Bart Van Assche <bart.vanassche@sandisk.com>
Subject: [PATCH] blk-mq: Two fixes for the code that exports the queue state
Remove the array entry for QUEUE_FLAG_RESTART since that flag has
been removed after the blk-mq-debugfs patch that introduced this
array entry was posted.
Avoid that querying the queue state of a dead queue triggers a
kernel crash.
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
---
block/blk-mq-debugfs.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 91d09f58a596..a1ce823578c7 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -92,7 +92,6 @@ static const char *const blk_queue_flag_name[] = {
[QUEUE_FLAG_FLUSH_NQ] = "FLUSH_NQ",
[QUEUE_FLAG_DAX] = "DAX",
[QUEUE_FLAG_STATS] = "STATS",
- [QUEUE_FLAG_RESTART] = "RESTART",
[QUEUE_FLAG_POLL_STATS] = "POLL_STATS",
[QUEUE_FLAG_REGISTERED] = "REGISTERED",
};
@@ -112,6 +111,14 @@ static ssize_t blk_queue_flags_store(struct file *file, const char __user *ubuf,
struct request_queue *q = file_inode(file)->i_private;
char op[16] = { }, *s;
+ /*
+ * The debugfs attributes are removed after blk_cleanup_queue() has
+ * called blk_mq_free_queue(). Return if QUEUE_FLAG_DEAD has been set
+ * to avoid triggering a use-after-free.
+ */
+ if (blk_queue_dead(q))
+ return -ENOENT;
+
len = min(len, sizeof(op) - 1);
if (copy_from_user(op, ubuf, len))
return -EFAULT;
--
2.12.0
^ permalink raw reply related
* [PATCH 1/3] lightnvm: convert sprintf into snprintf
From: Javier González @ 2017-04-10 18:51 UTC (permalink / raw)
To: mb; +Cc: linux-block, linux-kernel, Javier González
Convert sprintf calls to snprintf in order to make possible buffer
overflow more obvious.
Signed-off-by: Javier González <javier@cnexlabs.com>
---
drivers/lightnvm/core.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index c3340ef..bdbb333 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -272,7 +272,8 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
goto err_disk;
blk_queue_make_request(tqueue, tt->make_rq);
- sprintf(tdisk->disk_name, "%s", create->tgtname);
+ snprintf(tdisk->disk_name, sizeof(tdisk->disk_name), "%s",
+ create->tgtname);
tdisk->flags = GENHD_FL_EXT_DEVT;
tdisk->major = 0;
tdisk->first_minor = 0;
@@ -1195,13 +1196,13 @@ static long nvm_ioctl_get_devices(struct file *file, void __user *arg)
list_for_each_entry(dev, &nvm_devices, devices) {
struct nvm_ioctl_device_info *info = &devices->info[i];
- sprintf(info->devname, "%s", dev->name);
+ snprintf(info->devname, sizeof(info->devname), "%s", dev->name);
/* kept for compatibility */
info->bmversion[0] = 1;
info->bmversion[1] = 0;
info->bmversion[2] = 0;
- sprintf(info->bmname, "%s", "gennvm");
+ snprintf(info->bmname, sizeof(info->bmname), "%s", "gennvm");
i++;
if (i > 31) {
--
2.7.4
^ permalink raw reply related
* [PATCH 2/3] lightnvm: make nvm_free static
From: Javier González @ 2017-04-10 18:51 UTC (permalink / raw)
To: mb; +Cc: linux-block, linux-kernel, Javier González
In-Reply-To: <1491850297-18235-1-git-send-email-javier@cnexlabs.com>
Prefix the nvm_free static function with a missing static keyword.
Signed-off-by: Javier González <javier@cnexlabs.com>
---
drivers/lightnvm/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index bdbb333..3e51a05 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -999,7 +999,7 @@ static int nvm_core_init(struct nvm_dev *dev)
return ret;
}
-void nvm_free(struct nvm_dev *dev)
+static void nvm_free(struct nvm_dev *dev)
{
if (!dev)
return;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 1/3] lightnvm: convert sprintf into snprintf
From: Bart Van Assche @ 2017-04-10 18:56 UTC (permalink / raw)
To: mb@lightnvm.io, jg@lightnvm.io
Cc: linux-kernel@vger.kernel.org, linux-block@vger.kernel.org,
javier@cnexlabs.com
In-Reply-To: <1491850297-18235-1-git-send-email-javier@cnexlabs.com>
On Mon, 2017-04-10 at 20:51 +0200, Javier Gonz=E1lez wrote:
> Convert sprintf calls to snprintf in order to make possible buffer
> overflow more obvious.
>=20
> Signed-off-by: Javier Gonz=E1lez <javier@cnexlabs.com>
> ---
> drivers/lightnvm/core.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>=20
> diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
> index c3340ef..bdbb333 100644
> --- a/drivers/lightnvm/core.c
> +++ b/drivers/lightnvm/core.c
> @@ -272,7 +272,8 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct=
nvm_ioctl_create *create)
> goto err_disk;
> blk_queue_make_request(tqueue, tt->make_rq);
> =20
> - sprintf(tdisk->disk_name, "%s", create->tgtname);
> + snprintf(tdisk->disk_name, sizeof(tdisk->disk_name), "%s",
> + create->tgtname);
> tdisk->flags =3D GENHD_FL_EXT_DEVT;
> tdisk->major =3D 0;
> tdisk->first_minor =3D 0;
> @@ -1195,13 +1196,13 @@ static long nvm_ioctl_get_devices(struct file *fi=
le, void __user *arg)
> list_for_each_entry(dev, &nvm_devices, devices) {
> struct nvm_ioctl_device_info *info =3D &devices->info[i];
> =20
> - sprintf(info->devname, "%s", dev->name);
> + snprintf(info->devname, sizeof(info->devname), "%s", dev->name);
> =20
> /* kept for compatibility */
> info->bmversion[0] =3D 1;
> info->bmversion[1] =3D 0;
> info->bmversion[2] =3D 0;
> - sprintf(info->bmname, "%s", "gennvm");
> + snprintf(info->bmname, sizeof(info->bmname), "%s", "gennvm");
> i++;
> =20
> if (i > 31) {
Hello Javier,
Although the above changes look fine to me, have you considered to use strl=
cpy()
instead of snprintf() for these string copy operations?
Bart.=
^ permalink raw reply
* Re: [PATCH 03/27] block: implement splitting of REQ_OP_WRITE_ZEROES bios
From: Anthony Youngman @ 2017-04-10 19:40 UTC (permalink / raw)
To: Christoph Hellwig, axboe, martin.petersen, agk, snitzer, shli,
philipp.reisner, lars.ellenberg
Cc: linux-block, linux-scsi, drbd-dev, dm-devel, linux-raid
In-Reply-To: <20170405142205.6477-4-hch@lst.de>
s/past/paste/
On 05/04/17 15:21, Christoph Hellwig wrote:
> Copy and past the REQ_OP_WRITE_SAME code to prepare to implementations
> that limit the write zeroes size.
Cheers,
Wol
^ permalink raw reply
* Re: [PATCH 0/2] Export more queue state information through debugfs
From: Omar Sandoval @ 2017-04-10 20:00 UTC (permalink / raw)
To: Bart Van Assche; +Cc: Jens Axboe, linux-block@vger.kernel.org
In-Reply-To: <51f5cd27-4ae4-0a21-63e2-c7a2ec95e257@sandisk.com>
On Mon, Apr 10, 2017 at 11:40:49AM -0700, Bart Van Assche wrote:
> On 04/10/2017 11:28 AM, Jens Axboe wrote:
> > On 03/30/2017 12:21 PM, Bart Van Assche wrote:
> >> This is a short patch series with one patch that exports the queue state
> >> and another patch that shows symbolic names for hctx state and flags
> >> instead of a numerical bitmask.
> >>
> >> Please consider these patches for kernel v4.12.
> >
> > Thanks, added for 4.12.
>
> Hello Jens,
>
> Thanks! This infrastructure was essential while analyzing queue stalls.
>
> After I had posted this series I improved and extended the blk-mq debugfs
> functionality further. Please consider including the patch below in v4.12.
>
> Thanks,
>
> Bart.
>
>
> From: Bart Van Assche <bart.vanassche@sandisk.com>
> Subject: [PATCH] blk-mq: Two fixes for the code that exports the queue state
>
> Remove the array entry for QUEUE_FLAG_RESTART since that flag has
> been removed after the blk-mq-debugfs patch that introduced this
> array entry was posted.
>
> Avoid that querying the queue state of a dead queue triggers a
> kernel crash.
>
> Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
> ---
> block/blk-mq-debugfs.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
> index 91d09f58a596..a1ce823578c7 100644
> --- a/block/blk-mq-debugfs.c
> +++ b/block/blk-mq-debugfs.c
> @@ -92,7 +92,6 @@ static const char *const blk_queue_flag_name[] = {
> [QUEUE_FLAG_FLUSH_NQ] = "FLUSH_NQ",
> [QUEUE_FLAG_DAX] = "DAX",
> [QUEUE_FLAG_STATS] = "STATS",
> - [QUEUE_FLAG_RESTART] = "RESTART",
> [QUEUE_FLAG_POLL_STATS] = "POLL_STATS",
> [QUEUE_FLAG_REGISTERED] = "REGISTERED",
> };
> @@ -112,6 +111,14 @@ static ssize_t blk_queue_flags_store(struct file *file, const char __user *ubuf,
> struct request_queue *q = file_inode(file)->i_private;
> char op[16] = { }, *s;
>
> + /*
> + * The debugfs attributes are removed after blk_cleanup_queue() has
> + * called blk_mq_free_queue(). Return if QUEUE_FLAG_DEAD has been set
> + * to avoid triggering a use-after-free.
> + */
> + if (blk_queue_dead(q))
> + return -ENOENT;
> +
Can you just move blk_queue_flags_fops to blk_mq_debugfs_queue_attrs
instead of adding blk_queue_attrs?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox