Skip to content

Commit db8ffbd

Browse files
minchanktorvalds
authored andcommitted
zram: write incompressible pages to backing device
This patch enables write IO to transfer data to backing device. For that, it implements write_to_bdev function which creates new bio and chaining with parent bio to make the parent bio asynchrnous. For rw_page which don't have parent bio, it submit owned bio and handle IO completion by zram_page_end_io. Also, this patch defines new flag ZRAM_WB to mark written page for later read IO. [[email protected]: fix typo in comment] 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 ae85a80 commit db8ffbd

File tree

2 files changed

+103
-13
lines changed

2 files changed

+103
-13
lines changed

drivers/block/zram/zram_drv.c

Lines changed: 101 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -445,9 +445,76 @@ static void put_entry_bdev(struct zram *zram, unsigned long entry)
445445
WARN_ON_ONCE(!was_set);
446446
}
447447

448+
void zram_page_end_io(struct bio *bio)
449+
{
450+
struct page *page = bio->bi_io_vec[0].bv_page;
451+
452+
page_endio(page, op_is_write(bio_op(bio)),
453+
blk_status_to_errno(bio->bi_status));
454+
bio_put(bio);
455+
}
456+
457+
static int write_to_bdev(struct zram *zram, struct bio_vec *bvec,
458+
u32 index, struct bio *parent,
459+
unsigned long *pentry)
460+
{
461+
struct bio *bio;
462+
unsigned long entry;
463+
464+
bio = bio_alloc(GFP_ATOMIC, 1);
465+
if (!bio)
466+
return -ENOMEM;
467+
468+
entry = get_entry_bdev(zram);
469+
if (!entry) {
470+
bio_put(bio);
471+
return -ENOSPC;
472+
}
473+
474+
bio->bi_iter.bi_sector = entry * (PAGE_SIZE >> 9);
475+
bio->bi_bdev = zram->bdev;
476+
if (!bio_add_page(bio, bvec->bv_page, bvec->bv_len,
477+
bvec->bv_offset)) {
478+
bio_put(bio);
479+
put_entry_bdev(zram, entry);
480+
return -EIO;
481+
}
482+
483+
if (!parent) {
484+
bio->bi_opf = REQ_OP_WRITE | REQ_SYNC;
485+
bio->bi_end_io = zram_page_end_io;
486+
} else {
487+
bio->bi_opf = parent->bi_opf;
488+
bio_chain(bio, parent);
489+
}
490+
491+
submit_bio(bio);
492+
*pentry = entry;
493+
494+
return 0;
495+
}
496+
497+
static void zram_wb_clear(struct zram *zram, u32 index)
498+
{
499+
unsigned long entry;
500+
501+
zram_clear_flag(zram, index, ZRAM_WB);
502+
entry = zram_get_element(zram, index);
503+
zram_set_element(zram, index, 0);
504+
put_entry_bdev(zram, entry);
505+
}
506+
448507
#else
449508
static bool zram_wb_enabled(struct zram *zram) { return false; }
450509
static inline void reset_bdev(struct zram *zram) {};
510+
static int write_to_bdev(struct zram *zram, struct bio_vec *bvec,
511+
u32 index, struct bio *parent,
512+
unsigned long *pentry)
513+
514+
{
515+
return -EIO;
516+
}
517+
static void zram_wb_clear(struct zram *zram, u32 index) {}
451518
#endif
452519

453520

