Skip to content

Commit 8e654f8

Browse files
minchanktorvalds
authored andcommitted
zram: read page from backing device
This patch enables read IO from backing device. For the feature, it implements two IO read functions to transfer data from backing storage. One is asynchronous IO function and other is synchronous one. A reason I need synchrnous IO is due to partial write which need to complete read IO before the overwriting partial data. We can make the partial IO's case asynchronous, too but at the moment, I don't feel adding more complexity to support such rare use cases so want to go with simple. [[email protected]: read_from_bdev_async(): return 1 to avoid call page_endio() in zram_rw_page()] Link: http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Minchan Kim <[email protected]> Signed-off-by: Yisheng Xie <[email protected]> Cc: Juneho Choi <[email protected]> Cc: Sergey Senozhatsky <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent db8ffbd commit 8e654f8

File tree

1 file changed

+118
-5
lines changed

1 file changed

+118
-5
lines changed

drivers/block/zram/zram_drv.c

Lines changed: 118 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,95 @@ void zram_page_end_io(struct bio *bio)
454454
bio_put(bio);
455455
}
456456

457+
/*
458+
* Returns 1 if the submission is successful.
459+
*/
460+
static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec,
461+
unsigned long entry, struct bio *parent)
462+
{
463+
struct bio *bio;
464+
465+
bio = bio_alloc(GFP_ATOMIC, 1);
466+
if (!bio)
467+
return -ENOMEM;
468+
469+
bio->bi_iter.bi_sector = entry * (PAGE_SIZE >> 9);
470+
bio->bi_bdev = zram->bdev;
471+
if (!bio_add_page(bio, bvec->bv_page, bvec->bv_len, bvec->bv_offset)) {
472+
bio_put(bio);
473+
return -EIO;
474+
}
475+
476+
if (!parent) {
477+
bio->bi_opf = REQ_OP_READ;
478+
bio->bi_end_io = zram_page_end_io;
479+
} else {
480+
bio->bi_opf = parent->bi_opf;
481+
bio_chain(bio, parent);
482+
}
483+
484+
submit_bio(bio);
485+
return 1;
486+
}
487+
488+
struct zram_work {
489+
struct work_struct work;
490+
struct zram *zram;
491+
unsigned long entry;
492+
struct bio *bio;
493+
};
494+
495+
#if PAGE_SIZE != 4096
496+
static void zram_sync_read(struct work_struct *work)
497+
{
498+
struct bio_vec bvec;
499+
struct zram_work *zw = container_of(work, struct zram_work, work);
500+
struct zram *zram = zw->zram;
501+
unsigned long entry = zw->entry;
502+
struct bio *bio = zw->bio;
503+
504+
read_from_bdev_async(zram, &bvec, entry, bio);
505+
}
506+
507+
/*
508+
* Block layer want one ->make_request_fn to be active at a time
509+
* so if we use chained IO with parent IO in same context,
510+
* it's a deadlock. To avoid, it, it uses worker thread context.
511+
*/
512+
static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec,
513+
unsigned long entry, struct bio *bio)
514+
{
515+
struct zram_work work;
516+
517+
work.zram = zram;
518+
work.entry = entry;
519+
work.bio = bio;
520+
521+
INIT_WORK_ONSTACK(&work.work, zram_sync_read);
522+
queue_work(system_unbound_wq, &work.work);
523+
flush_work(&work.work);
524+
destroy_work_on_stack(&work.work);
525+
526+
return 1;
527+
}
528+
#else
529+
static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec,
530+
unsigned long entry, struct bio *bio)
531+
{
532+
WARN_ON(1);
533+
return -EIO;
534+
}
535+
#endif
536+
537+
static int read_from_bdev(struct zram *zram, struct bio_vec *bvec,
538+
unsigned long entry, struct bio *parent, bool sync)
539+
{
540+
if (sync)
541+
return read_from_bdev_sync(zram, bvec, entry, parent);
542+
else
543+
return read_from_bdev_async(zram, bvec, entry, parent);
544+
}
545+
457546
static int write_to_bdev(struct zram *zram, struct bio_vec *bvec,
458547
u32 index, struct bio *parent,
459548
unsigned long *pentry)
@@ -514,6 +603,12 @@ static int write_to_bdev(struct zram *zram, struct bio_vec *bvec,
514603
{
515604
return -EIO;
516605
}
606+
607+
static int read_from_bdev(struct zram *zram, struct bio_vec *bvec,
608+
unsigned long entry, struct bio *parent, bool sync)
609+
{
610+
return -EIO;
611+
}
517612
static void zram_wb_clear(struct zram *zram, u32 index) {}
518613
#endif
519614

@@ -773,13 +868,31 @@ static void zram_free_page(struct zram *zram, size_t index)
773868
zram_set_obj_size(zram, index, 0);
774869
}
775870

776-
static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index)
871+
static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
872+
struct bio *bio, bool partial_io)
777873
{
778874
int ret;
779875
unsigned long handle;
780876
unsigned int size;
781877
void *src, *dst;
782878

879+
if (zram_wb_enabled(zram)) {
880+
zram_slot_lock(zram, index);
881+
if (zram_test_flag(zram, index, ZRAM_WB)) {
882+
struct bio_vec bvec;
883+
884+
zram_slot_unlock(zram, index);
885+
886+
bvec.bv_page = page;
887+
bvec.bv_len = PAGE_SIZE;
888+
bvec.bv_offset = 0;
889+
return read_from_bdev(zram, &bvec,
890+
zram_get_element(zram, index),
891+
bio, partial_io);
892+
}
893+
zram_slot_unlock(zram, index);
894+
}
895+
783896
if (zram_same_page_read(zram, index, page, 0, PAGE_SIZE))
784897
return 0;
785898

@@ -812,7 +925,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index)
812925
}
813926

814927
static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
815-
u32 index, int offset)
928+
u32 index, int offset, struct bio *bio)
816929
{
817930
int ret;
818931
struct page *page;
@@ -825,7 +938,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
825938
return -ENOMEM;
826939
}
827940

828-
ret = __zram_bvec_read(zram, page, index);
941+
ret = __zram_bvec_read(zram, page, index, bio, is_partial_io(bvec));
829942
if (unlikely(ret))
830943
goto out;
831944

@@ -988,7 +1101,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
9881101
if (!page)
9891102
return -ENOMEM;
9901103

991-
ret = __zram_bvec_read(zram, page, index);
1104+
ret = __zram_bvec_read(zram, page, index, bio, true);
9921105
if (ret)
9931106
goto out;
9941107

@@ -1065,7 +1178,7 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
10651178

10661179
if (!is_write) {
10671180
atomic64_inc(&zram->stats.num_reads);
1068-
ret = zram_bvec_read(zram, bvec, index, offset);
1181+
ret = zram_bvec_read(zram, bvec, index, offset, bio);
10691182
flush_dcache_page(bvec->bv_page);
10701183
} else {
10711184
atomic64_inc(&zram->stats.num_writes);

0 commit comments

Comments
 (0)