From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx1.redhat.com ([209.132.183.28]:52736 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752655AbdIRPxK (ORCPT ); Mon, 18 Sep 2017 11:53:10 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9DD1F2F9468 for ; Mon, 18 Sep 2017 15:53:10 +0000 (UTC) From: Lukas Czerner To: linux-fsdevel@vger.kernel.org Cc: Lukas Czerner Subject: [PATCH 7/7] loop: Check for puch hole and zero range support specifically Date: Mon, 18 Sep 2017 17:52:27 +0200 Message-Id: <1505749947-26360-8-git-send-email-lczerner@redhat.com> In-Reply-To: <1505749947-26360-1-git-send-email-lczerner@redhat.com> References: <1505749947-26360-1-git-send-email-lczerner@redhat.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: Currently, when deciding whether the dirver can support discard, or write_zeroes we only check whether filesystem registered fallocate callback. However this is not really enough because file system does not necessarily need to support punch hole. With previous addition of query support to fallocate, we can query whether the file system support punch hole and zero range and set it up accordingly. Also, distinguish between discard, write_zeroes and write_zeroes with nounmap. Signed-off-by: Lukas Czerner --- drivers/block/loop.c | 61 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 85de673..cefabf4 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -414,7 +414,7 @@ static int lo_read_transfer(struct loop_device *lo, struct request *rq, return ret; } -static int lo_discard(struct loop_device *lo, struct request *rq, loff_t pos) +static int lo_falloc(struct loop_device *lo, struct request *rq, loff_t pos) { /* * We use punch hole to reclaim the free space used by the @@ -423,14 +423,28 @@ static int lo_discard(struct loop_device *lo, struct request *rq, loff_t pos) * useful information. */ struct file *file = lo->lo_backing_file; - int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; - int ret; + int mode, ret; if ((!file->f_op->fallocate) || lo->lo_encrypt_key_size) { ret = -EOPNOTSUPP; goto out; } + switch (req_op(rq)) { + case REQ_OP_WRITE_ZEROES: + if (rq->cmd_flags & REQ_NOUNMAP) + mode = FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE; + else + mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; + break; + case REQ_OP_DISCARD: + mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; + break; + default: + ret = -EOPNOTSUPP; + goto out; + } + ret = file->f_op->fallocate(file, mode, pos, blk_rq_bytes(rq)); if (unlikely(ret && ret != -EINVAL && ret != -EOPNOTSUPP)) ret = -EIO; @@ -567,7 +581,7 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) return lo_req_flush(lo, rq); case REQ_OP_DISCARD: case REQ_OP_WRITE_ZEROES: - return lo_discard(lo, rq, pos); + return lo_falloc(lo, rq, pos); case REQ_OP_WRITE: if (lo->transfer) return lo_write_transfer(lo, rq, pos); @@ -794,11 +808,18 @@ static void loop_sysfs_exit(struct loop_device *lo) &loop_attribute_group); } -static void loop_config_discard(struct loop_device *lo) +static void loop_config_falloc(struct loop_device *lo) { struct file *file = lo->lo_backing_file; struct inode *inode = file->f_mapping->host; struct request_queue *q = lo->lo_queue; + int mode, ret; + + q->limits.discard_granularity = 0; + q->limits.discard_alignment = 0; + blk_queue_max_discard_sectors(q, 0); + blk_queue_max_write_zeroes_sectors(q, 0); + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); /* * We use punch hole to reclaim the free space used by the @@ -807,21 +828,25 @@ static void loop_config_discard(struct loop_device *lo) * useful information. */ if ((!file->f_op->fallocate) || - lo->lo_encrypt_key_size) { - q->limits.discard_granularity = 0; - q->limits.discard_alignment = 0; - blk_queue_max_discard_sectors(q, 0); - blk_queue_max_write_zeroes_sectors(q, 0); - queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q); + lo->lo_encrypt_key_size) return; - } - q->limits.discard_granularity = inode->i_sb->s_blocksize; - q->limits.discard_alignment = 0; + /* + * Now find out whether the backing file supports punch hole + * or at least zero range operations. + */ + mode = FALLOC_FL_QUERY_SUPPORT; + ret = file->f_op->fallocate(file, mode, 0, 0); + if (ret & FALLOC_FL_ZERO_RANGE) + blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9); + if (ret & FALLOC_FL_PUNCH_HOLE) { + q->limits.discard_granularity = inode->i_sb->s_blocksize; + q->limits.discard_alignment = 0; - blk_queue_max_discard_sectors(q, UINT_MAX >> 9); - blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9); - queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); + blk_queue_max_discard_sectors(q, UINT_MAX >> 9); + blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9); + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); + } } static void loop_unprepare_queue(struct loop_device *lo) @@ -1118,7 +1143,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) } } - loop_config_discard(lo); + loop_config_falloc(lo); memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE); memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE); -- 2.7.5