diff options
author | Seth Jennings <sjenning@linux.vnet.ibm.com> | 2011-08-10 13:56:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-23 17:52:20 -0400 |
commit | c5f5c4db393837ebb2ae47bf061d70e498f48f8c (patch) | |
tree | e3b8823d57cd884d19ce2c98647ea32bd9b01a9c | |
parent | 20cc7995fe66ce6417678bb0db6b3d4955fb1ff6 (diff) |
staging: zcache: fix crash on high memory swap
zcache_put_page() was modified to pass page_address(page) instead of the
actual page structure. In combination with the function signature changes
to tmem_put() and zcache_pampd_create(), zcache_pampd_create() tries to
(re)derive the page structure from the virtual address. However, if the
original page is a high memory page (or any unmapped page), this
virt_to_page() fails because the page_address() in zcache_put_page()
returned NULL.
This patch changes zcache_put_page() and zcache_get_page() to pass
the page structure instead of the page's virtual address, which
may or may not exist.
Signed-off-by: Seth Jennings <sjenning@linux.vnet.ibm.com>
Acked-by: Dan Magenheimer <dan.magenheimer@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/zcache/zcache-main.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 855a5bb56a47..a3f5162bfedc 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c | |||
@@ -1158,7 +1158,7 @@ static void *zcache_pampd_create(char *data, size_t size, bool raw, int eph, | |||
1158 | size_t clen; | 1158 | size_t clen; |
1159 | int ret; | 1159 | int ret; |
1160 | unsigned long count; | 1160 | unsigned long count; |
1161 | struct page *page = virt_to_page(data); | 1161 | struct page *page = (struct page *)(data); |
1162 | struct zcache_client *cli = pool->client; | 1162 | struct zcache_client *cli = pool->client; |
1163 | uint16_t client_id = get_client_id_from_client(cli); | 1163 | uint16_t client_id = get_client_id_from_client(cli); |
1164 | unsigned long zv_mean_zsize; | 1164 | unsigned long zv_mean_zsize; |
@@ -1227,7 +1227,7 @@ static int zcache_pampd_get_data(char *data, size_t *bufsize, bool raw, | |||
1227 | int ret = 0; | 1227 | int ret = 0; |
1228 | 1228 | ||
1229 | BUG_ON(is_ephemeral(pool)); | 1229 | BUG_ON(is_ephemeral(pool)); |
1230 | zv_decompress(virt_to_page(data), pampd); | 1230 | zv_decompress((struct page *)(data), pampd); |
1231 | return ret; | 1231 | return ret; |
1232 | } | 1232 | } |
1233 | 1233 | ||
@@ -1539,7 +1539,7 @@ static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp, | |||
1539 | goto out; | 1539 | goto out; |
1540 | if (!zcache_freeze && zcache_do_preload(pool) == 0) { | 1540 | if (!zcache_freeze && zcache_do_preload(pool) == 0) { |
1541 | /* preload does preempt_disable on success */ | 1541 | /* preload does preempt_disable on success */ |
1542 | ret = tmem_put(pool, oidp, index, page_address(page), | 1542 | ret = tmem_put(pool, oidp, index, (char *)(page), |
1543 | PAGE_SIZE, 0, is_ephemeral(pool)); | 1543 | PAGE_SIZE, 0, is_ephemeral(pool)); |
1544 | if (ret < 0) { | 1544 | if (ret < 0) { |
1545 | if (is_ephemeral(pool)) | 1545 | if (is_ephemeral(pool)) |
@@ -1572,7 +1572,7 @@ static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp, | |||
1572 | pool = zcache_get_pool_by_id(cli_id, pool_id); | 1572 | pool = zcache_get_pool_by_id(cli_id, pool_id); |
1573 | if (likely(pool != NULL)) { | 1573 | if (likely(pool != NULL)) { |
1574 | if (atomic_read(&pool->obj_count) > 0) | 1574 | if (atomic_read(&pool->obj_count) > 0) |
1575 | ret = tmem_get(pool, oidp, index, page_address(page), | 1575 | ret = tmem_get(pool, oidp, index, (char *)(page), |
1576 | &size, 0, is_ephemeral(pool)); | 1576 | &size, 0, is_ephemeral(pool)); |
1577 | zcache_put_pool(pool); | 1577 | zcache_put_pool(pool); |
1578 | } | 1578 | } |