Commit 6e5f0f63 authored by Hongyu Jin's avatar Hongyu Jin Committed by Mike Snitzer

dm io: Support IO priority

Some IO will dispatch from kworker with different io_context settings
than the submitting task, we may need to specify a priority to avoid
losing priority.

Add IO priority parameter to dm_io() and update all callers.
Co-developed-by: default avatarYibin Ding <yibin.ding@unisoc.com>
Signed-off-by: default avatarYibin Ding <yibin.ding@unisoc.com>
Signed-off-by: default avatarHongyu Jin <hongyu.jin@unisoc.com>
Reviewed-by: default avatarEric Biggers <ebiggers@google.com>
Reviewed-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
parent b9d3ac48
...@@ -1315,7 +1315,7 @@ static void use_dmio(struct dm_buffer *b, enum req_op op, sector_t sector, ...@@ -1315,7 +1315,7 @@ static void use_dmio(struct dm_buffer *b, enum req_op op, sector_t sector,
io_req.mem.ptr.vma = (char *)b->data + offset; io_req.mem.ptr.vma = (char *)b->data + offset;
} }
r = dm_io(&io_req, 1, &region, NULL); r = dm_io(&io_req, 1, &region, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) if (unlikely(r))
b->end_io(b, errno_to_blk_status(r)); b->end_io(b, errno_to_blk_status(r));
} }
...@@ -2167,7 +2167,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c) ...@@ -2167,7 +2167,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c)
if (WARN_ON_ONCE(dm_bufio_in_request())) if (WARN_ON_ONCE(dm_bufio_in_request()))
return -EINVAL; return -EINVAL;
return dm_io(&io_req, 1, &io_reg, NULL); return dm_io(&io_req, 1, &io_reg, NULL, IOPRIO_DEFAULT);
} }
EXPORT_SYMBOL_GPL(dm_bufio_issue_flush); EXPORT_SYMBOL_GPL(dm_bufio_issue_flush);
...@@ -2191,7 +2191,7 @@ int dm_bufio_issue_discard(struct dm_bufio_client *c, sector_t block, sector_t c ...@@ -2191,7 +2191,7 @@ int dm_bufio_issue_discard(struct dm_bufio_client *c, sector_t block, sector_t c
if (WARN_ON_ONCE(dm_bufio_in_request())) if (WARN_ON_ONCE(dm_bufio_in_request()))
return -EINVAL; /* discards are optional */ return -EINVAL; /* discards are optional */
return dm_io(&io_req, 1, &io_reg, NULL); return dm_io(&io_req, 1, &io_reg, NULL, IOPRIO_DEFAULT);
} }
EXPORT_SYMBOL_GPL(dm_bufio_issue_discard); EXPORT_SYMBOL_GPL(dm_bufio_issue_discard);
......
...@@ -555,7 +555,7 @@ static int sync_rw_sb(struct dm_integrity_c *ic, blk_opf_t opf) ...@@ -555,7 +555,7 @@ static int sync_rw_sb(struct dm_integrity_c *ic, blk_opf_t opf)
} }
} }
r = dm_io(&io_req, 1, &io_loc, NULL); r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) if (unlikely(r))
return r; return r;
...@@ -1073,7 +1073,7 @@ static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf, ...@@ -1073,7 +1073,7 @@ static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf,
io_loc.sector = ic->start + SB_SECTORS + sector; io_loc.sector = ic->start + SB_SECTORS + sector;
io_loc.count = n_sectors; io_loc.count = n_sectors;
r = dm_io(&io_req, 1, &io_loc, NULL); r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) { if (unlikely(r)) {
dm_integrity_io_error(ic, (opf & REQ_OP_MASK) == REQ_OP_READ ? dm_integrity_io_error(ic, (opf & REQ_OP_MASK) == REQ_OP_READ ?
"reading journal" : "writing journal", r); "reading journal" : "writing journal", r);
...@@ -1190,7 +1190,7 @@ static void copy_from_journal(struct dm_integrity_c *ic, unsigned int section, u ...@@ -1190,7 +1190,7 @@ static void copy_from_journal(struct dm_integrity_c *ic, unsigned int section, u
io_loc.sector = target; io_loc.sector = target;
io_loc.count = n_sectors; io_loc.count = n_sectors;
r = dm_io(&io_req, 1, &io_loc, NULL); r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) { if (unlikely(r)) {
WARN_ONCE(1, "asynchronous dm_io failed: %d", r); WARN_ONCE(1, "asynchronous dm_io failed: %d", r);
fn(-1UL, data); fn(-1UL, data);
...@@ -1519,7 +1519,7 @@ static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_dat ...@@ -1519,7 +1519,7 @@ static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_dat
fr.io_reg.count = 0, fr.io_reg.count = 0,
fr.ic = ic; fr.ic = ic;
init_completion(&fr.comp); init_completion(&fr.comp);
r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL); r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL, IOPRIO_DEFAULT);
BUG_ON(r); BUG_ON(r);
} }
...@@ -1728,7 +1728,7 @@ static void integrity_recheck(struct dm_integrity_io *dio) ...@@ -1728,7 +1728,7 @@ static void integrity_recheck(struct dm_integrity_io *dio)
io_loc.sector = sector; io_loc.sector = sector;
io_loc.count = ic->sectors_per_block; io_loc.count = ic->sectors_per_block;
r = dm_io(&io_req, 1, &io_loc, NULL); r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) { if (unlikely(r)) {
dio->bi_status = errno_to_blk_status(r); dio->bi_status = errno_to_blk_status(r);
goto free_ret; goto free_ret;
...@@ -2808,7 +2808,7 @@ static void integrity_recalc(struct work_struct *w) ...@@ -2808,7 +2808,7 @@ static void integrity_recalc(struct work_struct *w)
io_loc.sector = get_data_sector(ic, area, offset); io_loc.sector = get_data_sector(ic, area, offset);
io_loc.count = n_sectors; io_loc.count = n_sectors;
r = dm_io(&io_req, 1, &io_loc, NULL); r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) { if (unlikely(r)) {
dm_integrity_io_error(ic, "reading data", r); dm_integrity_io_error(ic, "reading data", r);
goto err; goto err;
......
...@@ -305,7 +305,7 @@ static void km_dp_init(struct dpages *dp, void *data) ...@@ -305,7 +305,7 @@ static void km_dp_init(struct dpages *dp, void *data)
*/ */
static void do_region(const blk_opf_t opf, unsigned int region, static void do_region(const blk_opf_t opf, unsigned int region,
struct dm_io_region *where, struct dpages *dp, struct dm_io_region *where, struct dpages *dp,
struct io *io) struct io *io, unsigned short ioprio)
{ {
struct bio *bio; struct bio *bio;
struct page *page; struct page *page;
...@@ -354,6 +354,7 @@ static void do_region(const blk_opf_t opf, unsigned int region, ...@@ -354,6 +354,7 @@ static void do_region(const blk_opf_t opf, unsigned int region,
&io->client->bios); &io->client->bios);
bio->bi_iter.bi_sector = where->sector + (where->count - remaining); bio->bi_iter.bi_sector = where->sector + (where->count - remaining);
bio->bi_end_io = endio; bio->bi_end_io = endio;
bio->bi_ioprio = ioprio;
store_io_and_region_in_bio(bio, io, region); store_io_and_region_in_bio(bio, io, region);
if (op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES) { if (op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES) {
...@@ -383,7 +384,7 @@ static void do_region(const blk_opf_t opf, unsigned int region, ...@@ -383,7 +384,7 @@ static void do_region(const blk_opf_t opf, unsigned int region,
static void dispatch_io(blk_opf_t opf, unsigned int num_regions, static void dispatch_io(blk_opf_t opf, unsigned int num_regions,
struct dm_io_region *where, struct dpages *dp, struct dm_io_region *where, struct dpages *dp,
struct io *io, int sync) struct io *io, int sync, unsigned short ioprio)
{ {
int i; int i;
struct dpages old_pages = *dp; struct dpages old_pages = *dp;
...@@ -400,7 +401,7 @@ static void dispatch_io(blk_opf_t opf, unsigned int num_regions, ...@@ -400,7 +401,7 @@ static void dispatch_io(blk_opf_t opf, unsigned int num_regions,
for (i = 0; i < num_regions; i++) { for (i = 0; i < num_regions; i++) {
*dp = old_pages; *dp = old_pages;
if (where[i].count || (opf & REQ_PREFLUSH)) if (where[i].count || (opf & REQ_PREFLUSH))
do_region(opf, i, where + i, dp, io); do_region(opf, i, where + i, dp, io, ioprio);
} }
/* /*
...@@ -425,7 +426,7 @@ static void sync_io_complete(unsigned long error, void *context) ...@@ -425,7 +426,7 @@ static void sync_io_complete(unsigned long error, void *context)
static int sync_io(struct dm_io_client *client, unsigned int num_regions, static int sync_io(struct dm_io_client *client, unsigned int num_regions,
struct dm_io_region *where, blk_opf_t opf, struct dpages *dp, struct dm_io_region *where, blk_opf_t opf, struct dpages *dp,
unsigned long *error_bits) unsigned long *error_bits, unsigned short ioprio)
{ {
struct io *io; struct io *io;
struct sync_io sio; struct sync_io sio;
...@@ -447,7 +448,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, ...@@ -447,7 +448,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
io->vma_invalidate_address = dp->vma_invalidate_address; io->vma_invalidate_address = dp->vma_invalidate_address;
io->vma_invalidate_size = dp->vma_invalidate_size; io->vma_invalidate_size = dp->vma_invalidate_size;
dispatch_io(opf, num_regions, where, dp, io, 1); dispatch_io(opf, num_regions, where, dp, io, 1, ioprio);
wait_for_completion_io(&sio.wait); wait_for_completion_io(&sio.wait);
...@@ -459,7 +460,8 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, ...@@ -459,7 +460,8 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
static int async_io(struct dm_io_client *client, unsigned int num_regions, static int async_io(struct dm_io_client *client, unsigned int num_regions,
struct dm_io_region *where, blk_opf_t opf, struct dm_io_region *where, blk_opf_t opf,
struct dpages *dp, io_notify_fn fn, void *context) struct dpages *dp, io_notify_fn fn, void *context,
unsigned short ioprio)
{ {
struct io *io; struct io *io;
...@@ -479,7 +481,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, ...@@ -479,7 +481,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,
io->vma_invalidate_address = dp->vma_invalidate_address; io->vma_invalidate_address = dp->vma_invalidate_address;
io->vma_invalidate_size = dp->vma_invalidate_size; io->vma_invalidate_size = dp->vma_invalidate_size;
dispatch_io(opf, num_regions, where, dp, io, 0); dispatch_io(opf, num_regions, where, dp, io, 0, ioprio);
return 0; return 0;
} }
...@@ -521,7 +523,8 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp, ...@@ -521,7 +523,8 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
} }
int dm_io(struct dm_io_request *io_req, unsigned int num_regions, int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
struct dm_io_region *where, unsigned long *sync_error_bits) struct dm_io_region *where, unsigned long *sync_error_bits,
unsigned short ioprio)
{ {
int r; int r;
struct dpages dp; struct dpages dp;
...@@ -532,11 +535,11 @@ int dm_io(struct dm_io_request *io_req, unsigned int num_regions, ...@@ -532,11 +535,11 @@ int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
if (!io_req->notify.fn) if (!io_req->notify.fn)
return sync_io(io_req->client, num_regions, where, return sync_io(io_req->client, num_regions, where,
io_req->bi_opf, &dp, sync_error_bits); io_req->bi_opf, &dp, sync_error_bits, ioprio);
return async_io(io_req->client, num_regions, where, return async_io(io_req->client, num_regions, where,
io_req->bi_opf, &dp, io_req->notify.fn, io_req->bi_opf, &dp, io_req->notify.fn,
io_req->notify.context); io_req->notify.context, ioprio);
} }
EXPORT_SYMBOL(dm_io); EXPORT_SYMBOL(dm_io);
......
...@@ -578,9 +578,9 @@ static int run_io_job(struct kcopyd_job *job) ...@@ -578,9 +578,9 @@ static int run_io_job(struct kcopyd_job *job)
io_job_start(job->kc->throttle); io_job_start(job->kc->throttle);
if (job->op == REQ_OP_READ) if (job->op == REQ_OP_READ)
r = dm_io(&io_req, 1, &job->source, NULL); r = dm_io(&io_req, 1, &job->source, NULL, IOPRIO_DEFAULT);
else else
r = dm_io(&io_req, job->num_dests, job->dests, NULL); r = dm_io(&io_req, job->num_dests, job->dests, NULL, IOPRIO_DEFAULT);
return r; return r;
} }
......
...@@ -300,7 +300,7 @@ static int rw_header(struct log_c *lc, enum req_op op) ...@@ -300,7 +300,7 @@ static int rw_header(struct log_c *lc, enum req_op op)
{ {
lc->io_req.bi_opf = op; lc->io_req.bi_opf = op;
return dm_io(&lc->io_req, 1, &lc->header_location, NULL); return dm_io(&lc->io_req, 1, &lc->header_location, NULL, IOPRIO_DEFAULT);
} }
static int flush_header(struct log_c *lc) static int flush_header(struct log_c *lc)
...@@ -313,7 +313,7 @@ static int flush_header(struct log_c *lc) ...@@ -313,7 +313,7 @@ static int flush_header(struct log_c *lc)
lc->io_req.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; lc->io_req.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
return dm_io(&lc->io_req, 1, &null_location, NULL); return dm_io(&lc->io_req, 1, &null_location, NULL, IOPRIO_DEFAULT);
} }
static int read_header(struct log_c *log) static int read_header(struct log_c *log)
......
...@@ -278,7 +278,7 @@ static int mirror_flush(struct dm_target *ti) ...@@ -278,7 +278,7 @@ static int mirror_flush(struct dm_target *ti)
} }
error_bits = -1; error_bits = -1;
dm_io(&io_req, ms->nr_mirrors, io, &error_bits); dm_io(&io_req, ms->nr_mirrors, io, &error_bits, IOPRIO_DEFAULT);
if (unlikely(error_bits != 0)) { if (unlikely(error_bits != 0)) {
for (i = 0; i < ms->nr_mirrors; i++) for (i = 0; i < ms->nr_mirrors; i++)
if (test_bit(i, &error_bits)) if (test_bit(i, &error_bits))
...@@ -554,7 +554,7 @@ static void read_async_bio(struct mirror *m, struct bio *bio) ...@@ -554,7 +554,7 @@ static void read_async_bio(struct mirror *m, struct bio *bio)
map_region(&io, m, bio); map_region(&io, m, bio);
bio_set_m(bio, m); bio_set_m(bio, m);
BUG_ON(dm_io(&io_req, 1, &io, NULL)); BUG_ON(dm_io(&io_req, 1, &io, NULL, IOPRIO_DEFAULT));
} }
static inline int region_in_sync(struct mirror_set *ms, region_t region, static inline int region_in_sync(struct mirror_set *ms, region_t region,
...@@ -681,7 +681,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio) ...@@ -681,7 +681,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
*/ */
bio_set_m(bio, get_default_mirror(ms)); bio_set_m(bio, get_default_mirror(ms));
BUG_ON(dm_io(&io_req, ms->nr_mirrors, io, NULL)); BUG_ON(dm_io(&io_req, ms->nr_mirrors, io, NULL, IOPRIO_DEFAULT));
} }
static void do_writes(struct mirror_set *ms, struct bio_list *writes) static void do_writes(struct mirror_set *ms, struct bio_list *writes)
......
...@@ -223,7 +223,7 @@ static void do_metadata(struct work_struct *work) ...@@ -223,7 +223,7 @@ static void do_metadata(struct work_struct *work)
{ {
struct mdata_req *req = container_of(work, struct mdata_req, work); struct mdata_req *req = container_of(work, struct mdata_req, work);
req->result = dm_io(req->io_req, 1, req->where, NULL); req->result = dm_io(req->io_req, 1, req->where, NULL, IOPRIO_DEFAULT);
} }
/* /*
...@@ -247,7 +247,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, blk_opf_t opf, ...@@ -247,7 +247,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, blk_opf_t opf,
struct mdata_req req; struct mdata_req req;
if (!metadata) if (!metadata)
return dm_io(&io_req, 1, &where, NULL); return dm_io(&io_req, 1, &where, NULL, IOPRIO_DEFAULT);
req.where = &where; req.where = &where;
req.io_req = &io_req; req.io_req = &io_req;
......
...@@ -511,7 +511,7 @@ static int verity_recheck(struct dm_verity *v, struct dm_verity_io *io, ...@@ -511,7 +511,7 @@ static int verity_recheck(struct dm_verity *v, struct dm_verity_io *io,
io_loc.bdev = v->data_dev->bdev; io_loc.bdev = v->data_dev->bdev;
io_loc.sector = cur_block << (v->data_dev_block_bits - SECTOR_SHIFT); io_loc.sector = cur_block << (v->data_dev_block_bits - SECTOR_SHIFT);
io_loc.count = 1 << (v->data_dev_block_bits - SECTOR_SHIFT); io_loc.count = 1 << (v->data_dev_block_bits - SECTOR_SHIFT);
r = dm_io(&io_req, 1, &io_loc, NULL); r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) if (unlikely(r))
goto free_ret; goto free_ret;
......
...@@ -531,7 +531,7 @@ static void ssd_commit_flushed(struct dm_writecache *wc, bool wait_for_ios) ...@@ -531,7 +531,7 @@ static void ssd_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
req.notify.context = &endio; req.notify.context = &endio;
/* writing via async dm-io (implied by notify.fn above) won't return an error */ /* writing via async dm-io (implied by notify.fn above) won't return an error */
(void) dm_io(&req, 1, &region, NULL); (void) dm_io(&req, 1, &region, NULL, IOPRIO_DEFAULT);
i = j; i = j;
} }
...@@ -568,7 +568,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc) ...@@ -568,7 +568,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)
req.notify.fn = NULL; req.notify.fn = NULL;
req.notify.context = NULL; req.notify.context = NULL;
r = dm_io(&req, 1, &region, NULL); r = dm_io(&req, 1, &region, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) if (unlikely(r))
writecache_error(wc, r, "error writing superblock"); writecache_error(wc, r, "error writing superblock");
} }
...@@ -596,7 +596,7 @@ static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev) ...@@ -596,7 +596,7 @@ static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev)
req.client = wc->dm_io; req.client = wc->dm_io;
req.notify.fn = NULL; req.notify.fn = NULL;
r = dm_io(&req, 1, &region, NULL); r = dm_io(&req, 1, &region, NULL, IOPRIO_DEFAULT);
if (unlikely(r)) if (unlikely(r))
writecache_error(wc, r, "error flushing metadata: %d", r); writecache_error(wc, r, "error flushing metadata: %d", r);
} }
...@@ -990,7 +990,7 @@ static int writecache_read_metadata(struct dm_writecache *wc, sector_t n_sectors ...@@ -990,7 +990,7 @@ static int writecache_read_metadata(struct dm_writecache *wc, sector_t n_sectors
req.client = wc->dm_io; req.client = wc->dm_io;
req.notify.fn = NULL; req.notify.fn = NULL;
return dm_io(&req, 1, &region, NULL); return dm_io(&req, 1, &region, NULL, IOPRIO_DEFAULT);
} }
static void writecache_resume(struct dm_target *ti) static void writecache_resume(struct dm_target *ti)
......
...@@ -80,7 +80,8 @@ void dm_io_client_destroy(struct dm_io_client *client); ...@@ -80,7 +80,8 @@ void dm_io_client_destroy(struct dm_io_client *client);
* error occurred doing io to the corresponding region. * error occurred doing io to the corresponding region.
*/ */
int dm_io(struct dm_io_request *io_req, unsigned int num_regions, int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
struct dm_io_region *region, unsigned int long *sync_error_bits); struct dm_io_region *region, unsigned int long *sync_error_bits,
unsigned short ioprio);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_DM_IO_H */ #endif /* _LINUX_DM_IO_H */
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