linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk
@ 2021-05-21 19:02 Jaegeuk Kim
  2021-05-21 19:02 ` [PATCH 2/2] f2fs: support RO feature Jaegeuk Kim
  2021-05-26  9:08 ` [f2fs-dev] [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk Chao Yu
  0 siblings, 2 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-21 19:02 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel; +Cc: Jaegeuk Kim

If we released compressed blocks having an immutable bit, we can see less
number of compressed block addresses. Let's fix wrong BUG_ON.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/compress.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index d4f7371fb0d8..1189740aa141 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -927,7 +927,8 @@ static int __f2fs_cluster_blocks(struct inode *inode,
 			}
 		}
 
-		f2fs_bug_on(F2FS_I_SB(inode), !compr && ret != cluster_size);
+		f2fs_bug_on(F2FS_I_SB(inode),
+			!compr && ret != cluster_size && !IS_IMMUTABLE(inode));
 	}
 fail:
 	f2fs_put_dnode(&dn);
-- 
2.31.1.818.g46aad6cb9e-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/2] f2fs: support RO feature
  2021-05-21 19:02 [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk Jaegeuk Kim
@ 2021-05-21 19:02 ` Jaegeuk Kim
  2021-05-24 11:53   ` [f2fs-dev] " Chao Yu
                     ` (2 more replies)
  2021-05-26  9:08 ` [f2fs-dev] [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk Chao Yu
  1 sibling, 3 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-21 19:02 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel; +Cc: Jaegeuk Kim

Given RO feature in superblock, we don't need to check provisioning/reserve
spaces and SSA area.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/f2fs.h    |  2 ++
 fs/f2fs/segment.c |  3 +++
 fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
 3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c0bead0df66a..2c6913261586 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -168,6 +168,7 @@ struct f2fs_mount_info {
 #define F2FS_FEATURE_SB_CHKSUM		0x0800
 #define F2FS_FEATURE_CASEFOLD		0x1000
 #define F2FS_FEATURE_COMPRESSION	0x2000
+#define F2FS_FEATURE_RO			0x4000
 
 #define __F2FS_HAS_FEATURE(raw_super, mask)				\
 	((raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
 #define	NR_CURSEG_DATA_TYPE	(3)
 #define NR_CURSEG_NODE_TYPE	(3)
 #define NR_CURSEG_INMEM_TYPE	(2)
+#define NR_CURSEG_RO_TYPE	(2)
 #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
 #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
 
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 8668df7870d0..67cec8f858a2 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
 {
 	int i;
 
+	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
+		return 0;
+
 	/*
 	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
 	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index b29de80ab60e..312bfab54693 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 static void default_options(struct f2fs_sb_info *sbi)
 {
 	/* init some FS parameters */
-	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
+	else
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+
 	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
 	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
 	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
@@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 	err = parse_options(sb, data, true);
 	if (err)
 		goto restore_opts;
+
+	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
+					!(*flags & SB_RDONLY))
+		goto restore_opts;
+
 	checkpoint_changed =
 			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
 
@@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
 	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
 
+	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
+		goto no_reserved;
 	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
 			ovp_segments == 0 || reserved_segments == 0)) {
 		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
 		return 1;
 	}
-
+no_reserved:
 	user_block_count = le64_to_cpu(ckpt->user_block_count);
 	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
 	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
-	if (!user_block_count || user_block_count >=
+	if (!user_block_count || user_block_count >
 			segment_count_main << log_blocks_per_seg) {
 		f2fs_err(sbi, "Wrong user_block_count: %u",
 			 user_block_count);
@@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
+			goto check_data;
+
 		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
 				le32_to_cpu(ckpt->cur_node_segno[j])) {
@@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
+check_data:
 	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
 		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
+			goto skip_cross;
+
 		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
 				le32_to_cpu(ckpt->cur_data_segno[j])) {
@@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
-
+skip_cross:
 	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
 	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
 
@@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
 	if (err)
 		goto free_options;
 
+	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
+					!f2fs_readonly(sbi->sb)) {
+		f2fs_info(sbi, "Allow to mount readonly mode only");
+		err = -EINVAL;
+		goto free_options;
+	}
+
 	sb->s_maxbytes = max_file_blocks(NULL) <<
 				le32_to_cpu(raw_super->log_blocksize);
 	sb->s_max_links = F2FS_LINK_MAX;
-- 
2.31.1.818.g46aad6cb9e-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-21 19:02 ` [PATCH 2/2] f2fs: support RO feature Jaegeuk Kim
@ 2021-05-24 11:53   ` Chao Yu
  2021-05-24 17:07     ` Jaegeuk Kim
  2021-05-26  9:42   ` Chao Yu
  2021-05-26 13:59   ` [PATCH 2/2 v2] " Jaegeuk Kim
  2 siblings, 1 reply; 23+ messages in thread
From: Chao Yu @ 2021-05-24 11:53 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel

On 2021/5/22 3:02, Jaegeuk Kim wrote:
> Given RO feature in superblock, we don't need to check provisioning/reserve
> spaces and SSA area.

Cool, any solution to update files of ro f2fs image if there is such
scenario?

> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> ---
>   fs/f2fs/f2fs.h    |  2 ++
>   fs/f2fs/segment.c |  3 +++
>   fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
>   3 files changed, 36 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index c0bead0df66a..2c6913261586 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>   #define F2FS_FEATURE_SB_CHKSUM		0x0800
>   #define F2FS_FEATURE_CASEFOLD		0x1000
>   #define F2FS_FEATURE_COMPRESSION	0x2000
> +#define F2FS_FEATURE_RO			0x4000
>   
>   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>   #define	NR_CURSEG_DATA_TYPE	(3)
>   #define NR_CURSEG_NODE_TYPE	(3)
>   #define NR_CURSEG_INMEM_TYPE	(2)
> +#define NR_CURSEG_RO_TYPE	(2)
>   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>   
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 8668df7870d0..67cec8f858a2 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>   {
>   	int i;
>   
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))

Why not using F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))?

Ditto for all below __F2FS_HAS_FEATURE().

Thanks,

> +		return 0;
> +
>   	/*
>   	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
>   	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index b29de80ab60e..312bfab54693 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>   static void default_options(struct f2fs_sb_info *sbi)
>   {
>   	/* init some FS parameters */
> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> +	else
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +
>   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>   	err = parse_options(sb, data, true);
>   	if (err)
>   		goto restore_opts;
> +
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> +					!(*flags & SB_RDONLY))
> +		goto restore_opts;
> +
>   	checkpoint_changed =
>   			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
>   
> @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>   
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +		goto no_reserved;
>   	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>   			ovp_segments == 0 || reserved_segments == 0)) {
>   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>   		return 1;
>   	}
> -
> +no_reserved:
>   	user_block_count = le64_to_cpu(ckpt->user_block_count);
>   	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
>   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> -	if (!user_block_count || user_block_count >=
> +	if (!user_block_count || user_block_count >
>   			segment_count_main << log_blocks_per_seg) {
>   		f2fs_err(sbi, "Wrong user_block_count: %u",
>   			 user_block_count);
> @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +			goto check_data;
> +
>   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> +check_data:
>   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +			goto skip_cross;
> +
>   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> -
> +skip_cross:
>   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>   
> @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>   	if (err)
>   		goto free_options;
>   
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> +					!f2fs_readonly(sbi->sb)) {
> +		f2fs_info(sbi, "Allow to mount readonly mode only");
> +		err = -EINVAL;
> +		goto free_options;
> +	}
> +
>   	sb->s_maxbytes = max_file_blocks(NULL) <<
>   				le32_to_cpu(raw_super->log_blocksize);
>   	sb->s_max_links = F2FS_LINK_MAX;
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-24 11:53   ` [f2fs-dev] " Chao Yu
@ 2021-05-24 17:07     ` Jaegeuk Kim
  2021-05-25  1:15       ` Chao Yu
  0 siblings, 1 reply; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-24 17:07 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 05/24, Chao Yu wrote:
> On 2021/5/22 3:02, Jaegeuk Kim wrote:
> > Given RO feature in superblock, we don't need to check provisioning/reserve
> > spaces and SSA area.
> 
> Cool, any solution to update files of ro f2fs image if there is such
> scenario?

Hmm, overlayfs?

> 
> > 
> > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> > ---
> >   fs/f2fs/f2fs.h    |  2 ++
> >   fs/f2fs/segment.c |  3 +++
> >   fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
> >   3 files changed, 36 insertions(+), 4 deletions(-)
> > 
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index c0bead0df66a..2c6913261586 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -168,6 +168,7 @@ struct f2fs_mount_info {
> >   #define F2FS_FEATURE_SB_CHKSUM		0x0800
> >   #define F2FS_FEATURE_CASEFOLD		0x1000
> >   #define F2FS_FEATURE_COMPRESSION	0x2000
> > +#define F2FS_FEATURE_RO			0x4000
> >   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
> >   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> > @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
> >   #define	NR_CURSEG_DATA_TYPE	(3)
> >   #define NR_CURSEG_NODE_TYPE	(3)
> >   #define NR_CURSEG_INMEM_TYPE	(2)
> > +#define NR_CURSEG_RO_TYPE	(2)
> >   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
> >   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
> > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > index 8668df7870d0..67cec8f858a2 100644
> > --- a/fs/f2fs/segment.c
> > +++ b/fs/f2fs/segment.c
> > @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
> >   {
> >   	int i;
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> 
> Why not using F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))?

Oh, updated.

> 
> Ditto for all below __F2FS_HAS_FEATURE().
> 
> Thanks,
> 
> > +		return 0;
> > +
> >   	/*
> >   	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
> >   	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index b29de80ab60e..312bfab54693 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
> >   static void default_options(struct f2fs_sb_info *sbi)
> >   {
> >   	/* init some FS parameters */
> > -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> > +	else
> > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > +
> >   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
> >   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> >   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> > @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
> >   	err = parse_options(sb, data, true);
> >   	if (err)
> >   		goto restore_opts;
> > +
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > +					!(*flags & SB_RDONLY))
> > +		goto restore_opts;
> > +
> >   	checkpoint_changed =
> >   			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
> > @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
> >   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +		goto no_reserved;
> >   	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> >   			ovp_segments == 0 || reserved_segments == 0)) {
> >   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
> >   		return 1;
> >   	}
> > -
> > +no_reserved:
> >   	user_block_count = le64_to_cpu(ckpt->user_block_count);
> >   	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> >   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> > -	if (!user_block_count || user_block_count >=
> > +	if (!user_block_count || user_block_count >
> >   			segment_count_main << log_blocks_per_seg) {
> >   		f2fs_err(sbi, "Wrong user_block_count: %u",
> >   			 user_block_count);
> > @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
> >   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
> >   			return 1;
> > +
> > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +			goto check_data;
> > +
> >   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
> >   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
> >   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> > @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   			}
> >   		}
> >   	}
> > +check_data:
> >   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
> >   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
> >   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
> >   			return 1;
> > +
> > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +			goto skip_cross;
> > +
> >   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
> >   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
> >   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> > @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   			}
> >   		}
> >   	}
> > -
> > +skip_cross:
> >   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
> >   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
> > @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> >   	if (err)
> >   		goto free_options;
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > +					!f2fs_readonly(sbi->sb)) {
> > +		f2fs_info(sbi, "Allow to mount readonly mode only");
> > +		err = -EINVAL;
> > +		goto free_options;
> > +	}
> > +
> >   	sb->s_maxbytes = max_file_blocks(NULL) <<
> >   				le32_to_cpu(raw_super->log_blocksize);
> >   	sb->s_max_links = F2FS_LINK_MAX;
> > 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-24 17:07     ` Jaegeuk Kim
@ 2021-05-25  1:15       ` Chao Yu
  2021-05-25  1:45         ` Jaegeuk Kim
  0 siblings, 1 reply; 23+ messages in thread
From: Chao Yu @ 2021-05-25  1:15 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel

On 2021/5/25 1:07, Jaegeuk Kim wrote:
> On 05/24, Chao Yu wrote:
>> On 2021/5/22 3:02, Jaegeuk Kim wrote:
>>> Given RO feature in superblock, we don't need to check provisioning/reserve
>>> spaces and SSA area.
>>
>> Cool, any solution to update files of ro f2fs image if there is such
>> scenario?
> 
> Hmm, overlayfs?

I mean using f2fs-tools, maybe...

Thanks,

> 
>>
>>>
>>> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
>>> ---
>>>    fs/f2fs/f2fs.h    |  2 ++
>>>    fs/f2fs/segment.c |  3 +++
>>>    fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
>>>    3 files changed, 36 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index c0bead0df66a..2c6913261586 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>>>    #define F2FS_FEATURE_SB_CHKSUM		0x0800
>>>    #define F2FS_FEATURE_CASEFOLD		0x1000
>>>    #define F2FS_FEATURE_COMPRESSION	0x2000
>>> +#define F2FS_FEATURE_RO			0x4000
>>>    #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>>>    	((raw_super->feature & cpu_to_le32(mask)) != 0)
>>> @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>>>    #define	NR_CURSEG_DATA_TYPE	(3)
>>>    #define NR_CURSEG_NODE_TYPE	(3)
>>>    #define NR_CURSEG_INMEM_TYPE	(2)
>>> +#define NR_CURSEG_RO_TYPE	(2)
>>>    #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>>>    #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>> index 8668df7870d0..67cec8f858a2 100644
>>> --- a/fs/f2fs/segment.c
>>> +++ b/fs/f2fs/segment.c
>>> @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>>>    {
>>>    	int i;
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>
>> Why not using F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))?
> 
> Oh, updated.
> 
>>
>> Ditto for all below __F2FS_HAS_FEATURE().
>>
>> Thanks,
>>
>>> +		return 0;
>>> +
>>>    	/*
>>>    	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
>>>    	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
>>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>>> index b29de80ab60e..312bfab54693 100644
>>> --- a/fs/f2fs/super.c
>>> +++ b/fs/f2fs/super.c
>>> @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>>>    static void default_options(struct f2fs_sb_info *sbi)
>>>    {
>>>    	/* init some FS parameters */
>>> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
>>> +	else
>>> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
>>> +
>>>    	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>>>    	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>>>    	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
>>> @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>>>    	err = parse_options(sb, data, true);
>>>    	if (err)
>>>    		goto restore_opts;
>>> +
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
>>> +					!(*flags & SB_RDONLY))
>>> +		goto restore_opts;
>>> +
>>>    	checkpoint_changed =
>>>    			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
>>> @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>>>    	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +		goto no_reserved;
>>>    	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>>>    			ovp_segments == 0 || reserved_segments == 0)) {
>>>    		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>>>    		return 1;
>>>    	}
>>> -
>>> +no_reserved:
>>>    	user_block_count = le64_to_cpu(ckpt->user_block_count);
>>>    	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
>>>    	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
>>> -	if (!user_block_count || user_block_count >=
>>> +	if (!user_block_count || user_block_count >
>>>    			segment_count_main << log_blocks_per_seg) {
>>>    		f2fs_err(sbi, "Wrong user_block_count: %u",
>>>    			 user_block_count);
>>> @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>>>    			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>>>    			return 1;
>>> +
>>> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +			goto check_data;
>>> +
>>>    		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>>>    			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>>>    				le32_to_cpu(ckpt->cur_node_segno[j])) {
>>> @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    			}
>>>    		}
>>>    	}
>>> +check_data:
>>>    	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>>>    		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>>>    			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>>>    			return 1;
>>> +
>>> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +			goto skip_cross;
>>> +
>>>    		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>>>    			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>>>    				le32_to_cpu(ckpt->cur_data_segno[j])) {
>>> @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    			}
>>>    		}
>>>    	}
>>> -
>>> +skip_cross:
>>>    	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>>>    	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>>> @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>>>    	if (err)
>>>    		goto free_options;
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
>>> +					!f2fs_readonly(sbi->sb)) {
>>> +		f2fs_info(sbi, "Allow to mount readonly mode only");
>>> +		err = -EINVAL;
>>> +		goto free_options;
>>> +	}
>>> +
>>>    	sb->s_maxbytes = max_file_blocks(NULL) <<
>>>    				le32_to_cpu(raw_super->log_blocksize);
>>>    	sb->s_max_links = F2FS_LINK_MAX;
>>>
> .
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-25  1:15       ` Chao Yu
@ 2021-05-25  1:45         ` Jaegeuk Kim
  0 siblings, 0 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-25  1:45 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 05/25, Chao Yu wrote:
> On 2021/5/25 1:07, Jaegeuk Kim wrote:
> > On 05/24, Chao Yu wrote:
> > > On 2021/5/22 3:02, Jaegeuk Kim wrote:
> > > > Given RO feature in superblock, we don't need to check provisioning/reserve
> > > > spaces and SSA area.
> > > 
> > > Cool, any solution to update files of ro f2fs image if there is such
> > > scenario?
> > 
> > Hmm, overlayfs?
> 
> I mean using f2fs-tools, maybe...

sload.f2fs supports it with this patch?

https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git/commit/?h=dev&id=9069b6b6f17faa66c8546567882b2e66bc78b8eb

> 
> Thanks,
> 
> > 
> > > 
> > > > 
> > > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> > > > ---
> > > >    fs/f2fs/f2fs.h    |  2 ++
> > > >    fs/f2fs/segment.c |  3 +++
> > > >    fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
> > > >    3 files changed, 36 insertions(+), 4 deletions(-)
> > > > 
> > > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > > > index c0bead0df66a..2c6913261586 100644
> > > > --- a/fs/f2fs/f2fs.h
> > > > +++ b/fs/f2fs/f2fs.h
> > > > @@ -168,6 +168,7 @@ struct f2fs_mount_info {
> > > >    #define F2FS_FEATURE_SB_CHKSUM		0x0800
> > > >    #define F2FS_FEATURE_CASEFOLD		0x1000
> > > >    #define F2FS_FEATURE_COMPRESSION	0x2000
> > > > +#define F2FS_FEATURE_RO			0x4000
> > > >    #define __F2FS_HAS_FEATURE(raw_super, mask)				\
> > > >    	((raw_super->feature & cpu_to_le32(mask)) != 0)
> > > > @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
> > > >    #define	NR_CURSEG_DATA_TYPE	(3)
> > > >    #define NR_CURSEG_NODE_TYPE	(3)
> > > >    #define NR_CURSEG_INMEM_TYPE	(2)
> > > > +#define NR_CURSEG_RO_TYPE	(2)
> > > >    #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
> > > >    #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
> > > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > > > index 8668df7870d0..67cec8f858a2 100644
> > > > --- a/fs/f2fs/segment.c
> > > > +++ b/fs/f2fs/segment.c
> > > > @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
> > > >    {
> > > >    	int i;
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > 
> > > Why not using F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))?
> > 
> > Oh, updated.
> > 
> > > 
> > > Ditto for all below __F2FS_HAS_FEATURE().
> > > 
> > > Thanks,
> > > 
> > > > +		return 0;
> > > > +
> > > >    	/*
> > > >    	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
> > > >    	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
> > > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > > > index b29de80ab60e..312bfab54693 100644
> > > > --- a/fs/f2fs/super.c
> > > > +++ b/fs/f2fs/super.c
> > > > @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
> > > >    static void default_options(struct f2fs_sb_info *sbi)
> > > >    {
> > > >    	/* init some FS parameters */
> > > > -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> > > > +	else
> > > > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > > > +
> > > >    	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
> > > >    	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> > > >    	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> > > > @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
> > > >    	err = parse_options(sb, data, true);
> > > >    	if (err)
> > > >    		goto restore_opts;
> > > > +
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > > > +					!(*flags & SB_RDONLY))
> > > > +		goto restore_opts;
> > > > +
> > > >    	checkpoint_changed =
> > > >    			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
> > > > @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
> > > >    	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +		goto no_reserved;
> > > >    	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> > > >    			ovp_segments == 0 || reserved_segments == 0)) {
> > > >    		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
> > > >    		return 1;
> > > >    	}
> > > > -
> > > > +no_reserved:
> > > >    	user_block_count = le64_to_cpu(ckpt->user_block_count);
> > > >    	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> > > >    	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> > > > -	if (!user_block_count || user_block_count >=
> > > > +	if (!user_block_count || user_block_count >
> > > >    			segment_count_main << log_blocks_per_seg) {
> > > >    		f2fs_err(sbi, "Wrong user_block_count: %u",
> > > >    			 user_block_count);
> > > > @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
> > > >    			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
> > > >    			return 1;
> > > > +
> > > > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +			goto check_data;
> > > > +
> > > >    		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
> > > >    			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
> > > >    				le32_to_cpu(ckpt->cur_node_segno[j])) {
> > > > @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    			}
> > > >    		}
> > > >    	}
> > > > +check_data:
> > > >    	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
> > > >    		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
> > > >    			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
> > > >    			return 1;
> > > > +
> > > > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +			goto skip_cross;
> > > > +
> > > >    		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
> > > >    			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
> > > >    				le32_to_cpu(ckpt->cur_data_segno[j])) {
> > > > @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    			}
> > > >    		}
> > > >    	}
> > > > -
> > > > +skip_cross:
> > > >    	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
> > > >    	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
> > > > @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> > > >    	if (err)
> > > >    		goto free_options;
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > > > +					!f2fs_readonly(sbi->sb)) {
> > > > +		f2fs_info(sbi, "Allow to mount readonly mode only");
> > > > +		err = -EINVAL;
> > > > +		goto free_options;
> > > > +	}
> > > > +
> > > >    	sb->s_maxbytes = max_file_blocks(NULL) <<
> > > >    				le32_to_cpu(raw_super->log_blocksize);
> > > >    	sb->s_max_links = F2FS_LINK_MAX;
> > > > 
> > .
> > 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk
  2021-05-21 19:02 [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk Jaegeuk Kim
  2021-05-21 19:02 ` [PATCH 2/2] f2fs: support RO feature Jaegeuk Kim
