On Tue, 17 Aug 2021, SelvaKumar S wrote: > Introduce copy_jobs to use copy-offload, if supported by underlying devices > otherwise fall back to existing method. dm-kcopyd is usually used on the dm-linear target. And this patchset doesn't support passing copy requests through the linear target - so this patch doesn't seem useful. Mikulas > run_copy_jobs() calls block layer copy offload API, if both source and > destination request queue are same and support copy offload. > On successful completion, destination regions copied count is made zero, > failed regions are processed via existing method. > > Signed-off-by: SelvaKumar S <selvakuma.s1@xxxxxxxxxxx> > Signed-off-by: Nitesh Shetty <nj.shetty@xxxxxxxxxxx> > --- > drivers/md/dm-kcopyd.c | 56 +++++++++++++++++++++++++++++++++++++----- > 1 file changed, 50 insertions(+), 6 deletions(-) > > diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c > index 37b03ab7e5c9..d9ee105a6127 100644 > --- a/drivers/md/dm-kcopyd.c > +++ b/drivers/md/dm-kcopyd.c > @@ -74,18 +74,20 @@ struct dm_kcopyd_client { > atomic_t nr_jobs; > > /* > - * We maintain four lists of jobs: > + * We maintain five lists of jobs: > * > - * i) jobs waiting for pages > - * ii) jobs that have pages, and are waiting for the io to be issued. > - * iii) jobs that don't need to do any IO and just run a callback > - * iv) jobs that have completed. > + * i) jobs waiting to try copy offload > + * ii) jobs waiting for pages > + * iii) jobs that have pages, and are waiting for the io to be issued. > + * iv) jobs that don't need to do any IO and just run a callback > + * v) jobs that have completed. > * > - * All four of these are protected by job_lock. > + * All five of these are protected by job_lock. > */ > spinlock_t job_lock; > struct list_head callback_jobs; > struct list_head complete_jobs; > + struct list_head copy_jobs; > struct list_head io_jobs; > struct list_head pages_jobs; > }; > @@ -579,6 +581,43 @@ static int run_io_job(struct kcopyd_job *job) > return r; > } > > +static int run_copy_job(struct kcopyd_job *job) > +{ > + int r, i, count = 0; > + unsigned long flags = 0; > + struct range_entry srange; > + > + struct request_queue *src_q, *dest_q; > + > + for (i = 0; i < job->num_dests; i++) { > + srange.src = job->source.sector; > + srange.len = job->source.count; > + > + src_q = bdev_get_queue(job->source.bdev); > + dest_q = bdev_get_queue(job->dests[i].bdev); > + > + if (src_q != dest_q && !src_q->limits.copy_offload) > + break; > + > + r = blkdev_issue_copy(job->source.bdev, 1, &srange, > + job->dests[i].bdev, job->dests[i].sector, GFP_KERNEL, flags); > + if (r) > + break; > + > + job->dests[i].count = 0; > + count++; > + } > + > + if (count == job->num_dests) { > + push(&job->kc->complete_jobs, job); > + } else { > + push(&job->kc->pages_jobs, job); > + r = 0; > + } > + > + return r; > +} > + > static int run_pages_job(struct kcopyd_job *job) > { > int r; > @@ -659,6 +698,7 @@ static void do_work(struct work_struct *work) > spin_unlock_irq(&kc->job_lock); > > blk_start_plug(&plug); > + process_jobs(&kc->copy_jobs, kc, run_copy_job); > process_jobs(&kc->complete_jobs, kc, run_complete_job); > process_jobs(&kc->pages_jobs, kc, run_pages_job); > process_jobs(&kc->io_jobs, kc, run_io_job); > @@ -676,6 +716,8 @@ static void dispatch_job(struct kcopyd_job *job) > atomic_inc(&kc->nr_jobs); > if (unlikely(!job->source.count)) > push(&kc->callback_jobs, job); > + else if (job->source.bdev->bd_disk == job->dests[0].bdev->bd_disk) > + push(&kc->copy_jobs, job); > else if (job->pages == &zero_page_list) > push(&kc->io_jobs, job); > else > @@ -916,6 +958,7 @@ struct dm_kcopyd_client *dm_kcopyd_client_create(struct dm_kcopyd_throttle *thro > spin_lock_init(&kc->job_lock); > INIT_LIST_HEAD(&kc->callback_jobs); > INIT_LIST_HEAD(&kc->complete_jobs); > + INIT_LIST_HEAD(&kc->copy_jobs); > INIT_LIST_HEAD(&kc->io_jobs); > INIT_LIST_HEAD(&kc->pages_jobs); > kc->throttle = throttle; > @@ -971,6 +1014,7 @@ void dm_kcopyd_client_destroy(struct dm_kcopyd_client *kc) > > BUG_ON(!list_empty(&kc->callback_jobs)); > BUG_ON(!list_empty(&kc->complete_jobs)); > + WARN_ON(!list_empty(&kc->copy_jobs)); > BUG_ON(!list_empty(&kc->io_jobs)); > BUG_ON(!list_empty(&kc->pages_jobs)); > destroy_workqueue(kc->kcopyd_wq); > -- > 2.25.1 > > > -- > dm-devel mailing list > dm-devel@xxxxxxxxxx > https://listman.redhat.com/mailman/listinfo/dm-devel >