Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp1711990ybv; Fri, 21 Feb 2020 02:10:10 -0800 (PST) X-Google-Smtp-Source: APXvYqxPx4NYqrjd82Ei7N6m7mQvnA+piifEY/gkjbDINZWECkYKGm1h5vutVU5yHGQGkjrk1hJA X-Received: by 2002:aca:cd46:: with SMTP id d67mr1336045oig.156.1582279810680; Fri, 21 Feb 2020 02:10:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1582279810; cv=none; d=google.com; s=arc-20160816; b=VnUFU316W3PqAp/cK0dNjLDy+iI7NhnE5aB/WUmf/nZAztcTvZ7JhJoZax3imbg5x3 Sll9b0izl3hbCLBD7lm7fjxGleTvg1RlPwoprKr/5LiNQf58v0eUwA/YvuwAyYmXM61u AreFDu1vqLaHSGxV4UcfZamg5FfLXvMZK5+XXgbNoU2WQuOYDZcjfASIFa8AGk/2QE7W VETG589AltH9JoKWONABZR4B7rj0PSel3UUMWOXhcCIMNedYhdLKC46rGuw3zP2NWcjh I7pQnfrXN0ttx75sAWVHt1O/hxnL5jTIKQKpG1NxkqTdgSc8382t2fcJmAg0tY/VLx/H MyBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=HMbvTyA1PQOVX4pBq4oze5A9U0vovXi5KVkczw54Wko=; b=GUfIA3VSsLUowzzQPIA7AUyrB5AU0rl9mc8Fsv7Bpv1ViNxu1crDVFZNgRxHnuwNfG hGk+VZoHlZdgVo1LrJkXqaI1GDbWBOFZ2+mIPEZLFRrdw/2BMfzyvX6PCjtp2XoMMEri 9OBG7C/uhi9rGWsCR/jdRfEtb6PS2cgHlJE4nPB/zCSZkwgij6RmQtsRWoRP+ViJlxMY iTC87f3bQ9gjR1/572bFoQ81Ihxt4e5v4wgCrwj0rKJyseIJVNmqU511HzwaDxzCvb0W cmMG6A82WG9I95PXSaCPn9saOGQ89bNnx9QTkNQk6NZ1gi26y+AVn2xeT83TZvCkBZ6V +3VQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 25si490442oiz.230.2020.02.21.02.09.58; Fri, 21 Feb 2020 02:10:10 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728566AbgBUKJj (ORCPT + 99 others); Fri, 21 Feb 2020 05:09:39 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:55788 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728080AbgBUKJh (ORCPT ); Fri, 21 Feb 2020 05:09:37 -0500 Received: from DGGEMS403-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 8E09694DC8EB097A15DE; Fri, 21 Feb 2020 18:09:34 +0800 (CST) Received: from szvp000203569.huawei.com (10.120.216.130) by DGGEMS403-HUB.china.huawei.com (10.3.19.203) with Microsoft SMTP Server id 14.3.439.0; Fri, 21 Feb 2020 18:09:25 +0800 From: Chao Yu To: CC: , , , Chao Yu Subject: [RFC PATCH 2/2] f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS Date: Fri, 21 Feb 2020 18:09:22 +0800 Message-ID: <20200221100922.16781-2-yuchao0@huawei.com> X-Mailer: git-send-email 2.18.0.rc1 In-Reply-To: <20200221100922.16781-1-yuchao0@huawei.com> References: <20200221100922.16781-1-yuchao0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.120.216.130] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org There are still reserved blocks on compressed inode, this patch introduce a new ioctl to help release reserved blocks back to filesystem, so that userspace can reuse those freed space. Signed-off-by: Chao Yu --- fs/f2fs/f2fs.h | 6 +++ fs/f2fs/file.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 15199df5d40a..468f807fd917 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -427,6 +427,8 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal, #define F2FS_IOC_PRECACHE_EXTENTS _IO(F2FS_IOCTL_MAGIC, 15) #define F2FS_IOC_RESIZE_FS _IOW(F2FS_IOCTL_MAGIC, 16, __u64) #define F2FS_IOC_GET_COMPRESS_BLOCKS _IOR(F2FS_IOCTL_MAGIC, 17, __u64) +#define F2FS_IOC_RELEASE_COMPRESS_BLOCKS \ + _IOR(F2FS_IOCTL_MAGIC, 18, __u64) #define F2FS_IOC_GET_VOLUME_NAME FS_IOC_GETFSLABEL #define F2FS_IOC_SET_VOLUME_NAME FS_IOC_SETFSLABEL @@ -3957,6 +3959,10 @@ static inline void f2fs_i_compr_blocks_update(struct inode *inode, { int diff = F2FS_I(inode)->i_cluster_size - blocks; + /* don't update i_compr_blocks if saved blocks were released */ + if (!add && !F2FS_I(inode)->i_compr_blocks) + return; + if (add) { F2FS_I(inode)->i_compr_blocks += diff; stat_add_compr_blocks(inode, diff); diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 235708c892af..613f87151d90 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -557,6 +557,7 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count) bool compressed_cluster = false; int cluster_index = 0, valid_blocks = 0; int cluster_size = F2FS_I(dn->inode)->i_cluster_size; + bool released = !F2FS_I(dn->inode)->i_compr_blocks; if (IS_INODE(dn->node_page) && f2fs_has_extra_attr(dn->inode)) base = get_extra_isize(dn->inode); @@ -595,7 +596,9 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count) clear_inode_flag(dn->inode, FI_FIRST_BLOCK_WRITTEN); f2fs_invalidate_blocks(sbi, blkaddr); - nr_free++; + + if (released && blkaddr != COMPRESS_ADDR) + nr_free++; } if (compressed_cluster) @@ -3416,6 +3419,127 @@ static int f2fs_get_compress_blocks(struct file *filp, unsigned long arg) return put_user(blocks, (u64 __user *)arg); } +static int release_compress_blocks(struct dnode_of_data *dn, pgoff_t count) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); + unsigned int released_blocks = 0; + int cluster_size = F2FS_I(dn->inode)->i_cluster_size; + + while (count) { + int compr_blocks = 0; + block_t blkaddr = f2fs_data_blkaddr(dn); + int i; + + if (blkaddr != COMPRESS_ADDR) { + dn->ofs_in_node += cluster_size; + goto next; + } + + for (i = 0; i < cluster_size; i++, dn->ofs_in_node++) { + blkaddr = f2fs_data_blkaddr(dn); + + if (__is_valid_data_blkaddr(blkaddr)) { + compr_blocks++; + if (unlikely(!f2fs_is_valid_blkaddr(sbi, blkaddr, + DATA_GENERIC_ENHANCE))) + return -EFSCORRUPTED; + } + + if (blkaddr != NEW_ADDR) + continue; + + dn->data_blkaddr = NULL_ADDR; + f2fs_set_data_blkaddr(dn); + } + + f2fs_i_compr_blocks_update(dn->inode, compr_blocks, false); + dec_valid_block_count(sbi, dn->inode, + cluster_size - compr_blocks); + + released_blocks += cluster_size - compr_blocks; +next: + count -= cluster_size; + } + + return released_blocks; +} + +static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg) +{ + struct inode *inode = file_inode(filp); + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + pgoff_t page_idx = 0, last_idx; + unsigned int released_blocks = 0; + int ret; + + if (!f2fs_sb_has_compression(F2FS_I_SB(inode))) + return -EOPNOTSUPP; + + if (!f2fs_compressed_file(inode)) + return -EINVAL; + + if (f2fs_readonly(sbi->sb)) + return -EROFS; + + ret = mnt_want_write_file(filp); + if (ret) + return ret; + + if (!F2FS_I(inode)->i_compr_blocks) + goto out; + + f2fs_balance_fs(F2FS_I_SB(inode), true); + + inode_lock(inode); + + down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); + down_write(&F2FS_I(inode)->i_mmap_sem); + + last_idx = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); + + while (page_idx < last_idx) { + struct dnode_of_data dn; + pgoff_t end_offset, count; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + ret = f2fs_get_dnode_of_data(&dn, page_idx, LOOKUP_NODE); + if (ret) { + if (ret == -ENOENT) { + page_idx = f2fs_get_next_page_offset(&dn, + page_idx); + ret = 0; + continue; + } + break; + } + + end_offset = ADDRS_PER_PAGE(dn.node_page, inode); + count = min(end_offset - dn.ofs_in_node, last_idx - page_idx); + + ret = release_compress_blocks(&dn, count); + + f2fs_put_dnode(&dn); + + if (ret < 0) + break; + + page_idx += count; + released_blocks += ret; + } + + up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); + up_write(&F2FS_I(inode)->i_mmap_sem); + + inode_unlock(inode); +out: + mnt_drop_write_file(filp); + + if (!ret) + ret = put_user(released_blocks, (u64 __user *)arg); + + return ret; +} + long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp))))) @@ -3496,6 +3620,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return f2fs_set_volume_name(filp, arg); case F2FS_IOC_GET_COMPRESS_BLOCKS: return f2fs_get_compress_blocks(filp, arg); + case F2FS_IOC_RELEASE_COMPRESS_BLOCKS: + return f2fs_release_compress_blocks(filp, arg); default: return -ENOTTY; } @@ -3654,6 +3780,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case F2FS_IOC_GET_VOLUME_NAME: case F2FS_IOC_SET_VOLUME_NAME: case F2FS_IOC_GET_COMPRESS_BLOCKS: + case F2FS_IOC_RELEASE_COMPRESS_BLOCKS: break; default: return -ENOIOCTLCMD; -- 2.18.0.rc1