@ 2021-05-26  9:08 ` Chao Yu
  2021-05-26 14:02   ` Jaegeuk Kim
  1 sibling, 1 reply; 23+ messages in thread
From: Chao Yu @ 2021-05-26  9:08 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel

On 2021/5/22 3:02, Jaegeuk Kim wrote:
> If we released compressed blocks having an immutable bit, we can see less
> number of compressed block addresses. Let's fix wrong BUG_ON.
> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

It looks it will be better to merge this into
("f2fs: compress: remove unneeded preallocation")?

Reviewed-by: Chao Yu <yuchao0@huawei.com>

Thanks,

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-21 19:02 ` [PATCH 2/2] f2fs: support RO feature Jaegeuk Kim
  2021-05-24 11:53   ` [f2fs-dev] " Chao Yu
@ 2021-05-26  9:42   ` Chao Yu
  2021-05-26 13:58     ` Jaegeuk Kim
  2021-05-26 13:59   ` [PATCH 2/2 v2] " Jaegeuk Kim
  2 siblings, 1 reply; 23+ messages in thread
From: Chao Yu @ 2021-05-26  9:42 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel

On 2021/5/22 3:02, Jaegeuk Kim wrote:
> Given RO feature in superblock, we don't need to check provisioning/reserve
> spaces and SSA area.
> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> ---
>   fs/f2fs/f2fs.h    |  2 ++
>   fs/f2fs/segment.c |  3 +++
>   fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
>   3 files changed, 36 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index c0bead0df66a..2c6913261586 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>   #define F2FS_FEATURE_SB_CHKSUM		0x0800
>   #define F2FS_FEATURE_CASEFOLD		0x1000
>   #define F2FS_FEATURE_COMPRESSION	0x2000
> +#define F2FS_FEATURE_RO			0x4000
>   
>   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>   #define	NR_CURSEG_DATA_TYPE	(3)
>   #define NR_CURSEG_NODE_TYPE	(3)
>   #define NR_CURSEG_INMEM_TYPE	(2)
> +#define NR_CURSEG_RO_TYPE	(2)
>   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>   
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 8668df7870d0..67cec8f858a2 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>   {
>   	int i;
>   
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +		return 0;

We need to skip this sanity check because .next_blkoff may point to end position
of image?

> +
>   	/*
>   	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
>   	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index b29de80ab60e..312bfab54693 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>   static void default_options(struct f2fs_sb_info *sbi)
>   {
>   	/* init some FS parameters */
> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> +	else
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +
>   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>   	err = parse_options(sb, data, true);
>   	if (err)
>   		goto restore_opts;
> +
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> +					!(*flags & SB_RDONLY))

err = -EROFS; ?

> +		goto restore_opts;
> +
>   	checkpoint_changed =
>   			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
>   
> @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>   
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +		goto no_reserved;
>   	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>   			ovp_segments == 0 || reserved_segments == 0)) {
>   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>   		return 1;
>   	}

Well, why not:

if (!F2FS_HAS_FEATURE(, RO) && unlikely()) {
}

> -
> +no_reserved:
>   	user_block_count = le64_to_cpu(ckpt->user_block_count);
>   	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
>   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> -	if (!user_block_count || user_block_count >=
> +	if (!user_block_count || user_block_count >

Does this change related to RO feature? if so, let's split condition for
RO feature here?

>   			segment_count_main << log_blocks_per_seg) {
>   		f2fs_err(sbi, "Wrong user_block_count: %u",
>   			 user_block_count);
> @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +			goto check_data;
> +
>   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> +check_data:
>   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> +			goto skip_cross;
> +
>   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> -
> +skip_cross:
>   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>   
> @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>   	if (err)
>   		goto free_options;
>   
> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> +					!f2fs_readonly(sbi->sb)) {
> +		f2fs_info(sbi, "Allow to mount readonly mode only");
> +		err = -EINVAL;
> +		goto free_options;
> +	}

How about relocating this to parse_options() like other features did, then
we don't need to handle this in both fill_super() and remount()?

Thanks,

> +
>   	sb->s_maxbytes = max_file_blocks(NULL) <<
>   				le32_to_cpu(raw_super->log_blocksize);
>   	sb->s_max_links = F2FS_LINK_MAX;
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-26  9:42   ` Chao Yu
@ 2021-05-26 13:58     ` Jaegeuk Kim
  2021-05-26 15:06       ` Chao Yu
  0 siblings, 1 reply; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-26 13:58 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 05/26, Chao Yu wrote:
