Skip to content

Commit 98cc093

Browse files
yhuang-inteltorvalds
authored andcommitted
block, THP: make block_device_operations.rw_page support THP
The .rw_page in struct block_device_operations is used by the swap subsystem to read/write the page contents from/into the corresponding swap slot in the swap device. To support the THP (Transparent Huge Page) swap optimization, the .rw_page is enhanced to support to read/write THP if possible. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: "Huang, Ying" <[email protected]> Reviewed-by: Ross Zwisler <[email protected]> [for brd.c, zram_drv.c, pmem.c] Cc: Johannes Weiner <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Dan Williams <[email protected]> Cc: Vishal L Verma <[email protected]> Cc: Jens Axboe <[email protected]> Cc: "Kirill A . Shutemov" <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Shaohua Li <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f0eea18 commit 98cc093

File tree

4 files changed

+40
-13
lines changed

4 files changed

+40
-13
lines changed

drivers/block/brd.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,11 @@ static int brd_rw_page(struct block_device *bdev, sector_t sector,
326326
struct page *page, bool is_write)
327327
{
328328
struct brd_device *brd = bdev->bd_disk->private_data;
329-
int err = brd_do_bvec(brd, page, PAGE_SIZE, 0, is_write, sector);
329+
int err;
330+
331+
if (PageTransHuge(page))
332+
return -ENOTSUPP;
333+
err = brd_do_bvec(brd, page, PAGE_SIZE, 0, is_write, sector);
330334
page_endio(page, is_write, err);
331335
return err;
332336
}

drivers/block/zram/zram_drv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,8 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
12851285
struct zram *zram;
12861286
struct bio_vec bv;
12871287

1288+
if (PageTransHuge(page))
1289+
return -ENOTSUPP;
12881290
zram = bdev->bd_disk->private_data;
12891291

12901292
if (!valid_io_request(zram, sector, PAGE_SIZE)) {

drivers/nvdimm/btt.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1241,8 +1241,10 @@ static int btt_rw_page(struct block_device *bdev, sector_t sector,
12411241
{
12421242
struct btt *btt = bdev->bd_disk->private_data;
12431243
int rc;
1244+
unsigned int len;
12441245

1245-
rc = btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, is_write, sector);
1246+
len = hpage_nr_pages(page) * PAGE_SIZE;
1247+
rc = btt_do_bvec(btt, NULL, page, len, 0, is_write, sector);
12461248
if (rc == 0)
12471249
page_endio(page, is_write, 0);
12481250

drivers/nvdimm/pmem.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,22 +80,40 @@ static blk_status_t pmem_clear_poison(struct pmem_device *pmem,
8080
static void write_pmem(void *pmem_addr, struct page *page,
8181
unsigned int off, unsigned int len)
8282
{
83-
void *mem = kmap_atomic(page);
84-
85-
memcpy_flushcache(pmem_addr, mem + off, len);
86-
kunmap_atomic(mem);
83+
unsigned int chunk;
84+
void *mem;
85+
86+
while (len) {
87+
mem = kmap_atomic(page);
88+
chunk = min_t(unsigned int, len, PAGE_SIZE);
89+
memcpy_flushcache(pmem_addr, mem + off, chunk);
90+
kunmap_atomic(mem);
91+
len -= chunk;
92+
off = 0;
93+
page++;
94+
pmem_addr += PAGE_SIZE;
95+
}
8796
}
8897

8998
static blk_status_t read_pmem(struct page *page, unsigned int off,
9099
void *pmem_addr, unsigned int len)
91100
{
101+
unsigned int chunk;
92102
int rc;
93-
void *mem = kmap_atomic(page);
94-
95-
rc = memcpy_mcsafe(mem + off, pmem_addr, len);
96-
kunmap_atomic(mem);
97-
if (rc)
98-
return BLK_STS_IOERR;
103+
void *mem;
104+
105+
while (len) {
106+
mem = kmap_atomic(page);
107+
chunk = min_t(unsigned int, len, PAGE_SIZE);
108+
rc = memcpy_mcsafe(mem + off, pmem_addr, chunk);
109+
kunmap_atomic(mem);
110+
if (rc)
111+
return BLK_STS_IOERR;
112+
len -= chunk;
113+
off = 0;
114+
page++;
115+
pmem_addr += PAGE_SIZE;
116+
}
99117
return BLK_STS_OK;
100118
}
101119

@@ -188,7 +206,8 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,
188206
struct pmem_device *pmem = bdev->bd_queue->queuedata;
189207
blk_status_t rc;
190208

191-
rc = pmem_do_bvec(pmem, page, PAGE_SIZE, 0, is_write, sector);
209+
rc = pmem_do_bvec(pmem, page, hpage_nr_pages(page) * PAGE_SIZE,
210+
0, is_write, sector);
192211

193212
/*
194213
* The ->rw_page interface is subtle and tricky. The core

0 commit comments

Comments
 (0)