Skip to content

Commit 08eee69

Browse files
minchanktorvalds
authored andcommitted
zram: remove init_lock in zram_make_request
Admin could reset zram during I/O operation going on so we have used zram->init_lock as read-side lock in I/O path to prevent sudden zram meta freeing. However, the init_lock is really troublesome. We can't do call zram_meta_alloc under init_lock due to lockdep splat because zram_rw_page is one of the function under reclaim path and hold it as read_lock while other places in process context hold it as write_lock. So, we have used allocation out of the lock to avoid lockdep warn but it's not good for readability and fainally, I met another lockdep splat between init_lock and cpu_hotplug from kmem_cache_destroy during working zsmalloc compaction. :( Yes, the ideal is to remove horrible init_lock of zram in rw path. This patch removes it in rw path and instead, add atomic refcount for meta lifetime management and completion to free meta in process context. It's important to free meta in process context because some of resource destruction needs mutex lock, which could be held if we releases the resource in reclaim context so it's deadlock, again. As a bonus, we could remove init_done check in rw path because zram_meta_get will do a role for it, instead. Signed-off-by: Sergey Senozhatsky <[email protected]> Signed-off-by: Minchan Kim <[email protected]> Cc: Nitin Gupta <[email protected]> Cc: Jerome Marchand <[email protected]> Cc: Ganesh Mahendran <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 2b269ce commit 08eee69

File tree

2 files changed

+64
-32
lines changed

2 files changed

+64
-32
lines changed

drivers/block/zram/zram_drv.c

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ static ssize_t name##_show(struct device *d, \
5353
} \
5454
static DEVICE_ATTR_RO(name);
5555

56-
static inline int init_done(struct zram *zram)
56+
static inline bool init_done(struct zram *zram)
5757
{
58-
return zram->meta != NULL;
58+
return zram->disksize;
5959
}
6060

6161
static inline struct zram *dev_to_zram(struct device *dev)
@@ -356,6 +356,18 @@ static struct zram_meta *zram_meta_alloc(u64 disksize)
356356
return NULL;
357357
}
358358