> On 2021/5/22 3:02, Jaegeuk Kim wrote:
> > Given RO feature in superblock, we don't need to check provisioning/reserve
> > spaces and SSA area.
> > 
> > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> > ---
> >   fs/f2fs/f2fs.h    |  2 ++
> >   fs/f2fs/segment.c |  3 +++
> >   fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
> >   3 files changed, 36 insertions(+), 4 deletions(-)
> > 
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index c0bead0df66a..2c6913261586 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -168,6 +168,7 @@ struct f2fs_mount_info {
> >   #define F2FS_FEATURE_SB_CHKSUM		0x0800
> >   #define F2FS_FEATURE_CASEFOLD		0x1000
> >   #define F2FS_FEATURE_COMPRESSION	0x2000
> > +#define F2FS_FEATURE_RO			0x4000
> >   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
> >   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> > @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
> >   #define	NR_CURSEG_DATA_TYPE	(3)
> >   #define NR_CURSEG_NODE_TYPE	(3)
> >   #define NR_CURSEG_INMEM_TYPE	(2)
> > +#define NR_CURSEG_RO_TYPE	(2)
> >   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
> >   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
> > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > index 8668df7870d0..67cec8f858a2 100644
> > --- a/fs/f2fs/segment.c
> > +++ b/fs/f2fs/segment.c
> > @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
> >   {
> >   	int i;
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +		return 0;
> 
> We need to skip this sanity check because .next_blkoff may point to end position
> of image?

Since we only use hot data and node. Let me check them only.

> 
> > +
> >   	/*
> >   	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
> >   	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index b29de80ab60e..312bfab54693 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
> >   static void default_options(struct f2fs_sb_info *sbi)
> >   {
> >   	/* init some FS parameters */
> > -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> > +	else
> > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > +
> >   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
> >   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> >   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> > @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
> >   	err = parse_options(sb, data, true);
> >   	if (err)
> >   		goto restore_opts;
> > +
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > +					!(*flags & SB_RDONLY))
> 
> err = -EROFS; ?

Done.

> 
> > +		goto restore_opts;
> > +
> >   	checkpoint_changed =
> >   			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
> > @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
> >   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +		goto no_reserved;
> >   	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> >   			ovp_segments == 0 || reserved_segments == 0)) {
> >   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
> >   		return 1;
> >   	}
> 
> Well, why not:
> 
> if (!F2FS_HAS_FEATURE(, RO) && unlikely()) {
> }

Done.

> 
> > -
> > +no_reserved:
> >   	user_block_count = le64_to_cpu(ckpt->user_block_count);
> >   	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> >   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> > -	if (!user_block_count || user_block_count >=
> > +	if (!user_block_count || user_block_count >
> 
> Does this change related to RO feature? if so, let's split condition for
> RO feature here?

Done.

> 
> >   			segment_count_main << log_blocks_per_seg) {
> >   		f2fs_err(sbi, "Wrong user_block_count: %u",
> >   			 user_block_count);
> > @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
> >   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
> >   			return 1;
> > +
> > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +			goto check_data;
> > +
> >   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
> >   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
> >   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> > @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   			}
> >   		}
> >   	}
> > +check_data:
> >   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
> >   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
> >   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
> >   			return 1;
> > +
> > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > +			goto skip_cross;
> > +
> >   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
> >   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
> >   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> > @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   			}
> >   		}
> >   	}
> > -
> > +skip_cross:
> >   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
> >   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
> > @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> >   	if (err)
> >   		goto free_options;
> > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > +					!f2fs_readonly(sbi->sb)) {
> > +		f2fs_info(sbi, "Allow to mount readonly mode only");
> > +		err = -EINVAL;
> > +		goto free_options;
> > +	}
> 
> How about relocating this to parse_options() like other features did, then
> we don't need to handle this in both fill_super() and remount()?

Done. But not sure what you mean "we don't need to handle both".

Thanks,

> 
> Thanks,
> 
> > +
> >   	sb->s_maxbytes = max_file_blocks(NULL) <<
> >   				le32_to_cpu(raw_super->log_blocksize);
> >   	sb->s_max_links = F2FS_LINK_MAX;
> > 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2 v2] f2fs: support RO feature
  2021-05-21 19:02 ` [PATCH 2/2] f2fs: support RO feature Jaegeuk Kim
  2021-05-24 11:53   ` [f2fs-dev] " Chao Yu
  2021-05-26  9:42   ` Chao Yu
@ 2021-05-26 13:59   ` Jaegeuk Kim
  2021-05-26 14:06     ` [f2fs-dev] " Jaegeuk Kim
  2021-05-26 14:43     ` [f2fs-dev] [PATCH 2/2 v3] " Jaegeuk Kim
  2 siblings, 2 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-26 13:59 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel

Given RO feature in superblock, we don't need to check provisioning/reserve
spaces and SSA area.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
 fs/f2fs/f2fs.h    |  2 ++
 fs/f2fs/segment.c |  4 ++++
 fs/f2fs/super.c   | 35 ++++++++++++++++++++++++++++++-----
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index eaf57b5f3c4b..9ad502f92529 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -168,6 +168,7 @@ struct f2fs_mount_info {
 #define F2FS_FEATURE_SB_CHKSUM		0x0800
 #define F2FS_FEATURE_CASEFOLD		0x1000
 #define F2FS_FEATURE_COMPRESSION	0x2000
+#define F2FS_FEATURE_RO			0x4000
 
 #define __F2FS_HAS_FEATURE(raw_super, mask)				\
 	((raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
 #define	NR_CURSEG_DATA_TYPE	(3)
 #define NR_CURSEG_NODE_TYPE	(3)
 #define NR_CURSEG_INMEM_TYPE	(2)
+#define NR_CURSEG_RO_TYPE	(2)
 #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
 #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
 
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 8668df7870d0..02e0c38be7eb 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
 		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
 		unsigned int blkofs = curseg->next_blkoff;
 
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
+			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
+			continue;
+
 		sanity_check_seg_type(sbi, curseg->seg_type);
 
 		if (f2fs_test_bit(blkofs, se->cur_valid_map))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index e70aca8f97bd..7769ed789b38 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1162,6 +1162,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 	 */
 	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
 		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
+
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
+		f2fs_info(sbi, "Allow to mount readonly mode only");
+		err = -EINVAL;
+		goto free_options;
+	}
 	return 0;
 }
 
@@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 static void default_options(struct f2fs_sb_info *sbi)
 {
 	/* init some FS parameters */
-	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
+	else
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+
 	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
 	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
 	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
@@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
 		goto skip;
 
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
+		err = -EROFS;
+		goto restore_opts;
+	}
+
 #ifdef CONFIG_QUOTA
 	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
 		err = dquot_suspend(sb, -1);
@@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
 	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
 
-	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
+	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
+			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
 			ovp_segments == 0 || reserved_segments == 0)) {
 		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
 		return 1;
 	}
-
 	user_block_count = le64_to_cpu(ckpt->user_block_count);
-	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
+			F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0;
 	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
 	if (!user_block_count || user_block_count >=
 			segment_count_main << log_blocks_per_seg) {
@@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+			goto check_data;
+
 		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
 				le32_to_cpu(ckpt->cur_node_segno[j])) {
@@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
+check_data:
 	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
 		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+			goto skip_cross;
+
 		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
 				le32_to_cpu(ckpt->cur_data_segno[j])) {
@@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
-
+skip_cross:
 	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
 	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
 
-- 
2.32.0.rc0.204.g9fa02ecfa5-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk
  2021-05-26  9:08 ` [f2fs-dev] [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk Chao Yu
@ 2021-05-26 14:02   ` Jaegeuk Kim
  0 siblings, 0 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-26 14:02 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 05/26, Chao Yu wrote:
> On 2021/5/22 3:02, Jaegeuk Kim wrote:
> > If we released compressed blocks having an immutable bit, we can see less
> > number of compressed block addresses. Let's fix wrong BUG_ON.
> > 
> > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> 
> It looks it will be better to merge this into
> ("f2fs: compress: remove unneeded preallocation")?

Right, fixed there. :)

