Skip to content

Commit 837ed30

Browse files
Ming Leiaxboe
authored andcommitted
loop: add hint for handling aio via IOCB_NOWAIT
Add hint for using IOCB_NOWAIT to handle loop aio command for avoiding to cause write(especially randwrite) perf regression on sparse backed file. Try IOCB_NOWAIT in the following situations: - backing file is block device OR - READ aio command OR - there isn't any queued blocking async WRITEs, because NOWAIT won't cause contention with blocking WRITE, which often implies exclusive lock With this simple policy, perf regression of randwrite/write on sparse backing file is fixed. Link: https://lore.kernel.org/dm-devel/7d6ae2c9-df8e-50d0-7ad6-b787cb3cfab4@redhat.com/ Signed-off-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 0ba93a9 commit 837ed30

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

drivers/block/loop.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct loop_device {
6868
struct rb_root worker_tree;
6969
struct timer_list timer;
7070
bool sysfs_inited;
71+
unsigned lo_nr_blocking_writes;
7172

7273
struct request_queue *lo_queue;
7374
struct blk_mq_tag_set tag_set;
@@ -467,6 +468,33 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
467468
return -EIOCBQUEUED;
468469
}
469470

471+
static inline bool lo_aio_try_nowait(struct loop_device *lo,
472+
struct loop_cmd *cmd)
473+
{
474+
struct file *file = lo->lo_backing_file;
475+
struct inode *inode = file->f_mapping->host;
476+
struct request *rq = blk_mq_rq_from_pdu(cmd);
477+
478+
/* NOWAIT works fine for backing block device */
479+
if (S_ISBLK(inode->i_mode))
480+
return true;
481+
482+
/*
483+
* NOWAIT is supposed to be fine for READ without contending with
484+
* blocking WRITE
485+
*/
486+
if (req_op(rq) == REQ_OP_READ)
487+
return true;
488+
489+
/*
490+
* If there is any queued non-NOWAIT async WRITE , don't try new
491+
* NOWAIT WRITE for avoiding contention
492+
*
493+
* Here we focus on handling stable FS block mapping via NOWAIT
494+
*/
495+
return READ_ONCE(lo->lo_nr_blocking_writes) == 0;
496+
}
497+
470498
static int lo_rw_aio_nowait(struct loop_device *lo, struct loop_cmd *cmd,
471499
int rw)
472500
{
@@ -478,6 +506,9 @@ static int lo_rw_aio_nowait(struct loop_device *lo, struct loop_cmd *cmd,
478506
if (unlikely(ret))
479507
goto fail;
480508

509+
if (!lo_aio_try_nowait(lo, cmd))
510+
return -EAGAIN;
511+
481512
cmd->iocb.ki_flags |= IOCB_NOWAIT;
482513
ret = lo_submit_rw_aio(lo, cmd, nr_bvec, rw);
483514
fail:
@@ -780,12 +811,19 @@ static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf)
780811
return sysfs_emit(buf, "%s\n", dio ? "1" : "0");
781812
}
782813

814+
static ssize_t loop_attr_nr_blocking_writes_show(struct loop_device *lo,
815+
char *buf)
816+
{
817+
return sysfs_emit(buf, "%u\n", lo->lo_nr_blocking_writes);
818+
}
819+
783820
LOOP_ATTR_RO(backing_file);
784821
LOOP_ATTR_RO(offset);
785822
LOOP_ATTR_RO(sizelimit);
786823
LOOP_ATTR_RO(autoclear);
787824
LOOP_ATTR_RO(partscan);
788825
LOOP_ATTR_RO(dio);
826+
LOOP_ATTR_RO(nr_blocking_writes);
789827

790828
static struct attribute *loop_attrs[] = {
791829
&loop_attr_backing_file.attr,
@@ -794,6 +832,7 @@ static struct attribute *loop_attrs[] = {
794832
&loop_attr_autoclear.attr,
795833
&loop_attr_partscan.attr,
796834
&loop_attr_dio.attr,
835+
&loop_attr_nr_blocking_writes.attr,
797836
NULL,
798837
};
799838

@@ -869,6 +908,24 @@ static inline int queue_on_root_worker(struct cgroup_subsys_state *css)
869908
}
870909
#endif
871910

911+
static inline void loop_inc_blocking_writes(struct loop_device *lo,
912+
struct loop_cmd *cmd)
913+
{
914+
lockdep_assert_held(&lo->lo_work_lock);
915+
916+
if (req_op(blk_mq_rq_from_pdu(cmd)) == REQ_OP_WRITE)
917+
lo->lo_nr_blocking_writes += 1;
918+
}
919+
920+
static inline void loop_dec_blocking_writes(struct loop_device *lo,
921+
struct loop_cmd *cmd)
922+
{
923+
lockdep_assert_held(&lo->lo_work_lock);
924+
925+
if (req_op(blk_mq_rq_from_pdu(cmd)) == REQ_OP_WRITE)
926+
lo->lo_nr_blocking_writes -= 1;
927+
}
928+
872929
static void loop_queue_work(struct loop_device *lo, struct loop_cmd *cmd)
873930
{
874931
struct request __maybe_unused *rq = blk_mq_rq_from_pdu(cmd);
@@ -951,6 +1008,8 @@ static void loop_queue_work(struct loop_device *lo, struct loop_cmd *cmd)
9511008
work = &lo->rootcg_work;
9521009
cmd_list = &lo->rootcg_cmd_list;
9531010
}
1011+
if (cmd->use_aio)
1012+
loop_inc_blocking_writes(lo, cmd);
9541013
list_add_tail(&cmd->list_entry, cmd_list);
9551014
queue_work(lo->workqueue, work);
9561015
spin_unlock_irq(&lo->lo_work_lock);
@@ -2052,6 +2111,8 @@ static void loop_process_work(struct loop_worker *worker,
20522111
cond_resched();
20532112

20542113
spin_lock_irq(&lo->lo_work_lock);
2114+
if (cmd->use_aio)
2115+
loop_dec_blocking_writes(lo, cmd);
20552116
}
20562117

20572118
/*

0 commit comments

Comments
 (0)