From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964934AbbDPL56 (ORCPT ); Thu, 16 Apr 2015 07:57:58 -0400 Received: from mail-pd0-f171.google.com ([209.85.192.171]:33541 "EHLO mail-pd0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754881AbbDPL4D (ORCPT ); Thu, 16 Apr 2015 07:56:03 -0400 From: Sergey Senozhatsky To: Andrew Morton , Minchan Kim Cc: Nitin Gupta , linux-kernel@vger.kernel.org, Sergey Senozhatsky , Sergey Senozhatsky Subject: [PATCHv2 04/10] zram: factor out device reset from reset_store() Date: Thu, 16 Apr 2015 20:55:50 +0900 Message-Id: <1429185356-11096-5-git-send-email-sergey.senozhatsky@gmail.com> X-Mailer: git-send-email 2.4.0.rc2 In-Reply-To: <1429185356-11096-1-git-send-email-sergey.senozhatsky@gmail.com> References: <1429185356-11096-1-git-send-email-sergey.senozhatsky@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Device reset currently includes two steps: a) holding ->bd_mutex we ensure that there are no device users (bdev->bd_openers) b) and "internal" part (executed under bdev->bd_mutex and partially under zram->init_lock) that resets the device - frees allocated memory and returns the device back to its initial state. Up until now it worked just fine. But there will be yet another device reset user soon -- on-demand device removal. We currently can reuse (b), but step (a) is done in sysfs ATTR reset_store() handler, which makes it hard to use it in on-demand device reset path. Rename step (b) from zram_reset_device() to zram_reset_device_internal() and factor out step (a) to zram_reset_device(). Signed-off-by: Sergey Senozhatsky --- drivers/block/zram/zram_drv.c | 135 +++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 68 deletions(-) diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 4511830..14ec8f2 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -750,48 +750,6 @@ static void zram_bio_discard(struct zram *zram, u32 index, } } -static void zram_reset_device(struct zram *zram) -{ - struct zram_meta *meta; - struct zcomp *comp; - u64 disksize; - - down_write(&zram->init_lock); - - zram->limit_pages = 0; - - if (!init_done(zram)) { - up_write(&zram->init_lock); - return; - } - - meta = zram->meta; - comp = zram->comp; - disksize = zram->disksize; - /* - * Refcount will go down to 0 eventually and r/w handler - * cannot handle further I/O so it will bail out by - * check zram_meta_get. - */ - zram_meta_put(zram); - /* - * We want to free zram_meta in process context to avoid - * deadlock between reclaim path and any other locks. - */ - wait_event(zram->io_done, atomic_read(&zram->refcount) == 0); - - /* Reset stats */ - memset(&zram->stats, 0, sizeof(zram->stats)); - zram->disksize = 0; - zram->max_comp_streams = 1; - set_capacity(zram->disk, 0); - - up_write(&zram->init_lock); - /* I/O operation under all of CPU are done so let's free */ - zram_meta_free(meta, disksize); - zcomp_destroy(comp); -} - static ssize_t disksize_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -850,16 +808,54 @@ out_free_meta: return err; } -static ssize_t reset_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +/* internal device reset part -- cleanup allocated memory and + * return back to initial state */ +static void zram_reset_device_internal(struct zram *zram) { - int ret; - unsigned short do_reset; - struct zram *zram; - struct block_device *bdev; + struct zram_meta *meta; + struct zcomp *comp; + u64 disksize; - zram = dev_to_zram(dev); - bdev = bdget_disk(zram->disk, 0); + down_write(&zram->init_lock); + + zram->limit_pages = 0; + + if (!init_done(zram)) { + up_write(&zram->init_lock); + return; + } + + meta = zram->meta; + comp = zram->comp; + disksize = zram->disksize; + /* + * Refcount will go down to 0 eventually and r/w handler + * cannot handle further I/O so it will bail out by + * check zram_meta_get. + */ + zram_meta_put(zram); + /* + * We want to free zram_meta in process context to avoid + * deadlock between reclaim path and any other locks. + */ + wait_event(zram->io_done, atomic_read(&zram->refcount) == 0); + + /* Reset stats */ + memset(&zram->stats, 0, sizeof(zram->stats)); + zram->disksize = 0; + zram->max_comp_streams = 1; + set_capacity(zram->disk, 0); + + up_write(&zram->init_lock); + /* I/O operation under all of CPU are done so let's free */ + zram_meta_free(meta, disksize); + zcomp_destroy(comp); +} + +static int zram_reset_device(struct zram *zram) +{ + int ret = 0; + struct block_device *bdev = bdget_disk(zram->disk, 0); if (!bdev) return -ENOMEM; @@ -871,31 +867,34 @@ static ssize_t reset_store(struct device *dev, goto out; } - ret = kstrtou16(buf, 10, &do_reset); - if (ret) - goto out; - - if (!do_reset) { - ret = -EINVAL; - goto out; - } - /* Make sure all pending I/O is finished */ fsync_bdev(bdev); - zram_reset_device(zram); - - mutex_unlock(&bdev->bd_mutex); - revalidate_disk(zram->disk); - bdput(bdev); - - return len; - + zram_reset_device_internal(zram); out: mutex_unlock(&bdev->bd_mutex); bdput(bdev); return ret; } +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + int ret; + unsigned short do_reset; + struct zram *zram; + + zram = dev_to_zram(dev); + ret = kstrtou16(buf, 10, &do_reset); + if (ret) + return ret; + + if (!do_reset) + return -EINVAL; + + ret = zram_reset_device(zram); + return ret ? ret : len; +} + static void __zram_make_request(struct zram *zram, struct bio *bio) { int offset, rw; @@ -1264,7 +1263,7 @@ static void zram_remove(struct zram *zram) sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, &zram_disk_attr_group); - zram_reset_device(zram); + zram_reset_device_internal(zram); idr_remove(&zram_index_idr, zram->disk->first_minor); blk_cleanup_queue(zram->disk->queue); del_gendisk(zram->disk); -- 2.4.0.rc2