> 
> Reviewed-by: Chao Yu <yuchao0@huawei.com>
> 
> Thanks,

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v2] f2fs: support RO feature
  2021-05-26 13:59   ` [PATCH 2/2 v2] " Jaegeuk Kim
@ 2021-05-26 14:06     ` Jaegeuk Kim
  2021-05-26 14:43     ` [f2fs-dev] [PATCH 2/2 v3] " Jaegeuk Kim
  1 sibling, 0 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-26 14:06 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel

On 05/26, Jaegeuk Kim wrote:
> Given RO feature in superblock, we don't need to check provisioning/reserve
> spaces and SSA area.
> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> ---
>  fs/f2fs/f2fs.h    |  2 ++
>  fs/f2fs/segment.c |  4 ++++
>  fs/f2fs/super.c   | 35 ++++++++++++++++++++++++++++++-----
>  3 files changed, 36 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index eaf57b5f3c4b..9ad502f92529 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>  #define F2FS_FEATURE_SB_CHKSUM		0x0800
>  #define F2FS_FEATURE_CASEFOLD		0x1000
>  #define F2FS_FEATURE_COMPRESSION	0x2000
> +#define F2FS_FEATURE_RO			0x4000
>  
>  #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>  	((raw_super->feature & cpu_to_le32(mask)) != 0)
> @@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>  #define	NR_CURSEG_DATA_TYPE	(3)
>  #define NR_CURSEG_NODE_TYPE	(3)
>  #define NR_CURSEG_INMEM_TYPE	(2)
> +#define NR_CURSEG_RO_TYPE	(2)
>  #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>  #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>  
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 8668df7870d0..02e0c38be7eb 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>  		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
>  		unsigned int blkofs = curseg->next_blkoff;
>  
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
> +			continue;
> +
>  		sanity_check_seg_type(sbi, curseg->seg_type);
>  
>  		if (f2fs_test_bit(blkofs, se->cur_valid_map))
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index e70aca8f97bd..7769ed789b38 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -1162,6 +1162,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>  	 */
>  	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
>  		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> +
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
> +		f2fs_info(sbi, "Allow to mount readonly mode only");
> +		err = -EINVAL;
> +		goto free_options;

Fixed:
       if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
               f2fs_err(sbi, "Allow to mount readonly mode only");
               return EINVAL;
       }

> +	}
>  	return 0;
>  }
>  
> @@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>  static void default_options(struct f2fs_sb_info *sbi)
>  {
>  	/* init some FS parameters */
> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> +	else
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +
>  	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>  	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>  	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> @@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>  	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
>  		goto skip;
>  
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
> +		err = -EROFS;
> +		goto restore_opts;
> +	}
> +
>  #ifdef CONFIG_QUOTA
>  	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
>  		err = dquot_suspend(sb, -1);
> @@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>  	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>  	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>  
> -	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> +	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>  			ovp_segments == 0 || reserved_segments == 0)) {
>  		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>  		return 1;
>  	}
> -
>  	user_block_count = le64_to_cpu(ckpt->user_block_count);
> -	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> +	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
> +			F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0;
>  	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
>  	if (!user_block_count || user_block_count >=
>  			segment_count_main << log_blocks_per_seg) {
> @@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>  		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>  			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>  			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto check_data;
> +
>  		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>  			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>  				le32_to_cpu(ckpt->cur_node_segno[j])) {
> @@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>  			}
>  		}
>  	}
> +check_data:
>  	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>  		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>  			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>  			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto skip_cross;
> +
>  		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>  			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>  				le32_to_cpu(ckpt->cur_data_segno[j])) {
> @@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>  			}
>  		}
>  	}
> -
> +skip_cross:
>  	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>  	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>  
> -- 
> 2.32.0.rc0.204.g9fa02ecfa5-goog
> 
> 
> 
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v3] f2fs: support RO feature
  2021-05-26 13:59   ` [PATCH 2/2 v2] " Jaegeuk Kim
  2021-05-26 14:06     ` [f2fs-dev] " Jaegeuk Kim
@ 2021-05-26 14:43     ` Jaegeuk Kim
  2021-05-27  1:19       ` Chao Yu
                         ` (2 more replies)
  1 sibling, 3 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-26 14:43 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel

Given RO feature in superblock, we don't need to check provisioning/reserve
spaces and SSA area.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
Change log from v2:
 - allow curseg updates
 - fix some bugs

 fs/f2fs/f2fs.h    |  2 ++
 fs/f2fs/segment.c |  4 ++++
 fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
 3 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index eaf57b5f3c4b..9ad502f92529 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -168,6 +168,7 @@ struct f2fs_mount_info {
 #define F2FS_FEATURE_SB_CHKSUM		0x0800
 #define F2FS_FEATURE_CASEFOLD		0x1000
 #define F2FS_FEATURE_COMPRESSION	0x2000
+#define F2FS_FEATURE_RO			0x4000
 
 #define __F2FS_HAS_FEATURE(raw_super, mask)				\
 	((raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
 #define	NR_CURSEG_DATA_TYPE	(3)
 #define NR_CURSEG_NODE_TYPE	(3)
 #define NR_CURSEG_INMEM_TYPE	(2)
+#define NR_CURSEG_RO_TYPE	(2)
 #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
 #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
 
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 8668df7870d0..02e0c38be7eb 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
 		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
 		unsigned int blkofs = curseg->next_blkoff;
 
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
+			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
+			continue;
+
 		sanity_check_seg_type(sbi, curseg->seg_type);
 
 		if (f2fs_test_bit(blkofs, se->cur_valid_map))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index e70aca8f97bd..6788e7b71e27 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 	int ret;
 
 	if (!options)
-		return 0;
+		goto default_check;
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
@@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 			return -EINVAL;
 		}
 	}
+default_check:
 #ifdef CONFIG_QUOTA
 	if (f2fs_check_quota_options(sbi))
 		return -EINVAL;
@@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 	 */
 	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
 		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
+
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
+		f2fs_err(sbi, "Allow to mount readonly mode only");
+		return -EROFS;
+	}
 	return 0;
 }
 
@@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 static void default_options(struct f2fs_sb_info *sbi)
 {
 	/* init some FS parameters */
-	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
+	else
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+
 	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
 	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
 	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
@@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
 		goto skip;
 
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
+		err = -EROFS;
+		goto restore_opts;
+	}
+
 #ifdef CONFIG_QUOTA
 	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
 		err = dquot_suspend(sb, -1);
@@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
 	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
 
-	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
+	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
+			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
 			ovp_segments == 0 || reserved_segments == 0)) {
 		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
 		return 1;
 	}
-
 	user_block_count = le64_to_cpu(ckpt->user_block_count);