359+
static inline bool zram_meta_get(struct zram *zram)
360+
{
361+
if (atomic_inc_not_zero(&zram->refcount))
362+
return true;
363+
return false;
364+
}
365+
366+
static inline void zram_meta_put(struct zram *zram)
367+
{
368+
atomic_dec(&zram->refcount);
369+
}
370+
359371
static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
360372
{
361373
if (*offset + bvec->bv_len >= PAGE_SIZE)
@@ -717,6 +729,10 @@ static void zram_bio_discard(struct zram *zram, u32 index,
717729

718730
static void zram_reset_device(struct zram *zram)
719731
{
732+
struct zram_meta *meta;
733+
struct zcomp *comp;
734+
u64 disksize;
735+
720736
down_write(&zram->init_lock);
721737

722738
zram->limit_pages = 0;
@@ -726,16 +742,31 @@ static void zram_reset_device(struct zram *zram)
726742
return;
727743
}
728744

729-
zcomp_destroy(zram->comp);
730-
zram->max_comp_streams = 1;
731-
zram_meta_free(zram->meta, zram->disksize);
732-
zram->meta = NULL;
745+
meta = zram->meta;
746+
comp = zram->comp;
747+
disksize = zram->disksize;
748+
/*
749+
* Refcount will go down to 0 eventually and r/w handler
750+
* cannot handle further I/O so it will bail out by
751+
* check zram_meta_get.
752+
*/
753+
zram_meta_put(zram);
754+
/*
755+
* We want to free zram_meta in process context to avoid
756+
* deadlock between reclaim path and any other locks.
757+
*/
758+
wait_event(zram->io_done, atomic_read(&zram->refcount) == 0);
759+
733760
/* Reset stats */
734761
memset(&zram->stats, 0, sizeof(zram->stats));
735762
zram->disksize = 0;
763+
zram->max_comp_streams = 1;
736764
set_capacity(zram->disk, 0);
737765

738766
up_write(&zram->init_lock);
767+
/* I/O operation under all of CPU are done so let's free */
768+
zram_meta_free(meta, disksize);
769+
zcomp_destroy(comp);
739770
}
740771

741772
static ssize_t disksize_store(struct device *dev,
@@ -771,6 +802,8 @@ static ssize_t disksize_store(struct device *dev,
771802
goto out_destroy_comp;
772803
}
773804

805+
init_waitqueue_head(&zram->io_done);
806+
atomic_set(&zram->refcount, 1);
774807
zram->meta = meta;
775808
zram->comp = comp;
776809
zram->disksize = disksize;
@@ -901,23 +934,21 @@ static void zram_make_request(struct request_queue *queue, struct bio *bio)
901934
{
902935
struct zram *zram = queue->queuedata;
903936

904-
down_read(&zram->init_lock);
905-
if (unlikely(!init_done(zram)))
937+
if (unlikely(!zram_meta_get(zram)))
906938
goto error;
907939

908940
if (!valid_io_request(zram, bio->bi_iter.bi_sector,
909941
bio->bi_iter.bi_size)) {
910942
atomic64_inc(&zram->stats.invalid_io);
911-
goto error;
943+
goto put_zram;
912944
}
913945

914946
__zram_make_request(zram, bio);
915-
up_read(&zram->init_lock);
916-
947+
zram_meta_put(zram);
917948
return;
918-
949+
put_zram:
950+
zram_meta_put(zram);
919951
error:
920-
up_read(&zram->init_lock);
921952
bio_io_error(bio);
922953
}
923954

@@ -939,21 +970,19 @@ static void zram_slot_free_notify(struct block_device *bdev,
939970
static int zram_rw_page(struct block_device *bdev, sector_t sector,
940971
struct page *page, int rw)
941972
{
942-
int offset, err;
973+
int offset, err = -EIO;
943974
u32 index;
944975
struct zram *zram;
945976
struct bio_vec bv;
946977

947978
zram = bdev->bd_disk->private_data;
979+
if (unlikely(!zram_meta_get(zram)))
980+
goto out;
981+
948982
if (!valid_io_request(zram, sector, PAGE_SIZE)) {
949983
atomic64_inc(&zram->stats.invalid_io);
950-
return -EINVAL;
951-
}
952-
953-
down_read(&zram->init_lock);
954-
if (unlikely(!init_done(zram))) {
955-
err = -EIO;
956-
goto out_unlock;
984+
err = -EINVAL;
985+
goto put_zram;
957986
}
958987

959988
index = sector >> SECTORS_PER_PAGE_SHIFT;
@@ -964,8 +993,9 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
964993
bv.bv_offset = 0;
965994

966995
err = zram_bvec_rw(zram, &bv, index, offset, rw);
967-
out_unlock:
968-
up_read(&zram->init_lock);
996+
put_zram:
997+
zram_meta_put(zram);
998+
out:
969999
/*
9701000
* If I/O fails, just return error(ie, non-zero) without
9711001
* calling page_endio.

drivers/block/zram/zram_drv.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,26 @@ struct zram_meta {
100100

101101
struct zram {
102102
struct zram_meta *meta;
103+
struct zcomp *comp;
103104
struct request_queue *queue;
104105
struct gendisk *disk;
105-
struct zcomp *comp;
106-
107-
/* Prevent concurrent execution of device init, reset and R/W request */
106+
/* Prevent concurrent execution of device init */
108107
struct rw_semaphore init_lock;
109108
/*
110-
* This is the limit on amount of *uncompressed* worth of data
111-
* we can store in a disk.
109+
* the number of pages zram can consume for storing compressed data
112110
*/
113-
u64 disksize; /* bytes */
111+
unsigned long limit_pages;
114112
int max_comp_streams;
113+
115114
struct zram_stats stats;
115+
atomic_t refcount; /* refcount for zram_meta */
116+
/* wait all IO under all of cpu are done */
117+
wait_queue_head_t io_done;
116118
/*
117-
* the number of pages zram can consume for storing compressed data
119+
* This is the limit on amount of *uncompressed* worth of data
120+
* we can store in a disk.
118121
*/
119-
unsigned long limit_pages;
120-
122+
u64 disksize; /* bytes */
121123
char compressor[10];
122124
};
123125
#endif

0 commit comments

Comments
 (0)