@@ -672,7 +739,13 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
672739
*/
673740
static void zram_free_page(struct zram *zram, size_t index)
674741
{
675-
unsigned long handle = zram_get_handle(zram, index);
742+
unsigned long handle;
743+
744+
if (zram_wb_enabled(zram) && zram_test_flag(zram, index, ZRAM_WB)) {
745+
zram_wb_clear(zram, index);
746+
atomic64_dec(&zram->stats.pages_stored);
747+
return;
748+
}
676749

677750
/*
678751
* No memory is allocated for same element filled pages.
@@ -686,6 +759,7 @@ static void zram_free_page(struct zram *zram, size_t index)
686759
return;
687760
}
688761

762+
handle = zram_get_handle(zram, index);
689763
if (!handle)
690764
return;
691765

@@ -770,7 +844,8 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
770844
return ret;
771845
}
772846

773-
static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
847+
static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
848+
u32 index, struct bio *bio)
774849
{
775850
int ret = 0;
776851
unsigned long alloced_pages;
@@ -781,6 +856,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
781856
struct page *page = bvec->bv_page;
782857
unsigned long element = 0;
783858
enum zram_pageflags flags = 0;
859+
bool allow_wb = true;
784860

785861
mem = kmap_atomic(page);
786862
if (page_same_filled(mem, &element)) {
@@ -805,8 +881,20 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
805881
return ret;
806882
}
807883

808-
if (unlikely(comp_len > max_zpage_size))
884+
if (unlikely(comp_len > max_zpage_size)) {
885+
if (zram_wb_enabled(zram) && allow_wb) {
886+
zcomp_stream_put(zram->comp);
887+
ret = write_to_bdev(zram, bvec, index, bio, &element);
888+
if (!ret) {
889+
flags = ZRAM_WB;
890+
ret = 1;
891+
goto out;
892+
}
893+
allow_wb = false;
894+
goto compress_again;
895+
}
809896
comp_len = PAGE_SIZE;
897+
}
810898

811899
/*
812900
* handle allocation has 2 paths:
@@ -866,10 +954,11 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
866954
*/
867955
zram_slot_lock(zram, index);
868956
zram_free_page(zram, index);
869-
if (flags == ZRAM_SAME) {
870-
zram_set_flag(zram, index, ZRAM_SAME);
957+
958+
if (flags) {
959+
zram_set_flag(zram, index, flags);
871960
zram_set_element(zram, index, element);
872-
} else {
961+
} else {
873962
zram_set_handle(zram, index, handle);
874963
zram_set_obj_size(zram, index, comp_len);
875964
}
@@ -881,7 +970,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index)
881970
}
882971

883972
static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
884-
u32 index, int offset)
973+
u32 index, int offset, struct bio *bio)
885974
{
886975
int ret;
887976
struct page *page = NULL;
@@ -914,7 +1003,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
9141003
vec.bv_offset = 0;
9151004
}
9161005

917-
ret = __zram_bvec_write(zram, &vec, index);
1006+
ret = __zram_bvec_write(zram, &vec, index, bio);
9181007
out:
9191008
if (is_partial_io(bvec))
9201009
__free_page(page);
@@ -965,7 +1054,7 @@ static void zram_bio_discard(struct zram *zram, u32 index,
9651054
* Returns 1 if IO request was successfully submitted.
9661055
*/
9671056
static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
968-
int offset, bool is_write)
1057+
int offset, bool is_write, struct bio *bio)
9691058
{
9701059
unsigned long start_time = jiffies;
9711060
int rw_acct = is_write ? REQ_OP_WRITE : REQ_OP_READ;
@@ -980,7 +1069,7 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
9801069
flush_dcache_page(bvec->bv_page);
9811070
} else {
9821071
atomic64_inc(&zram->stats.num_writes);
983-
ret = zram_bvec_write(zram, bvec, index, offset);
1072+
ret = zram_bvec_write(zram, bvec, index, offset, bio);
9841073
}
9851074

9861075
generic_end_io_acct(rw_acct, &zram->disk->part0, start_time);
@@ -1024,7 +1113,7 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
10241113
bv.bv_len = min_t(unsigned int, PAGE_SIZE - offset,
10251114
unwritten);
10261115
if (zram_bvec_rw(zram, &bv, index, offset,
1027-
op_is_write(bio_op(bio))) < 0)
1116+
op_is_write(bio_op(bio)), bio) < 0)
10281117
goto out;
10291118

10301119
bv.bv_offset += bv.bv_len;
@@ -1098,7 +1187,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
10981187
bv.bv_len = PAGE_SIZE;
10991188
bv.bv_offset = 0;
11001189

1101-
ret = zram_bvec_rw(zram, &bv, index, offset, is_write);
1190+
ret = zram_bvec_rw(zram, &bv, index, offset, is_write, NULL);
11021191
out:
11031192
/*
11041193
* If I/O fails, just return error(ie, non-zero) without

drivers/block/zram/zram_drv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3;
6060

6161
/* Flags for zram pages (table[page_no].value) */
6262
enum zram_pageflags {
63-
/* Page consists entirely of zeros */
63+
/* Page consists the same element */
6464
ZRAM_SAME = ZRAM_FLAG_SHIFT,
6565
ZRAM_ACCESS, /* page is now accessed */
66+
ZRAM_WB, /* page is stored on backing_device */
6667

6768
__NR_ZRAM_PAGEFLAGS,
6869
};

0 commit comments

Comments
 (0)