-	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
+			(F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0);
 	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
 	if (!user_block_count || user_block_count >=
 			segment_count_main << log_blocks_per_seg) {
@@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+			goto check_data;
+
 		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
 				le32_to_cpu(ckpt->cur_node_segno[j])) {
@@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
+check_data:
 	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
 		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+			goto skip_cross;
+
 		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
 				le32_to_cpu(ckpt->cur_data_segno[j])) {
@@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
-
+skip_cross:
 	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
 	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
 
-- 
2.32.0.rc0.204.g9fa02ecfa5-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-26 13:58     ` Jaegeuk Kim
@ 2021-05-26 15:06       ` Chao Yu
  2021-05-26 15:45         ` Jaegeuk Kim
  0 siblings, 1 reply; 23+ messages in thread
From: Chao Yu @ 2021-05-26 15:06 UTC (permalink / raw)
  To: Jaegeuk Kim, Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 2021/5/26 21:58, Jaegeuk Kim wrote:
> On 05/26, Chao Yu wrote:
>> On 2021/5/22 3:02, Jaegeuk Kim wrote:
>>> Given RO feature in superblock, we don't need to check provisioning/reserve
>>> spaces and SSA area.
>>>
>>> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
>>> ---
>>>    fs/f2fs/f2fs.h    |  2 ++
>>>    fs/f2fs/segment.c |  3 +++
>>>    fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
>>>    3 files changed, 36 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index c0bead0df66a..2c6913261586 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>>>    #define F2FS_FEATURE_SB_CHKSUM		0x0800
>>>    #define F2FS_FEATURE_CASEFOLD		0x1000
>>>    #define F2FS_FEATURE_COMPRESSION	0x2000
>>> +#define F2FS_FEATURE_RO			0x4000
>>>    #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>>>    	((raw_super->feature & cpu_to_le32(mask)) != 0)
>>> @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>>>    #define	NR_CURSEG_DATA_TYPE	(3)
>>>    #define NR_CURSEG_NODE_TYPE	(3)
>>>    #define NR_CURSEG_INMEM_TYPE	(2)
>>> +#define NR_CURSEG_RO_TYPE	(2)
>>>    #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>>>    #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>> index 8668df7870d0..67cec8f858a2 100644
>>> --- a/fs/f2fs/segment.c
>>> +++ b/fs/f2fs/segment.c
>>> @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>>>    {
>>>    	int i;
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +		return 0;
>>
>> We need to skip this sanity check because .next_blkoff may point to end position
>> of image?
> 
> Since we only use hot data and node. Let me check them only.
> 
>>
>>> +
>>>    	/*
>>>    	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
>>>    	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
>>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>>> index b29de80ab60e..312bfab54693 100644
>>> --- a/fs/f2fs/super.c
>>> +++ b/fs/f2fs/super.c
>>> @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>>>    static void default_options(struct f2fs_sb_info *sbi)
>>>    {
>>>    	/* init some FS parameters */
>>> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
>>> +	else
>>> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
>>> +
>>>    	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>>>    	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>>>    	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
>>> @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>>>    	err = parse_options(sb, data, true);
>>>    	if (err)
>>>    		goto restore_opts;
>>> +
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
>>> +					!(*flags & SB_RDONLY))
>>
>> err = -EROFS; ?
> 
> Done.
> 
>>
>>> +		goto restore_opts;
>>> +
>>>    	checkpoint_changed =
>>>    			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
>>> @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>>>    	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +		goto no_reserved;
>>>    	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>>>    			ovp_segments == 0 || reserved_segments == 0)) {
>>>    		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>>>    		return 1;
>>>    	}
>>
>> Well, why not:
>>
>> if (!F2FS_HAS_FEATURE(, RO) && unlikely()) {
>> }
> 
> Done.
> 
>>
>>> -
>>> +no_reserved:
>>>    	user_block_count = le64_to_cpu(ckpt->user_block_count);
>>>    	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
>>>    	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
>>> -	if (!user_block_count || user_block_count >=
>>> +	if (!user_block_count || user_block_count >
>>
>> Does this change related to RO feature? if so, let's split condition for
>> RO feature here?
> 
> Done.
> 
>>
>>>    			segment_count_main << log_blocks_per_seg) {
>>>    		f2fs_err(sbi, "Wrong user_block_count: %u",
>>>    			 user_block_count);
>>> @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>>>    			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>>>    			return 1;
>>> +
>>> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +			goto check_data;
>>> +
>>>    		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>>>    			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>>>    				le32_to_cpu(ckpt->cur_node_segno[j])) {
>>> @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    			}
>>>    		}
>>>    	}
>>> +check_data:
>>>    	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>>>    		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>>>    			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>>>    			return 1;
>>> +
>>> +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
>>> +			goto skip_cross;
>>> +
>>>    		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>>>    			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>>>    				le32_to_cpu(ckpt->cur_data_segno[j])) {
>>> @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    			}
>>>    		}
>>>    	}
>>> -
>>> +skip_cross:
>>>    	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>>>    	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>>> @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
>>>    	if (err)
>>>    		goto free_options;
>>> +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
>>> +					!f2fs_readonly(sbi->sb)) {
>>> +		f2fs_info(sbi, "Allow to mount readonly mode only");
>>> +		err = -EINVAL;
>>> +		goto free_options;
>>> +	}
>>
>> How about relocating this to parse_options() like other features did, then
>> we don't need to handle this in both fill_super() and remount()?
> 
> Done. But not sure what you mean "we don't need to handle both".

Oh, I mean both fill_super() and remount() will call parse_options(),
so if we want to avoid mounting ro image with rw mountoption, we just
need to add one condition check in parse_option().

Thanks,

> 
> Thanks,
> 
>>
>> Thanks,
>>
>>> +
>>>    	sb->s_maxbytes = max_file_blocks(NULL) <<
>>>    				le32_to_cpu(raw_super->log_blocksize);
>>>    	sb->s_max_links = F2FS_LINK_MAX;
>>>
> 
> 
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2] f2fs: support RO feature
  2021-05-26 15:06       ` Chao Yu
@ 2021-05-26 15:45         ` Jaegeuk Kim
  0 siblings, 0 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-26 15:45 UTC (permalink / raw)
  To: Chao Yu; +Cc: Chao Yu, linux-kernel, linux-f2fs-devel

On 05/26, Chao Yu wrote:
> On 2021/5/26 21:58, Jaegeuk Kim wrote:
> > On 05/26, Chao Yu wrote:
> > > On 2021/5/22 3:02, Jaegeuk Kim wrote:
> > > > Given RO feature in superblock, we don't need to check provisioning/reserve
> > > > spaces and SSA area.
> > > > 
> > > > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> > > > ---
> > > >    fs/f2fs/f2fs.h    |  2 ++
> > > >    fs/f2fs/segment.c |  3 +++
> > > >    fs/f2fs/super.c   | 35 +++++++++++++++++++++++++++++++----
> > > >    3 files changed, 36 insertions(+), 4 deletions(-)
> > > > 
> > > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > > > index c0bead0df66a..2c6913261586 100644
> > > > --- a/fs/f2fs/f2fs.h
> > > > +++ b/fs/f2fs/f2fs.h
> > > > @@ -168,6 +168,7 @@ struct f2fs_mount_info {
> > > >    #define F2FS_FEATURE_SB_CHKSUM		0x0800
> > > >    #define F2FS_FEATURE_CASEFOLD		0x1000
> > > >    #define F2FS_FEATURE_COMPRESSION	0x2000
> > > > +#define F2FS_FEATURE_RO			0x4000
> > > >    #define __F2FS_HAS_FEATURE(raw_super, mask)				\
> > > >    	((raw_super->feature & cpu_to_le32(mask)) != 0)
> > > > @@ -939,6 +940,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
> > > >    #define	NR_CURSEG_DATA_TYPE	(3)
> > > >    #define NR_CURSEG_NODE_TYPE	(3)
> > > >    #define NR_CURSEG_INMEM_TYPE	(2)
> > > > +#define NR_CURSEG_RO_TYPE	(2)
> > > >    #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
> > > >    #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
> > > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > > > index 8668df7870d0..67cec8f858a2 100644
> > > > --- a/fs/f2fs/segment.c
> > > > +++ b/fs/f2fs/segment.c
> > > > @@ -4674,6 +4674,9 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
> > > >    {
> > > >    	int i;
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +		return 0;
> > > 
> > > We need to skip this sanity check because .next_blkoff may point to end position
> > > of image?
> > 
> > Since we only use hot data and node. Let me check them only.
> > 
> > > 
> > > > +
> > > >    	/*
> > > >    	 * In LFS/SSR curseg, .next_blkoff should point to an unused blkaddr;
> > > >    	 * In LFS curseg, all blkaddr after .next_blkoff should be unused.
> > > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > > > index b29de80ab60e..312bfab54693 100644
> > > > --- a/fs/f2fs/super.c
> > > > +++ b/fs/f2fs/super.c
> > > > @@ -1819,7 +1819,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
> > > >    static void default_options(struct f2fs_sb_info *sbi)
> > > >    {
> > > >    	/* init some FS parameters */
> > > > -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> > > > +	else
> > > > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > > > +
> > > >    	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
> > > >    	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> > > >    	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> > > > @@ -1994,6 +1998,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
> > > >    	err = parse_options(sb, data, true);
> > > >    	if (err)
> > > >    		goto restore_opts;
> > > > +
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > > > +					!(*flags & SB_RDONLY))
> > > 
> > > err = -EROFS; ?
> > 
> > Done.
> > 
> > > 
> > > > +		goto restore_opts;
> > > > +
> > > >    	checkpoint_changed =
> > > >    			disable_checkpoint != test_opt(sbi, DISABLE_CHECKPOINT);
> > > > @@ -3137,16 +3146,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
> > > >    	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +		goto no_reserved;
> > > >    	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> > > >    			ovp_segments == 0 || reserved_segments == 0)) {
> > > >    		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
> > > >    		return 1;
> > > >    	}
> > > 
> > > Well, why not:
> > > 
> > > if (!F2FS_HAS_FEATURE(, RO) && unlikely()) {
> > > }
> > 
> > Done.
> > 
> > > 
> > > > -
> > > > +no_reserved:
> > > >    	user_block_count = le64_to_cpu(ckpt->user_block_count);
> > > >    	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> > > >    	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> > > > -	if (!user_block_count || user_block_count >=
> > > > +	if (!user_block_count || user_block_count >
> > > 
> > > Does this change related to RO feature? if so, let's split condition for
> > > RO feature here?
> > 
> > Done.
> > 
> > > 
> > > >    			segment_count_main << log_blocks_per_seg) {
> > > >    		f2fs_err(sbi, "Wrong user_block_count: %u",
> > > >    			 user_block_count);
> > > > @@ -3175,6 +3186,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
> > > >    			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
> > > >    			return 1;
> > > > +
> > > > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +			goto check_data;
> > > > +
> > > >    		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
> > > >    			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
> > > >    				le32_to_cpu(ckpt->cur_node_segno[j])) {
> > > > @@ -3185,10 +3200,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    			}
> > > >    		}
> > > >    	}
> > > > +check_data:
> > > >    	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
> > > >    		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
> > > >    			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
> > > >    			return 1;
> > > > +
> > > > +		if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO))
> > > > +			goto skip_cross;
> > > > +
> > > >    		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
> > > >    			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
> > > >    				le32_to_cpu(ckpt->cur_data_segno[j])) {
> > > > @@ -3210,7 +3230,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> > > >    			}
> > > >    		}
> > > >    	}
> > > > -
> > > > +skip_cross:
> > > >    	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
> > > >    	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
> > > > @@ -3703,6 +3723,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
> > > >    	if (err)
> > > >    		goto free_options;
> > > > +	if (__F2FS_HAS_FEATURE(sbi->raw_super, F2FS_FEATURE_RO) &&
> > > > +					!f2fs_readonly(sbi->sb)) {
> > > > +		f2fs_info(sbi, "Allow to mount readonly mode only");
> > > > +		err = -EINVAL;
> > > > +		goto free_options;
> > > > +	}
> > > 
> > > How about relocating this to parse_options() like other features did, then
> > > we don't need to handle this in both fill_super() and remount()?
> > 
> > Done. But not sure what you mean "we don't need to handle both".
> 
> Oh, I mean both fill_super() and remount() will call parse_options(),
> so if we want to avoid mounting ro image with rw mountoption, we just
> need to add one condition check in parse_option().

1. mount forced mounting ro only.
2. remount needs to check rw mount after parse_options.

> 
> Thanks,
> 
> > 
> > Thanks,
> > 
> > > 
> > > Thanks,
> > > 
> > > > +
> > > >    	sb->s_maxbytes = max_file_blocks(NULL) <<
> > > >    				le32_to_cpu(raw_super->log_blocksize);
> > > >    	sb->s_max_links = F2FS_LINK_MAX;
> > > > 
> > 
> > 
> > _______________________________________________
> > Linux-f2fs-devel mailing list
> > Linux-f2fs-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
> > 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v3] f2fs: support RO feature
  2021-05-26 14:43     ` [f2fs-dev] [PATCH 2/2 v3] " Jaegeuk Kim
@ 2021-05-27  1:19       ` Chao Yu
  2021-05-27  1:36         ` Jaegeuk Kim
  2021-06-02 15:16       ` Chao Yu
  2021-06-02 19:02       ` [f2fs-dev] [PATCH 2/2 v4] " Jaegeuk Kim
  2 siblings, 1 reply; 23+ messages in thread
From: Chao Yu @ 2021-05-27  1:19 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel

On 2021/5/26 22:43, Jaegeuk Kim wrote:
> Given RO feature in superblock, we don't need to check provisioning/reserve
> spaces and SSA area.
> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> ---
> Change log from v2:
>   - allow curseg updates
>   - fix some bugs
> 
>   fs/f2fs/f2fs.h    |  2 ++
>   fs/f2fs/segment.c |  4 ++++
>   fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
>   3 files changed, 37 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index eaf57b5f3c4b..9ad502f92529 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>   #define F2FS_FEATURE_SB_CHKSUM		0x0800
>   #define F2FS_FEATURE_CASEFOLD		0x1000
>   #define F2FS_FEATURE_COMPRESSION	0x2000
> +#define F2FS_FEATURE_RO			0x4000
>   
>   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> @@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>   #define	NR_CURSEG_DATA_TYPE	(3)
>   #define NR_CURSEG_NODE_TYPE	(3)
>   #define NR_CURSEG_INMEM_TYPE	(2)
> +#define NR_CURSEG_RO_TYPE	(2)
>   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>   
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 8668df7870d0..02e0c38be7eb 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>   		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
>   		unsigned int blkofs = curseg->next_blkoff;
>   
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
> +			continue;
> +
>   		sanity_check_seg_type(sbi, curseg->seg_type);
>   
>   		if (f2fs_test_bit(blkofs, se->cur_valid_map))
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index e70aca8f97bd..6788e7b71e27 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   	int ret;
>   
>   	if (!options)
> -		return 0;
> +		goto default_check;
>   
>   	while ((p = strsep(&options, ",")) != NULL) {
>   		int token;
> @@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   			return -EINVAL;
>   		}
>   	}
> +default_check:
>   #ifdef CONFIG_QUOTA
>   	if (f2fs_check_quota_options(sbi))
>   		return -EINVAL;
> @@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   	 */
>   	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
>   		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> +
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
> +		f2fs_err(sbi, "Allow to mount readonly mode only");
> +		return -EROFS;
> +	}
>   	return 0;
>   }
>   
> @@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>   static void default_options(struct f2fs_sb_info *sbi)
>   {
>   	/* init some FS parameters */
> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> +	else
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +
>   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> @@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>   	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
>   		goto skip;
>   
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
> +		err = -EROFS;
> +		goto restore_opts;
> +	}

remount() -> parse_options() will fail due to below check, so it doesn't need
to check again? Am I missing something?

@@ -1162,6 +1163,11 @@

  static int parse_options(struct super_block *sb, char *options, bool is_remount)

  	 */
  	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
  		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
+
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
+		f2fs_err(sbi, "Allow to mount readonly mode only");
+		return -EROFS;
+	}
  	return 0;
  }

Thanks,

