All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chao Yu <yuchao0@huawei.com>
To: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: <linux-f2fs-devel@lists.sourceforge.net>,
	<linux-kernel@vger.kernel.org>, <chao@kernel.org>
Subject: Re: [PATCH v2] f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS
Date: Fri, 28 Feb 2020 16:20:09 +0800	[thread overview]
Message-ID: <8cb4552e-e6a2-e57b-1baa-40171e53e120@huawei.com> (raw)
In-Reply-To: <20200227183052.GA55284@google.com>

On 2020/2/28 2:30, Jaegeuk Kim wrote:
> On 02/27, Chao Yu wrote:
>> 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.
> 
> Hmm, once we release the blocks, what happens if we remove the immutable
> bit back?

Oh, if we allow to overwrite on compress file, i_blocks and real physical blocks
usage may be inconsistent?

So if we need to support above scenario, should we add another ioctl interface
to rollback all compress inode status:
- add reserved blocks in dnode blocks
- increase i_compr_blocks, i_blocks, total_valid_block_count
- remove immutable

Thanks,

> 
>>
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>> v2:
>> - set inode as immutable in ioctl.
>>  fs/f2fs/f2fs.h |   6 +++
>>  fs/f2fs/file.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++-
>>  2 files changed, 141 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index 23b93a116c73..4a02edc2454b 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
>> @@ -3956,6 +3958,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 37c1147eb244..b8f01ee9d698 100644
>> --- a/fs/f2fs/file.c
>> +++ b/fs/f2fs/file.c
>> @@ -550,6 +550,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);
>> @@ -588,7 +589,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)
>> @@ -3403,6 +3406,134 @@ 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);
>> +
>> +	if (!IS_IMMUTABLE(inode)) {
>> +		F2FS_I(inode)->i_flags |= F2FS_IMMUTABLE_FL;
>> +		f2fs_set_inode_flags(inode);
>> +		inode->i_ctime = current_time(inode);
>> +		f2fs_mark_inode_dirty_sync(inode, true);
>> +	}
>> +
>> +	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)))))
>> @@ -3483,6 +3614,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;
>>  	}
>> @@ -3643,6 +3776,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
> .
> 

WARNING: multiple messages have this Message-ID (diff)
From: Chao Yu <yuchao0@huawei.com>
To: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net
Subject: Re: [f2fs-dev] [PATCH v2] f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS
Date: Fri, 28 Feb 2020 16:20:09 +0800	[thread overview]
Message-ID: <8cb4552e-e6a2-e57b-1baa-40171e53e120@huawei.com> (raw)
In-Reply-To: <20200227183052.GA55284@google.com>

On 2020/2/28 2:30, Jaegeuk Kim wrote:
> On 02/27, Chao Yu wrote:
>> 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.
> 
> Hmm, once we release the blocks, what happens if we remove the immutable
> bit back?

Oh, if we allow to overwrite on compress file, i_blocks and real physical blocks
usage may be inconsistent?

So if we need to support above scenario, should we add another ioctl interface
to rollback all compress inode status:
- add reserved blocks in dnode blocks
- increase i_compr_blocks, i_blocks, total_valid_block_count
- remove immutable

Thanks,

> 
>>
>> Signed-off-by: Chao Yu <yuchao0@huawei.com>
>> ---
>> v2:
>> - set inode as immutable in ioctl.
>>  fs/f2fs/f2fs.h |   6 +++
>>  fs/f2fs/file.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++-
>>  2 files changed, 141 insertions(+), 1 deletion(-)
>>
>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>> index 23b93a116c73..4a02edc2454b 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
>> @@ -3956,6 +3958,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 37c1147eb244..b8f01ee9d698 100644
>> --- a/fs/f2fs/file.c
>> +++ b/fs/f2fs/file.c
>> @@ -550,6 +550,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);
>> @@ -588,7 +589,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)
>> @@ -3403,6 +3406,134 @@ 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);
>> +
>> +	if (!IS_IMMUTABLE(inode)) {
>> +		F2FS_I(inode)->i_flags |= F2FS_IMMUTABLE_FL;
>> +		f2fs_set_inode_flags(inode);
>> +		inode->i_ctime = current_time(inode);
>> +		f2fs_mark_inode_dirty_sync(inode, true);
>> +	}
>> +
>> +	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)))))
>> @@ -3483,6 +3614,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;
>>  	}
>> @@ -3643,6 +3776,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
> .
> 


_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

  reply	other threads:[~2020-02-28  8:20 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-27 11:26 [PATCH v2] f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS Chao Yu
2020-02-27 11:26 ` [f2fs-dev] " Chao Yu
2020-02-27 18:30 ` Jaegeuk Kim
2020-02-27 18:30   ` [f2fs-dev] " Jaegeuk Kim
2020-02-28  8:20   ` Chao Yu [this message]
2020-02-28  8:20     ` Chao Yu
2020-03-04 18:26     ` Jaegeuk Kim
2020-03-04 18:26       ` [f2fs-dev] " Jaegeuk Kim
2020-03-05  0:29       ` Jaegeuk Kim
2020-03-05  0:29         ` [f2fs-dev] " Jaegeuk Kim
2020-03-05  6:34         ` Chao Yu
2020-03-05  6:34           ` [f2fs-dev] " Chao Yu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8cb4552e-e6a2-e57b-1baa-40171e53e120@huawei.com \
    --to=yuchao0@huawei.com \
    --cc=chao@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.