drivers/zram: Don't disable preemption in zcomp_stream_get/put()
In v4.7, the driver switched to percpu compression streams, disabling preemption via get/put_cpu_ptr(). Use a per-zcomp_strm lock here. We also have to fix an lock order issue in zram_decompress_page() such that zs_map_object() nests inside of zcomp_stream_put() as it does in zram_bvec_write(). Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com> [bigeasy: get_locked_var() -> per zcomp_strm lock] Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
This commit is contained in:
parent
c6cc729f9a
commit
bc7cc87312
|
@ -113,12 +113,20 @@ ssize_t zcomp_available_show(const char *comp, char *buf)
|
|||
|
||||
struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
|
||||
{
|
||||
return *get_cpu_ptr(comp->stream);
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
zstrm = *get_local_ptr(comp->stream);
|
||||
spin_lock(&zstrm->zcomp_lock);
|
||||
return zstrm;
|
||||
}
|
||||
|
||||
void zcomp_stream_put(struct zcomp *comp)
|
||||
{
|
||||
put_cpu_ptr(comp->stream);
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
zstrm = *this_cpu_ptr(comp->stream);
|
||||
spin_unlock(&zstrm->zcomp_lock);
|
||||
put_local_ptr(zstrm);
|
||||
}
|
||||
|
||||
int zcomp_compress(struct zcomp_strm *zstrm,
|
||||
|
@ -168,6 +176,7 @@ int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
|
|||
pr_err("Can't allocate a compression stream\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
spin_lock_init(&zstrm->zcomp_lock);
|
||||
*per_cpu_ptr(comp->stream, cpu) = zstrm;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ struct zcomp_strm {
|
|||
/* compression/decompression buffer */
|
||||
void *buffer;
|
||||
struct crypto_comp *tfm;
|
||||
spinlock_t zcomp_lock;
|
||||
};
|
||||
|
||||
/* dynamic per-device compression frontend */
|
||||
|
|
|
@ -1257,6 +1257,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
|||
unsigned long handle;
|
||||
unsigned int size;
|
||||
void *src, *dst;
|
||||
struct zcomp_strm *zstrm;
|
||||
|
||||
zram_slot_lock(zram, index);
|
||||
if (zram_test_flag(zram, index, ZRAM_WB)) {
|
||||
|
@ -1287,6 +1288,7 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
|||
|
||||
size = zram_get_obj_size(zram, index);
|
||||
|
||||
zstrm = zcomp_stream_get(zram->comp);
|
||||
src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
|
||||
if (size == PAGE_SIZE) {
|
||||
dst = kmap_atomic(page);
|
||||
|
@ -1294,14 +1296,13 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
|
|||
kunmap_atomic(dst);
|
||||
ret = 0;
|
||||
} else {
|
||||
struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp);
|
||||
|
||||
dst = kmap_atomic(page);
|
||||
ret = zcomp_decompress(zstrm, src, size, dst);
|
||||
kunmap_atomic(dst);
|
||||
zcomp_stream_put(zram->comp);
|
||||
}
|
||||
zs_unmap_object(zram->mem_pool, handle);
|
||||
zcomp_stream_put(zram->comp);
|
||||
zram_slot_unlock(zram, index);
|
||||
|
||||
/* Should NEVER happen. Return bio error if it does. */
|
||||
|
|
Loading…
Reference in New Issue