> +
>   #ifdef CONFIG_QUOTA
>   	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
>   		err = dquot_suspend(sb, -1);
> @@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>   
> -	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> +	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>   			ovp_segments == 0 || reserved_segments == 0)) {
>   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>   		return 1;
>   	}
> -
>   	user_block_count = le64_to_cpu(ckpt->user_block_count);
> -	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> +	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
> +			(F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0);
>   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
>   	if (!user_block_count || user_block_count >=
>   			segment_count_main << log_blocks_per_seg) {
> @@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto check_data;
> +
>   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> @@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> +check_data:
>   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto skip_cross;
> +
>   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> @@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> -
> +skip_cross:
>   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>   
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v3] f2fs: support RO feature
  2021-05-27  1:19       ` Chao Yu
@ 2021-05-27  1:36         ` Jaegeuk Kim
  2021-05-28  2:07           ` Chao Yu
  0 siblings, 1 reply; 23+ messages in thread
From: Jaegeuk Kim @ 2021-05-27  1:36 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-kernel, linux-f2fs-devel

On 05/27, Chao Yu wrote:
> On 2021/5/26 22:43, Jaegeuk Kim wrote:
> > Given RO feature in superblock, we don't need to check provisioning/reserve
> > spaces and SSA area.
> > 
> > Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> > ---
> > Change log from v2:
> >   - allow curseg updates
> >   - fix some bugs
> > 
> >   fs/f2fs/f2fs.h    |  2 ++
> >   fs/f2fs/segment.c |  4 ++++
> >   fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
> >   3 files changed, 37 insertions(+), 6 deletions(-)
> > 
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index eaf57b5f3c4b..9ad502f92529 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -168,6 +168,7 @@ struct f2fs_mount_info {
> >   #define F2FS_FEATURE_SB_CHKSUM		0x0800
> >   #define F2FS_FEATURE_CASEFOLD		0x1000
> >   #define F2FS_FEATURE_COMPRESSION	0x2000
> > +#define F2FS_FEATURE_RO			0x4000
> >   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
> >   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> > @@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
> >   #define	NR_CURSEG_DATA_TYPE	(3)
> >   #define NR_CURSEG_NODE_TYPE	(3)
> >   #define NR_CURSEG_INMEM_TYPE	(2)
> > +#define NR_CURSEG_RO_TYPE	(2)
> >   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
> >   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
> > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > index 8668df7870d0..02e0c38be7eb 100644
> > --- a/fs/f2fs/segment.c
> > +++ b/fs/f2fs/segment.c
> > @@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
> >   		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
> >   		unsigned int blkofs = curseg->next_blkoff;
> > +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> > +			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
> > +			continue;
> > +
> >   		sanity_check_seg_type(sbi, curseg->seg_type);
> >   		if (f2fs_test_bit(blkofs, se->cur_valid_map))
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index e70aca8f97bd..6788e7b71e27 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
> >   	int ret;
> >   	if (!options)
> > -		return 0;
> > +		goto default_check;
> >   	while ((p = strsep(&options, ",")) != NULL) {
> >   		int token;
> > @@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
> >   			return -EINVAL;
> >   		}
> >   	}
> > +default_check:
> >   #ifdef CONFIG_QUOTA
> >   	if (f2fs_check_quota_options(sbi))
> >   		return -EINVAL;
> > @@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
> >   	 */
> >   	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
> >   		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> > +
> > +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
> > +		f2fs_err(sbi, "Allow to mount readonly mode only");
> > +		return -EROFS;
> > +	}
> >   	return 0;
> >   }
> > @@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
> >   static void default_options(struct f2fs_sb_info *sbi)
> >   {
> >   	/* init some FS parameters */
> > -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> > +	else
> > +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> > +
> >   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
> >   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> >   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> > @@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
> >   	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
> >   		goto skip;
> > +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
> > +		err = -EROFS;
> > +		goto restore_opts;
> > +	}
> 
> remount() -> parse_options() will fail due to below check, so it doesn't need
> to check again? Am I missing something?

We haven't changed sb->ro at this point yet.

> 
> @@ -1162,6 +1163,11 @@
> 
>  static int parse_options(struct super_block *sb, char *options, bool is_remount)
> 
>  	 */
>  	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
>  		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> +
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
> +		f2fs_err(sbi, "Allow to mount readonly mode only");
> +		return -EROFS;
> +	}
>  	return 0;
>  }
> 
> Thanks,
> 
> > +
> >   #ifdef CONFIG_QUOTA
> >   	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
> >   		err = dquot_suspend(sb, -1);
> > @@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
> >   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
> > -	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> > +	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> > +			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> >   			ovp_segments == 0 || reserved_segments == 0)) {
> >   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
> >   		return 1;
> >   	}
> > -
> >   	user_block_count = le64_to_cpu(ckpt->user_block_count);
> > -	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> > +	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
> > +			(F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0);
> >   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
> >   	if (!user_block_count || user_block_count >=
> >   			segment_count_main << log_blocks_per_seg) {
> > @@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
> >   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
> >   			return 1;
> > +
> > +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> > +			goto check_data;
> > +
> >   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
> >   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
> >   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> > @@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   			}
> >   		}
> >   	}
> > +check_data:
> >   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
> >   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
> >   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
> >   			return 1;
> > +
> > +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> > +			goto skip_cross;
> > +
> >   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
> >   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
> >   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> > @@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
> >   			}
> >   		}
> >   	}
> > -
> > +skip_cross:
> >   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
> >   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
> > 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v3] f2fs: support RO feature
  2021-05-27  1:36         ` Jaegeuk Kim
@ 2021-05-28  2:07           ` Chao Yu
  0 siblings, 0 replies; 23+ messages in thread
From: Chao Yu @ 2021-05-28  2:07 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-kernel, linux-f2fs-devel

On 2021/5/27 9:36, Jaegeuk Kim wrote:
> On 05/27, Chao Yu wrote:
>> On 2021/5/26 22:43, Jaegeuk Kim wrote:
>>> Given RO feature in superblock, we don't need to check provisioning/reserve
>>> spaces and SSA area.
>>>
>>> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
>>> ---
>>> Change log from v2:
>>>    - allow curseg updates
>>>    - fix some bugs
>>>
>>>    fs/f2fs/f2fs.h    |  2 ++
>>>    fs/f2fs/segment.c |  4 ++++
>>>    fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
>>>    3 files changed, 37 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
>>> index eaf57b5f3c4b..9ad502f92529 100644
>>> --- a/fs/f2fs/f2fs.h
>>> +++ b/fs/f2fs/f2fs.h
>>> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>>>    #define F2FS_FEATURE_SB_CHKSUM		0x0800
>>>    #define F2FS_FEATURE_CASEFOLD		0x1000
>>>    #define F2FS_FEATURE_COMPRESSION	0x2000
>>> +#define F2FS_FEATURE_RO			0x4000
>>>    #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>>>    	((raw_super->feature & cpu_to_le32(mask)) != 0)
>>> @@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>>>    #define	NR_CURSEG_DATA_TYPE	(3)
>>>    #define NR_CURSEG_NODE_TYPE	(3)
>>>    #define NR_CURSEG_INMEM_TYPE	(2)
>>> +#define NR_CURSEG_RO_TYPE	(2)
>>>    #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>>>    #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>> index 8668df7870d0..02e0c38be7eb 100644
>>> --- a/fs/f2fs/segment.c
>>> +++ b/fs/f2fs/segment.c
>>> @@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>>>    		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
>>>    		unsigned int blkofs = curseg->next_blkoff;
>>> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
>>> +			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
>>> +			continue;
>>> +
>>>    		sanity_check_seg_type(sbi, curseg->seg_type);
>>>    		if (f2fs_test_bit(blkofs, se->cur_valid_map))
>>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
>>> index e70aca8f97bd..6788e7b71e27 100644
>>> --- a/fs/f2fs/super.c
>>> +++ b/fs/f2fs/super.c
>>> @@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>>>    	int ret;
>>>    	if (!options)
>>> -		return 0;
>>> +		goto default_check;
>>>    	while ((p = strsep(&options, ",")) != NULL) {
>>>    		int token;
>>> @@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>>>    			return -EINVAL;
>>>    		}
>>>    	}
>>> +default_check:
>>>    #ifdef CONFIG_QUOTA
>>>    	if (f2fs_check_quota_options(sbi))
>>>    		return -EINVAL;
>>> @@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>>>    	 */
>>>    	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
>>>    		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>>> +
>>> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
>>> +		f2fs_err(sbi, "Allow to mount readonly mode only");
>>> +		return -EROFS;
>>> +	}
>>>    	return 0;
>>>    }
>>> @@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>>>    static void default_options(struct f2fs_sb_info *sbi)
>>>    {
>>>    	/* init some FS parameters */
>>> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
>>> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
>>> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
>>> +	else
>>> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
>>> +
>>>    	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>>>    	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>>>    	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
>>> @@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>>>    	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
>>>    		goto skip;
>>> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
>>> +		err = -EROFS;
>>> +		goto restore_opts;
>>> +	}
>>
>> remount() -> parse_options() will fail due to below check, so it doesn't need
>> to check again? Am I missing something?
> 
> We haven't changed sb->ro at this point yet.

Correct.

Thanks,

> 
>>
>> @@ -1162,6 +1163,11 @@
>>
>>   static int parse_options(struct super_block *sb, char *options, bool is_remount)
>>
>>   	 */
>>   	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
>>   		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>> +
>> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
>> +		f2fs_err(sbi, "Allow to mount readonly mode only");
>> +		return -EROFS;
>> +	}
>>   	return 0;
>>   }
>>
>> Thanks,
>>
>>> +
>>>    #ifdef CONFIG_QUOTA
>>>    	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
>>>    		err = dquot_suspend(sb, -1);
>>> @@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>>>    	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>>> -	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>>> +	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
>>> +			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>>>    			ovp_segments == 0 || reserved_segments == 0)) {
>>>    		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>>>    		return 1;
>>>    	}
>>> -
>>>    	user_block_count = le64_to_cpu(ckpt->user_block_count);
>>> -	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
>>> +	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
>>> +			(F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0);
>>>    	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
>>>    	if (!user_block_count || user_block_count >=
>>>    			segment_count_main << log_blocks_per_seg) {
>>> @@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>>>    			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>>>    			return 1;
>>> +
>>> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
>>> +			goto check_data;
>>> +
>>>    		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>>>    			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>>>    				le32_to_cpu(ckpt->cur_node_segno[j])) {
>>> @@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    			}
>>>    		}
>>>    	}
>>> +check_data:
>>>    	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>>>    		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>>>    			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>>>    			return 1;
>>> +
>>> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
>>> +			goto skip_cross;
>>> +
>>>    		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>>>    			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>>>    				le32_to_cpu(ckpt->cur_data_segno[j])) {
>>> @@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>>>    			}
>>>    		}
>>>    	}
>>> -
>>> +skip_cross:
>>>    	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>>>    	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>>>
> .
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v3] f2fs: support RO feature
  2021-05-26 14:43     ` [f2fs-dev] [PATCH 2/2 v3] " Jaegeuk Kim
  2021-05-27  1:19       ` Chao Yu
@ 2021-06-02 15:16       ` Chao Yu
  2021-06-02 19:02       ` [f2fs-dev] [PATCH 2/2 v4] " Jaegeuk Kim
  2 siblings, 0 replies; 23+ messages in thread
From: Chao Yu @ 2021-06-02 15:16 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel

On 2021/5/26 22:43, Jaegeuk Kim wrote:
> Given RO feature in superblock, we don't need to check provisioning/reserve
> spaces and SSA area.

It needs to update below two sysfs entries for RO feature?
/sys/fs/f2fs/<device>/features
/sys/fs/f2fs/features/..

Thanks,

> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> ---
> Change log from v2:
>   - allow curseg updates
>   - fix some bugs
> 
>   fs/f2fs/f2fs.h    |  2 ++
>   fs/f2fs/segment.c |  4 ++++
>   fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
>   3 files changed, 37 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index eaf57b5f3c4b..9ad502f92529 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>   #define F2FS_FEATURE_SB_CHKSUM		0x0800
>   #define F2FS_FEATURE_CASEFOLD		0x1000
>   #define F2FS_FEATURE_COMPRESSION	0x2000
> +#define F2FS_FEATURE_RO			0x4000
>   
>   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> @@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>   #define	NR_CURSEG_DATA_TYPE	(3)
>   #define NR_CURSEG_NODE_TYPE	(3)
>   #define NR_CURSEG_INMEM_TYPE	(2)
> +#define NR_CURSEG_RO_TYPE	(2)
>   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>   
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 8668df7870d0..02e0c38be7eb 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>   		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
>   		unsigned int blkofs = curseg->next_blkoff;
>   
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
> +			continue;
> +
>   		sanity_check_seg_type(sbi, curseg->seg_type);
>   
>   		if (f2fs_test_bit(blkofs, se->cur_valid_map))
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index e70aca8f97bd..6788e7b71e27 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   	int ret;
>   
>   	if (!options)
> -		return 0;
> +		goto default_check;
>   
>   	while ((p = strsep(&options, ",")) != NULL) {
>   		int token;
> @@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   			return -EINVAL;
>   		}
>   	}
> +default_check:
>   #ifdef CONFIG_QUOTA
>   	if (f2fs_check_quota_options(sbi))
>   		return -EINVAL;
> @@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   	 */
>   	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
>   		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> +
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
> +		f2fs_err(sbi, "Allow to mount readonly mode only");
> +		return -EROFS;
> +	}
>   	return 0;
>   }
>   
> @@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>   static void default_options(struct f2fs_sb_info *sbi)
>   {
>   	/* init some FS parameters */
> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> +	else
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +
>   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> @@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>   	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
>   		goto skip;
>   
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
> +		err = -EROFS;
> +		goto restore_opts;
> +	}
> +
>   #ifdef CONFIG_QUOTA
>   	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
>   		err = dquot_suspend(sb, -1);
> @@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>   
> -	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> +	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>   			ovp_segments == 0 || reserved_segments == 0)) {
>   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>   		return 1;
>   	}
> -
>   	user_block_count = le64_to_cpu(ckpt->user_block_count);
> -	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> +	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
> +			(F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0);
>   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
>   	if (!user_block_count || user_block_count >=
>   			segment_count_main << log_blocks_per_seg) {
> @@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto check_data;
> +
>   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> @@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> +check_data:
>   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto skip_cross;
> +
>   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> @@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> -
> +skip_cross:
>   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>   
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v4] f2fs: support RO feature
  2021-05-26 14:43     ` [f2fs-dev] [PATCH 2/2 v3] " Jaegeuk Kim
  2021-05-27  1:19       ` Chao Yu
  2021-06-02 15:16       ` Chao Yu
@ 2021-06-02 19:02       ` Jaegeuk Kim
  2021-06-03 15:52         ` Chao Yu
  2021-06-03 16:08         ` [f2fs-dev] [PATCH 2/2 v5] " Jaegeuk Kim
  2 siblings, 2 replies; 23+ messages in thread
From: Jaegeuk Kim @ 2021-06-02 19:02 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel

Given RO feature in superblock, we don't need to check provisioning/reserve
spaces and SSA area.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---

Change log from v3:
 - add feature sysfs entries

 fs/f2fs/f2fs.h    |  3 +++
 fs/f2fs/segment.c |  4 ++++
 fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
 fs/f2fs/sysfs.c   |  8 ++++++++
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index eaf57b5f3c4b..8903c43091f8 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -168,6 +168,7 @@ struct f2fs_mount_info {
 #define F2FS_FEATURE_SB_CHKSUM		0x0800
 #define F2FS_FEATURE_CASEFOLD		0x1000
 #define F2FS_FEATURE_COMPRESSION	0x2000
+#define F2FS_FEATURE_RO			0x4000
 
 #define __F2FS_HAS_FEATURE(raw_super, mask)				\
 	((raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
 #define	NR_CURSEG_DATA_TYPE	(3)
 #define NR_CURSEG_NODE_TYPE	(3)
 #define NR_CURSEG_INMEM_TYPE	(2)
+#define NR_CURSEG_RO_TYPE	(2)
 #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
 #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
 
@@ -4128,6 +4130,7 @@ F2FS_FEATURE_FUNCS(verity, VERITY);
 F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM);
 F2FS_FEATURE_FUNCS(casefold, CASEFOLD);
 F2FS_FEATURE_FUNCS(compression, COMPRESSION);
+F2FS_FEATURE_FUNCS(readonly, RO);
 
 #ifdef CONFIG_BLK_DEV_ZONED
 static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 380ef34e1a59..376c33ab71e2 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
 		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
 		unsigned int blkofs = curseg->next_blkoff;
 
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
+			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
+			continue;
+
 		sanity_check_seg_type(sbi, curseg->seg_type);
 
 		if (f2fs_test_bit(blkofs, se->cur_valid_map))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 2fa59c674cd9..fb490383c767 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 	int ret;
 
 	if (!options)
-		return 0;
+		goto default_check;
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
@@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 			return -EINVAL;
 		}
 	}
+default_check:
 #ifdef CONFIG_QUOTA
 	if (f2fs_check_quota_options(sbi))
 		return -EINVAL;
@@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 	 */
 	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
 		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
+
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
+		f2fs_err(sbi, "Allow to mount readonly mode only");
+		return -EROFS;
+	}
 	return 0;
 }
 
@@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 static void default_options(struct f2fs_sb_info *sbi)
 {
 	/* init some FS parameters */
-	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
+	else
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+
 	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
 	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
 	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
@@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
 		goto skip;
 
+	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
+		err = -EROFS;
+		goto restore_opts;
+	}
+
 #ifdef CONFIG_QUOTA
 	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
 		err = dquot_suspend(sb, -1);
@@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
 	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
 
-	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
+	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
+			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
 			ovp_segments == 0 || reserved_segments == 0)) {
 		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
 		return 1;
 	}
-
 	user_block_count = le64_to_cpu(ckpt->user_block_count);
-	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
+			(F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0);
 	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
 	if (!user_block_count || user_block_count >=
 			segment_count_main << log_blocks_per_seg) {
@@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+			goto check_data;
+
 		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
 				le32_to_cpu(ckpt->cur_node_segno[j])) {
@@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
+check_data:
 	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
 		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
+			goto skip_cross;
+
 		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
 				le32_to_cpu(ckpt->cur_data_segno[j])) {
@@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
-
+skip_cross:
 	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
 	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
 
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 09e3f258eb52..62fbe4f20dd6 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -158,6 +158,9 @@ static ssize_t features_show(struct f2fs_attr *a,
 	if (f2fs_sb_has_casefold(sbi))
 		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
 				len ? ", " : "", "casefold");
+	if (f2fs_sb_has_readonly(sbi))
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
+				len ? ", " : "", "readonly");
 	if (f2fs_sb_has_compression(sbi))
 		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
 				len ? ", " : "", "compression");
@@ -578,6 +581,7 @@ enum feat_id {
 	FEAT_SB_CHECKSUM,
 	FEAT_CASEFOLD,
 	FEAT_COMPRESSION,
+	FEAT_RO,
 	FEAT_TEST_DUMMY_ENCRYPTION_V2,
 };
 
@@ -599,6 +603,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
 	case FEAT_SB_CHECKSUM:
 	case FEAT_CASEFOLD:
 	case FEAT_COMPRESSION:
+	case FEAT_RO:
 	case FEAT_TEST_DUMMY_ENCRYPTION_V2:
 		return sprintf(buf, "supported\n");
 	}
@@ -723,12 +728,14 @@ F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
 #ifdef CONFIG_UNICODE
 F2FS_FEATURE_RO_ATTR(casefold, FEAT_CASEFOLD);
 #endif
+F2FS_FEATURE_RO_ATTR(readonly, FEAT_RO);
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 F2FS_FEATURE_RO_ATTR(compression, FEAT_COMPRESSION);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_new_inode, compr_new_inode);
 #endif
+
 /* For ATGC */
 F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_ratio, candidate_ratio);
 F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_count, max_candidate_count);
@@ -834,6 +841,7 @@ static struct attribute *f2fs_feat_attrs[] = {
 #ifdef CONFIG_UNICODE
 	ATTR_LIST(casefold),
 #endif
+	ATTR_LIST(readonly),
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 	ATTR_LIST(compression),
 #endif
-- 
2.32.0.rc0.204.g9fa02ecfa5-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v4] f2fs: support RO feature
  2021-06-02 19:02       ` [f2fs-dev] [PATCH 2/2 v4] " Jaegeuk Kim
@ 2021-06-03 15:52         ` Chao Yu
  2021-06-03 16:08         ` [f2fs-dev] [PATCH 2/2 v5] " Jaegeuk Kim
  1 sibling, 0 replies; 23+ messages in thread
From: Chao Yu @ 2021-06-03 15:52 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel

On 2021/6/3 3:02, Jaegeuk Kim wrote:
> Given RO feature in superblock, we don't need to check provisioning/reserve
> spaces and SSA area.
> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
> ---
> 
> Change log from v3:
>   - add feature sysfs entries
> 
>   fs/f2fs/f2fs.h    |  3 +++
>   fs/f2fs/segment.c |  4 ++++
>   fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
>   fs/f2fs/sysfs.c   |  8 ++++++++
>   4 files changed, 46 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index eaf57b5f3c4b..8903c43091f8 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -168,6 +168,7 @@ struct f2fs_mount_info {
>   #define F2FS_FEATURE_SB_CHKSUM		0x0800
>   #define F2FS_FEATURE_CASEFOLD		0x1000
>   #define F2FS_FEATURE_COMPRESSION	0x2000
> +#define F2FS_FEATURE_RO			0x4000
>   
>   #define __F2FS_HAS_FEATURE(raw_super, mask)				\
>   	((raw_super->feature & cpu_to_le32(mask)) != 0)
> @@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
>   #define	NR_CURSEG_DATA_TYPE	(3)
>   #define NR_CURSEG_NODE_TYPE	(3)
>   #define NR_CURSEG_INMEM_TYPE	(2)
> +#define NR_CURSEG_RO_TYPE	(2)
>   #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
>   #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
>   
> @@ -4128,6 +4130,7 @@ F2FS_FEATURE_FUNCS(verity, VERITY);
>   F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM);
>   F2FS_FEATURE_FUNCS(casefold, CASEFOLD);
>   F2FS_FEATURE_FUNCS(compression, COMPRESSION);
> +F2FS_FEATURE_FUNCS(readonly, RO);

If so, we'd better to use f2fs_sb_has_readonly() instead of F2FS_HAS_FEATURE()?

Thanks,

>   
>   #ifdef CONFIG_BLK_DEV_ZONED
>   static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 380ef34e1a59..376c33ab71e2 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
>   		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
>   		unsigned int blkofs = curseg->next_blkoff;
>   
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
> +			continue;
> +
>   		sanity_check_seg_type(sbi, curseg->seg_type);
>   
>   		if (f2fs_test_bit(blkofs, se->cur_valid_map))
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 2fa59c674cd9..fb490383c767 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   	int ret;
>   
>   	if (!options)
> -		return 0;
> +		goto default_check;
>   
>   	while ((p = strsep(&options, ",")) != NULL) {
>   		int token;
> @@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   			return -EINVAL;
>   		}
>   	}
> +default_check:
>   #ifdef CONFIG_QUOTA
>   	if (f2fs_check_quota_options(sbi))
>   		return -EINVAL;
> @@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
>   	 */
>   	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
>   		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
> +
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !f2fs_readonly(sbi->sb)) {
> +		f2fs_err(sbi, "Allow to mount readonly mode only");
> +		return -EROFS;
> +	}
>   	return 0;
>   }
>   
> @@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
>   static void default_options(struct f2fs_sb_info *sbi)
>   {
>   	/* init some FS parameters */
> -	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
> +	else
> +		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
> +
>   	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
>   	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
>   	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
> @@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
>   	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
>   		goto skip;
>   
> +	if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) && !(*flags & SB_RDONLY)) {
> +		err = -EROFS;
> +		goto restore_opts;
> +	}
> +
>   #ifdef CONFIG_QUOTA
>   	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
>   		err = dquot_suspend(sb, -1);
> @@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
>   	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
>   
> -	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
> +	if (!F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) &&
> +			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
>   			ovp_segments == 0 || reserved_segments == 0)) {
>   		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
>   		return 1;
>   	}
> -
>   	user_block_count = le64_to_cpu(ckpt->user_block_count);
> -	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
> +	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
> +			(F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO) ? 1 : 0);
>   	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
>   	if (!user_block_count || user_block_count >=
>   			segment_count_main << log_blocks_per_seg) {
> @@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto check_data;
> +
>   		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_node_segno[j])) {
> @@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> +check_data:
>   	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
>   		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
>   			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
>   			return 1;
> +
> +		if (F2FS_HAS_FEATURE(sbi, F2FS_FEATURE_RO))
> +			goto skip_cross;
> +
>   		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
>   			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
>   				le32_to_cpu(ckpt->cur_data_segno[j])) {
> @@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
>   			}
>   		}
>   	}
> -
> +skip_cross:
>   	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
>   	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
>   
> diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
> index 09e3f258eb52..62fbe4f20dd6 100644
> --- a/fs/f2fs/sysfs.c
> +++ b/fs/f2fs/sysfs.c
> @@ -158,6 +158,9 @@ static ssize_t features_show(struct f2fs_attr *a,
>   	if (f2fs_sb_has_casefold(sbi))
>   		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
>   				len ? ", " : "", "casefold");
> +	if (f2fs_sb_has_readonly(sbi))
> +		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
> +				len ? ", " : "", "readonly");
>   	if (f2fs_sb_has_compression(sbi))
>   		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
>   				len ? ", " : "", "compression");
> @@ -578,6 +581,7 @@ enum feat_id {
>   	FEAT_SB_CHECKSUM,
>   	FEAT_CASEFOLD,
>   	FEAT_COMPRESSION,
> +	FEAT_RO,
>   	FEAT_TEST_DUMMY_ENCRYPTION_V2,
>   };
>   
> @@ -599,6 +603,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
>   	case FEAT_SB_CHECKSUM:
>   	case FEAT_CASEFOLD:
>   	case FEAT_COMPRESSION:
> +	case FEAT_RO:
>   	case FEAT_TEST_DUMMY_ENCRYPTION_V2:
>   		return sprintf(buf, "supported\n");
>   	}
> @@ -723,12 +728,14 @@ F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
>   #ifdef CONFIG_UNICODE
>   F2FS_FEATURE_RO_ATTR(casefold, FEAT_CASEFOLD);
>   #endif
> +F2FS_FEATURE_RO_ATTR(readonly, FEAT_RO);
>   #ifdef CONFIG_F2FS_FS_COMPRESSION
>   F2FS_FEATURE_RO_ATTR(compression, FEAT_COMPRESSION);
>   F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block);
>   F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block);
>   F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_new_inode, compr_new_inode);
>   #endif
> +
>   /* For ATGC */
>   F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_ratio, candidate_ratio);
>   F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_count, max_candidate_count);
> @@ -834,6 +841,7 @@ static struct attribute *f2fs_feat_attrs[] = {
>   #ifdef CONFIG_UNICODE
>   	ATTR_LIST(casefold),
>   #endif
> +	ATTR_LIST(readonly),
>   #ifdef CONFIG_F2FS_FS_COMPRESSION
>   	ATTR_LIST(compression),
>   #endif
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v5] f2fs: support RO feature
  2021-06-02 19:02       ` [f2fs-dev] [PATCH 2/2 v4] " Jaegeuk Kim
  2021-06-03 15:52         ` Chao Yu
@ 2021-06-03 16:08         ` Jaegeuk Kim
  2021-06-04 23:47           ` Chao Yu
  1 sibling, 1 reply; 23+ messages in thread
From: Jaegeuk Kim @ 2021-06-03 16:08 UTC (permalink / raw)
  To: linux-kernel, linux-f2fs-devel

Given RO feature in superblock, we don't need to check provisioning/reserve
spaces and SSA area.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
---
Change log from v4:
 - use f2fs_sb_has_readonly

 fs/f2fs/f2fs.h    |  3 +++
 fs/f2fs/segment.c |  4 ++++
 fs/f2fs/super.c   | 37 +++++++++++++++++++++++++++++++------
 fs/f2fs/sysfs.c   |  8 ++++++++
 4 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index eaf57b5f3c4b..8903c43091f8 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -168,6 +168,7 @@ struct f2fs_mount_info {
 #define F2FS_FEATURE_SB_CHKSUM		0x0800
 #define F2FS_FEATURE_CASEFOLD		0x1000
 #define F2FS_FEATURE_COMPRESSION	0x2000
+#define F2FS_FEATURE_RO			0x4000
 
 #define __F2FS_HAS_FEATURE(raw_super, mask)				\
 	((raw_super->feature & cpu_to_le32(mask)) != 0)
@@ -940,6 +941,7 @@ static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
 #define	NR_CURSEG_DATA_TYPE	(3)
 #define NR_CURSEG_NODE_TYPE	(3)
 #define NR_CURSEG_INMEM_TYPE	(2)
+#define NR_CURSEG_RO_TYPE	(2)
 #define NR_CURSEG_PERSIST_TYPE	(NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE)
 #define NR_CURSEG_TYPE		(NR_CURSEG_INMEM_TYPE + NR_CURSEG_PERSIST_TYPE)
 
@@ -4128,6 +4130,7 @@ F2FS_FEATURE_FUNCS(verity, VERITY);
 F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM);
 F2FS_FEATURE_FUNCS(casefold, CASEFOLD);
 F2FS_FEATURE_FUNCS(compression, COMPRESSION);
+F2FS_FEATURE_FUNCS(readonly, RO);
 
 #ifdef CONFIG_BLK_DEV_ZONED
 static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi,
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 380ef34e1a59..54847eebc5ca 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -4683,6 +4683,10 @@ static int sanity_check_curseg(struct f2fs_sb_info *sbi)
 		struct seg_entry *se = get_seg_entry(sbi, curseg->segno);
 		unsigned int blkofs = curseg->next_blkoff;
 
+		if (f2fs_sb_has_readonly(sbi) &&
+			i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE)
+			continue;
+
 		sanity_check_seg_type(sbi, curseg->seg_type);
 
 		if (f2fs_test_bit(blkofs, se->cur_valid_map))
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 2fa59c674cd9..df8ac902886d 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -555,7 +555,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 	int ret;
 
 	if (!options)
-		return 0;
+		goto default_check;
 
 	while ((p = strsep(&options, ",")) != NULL) {
 		int token;
@@ -1090,6 +1090,7 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 			return -EINVAL;
 		}
 	}
+default_check:
 #ifdef CONFIG_QUOTA
 	if (f2fs_check_quota_options(sbi))
 		return -EINVAL;
@@ -1162,6 +1163,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
 	 */
 	if (F2FS_OPTION(sbi).active_logs != NR_CURSEG_TYPE)
 		F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
+
+	if (f2fs_sb_has_readonly(sbi) && !f2fs_readonly(sbi->sb)) {
+		f2fs_err(sbi, "Allow to mount readonly mode only");
+		return -EROFS;
+	}
 	return 0;
 }
 
@@ -1819,7 +1825,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
 static void default_options(struct f2fs_sb_info *sbi)
 {
 	/* init some FS parameters */
-	F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+	if (f2fs_sb_has_readonly(sbi))
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_RO_TYPE;
+	else
+		F2FS_OPTION(sbi).active_logs = NR_CURSEG_PERSIST_TYPE;
+
 	F2FS_OPTION(sbi).inline_xattr_size = DEFAULT_INLINE_XATTR_ADDRS;
 	F2FS_OPTION(sbi).whint_mode = WHINT_MODE_OFF;
 	F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
@@ -2001,6 +2011,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
 	if (f2fs_readonly(sb) && (*flags & SB_RDONLY))
 		goto skip;
 
+	if (f2fs_sb_has_readonly(sbi) && !(*flags & SB_RDONLY)) {
+		err = -EROFS;
+		goto restore_opts;
+	}
+
 #ifdef CONFIG_QUOTA
 	if (!f2fs_readonly(sb) && (*flags & SB_RDONLY)) {
 		err = dquot_suspend(sb, -1);
@@ -3134,14 +3149,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 	ovp_segments = le32_to_cpu(ckpt->overprov_segment_count);
 	reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count);
 
-	if (unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
+	if (!f2fs_sb_has_readonly(sbi) &&
+			unlikely(fsmeta < F2FS_MIN_META_SEGMENTS ||
 			ovp_segments == 0 || reserved_segments == 0)) {
 		f2fs_err(sbi, "Wrong layout: check mkfs.f2fs version");
 		return 1;
 	}
-
 	user_block_count = le64_to_cpu(ckpt->user_block_count);
-	segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+	segment_count_main = le32_to_cpu(raw_super->segment_count_main) +
+			(f2fs_sb_has_readonly(sbi) ? 1 : 0);
 	log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
 	if (!user_block_count || user_block_count >=
 			segment_count_main << log_blocks_per_seg) {
@@ -3172,6 +3188,10 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 		if (le32_to_cpu(ckpt->cur_node_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_node_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (f2fs_sb_has_readonly(sbi))
+			goto check_data;
+
 		for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
 				le32_to_cpu(ckpt->cur_node_segno[j])) {
@@ -3182,10 +3202,15 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
+check_data:
 	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
 		if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
 			le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
 			return 1;
+
+		if (f2fs_sb_has_readonly(sbi))
+			goto skip_cross;
+
 		for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
 			if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
 				le32_to_cpu(ckpt->cur_data_segno[j])) {
@@ -3207,7 +3232,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
 			}
 		}
 	}
-
+skip_cross:
 	sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
 	nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
 
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index dc71bc968c72..c579d5d3a916 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -158,6 +158,9 @@ static ssize_t features_show(struct f2fs_attr *a,
 	if (f2fs_sb_has_casefold(sbi))
 		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
 				len ? ", " : "", "casefold");
+	if (f2fs_sb_has_readonly(sbi))
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
+				len ? ", " : "", "readonly");
 	if (f2fs_sb_has_compression(sbi))
 		len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
 				len ? ", " : "", "compression");
@@ -578,6 +581,7 @@ enum feat_id {
 	FEAT_SB_CHECKSUM,
 	FEAT_CASEFOLD,
 	FEAT_COMPRESSION,
+	FEAT_RO,
 	FEAT_TEST_DUMMY_ENCRYPTION_V2,
 };
 
@@ -599,6 +603,7 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
 	case FEAT_SB_CHECKSUM:
 	case FEAT_CASEFOLD:
 	case FEAT_COMPRESSION:
+	case FEAT_RO:
 	case FEAT_TEST_DUMMY_ENCRYPTION_V2:
 		return sprintf(buf, "supported\n");
 	}
@@ -721,12 +726,14 @@ F2FS_FEATURE_RO_ATTR(verity, FEAT_VERITY);
 #endif
 F2FS_FEATURE_RO_ATTR(sb_checksum, FEAT_SB_CHECKSUM);
 F2FS_FEATURE_RO_ATTR(casefold, FEAT_CASEFOLD);
+F2FS_FEATURE_RO_ATTR(readonly, FEAT_RO);
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 F2FS_FEATURE_RO_ATTR(compression, FEAT_COMPRESSION);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block);
 F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_new_inode, compr_new_inode);
 #endif
+
 /* For ATGC */
 F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_ratio, candidate_ratio);
 F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_count, max_candidate_count);
@@ -830,6 +837,7 @@ static struct attribute *f2fs_feat_attrs[] = {
 #endif
 	ATTR_LIST(sb_checksum),
 	ATTR_LIST(casefold),
+	ATTR_LIST(readonly),
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 	ATTR_LIST(compression),
 #endif
-- 
2.32.0.rc0.204.g9fa02ecfa5-goog


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [f2fs-dev] [PATCH 2/2 v5] f2fs: support RO feature
  2021-06-03 16:08         ` [f2fs-dev] [PATCH 2/2 v5] " Jaegeuk Kim
@ 2021-06-04 23:47           ` Chao Yu
  0 siblings, 0 replies; 23+ messages in thread
From: Chao Yu @ 2021-06-04 23:47 UTC (permalink / raw)
  To: Jaegeuk Kim, linux-kernel, linux-f2fs-devel

On 2021/6/4 0:08, Jaegeuk Kim wrote:
> Given RO feature in superblock, we don't need to check provisioning/reserve
> spaces and SSA area.
> 
> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

Reviewed-by: Chao Yu <yuchao0@huawei.com>

Thanks,

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2021-06-04 23:47 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21 19:02 [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk Jaegeuk Kim
2021-05-21 19:02 ` [PATCH 2/2] f2fs: support RO feature Jaegeuk Kim
2021-05-24 11:53   ` [f2fs-dev] " Chao Yu
2021-05-24 17:07     ` Jaegeuk Kim
2021-05-25  1:15       ` Chao Yu
2021-05-25  1:45         ` Jaegeuk Kim
2021-05-26  9:42   ` Chao Yu
2021-05-26 13:58     ` Jaegeuk Kim
2021-05-26 15:06       ` Chao Yu
2021-05-26 15:45         ` Jaegeuk Kim
2021-05-26 13:59   ` [PATCH 2/2 v2] " Jaegeuk Kim
2021-05-26 14:06     ` [f2fs-dev] " Jaegeuk Kim
2021-05-26 14:43     ` [f2fs-dev] [PATCH 2/2 v3] " Jaegeuk Kim
2021-05-27  1:19       ` Chao Yu
2021-05-27  1:36         ` Jaegeuk Kim
2021-05-28  2:07           ` Chao Yu
2021-06-02 15:16       ` Chao Yu
2021-06-02 19:02       ` [f2fs-dev] [PATCH 2/2 v4] " Jaegeuk Kim
2021-06-03 15:52         ` Chao Yu
2021-06-03 16:08         ` [f2fs-dev] [PATCH 2/2 v5] " Jaegeuk Kim
2021-06-04 23:47           ` Chao Yu
2021-05-26  9:08 ` [f2fs-dev] [PATCH 1/2] f2fs: immutable file can have null address in compressed chunk Chao Yu
2021-05-26 14:02   ` Jaegeuk Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).