Linux-EROFS Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] erofs-utils: code for superblock checksum calculation.
@ 2019-08-24 12:38 Pratik Shinde
  2019-08-24 14:00 ` Gao Xiang via Linux-erofs
  0 siblings, 1 reply; 19+ messages in thread
From: Pratik Shinde @ 2019-08-24 12:38 UTC (permalink / raw)
  To: linux-erofs, bluce.liguifu, miaoxie, fangwei1

Adding code for superblock checksum calculation.

incorporated the changes suggested in previous patch.

Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
---
 include/erofs/config.h |  1 +
 include/erofs_fs.h     | 10 ++++++++
 mkfs/main.c            | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/include/erofs/config.h b/include/erofs/config.h
index 05fe6b2..40cd466 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -22,6 +22,7 @@ struct erofs_configure {
 	char *c_src_path;
 	char *c_compr_alg_master;
 	int c_compr_level_master;
+	int c_feature_flags;
 };
 
 extern struct erofs_configure cfg;
diff --git a/include/erofs_fs.h b/include/erofs_fs.h
index 601b477..9ac2635 100644
--- a/include/erofs_fs.h
+++ b/include/erofs_fs.h
@@ -20,6 +20,16 @@
 #define EROFS_REQUIREMENT_LZ4_0PADDING	0x00000001
 #define EROFS_ALL_REQUIREMENTS		EROFS_REQUIREMENT_LZ4_0PADDING
 
+/*
+ * feature definations.
+ */
+#define EROFS_DEFAULT_FEATURES		EROFS_FEATURE_SB_CHKSUM
+#define EROFS_FEATURE_SB_CHKSUM		0x0001
+
+
+#define EROFS_HAS_COMPAT_FEATURE(super,mask)	\
+	( le32_to_cpu((super)->features) & (mask) )
+
 struct erofs_super_block {
 /*  0 */__le32 magic;           /* in the little endian */
 /*  4 */__le32 checksum;        /* crc32c(super_block) */
diff --git a/mkfs/main.c b/mkfs/main.c
index f127fe1..355fd2c 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -31,6 +31,45 @@ static void usage(void)
 	fprintf(stderr, " -EX[,...] X=extended options\n");
 }
 
+#define CRCPOLY	0x82F63B78
+static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)
+{
+	int i;
+	u32 crc = seed;
+
+	while (len--) {
+		crc ^= *in++;
+		for (i = 0; i < 8; i++) {
+			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
+		}
+	}
+	erofs_dump("calculated crc: 0x%x\n", crc);
+	return crc;
+}
+
+char *feature_opts[] = {
+	"nosbcrc", NULL
+};
+#define O_SB_CKSUM	0
+
+static int parse_feature_subopts(char *opts)
+{
+	char *arg;
+
+	cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
+	while (*opts != '\0') {
+		switch(getsubopt(&opts, feature_opts, &arg)) {
+		case O_SB_CKSUM:
+			cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);
+			break;
+		default:
+			erofs_err("incorrect suboption");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
 static int parse_extended_opts(const char *opts)
 {
 #define MATCH_EXTENTED_OPT(opt, token, keylen) \
@@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 {
 	int opt, i;
 
-	while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
+	cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
+	while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
 		switch (opt) {
 		case 'z':
 			if (!optarg) {
@@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 				return opt;
 			break;
 
+		case 'O':
+			opt = parse_feature_subopts(optarg);
+			if (opt)
+				return opt;
+			break;
+
 		default: /* '?' */
 			return -EINVAL;
 		}
@@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 	return 0;
 }
 
+u32 erofs_superblock_checksum(struct erofs_super_block *sb)
+{
+	u32 crc;
+	crc = crc32c(~0, (const unsigned char *)sb,
+		    sizeof(struct erofs_super_block));
+	erofs_dump("superblock checksum: 0x%x\n", crc);
+	return crc;
+}
+
 int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
 				  erofs_nid_t root_nid)
 {
@@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
 		.meta_blkaddr  = sbi.meta_blkaddr,
 		.xattr_blkaddr = 0,
 		.requirements = cpu_to_le32(sbi.requirements),
+		.features = cpu_to_le32(cfg.c_feature_flags),
 	};
 	const unsigned int sb_blksize =
 		round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
@@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
 	sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
 	sb.root_nid     = cpu_to_le16(root_nid);
 
+	if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
+		sb.checksum = 0;
+		u32 crc = erofs_superblock_checksum(&sb);
+		sb.checksum = cpu_to_le32(crc);
+	}
+
 	buf = calloc(sb_blksize, 1);
 	if (!buf) {
 		erofs_err("Failed to allocate memory for sb: %s",
-- 
2.9.3


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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24 12:38 [PATCH] erofs-utils: code for superblock checksum calculation Pratik Shinde
@ 2019-08-24 14:00 ` Gao Xiang via Linux-erofs
  2019-08-24 14:12   ` Gao Xiang via Linux-erofs
  2019-08-24 14:56   ` Pratik Shinde
  0 siblings, 2 replies; 19+ messages in thread
From: Gao Xiang via Linux-erofs @ 2019-08-24 14:00 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: miaoxie, linux-erofs

Hi Pratik,

On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> Adding code for superblock checksum calculation.
> 
> incorporated the changes suggested in previous patch.
> 
> Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>

Thanks for your v2 patch.

Actually, I have some concern about the length of checksum,
sizeof(struct erofs_super_block) could be changed in the
later version, it's bad for EROFS future scalablity.

And I tend not to add another on-disk field to record
the size of erofs_super_block as well, because the old
Linux kernel cannot handle more about the new size,
so it has little use except for checksum calculation.

Few hours ago, I discussed with Chao about this concern,
I think this feature can be changed to do multiple-block
checksum at the mount time, e.g:
 - for small images, we can check the whole image once
   at the mount time;
 - for the large image, we can check the superblock
   at the mount time, the rest can be handled by
   block-based verification layer.

But we agreed that don't add this for this round
since it's quite a new feature.

All in all, it's a new feature since we are addressing moving
out of staging for this round. I tend to postpone this feature
for now. I understand that you are very interested in EROFS.
Considering EROFS current staging status, it's not such a place
to add new features at all! I have marked your patch down and
I will work with you later. Hope to get your understanding...

Thanks,
Gao Xiang

> ---
>  include/erofs/config.h |  1 +
>  include/erofs_fs.h     | 10 ++++++++
>  mkfs/main.c            | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/include/erofs/config.h b/include/erofs/config.h
> index 05fe6b2..40cd466 100644
> --- a/include/erofs/config.h
> +++ b/include/erofs/config.h
> @@ -22,6 +22,7 @@ struct erofs_configure {
>  	char *c_src_path;
>  	char *c_compr_alg_master;
>  	int c_compr_level_master;
> +	int c_feature_flags;
>  };
>  
>  extern struct erofs_configure cfg;
> diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> index 601b477..9ac2635 100644
> --- a/include/erofs_fs.h
> +++ b/include/erofs_fs.h
> @@ -20,6 +20,16 @@
>  #define EROFS_REQUIREMENT_LZ4_0PADDING	0x00000001
>  #define EROFS_ALL_REQUIREMENTS		EROFS_REQUIREMENT_LZ4_0PADDING
>  
> +/*
> + * feature definations.
> + */
> +#define EROFS_DEFAULT_FEATURES		EROFS_FEATURE_SB_CHKSUM
> +#define EROFS_FEATURE_SB_CHKSUM		0x0001
> +
> +
> +#define EROFS_HAS_COMPAT_FEATURE(super,mask)	\
> +	( le32_to_cpu((super)->features) & (mask) )
> +
>  struct erofs_super_block {
>  /*  0 */__le32 magic;           /* in the little endian */
>  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> diff --git a/mkfs/main.c b/mkfs/main.c
> index f127fe1..355fd2c 100644
> --- a/mkfs/main.c
> +++ b/mkfs/main.c
> @@ -31,6 +31,45 @@ static void usage(void)
>  	fprintf(stderr, " -EX[,...] X=extended options\n");
>  }
>  
> +#define CRCPOLY	0x82F63B78
> +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)
> +{
> +	int i;
> +	u32 crc = seed;
> +
> +	while (len--) {
> +		crc ^= *in++;
> +		for (i = 0; i < 8; i++) {
> +			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
> +		}
> +	}
> +	erofs_dump("calculated crc: 0x%x\n", crc);
> +	return crc;
> +}
> +
> +char *feature_opts[] = {
> +	"nosbcrc", NULL
> +};
> +#define O_SB_CKSUM	0
> +
> +static int parse_feature_subopts(char *opts)
> +{
> +	char *arg;
> +
> +	cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> +	while (*opts != '\0') {
> +		switch(getsubopt(&opts, feature_opts, &arg)) {
> +		case O_SB_CKSUM:
> +			cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);
> +			break;
> +		default:
> +			erofs_err("incorrect suboption");
> +			return -EINVAL;
> +		}
> +	}
> +	return 0;
> +}
> +
>  static int parse_extended_opts(const char *opts)
>  {
>  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
>  {
>  	int opt, i;
>  
> -	while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> +	cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> +	while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
>  		switch (opt) {
>  		case 'z':
>  			if (!optarg) {
> @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
>  				return opt;
>  			break;
>  
> +		case 'O':
> +			opt = parse_feature_subopts(optarg);
> +			if (opt)
> +				return opt;
> +			break;
> +
>  		default: /* '?' */
>  			return -EINVAL;
>  		}
> @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
>  	return 0;
>  }
>  
> +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> +{
> +	u32 crc;
> +	crc = crc32c(~0, (const unsigned char *)sb,
> +		    sizeof(struct erofs_super_block));
> +	erofs_dump("superblock checksum: 0x%x\n", crc);
> +	return crc;
> +}
> +
>  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
>  				  erofs_nid_t root_nid)
>  {
> @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
>  		.meta_blkaddr  = sbi.meta_blkaddr,
>  		.xattr_blkaddr = 0,
>  		.requirements = cpu_to_le32(sbi.requirements),
> +		.features = cpu_to_le32(cfg.c_feature_flags),
>  	};
>  	const unsigned int sb_blksize =
>  		round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
>  	sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
>  	sb.root_nid     = cpu_to_le16(root_nid);
>  
> +	if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> +		sb.checksum = 0;
> +		u32 crc = erofs_superblock_checksum(&sb);
> +		sb.checksum = cpu_to_le32(crc);
> +	}
> +
>  	buf = calloc(sb_blksize, 1);
>  	if (!buf) {
>  		erofs_err("Failed to allocate memory for sb: %s",
> -- 
> 2.9.3
> 

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24 14:00 ` Gao Xiang via Linux-erofs
@ 2019-08-24 14:12   ` Gao Xiang via Linux-erofs
  2019-08-24 14:56   ` Pratik Shinde
  1 sibling, 0 replies; 19+ messages in thread
From: Gao Xiang via Linux-erofs @ 2019-08-24 14:12 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: linux-erofs, miaoxie

On Sat, Aug 24, 2019 at 10:00:25PM +0800, Gao Xiang via Linux-erofs wrote:
> Hi Pratik,
> 
> On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > Adding code for superblock checksum calculation.
> > 
> > incorporated the changes suggested in previous patch.
> > 
> > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> 
> Thanks for your v2 patch.
> 
> Actually, I have some concern about the length of checksum,
> sizeof(struct erofs_super_block) could be changed in the
> later version, it's bad for EROFS future scalablity.
> 
> And I tend not to add another on-disk field to record
> the size of erofs_super_block as well, because the old
> Linux kernel cannot handle more about the new size,
> so it has little use except for checksum calculation.
> 
> Few hours ago, I discussed with Chao about this concern,
> I think this feature can be changed to do multiple-block
> checksum at the mount time, e.g:
>  - for small images, we can check the whole image once
>    at the mount time;
>  - for the large image, we can check the superblock
>    at the mount time, the rest can be handled by
>    block-based verification layer.
> 
> But we agreed that don't add this for this round
> since it's quite a new feature.
> 
> All in all, it's a new feature since we are addressing moving
> out of staging for this round. I tend to postpone this feature
> for now. I understand that you are very interested in EROFS.
> Considering EROFS current staging status, it's not such a place
> to add new features at all! I have marked your patch down and
                            ^ it should be a stop sign (.)
 
Sorry... that's my keyboard fault...

Let's postpone all new features and address more about moving out
EROFS. Only in this way, EROFS could have good future or it would
be dead. Hope to get your understanding...

Thanks,
Gao Xiang

> I will work with you later. Hope to get your understanding...
> 
> Thanks,
> Gao Xiang
> 
> > ---
> >  include/erofs/config.h |  1 +
> >  include/erofs_fs.h     | 10 ++++++++
> >  mkfs/main.c            | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-
> >  3 files changed, 74 insertions(+), 1 deletion(-)
> > 
> > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > index 05fe6b2..40cd466 100644
> > --- a/include/erofs/config.h
> > +++ b/include/erofs/config.h
> > @@ -22,6 +22,7 @@ struct erofs_configure {
> >  	char *c_src_path;
> >  	char *c_compr_alg_master;
> >  	int c_compr_level_master;
> > +	int c_feature_flags;
> >  };
> >  
> >  extern struct erofs_configure cfg;
> > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > index 601b477..9ac2635 100644
> > --- a/include/erofs_fs.h
> > +++ b/include/erofs_fs.h
> > @@ -20,6 +20,16 @@
> >  #define EROFS_REQUIREMENT_LZ4_0PADDING	0x00000001
> >  #define EROFS_ALL_REQUIREMENTS		EROFS_REQUIREMENT_LZ4_0PADDING
> >  
> > +/*
> > + * feature definations.
> > + */
> > +#define EROFS_DEFAULT_FEATURES		EROFS_FEATURE_SB_CHKSUM
> > +#define EROFS_FEATURE_SB_CHKSUM		0x0001
> > +
> > +
> > +#define EROFS_HAS_COMPAT_FEATURE(super,mask)	\
> > +	( le32_to_cpu((super)->features) & (mask) )
> > +
> >  struct erofs_super_block {
> >  /*  0 */__le32 magic;           /* in the little endian */
> >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > diff --git a/mkfs/main.c b/mkfs/main.c
> > index f127fe1..355fd2c 100644
> > --- a/mkfs/main.c
> > +++ b/mkfs/main.c
> > @@ -31,6 +31,45 @@ static void usage(void)
> >  	fprintf(stderr, " -EX[,...] X=extended options\n");
> >  }
> >  
> > +#define CRCPOLY	0x82F63B78
> > +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)
> > +{
> > +	int i;
> > +	u32 crc = seed;
> > +
> > +	while (len--) {
> > +		crc ^= *in++;
> > +		for (i = 0; i < 8; i++) {
> > +			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
> > +		}
> > +	}
> > +	erofs_dump("calculated crc: 0x%x\n", crc);
> > +	return crc;
> > +}
> > +
> > +char *feature_opts[] = {
> > +	"nosbcrc", NULL
> > +};
> > +#define O_SB_CKSUM	0
> > +
> > +static int parse_feature_subopts(char *opts)
> > +{
> > +	char *arg;
> > +
> > +	cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > +	while (*opts != '\0') {
> > +		switch(getsubopt(&opts, feature_opts, &arg)) {
> > +		case O_SB_CKSUM:
> > +			cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);
> > +			break;
> > +		default:
> > +			erofs_err("incorrect suboption");
> > +			return -EINVAL;
> > +		}
> > +	}
> > +	return 0;
> > +}
> > +
> >  static int parse_extended_opts(const char *opts)
> >  {
> >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
> >  {
> >  	int opt, i;
> >  
> > -	while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > +	cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > +	while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> >  		switch (opt) {
> >  		case 'z':
> >  			if (!optarg) {
> > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
> >  				return opt;
> >  			break;
> >  
> > +		case 'O':
> > +			opt = parse_feature_subopts(optarg);
> > +			if (opt)
> > +				return opt;
> > +			break;
> > +
> >  		default: /* '?' */
> >  			return -EINVAL;
> >  		}
> > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
> >  	return 0;
> >  }
> >  
> > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > +{
> > +	u32 crc;
> > +	crc = crc32c(~0, (const unsigned char *)sb,
> > +		    sizeof(struct erofs_super_block));
> > +	erofs_dump("superblock checksum: 0x%x\n", crc);
> > +	return crc;
> > +}
> > +
> >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> >  				  erofs_nid_t root_nid)
> >  {
> > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> >  		.meta_blkaddr  = sbi.meta_blkaddr,
> >  		.xattr_blkaddr = 0,
> >  		.requirements = cpu_to_le32(sbi.requirements),
> > +		.features = cpu_to_le32(cfg.c_feature_flags),
> >  	};
> >  	const unsigned int sb_blksize =
> >  		round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> >  	sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> >  	sb.root_nid     = cpu_to_le16(root_nid);
> >  
> > +	if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > +		sb.checksum = 0;
> > +		u32 crc = erofs_superblock_checksum(&sb);
> > +		sb.checksum = cpu_to_le32(crc);
> > +	}
> > +
> >  	buf = calloc(sb_blksize, 1);
> >  	if (!buf) {
> >  		erofs_err("Failed to allocate memory for sb: %s",
> > -- 
> > 2.9.3
> > 

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24 14:00 ` Gao Xiang via Linux-erofs
  2019-08-24 14:12   ` Gao Xiang via Linux-erofs
@ 2019-08-24 14:56   ` Pratik Shinde
  2019-08-24 15:16     ` Gao Xiang via Linux-erofs
  2019-10-06  5:39     ` Gao Xiang via Linux-erofs
  1 sibling, 2 replies; 19+ messages in thread
From: Pratik Shinde @ 2019-08-24 14:56 UTC (permalink / raw)
  To: Gao Xiang; +Cc: miaoxie, linux-erofs

[-- Attachment #1: Type: text/plain, Size: 7187 bytes --]

Hi Gao,

I completely understand your concern.You can drop this patch for now.
Once erofs makes it 'fs/' please do reconsider implementing it.

One more thing, can we still send non feature patches?

--Pratik


On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com> wrote:

> Hi Pratik,
>
> On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > Adding code for superblock checksum calculation.
> >
> > incorporated the changes suggested in previous patch.
> >
> > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
>
> Thanks for your v2 patch.
>
> Actually, I have some concern about the length of checksum,
> sizeof(struct erofs_super_block) could be changed in the
> later version, it's bad for EROFS future scalablity.
>
> And I tend not to add another on-disk field to record
> the size of erofs_super_block as well, because the old
> Linux kernel cannot handle more about the new size,
> so it has little use except for checksum calculation.
>
> Few hours ago, I discussed with Chao about this concern,
> I think this feature can be changed to do multiple-block
> checksum at the mount time, e.g:
>  - for small images, we can check the whole image once
>    at the mount time;
>  - for the large image, we can check the superblock
>    at the mount time, the rest can be handled by
>    block-based verification layer.
>
> But we agreed that don't add this for this round
> since it's quite a new feature.
>
> All in all, it's a new feature since we are addressing moving
> out of staging for this round. I tend to postpone this feature
> for now. I understand that you are very interested in EROFS.
> Considering EROFS current staging status, it's not such a place
> to add new features at all! I have marked your patch down and
> I will work with you later. Hope to get your understanding...
>
> Thanks,
> Gao Xiang
>
> > ---
> >  include/erofs/config.h |  1 +
> >  include/erofs_fs.h     | 10 ++++++++
> >  mkfs/main.c            | 64
> +++++++++++++++++++++++++++++++++++++++++++++++++-
> >  3 files changed, 74 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > index 05fe6b2..40cd466 100644
> > --- a/include/erofs/config.h
> > +++ b/include/erofs/config.h
> > @@ -22,6 +22,7 @@ struct erofs_configure {
> >       char *c_src_path;
> >       char *c_compr_alg_master;
> >       int c_compr_level_master;
> > +     int c_feature_flags;
> >  };
> >
> >  extern struct erofs_configure cfg;
> > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > index 601b477..9ac2635 100644
> > --- a/include/erofs_fs.h
> > +++ b/include/erofs_fs.h
> > @@ -20,6 +20,16 @@
> >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> >  #define EROFS_ALL_REQUIREMENTS
>  EROFS_REQUIREMENT_LZ4_0PADDING
> >
> > +/*
> > + * feature definations.
> > + */
> > +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM
> > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > +
> > +
> > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > +     ( le32_to_cpu((super)->features) & (mask) )
> > +
> >  struct erofs_super_block {
> >  /*  0 */__le32 magic;           /* in the little endian */
> >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > diff --git a/mkfs/main.c b/mkfs/main.c
> > index f127fe1..355fd2c 100644
> > --- a/mkfs/main.c
> > +++ b/mkfs/main.c
> > @@ -31,6 +31,45 @@ static void usage(void)
> >       fprintf(stderr, " -EX[,...] X=extended options\n");
> >  }
> >
> > +#define CRCPOLY      0x82F63B78
> > +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)
> > +{
> > +     int i;
> > +     u32 crc = seed;
> > +
> > +     while (len--) {
> > +             crc ^= *in++;
> > +             for (i = 0; i < 8; i++) {
> > +                     crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
> > +             }
> > +     }
> > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > +     return crc;
> > +}
> > +
> > +char *feature_opts[] = {
> > +     "nosbcrc", NULL
> > +};
> > +#define O_SB_CKSUM   0
> > +
> > +static int parse_feature_subopts(char *opts)
> > +{
> > +     char *arg;
> > +
> > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > +     while (*opts != '\0') {
> > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > +             case O_SB_CKSUM:
> > +                     cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);
> > +                     break;
> > +             default:
> > +                     erofs_err("incorrect suboption");
> > +                     return -EINVAL;
> > +             }
> > +     }
> > +     return 0;
> > +}
> > +
> >  static int parse_extended_opts(const char *opts)
> >  {
> >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char
> *argv[])
> >  {
> >       int opt, i;
> >
> > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> >               switch (opt) {
> >               case 'z':
> >                       if (!optarg) {
> > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char
> *argv[])
> >                               return opt;
> >                       break;
> >
> > +             case 'O':
> > +                     opt = parse_feature_subopts(optarg);
> > +                     if (opt)
> > +                             return opt;
> > +                     break;
> > +
> >               default: /* '?' */
> >                       return -EINVAL;
> >               }
> > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char
> *argv[])
> >       return 0;
> >  }
> >
> > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > +{
> > +     u32 crc;
> > +     crc = crc32c(~0, (const unsigned char *)sb,
> > +                 sizeof(struct erofs_super_block));
> > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > +     return crc;
> > +}
> > +
> >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> >                                 erofs_nid_t root_nid)
> >  {
> > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> erofs_buffer_head *bh,
> >               .meta_blkaddr  = sbi.meta_blkaddr,
> >               .xattr_blkaddr = 0,
> >               .requirements = cpu_to_le32(sbi.requirements),
> > +             .features = cpu_to_le32(cfg.c_feature_flags),
> >       };
> >       const unsigned int sb_blksize =
> >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> erofs_buffer_head *bh,
> >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> >       sb.root_nid     = cpu_to_le16(root_nid);
> >
> > +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > +             sb.checksum = 0;
> > +             u32 crc = erofs_superblock_checksum(&sb);
> > +             sb.checksum = cpu_to_le32(crc);
> > +     }
> > +
> >       buf = calloc(sb_blksize, 1);
> >       if (!buf) {
> >               erofs_err("Failed to allocate memory for sb: %s",
> > --
> > 2.9.3
> >
>

[-- Attachment #2: Type: text/html, Size: 9589 bytes --]

<div dir="auto">Hi Gao,<div dir="auto"><br></div><div dir="auto">I completely understand your concern.You can drop this patch for now.</div><div dir="auto">Once erofs makes it &#39;fs/&#39; please do reconsider implementing it.</div><div dir="auto"><br></div><div dir="auto">One more thing, can we still send non feature patches? </div><div dir="auto"><br></div><div dir="auto">--Pratik</div><div dir="auto"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, &lt;<a href="mailto:hsiangkao@aol.com" rel="noreferrer noreferrer" target="_blank">hsiangkao@aol.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Pratik,<br>
<br>
On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:<br>
&gt; Adding code for superblock checksum calculation.<br>
&gt; <br>
&gt; incorporated the changes suggested in previous patch.<br>
&gt; <br>
&gt; Signed-off-by: Pratik Shinde &lt;<a href="mailto:pratikshinde320@gmail.com" rel="noreferrer noreferrer noreferrer" target="_blank">pratikshinde320@gmail.com</a>&gt;<br>
<br>
Thanks for your v2 patch.<br>
<br>
Actually, I have some concern about the length of checksum,<br>
sizeof(struct erofs_super_block) could be changed in the<br>
later version, it&#39;s bad for EROFS future scalablity.<br>
<br>
And I tend not to add another on-disk field to record<br>
the size of erofs_super_block as well, because the old<br>
Linux kernel cannot handle more about the new size,<br>
so it has little use except for checksum calculation.<br>
<br>
Few hours ago, I discussed with Chao about this concern,<br>
I think this feature can be changed to do multiple-block<br>
checksum at the mount time, e.g:<br>
 - for small images, we can check the whole image once<br>
   at the mount time;<br>
 - for the large image, we can check the superblock<br>
   at the mount time, the rest can be handled by<br>
   block-based verification layer.<br>
<br>
But we agreed that don&#39;t add this for this round<br>
since it&#39;s quite a new feature.<br>
<br>
All in all, it&#39;s a new feature since we are addressing moving<br>
out of staging for this round. I tend to postpone this feature<br>
for now. I understand that you are very interested in EROFS.<br>
Considering EROFS current staging status, it&#39;s not such a place<br>
to add new features at all! I have marked your patch down and<br>
I will work with you later. Hope to get your understanding...<br>
<br>
Thanks,<br>
Gao Xiang<br>
<br>
&gt; ---<br>
&gt;  include/erofs/config.h |  1 +<br>
&gt;  include/erofs_fs.h     | 10 ++++++++<br>
&gt;  mkfs/main.c            | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-<br>
&gt;  3 files changed, 74 insertions(+), 1 deletion(-)<br>
&gt; <br>
&gt; diff --git a/include/erofs/config.h b/include/erofs/config.h<br>
&gt; index 05fe6b2..40cd466 100644<br>
&gt; --- a/include/erofs/config.h<br>
&gt; +++ b/include/erofs/config.h<br>
&gt; @@ -22,6 +22,7 @@ struct erofs_configure {<br>
&gt;       char *c_src_path;<br>
&gt;       char *c_compr_alg_master;<br>
&gt;       int c_compr_level_master;<br>
&gt; +     int c_feature_flags;<br>
&gt;  };<br>
&gt;  <br>
&gt;  extern struct erofs_configure cfg;<br>
&gt; diff --git a/include/erofs_fs.h b/include/erofs_fs.h<br>
&gt; index 601b477..9ac2635 100644<br>
&gt; --- a/include/erofs_fs.h<br>
&gt; +++ b/include/erofs_fs.h<br>
&gt; @@ -20,6 +20,16 @@<br>
&gt;  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001<br>
&gt;  #define EROFS_ALL_REQUIREMENTS               EROFS_REQUIREMENT_LZ4_0PADDING<br>
&gt;  <br>
&gt; +/*<br>
&gt; + * feature definations.<br>
&gt; + */<br>
&gt; +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM<br>
&gt; +#define EROFS_FEATURE_SB_CHKSUM              0x0001<br>
&gt; +<br>
&gt; +<br>
&gt; +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \<br>
&gt; +     ( le32_to_cpu((super)-&gt;features) &amp; (mask) )<br>
&gt; +<br>
&gt;  struct erofs_super_block {<br>
&gt;  /*  0 */__le32 magic;           /* in the little endian */<br>
&gt;  /*  4 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt; diff --git a/mkfs/main.c b/mkfs/main.c<br>
&gt; index f127fe1..355fd2c 100644<br>
&gt; --- a/mkfs/main.c<br>
&gt; +++ b/mkfs/main.c<br>
&gt; @@ -31,6 +31,45 @@ static void usage(void)<br>
&gt;       fprintf(stderr, &quot; -EX[,...] X=extended options\n&quot;);<br>
&gt;  }<br>
&gt;  <br>
&gt; +#define CRCPOLY      0x82F63B78<br>
&gt; +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)<br>
&gt; +{<br>
&gt; +     int i;<br>
&gt; +     u32 crc = seed;<br>
&gt; +<br>
&gt; +     while (len--) {<br>
&gt; +             crc ^= *in++;<br>
&gt; +             for (i = 0; i &lt; 8; i++) {<br>
&gt; +                     crc = (crc &gt;&gt; 1) ^ ((crc &amp; 1) ? CRCPOLY : 0);<br>
&gt; +             }<br>
&gt; +     }<br>
&gt; +     erofs_dump(&quot;calculated crc: 0x%x\n&quot;, crc);<br>
&gt; +     return crc;<br>
&gt; +}<br>
&gt; +<br>
&gt; +char *feature_opts[] = {<br>
&gt; +     &quot;nosbcrc&quot;, NULL<br>
&gt; +};<br>
&gt; +#define O_SB_CKSUM   0<br>
&gt; +<br>
&gt; +static int parse_feature_subopts(char *opts)<br>
&gt; +{<br>
&gt; +     char *arg;<br>
&gt; +<br>
&gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; +     while (*opts != &#39;\0&#39;) {<br>
&gt; +             switch(getsubopt(&amp;opts, feature_opts, &amp;arg)) {<br>
&gt; +             case O_SB_CKSUM:<br>
&gt; +                     cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);<br>
&gt; +                     break;<br>
&gt; +             default:<br>
&gt; +                     erofs_err(&quot;incorrect suboption&quot;);<br>
&gt; +                     return -EINVAL;<br>
&gt; +             }<br>
&gt; +     }<br>
&gt; +     return 0;<br>
&gt; +}<br>
&gt; +<br>
&gt;  static int parse_extended_opts(const char *opts)<br>
&gt;  {<br>
&gt;  #define MATCH_EXTENTED_OPT(opt, token, keylen) \<br>
&gt; @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])<br>
&gt;  {<br>
&gt;       int opt, i;<br>
&gt;  <br>
&gt; -     while ((opt = getopt(argc, argv, &quot;d:z:E:&quot;)) != -1) {<br>
&gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; +     while ((opt = getopt(argc, argv, &quot;d:z:E:o:&quot;)) != -1) {<br>
&gt;               switch (opt) {<br>
&gt;               case &#39;z&#39;:<br>
&gt;                       if (!optarg) {<br>
&gt; @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])<br>
&gt;                               return opt;<br>
&gt;                       break;<br>
&gt;  <br>
&gt; +             case &#39;O&#39;:<br>
&gt; +                     opt = parse_feature_subopts(optarg);<br>
&gt; +                     if (opt)<br>
&gt; +                             return opt;<br>
&gt; +                     break;<br>
&gt; +<br>
&gt;               default: /* &#39;?&#39; */<br>
&gt;                       return -EINVAL;<br>
&gt;               }<br>
&gt; @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])<br>
&gt;       return 0;<br>
&gt;  }<br>
&gt;  <br>
&gt; +u32 erofs_superblock_checksum(struct erofs_super_block *sb)<br>
&gt; +{<br>
&gt; +     u32 crc;<br>
&gt; +     crc = crc32c(~0, (const unsigned char *)sb,<br>
&gt; +                 sizeof(struct erofs_super_block));<br>
&gt; +     erofs_dump(&quot;superblock checksum: 0x%x\n&quot;, crc);<br>
&gt; +     return crc;<br>
&gt; +}<br>
&gt; +<br>
&gt;  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt;                                 erofs_nid_t root_nid)<br>
&gt;  {<br>
&gt; @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt;               .meta_blkaddr  = sbi.meta_blkaddr,<br>
&gt;               .xattr_blkaddr = 0,<br>
&gt;               .requirements = cpu_to_le32(sbi.requirements),<br>
&gt; +             .features = cpu_to_le32(cfg.c_feature_flags),<br>
&gt;       };<br>
&gt;       const unsigned int sb_blksize =<br>
&gt;               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);<br>
&gt; @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt;       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));<br>
&gt;       sb.root_nid     = cpu_to_le16(root_nid);<br>
&gt;  <br>
&gt; +     if (EROFS_HAS_COMPAT_FEATURE(&amp;sb, EROFS_FEATURE_SB_CHKSUM)) {<br>
&gt; +             sb.checksum = 0;<br>
&gt; +             u32 crc = erofs_superblock_checksum(&amp;sb);<br>
&gt; +             sb.checksum = cpu_to_le32(crc);<br>
&gt; +     }<br>
&gt; +<br>
&gt;       buf = calloc(sb_blksize, 1);<br>
&gt;       if (!buf) {<br>
&gt;               erofs_err(&quot;Failed to allocate memory for sb: %s&quot;,<br>
&gt; -- <br>
&gt; 2.9.3<br>
&gt; <br>
</blockquote></div>

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24 14:56   ` Pratik Shinde
@ 2019-08-24 15:16     ` Gao Xiang via Linux-erofs
  2019-10-06  5:39     ` Gao Xiang via Linux-erofs
  1 sibling, 0 replies; 19+ messages in thread
From: Gao Xiang via Linux-erofs @ 2019-08-24 15:16 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: miaoxie, linux-erofs

Hi Pratik,

On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> Hi Gao,
> 
> I completely understand your concern.You can drop this patch for now.

Thank you.

> Once erofs makes it 'fs/' please do reconsider implementing it.
> 
> One more thing, can we still send non feature patches?

Yes, of course. All bugfix patches for erofs kernel and erofs-utils
are OK, if it's important, I will apply it for 5.4 round immediately.

Thanks,
Gao Xiang

> 
> --Pratik
> 
> 
> On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com> wrote:
> 
> > Hi Pratik,
> >
> > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > Adding code for superblock checksum calculation.
> > >
> > > incorporated the changes suggested in previous patch.
> > >
> > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> >
> > Thanks for your v2 patch.
> >
> > Actually, I have some concern about the length of checksum,
> > sizeof(struct erofs_super_block) could be changed in the
> > later version, it's bad for EROFS future scalablity.
> >
> > And I tend not to add another on-disk field to record
> > the size of erofs_super_block as well, because the old
> > Linux kernel cannot handle more about the new size,
> > so it has little use except for checksum calculation.
> >
> > Few hours ago, I discussed with Chao about this concern,
> > I think this feature can be changed to do multiple-block
> > checksum at the mount time, e.g:
> >  - for small images, we can check the whole image once
> >    at the mount time;
> >  - for the large image, we can check the superblock
> >    at the mount time, the rest can be handled by
> >    block-based verification layer.
> >
> > But we agreed that don't add this for this round
> > since it's quite a new feature.
> >
> > All in all, it's a new feature since we are addressing moving
> > out of staging for this round. I tend to postpone this feature
> > for now. I understand that you are very interested in EROFS.
> > Considering EROFS current staging status, it's not such a place
> > to add new features at all! I have marked your patch down and
> > I will work with you later. Hope to get your understanding...
> >
> > Thanks,
> > Gao Xiang
> >
> > > ---
> > >  include/erofs/config.h |  1 +
> > >  include/erofs_fs.h     | 10 ++++++++
> > >  mkfs/main.c            | 64
> > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > index 05fe6b2..40cd466 100644
> > > --- a/include/erofs/config.h
> > > +++ b/include/erofs/config.h
> > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > >       char *c_src_path;
> > >       char *c_compr_alg_master;
> > >       int c_compr_level_master;
> > > +     int c_feature_flags;
> > >  };
> > >
> > >  extern struct erofs_configure cfg;
> > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > index 601b477..9ac2635 100644
> > > --- a/include/erofs_fs.h
> > > +++ b/include/erofs_fs.h
> > > @@ -20,6 +20,16 @@
> > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > >  #define EROFS_ALL_REQUIREMENTS
> >  EROFS_REQUIREMENT_LZ4_0PADDING
> > >
> > > +/*
> > > + * feature definations.
> > > + */
> > > +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM
> > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > +
> > > +
> > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > +
> > >  struct erofs_super_block {
> > >  /*  0 */__le32 magic;           /* in the little endian */
> > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > index f127fe1..355fd2c 100644
> > > --- a/mkfs/main.c
> > > +++ b/mkfs/main.c
> > > @@ -31,6 +31,45 @@ static void usage(void)
> > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > >  }
> > >
> > > +#define CRCPOLY      0x82F63B78
> > > +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)
> > > +{
> > > +     int i;
> > > +     u32 crc = seed;
> > > +
> > > +     while (len--) {
> > > +             crc ^= *in++;
> > > +             for (i = 0; i < 8; i++) {
> > > +                     crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
> > > +             }
> > > +     }
> > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > +     return crc;
> > > +}
> > > +
> > > +char *feature_opts[] = {
> > > +     "nosbcrc", NULL
> > > +};
> > > +#define O_SB_CKSUM   0
> > > +
> > > +static int parse_feature_subopts(char *opts)
> > > +{
> > > +     char *arg;
> > > +
> > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > +     while (*opts != '\0') {
> > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > +             case O_SB_CKSUM:
> > > +                     cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);
> > > +                     break;
> > > +             default:
> > > +                     erofs_err("incorrect suboption");
> > > +                     return -EINVAL;
> > > +             }
> > > +     }
> > > +     return 0;
> > > +}
> > > +
> > >  static int parse_extended_opts(const char *opts)
> > >  {
> > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >  {
> > >       int opt, i;
> > >
> > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > >               switch (opt) {
> > >               case 'z':
> > >                       if (!optarg) {
> > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >                               return opt;
> > >                       break;
> > >
> > > +             case 'O':
> > > +                     opt = parse_feature_subopts(optarg);
> > > +                     if (opt)
> > > +                             return opt;
> > > +                     break;
> > > +
> > >               default: /* '?' */
> > >                       return -EINVAL;
> > >               }
> > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >       return 0;
> > >  }
> > >
> > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > +{
> > > +     u32 crc;
> > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > +                 sizeof(struct erofs_super_block));
> > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > +     return crc;
> > > +}
> > > +
> > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > >                                 erofs_nid_t root_nid)
> > >  {
> > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > erofs_buffer_head *bh,
> > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > >               .xattr_blkaddr = 0,
> > >               .requirements = cpu_to_le32(sbi.requirements),
> > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > >       };
> > >       const unsigned int sb_blksize =
> > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > erofs_buffer_head *bh,
> > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > >       sb.root_nid     = cpu_to_le16(root_nid);
> > >
> > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > > +             sb.checksum = 0;
> > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > +             sb.checksum = cpu_to_le32(crc);
> > > +     }
> > > +
> > >       buf = calloc(sb_blksize, 1);
> > >       if (!buf) {
> > >               erofs_err("Failed to allocate memory for sb: %s",
> > > --
> > > 2.9.3
> > >
> >

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24 14:56   ` Pratik Shinde
  2019-08-24 15:16     ` Gao Xiang via Linux-erofs
@ 2019-10-06  5:39     ` Gao Xiang via Linux-erofs
  2019-10-09  6:29       ` Pratik Shinde
  1 sibling, 1 reply; 19+ messages in thread
From: Gao Xiang via Linux-erofs @ 2019-10-06  5:39 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: linux-erofs, miaoxie

Hi Pratik,

On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> Hi Gao,
> 
> I completely understand your concern.You can drop this patch for now.
> Once erofs makes it 'fs/' please do reconsider implementing it.

I think we can work on this pending feature for v5.5 now.
My idea is to add an extra field in erofs_super_block to
indicate the number of blocks (4k) for checking.

So for small images, this feature can checksum the whole image at mount time,
and for large images, this feature can be used to checksum the super block only
(and then use verficiation subsystem to verify on-the-fly in the future...)

The following workflow is for erofs-utils, I think it's
 1) erofs_mkfs_update_super_block with checksum = 0
 2) erofs_bflush(NULL)
 3) reread the corresponding blocks and calculate checksum;
 4) write checksum to erofs_super_block;

Does it sound reasonable? and do you still have interest and
time for this? Looking forword to your reply...

Thanks,
Gao Xiang

> 
> One more thing, can we still send non feature patches?
> 
> --Pratik
> 
> 
> On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com> wrote:
> 
> > Hi Pratik,
> >
> > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > Adding code for superblock checksum calculation.
> > >
> > > incorporated the changes suggested in previous patch.
> > >
> > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> >
> > Thanks for your v2 patch.
> >
> > Actually, I have some concern about the length of checksum,
> > sizeof(struct erofs_super_block) could be changed in the
> > later version, it's bad for EROFS future scalablity.
> >
> > And I tend not to add another on-disk field to record
> > the size of erofs_super_block as well, because the old
> > Linux kernel cannot handle more about the new size,
> > so it has little use except for checksum calculation.
> >
> > Few hours ago, I discussed with Chao about this concern,
> > I think this feature can be changed to do multiple-block
> > checksum at the mount time, e.g:
> >  - for small images, we can check the whole image once
> >    at the mount time;
> >  - for the large image, we can check the superblock
> >    at the mount time, the rest can be handled by
> >    block-based verification layer.
> >
> > But we agreed that don't add this for this round
> > since it's quite a new feature.
> >
> > All in all, it's a new feature since we are addressing moving
> > out of staging for this round. I tend to postpone this feature
> > for now. I understand that you are very interested in EROFS.
> > Considering EROFS current staging status, it's not such a place
> > to add new features at all! I have marked your patch down and
> > I will work with you later. Hope to get your understanding...
> >
> > Thanks,
> > Gao Xiang
> >
> > > ---
> > >  include/erofs/config.h |  1 +
> > >  include/erofs_fs.h     | 10 ++++++++
> > >  mkfs/main.c            | 64
> > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > index 05fe6b2..40cd466 100644
> > > --- a/include/erofs/config.h
> > > +++ b/include/erofs/config.h
> > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > >       char *c_src_path;
> > >       char *c_compr_alg_master;
> > >       int c_compr_level_master;
> > > +     int c_feature_flags;
> > >  };
> > >
> > >  extern struct erofs_configure cfg;
> > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > index 601b477..9ac2635 100644
> > > --- a/include/erofs_fs.h
> > > +++ b/include/erofs_fs.h
> > > @@ -20,6 +20,16 @@
> > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > >  #define EROFS_ALL_REQUIREMENTS
> >  EROFS_REQUIREMENT_LZ4_0PADDING
> > >
> > > +/*
> > > + * feature definations.
> > > + */
> > > +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM
> > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > +
> > > +
> > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > +
> > >  struct erofs_super_block {
> > >  /*  0 */__le32 magic;           /* in the little endian */
> > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > index f127fe1..355fd2c 100644
> > > --- a/mkfs/main.c
> > > +++ b/mkfs/main.c
> > > @@ -31,6 +31,45 @@ static void usage(void)
> > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > >  }
> > >
> > > +#define CRCPOLY      0x82F63B78
> > > +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)
> > > +{
> > > +     int i;
> > > +     u32 crc = seed;
> > > +
> > > +     while (len--) {
> > > +             crc ^= *in++;
> > > +             for (i = 0; i < 8; i++) {
> > > +                     crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
> > > +             }
> > > +     }
> > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > +     return crc;
> > > +}
> > > +
> > > +char *feature_opts[] = {
> > > +     "nosbcrc", NULL
> > > +};
> > > +#define O_SB_CKSUM   0
> > > +
> > > +static int parse_feature_subopts(char *opts)
> > > +{
> > > +     char *arg;
> > > +
> > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > +     while (*opts != '\0') {
> > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > +             case O_SB_CKSUM:
> > > +                     cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);
> > > +                     break;
> > > +             default:
> > > +                     erofs_err("incorrect suboption");
> > > +                     return -EINVAL;
> > > +             }
> > > +     }
> > > +     return 0;
> > > +}
> > > +
> > >  static int parse_extended_opts(const char *opts)
> > >  {
> > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >  {
> > >       int opt, i;
> > >
> > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > >               switch (opt) {
> > >               case 'z':
> > >                       if (!optarg) {
> > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >                               return opt;
> > >                       break;
> > >
> > > +             case 'O':
> > > +                     opt = parse_feature_subopts(optarg);
> > > +                     if (opt)
> > > +                             return opt;
> > > +                     break;
> > > +
> > >               default: /* '?' */
> > >                       return -EINVAL;
> > >               }
> > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >       return 0;
> > >  }
> > >
> > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > +{
> > > +     u32 crc;
> > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > +                 sizeof(struct erofs_super_block));
> > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > +     return crc;
> > > +}
> > > +
> > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > >                                 erofs_nid_t root_nid)
> > >  {
> > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > erofs_buffer_head *bh,
> > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > >               .xattr_blkaddr = 0,
> > >               .requirements = cpu_to_le32(sbi.requirements),
> > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > >       };
> > >       const unsigned int sb_blksize =
> > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > erofs_buffer_head *bh,
> > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > >       sb.root_nid     = cpu_to_le16(root_nid);
> > >
> > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > > +             sb.checksum = 0;
> > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > +             sb.checksum = cpu_to_le32(crc);
> > > +     }
> > > +
> > >       buf = calloc(sb_blksize, 1);
> > >       if (!buf) {
> > >               erofs_err("Failed to allocate memory for sb: %s",
> > > --
> > > 2.9.3
> > >
> >

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-10-06  5:39     ` Gao Xiang via Linux-erofs
@ 2019-10-09  6:29       ` Pratik Shinde
  2019-10-09  6:57         ` Gao Xiang
  0 siblings, 1 reply; 19+ messages in thread
From: Pratik Shinde @ 2019-10-09  6:29 UTC (permalink / raw)
  To: Gao Xiang; +Cc: linux-erofs, miaoxie

[-- Attachment #1: Type: text/plain, Size: 9145 bytes --]

Hi Gao,

Yes I can work on it. Sorry I missed this mail. I think your approach is
good. Let me go through it one more time and reply back.

--Pratik

On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, <hsiangkao@aol.com> wrote:

> Hi Pratik,
>
> On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> > Hi Gao,
> >
> > I completely understand your concern.You can drop this patch for now.
> > Once erofs makes it 'fs/' please do reconsider implementing it.
>
> I think we can work on this pending feature for v5.5 now.
> My idea is to add an extra field in erofs_super_block to
> indicate the number of blocks (4k) for checking.
>
> So for small images, this feature can checksum the whole image at mount
> time,
> and for large images, this feature can be used to checksum the super block
> only
> (and then use verficiation subsystem to verify on-the-fly in the future...)
>
> The following workflow is for erofs-utils, I think it's
>  1) erofs_mkfs_update_super_block with checksum = 0
>  2) erofs_bflush(NULL)
>  3) reread the corresponding blocks and calculate checksum;
>  4) write checksum to erofs_super_block;
>
> Does it sound reasonable? and do you still have interest and
> time for this? Looking forword to your reply...
>
> Thanks,
> Gao Xiang
>
> >
> > One more thing, can we still send non feature patches?
> >
> > --Pratik
> >
> >
> > On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com> wrote:
> >
> > > Hi Pratik,
> > >
> > > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > > Adding code for superblock checksum calculation.
> > > >
> > > > incorporated the changes suggested in previous patch.
> > > >
> > > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> > >
> > > Thanks for your v2 patch.
> > >
> > > Actually, I have some concern about the length of checksum,
> > > sizeof(struct erofs_super_block) could be changed in the
> > > later version, it's bad for EROFS future scalablity.
> > >
> > > And I tend not to add another on-disk field to record
> > > the size of erofs_super_block as well, because the old
> > > Linux kernel cannot handle more about the new size,
> > > so it has little use except for checksum calculation.
> > >
> > > Few hours ago, I discussed with Chao about this concern,
> > > I think this feature can be changed to do multiple-block
> > > checksum at the mount time, e.g:
> > >  - for small images, we can check the whole image once
> > >    at the mount time;
> > >  - for the large image, we can check the superblock
> > >    at the mount time, the rest can be handled by
> > >    block-based verification layer.
> > >
> > > But we agreed that don't add this for this round
> > > since it's quite a new feature.
> > >
> > > All in all, it's a new feature since we are addressing moving
> > > out of staging for this round. I tend to postpone this feature
> > > for now. I understand that you are very interested in EROFS.
> > > Considering EROFS current staging status, it's not such a place
> > > to add new features at all! I have marked your patch down and
> > > I will work with you later. Hope to get your understanding...
> > >
> > > Thanks,
> > > Gao Xiang
> > >
> > > > ---
> > > >  include/erofs/config.h |  1 +
> > > >  include/erofs_fs.h     | 10 ++++++++
> > > >  mkfs/main.c            | 64
> > > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > > index 05fe6b2..40cd466 100644
> > > > --- a/include/erofs/config.h
> > > > +++ b/include/erofs/config.h
> > > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > > >       char *c_src_path;
> > > >       char *c_compr_alg_master;
> > > >       int c_compr_level_master;
> > > > +     int c_feature_flags;
> > > >  };
> > > >
> > > >  extern struct erofs_configure cfg;
> > > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > > index 601b477..9ac2635 100644
> > > > --- a/include/erofs_fs.h
> > > > +++ b/include/erofs_fs.h
> > > > @@ -20,6 +20,16 @@
> > > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > > >  #define EROFS_ALL_REQUIREMENTS
> > >  EROFS_REQUIREMENT_LZ4_0PADDING
> > > >
> > > > +/*
> > > > + * feature definations.
> > > > + */
> > > > +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM
> > > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > > +
> > > > +
> > > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > > +
> > > >  struct erofs_super_block {
> > > >  /*  0 */__le32 magic;           /* in the little endian */
> > > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > > index f127fe1..355fd2c 100644
> > > > --- a/mkfs/main.c
> > > > +++ b/mkfs/main.c
> > > > @@ -31,6 +31,45 @@ static void usage(void)
> > > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > > >  }
> > > >
> > > > +#define CRCPOLY      0x82F63B78
> > > > +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t
> len)
> > > > +{
> > > > +     int i;
> > > > +     u32 crc = seed;
> > > > +
> > > > +     while (len--) {
> > > > +             crc ^= *in++;
> > > > +             for (i = 0; i < 8; i++) {
> > > > +                     crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
> > > > +             }
> > > > +     }
> > > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > > +     return crc;
> > > > +}
> > > > +
> > > > +char *feature_opts[] = {
> > > > +     "nosbcrc", NULL
> > > > +};
> > > > +#define O_SB_CKSUM   0
> > > > +
> > > > +static int parse_feature_subopts(char *opts)
> > > > +{
> > > > +     char *arg;
> > > > +
> > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > +     while (*opts != '\0') {
> > > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > > +             case O_SB_CKSUM:
> > > > +                     cfg.c_feature_flags |=
> (~EROFS_FEATURE_SB_CHKSUM);
> > > > +                     break;
> > > > +             default:
> > > > +                     erofs_err("incorrect suboption");
> > > > +                     return -EINVAL;
> > > > +             }
> > > > +     }
> > > > +     return 0;
> > > > +}
> > > > +
> > > >  static int parse_extended_opts(const char *opts)
> > > >  {
> > > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char
> > > *argv[])
> > > >  {
> > > >       int opt, i;
> > > >
> > > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > > >               switch (opt) {
> > > >               case 'z':
> > > >                       if (!optarg) {
> > > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char
> > > *argv[])
> > > >                               return opt;
> > > >                       break;
> > > >
> > > > +             case 'O':
> > > > +                     opt = parse_feature_subopts(optarg);
> > > > +                     if (opt)
> > > > +                             return opt;
> > > > +                     break;
> > > > +
> > > >               default: /* '?' */
> > > >                       return -EINVAL;
> > > >               }
> > > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char
> > > *argv[])
> > > >       return 0;
> > > >  }
> > > >
> > > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > > +{
> > > > +     u32 crc;
> > > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > > +                 sizeof(struct erofs_super_block));
> > > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > > +     return crc;
> > > > +}
> > > > +
> > > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > > >                                 erofs_nid_t root_nid)
> > > >  {
> > > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > > erofs_buffer_head *bh,
> > > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > > >               .xattr_blkaddr = 0,
> > > >               .requirements = cpu_to_le32(sbi.requirements),
> > > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > > >       };
> > > >       const unsigned int sb_blksize =
> > > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > > erofs_buffer_head *bh,
> > > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > > >       sb.root_nid     = cpu_to_le16(root_nid);
> > > >
> > > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > > > +             sb.checksum = 0;
> > > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > > +             sb.checksum = cpu_to_le32(crc);
> > > > +     }
> > > > +
> > > >       buf = calloc(sb_blksize, 1);
> > > >       if (!buf) {
> > > >               erofs_err("Failed to allocate memory for sb: %s",
> > > > --
> > > > 2.9.3
> > > >
> > >
>

[-- Attachment #2: Type: text/html, Size: 12872 bytes --]

<div dir="auto">Hi Gao,<div dir="auto"><br></div><div dir="auto">Yes I can work on it. Sorry I missed this mail. I think your approach is good. Let me go through it one more time and reply back.</div><div dir="auto"><br></div><div dir="auto">--Pratik</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, &lt;<a href="mailto:hsiangkao@aol.com" target="_blank" rel="noreferrer">hsiangkao@aol.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Pratik,<br>
<br>
On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:<br>
&gt; Hi Gao,<br>
&gt; <br>
&gt; I completely understand your concern.You can drop this patch for now.<br>
&gt; Once erofs makes it &#39;fs/&#39; please do reconsider implementing it.<br>
<br>
I think we can work on this pending feature for v5.5 now.<br>
My idea is to add an extra field in erofs_super_block to<br>
indicate the number of blocks (4k) for checking.<br>
<br>
So for small images, this feature can checksum the whole image at mount time,<br>
and for large images, this feature can be used to checksum the super block only<br>
(and then use verficiation subsystem to verify on-the-fly in the future...)<br>
<br>
The following workflow is for erofs-utils, I think it&#39;s<br>
 1) erofs_mkfs_update_super_block with checksum = 0<br>
 2) erofs_bflush(NULL)<br>
 3) reread the corresponding blocks and calculate checksum;<br>
 4) write checksum to erofs_super_block;<br>
<br>
Does it sound reasonable? and do you still have interest and<br>
time for this? Looking forword to your reply...<br>
<br>
Thanks,<br>
Gao Xiang<br>
<br>
&gt; <br>
&gt; One more thing, can we still send non feature patches?<br>
&gt; <br>
&gt; --Pratik<br>
&gt; <br>
&gt; <br>
&gt; On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, &lt;<a href="mailto:hsiangkao@aol.com" rel="noreferrer noreferrer" target="_blank">hsiangkao@aol.com</a>&gt; wrote:<br>
&gt; <br>
&gt; &gt; Hi Pratik,<br>
&gt; &gt;<br>
&gt; &gt; On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:<br>
&gt; &gt; &gt; Adding code for superblock checksum calculation.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; incorporated the changes suggested in previous patch.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Signed-off-by: Pratik Shinde &lt;<a href="mailto:pratikshinde320@gmail.com" rel="noreferrer noreferrer" target="_blank">pratikshinde320@gmail.com</a>&gt;<br>
&gt; &gt;<br>
&gt; &gt; Thanks for your v2 patch.<br>
&gt; &gt;<br>
&gt; &gt; Actually, I have some concern about the length of checksum,<br>
&gt; &gt; sizeof(struct erofs_super_block) could be changed in the<br>
&gt; &gt; later version, it&#39;s bad for EROFS future scalablity.<br>
&gt; &gt;<br>
&gt; &gt; And I tend not to add another on-disk field to record<br>
&gt; &gt; the size of erofs_super_block as well, because the old<br>
&gt; &gt; Linux kernel cannot handle more about the new size,<br>
&gt; &gt; so it has little use except for checksum calculation.<br>
&gt; &gt;<br>
&gt; &gt; Few hours ago, I discussed with Chao about this concern,<br>
&gt; &gt; I think this feature can be changed to do multiple-block<br>
&gt; &gt; checksum at the mount time, e.g:<br>
&gt; &gt;  - for small images, we can check the whole image once<br>
&gt; &gt;    at the mount time;<br>
&gt; &gt;  - for the large image, we can check the superblock<br>
&gt; &gt;    at the mount time, the rest can be handled by<br>
&gt; &gt;    block-based verification layer.<br>
&gt; &gt;<br>
&gt; &gt; But we agreed that don&#39;t add this for this round<br>
&gt; &gt; since it&#39;s quite a new feature.<br>
&gt; &gt;<br>
&gt; &gt; All in all, it&#39;s a new feature since we are addressing moving<br>
&gt; &gt; out of staging for this round. I tend to postpone this feature<br>
&gt; &gt; for now. I understand that you are very interested in EROFS.<br>
&gt; &gt; Considering EROFS current staging status, it&#39;s not such a place<br>
&gt; &gt; to add new features at all! I have marked your patch down and<br>
&gt; &gt; I will work with you later. Hope to get your understanding...<br>
&gt; &gt;<br>
&gt; &gt; Thanks,<br>
&gt; &gt; Gao Xiang<br>
&gt; &gt;<br>
&gt; &gt; &gt; ---<br>
&gt; &gt; &gt;  include/erofs/config.h |  1 +<br>
&gt; &gt; &gt;  include/erofs_fs.h     | 10 ++++++++<br>
&gt; &gt; &gt;  mkfs/main.c            | 64<br>
&gt; &gt; +++++++++++++++++++++++++++++++++++++++++++++++++-<br>
&gt; &gt; &gt;  3 files changed, 74 insertions(+), 1 deletion(-)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; diff --git a/include/erofs/config.h b/include/erofs/config.h<br>
&gt; &gt; &gt; index 05fe6b2..40cd466 100644<br>
&gt; &gt; &gt; --- a/include/erofs/config.h<br>
&gt; &gt; &gt; +++ b/include/erofs/config.h<br>
&gt; &gt; &gt; @@ -22,6 +22,7 @@ struct erofs_configure {<br>
&gt; &gt; &gt;       char *c_src_path;<br>
&gt; &gt; &gt;       char *c_compr_alg_master;<br>
&gt; &gt; &gt;       int c_compr_level_master;<br>
&gt; &gt; &gt; +     int c_feature_flags;<br>
&gt; &gt; &gt;  };<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;  extern struct erofs_configure cfg;<br>
&gt; &gt; &gt; diff --git a/include/erofs_fs.h b/include/erofs_fs.h<br>
&gt; &gt; &gt; index 601b477..9ac2635 100644<br>
&gt; &gt; &gt; --- a/include/erofs_fs.h<br>
&gt; &gt; &gt; +++ b/include/erofs_fs.h<br>
&gt; &gt; &gt; @@ -20,6 +20,16 @@<br>
&gt; &gt; &gt;  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001<br>
&gt; &gt; &gt;  #define EROFS_ALL_REQUIREMENTS<br>
&gt; &gt;  EROFS_REQUIREMENT_LZ4_0PADDING<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +/*<br>
&gt; &gt; &gt; + * feature definations.<br>
&gt; &gt; &gt; + */<br>
&gt; &gt; &gt; +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM<br>
&gt; &gt; &gt; +#define EROFS_FEATURE_SB_CHKSUM              0x0001<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \<br>
&gt; &gt; &gt; +     ( le32_to_cpu((super)-&gt;features) &amp; (mask) )<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;  struct erofs_super_block {<br>
&gt; &gt; &gt;  /*  0 */__le32 magic;           /* in the little endian */<br>
&gt; &gt; &gt;  /*  4 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt; &gt; &gt; diff --git a/mkfs/main.c b/mkfs/main.c<br>
&gt; &gt; &gt; index f127fe1..355fd2c 100644<br>
&gt; &gt; &gt; --- a/mkfs/main.c<br>
&gt; &gt; &gt; +++ b/mkfs/main.c<br>
&gt; &gt; &gt; @@ -31,6 +31,45 @@ static void usage(void)<br>
&gt; &gt; &gt;       fprintf(stderr, &quot; -EX[,...] X=extended options\n&quot;);<br>
&gt; &gt; &gt;  }<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +#define CRCPOLY      0x82F63B78<br>
&gt; &gt; &gt; +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t len)<br>
&gt; &gt; &gt; +{<br>
&gt; &gt; &gt; +     int i;<br>
&gt; &gt; &gt; +     u32 crc = seed;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +     while (len--) {<br>
&gt; &gt; &gt; +             crc ^= *in++;<br>
&gt; &gt; &gt; +             for (i = 0; i &lt; 8; i++) {<br>
&gt; &gt; &gt; +                     crc = (crc &gt;&gt; 1) ^ ((crc &amp; 1) ? CRCPOLY : 0);<br>
&gt; &gt; &gt; +             }<br>
&gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; +     erofs_dump(&quot;calculated crc: 0x%x\n&quot;, crc);<br>
&gt; &gt; &gt; +     return crc;<br>
&gt; &gt; &gt; +}<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +char *feature_opts[] = {<br>
&gt; &gt; &gt; +     &quot;nosbcrc&quot;, NULL<br>
&gt; &gt; &gt; +};<br>
&gt; &gt; &gt; +#define O_SB_CKSUM   0<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +static int parse_feature_subopts(char *opts)<br>
&gt; &gt; &gt; +{<br>
&gt; &gt; &gt; +     char *arg;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; &gt; &gt; +     while (*opts != &#39;\0&#39;) {<br>
&gt; &gt; &gt; +             switch(getsubopt(&amp;opts, feature_opts, &amp;arg)) {<br>
&gt; &gt; &gt; +             case O_SB_CKSUM:<br>
&gt; &gt; &gt; +                     cfg.c_feature_flags |= (~EROFS_FEATURE_SB_CHKSUM);<br>
&gt; &gt; &gt; +                     break;<br>
&gt; &gt; &gt; +             default:<br>
&gt; &gt; &gt; +                     erofs_err(&quot;incorrect suboption&quot;);<br>
&gt; &gt; &gt; +                     return -EINVAL;<br>
&gt; &gt; &gt; +             }<br>
&gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; +     return 0;<br>
&gt; &gt; &gt; +}<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;  static int parse_extended_opts(const char *opts)<br>
&gt; &gt; &gt;  {<br>
&gt; &gt; &gt;  #define MATCH_EXTENTED_OPT(opt, token, keylen) \<br>
&gt; &gt; &gt; @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt; &gt; *argv[])<br>
&gt; &gt; &gt;  {<br>
&gt; &gt; &gt;       int opt, i;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; -     while ((opt = getopt(argc, argv, &quot;d:z:E:&quot;)) != -1) {<br>
&gt; &gt; &gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; &gt; &gt; +     while ((opt = getopt(argc, argv, &quot;d:z:E:o:&quot;)) != -1) {<br>
&gt; &gt; &gt;               switch (opt) {<br>
&gt; &gt; &gt;               case &#39;z&#39;:<br>
&gt; &gt; &gt;                       if (!optarg) {<br>
&gt; &gt; &gt; @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt; &gt; *argv[])<br>
&gt; &gt; &gt;                               return opt;<br>
&gt; &gt; &gt;                       break;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +             case &#39;O&#39;:<br>
&gt; &gt; &gt; +                     opt = parse_feature_subopts(optarg);<br>
&gt; &gt; &gt; +                     if (opt)<br>
&gt; &gt; &gt; +                             return opt;<br>
&gt; &gt; &gt; +                     break;<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;               default: /* &#39;?&#39; */<br>
&gt; &gt; &gt;                       return -EINVAL;<br>
&gt; &gt; &gt;               }<br>
&gt; &gt; &gt; @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt; &gt; *argv[])<br>
&gt; &gt; &gt;       return 0;<br>
&gt; &gt; &gt;  }<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +u32 erofs_superblock_checksum(struct erofs_super_block *sb)<br>
&gt; &gt; &gt; +{<br>
&gt; &gt; &gt; +     u32 crc;<br>
&gt; &gt; &gt; +     crc = crc32c(~0, (const unsigned char *)sb,<br>
&gt; &gt; &gt; +                 sizeof(struct erofs_super_block));<br>
&gt; &gt; &gt; +     erofs_dump(&quot;superblock checksum: 0x%x\n&quot;, crc);<br>
&gt; &gt; &gt; +     return crc;<br>
&gt; &gt; &gt; +}<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt; &gt; &gt;                                 erofs_nid_t root_nid)<br>
&gt; &gt; &gt;  {<br>
&gt; &gt; &gt; @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct<br>
&gt; &gt; erofs_buffer_head *bh,<br>
&gt; &gt; &gt;               .meta_blkaddr  = sbi.meta_blkaddr,<br>
&gt; &gt; &gt;               .xattr_blkaddr = 0,<br>
&gt; &gt; &gt;               .requirements = cpu_to_le32(sbi.requirements),<br>
&gt; &gt; &gt; +             .features = cpu_to_le32(cfg.c_feature_flags),<br>
&gt; &gt; &gt;       };<br>
&gt; &gt; &gt;       const unsigned int sb_blksize =<br>
&gt; &gt; &gt;               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);<br>
&gt; &gt; &gt; @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct<br>
&gt; &gt; erofs_buffer_head *bh,<br>
&gt; &gt; &gt;       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));<br>
&gt; &gt; &gt;       sb.root_nid     = cpu_to_le16(root_nid);<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +     if (EROFS_HAS_COMPAT_FEATURE(&amp;sb, EROFS_FEATURE_SB_CHKSUM)) {<br>
&gt; &gt; &gt; +             sb.checksum = 0;<br>
&gt; &gt; &gt; +             u32 crc = erofs_superblock_checksum(&amp;sb);<br>
&gt; &gt; &gt; +             sb.checksum = cpu_to_le32(crc);<br>
&gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;       buf = calloc(sb_blksize, 1);<br>
&gt; &gt; &gt;       if (!buf) {<br>
&gt; &gt; &gt;               erofs_err(&quot;Failed to allocate memory for sb: %s&quot;,<br>
&gt; &gt; &gt; --<br>
&gt; &gt; &gt; 2.9.3<br>
&gt; &gt; &gt;<br>
&gt; &gt;<br>
</blockquote></div>

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-10-09  6:29       ` Pratik Shinde
@ 2019-10-09  6:57         ` Gao Xiang
  2019-10-09  8:24           ` Pratik Shinde
  0 siblings, 1 reply; 19+ messages in thread
From: Gao Xiang @ 2019-10-09  6:57 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: miaoxie, linux-erofs

Hi Pratik,

On Wed, Oct 09, 2019 at 11:59:01AM +0530, Pratik Shinde wrote:
> Hi Gao,
> 
> Yes I can work on it. Sorry I missed this mail. I think your approach is
> good. Let me go through it one more time and reply back.

Thanks for your reply and interest :)
I think we can complete all pending features together
if you have some time on this stuff. (fsdebug utility is
on the way as well...)

BTW, I'm now investigating new high CR algorithm (very likely
XZ) as well, it will be likely a RFC version in this round for
wider scenarios and later decompression subsystem.

Preliminary TODO lists will be discussed in this year China
Linux Storage & Filesystem workshop (next week) and will be
posted to mailing lists for further wider discussion (if more
folks have interest in developing it) as well. :)

Thanks,
Gao Xiang

> 
> --Pratik
> 
> On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, <hsiangkao@aol.com> wrote:
> 
> > Hi Pratik,
> >
> > On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> > > Hi Gao,
> > >
> > > I completely understand your concern.You can drop this patch for now.
> > > Once erofs makes it 'fs/' please do reconsider implementing it.
> >
> > I think we can work on this pending feature for v5.5 now.
> > My idea is to add an extra field in erofs_super_block to
> > indicate the number of blocks (4k) for checking.
> >
> > So for small images, this feature can checksum the whole image at mount
> > time,
> > and for large images, this feature can be used to checksum the super block
> > only
> > (and then use verficiation subsystem to verify on-the-fly in the future...)
> >
> > The following workflow is for erofs-utils, I think it's
> >  1) erofs_mkfs_update_super_block with checksum = 0
> >  2) erofs_bflush(NULL)
> >  3) reread the corresponding blocks and calculate checksum;
> >  4) write checksum to erofs_super_block;
> >
> > Does it sound reasonable? and do you still have interest and
> > time for this? Looking forword to your reply...
> >
> > Thanks,
> > Gao Xiang
> >
> > >
> > > One more thing, can we still send non feature patches?
> > >
> > > --Pratik
> > >
> > >
> > > On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com> wrote:
> > >
> > > > Hi Pratik,
> > > >
> > > > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > > > Adding code for superblock checksum calculation.
> > > > >
> > > > > incorporated the changes suggested in previous patch.
> > > > >
> > > > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> > > >
> > > > Thanks for your v2 patch.
> > > >
> > > > Actually, I have some concern about the length of checksum,
> > > > sizeof(struct erofs_super_block) could be changed in the
> > > > later version, it's bad for EROFS future scalablity.
> > > >
> > > > And I tend not to add another on-disk field to record
> > > > the size of erofs_super_block as well, because the old
> > > > Linux kernel cannot handle more about the new size,
> > > > so it has little use except for checksum calculation.
> > > >
> > > > Few hours ago, I discussed with Chao about this concern,
> > > > I think this feature can be changed to do multiple-block
> > > > checksum at the mount time, e.g:
> > > >  - for small images, we can check the whole image once
> > > >    at the mount time;
> > > >  - for the large image, we can check the superblock
> > > >    at the mount time, the rest can be handled by
> > > >    block-based verification layer.
> > > >
> > > > But we agreed that don't add this for this round
> > > > since it's quite a new feature.
> > > >
> > > > All in all, it's a new feature since we are addressing moving
> > > > out of staging for this round. I tend to postpone this feature
> > > > for now. I understand that you are very interested in EROFS.
> > > > Considering EROFS current staging status, it's not such a place
> > > > to add new features at all! I have marked your patch down and
> > > > I will work with you later. Hope to get your understanding...
> > > >
> > > > Thanks,
> > > > Gao Xiang
> > > >
> > > > > ---
> > > > >  include/erofs/config.h |  1 +
> > > > >  include/erofs_fs.h     | 10 ++++++++
> > > > >  mkfs/main.c            | 64
> > > > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > > > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > > > index 05fe6b2..40cd466 100644
> > > > > --- a/include/erofs/config.h
> > > > > +++ b/include/erofs/config.h
> > > > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > > > >       char *c_src_path;
> > > > >       char *c_compr_alg_master;
> > > > >       int c_compr_level_master;
> > > > > +     int c_feature_flags;
> > > > >  };
> > > > >
> > > > >  extern struct erofs_configure cfg;
> > > > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > > > index 601b477..9ac2635 100644
> > > > > --- a/include/erofs_fs.h
> > > > > +++ b/include/erofs_fs.h
> > > > > @@ -20,6 +20,16 @@
> > > > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > > > >  #define EROFS_ALL_REQUIREMENTS
> > > >  EROFS_REQUIREMENT_LZ4_0PADDING
> > > > >
> > > > > +/*
> > > > > + * feature definations.
> > > > > + */
> > > > > +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM
> > > > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > > > +
> > > > > +
> > > > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > > > +
> > > > >  struct erofs_super_block {
> > > > >  /*  0 */__le32 magic;           /* in the little endian */
> > > > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > > > index f127fe1..355fd2c 100644
> > > > > --- a/mkfs/main.c
> > > > > +++ b/mkfs/main.c
> > > > > @@ -31,6 +31,45 @@ static void usage(void)
> > > > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > > > >  }
> > > > >
> > > > > +#define CRCPOLY      0x82F63B78
> > > > > +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t
> > len)
> > > > > +{
> > > > > +     int i;
> > > > > +     u32 crc = seed;
> > > > > +
> > > > > +     while (len--) {
> > > > > +             crc ^= *in++;
> > > > > +             for (i = 0; i < 8; i++) {
> > > > > +                     crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY : 0);
> > > > > +             }
> > > > > +     }
> > > > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > > > +     return crc;
> > > > > +}
> > > > > +
> > > > > +char *feature_opts[] = {
> > > > > +     "nosbcrc", NULL
> > > > > +};
> > > > > +#define O_SB_CKSUM   0
> > > > > +
> > > > > +static int parse_feature_subopts(char *opts)
> > > > > +{
> > > > > +     char *arg;
> > > > > +
> > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > +     while (*opts != '\0') {
> > > > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > > > +             case O_SB_CKSUM:
> > > > > +                     cfg.c_feature_flags |=
> > (~EROFS_FEATURE_SB_CHKSUM);
> > > > > +                     break;
> > > > > +             default:
> > > > > +                     erofs_err("incorrect suboption");
> > > > > +                     return -EINVAL;
> > > > > +             }
> > > > > +     }
> > > > > +     return 0;
> > > > > +}
> > > > > +
> > > > >  static int parse_extended_opts(const char *opts)
> > > > >  {
> > > > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char
> > > > *argv[])
> > > > >  {
> > > > >       int opt, i;
> > > > >
> > > > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > > > >               switch (opt) {
> > > > >               case 'z':
> > > > >                       if (!optarg) {
> > > > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char
> > > > *argv[])
> > > > >                               return opt;
> > > > >                       break;
> > > > >
> > > > > +             case 'O':
> > > > > +                     opt = parse_feature_subopts(optarg);
> > > > > +                     if (opt)
> > > > > +                             return opt;
> > > > > +                     break;
> > > > > +
> > > > >               default: /* '?' */
> > > > >                       return -EINVAL;
> > > > >               }
> > > > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char
> > > > *argv[])
> > > > >       return 0;
> > > > >  }
> > > > >
> > > > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > > > +{
> > > > > +     u32 crc;
> > > > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > > > +                 sizeof(struct erofs_super_block));
> > > > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > > > +     return crc;
> > > > > +}
> > > > > +
> > > > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > > > >                                 erofs_nid_t root_nid)
> > > > >  {
> > > > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > > > erofs_buffer_head *bh,
> > > > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > > > >               .xattr_blkaddr = 0,
> > > > >               .requirements = cpu_to_le32(sbi.requirements),
> > > > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > > > >       };
> > > > >       const unsigned int sb_blksize =
> > > > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > > > erofs_buffer_head *bh,
> > > > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > > > >       sb.root_nid     = cpu_to_le16(root_nid);
> > > > >
> > > > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > > > > +             sb.checksum = 0;
> > > > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > > > +             sb.checksum = cpu_to_le32(crc);
> > > > > +     }
> > > > > +
> > > > >       buf = calloc(sb_blksize, 1);
> > > > >       if (!buf) {
> > > > >               erofs_err("Failed to allocate memory for sb: %s",
> > > > > --
> > > > > 2.9.3
> > > > >
> > > >
> >

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-10-09  6:57         ` Gao Xiang
@ 2019-10-09  8:24           ` Pratik Shinde
  2019-10-09  8:48             ` Gao Xiang
  0 siblings, 1 reply; 19+ messages in thread
From: Pratik Shinde @ 2019-10-09  8:24 UTC (permalink / raw)
  To: Gao Xiang; +Cc: miaoxie, linux-erofs

[-- Attachment #1: Type: text/plain, Size: 11063 bytes --]

Hello Gao,

Yes I would like to work on pending features.
Also please let us know the new development items.

--Pratik

On Wed, 9 Oct, 2019, 12:24 PM Gao Xiang, <gaoxiang25@huawei.com> wrote:

> Hi Pratik,
>
> On Wed, Oct 09, 2019 at 11:59:01AM +0530, Pratik Shinde wrote:
> > Hi Gao,
> >
> > Yes I can work on it. Sorry I missed this mail. I think your approach is
> > good. Let me go through it one more time and reply back.
>
> Thanks for your reply and interest :)
> I think we can complete all pending features together
> if you have some time on this stuff. (fsdebug utility is
> on the way as well...)
>
> BTW, I'm now investigating new high CR algorithm (very likely
> XZ) as well, it will be likely a RFC version in this round for
> wider scenarios and later decompression subsystem.
>
> Preliminary TODO lists will be discussed in this year China
> Linux Storage & Filesystem workshop (next week) and will be
> posted to mailing lists for further wider discussion (if more
> folks have interest in developing it) as well. :)
>
> Thanks,
> Gao Xiang
>
> >
> > --Pratik
> >
> > On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, <hsiangkao@aol.com> wrote:
> >
> > > Hi Pratik,
> > >
> > > On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> > > > Hi Gao,
> > > >
> > > > I completely understand your concern.You can drop this patch for now.
> > > > Once erofs makes it 'fs/' please do reconsider implementing it.
> > >
> > > I think we can work on this pending feature for v5.5 now.
> > > My idea is to add an extra field in erofs_super_block to
> > > indicate the number of blocks (4k) for checking.
> > >
> > > So for small images, this feature can checksum the whole image at mount
> > > time,
> > > and for large images, this feature can be used to checksum the super
> block
> > > only
> > > (and then use verficiation subsystem to verify on-the-fly in the
> future...)
> > >
> > > The following workflow is for erofs-utils, I think it's
> > >  1) erofs_mkfs_update_super_block with checksum = 0
> > >  2) erofs_bflush(NULL)
> > >  3) reread the corresponding blocks and calculate checksum;
> > >  4) write checksum to erofs_super_block;
> > >
> > > Does it sound reasonable? and do you still have interest and
> > > time for this? Looking forword to your reply...
> > >
> > > Thanks,
> > > Gao Xiang
> > >
> > > >
> > > > One more thing, can we still send non feature patches?
> > > >
> > > > --Pratik
> > > >
> > > >
> > > > On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com> wrote:
> > > >
> > > > > Hi Pratik,
> > > > >
> > > > > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > > > > Adding code for superblock checksum calculation.
> > > > > >
> > > > > > incorporated the changes suggested in previous patch.
> > > > > >
> > > > > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> > > > >
> > > > > Thanks for your v2 patch.
> > > > >
> > > > > Actually, I have some concern about the length of checksum,
> > > > > sizeof(struct erofs_super_block) could be changed in the
> > > > > later version, it's bad for EROFS future scalablity.
> > > > >
> > > > > And I tend not to add another on-disk field to record
> > > > > the size of erofs_super_block as well, because the old
> > > > > Linux kernel cannot handle more about the new size,
> > > > > so it has little use except for checksum calculation.
> > > > >
> > > > > Few hours ago, I discussed with Chao about this concern,
> > > > > I think this feature can be changed to do multiple-block
> > > > > checksum at the mount time, e.g:
> > > > >  - for small images, we can check the whole image once
> > > > >    at the mount time;
> > > > >  - for the large image, we can check the superblock
> > > > >    at the mount time, the rest can be handled by
> > > > >    block-based verification layer.
> > > > >
> > > > > But we agreed that don't add this for this round
> > > > > since it's quite a new feature.
> > > > >
> > > > > All in all, it's a new feature since we are addressing moving
> > > > > out of staging for this round. I tend to postpone this feature
> > > > > for now. I understand that you are very interested in EROFS.
> > > > > Considering EROFS current staging status, it's not such a place
> > > > > to add new features at all! I have marked your patch down and
> > > > > I will work with you later. Hope to get your understanding...
> > > > >
> > > > > Thanks,
> > > > > Gao Xiang
> > > > >
> > > > > > ---
> > > > > >  include/erofs/config.h |  1 +
> > > > > >  include/erofs_fs.h     | 10 ++++++++
> > > > > >  mkfs/main.c            | 64
> > > > > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > > > > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > > > > >
> > > > > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > > > > index 05fe6b2..40cd466 100644
> > > > > > --- a/include/erofs/config.h
> > > > > > +++ b/include/erofs/config.h
> > > > > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > > > > >       char *c_src_path;
> > > > > >       char *c_compr_alg_master;
> > > > > >       int c_compr_level_master;
> > > > > > +     int c_feature_flags;
> > > > > >  };
> > > > > >
> > > > > >  extern struct erofs_configure cfg;
> > > > > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > > > > index 601b477..9ac2635 100644
> > > > > > --- a/include/erofs_fs.h
> > > > > > +++ b/include/erofs_fs.h
> > > > > > @@ -20,6 +20,16 @@
> > > > > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > > > > >  #define EROFS_ALL_REQUIREMENTS
> > > > >  EROFS_REQUIREMENT_LZ4_0PADDING
> > > > > >
> > > > > > +/*
> > > > > > + * feature definations.
> > > > > > + */
> > > > > > +#define EROFS_DEFAULT_FEATURES
>  EROFS_FEATURE_SB_CHKSUM
> > > > > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > > > > +
> > > > > > +
> > > > > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > > > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > > > > +
> > > > > >  struct erofs_super_block {
> > > > > >  /*  0 */__le32 magic;           /* in the little endian */
> > > > > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > > > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > > > > index f127fe1..355fd2c 100644
> > > > > > --- a/mkfs/main.c
> > > > > > +++ b/mkfs/main.c
> > > > > > @@ -31,6 +31,45 @@ static void usage(void)
> > > > > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > > > > >  }
> > > > > >
> > > > > > +#define CRCPOLY      0x82F63B78
> > > > > > +static inline u32 crc32c(u32 seed, unsigned char const *in,
> size_t
> > > len)
> > > > > > +{
> > > > > > +     int i;
> > > > > > +     u32 crc = seed;
> > > > > > +
> > > > > > +     while (len--) {
> > > > > > +             crc ^= *in++;
> > > > > > +             for (i = 0; i < 8; i++) {
> > > > > > +                     crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY :
> 0);
> > > > > > +             }
> > > > > > +     }
> > > > > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > > > > +     return crc;
> > > > > > +}
> > > > > > +
> > > > > > +char *feature_opts[] = {
> > > > > > +     "nosbcrc", NULL
> > > > > > +};
> > > > > > +#define O_SB_CKSUM   0
> > > > > > +
> > > > > > +static int parse_feature_subopts(char *opts)
> > > > > > +{
> > > > > > +     char *arg;
> > > > > > +
> > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > +     while (*opts != '\0') {
> > > > > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > > > > +             case O_SB_CKSUM:
> > > > > > +                     cfg.c_feature_flags |=
> > > (~EROFS_FEATURE_SB_CHKSUM);
> > > > > > +                     break;
> > > > > > +             default:
> > > > > > +                     erofs_err("incorrect suboption");
> > > > > > +                     return -EINVAL;
> > > > > > +             }
> > > > > > +     }
> > > > > > +     return 0;
> > > > > > +}
> > > > > > +
> > > > > >  static int parse_extended_opts(const char *opts)
> > > > > >  {
> > > > > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > > > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc,
> char
> > > > > *argv[])
> > > > > >  {
> > > > > >       int opt, i;
> > > > > >
> > > > > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > > > > >               switch (opt) {
> > > > > >               case 'z':
> > > > > >                       if (!optarg) {
> > > > > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc,
> char
> > > > > *argv[])
> > > > > >                               return opt;
> > > > > >                       break;
> > > > > >
> > > > > > +             case 'O':
> > > > > > +                     opt = parse_feature_subopts(optarg);
> > > > > > +                     if (opt)
> > > > > > +                             return opt;
> > > > > > +                     break;
> > > > > > +
> > > > > >               default: /* '?' */
> > > > > >                       return -EINVAL;
> > > > > >               }
> > > > > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc,
> char
> > > > > *argv[])
> > > > > >       return 0;
> > > > > >  }
> > > > > >
> > > > > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > > > > +{
> > > > > > +     u32 crc;
> > > > > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > > > > +                 sizeof(struct erofs_super_block));
> > > > > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > > > > +     return crc;
> > > > > > +}
> > > > > > +
> > > > > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > > > > >                                 erofs_nid_t root_nid)
> > > > > >  {
> > > > > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > > > > erofs_buffer_head *bh,
> > > > > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > > > > >               .xattr_blkaddr = 0,
> > > > > >               .requirements = cpu_to_le32(sbi.requirements),
> > > > > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > > > > >       };
> > > > > >       const unsigned int sb_blksize =
> > > > > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > > > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > > > > erofs_buffer_head *bh,
> > > > > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > > > > >       sb.root_nid     = cpu_to_le16(root_nid);
> > > > > >
> > > > > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb,
> EROFS_FEATURE_SB_CHKSUM)) {
> > > > > > +             sb.checksum = 0;
> > > > > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > > > > +             sb.checksum = cpu_to_le32(crc);
> > > > > > +     }
> > > > > > +
> > > > > >       buf = calloc(sb_blksize, 1);
> > > > > >       if (!buf) {
> > > > > >               erofs_err("Failed to allocate memory for sb: %s",
> > > > > > --
> > > > > > 2.9.3
> > > > > >
> > > > >
> > >
>

[-- Attachment #2: Type: text/html, Size: 16435 bytes --]

<div dir="auto">Hello Gao,<div dir="auto"><br></div><div dir="auto">Yes I would like to work on pending features.</div><div dir="auto">Also please let us know the new development items.</div><div dir="auto"><br></div><div dir="auto">--Pratik</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 9 Oct, 2019, 12:24 PM Gao Xiang, &lt;<a href="mailto:gaoxiang25@huawei.com">gaoxiang25@huawei.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Pratik,<br>
<br>
On Wed, Oct 09, 2019 at 11:59:01AM +0530, Pratik Shinde wrote:<br>
&gt; Hi Gao,<br>
&gt; <br>
&gt; Yes I can work on it. Sorry I missed this mail. I think your approach is<br>
&gt; good. Let me go through it one more time and reply back.<br>
<br>
Thanks for your reply and interest :)<br>
I think we can complete all pending features together<br>
if you have some time on this stuff. (fsdebug utility is<br>
on the way as well...)<br>
<br>
BTW, I&#39;m now investigating new high CR algorithm (very likely<br>
XZ) as well, it will be likely a RFC version in this round for<br>
wider scenarios and later decompression subsystem.<br>
<br>
Preliminary TODO lists will be discussed in this year China<br>
Linux Storage &amp; Filesystem workshop (next week) and will be<br>
posted to mailing lists for further wider discussion (if more<br>
folks have interest in developing it) as well. :)<br>
<br>
Thanks,<br>
Gao Xiang<br>
<br>
&gt; <br>
&gt; --Pratik<br>
&gt; <br>
&gt; On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, &lt;<a href="mailto:hsiangkao@aol.com" target="_blank" rel="noreferrer">hsiangkao@aol.com</a>&gt; wrote:<br>
&gt; <br>
&gt; &gt; Hi Pratik,<br>
&gt; &gt;<br>
&gt; &gt; On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:<br>
&gt; &gt; &gt; Hi Gao,<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; I completely understand your concern.You can drop this patch for now.<br>
&gt; &gt; &gt; Once erofs makes it &#39;fs/&#39; please do reconsider implementing it.<br>
&gt; &gt;<br>
&gt; &gt; I think we can work on this pending feature for v5.5 now.<br>
&gt; &gt; My idea is to add an extra field in erofs_super_block to<br>
&gt; &gt; indicate the number of blocks (4k) for checking.<br>
&gt; &gt;<br>
&gt; &gt; So for small images, this feature can checksum the whole image at mount<br>
&gt; &gt; time,<br>
&gt; &gt; and for large images, this feature can be used to checksum the super block<br>
&gt; &gt; only<br>
&gt; &gt; (and then use verficiation subsystem to verify on-the-fly in the future...)<br>
&gt; &gt;<br>
&gt; &gt; The following workflow is for erofs-utils, I think it&#39;s<br>
&gt; &gt;  1) erofs_mkfs_update_super_block with checksum = 0<br>
&gt; &gt;  2) erofs_bflush(NULL)<br>
&gt; &gt;  3) reread the corresponding blocks and calculate checksum;<br>
&gt; &gt;  4) write checksum to erofs_super_block;<br>
&gt; &gt;<br>
&gt; &gt; Does it sound reasonable? and do you still have interest and<br>
&gt; &gt; time for this? Looking forword to your reply...<br>
&gt; &gt;<br>
&gt; &gt; Thanks,<br>
&gt; &gt; Gao Xiang<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; One more thing, can we still send non feature patches?<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; --Pratik<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, &lt;<a href="mailto:hsiangkao@aol.com" target="_blank" rel="noreferrer">hsiangkao@aol.com</a>&gt; wrote:<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Hi Pratik,<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:<br>
&gt; &gt; &gt; &gt; &gt; Adding code for superblock checksum calculation.<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; incorporated the changes suggested in previous patch.<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; Signed-off-by: Pratik Shinde &lt;<a href="mailto:pratikshinde320@gmail.com" target="_blank" rel="noreferrer">pratikshinde320@gmail.com</a>&gt;<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Thanks for your v2 patch.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Actually, I have some concern about the length of checksum,<br>
&gt; &gt; &gt; &gt; sizeof(struct erofs_super_block) could be changed in the<br>
&gt; &gt; &gt; &gt; later version, it&#39;s bad for EROFS future scalablity.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; And I tend not to add another on-disk field to record<br>
&gt; &gt; &gt; &gt; the size of erofs_super_block as well, because the old<br>
&gt; &gt; &gt; &gt; Linux kernel cannot handle more about the new size,<br>
&gt; &gt; &gt; &gt; so it has little use except for checksum calculation.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Few hours ago, I discussed with Chao about this concern,<br>
&gt; &gt; &gt; &gt; I think this feature can be changed to do multiple-block<br>
&gt; &gt; &gt; &gt; checksum at the mount time, e.g:<br>
&gt; &gt; &gt; &gt;  - for small images, we can check the whole image once<br>
&gt; &gt; &gt; &gt;    at the mount time;<br>
&gt; &gt; &gt; &gt;  - for the large image, we can check the superblock<br>
&gt; &gt; &gt; &gt;    at the mount time, the rest can be handled by<br>
&gt; &gt; &gt; &gt;    block-based verification layer.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; But we agreed that don&#39;t add this for this round<br>
&gt; &gt; &gt; &gt; since it&#39;s quite a new feature.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; All in all, it&#39;s a new feature since we are addressing moving<br>
&gt; &gt; &gt; &gt; out of staging for this round. I tend to postpone this feature<br>
&gt; &gt; &gt; &gt; for now. I understand that you are very interested in EROFS.<br>
&gt; &gt; &gt; &gt; Considering EROFS current staging status, it&#39;s not such a place<br>
&gt; &gt; &gt; &gt; to add new features at all! I have marked your patch down and<br>
&gt; &gt; &gt; &gt; I will work with you later. Hope to get your understanding...<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Thanks,<br>
&gt; &gt; &gt; &gt; Gao Xiang<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; ---<br>
&gt; &gt; &gt; &gt; &gt;  include/erofs/config.h |  1 +<br>
&gt; &gt; &gt; &gt; &gt;  include/erofs_fs.h     | 10 ++++++++<br>
&gt; &gt; &gt; &gt; &gt;  mkfs/main.c            | 64<br>
&gt; &gt; &gt; &gt; +++++++++++++++++++++++++++++++++++++++++++++++++-<br>
&gt; &gt; &gt; &gt; &gt;  3 files changed, 74 insertions(+), 1 deletion(-)<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; diff --git a/include/erofs/config.h b/include/erofs/config.h<br>
&gt; &gt; &gt; &gt; &gt; index 05fe6b2..40cd466 100644<br>
&gt; &gt; &gt; &gt; &gt; --- a/include/erofs/config.h<br>
&gt; &gt; &gt; &gt; &gt; +++ b/include/erofs/config.h<br>
&gt; &gt; &gt; &gt; &gt; @@ -22,6 +22,7 @@ struct erofs_configure {<br>
&gt; &gt; &gt; &gt; &gt;       char *c_src_path;<br>
&gt; &gt; &gt; &gt; &gt;       char *c_compr_alg_master;<br>
&gt; &gt; &gt; &gt; &gt;       int c_compr_level_master;<br>
&gt; &gt; &gt; &gt; &gt; +     int c_feature_flags;<br>
&gt; &gt; &gt; &gt; &gt;  };<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt;  extern struct erofs_configure cfg;<br>
&gt; &gt; &gt; &gt; &gt; diff --git a/include/erofs_fs.h b/include/erofs_fs.h<br>
&gt; &gt; &gt; &gt; &gt; index 601b477..9ac2635 100644<br>
&gt; &gt; &gt; &gt; &gt; --- a/include/erofs_fs.h<br>
&gt; &gt; &gt; &gt; &gt; +++ b/include/erofs_fs.h<br>
&gt; &gt; &gt; &gt; &gt; @@ -20,6 +20,16 @@<br>
&gt; &gt; &gt; &gt; &gt;  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001<br>
&gt; &gt; &gt; &gt; &gt;  #define EROFS_ALL_REQUIREMENTS<br>
&gt; &gt; &gt; &gt;  EROFS_REQUIREMENT_LZ4_0PADDING<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; +/*<br>
&gt; &gt; &gt; &gt; &gt; + * feature definations.<br>
&gt; &gt; &gt; &gt; &gt; + */<br>
&gt; &gt; &gt; &gt; &gt; +#define EROFS_DEFAULT_FEATURES               EROFS_FEATURE_SB_CHKSUM<br>
&gt; &gt; &gt; &gt; &gt; +#define EROFS_FEATURE_SB_CHKSUM              0x0001<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \<br>
&gt; &gt; &gt; &gt; &gt; +     ( le32_to_cpu((super)-&gt;features) &amp; (mask) )<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt;  struct erofs_super_block {<br>
&gt; &gt; &gt; &gt; &gt;  /*  0 */__le32 magic;           /* in the little endian */<br>
&gt; &gt; &gt; &gt; &gt;  /*  4 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt; &gt; &gt; &gt; &gt; diff --git a/mkfs/main.c b/mkfs/main.c<br>
&gt; &gt; &gt; &gt; &gt; index f127fe1..355fd2c 100644<br>
&gt; &gt; &gt; &gt; &gt; --- a/mkfs/main.c<br>
&gt; &gt; &gt; &gt; &gt; +++ b/mkfs/main.c<br>
&gt; &gt; &gt; &gt; &gt; @@ -31,6 +31,45 @@ static void usage(void)<br>
&gt; &gt; &gt; &gt; &gt;       fprintf(stderr, &quot; -EX[,...] X=extended options\n&quot;);<br>
&gt; &gt; &gt; &gt; &gt;  }<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; +#define CRCPOLY      0x82F63B78<br>
&gt; &gt; &gt; &gt; &gt; +static inline u32 crc32c(u32 seed, unsigned char const *in, size_t<br>
&gt; &gt; len)<br>
&gt; &gt; &gt; &gt; &gt; +{<br>
&gt; &gt; &gt; &gt; &gt; +     int i;<br>
&gt; &gt; &gt; &gt; &gt; +     u32 crc = seed;<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; +     while (len--) {<br>
&gt; &gt; &gt; &gt; &gt; +             crc ^= *in++;<br>
&gt; &gt; &gt; &gt; &gt; +             for (i = 0; i &lt; 8; i++) {<br>
&gt; &gt; &gt; &gt; &gt; +                     crc = (crc &gt;&gt; 1) ^ ((crc &amp; 1) ? CRCPOLY : 0);<br>
&gt; &gt; &gt; &gt; &gt; +             }<br>
&gt; &gt; &gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; &gt; &gt; +     erofs_dump(&quot;calculated crc: 0x%x\n&quot;, crc);<br>
&gt; &gt; &gt; &gt; &gt; +     return crc;<br>
&gt; &gt; &gt; &gt; &gt; +}<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; +char *feature_opts[] = {<br>
&gt; &gt; &gt; &gt; &gt; +     &quot;nosbcrc&quot;, NULL<br>
&gt; &gt; &gt; &gt; &gt; +};<br>
&gt; &gt; &gt; &gt; &gt; +#define O_SB_CKSUM   0<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; +static int parse_feature_subopts(char *opts)<br>
&gt; &gt; &gt; &gt; &gt; +{<br>
&gt; &gt; &gt; &gt; &gt; +     char *arg;<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; &gt; &gt; &gt; &gt; +     while (*opts != &#39;\0&#39;) {<br>
&gt; &gt; &gt; &gt; &gt; +             switch(getsubopt(&amp;opts, feature_opts, &amp;arg)) {<br>
&gt; &gt; &gt; &gt; &gt; +             case O_SB_CKSUM:<br>
&gt; &gt; &gt; &gt; &gt; +                     cfg.c_feature_flags |=<br>
&gt; &gt; (~EROFS_FEATURE_SB_CHKSUM);<br>
&gt; &gt; &gt; &gt; &gt; +                     break;<br>
&gt; &gt; &gt; &gt; &gt; +             default:<br>
&gt; &gt; &gt; &gt; &gt; +                     erofs_err(&quot;incorrect suboption&quot;);<br>
&gt; &gt; &gt; &gt; &gt; +                     return -EINVAL;<br>
&gt; &gt; &gt; &gt; &gt; +             }<br>
&gt; &gt; &gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; &gt; &gt; +     return 0;<br>
&gt; &gt; &gt; &gt; &gt; +}<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt;  static int parse_extended_opts(const char *opts)<br>
&gt; &gt; &gt; &gt; &gt;  {<br>
&gt; &gt; &gt; &gt; &gt;  #define MATCH_EXTENTED_OPT(opt, token, keylen) \<br>
&gt; &gt; &gt; &gt; &gt; @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt; &gt; &gt; &gt; *argv[])<br>
&gt; &gt; &gt; &gt; &gt;  {<br>
&gt; &gt; &gt; &gt; &gt;       int opt, i;<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; -     while ((opt = getopt(argc, argv, &quot;d:z:E:&quot;)) != -1) {<br>
&gt; &gt; &gt; &gt; &gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; &gt; &gt; &gt; &gt; +     while ((opt = getopt(argc, argv, &quot;d:z:E:o:&quot;)) != -1) {<br>
&gt; &gt; &gt; &gt; &gt;               switch (opt) {<br>
&gt; &gt; &gt; &gt; &gt;               case &#39;z&#39;:<br>
&gt; &gt; &gt; &gt; &gt;                       if (!optarg) {<br>
&gt; &gt; &gt; &gt; &gt; @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt; &gt; &gt; &gt; *argv[])<br>
&gt; &gt; &gt; &gt; &gt;                               return opt;<br>
&gt; &gt; &gt; &gt; &gt;                       break;<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; +             case &#39;O&#39;:<br>
&gt; &gt; &gt; &gt; &gt; +                     opt = parse_feature_subopts(optarg);<br>
&gt; &gt; &gt; &gt; &gt; +                     if (opt)<br>
&gt; &gt; &gt; &gt; &gt; +                             return opt;<br>
&gt; &gt; &gt; &gt; &gt; +                     break;<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt;               default: /* &#39;?&#39; */<br>
&gt; &gt; &gt; &gt; &gt;                       return -EINVAL;<br>
&gt; &gt; &gt; &gt; &gt;               }<br>
&gt; &gt; &gt; &gt; &gt; @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt; &gt; &gt; &gt; *argv[])<br>
&gt; &gt; &gt; &gt; &gt;       return 0;<br>
&gt; &gt; &gt; &gt; &gt;  }<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; +u32 erofs_superblock_checksum(struct erofs_super_block *sb)<br>
&gt; &gt; &gt; &gt; &gt; +{<br>
&gt; &gt; &gt; &gt; &gt; +     u32 crc;<br>
&gt; &gt; &gt; &gt; &gt; +     crc = crc32c(~0, (const unsigned char *)sb,<br>
&gt; &gt; &gt; &gt; &gt; +                 sizeof(struct erofs_super_block));<br>
&gt; &gt; &gt; &gt; &gt; +     erofs_dump(&quot;superblock checksum: 0x%x\n&quot;, crc);<br>
&gt; &gt; &gt; &gt; &gt; +     return crc;<br>
&gt; &gt; &gt; &gt; &gt; +}<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt;  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt; &gt; &gt; &gt; &gt;                                 erofs_nid_t root_nid)<br>
&gt; &gt; &gt; &gt; &gt;  {<br>
&gt; &gt; &gt; &gt; &gt; @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct<br>
&gt; &gt; &gt; &gt; erofs_buffer_head *bh,<br>
&gt; &gt; &gt; &gt; &gt;               .meta_blkaddr  = sbi.meta_blkaddr,<br>
&gt; &gt; &gt; &gt; &gt;               .xattr_blkaddr = 0,<br>
&gt; &gt; &gt; &gt; &gt;               .requirements = cpu_to_le32(sbi.requirements),<br>
&gt; &gt; &gt; &gt; &gt; +             .features = cpu_to_le32(cfg.c_feature_flags),<br>
&gt; &gt; &gt; &gt; &gt;       };<br>
&gt; &gt; &gt; &gt; &gt;       const unsigned int sb_blksize =<br>
&gt; &gt; &gt; &gt; &gt;               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);<br>
&gt; &gt; &gt; &gt; &gt; @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct<br>
&gt; &gt; &gt; &gt; erofs_buffer_head *bh,<br>
&gt; &gt; &gt; &gt; &gt;       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));<br>
&gt; &gt; &gt; &gt; &gt;       sb.root_nid     = cpu_to_le16(root_nid);<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; +     if (EROFS_HAS_COMPAT_FEATURE(&amp;sb, EROFS_FEATURE_SB_CHKSUM)) {<br>
&gt; &gt; &gt; &gt; &gt; +             sb.checksum = 0;<br>
&gt; &gt; &gt; &gt; &gt; +             u32 crc = erofs_superblock_checksum(&amp;sb);<br>
&gt; &gt; &gt; &gt; &gt; +             sb.checksum = cpu_to_le32(crc);<br>
&gt; &gt; &gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt;       buf = calloc(sb_blksize, 1);<br>
&gt; &gt; &gt; &gt; &gt;       if (!buf) {<br>
&gt; &gt; &gt; &gt; &gt;               erofs_err(&quot;Failed to allocate memory for sb: %s&quot;,<br>
&gt; &gt; &gt; &gt; &gt; --<br>
&gt; &gt; &gt; &gt; &gt; 2.9.3<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt;<br>
</blockquote></div>

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-10-09  8:24           ` Pratik Shinde
@ 2019-10-09  8:48             ` Gao Xiang
  2019-10-09 14:14               ` Pratik Shinde
  0 siblings, 1 reply; 19+ messages in thread
From: Gao Xiang @ 2019-10-09  8:48 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: miaoxie, linux-erofs

Hi Pratik,

On Wed, Oct 09, 2019 at 01:54:40PM +0530, Pratik Shinde wrote:
> Hello Gao,
> 
> Yes I would like to work on pending features.
> Also please let us know the new development items.

Thanks, I will post later after gathering the first round
suggestions to mailing lists. We have time to improve this
filesystem. :)

Thanks,
Gao Xiang

> 
> --Pratik
> 
> On Wed, 9 Oct, 2019, 12:24 PM Gao Xiang, <gaoxiang25@huawei.com> wrote:
> 
> > Hi Pratik,
> >
> > On Wed, Oct 09, 2019 at 11:59:01AM +0530, Pratik Shinde wrote:
> > > Hi Gao,
> > >
> > > Yes I can work on it. Sorry I missed this mail. I think your approach is
> > > good. Let me go through it one more time and reply back.
> >
> > Thanks for your reply and interest :)
> > I think we can complete all pending features together
> > if you have some time on this stuff. (fsdebug utility is
> > on the way as well...)
> >
> > BTW, I'm now investigating new high CR algorithm (very likely
> > XZ) as well, it will be likely a RFC version in this round for
> > wider scenarios and later decompression subsystem.
> >
> > Preliminary TODO lists will be discussed in this year China
> > Linux Storage & Filesystem workshop (next week) and will be
> > posted to mailing lists for further wider discussion (if more
> > folks have interest in developing it) as well. :)
> >
> > Thanks,
> > Gao Xiang
> >
> > >
> > > --Pratik
> > >
> > > On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, <hsiangkao@aol.com> wrote:
> > >
> > > > Hi Pratik,
> > > >
> > > > On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> > > > > Hi Gao,
> > > > >
> > > > > I completely understand your concern.You can drop this patch for now.
> > > > > Once erofs makes it 'fs/' please do reconsider implementing it.
> > > >
> > > > I think we can work on this pending feature for v5.5 now.
> > > > My idea is to add an extra field in erofs_super_block to
> > > > indicate the number of blocks (4k) for checking.
> > > >
> > > > So for small images, this feature can checksum the whole image at mount
> > > > time,
> > > > and for large images, this feature can be used to checksum the super
> > block
> > > > only
> > > > (and then use verficiation subsystem to verify on-the-fly in the
> > future...)
> > > >
> > > > The following workflow is for erofs-utils, I think it's
> > > >  1) erofs_mkfs_update_super_block with checksum = 0
> > > >  2) erofs_bflush(NULL)
> > > >  3) reread the corresponding blocks and calculate checksum;
> > > >  4) write checksum to erofs_super_block;
> > > >
> > > > Does it sound reasonable? and do you still have interest and
> > > > time for this? Looking forword to your reply...
> > > >
> > > > Thanks,
> > > > Gao Xiang
> > > >
> > > > >
> > > > > One more thing, can we still send non feature patches?
> > > > >
> > > > > --Pratik
> > > > >
> > > > >
> > > > > On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com> wrote:
> > > > >
> > > > > > Hi Pratik,
> > > > > >
> > > > > > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > > > > > Adding code for superblock checksum calculation.
> > > > > > >
> > > > > > > incorporated the changes suggested in previous patch.
> > > > > > >
> > > > > > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> > > > > >
> > > > > > Thanks for your v2 patch.
> > > > > >
> > > > > > Actually, I have some concern about the length of checksum,
> > > > > > sizeof(struct erofs_super_block) could be changed in the
> > > > > > later version, it's bad for EROFS future scalablity.
> > > > > >
> > > > > > And I tend not to add another on-disk field to record
> > > > > > the size of erofs_super_block as well, because the old
> > > > > > Linux kernel cannot handle more about the new size,
> > > > > > so it has little use except for checksum calculation.
> > > > > >
> > > > > > Few hours ago, I discussed with Chao about this concern,
> > > > > > I think this feature can be changed to do multiple-block
> > > > > > checksum at the mount time, e.g:
> > > > > >  - for small images, we can check the whole image once
> > > > > >    at the mount time;
> > > > > >  - for the large image, we can check the superblock
> > > > > >    at the mount time, the rest can be handled by
> > > > > >    block-based verification layer.
> > > > > >
> > > > > > But we agreed that don't add this for this round
> > > > > > since it's quite a new feature.
> > > > > >
> > > > > > All in all, it's a new feature since we are addressing moving
> > > > > > out of staging for this round. I tend to postpone this feature
> > > > > > for now. I understand that you are very interested in EROFS.
> > > > > > Considering EROFS current staging status, it's not such a place
> > > > > > to add new features at all! I have marked your patch down and
> > > > > > I will work with you later. Hope to get your understanding...
> > > > > >
> > > > > > Thanks,
> > > > > > Gao Xiang
> > > > > >
> > > > > > > ---
> > > > > > >  include/erofs/config.h |  1 +
> > > > > > >  include/erofs_fs.h     | 10 ++++++++
> > > > > > >  mkfs/main.c            | 64
> > > > > > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > > > > > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > > > > > >
> > > > > > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > > > > > index 05fe6b2..40cd466 100644
> > > > > > > --- a/include/erofs/config.h
> > > > > > > +++ b/include/erofs/config.h
> > > > > > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > > > > > >       char *c_src_path;
> > > > > > >       char *c_compr_alg_master;
> > > > > > >       int c_compr_level_master;
> > > > > > > +     int c_feature_flags;
> > > > > > >  };
> > > > > > >
> > > > > > >  extern struct erofs_configure cfg;
> > > > > > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > > > > > index 601b477..9ac2635 100644
> > > > > > > --- a/include/erofs_fs.h
> > > > > > > +++ b/include/erofs_fs.h
> > > > > > > @@ -20,6 +20,16 @@
> > > > > > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > > > > > >  #define EROFS_ALL_REQUIREMENTS
> > > > > >  EROFS_REQUIREMENT_LZ4_0PADDING
> > > > > > >
> > > > > > > +/*
> > > > > > > + * feature definations.
> > > > > > > + */
> > > > > > > +#define EROFS_DEFAULT_FEATURES
> >  EROFS_FEATURE_SB_CHKSUM
> > > > > > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > > > > > +
> > > > > > > +
> > > > > > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > > > > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > > > > > +
> > > > > > >  struct erofs_super_block {
> > > > > > >  /*  0 */__le32 magic;           /* in the little endian */
> > > > > > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > > > > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > > > > > index f127fe1..355fd2c 100644
> > > > > > > --- a/mkfs/main.c
> > > > > > > +++ b/mkfs/main.c
> > > > > > > @@ -31,6 +31,45 @@ static void usage(void)
> > > > > > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > > > > > >  }
> > > > > > >
> > > > > > > +#define CRCPOLY      0x82F63B78
> > > > > > > +static inline u32 crc32c(u32 seed, unsigned char const *in,
> > size_t
> > > > len)
> > > > > > > +{
> > > > > > > +     int i;
> > > > > > > +     u32 crc = seed;
> > > > > > > +
> > > > > > > +     while (len--) {
> > > > > > > +             crc ^= *in++;
> > > > > > > +             for (i = 0; i < 8; i++) {
> > > > > > > +                     crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY :
> > 0);
> > > > > > > +             }
> > > > > > > +     }
> > > > > > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > > > > > +     return crc;
> > > > > > > +}
> > > > > > > +
> > > > > > > +char *feature_opts[] = {
> > > > > > > +     "nosbcrc", NULL
> > > > > > > +};
> > > > > > > +#define O_SB_CKSUM   0
> > > > > > > +
> > > > > > > +static int parse_feature_subopts(char *opts)
> > > > > > > +{
> > > > > > > +     char *arg;
> > > > > > > +
> > > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > > +     while (*opts != '\0') {
> > > > > > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > > > > > +             case O_SB_CKSUM:
> > > > > > > +                     cfg.c_feature_flags |=
> > > > (~EROFS_FEATURE_SB_CHKSUM);
> > > > > > > +                     break;
> > > > > > > +             default:
> > > > > > > +                     erofs_err("incorrect suboption");
> > > > > > > +                     return -EINVAL;
> > > > > > > +             }
> > > > > > > +     }
> > > > > > > +     return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > >  static int parse_extended_opts(const char *opts)
> > > > > > >  {
> > > > > > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > > > > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc,
> > char
> > > > > > *argv[])
> > > > > > >  {
> > > > > > >       int opt, i;
> > > > > > >
> > > > > > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > > > > > >               switch (opt) {
> > > > > > >               case 'z':
> > > > > > >                       if (!optarg) {
> > > > > > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc,
> > char
> > > > > > *argv[])
> > > > > > >                               return opt;
> > > > > > >                       break;
> > > > > > >
> > > > > > > +             case 'O':
> > > > > > > +                     opt = parse_feature_subopts(optarg);
> > > > > > > +                     if (opt)
> > > > > > > +                             return opt;
> > > > > > > +                     break;
> > > > > > > +
> > > > > > >               default: /* '?' */
> > > > > > >                       return -EINVAL;
> > > > > > >               }
> > > > > > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc,
> > char
> > > > > > *argv[])
> > > > > > >       return 0;
> > > > > > >  }
> > > > > > >
> > > > > > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > > > > > +{
> > > > > > > +     u32 crc;
> > > > > > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > > > > > +                 sizeof(struct erofs_super_block));
> > > > > > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > > > > > +     return crc;
> > > > > > > +}
> > > > > > > +
> > > > > > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > > > > > >                                 erofs_nid_t root_nid)
> > > > > > >  {
> > > > > > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > > > > > erofs_buffer_head *bh,
> > > > > > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > > > > > >               .xattr_blkaddr = 0,
> > > > > > >               .requirements = cpu_to_le32(sbi.requirements),
> > > > > > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > > > > > >       };
> > > > > > >       const unsigned int sb_blksize =
> > > > > > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > > > > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > > > > > erofs_buffer_head *bh,
> > > > > > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > > > > > >       sb.root_nid     = cpu_to_le16(root_nid);
> > > > > > >
> > > > > > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb,
> > EROFS_FEATURE_SB_CHKSUM)) {
> > > > > > > +             sb.checksum = 0;
> > > > > > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > > > > > +             sb.checksum = cpu_to_le32(crc);
> > > > > > > +     }
> > > > > > > +
> > > > > > >       buf = calloc(sb_blksize, 1);
> > > > > > >       if (!buf) {
> > > > > > >               erofs_err("Failed to allocate memory for sb: %s",
> > > > > > > --
> > > > > > > 2.9.3
> > > > > > >
> > > > > >
> > > >
> >

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-10-09  8:48             ` Gao Xiang
@ 2019-10-09 14:14               ` Pratik Shinde
  2019-10-09 14:27                 ` Gao Xiang via Linux-erofs
  0 siblings, 1 reply; 19+ messages in thread
From: Pratik Shinde @ 2019-10-09 14:14 UTC (permalink / raw)
  To: Gao Xiang; +Cc: miaoxie, linux-erofs

[-- Attachment #1: Type: text/plain, Size: 12973 bytes --]

Hello Gao,

I have few questions regarding the checksum feature:
1) Are we still keeping it as a feature. (i.e enabled by default . but can
be disabled during mkfs)
2) For small images we are going to cksum the entire image. what could be
the maximum size of 'small' images.

also, I think we don't have routines to read buffers back into the memory.
I will write them first and send a patch.

-Pratik

On Wed, Oct 9, 2019 at 2:14 PM Gao Xiang <gaoxiang25@huawei.com> wrote:

> Hi Pratik,
>
> On Wed, Oct 09, 2019 at 01:54:40PM +0530, Pratik Shinde wrote:
> > Hello Gao,
> >
> > Yes I would like to work on pending features.
> > Also please let us know the new development items.
>
> Thanks, I will post later after gathering the first round
> suggestions to mailing lists. We have time to improve this
> filesystem. :)
>
> Thanks,
> Gao Xiang
>
> >
> > --Pratik
> >
> > On Wed, 9 Oct, 2019, 12:24 PM Gao Xiang, <gaoxiang25@huawei.com> wrote:
> >
> > > Hi Pratik,
> > >
> > > On Wed, Oct 09, 2019 at 11:59:01AM +0530, Pratik Shinde wrote:
> > > > Hi Gao,
> > > >
> > > > Yes I can work on it. Sorry I missed this mail. I think your
> approach is
> > > > good. Let me go through it one more time and reply back.
> > >
> > > Thanks for your reply and interest :)
> > > I think we can complete all pending features together
> > > if you have some time on this stuff. (fsdebug utility is
> > > on the way as well...)
> > >
> > > BTW, I'm now investigating new high CR algorithm (very likely
> > > XZ) as well, it will be likely a RFC version in this round for
> > > wider scenarios and later decompression subsystem.
> > >
> > > Preliminary TODO lists will be discussed in this year China
> > > Linux Storage & Filesystem workshop (next week) and will be
> > > posted to mailing lists for further wider discussion (if more
> > > folks have interest in developing it) as well. :)
> > >
> > > Thanks,
> > > Gao Xiang
> > >
> > > >
> > > > --Pratik
> > > >
> > > > On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, <hsiangkao@aol.com> wrote:
> > > >
> > > > > Hi Pratik,
> > > > >
> > > > > On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> > > > > > Hi Gao,
> > > > > >
> > > > > > I completely understand your concern.You can drop this patch for
> now.
> > > > > > Once erofs makes it 'fs/' please do reconsider implementing it.
> > > > >
> > > > > I think we can work on this pending feature for v5.5 now.
> > > > > My idea is to add an extra field in erofs_super_block to
> > > > > indicate the number of blocks (4k) for checking.
> > > > >
> > > > > So for small images, this feature can checksum the whole image at
> mount
> > > > > time,
> > > > > and for large images, this feature can be used to checksum the
> super
> > > block
> > > > > only
> > > > > (and then use verficiation subsystem to verify on-the-fly in the
> > > future...)
> > > > >
> > > > > The following workflow is for erofs-utils, I think it's
> > > > >  1) erofs_mkfs_update_super_block with checksum = 0
> > > > >  2) erofs_bflush(NULL)
> > > > >  3) reread the corresponding blocks and calculate checksum;
> > > > >  4) write checksum to erofs_super_block;
> > > > >
> > > > > Does it sound reasonable? and do you still have interest and
> > > > > time for this? Looking forword to your reply...
> > > > >
> > > > > Thanks,
> > > > > Gao Xiang
> > > > >
> > > > > >
> > > > > > One more thing, can we still send non feature patches?
> > > > > >
> > > > > > --Pratik
> > > > > >
> > > > > >
> > > > > > On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com>
> wrote:
> > > > > >
> > > > > > > Hi Pratik,
> > > > > > >
> > > > > > > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > > > > > > Adding code for superblock checksum calculation.
> > > > > > > >
> > > > > > > > incorporated the changes suggested in previous patch.
> > > > > > > >
> > > > > > > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> > > > > > >
> > > > > > > Thanks for your v2 patch.
> > > > > > >
> > > > > > > Actually, I have some concern about the length of checksum,
> > > > > > > sizeof(struct erofs_super_block) could be changed in the
> > > > > > > later version, it's bad for EROFS future scalablity.
> > > > > > >
> > > > > > > And I tend not to add another on-disk field to record
> > > > > > > the size of erofs_super_block as well, because the old
> > > > > > > Linux kernel cannot handle more about the new size,
> > > > > > > so it has little use except for checksum calculation.
> > > > > > >
> > > > > > > Few hours ago, I discussed with Chao about this concern,
> > > > > > > I think this feature can be changed to do multiple-block
> > > > > > > checksum at the mount time, e.g:
> > > > > > >  - for small images, we can check the whole image once
> > > > > > >    at the mount time;
> > > > > > >  - for the large image, we can check the superblock
> > > > > > >    at the mount time, the rest can be handled by
> > > > > > >    block-based verification layer.
> > > > > > >
> > > > > > > But we agreed that don't add this for this round
> > > > > > > since it's quite a new feature.
> > > > > > >
> > > > > > > All in all, it's a new feature since we are addressing moving
> > > > > > > out of staging for this round. I tend to postpone this feature
> > > > > > > for now. I understand that you are very interested in EROFS.
> > > > > > > Considering EROFS current staging status, it's not such a place
> > > > > > > to add new features at all! I have marked your patch down and
> > > > > > > I will work with you later. Hope to get your understanding...
> > > > > > >
> > > > > > > Thanks,
> > > > > > > Gao Xiang
> > > > > > >
> > > > > > > > ---
> > > > > > > >  include/erofs/config.h |  1 +
> > > > > > > >  include/erofs_fs.h     | 10 ++++++++
> > > > > > > >  mkfs/main.c            | 64
> > > > > > > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > > > > > > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > > > > > > >
> > > > > > > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > > > > > > index 05fe6b2..40cd466 100644
> > > > > > > > --- a/include/erofs/config.h
> > > > > > > > +++ b/include/erofs/config.h
> > > > > > > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > > > > > > >       char *c_src_path;
> > > > > > > >       char *c_compr_alg_master;
> > > > > > > >       int c_compr_level_master;
> > > > > > > > +     int c_feature_flags;
> > > > > > > >  };
> > > > > > > >
> > > > > > > >  extern struct erofs_configure cfg;
> > > > > > > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > > > > > > index 601b477..9ac2635 100644
> > > > > > > > --- a/include/erofs_fs.h
> > > > > > > > +++ b/include/erofs_fs.h
> > > > > > > > @@ -20,6 +20,16 @@
> > > > > > > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > > > > > > >  #define EROFS_ALL_REQUIREMENTS
> > > > > > >  EROFS_REQUIREMENT_LZ4_0PADDING
> > > > > > > >
> > > > > > > > +/*
> > > > > > > > + * feature definations.
> > > > > > > > + */
> > > > > > > > +#define EROFS_DEFAULT_FEATURES
> > >  EROFS_FEATURE_SB_CHKSUM
> > > > > > > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > > > > > > +
> > > > > > > > +
> > > > > > > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > > > > > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > > > > > > +
> > > > > > > >  struct erofs_super_block {
> > > > > > > >  /*  0 */__le32 magic;           /* in the little endian */
> > > > > > > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > > > > > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > > > > > > index f127fe1..355fd2c 100644
> > > > > > > > --- a/mkfs/main.c
> > > > > > > > +++ b/mkfs/main.c
> > > > > > > > @@ -31,6 +31,45 @@ static void usage(void)
> > > > > > > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +#define CRCPOLY      0x82F63B78
> > > > > > > > +static inline u32 crc32c(u32 seed, unsigned char const *in,
> > > size_t
> > > > > len)
> > > > > > > > +{
> > > > > > > > +     int i;
> > > > > > > > +     u32 crc = seed;
> > > > > > > > +
> > > > > > > > +     while (len--) {
> > > > > > > > +             crc ^= *in++;
> > > > > > > > +             for (i = 0; i < 8; i++) {
> > > > > > > > +                     crc = (crc >> 1) ^ ((crc & 1) ?
> CRCPOLY :
> > > 0);
> > > > > > > > +             }
> > > > > > > > +     }
> > > > > > > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > > > > > > +     return crc;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +char *feature_opts[] = {
> > > > > > > > +     "nosbcrc", NULL
> > > > > > > > +};
> > > > > > > > +#define O_SB_CKSUM   0
> > > > > > > > +
> > > > > > > > +static int parse_feature_subopts(char *opts)
> > > > > > > > +{
> > > > > > > > +     char *arg;
> > > > > > > > +
> > > > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > > > +     while (*opts != '\0') {
> > > > > > > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > > > > > > +             case O_SB_CKSUM:
> > > > > > > > +                     cfg.c_feature_flags |=
> > > > > (~EROFS_FEATURE_SB_CHKSUM);
> > > > > > > > +                     break;
> > > > > > > > +             default:
> > > > > > > > +                     erofs_err("incorrect suboption");
> > > > > > > > +                     return -EINVAL;
> > > > > > > > +             }
> > > > > > > > +     }
> > > > > > > > +     return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  static int parse_extended_opts(const char *opts)
> > > > > > > >  {
> > > > > > > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > > > > > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int
> argc,
> > > char
> > > > > > > *argv[])
> > > > > > > >  {
> > > > > > > >       int opt, i;
> > > > > > > >
> > > > > > > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > > > > > > >               switch (opt) {
> > > > > > > >               case 'z':
> > > > > > > >                       if (!optarg) {
> > > > > > > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int
> argc,
> > > char
> > > > > > > *argv[])
> > > > > > > >                               return opt;
> > > > > > > >                       break;
> > > > > > > >
> > > > > > > > +             case 'O':
> > > > > > > > +                     opt = parse_feature_subopts(optarg);
> > > > > > > > +                     if (opt)
> > > > > > > > +                             return opt;
> > > > > > > > +                     break;
> > > > > > > > +
> > > > > > > >               default: /* '?' */
> > > > > > > >                       return -EINVAL;
> > > > > > > >               }
> > > > > > > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int
> argc,
> > > char
> > > > > > > *argv[])
> > > > > > > >       return 0;
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > > > > > > +{
> > > > > > > > +     u32 crc;
> > > > > > > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > > > > > > +                 sizeof(struct erofs_super_block));
> > > > > > > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > > > > > > +     return crc;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head
> *bh,
> > > > > > > >                                 erofs_nid_t root_nid)
> > > > > > > >  {
> > > > > > > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > > > > > > erofs_buffer_head *bh,
> > > > > > > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > > > > > > >               .xattr_blkaddr = 0,
> > > > > > > >               .requirements = cpu_to_le32(sbi.requirements),
> > > > > > > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > > > > > > >       };
> > > > > > > >       const unsigned int sb_blksize =
> > > > > > > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > > > > > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > > > > > > erofs_buffer_head *bh,
> > > > > > > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > > > > > > >       sb.root_nid     = cpu_to_le16(root_nid);
> > > > > > > >
> > > > > > > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb,
> > > EROFS_FEATURE_SB_CHKSUM)) {
> > > > > > > > +             sb.checksum = 0;
> > > > > > > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > > > > > > +             sb.checksum = cpu_to_le32(crc);
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > >       buf = calloc(sb_blksize, 1);
> > > > > > > >       if (!buf) {
> > > > > > > >               erofs_err("Failed to allocate memory for sb:
> %s",
> > > > > > > > --
> > > > > > > > 2.9.3
> > > > > > > >
> > > > > > >
> > > > >
> > >
>

[-- Attachment #2: Type: text/html, Size: 20172 bytes --]

<div dir="ltr"><div>Hello Gao,</div><div><br></div><div>I have few questions regarding the checksum feature:</div><div>1) Are we still keeping it as a feature. (i.e enabled by default . but can be disabled during mkfs)</div><div>2) For small images we are going to cksum the entire image. what could be the maximum size of &#39;small&#39; images.</div><div><br></div><div>also, I think we don&#39;t have routines to read buffers back into the memory. I will write them first and send a patch.</div><div><br></div><div>-Pratik<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Oct 9, 2019 at 2:14 PM Gao Xiang &lt;<a href="mailto:gaoxiang25@huawei.com">gaoxiang25@huawei.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Pratik,<br>
<br>
On Wed, Oct 09, 2019 at 01:54:40PM +0530, Pratik Shinde wrote:<br>
&gt; Hello Gao,<br>
&gt; <br>
&gt; Yes I would like to work on pending features.<br>
&gt; Also please let us know the new development items.<br>
<br>
Thanks, I will post later after gathering the first round<br>
suggestions to mailing lists. We have time to improve this<br>
filesystem. :)<br>
<br>
Thanks,<br>
Gao Xiang<br>
<br>
&gt; <br>
&gt; --Pratik<br>
&gt; <br>
&gt; On Wed, 9 Oct, 2019, 12:24 PM Gao Xiang, &lt;<a href="mailto:gaoxiang25@huawei.com" target="_blank">gaoxiang25@huawei.com</a>&gt; wrote:<br>
&gt; <br>
&gt; &gt; Hi Pratik,<br>
&gt; &gt;<br>
&gt; &gt; On Wed, Oct 09, 2019 at 11:59:01AM +0530, Pratik Shinde wrote:<br>
&gt; &gt; &gt; Hi Gao,<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Yes I can work on it. Sorry I missed this mail. I think your approach is<br>
&gt; &gt; &gt; good. Let me go through it one more time and reply back.<br>
&gt; &gt;<br>
&gt; &gt; Thanks for your reply and interest :)<br>
&gt; &gt; I think we can complete all pending features together<br>
&gt; &gt; if you have some time on this stuff. (fsdebug utility is<br>
&gt; &gt; on the way as well...)<br>
&gt; &gt;<br>
&gt; &gt; BTW, I&#39;m now investigating new high CR algorithm (very likely<br>
&gt; &gt; XZ) as well, it will be likely a RFC version in this round for<br>
&gt; &gt; wider scenarios and later decompression subsystem.<br>
&gt; &gt;<br>
&gt; &gt; Preliminary TODO lists will be discussed in this year China<br>
&gt; &gt; Linux Storage &amp; Filesystem workshop (next week) and will be<br>
&gt; &gt; posted to mailing lists for further wider discussion (if more<br>
&gt; &gt; folks have interest in developing it) as well. :)<br>
&gt; &gt;<br>
&gt; &gt; Thanks,<br>
&gt; &gt; Gao Xiang<br>
&gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; --Pratik<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, &lt;<a href="mailto:hsiangkao@aol.com" target="_blank">hsiangkao@aol.com</a>&gt; wrote:<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Hi Pratik,<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:<br>
&gt; &gt; &gt; &gt; &gt; Hi Gao,<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; I completely understand your concern.You can drop this patch for now.<br>
&gt; &gt; &gt; &gt; &gt; Once erofs makes it &#39;fs/&#39; please do reconsider implementing it.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; I think we can work on this pending feature for v5.5 now.<br>
&gt; &gt; &gt; &gt; My idea is to add an extra field in erofs_super_block to<br>
&gt; &gt; &gt; &gt; indicate the number of blocks (4k) for checking.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; So for small images, this feature can checksum the whole image at mount<br>
&gt; &gt; &gt; &gt; time,<br>
&gt; &gt; &gt; &gt; and for large images, this feature can be used to checksum the super<br>
&gt; &gt; block<br>
&gt; &gt; &gt; &gt; only<br>
&gt; &gt; &gt; &gt; (and then use verficiation subsystem to verify on-the-fly in the<br>
&gt; &gt; future...)<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; The following workflow is for erofs-utils, I think it&#39;s<br>
&gt; &gt; &gt; &gt;  1) erofs_mkfs_update_super_block with checksum = 0<br>
&gt; &gt; &gt; &gt;  2) erofs_bflush(NULL)<br>
&gt; &gt; &gt; &gt;  3) reread the corresponding blocks and calculate checksum;<br>
&gt; &gt; &gt; &gt;  4) write checksum to erofs_super_block;<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Does it sound reasonable? and do you still have interest and<br>
&gt; &gt; &gt; &gt; time for this? Looking forword to your reply...<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; Thanks,<br>
&gt; &gt; &gt; &gt; Gao Xiang<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; One more thing, can we still send non feature patches?<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; --Pratik<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, &lt;<a href="mailto:hsiangkao@aol.com" target="_blank">hsiangkao@aol.com</a>&gt; wrote:<br>
&gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; Hi Pratik,<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; Adding code for superblock checksum calculation.<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; incorporated the changes suggested in previous patch.<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; Signed-off-by: Pratik Shinde &lt;<a href="mailto:pratikshinde320@gmail.com" target="_blank">pratikshinde320@gmail.com</a>&gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; Thanks for your v2 patch.<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; Actually, I have some concern about the length of checksum,<br>
&gt; &gt; &gt; &gt; &gt; &gt; sizeof(struct erofs_super_block) could be changed in the<br>
&gt; &gt; &gt; &gt; &gt; &gt; later version, it&#39;s bad for EROFS future scalablity.<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; And I tend not to add another on-disk field to record<br>
&gt; &gt; &gt; &gt; &gt; &gt; the size of erofs_super_block as well, because the old<br>
&gt; &gt; &gt; &gt; &gt; &gt; Linux kernel cannot handle more about the new size,<br>
&gt; &gt; &gt; &gt; &gt; &gt; so it has little use except for checksum calculation.<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; Few hours ago, I discussed with Chao about this concern,<br>
&gt; &gt; &gt; &gt; &gt; &gt; I think this feature can be changed to do multiple-block<br>
&gt; &gt; &gt; &gt; &gt; &gt; checksum at the mount time, e.g:<br>
&gt; &gt; &gt; &gt; &gt; &gt;  - for small images, we can check the whole image once<br>
&gt; &gt; &gt; &gt; &gt; &gt;    at the mount time;<br>
&gt; &gt; &gt; &gt; &gt; &gt;  - for the large image, we can check the superblock<br>
&gt; &gt; &gt; &gt; &gt; &gt;    at the mount time, the rest can be handled by<br>
&gt; &gt; &gt; &gt; &gt; &gt;    block-based verification layer.<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; But we agreed that don&#39;t add this for this round<br>
&gt; &gt; &gt; &gt; &gt; &gt; since it&#39;s quite a new feature.<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; All in all, it&#39;s a new feature since we are addressing moving<br>
&gt; &gt; &gt; &gt; &gt; &gt; out of staging for this round. I tend to postpone this feature<br>
&gt; &gt; &gt; &gt; &gt; &gt; for now. I understand that you are very interested in EROFS.<br>
&gt; &gt; &gt; &gt; &gt; &gt; Considering EROFS current staging status, it&#39;s not such a place<br>
&gt; &gt; &gt; &gt; &gt; &gt; to add new features at all! I have marked your patch down and<br>
&gt; &gt; &gt; &gt; &gt; &gt; I will work with you later. Hope to get your understanding...<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; Thanks,<br>
&gt; &gt; &gt; &gt; &gt; &gt; Gao Xiang<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; ---<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  include/erofs/config.h |  1 +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  include/erofs_fs.h     | 10 ++++++++<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  mkfs/main.c            | 64<br>
&gt; &gt; &gt; &gt; &gt; &gt; +++++++++++++++++++++++++++++++++++++++++++++++++-<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  3 files changed, 74 insertions(+), 1 deletion(-)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; diff --git a/include/erofs/config.h b/include/erofs/config.h<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; index 05fe6b2..40cd466 100644<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; --- a/include/erofs/config.h<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +++ b/include/erofs/config.h<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -22,6 +22,7 @@ struct erofs_configure {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       char *c_src_path;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       char *c_compr_alg_master;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       int c_compr_level_master;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     int c_feature_flags;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  };<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  extern struct erofs_configure cfg;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; diff --git a/include/erofs_fs.h b/include/erofs_fs.h<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; index 601b477..9ac2635 100644<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; --- a/include/erofs_fs.h<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +++ b/include/erofs_fs.h<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -20,6 +20,16 @@<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  #define EROFS_ALL_REQUIREMENTS<br>
&gt; &gt; &gt; &gt; &gt; &gt;  EROFS_REQUIREMENT_LZ4_0PADDING<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +/*<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; + * feature definations.<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; + */<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +#define EROFS_DEFAULT_FEATURES<br>
&gt; &gt;  EROFS_FEATURE_SB_CHKSUM<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +#define EROFS_FEATURE_SB_CHKSUM              0x0001<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     ( le32_to_cpu((super)-&gt;features) &amp; (mask) )<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  struct erofs_super_block {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  /*  0 */__le32 magic;           /* in the little endian */<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  /*  4 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; diff --git a/mkfs/main.c b/mkfs/main.c<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; index f127fe1..355fd2c 100644<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; --- a/mkfs/main.c<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +++ b/mkfs/main.c<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -31,6 +31,45 @@ static void usage(void)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       fprintf(stderr, &quot; -EX[,...] X=extended options\n&quot;);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +#define CRCPOLY      0x82F63B78<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +static inline u32 crc32c(u32 seed, unsigned char const *in,<br>
&gt; &gt; size_t<br>
&gt; &gt; &gt; &gt; len)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +{<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     int i;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     u32 crc = seed;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     while (len--) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             crc ^= *in++;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             for (i = 0; i &lt; 8; i++) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     crc = (crc &gt;&gt; 1) ^ ((crc &amp; 1) ? CRCPOLY :<br>
&gt; &gt; 0);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     erofs_dump(&quot;calculated crc: 0x%x\n&quot;, crc);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     return crc;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +}<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +char *feature_opts[] = {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     &quot;nosbcrc&quot;, NULL<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +};<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +#define O_SB_CKSUM   0<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +static int parse_feature_subopts(char *opts)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +{<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     char *arg;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     while (*opts != &#39;\0&#39;) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             switch(getsubopt(&amp;opts, feature_opts, &amp;arg)) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             case O_SB_CKSUM:<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     cfg.c_feature_flags |=<br>
&gt; &gt; &gt; &gt; (~EROFS_FEATURE_SB_CHKSUM);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     break;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             default:<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     erofs_err(&quot;incorrect suboption&quot;);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     return -EINVAL;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     return 0;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +}<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  static int parse_extended_opts(const char *opts)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  #define MATCH_EXTENTED_OPT(opt, token, keylen) \<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int argc,<br>
&gt; &gt; char<br>
&gt; &gt; &gt; &gt; &gt; &gt; *argv[])<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       int opt, i;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; -     while ((opt = getopt(argc, argv, &quot;d:z:E:&quot;)) != -1) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     while ((opt = getopt(argc, argv, &quot;d:z:E:o:&quot;)) != -1) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               switch (opt) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               case &#39;z&#39;:<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;                       if (!optarg) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int argc,<br>
&gt; &gt; char<br>
&gt; &gt; &gt; &gt; &gt; &gt; *argv[])<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;                               return opt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;                       break;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             case &#39;O&#39;:<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     opt = parse_feature_subopts(optarg);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     if (opt)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                             return opt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                     break;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               default: /* &#39;?&#39; */<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;                       return -EINVAL;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int argc,<br>
&gt; &gt; char<br>
&gt; &gt; &gt; &gt; &gt; &gt; *argv[])<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       return 0;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +u32 erofs_superblock_checksum(struct erofs_super_block *sb)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +{<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     u32 crc;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     crc = crc32c(~0, (const unsigned char *)sb,<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +                 sizeof(struct erofs_super_block));<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     erofs_dump(&quot;superblock checksum: 0x%x\n&quot;, crc);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     return crc;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +}<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;                                 erofs_nid_t root_nid)<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;  {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct<br>
&gt; &gt; &gt; &gt; &gt; &gt; erofs_buffer_head *bh,<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               .meta_blkaddr  = sbi.meta_blkaddr,<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               .xattr_blkaddr = 0,<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               .requirements = cpu_to_le32(sbi.requirements),<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             .features = cpu_to_le32(cfg.c_feature_flags),<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       };<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       const unsigned int sb_blksize =<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct<br>
&gt; &gt; &gt; &gt; &gt; &gt; erofs_buffer_head *bh,<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       sb.root_nid     = cpu_to_le16(root_nid);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     if (EROFS_HAS_COMPAT_FEATURE(&amp;sb,<br>
&gt; &gt; EROFS_FEATURE_SB_CHKSUM)) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             sb.checksum = 0;<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             u32 crc = erofs_superblock_checksum(&amp;sb);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +             sb.checksum = cpu_to_le32(crc);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +     }<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; +<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       buf = calloc(sb_blksize, 1);<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;       if (!buf) {<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;               erofs_err(&quot;Failed to allocate memory for sb: %s&quot;,<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; --<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt; 2.9.3<br>
&gt; &gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt;<br>
</blockquote></div>

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-10-09 14:14               ` Pratik Shinde
@ 2019-10-09 14:27                 ` Gao Xiang via Linux-erofs
  0 siblings, 0 replies; 19+ messages in thread
From: Gao Xiang via Linux-erofs @ 2019-10-09 14:27 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: linux-erofs, miaoxie

Hi Pratik,

On Wed, Oct 09, 2019 at 07:44:08PM +0530, Pratik Shinde wrote:
> Hello Gao,
> 
> I have few questions regarding the checksum feature:
> 1) Are we still keeping it as a feature. (i.e enabled by default . but can
> be disabled during mkfs)

Yes, I think it should be a new compatible feature suggested by Richard
and enabled by default (this feature should be marked in on-disk
super_block...)

> 2) For small images we are going to cksum the entire image. what could be
> the maximum size of 'small' images.

I think we can checksum the first 4k for now in mkfs by default
(or only checksum 4k as the first step), and then it can be
configured to a larger number n*4k. (But for the kernel side,
it has to be fully implemented due to forward compatibility.)

> 
> also, I think we don't have routines to read buffers back into the memory.
> I will write them first and send a patch.

Yes, I remembered that you once wrote a similar function, that is ok.
And it's no rush, we have more than a month to develop pending features
for linux-5.5. Just a reminder because we can prepare them for now :)

Thanks,
Gao Xiang

> 
> -Pratik
> 
> On Wed, Oct 9, 2019 at 2:14 PM Gao Xiang <gaoxiang25@huawei.com> wrote:
> 
> > Hi Pratik,
> >
> > On Wed, Oct 09, 2019 at 01:54:40PM +0530, Pratik Shinde wrote:
> > > Hello Gao,
> > >
> > > Yes I would like to work on pending features.
> > > Also please let us know the new development items.
> >
> > Thanks, I will post later after gathering the first round
> > suggestions to mailing lists. We have time to improve this
> > filesystem. :)
> >
> > Thanks,
> > Gao Xiang
> >
> > >
> > > --Pratik
> > >
> > > On Wed, 9 Oct, 2019, 12:24 PM Gao Xiang, <gaoxiang25@huawei.com> wrote:
> > >
> > > > Hi Pratik,
> > > >
> > > > On Wed, Oct 09, 2019 at 11:59:01AM +0530, Pratik Shinde wrote:
> > > > > Hi Gao,
> > > > >
> > > > > Yes I can work on it. Sorry I missed this mail. I think your
> > approach is
> > > > > good. Let me go through it one more time and reply back.
> > > >
> > > > Thanks for your reply and interest :)
> > > > I think we can complete all pending features together
> > > > if you have some time on this stuff. (fsdebug utility is
> > > > on the way as well...)
> > > >
> > > > BTW, I'm now investigating new high CR algorithm (very likely
> > > > XZ) as well, it will be likely a RFC version in this round for
> > > > wider scenarios and later decompression subsystem.
> > > >
> > > > Preliminary TODO lists will be discussed in this year China
> > > > Linux Storage & Filesystem workshop (next week) and will be
> > > > posted to mailing lists for further wider discussion (if more
> > > > folks have interest in developing it) as well. :)
> > > >
> > > > Thanks,
> > > > Gao Xiang
> > > >
> > > > >
> > > > > --Pratik
> > > > >
> > > > > On Sun, 6 Oct, 2019, 11:09 AM Gao Xiang, <hsiangkao@aol.com> wrote:
> > > > >
> > > > > > Hi Pratik,
> > > > > >
> > > > > > On Sat, Aug 24, 2019 at 08:26:28PM +0530, Pratik Shinde wrote:
> > > > > > > Hi Gao,
> > > > > > >
> > > > > > > I completely understand your concern.You can drop this patch for
> > now.
> > > > > > > Once erofs makes it 'fs/' please do reconsider implementing it.
> > > > > >
> > > > > > I think we can work on this pending feature for v5.5 now.
> > > > > > My idea is to add an extra field in erofs_super_block to
> > > > > > indicate the number of blocks (4k) for checking.
> > > > > >
> > > > > > So for small images, this feature can checksum the whole image at
> > mount
> > > > > > time,
> > > > > > and for large images, this feature can be used to checksum the
> > super
> > > > block
> > > > > > only
> > > > > > (and then use verficiation subsystem to verify on-the-fly in the
> > > > future...)
> > > > > >
> > > > > > The following workflow is for erofs-utils, I think it's
> > > > > >  1) erofs_mkfs_update_super_block with checksum = 0
> > > > > >  2) erofs_bflush(NULL)
> > > > > >  3) reread the corresponding blocks and calculate checksum;
> > > > > >  4) write checksum to erofs_super_block;
> > > > > >
> > > > > > Does it sound reasonable? and do you still have interest and
> > > > > > time for this? Looking forword to your reply...
> > > > > >
> > > > > > Thanks,
> > > > > > Gao Xiang
> > > > > >
> > > > > > >
> > > > > > > One more thing, can we still send non feature patches?
> > > > > > >
> > > > > > > --Pratik
> > > > > > >
> > > > > > >
> > > > > > > On Sat, 24 Aug, 2019, 7:30 PM Gao Xiang, <hsiangkao@aol.com>
> > wrote:
> > > > > > >
> > > > > > > > Hi Pratik,
> > > > > > > >
> > > > > > > > On Sat, Aug 24, 2019 at 06:08:03PM +0530, Pratik Shinde wrote:
> > > > > > > > > Adding code for superblock checksum calculation.
> > > > > > > > >
> > > > > > > > > incorporated the changes suggested in previous patch.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> > > > > > > >
> > > > > > > > Thanks for your v2 patch.
> > > > > > > >
> > > > > > > > Actually, I have some concern about the length of checksum,
> > > > > > > > sizeof(struct erofs_super_block) could be changed in the
> > > > > > > > later version, it's bad for EROFS future scalablity.
> > > > > > > >
> > > > > > > > And I tend not to add another on-disk field to record
> > > > > > > > the size of erofs_super_block as well, because the old
> > > > > > > > Linux kernel cannot handle more about the new size,
> > > > > > > > so it has little use except for checksum calculation.
> > > > > > > >
> > > > > > > > Few hours ago, I discussed with Chao about this concern,
> > > > > > > > I think this feature can be changed to do multiple-block
> > > > > > > > checksum at the mount time, e.g:
> > > > > > > >  - for small images, we can check the whole image once
> > > > > > > >    at the mount time;
> > > > > > > >  - for the large image, we can check the superblock
> > > > > > > >    at the mount time, the rest can be handled by
> > > > > > > >    block-based verification layer.
> > > > > > > >
> > > > > > > > But we agreed that don't add this for this round
> > > > > > > > since it's quite a new feature.
> > > > > > > >
> > > > > > > > All in all, it's a new feature since we are addressing moving
> > > > > > > > out of staging for this round. I tend to postpone this feature
> > > > > > > > for now. I understand that you are very interested in EROFS.
> > > > > > > > Considering EROFS current staging status, it's not such a place
> > > > > > > > to add new features at all! I have marked your patch down and
> > > > > > > > I will work with you later. Hope to get your understanding...
> > > > > > > >
> > > > > > > > Thanks,
> > > > > > > > Gao Xiang
> > > > > > > >
> > > > > > > > > ---
> > > > > > > > >  include/erofs/config.h |  1 +
> > > > > > > > >  include/erofs_fs.h     | 10 ++++++++
> > > > > > > > >  mkfs/main.c            | 64
> > > > > > > > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > > > > > > > >  3 files changed, 74 insertions(+), 1 deletion(-)
> > > > > > > > >
> > > > > > > > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > > > > > > > index 05fe6b2..40cd466 100644
> > > > > > > > > --- a/include/erofs/config.h
> > > > > > > > > +++ b/include/erofs/config.h
> > > > > > > > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > > > > > > > >       char *c_src_path;
> > > > > > > > >       char *c_compr_alg_master;
> > > > > > > > >       int c_compr_level_master;
> > > > > > > > > +     int c_feature_flags;
> > > > > > > > >  };
> > > > > > > > >
> > > > > > > > >  extern struct erofs_configure cfg;
> > > > > > > > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > > > > > > > index 601b477..9ac2635 100644
> > > > > > > > > --- a/include/erofs_fs.h
> > > > > > > > > +++ b/include/erofs_fs.h
> > > > > > > > > @@ -20,6 +20,16 @@
> > > > > > > > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > > > > > > > >  #define EROFS_ALL_REQUIREMENTS
> > > > > > > >  EROFS_REQUIREMENT_LZ4_0PADDING
> > > > > > > > >
> > > > > > > > > +/*
> > > > > > > > > + * feature definations.
> > > > > > > > > + */
> > > > > > > > > +#define EROFS_DEFAULT_FEATURES
> > > >  EROFS_FEATURE_SB_CHKSUM
> > > > > > > > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > > > > > > > +
> > > > > > > > > +
> > > > > > > > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > > > > > > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > > > > > > > +
> > > > > > > > >  struct erofs_super_block {
> > > > > > > > >  /*  0 */__le32 magic;           /* in the little endian */
> > > > > > > > >  /*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > > > > > > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > > > > > > > index f127fe1..355fd2c 100644
> > > > > > > > > --- a/mkfs/main.c
> > > > > > > > > +++ b/mkfs/main.c
> > > > > > > > > @@ -31,6 +31,45 @@ static void usage(void)
> > > > > > > > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > > +#define CRCPOLY      0x82F63B78
> > > > > > > > > +static inline u32 crc32c(u32 seed, unsigned char const *in,
> > > > size_t
> > > > > > len)
> > > > > > > > > +{
> > > > > > > > > +     int i;
> > > > > > > > > +     u32 crc = seed;
> > > > > > > > > +
> > > > > > > > > +     while (len--) {
> > > > > > > > > +             crc ^= *in++;
> > > > > > > > > +             for (i = 0; i < 8; i++) {
> > > > > > > > > +                     crc = (crc >> 1) ^ ((crc & 1) ?
> > CRCPOLY :
> > > > 0);
> > > > > > > > > +             }
> > > > > > > > > +     }
> > > > > > > > > +     erofs_dump("calculated crc: 0x%x\n", crc);
> > > > > > > > > +     return crc;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > > +char *feature_opts[] = {
> > > > > > > > > +     "nosbcrc", NULL
> > > > > > > > > +};
> > > > > > > > > +#define O_SB_CKSUM   0
> > > > > > > > > +
> > > > > > > > > +static int parse_feature_subopts(char *opts)
> > > > > > > > > +{
> > > > > > > > > +     char *arg;
> > > > > > > > > +
> > > > > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > > > > +     while (*opts != '\0') {
> > > > > > > > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > > > > > > > +             case O_SB_CKSUM:
> > > > > > > > > +                     cfg.c_feature_flags |=
> > > > > > (~EROFS_FEATURE_SB_CHKSUM);
> > > > > > > > > +                     break;
> > > > > > > > > +             default:
> > > > > > > > > +                     erofs_err("incorrect suboption");
> > > > > > > > > +                     return -EINVAL;
> > > > > > > > > +             }
> > > > > > > > > +     }
> > > > > > > > > +     return 0;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >  static int parse_extended_opts(const char *opts)
> > > > > > > > >  {
> > > > > > > > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > > > > > > > @@ -79,7 +118,8 @@ static int mkfs_parse_options_cfg(int
> > argc,
> > > > char
> > > > > > > > *argv[])
> > > > > > > > >  {
> > > > > > > > >       int opt, i;
> > > > > > > > >
> > > > > > > > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > > > > > > > +     cfg.c_feature_flags = EROFS_DEFAULT_FEATURES;
> > > > > > > > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > > > > > > > >               switch (opt) {
> > > > > > > > >               case 'z':
> > > > > > > > >                       if (!optarg) {
> > > > > > > > > @@ -113,6 +153,12 @@ static int mkfs_parse_options_cfg(int
> > argc,
> > > > char
> > > > > > > > *argv[])
> > > > > > > > >                               return opt;
> > > > > > > > >                       break;
> > > > > > > > >
> > > > > > > > > +             case 'O':
> > > > > > > > > +                     opt = parse_feature_subopts(optarg);
> > > > > > > > > +                     if (opt)
> > > > > > > > > +                             return opt;
> > > > > > > > > +                     break;
> > > > > > > > > +
> > > > > > > > >               default: /* '?' */
> > > > > > > > >                       return -EINVAL;
> > > > > > > > >               }
> > > > > > > > > @@ -144,6 +190,15 @@ static int mkfs_parse_options_cfg(int
> > argc,
> > > > char
> > > > > > > > *argv[])
> > > > > > > > >       return 0;
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > > > > > > > +{
> > > > > > > > > +     u32 crc;
> > > > > > > > > +     crc = crc32c(~0, (const unsigned char *)sb,
> > > > > > > > > +                 sizeof(struct erofs_super_block));
> > > > > > > > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > > > > > > > +     return crc;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head
> > *bh,
> > > > > > > > >                                 erofs_nid_t root_nid)
> > > > > > > > >  {
> > > > > > > > > @@ -155,6 +210,7 @@ int erofs_mkfs_update_super_block(struct
> > > > > > > > erofs_buffer_head *bh,
> > > > > > > > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > > > > > > > >               .xattr_blkaddr = 0,
> > > > > > > > >               .requirements = cpu_to_le32(sbi.requirements),
> > > > > > > > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > > > > > > > >       };
> > > > > > > > >       const unsigned int sb_blksize =
> > > > > > > > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > > > > > > > @@ -169,6 +225,12 @@ int erofs_mkfs_update_super_block(struct
> > > > > > > > erofs_buffer_head *bh,
> > > > > > > > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > > > > > > > >       sb.root_nid     = cpu_to_le16(root_nid);
> > > > > > > > >
> > > > > > > > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb,
> > > > EROFS_FEATURE_SB_CHKSUM)) {
> > > > > > > > > +             sb.checksum = 0;
> > > > > > > > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > > > > > > > +             sb.checksum = cpu_to_le32(crc);
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > >       buf = calloc(sb_blksize, 1);
> > > > > > > > >       if (!buf) {
> > > > > > > > >               erofs_err("Failed to allocate memory for sb:
> > %s",
> > > > > > > > > --
> > > > > > > > > 2.9.3
> > > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> >

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24 10:05         ` Pratik Shinde
@ 2019-08-24 10:14           ` Gao Xiang via Linux-erofs
  0 siblings, 0 replies; 19+ messages in thread
From: Gao Xiang via Linux-erofs @ 2019-08-24 10:14 UTC (permalink / raw)
  To: Pratik Shinde, Chao Yu; +Cc: linux-erofs

Hi Pratik, and Chao,

On Sat, Aug 24, 2019 at 03:35:40PM +0530, Pratik Shinde wrote:
> Thanks Chao,
> 
> Initially I was of doing the same, but then I thought changing the position
> of cheksum field to either start OR end
> will be much simpler.

To Pratik: erofs layout is almost determined from linux-4.19, and it is fine
           for this chksum field;

> I think I will go with Gao's method. thereby not changing the layout of
> super-block.
> So just to be clear, I will be writing our own crc32c() function correct ?

           Yes, just go with crc32c(). and it's very simple to implement :)

> 
> --Pratik.
> 
> On Sat, Aug 24, 2019 at 3:31 PM Chao Yu <chao@kernel.org> wrote:
> 
> > On 2019-8-24 17:49, Gao Xiang via Linux-erofs wrote:
> > > Hi Pratik,
> > >
> > > On Sat, Aug 24, 2019 at 02:52:31PM +0530, Pratik Shinde wrote:
> > >> Hi Gao,
> > >> Yes I will make the suboption naming similar to that of mk2fs.
> > >
> > > Great! :)
> > >
> > >>
> > >> The reason I changed the position of 'checksum' field :
> > >>
> > >> Since we are calculating the checksum of erofs_super_block structure and
> > >> storing it in the same structure; we cannot include
> > >> this field for actual crc calculations. Keeping it at the end makes it
> > easy
> > >> for me to calculate length of the data of which
> > >> checksum needs to be calculated. I saw similar logic in other
> > filesystems
> > >> like ext4.
> > >
> > > No, that is just they didn't add checksum field at the beginning of its
> > design.
> > > I think you can leave chksum to 0, and calculate chksum and fill it, to
> > be specfic:
> > >
> > > In the erofs-utils,
> > >  1) fill .checksum to 0;
> > >  2) calculate crc32c of the entire erofs_super_block;
> > >  3) fill the real checksum to .checksum;
> > >
> > > In the kernel,
> > >  1) read .checksum to a variable;
> > >  2) fill .checksum to 0;
> > >  3) calculate crc32c of the entire erofs_super_block;
> > >  4) compare the given one and the calculated one;
> >
> > That's one way, FYI, the way used in ext4/f2fs now is:
> > - calc [0, checksum]'s chksum
> > - use above chksum as seed of chksum within range [chksum + chksum_size,
> > end]
> > - fill chksum value in range [checksum, chksum + chksum_size]

To Chao: Yes, I think that's ok as well, but we can do much simple in EROFS,
         and it won't break crc32c pipeline... (calculate in one crc32c function) :)

Thanks,
Gao Xiang

> >
> > Thanks,
> >
> > >
> > > That is all :)
> > >
> > >>
> > >> We can write our own crc32() function. :) There is no problem. I thought
> > >> zlib already provides one & we can use it.
> > >
> > > I think we can use crc32c() since I already wrote comments for erofs in
> > 4.19.
> > >
> > > Looking forward to your next version :)
> > >
> > > Thanks,
> > > Gao Xiang
> > >
> > >> anyways , I will write.
> > >>
> > >> --Pratik.
> > >>
> > >> On Sat, Aug 24, 2019 at 2:16 PM Gao Xiang <hsiangkao@gmx.com> wrote:
> > >>
> > >>> Hi Pratik,
> > >>>
> > >>> On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:
> > >>>> Adding code for superblock checksum calculation.
> > >>>>
> > >>>> This patch adds following things:
> > >>>> 1)Handle suboptions('-o') to mkfs utility.
> > >>>
> > >>> Thanks for your patch. :)
> > >>>
> > >>> Can we use "-O feature" instead in order to keep in line with mke2fs?
> > >>>
> > >>>> 2)Add superblock checksum calculation(-o sb_cksum) as suboption.
> > >>>
> > >>> ditto. and I think we can enable sbcrc by default since it is a compat
> > >>> feature,
> > >>> and add "-O nosbcrc" to disable it.
> > >>>
> > >>>> 3)Calculate superblock checksum if feature is enabled.
> > >>>>
> > >>>> Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> > >>>
> > >>> And could you please also read my following comments and fix them.
> > >>> and I'd like to accept your erofs-utils modification in advance. :)
> > >>>
> > >>>
> > >>> But now you can see we are moving EROFS out of staging now as
> > >>> the "real" part of Linux, this is the fundamental stuff of other
> > >>> new features if we want to develop more actively... So we can wait
> > >>> for the final result and add this new feature to kernel then...
> > >>>
> > >>>> ---
> > >>>>  include/erofs/config.h |  1 +
> > >>>>  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------
> > >>>>  mkfs/main.c            | 53
> > >>> +++++++++++++++++++++++++++++++++++++++++++++++++-
> > >>>>  3 files changed, 76 insertions(+), 18 deletions(-)
> > >>>>
> > >>>> diff --git a/include/erofs/config.h b/include/erofs/config.h
> > >>>> index 05fe6b2..40cd466 100644
> > >>>> --- a/include/erofs/config.h
> > >>>> +++ b/include/erofs/config.h
> > >>>> @@ -22,6 +22,7 @@ struct erofs_configure {
> > >>>>       char *c_src_path;
> > >>>>       char *c_compr_alg_master;
> > >>>>       int c_compr_level_master;
> > >>>> +     int c_feature_flags;
> > >>>
> > >>> we can add this to sbi like requirements...
> > >>>
> > >>>>  };
> > >>>>
> > >>>>  extern struct erofs_configure cfg;
> > >>>> diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > >>>> index 601b477..c9ef057 100644
> > >>>> --- a/include/erofs_fs.h
> > >>>> +++ b/include/erofs_fs.h
> > >>>> @@ -20,25 +20,31 @@
> > >>>>  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > >>>>  #define EROFS_ALL_REQUIREMENTS
> > >>>  EROFS_REQUIREMENT_LZ4_0PADDING
> > >>>>
> > >>>> +/*
> > >>>> + * feature definations.
> > >>>> + */
> > >>>> +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > >>>> +
> > >>>> +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > >>>> +     ( le32_to_cpu((super)->features) & (mask) )
> > >>>> +
> > >>>>  struct erofs_super_block {
> > >>>>  /*  0 */__le32 magic;           /* in the little endian */
> > >>>> -/*  4 */__le32 checksum;        /* crc32c(super_block) */
> > >>>> -/*  8 */__le32 features;        /* (aka. feature_compat) */
> > >>>> -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE
> > only
> > >>> */
> > >>>> -/* 13 */__u8 reserved;
> > >>>> -
> > >>>> -/* 14 */__le16 root_nid;
> > >>>> -/* 16 */__le64 inos;            /* total valid ino # (== f_files -
> > >>> f_favail) */
> > >>>> -
> > >>>> -/* 24 */__le64 build_time;      /* inode v1 time derivation */
> > >>>> -/* 32 */__le32 build_time_nsec;
> > >>>> -/* 36 */__le32 blocks;          /* used for statfs */
> > >>>> -/* 40 */__le32 meta_blkaddr;
> > >>>> -/* 44 */__le32 xattr_blkaddr;
> > >>>> -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */
> > >>>> -/* 64 */__u8 volume_name[16];   /* volume name */
> > >>>> -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */
> > >>>> -
> > >>>> +/*  4 */__le32 features;        /* (aka. feature_compat) */
> > >>>> +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE
> > only
> > >>> */
> > >>>> +/*  9 */__u8 reserved;
> > >>>> +
> > >>>> +/* 10 */__le16 root_nid;
> > >>>> +/* 12 */__le64 inos;            /* total valid ino # (== f_files -
> > >>> f_favail) */
> > >>>> +/* 20 */__le64 build_time;      /* inode v1 time derivation */
> > >>>> +/* 28 */__le32 build_time_nsec;
> > >>>> +/* 32 */__le32 blocks;          /* used for statfs */
> > >>>> +/* 36 */__le32 meta_blkaddr;
> > >>>> +/* 40 */__le32 xattr_blkaddr;
> > >>>> +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */
> > >>>> +/* 60 */__u8 volume_name[16];   /* volume name */
> > >>>> +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */
> > >>>> +/* 80 */__le32 checksum;        /* crc32c(super_block) */
> > >>>>  /* 84 */__u8 reserved2[44];
> > >>>
> > >>> Why modifying the above?
> > >>>
> > >>>>  } __packed;                     /* 128 bytes */
> > >>>>
> > >>>> diff --git a/mkfs/main.c b/mkfs/main.c
> > >>>> index f127fe1..26e14a3 100644
> > >>>> --- a/mkfs/main.c
> > >>>> +++ b/mkfs/main.c
> > >>>> @@ -13,12 +13,14 @@
> > >>>>  #include <limits.h>
> > >>>>  #include <libgen.h>
> > >>>>  #include <sys/stat.h>
> > >>>> +#include <zlib.h>
> > >>>
> > >>> I have no idea that we should introduce "zlib" just for crc32c
> > currently...
> > >>> Maybe we can add some independent crc32 function..
> > >>>
> > >>> Thanks,
> > >>> Gao Xiang
> > >>>
> > >>>>  #include "erofs/config.h"
> > >>>>  #include "erofs/print.h"
> > >>>>  #include "erofs/cache.h"
> > >>>>  #include "erofs/inode.h"
> > >>>>  #include "erofs/io.h"
> > >>>>  #include "erofs/compress.h"
> > >>>> +#include "erofs/defs.h"
> > >>>>
> > >>>>  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct
> > >>> erofs_super_block))
> > >>>>
> > >>>> @@ -31,6 +33,28 @@ static void usage(void)
> > >>>>       fprintf(stderr, " -EX[,...] X=extended options\n");
> > >>>>  }
> > >>>>
> > >>>> +char *feature_opts[] = {
> > >>>> +     "sb_cksum", NULL
> > >>>> +};
> > >>>> +#define O_SB_CKSUM   0
> > >>>> +
> > >>>> +static int parse_feature_subopts(char *opts)
> > >>>> +{
> > >>>> +     char *arg;
> > >>>> +
> > >>>> +     while (*opts != '\0') {
> > >>>> +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > >>>> +             case O_SB_CKSUM:
> > >>>> +                     cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;
> > >>>> +                     break;
> > >>>> +             default:
> > >>>> +                     erofs_err("incorrect suboption");
> > >>>> +                     return -EINVAL;
> > >>>> +             }
> > >>>> +     }
> > >>>> +     return 0;
> > >>>> +}
> > >>>> +
> > >>>>  static int parse_extended_opts(const char *opts)
> > >>>>  {
> > >>>>  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > >>>> @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char
> > >>> *argv[])
> > >>>>  {
> > >>>>       int opt, i;
> > >>>>
> > >>>> -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > >>>> +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > >>>>               switch (opt) {
> > >>>>               case 'z':
> > >>>>                       if (!optarg) {
> > >>>> @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char
> > >>> *argv[])
> > >>>>                               return opt;
> > >>>>                       break;
> > >>>>
> > >>>> +             case 'o':
> > >>>> +                     opt = parse_feature_subopts(optarg);
> > >>>> +                     if (opt)
> > >>>> +                             return opt;
> > >>>> +                     break;
> > >>>> +
> > >>>>               default: /* '?' */
> > >>>>                       return -EINVAL;
> > >>>>               }
> > >>>> @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char
> > >>> *argv[])
> > >>>>       return 0;
> > >>>>  }
> > >>>>
> > >>>> +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > >>>> +{
> > >>>> +     int offset;
> > >>>> +     u32 crc;
> > >>>> +
> > >>>> +     offset = offsetof(struct erofs_super_block, checksum);
> > >>>> +     if (offset < 0 || offset > sizeof(struct erofs_super_block)) {
> > >>>> +             erofs_err("Invalid offset of checksum field: %d",
> > offset);
> > >>>> +             return -1;
> > >>>> +     }
> > >>>> +     crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);
> > >>>> +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > >>>> +     return 0;
> > >>>> +}
> > >>>> +
> > >>>>  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > >>>>                                 erofs_nid_t root_nid)
> > >>>>  {
> > >>>> @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct
> > >>> erofs_buffer_head *bh,
> > >>>>               .meta_blkaddr  = sbi.meta_blkaddr,
> > >>>>               .xattr_blkaddr = 0,
> > >>>>               .requirements = cpu_to_le32(sbi.requirements),
> > >>>> +             .features = cpu_to_le32(cfg.c_feature_flags),
> > >>>>       };
> > >>>>       const unsigned int sb_blksize =
> > >>>>               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > >>>> @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct
> > >>> erofs_buffer_head *bh,
> > >>>>       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > >>>>       sb.root_nid     = cpu_to_le16(root_nid);
> > >>>>
> > >>>> +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > >>>> +             u32 crc = erofs_superblock_checksum(&sb);
> > >>>> +             sb.checksum = cpu_to_le32(crc);
> > >>>> +     }
> > >>>> +
> > >>>>       buf = calloc(sb_blksize, 1);
> > >>>>       if (!buf) {
> > >>>>               erofs_err("Failed to allocate memory for sb: %s",
> > >>>> --
> > >>>> 2.9.3
> > >>>>
> > >>>
> >

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24 10:01       ` Chao Yu
@ 2019-08-24 10:05         ` Pratik Shinde
  2019-08-24 10:14           ` Gao Xiang via Linux-erofs
  0 siblings, 1 reply; 19+ messages in thread
From: Pratik Shinde @ 2019-08-24 10:05 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-erofs

[-- Attachment #1: Type: text/plain, Size: 11363 bytes --]

Thanks Chao,

Initially I was of doing the same, but then I thought changing the position
of cheksum field to either start OR end
will be much simpler.
I think I will go with Gao's method. thereby not changing the layout of
super-block.
So just to be clear, I will be writing our own crc32c() function correct ?

--Pratik.

On Sat, Aug 24, 2019 at 3:31 PM Chao Yu <chao@kernel.org> wrote:

> On 2019-8-24 17:49, Gao Xiang via Linux-erofs wrote:
> > Hi Pratik,
> >
> > On Sat, Aug 24, 2019 at 02:52:31PM +0530, Pratik Shinde wrote:
> >> Hi Gao,
> >> Yes I will make the suboption naming similar to that of mk2fs.
> >
> > Great! :)
> >
> >>
> >> The reason I changed the position of 'checksum' field :
> >>
> >> Since we are calculating the checksum of erofs_super_block structure and
> >> storing it in the same structure; we cannot include
> >> this field for actual crc calculations. Keeping it at the end makes it
> easy
> >> for me to calculate length of the data of which
> >> checksum needs to be calculated. I saw similar logic in other
> filesystems
> >> like ext4.
> >
> > No, that is just they didn't add checksum field at the beginning of its
> design.
> > I think you can leave chksum to 0, and calculate chksum and fill it, to
> be specfic:
> >
> > In the erofs-utils,
> >  1) fill .checksum to 0;
> >  2) calculate crc32c of the entire erofs_super_block;
> >  3) fill the real checksum to .checksum;
> >
> > In the kernel,
> >  1) read .checksum to a variable;
> >  2) fill .checksum to 0;
> >  3) calculate crc32c of the entire erofs_super_block;
> >  4) compare the given one and the calculated one;
>
> That's one way, FYI, the way used in ext4/f2fs now is:
> - calc [0, checksum]'s chksum
> - use above chksum as seed of chksum within range [chksum + chksum_size,
> end]
> - fill chksum value in range [checksum, chksum + chksum_size]
>
> Thanks,
>
> >
> > That is all :)
> >
> >>
> >> We can write our own crc32() function. :) There is no problem. I thought
> >> zlib already provides one & we can use it.
> >
> > I think we can use crc32c() since I already wrote comments for erofs in
> 4.19.
> >
> > Looking forward to your next version :)
> >
> > Thanks,
> > Gao Xiang
> >
> >> anyways , I will write.
> >>
> >> --Pratik.
> >>
> >> On Sat, Aug 24, 2019 at 2:16 PM Gao Xiang <hsiangkao@gmx.com> wrote:
> >>
> >>> Hi Pratik,
> >>>
> >>> On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:
> >>>> Adding code for superblock checksum calculation.
> >>>>
> >>>> This patch adds following things:
> >>>> 1)Handle suboptions('-o') to mkfs utility.
> >>>
> >>> Thanks for your patch. :)
> >>>
> >>> Can we use "-O feature" instead in order to keep in line with mke2fs?
> >>>
> >>>> 2)Add superblock checksum calculation(-o sb_cksum) as suboption.
> >>>
> >>> ditto. and I think we can enable sbcrc by default since it is a compat
> >>> feature,
> >>> and add "-O nosbcrc" to disable it.
> >>>
> >>>> 3)Calculate superblock checksum if feature is enabled.
> >>>>
> >>>> Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> >>>
> >>> And could you please also read my following comments and fix them.
> >>> and I'd like to accept your erofs-utils modification in advance. :)
> >>>
> >>>
> >>> But now you can see we are moving EROFS out of staging now as
> >>> the "real" part of Linux, this is the fundamental stuff of other
> >>> new features if we want to develop more actively... So we can wait
> >>> for the final result and add this new feature to kernel then...
> >>>
> >>>> ---
> >>>>  include/erofs/config.h |  1 +
> >>>>  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------
> >>>>  mkfs/main.c            | 53
> >>> +++++++++++++++++++++++++++++++++++++++++++++++++-
> >>>>  3 files changed, 76 insertions(+), 18 deletions(-)
> >>>>
> >>>> diff --git a/include/erofs/config.h b/include/erofs/config.h
> >>>> index 05fe6b2..40cd466 100644
> >>>> --- a/include/erofs/config.h
> >>>> +++ b/include/erofs/config.h
> >>>> @@ -22,6 +22,7 @@ struct erofs_configure {
> >>>>       char *c_src_path;
> >>>>       char *c_compr_alg_master;
> >>>>       int c_compr_level_master;
> >>>> +     int c_feature_flags;
> >>>
> >>> we can add this to sbi like requirements...
> >>>
> >>>>  };
> >>>>
> >>>>  extern struct erofs_configure cfg;
> >>>> diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> >>>> index 601b477..c9ef057 100644
> >>>> --- a/include/erofs_fs.h
> >>>> +++ b/include/erofs_fs.h
> >>>> @@ -20,25 +20,31 @@
> >>>>  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> >>>>  #define EROFS_ALL_REQUIREMENTS
> >>>  EROFS_REQUIREMENT_LZ4_0PADDING
> >>>>
> >>>> +/*
> >>>> + * feature definations.
> >>>> + */
> >>>> +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> >>>> +
> >>>> +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> >>>> +     ( le32_to_cpu((super)->features) & (mask) )
> >>>> +
> >>>>  struct erofs_super_block {
> >>>>  /*  0 */__le32 magic;           /* in the little endian */
> >>>> -/*  4 */__le32 checksum;        /* crc32c(super_block) */
> >>>> -/*  8 */__le32 features;        /* (aka. feature_compat) */
> >>>> -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE
> only
> >>> */
> >>>> -/* 13 */__u8 reserved;
> >>>> -
> >>>> -/* 14 */__le16 root_nid;
> >>>> -/* 16 */__le64 inos;            /* total valid ino # (== f_files -
> >>> f_favail) */
> >>>> -
> >>>> -/* 24 */__le64 build_time;      /* inode v1 time derivation */
> >>>> -/* 32 */__le32 build_time_nsec;
> >>>> -/* 36 */__le32 blocks;          /* used for statfs */
> >>>> -/* 40 */__le32 meta_blkaddr;
> >>>> -/* 44 */__le32 xattr_blkaddr;
> >>>> -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */
> >>>> -/* 64 */__u8 volume_name[16];   /* volume name */
> >>>> -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */
> >>>> -
> >>>> +/*  4 */__le32 features;        /* (aka. feature_compat) */
> >>>> +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE
> only
> >>> */
> >>>> +/*  9 */__u8 reserved;
> >>>> +
> >>>> +/* 10 */__le16 root_nid;
> >>>> +/* 12 */__le64 inos;            /* total valid ino # (== f_files -
> >>> f_favail) */
> >>>> +/* 20 */__le64 build_time;      /* inode v1 time derivation */
> >>>> +/* 28 */__le32 build_time_nsec;
> >>>> +/* 32 */__le32 blocks;          /* used for statfs */
> >>>> +/* 36 */__le32 meta_blkaddr;
> >>>> +/* 40 */__le32 xattr_blkaddr;
> >>>> +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */
> >>>> +/* 60 */__u8 volume_name[16];   /* volume name */
> >>>> +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */
> >>>> +/* 80 */__le32 checksum;        /* crc32c(super_block) */
> >>>>  /* 84 */__u8 reserved2[44];
> >>>
> >>> Why modifying the above?
> >>>
> >>>>  } __packed;                     /* 128 bytes */
> >>>>
> >>>> diff --git a/mkfs/main.c b/mkfs/main.c
> >>>> index f127fe1..26e14a3 100644
> >>>> --- a/mkfs/main.c
> >>>> +++ b/mkfs/main.c
> >>>> @@ -13,12 +13,14 @@
> >>>>  #include <limits.h>
> >>>>  #include <libgen.h>
> >>>>  #include <sys/stat.h>
> >>>> +#include <zlib.h>
> >>>
> >>> I have no idea that we should introduce "zlib" just for crc32c
> currently...
> >>> Maybe we can add some independent crc32 function..
> >>>
> >>> Thanks,
> >>> Gao Xiang
> >>>
> >>>>  #include "erofs/config.h"
> >>>>  #include "erofs/print.h"
> >>>>  #include "erofs/cache.h"
> >>>>  #include "erofs/inode.h"
> >>>>  #include "erofs/io.h"
> >>>>  #include "erofs/compress.h"
> >>>> +#include "erofs/defs.h"
> >>>>
> >>>>  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct
> >>> erofs_super_block))
> >>>>
> >>>> @@ -31,6 +33,28 @@ static void usage(void)
> >>>>       fprintf(stderr, " -EX[,...] X=extended options\n");
> >>>>  }
> >>>>
> >>>> +char *feature_opts[] = {
> >>>> +     "sb_cksum", NULL
> >>>> +};
> >>>> +#define O_SB_CKSUM   0
> >>>> +
> >>>> +static int parse_feature_subopts(char *opts)
> >>>> +{
> >>>> +     char *arg;
> >>>> +
> >>>> +     while (*opts != '\0') {
> >>>> +             switch(getsubopt(&opts, feature_opts, &arg)) {
> >>>> +             case O_SB_CKSUM:
> >>>> +                     cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;
> >>>> +                     break;
> >>>> +             default:
> >>>> +                     erofs_err("incorrect suboption");
> >>>> +                     return -EINVAL;
> >>>> +             }
> >>>> +     }
> >>>> +     return 0;
> >>>> +}
> >>>> +
> >>>>  static int parse_extended_opts(const char *opts)
> >>>>  {
> >>>>  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> >>>> @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char
> >>> *argv[])
> >>>>  {
> >>>>       int opt, i;
> >>>>
> >>>> -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> >>>> +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> >>>>               switch (opt) {
> >>>>               case 'z':
> >>>>                       if (!optarg) {
> >>>> @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char
> >>> *argv[])
> >>>>                               return opt;
> >>>>                       break;
> >>>>
> >>>> +             case 'o':
> >>>> +                     opt = parse_feature_subopts(optarg);
> >>>> +                     if (opt)
> >>>> +                             return opt;
> >>>> +                     break;
> >>>> +
> >>>>               default: /* '?' */
> >>>>                       return -EINVAL;
> >>>>               }
> >>>> @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char
> >>> *argv[])
> >>>>       return 0;
> >>>>  }
> >>>>
> >>>> +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> >>>> +{
> >>>> +     int offset;
> >>>> +     u32 crc;
> >>>> +
> >>>> +     offset = offsetof(struct erofs_super_block, checksum);
> >>>> +     if (offset < 0 || offset > sizeof(struct erofs_super_block)) {
> >>>> +             erofs_err("Invalid offset of checksum field: %d",
> offset);
> >>>> +             return -1;
> >>>> +     }
> >>>> +     crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);
> >>>> +     erofs_dump("superblock checksum: 0x%x\n", crc);
> >>>> +     return 0;
> >>>> +}
> >>>> +
> >>>>  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> >>>>                                 erofs_nid_t root_nid)
> >>>>  {
> >>>> @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct
> >>> erofs_buffer_head *bh,
> >>>>               .meta_blkaddr  = sbi.meta_blkaddr,
> >>>>               .xattr_blkaddr = 0,
> >>>>               .requirements = cpu_to_le32(sbi.requirements),
> >>>> +             .features = cpu_to_le32(cfg.c_feature_flags),
> >>>>       };
> >>>>       const unsigned int sb_blksize =
> >>>>               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> >>>> @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct
> >>> erofs_buffer_head *bh,
> >>>>       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> >>>>       sb.root_nid     = cpu_to_le16(root_nid);
> >>>>
> >>>> +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> >>>> +             u32 crc = erofs_superblock_checksum(&sb);
> >>>> +             sb.checksum = cpu_to_le32(crc);
> >>>> +     }
> >>>> +
> >>>>       buf = calloc(sb_blksize, 1);
> >>>>       if (!buf) {
> >>>>               erofs_err("Failed to allocate memory for sb: %s",
> >>>> --
> >>>> 2.9.3
> >>>>
> >>>
>

[-- Attachment #2: Type: text/html, Size: 16642 bytes --]

<div dir="ltr"><div>Thanks Chao,</div><div><br></div><div>Initially I was of doing the same, but then I thought changing the position of cheksum field to either start OR end <br></div><div>will be much simpler. <br></div><div>I think I will go with Gao&#39;s method. thereby not changing the layout of super-block.</div><div>So just to be clear, I will be writing our own crc32c() function correct ?</div><div><br></div><div>--Pratik.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Aug 24, 2019 at 3:31 PM Chao Yu &lt;<a href="mailto:chao@kernel.org">chao@kernel.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 2019-8-24 17:49, Gao Xiang via Linux-erofs wrote:<br>
&gt; Hi Pratik,<br>
&gt; <br>
&gt; On Sat, Aug 24, 2019 at 02:52:31PM +0530, Pratik Shinde wrote:<br>
&gt;&gt; Hi Gao,<br>
&gt;&gt; Yes I will make the suboption naming similar to that of mk2fs.<br>
&gt; <br>
&gt; Great! :)<br>
&gt; <br>
&gt;&gt;<br>
&gt;&gt; The reason I changed the position of &#39;checksum&#39; field :<br>
&gt;&gt;<br>
&gt;&gt; Since we are calculating the checksum of erofs_super_block structure and<br>
&gt;&gt; storing it in the same structure; we cannot include<br>
&gt;&gt; this field for actual crc calculations. Keeping it at the end makes it easy<br>
&gt;&gt; for me to calculate length of the data of which<br>
&gt;&gt; checksum needs to be calculated. I saw similar logic in other filesystems<br>
&gt;&gt; like ext4.<br>
&gt; <br>
&gt; No, that is just they didn&#39;t add checksum field at the beginning of its design.<br>
&gt; I think you can leave chksum to 0, and calculate chksum and fill it, to be specfic:<br>
&gt; <br>
&gt; In the erofs-utils,<br>
&gt;  1) fill .checksum to 0;<br>
&gt;  2) calculate crc32c of the entire erofs_super_block;<br>
&gt;  3) fill the real checksum to .checksum;<br>
&gt; <br>
&gt; In the kernel,<br>
&gt;  1) read .checksum to a variable;<br>
&gt;  2) fill .checksum to 0;<br>
&gt;  3) calculate crc32c of the entire erofs_super_block;<br>
&gt;  4) compare the given one and the calculated one;<br>
<br>
That&#39;s one way, FYI, the way used in ext4/f2fs now is:<br>
- calc [0, checksum]&#39;s chksum<br>
- use above chksum as seed of chksum within range [chksum + chksum_size, end]<br>
- fill chksum value in range [checksum, chksum + chksum_size]<br>
<br>
Thanks,<br>
<br>
&gt; <br>
&gt; That is all :)<br>
&gt; <br>
&gt;&gt;<br>
&gt;&gt; We can write our own crc32() function. :) There is no problem. I thought<br>
&gt;&gt; zlib already provides one &amp; we can use it.<br>
&gt; <br>
&gt; I think we can use crc32c() since I already wrote comments for erofs in 4.19.<br>
&gt; <br>
&gt; Looking forward to your next version :)<br>
&gt; <br>
&gt; Thanks,<br>
&gt; Gao Xiang<br>
&gt; <br>
&gt;&gt; anyways , I will write.<br>
&gt;&gt;<br>
&gt;&gt; --Pratik.<br>
&gt;&gt;<br>
&gt;&gt; On Sat, Aug 24, 2019 at 2:16 PM Gao Xiang &lt;<a href="mailto:hsiangkao@gmx.com" target="_blank">hsiangkao@gmx.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt;&gt; Hi Pratik,<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:<br>
&gt;&gt;&gt;&gt; Adding code for superblock checksum calculation.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; This patch adds following things:<br>
&gt;&gt;&gt;&gt; 1)Handle suboptions(&#39;-o&#39;) to mkfs utility.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Thanks for your patch. :)<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Can we use &quot;-O feature&quot; instead in order to keep in line with mke2fs?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 2)Add superblock checksum calculation(-o sb_cksum) as suboption.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; ditto. and I think we can enable sbcrc by default since it is a compat<br>
&gt;&gt;&gt; feature,<br>
&gt;&gt;&gt; and add &quot;-O nosbcrc&quot; to disable it.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 3)Calculate superblock checksum if feature is enabled.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Signed-off-by: Pratik Shinde &lt;<a href="mailto:pratikshinde320@gmail.com" target="_blank">pratikshinde320@gmail.com</a>&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; And could you please also read my following comments and fix them.<br>
&gt;&gt;&gt; and I&#39;d like to accept your erofs-utils modification in advance. :)<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; But now you can see we are moving EROFS out of staging now as<br>
&gt;&gt;&gt; the &quot;real&quot; part of Linux, this is the fundamental stuff of other<br>
&gt;&gt;&gt; new features if we want to develop more actively... So we can wait<br>
&gt;&gt;&gt; for the final result and add this new feature to kernel then...<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; ---<br>
&gt;&gt;&gt;&gt;  include/erofs/config.h |  1 +<br>
&gt;&gt;&gt;&gt;  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------<br>
&gt;&gt;&gt;&gt;  mkfs/main.c            | 53<br>
&gt;&gt;&gt; +++++++++++++++++++++++++++++++++++++++++++++++++-<br>
&gt;&gt;&gt;&gt;  3 files changed, 76 insertions(+), 18 deletions(-)<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; diff --git a/include/erofs/config.h b/include/erofs/config.h<br>
&gt;&gt;&gt;&gt; index 05fe6b2..40cd466 100644<br>
&gt;&gt;&gt;&gt; --- a/include/erofs/config.h<br>
&gt;&gt;&gt;&gt; +++ b/include/erofs/config.h<br>
&gt;&gt;&gt;&gt; @@ -22,6 +22,7 @@ struct erofs_configure {<br>
&gt;&gt;&gt;&gt;       char *c_src_path;<br>
&gt;&gt;&gt;&gt;       char *c_compr_alg_master;<br>
&gt;&gt;&gt;&gt;       int c_compr_level_master;<br>
&gt;&gt;&gt;&gt; +     int c_feature_flags;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; we can add this to sbi like requirements...<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;  };<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;  extern struct erofs_configure cfg;<br>
&gt;&gt;&gt;&gt; diff --git a/include/erofs_fs.h b/include/erofs_fs.h<br>
&gt;&gt;&gt;&gt; index 601b477..c9ef057 100644<br>
&gt;&gt;&gt;&gt; --- a/include/erofs_fs.h<br>
&gt;&gt;&gt;&gt; +++ b/include/erofs_fs.h<br>
&gt;&gt;&gt;&gt; @@ -20,25 +20,31 @@<br>
&gt;&gt;&gt;&gt;  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001<br>
&gt;&gt;&gt;&gt;  #define EROFS_ALL_REQUIREMENTS<br>
&gt;&gt;&gt;  EROFS_REQUIREMENT_LZ4_0PADDING<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; +/*<br>
&gt;&gt;&gt;&gt; + * feature definations.<br>
&gt;&gt;&gt;&gt; + */<br>
&gt;&gt;&gt;&gt; +#define EROFS_FEATURE_SB_CHKSUM              0x0001<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt; +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \<br>
&gt;&gt;&gt;&gt; +     ( le32_to_cpu((super)-&gt;features) &amp; (mask) )<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt;  struct erofs_super_block {<br>
&gt;&gt;&gt;&gt;  /*  0 */__le32 magic;           /* in the little endian */<br>
&gt;&gt;&gt;&gt; -/*  4 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt;&gt;&gt;&gt; -/*  8 */__le32 features;        /* (aka. feature_compat) */<br>
&gt;&gt;&gt;&gt; -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only<br>
&gt;&gt;&gt; */<br>
&gt;&gt;&gt;&gt; -/* 13 */__u8 reserved;<br>
&gt;&gt;&gt;&gt; -<br>
&gt;&gt;&gt;&gt; -/* 14 */__le16 root_nid;<br>
&gt;&gt;&gt;&gt; -/* 16 */__le64 inos;            /* total valid ino # (== f_files -<br>
&gt;&gt;&gt; f_favail) */<br>
&gt;&gt;&gt;&gt; -<br>
&gt;&gt;&gt;&gt; -/* 24 */__le64 build_time;      /* inode v1 time derivation */<br>
&gt;&gt;&gt;&gt; -/* 32 */__le32 build_time_nsec;<br>
&gt;&gt;&gt;&gt; -/* 36 */__le32 blocks;          /* used for statfs */<br>
&gt;&gt;&gt;&gt; -/* 40 */__le32 meta_blkaddr;<br>
&gt;&gt;&gt;&gt; -/* 44 */__le32 xattr_blkaddr;<br>
&gt;&gt;&gt;&gt; -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */<br>
&gt;&gt;&gt;&gt; -/* 64 */__u8 volume_name[16];   /* volume name */<br>
&gt;&gt;&gt;&gt; -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */<br>
&gt;&gt;&gt;&gt; -<br>
&gt;&gt;&gt;&gt; +/*  4 */__le32 features;        /* (aka. feature_compat) */<br>
&gt;&gt;&gt;&gt; +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only<br>
&gt;&gt;&gt; */<br>
&gt;&gt;&gt;&gt; +/*  9 */__u8 reserved;<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt; +/* 10 */__le16 root_nid;<br>
&gt;&gt;&gt;&gt; +/* 12 */__le64 inos;            /* total valid ino # (== f_files -<br>
&gt;&gt;&gt; f_favail) */<br>
&gt;&gt;&gt;&gt; +/* 20 */__le64 build_time;      /* inode v1 time derivation */<br>
&gt;&gt;&gt;&gt; +/* 28 */__le32 build_time_nsec;<br>
&gt;&gt;&gt;&gt; +/* 32 */__le32 blocks;          /* used for statfs */<br>
&gt;&gt;&gt;&gt; +/* 36 */__le32 meta_blkaddr;<br>
&gt;&gt;&gt;&gt; +/* 40 */__le32 xattr_blkaddr;<br>
&gt;&gt;&gt;&gt; +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */<br>
&gt;&gt;&gt;&gt; +/* 60 */__u8 volume_name[16];   /* volume name */<br>
&gt;&gt;&gt;&gt; +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */<br>
&gt;&gt;&gt;&gt; +/* 80 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt;&gt;&gt;&gt;  /* 84 */__u8 reserved2[44];<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Why modifying the above?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;  } __packed;                     /* 128 bytes */<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; diff --git a/mkfs/main.c b/mkfs/main.c<br>
&gt;&gt;&gt;&gt; index f127fe1..26e14a3 100644<br>
&gt;&gt;&gt;&gt; --- a/mkfs/main.c<br>
&gt;&gt;&gt;&gt; +++ b/mkfs/main.c<br>
&gt;&gt;&gt;&gt; @@ -13,12 +13,14 @@<br>
&gt;&gt;&gt;&gt;  #include &lt;limits.h&gt;<br>
&gt;&gt;&gt;&gt;  #include &lt;libgen.h&gt;<br>
&gt;&gt;&gt;&gt;  #include &lt;sys/stat.h&gt;<br>
&gt;&gt;&gt;&gt; +#include &lt;zlib.h&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I have no idea that we should introduce &quot;zlib&quot; just for crc32c currently...<br>
&gt;&gt;&gt; Maybe we can add some independent crc32 function..<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Thanks,<br>
&gt;&gt;&gt; Gao Xiang<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;  #include &quot;erofs/config.h&quot;<br>
&gt;&gt;&gt;&gt;  #include &quot;erofs/print.h&quot;<br>
&gt;&gt;&gt;&gt;  #include &quot;erofs/cache.h&quot;<br>
&gt;&gt;&gt;&gt;  #include &quot;erofs/inode.h&quot;<br>
&gt;&gt;&gt;&gt;  #include &quot;erofs/io.h&quot;<br>
&gt;&gt;&gt;&gt;  #include &quot;erofs/compress.h&quot;<br>
&gt;&gt;&gt;&gt; +#include &quot;erofs/defs.h&quot;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct<br>
&gt;&gt;&gt; erofs_super_block))<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; @@ -31,6 +33,28 @@ static void usage(void)<br>
&gt;&gt;&gt;&gt;       fprintf(stderr, &quot; -EX[,...] X=extended options\n&quot;);<br>
&gt;&gt;&gt;&gt;  }<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; +char *feature_opts[] = {<br>
&gt;&gt;&gt;&gt; +     &quot;sb_cksum&quot;, NULL<br>
&gt;&gt;&gt;&gt; +};<br>
&gt;&gt;&gt;&gt; +#define O_SB_CKSUM   0<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt; +static int parse_feature_subopts(char *opts)<br>
&gt;&gt;&gt;&gt; +{<br>
&gt;&gt;&gt;&gt; +     char *arg;<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt; +     while (*opts != &#39;\0&#39;) {<br>
&gt;&gt;&gt;&gt; +             switch(getsubopt(&amp;opts, feature_opts, &amp;arg)) {<br>
&gt;&gt;&gt;&gt; +             case O_SB_CKSUM:<br>
&gt;&gt;&gt;&gt; +                     cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;<br>
&gt;&gt;&gt;&gt; +                     break;<br>
&gt;&gt;&gt;&gt; +             default:<br>
&gt;&gt;&gt;&gt; +                     erofs_err(&quot;incorrect suboption&quot;);<br>
&gt;&gt;&gt;&gt; +                     return -EINVAL;<br>
&gt;&gt;&gt;&gt; +             }<br>
&gt;&gt;&gt;&gt; +     }<br>
&gt;&gt;&gt;&gt; +     return 0;<br>
&gt;&gt;&gt;&gt; +}<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt;  static int parse_extended_opts(const char *opts)<br>
&gt;&gt;&gt;&gt;  {<br>
&gt;&gt;&gt;&gt;  #define MATCH_EXTENTED_OPT(opt, token, keylen) \<br>
&gt;&gt;&gt;&gt; @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt;&gt;&gt; *argv[])<br>
&gt;&gt;&gt;&gt;  {<br>
&gt;&gt;&gt;&gt;       int opt, i;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; -     while ((opt = getopt(argc, argv, &quot;d:z:E:&quot;)) != -1) {<br>
&gt;&gt;&gt;&gt; +     while ((opt = getopt(argc, argv, &quot;d:z:E:o:&quot;)) != -1) {<br>
&gt;&gt;&gt;&gt;               switch (opt) {<br>
&gt;&gt;&gt;&gt;               case &#39;z&#39;:<br>
&gt;&gt;&gt;&gt;                       if (!optarg) {<br>
&gt;&gt;&gt;&gt; @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt;&gt;&gt; *argv[])<br>
&gt;&gt;&gt;&gt;                               return opt;<br>
&gt;&gt;&gt;&gt;                       break;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; +             case &#39;o&#39;:<br>
&gt;&gt;&gt;&gt; +                     opt = parse_feature_subopts(optarg);<br>
&gt;&gt;&gt;&gt; +                     if (opt)<br>
&gt;&gt;&gt;&gt; +                             return opt;<br>
&gt;&gt;&gt;&gt; +                     break;<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt;               default: /* &#39;?&#39; */<br>
&gt;&gt;&gt;&gt;                       return -EINVAL;<br>
&gt;&gt;&gt;&gt;               }<br>
&gt;&gt;&gt;&gt; @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char<br>
&gt;&gt;&gt; *argv[])<br>
&gt;&gt;&gt;&gt;       return 0;<br>
&gt;&gt;&gt;&gt;  }<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; +u32 erofs_superblock_checksum(struct erofs_super_block *sb)<br>
&gt;&gt;&gt;&gt; +{<br>
&gt;&gt;&gt;&gt; +     int offset;<br>
&gt;&gt;&gt;&gt; +     u32 crc;<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt; +     offset = offsetof(struct erofs_super_block, checksum);<br>
&gt;&gt;&gt;&gt; +     if (offset &lt; 0 || offset &gt; sizeof(struct erofs_super_block)) {<br>
&gt;&gt;&gt;&gt; +             erofs_err(&quot;Invalid offset of checksum field: %d&quot;, offset);<br>
&gt;&gt;&gt;&gt; +             return -1;<br>
&gt;&gt;&gt;&gt; +     }<br>
&gt;&gt;&gt;&gt; +     crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);<br>
&gt;&gt;&gt;&gt; +     erofs_dump(&quot;superblock checksum: 0x%x\n&quot;, crc);<br>
&gt;&gt;&gt;&gt; +     return 0;<br>
&gt;&gt;&gt;&gt; +}<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt;  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt;&gt;&gt;&gt;                                 erofs_nid_t root_nid)<br>
&gt;&gt;&gt;&gt;  {<br>
&gt;&gt;&gt;&gt; @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct<br>
&gt;&gt;&gt; erofs_buffer_head *bh,<br>
&gt;&gt;&gt;&gt;               .meta_blkaddr  = sbi.meta_blkaddr,<br>
&gt;&gt;&gt;&gt;               .xattr_blkaddr = 0,<br>
&gt;&gt;&gt;&gt;               .requirements = cpu_to_le32(sbi.requirements),<br>
&gt;&gt;&gt;&gt; +             .features = cpu_to_le32(cfg.c_feature_flags),<br>
&gt;&gt;&gt;&gt;       };<br>
&gt;&gt;&gt;&gt;       const unsigned int sb_blksize =<br>
&gt;&gt;&gt;&gt;               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);<br>
&gt;&gt;&gt;&gt; @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct<br>
&gt;&gt;&gt; erofs_buffer_head *bh,<br>
&gt;&gt;&gt;&gt;       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));<br>
&gt;&gt;&gt;&gt;       sb.root_nid     = cpu_to_le16(root_nid);<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; +     if (EROFS_HAS_COMPAT_FEATURE(&amp;sb, EROFS_FEATURE_SB_CHKSUM)) {<br>
&gt;&gt;&gt;&gt; +             u32 crc = erofs_superblock_checksum(&amp;sb);<br>
&gt;&gt;&gt;&gt; +             sb.checksum = cpu_to_le32(crc);<br>
&gt;&gt;&gt;&gt; +     }<br>
&gt;&gt;&gt;&gt; +<br>
&gt;&gt;&gt;&gt;       buf = calloc(sb_blksize, 1);<br>
&gt;&gt;&gt;&gt;       if (!buf) {<br>
&gt;&gt;&gt;&gt;               erofs_err(&quot;Failed to allocate memory for sb: %s&quot;,<br>
&gt;&gt;&gt;&gt; --<br>
&gt;&gt;&gt;&gt; 2.9.3<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
</blockquote></div>

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24  9:49     ` Gao Xiang via Linux-erofs
@ 2019-08-24 10:01       ` Chao Yu
  2019-08-24 10:05         ` Pratik Shinde
  0 siblings, 1 reply; 19+ messages in thread
From: Chao Yu @ 2019-08-24 10:01 UTC (permalink / raw)
  To: linux-erofs

On 2019-8-24 17:49, Gao Xiang via Linux-erofs wrote:
> Hi Pratik,
> 
> On Sat, Aug 24, 2019 at 02:52:31PM +0530, Pratik Shinde wrote:
>> Hi Gao,
>> Yes I will make the suboption naming similar to that of mk2fs.
> 
> Great! :)
> 
>>
>> The reason I changed the position of 'checksum' field :
>>
>> Since we are calculating the checksum of erofs_super_block structure and
>> storing it in the same structure; we cannot include
>> this field for actual crc calculations. Keeping it at the end makes it easy
>> for me to calculate length of the data of which
>> checksum needs to be calculated. I saw similar logic in other filesystems
>> like ext4.
> 
> No, that is just they didn't add checksum field at the beginning of its design.
> I think you can leave chksum to 0, and calculate chksum and fill it, to be specfic:
> 
> In the erofs-utils,
>  1) fill .checksum to 0;
>  2) calculate crc32c of the entire erofs_super_block;
>  3) fill the real checksum to .checksum;
> 
> In the kernel,
>  1) read .checksum to a variable;
>  2) fill .checksum to 0;
>  3) calculate crc32c of the entire erofs_super_block;
>  4) compare the given one and the calculated one;

That's one way, FYI, the way used in ext4/f2fs now is:
- calc [0, checksum]'s chksum
- use above chksum as seed of chksum within range [chksum + chksum_size, end]
- fill chksum value in range [checksum, chksum + chksum_size]

Thanks,

> 
> That is all :)
> 
>>
>> We can write our own crc32() function. :) There is no problem. I thought
>> zlib already provides one & we can use it.
> 
> I think we can use crc32c() since I already wrote comments for erofs in 4.19.
> 
> Looking forward to your next version :)
> 
> Thanks,
> Gao Xiang
> 
>> anyways , I will write.
>>
>> --Pratik.
>>
>> On Sat, Aug 24, 2019 at 2:16 PM Gao Xiang <hsiangkao@gmx.com> wrote:
>>
>>> Hi Pratik,
>>>
>>> On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:
>>>> Adding code for superblock checksum calculation.
>>>>
>>>> This patch adds following things:
>>>> 1)Handle suboptions('-o') to mkfs utility.
>>>
>>> Thanks for your patch. :)
>>>
>>> Can we use "-O feature" instead in order to keep in line with mke2fs?
>>>
>>>> 2)Add superblock checksum calculation(-o sb_cksum) as suboption.
>>>
>>> ditto. and I think we can enable sbcrc by default since it is a compat
>>> feature,
>>> and add "-O nosbcrc" to disable it.
>>>
>>>> 3)Calculate superblock checksum if feature is enabled.
>>>>
>>>> Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
>>>
>>> And could you please also read my following comments and fix them.
>>> and I'd like to accept your erofs-utils modification in advance. :)
>>>
>>>
>>> But now you can see we are moving EROFS out of staging now as
>>> the "real" part of Linux, this is the fundamental stuff of other
>>> new features if we want to develop more actively... So we can wait
>>> for the final result and add this new feature to kernel then...
>>>
>>>> ---
>>>>  include/erofs/config.h |  1 +
>>>>  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------
>>>>  mkfs/main.c            | 53
>>> +++++++++++++++++++++++++++++++++++++++++++++++++-
>>>>  3 files changed, 76 insertions(+), 18 deletions(-)
>>>>
>>>> diff --git a/include/erofs/config.h b/include/erofs/config.h
>>>> index 05fe6b2..40cd466 100644
>>>> --- a/include/erofs/config.h
>>>> +++ b/include/erofs/config.h
>>>> @@ -22,6 +22,7 @@ struct erofs_configure {
>>>>       char *c_src_path;
>>>>       char *c_compr_alg_master;
>>>>       int c_compr_level_master;
>>>> +     int c_feature_flags;
>>>
>>> we can add this to sbi like requirements...
>>>
>>>>  };
>>>>
>>>>  extern struct erofs_configure cfg;
>>>> diff --git a/include/erofs_fs.h b/include/erofs_fs.h
>>>> index 601b477..c9ef057 100644
>>>> --- a/include/erofs_fs.h
>>>> +++ b/include/erofs_fs.h
>>>> @@ -20,25 +20,31 @@
>>>>  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
>>>>  #define EROFS_ALL_REQUIREMENTS
>>>  EROFS_REQUIREMENT_LZ4_0PADDING
>>>>
>>>> +/*
>>>> + * feature definations.
>>>> + */
>>>> +#define EROFS_FEATURE_SB_CHKSUM              0x0001
>>>> +
>>>> +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
>>>> +     ( le32_to_cpu((super)->features) & (mask) )
>>>> +
>>>>  struct erofs_super_block {
>>>>  /*  0 */__le32 magic;           /* in the little endian */
>>>> -/*  4 */__le32 checksum;        /* crc32c(super_block) */
>>>> -/*  8 */__le32 features;        /* (aka. feature_compat) */
>>>> -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only
>>> */
>>>> -/* 13 */__u8 reserved;
>>>> -
>>>> -/* 14 */__le16 root_nid;
>>>> -/* 16 */__le64 inos;            /* total valid ino # (== f_files -
>>> f_favail) */
>>>> -
>>>> -/* 24 */__le64 build_time;      /* inode v1 time derivation */
>>>> -/* 32 */__le32 build_time_nsec;
>>>> -/* 36 */__le32 blocks;          /* used for statfs */
>>>> -/* 40 */__le32 meta_blkaddr;
>>>> -/* 44 */__le32 xattr_blkaddr;
>>>> -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */
>>>> -/* 64 */__u8 volume_name[16];   /* volume name */
>>>> -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */
>>>> -
>>>> +/*  4 */__le32 features;        /* (aka. feature_compat) */
>>>> +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only
>>> */
>>>> +/*  9 */__u8 reserved;
>>>> +
>>>> +/* 10 */__le16 root_nid;
>>>> +/* 12 */__le64 inos;            /* total valid ino # (== f_files -
>>> f_favail) */
>>>> +/* 20 */__le64 build_time;      /* inode v1 time derivation */
>>>> +/* 28 */__le32 build_time_nsec;
>>>> +/* 32 */__le32 blocks;          /* used for statfs */
>>>> +/* 36 */__le32 meta_blkaddr;
>>>> +/* 40 */__le32 xattr_blkaddr;
>>>> +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */
>>>> +/* 60 */__u8 volume_name[16];   /* volume name */
>>>> +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */
>>>> +/* 80 */__le32 checksum;        /* crc32c(super_block) */
>>>>  /* 84 */__u8 reserved2[44];
>>>
>>> Why modifying the above?
>>>
>>>>  } __packed;                     /* 128 bytes */
>>>>
>>>> diff --git a/mkfs/main.c b/mkfs/main.c
>>>> index f127fe1..26e14a3 100644
>>>> --- a/mkfs/main.c
>>>> +++ b/mkfs/main.c
>>>> @@ -13,12 +13,14 @@
>>>>  #include <limits.h>
>>>>  #include <libgen.h>
>>>>  #include <sys/stat.h>
>>>> +#include <zlib.h>
>>>
>>> I have no idea that we should introduce "zlib" just for crc32c currently...
>>> Maybe we can add some independent crc32 function..
>>>
>>> Thanks,
>>> Gao Xiang
>>>
>>>>  #include "erofs/config.h"
>>>>  #include "erofs/print.h"
>>>>  #include "erofs/cache.h"
>>>>  #include "erofs/inode.h"
>>>>  #include "erofs/io.h"
>>>>  #include "erofs/compress.h"
>>>> +#include "erofs/defs.h"
>>>>
>>>>  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct
>>> erofs_super_block))
>>>>
>>>> @@ -31,6 +33,28 @@ static void usage(void)
>>>>       fprintf(stderr, " -EX[,...] X=extended options\n");
>>>>  }
>>>>
>>>> +char *feature_opts[] = {
>>>> +     "sb_cksum", NULL
>>>> +};
>>>> +#define O_SB_CKSUM   0
>>>> +
>>>> +static int parse_feature_subopts(char *opts)
>>>> +{
>>>> +     char *arg;
>>>> +
>>>> +     while (*opts != '\0') {
>>>> +             switch(getsubopt(&opts, feature_opts, &arg)) {
>>>> +             case O_SB_CKSUM:
>>>> +                     cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;
>>>> +                     break;
>>>> +             default:
>>>> +                     erofs_err("incorrect suboption");
>>>> +                     return -EINVAL;
>>>> +             }
>>>> +     }
>>>> +     return 0;
>>>> +}
>>>> +
>>>>  static int parse_extended_opts(const char *opts)
>>>>  {
>>>>  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
>>>> @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char
>>> *argv[])
>>>>  {
>>>>       int opt, i;
>>>>
>>>> -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
>>>> +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
>>>>               switch (opt) {
>>>>               case 'z':
>>>>                       if (!optarg) {
>>>> @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char
>>> *argv[])
>>>>                               return opt;
>>>>                       break;
>>>>
>>>> +             case 'o':
>>>> +                     opt = parse_feature_subopts(optarg);
>>>> +                     if (opt)
>>>> +                             return opt;
>>>> +                     break;
>>>> +
>>>>               default: /* '?' */
>>>>                       return -EINVAL;
>>>>               }
>>>> @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char
>>> *argv[])
>>>>       return 0;
>>>>  }
>>>>
>>>> +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
>>>> +{
>>>> +     int offset;
>>>> +     u32 crc;
>>>> +
>>>> +     offset = offsetof(struct erofs_super_block, checksum);
>>>> +     if (offset < 0 || offset > sizeof(struct erofs_super_block)) {
>>>> +             erofs_err("Invalid offset of checksum field: %d", offset);
>>>> +             return -1;
>>>> +     }
>>>> +     crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);
>>>> +     erofs_dump("superblock checksum: 0x%x\n", crc);
>>>> +     return 0;
>>>> +}
>>>> +
>>>>  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
>>>>                                 erofs_nid_t root_nid)
>>>>  {
>>>> @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct
>>> erofs_buffer_head *bh,
>>>>               .meta_blkaddr  = sbi.meta_blkaddr,
>>>>               .xattr_blkaddr = 0,
>>>>               .requirements = cpu_to_le32(sbi.requirements),
>>>> +             .features = cpu_to_le32(cfg.c_feature_flags),
>>>>       };
>>>>       const unsigned int sb_blksize =
>>>>               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
>>>> @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct
>>> erofs_buffer_head *bh,
>>>>       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
>>>>       sb.root_nid     = cpu_to_le16(root_nid);
>>>>
>>>> +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
>>>> +             u32 crc = erofs_superblock_checksum(&sb);
>>>> +             sb.checksum = cpu_to_le32(crc);
>>>> +     }
>>>> +
>>>>       buf = calloc(sb_blksize, 1);
>>>>       if (!buf) {
>>>>               erofs_err("Failed to allocate memory for sb: %s",
>>>> --
>>>> 2.9.3
>>>>
>>>

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24  9:22   ` Pratik Shinde
@ 2019-08-24  9:49     ` Gao Xiang via Linux-erofs
  2019-08-24 10:01       ` Chao Yu
  0 siblings, 1 reply; 19+ messages in thread
From: Gao Xiang via Linux-erofs @ 2019-08-24  9:49 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: linux-erofs, miaoxie

Hi Pratik,

On Sat, Aug 24, 2019 at 02:52:31PM +0530, Pratik Shinde wrote:
> Hi Gao,
> Yes I will make the suboption naming similar to that of mk2fs.

Great! :)

> 
> The reason I changed the position of 'checksum' field :
> 
> Since we are calculating the checksum of erofs_super_block structure and
> storing it in the same structure; we cannot include
> this field for actual crc calculations. Keeping it at the end makes it easy
> for me to calculate length of the data of which
> checksum needs to be calculated. I saw similar logic in other filesystems
> like ext4.

No, that is just they didn't add checksum field at the beginning of its design.
I think you can leave chksum to 0, and calculate chksum and fill it, to be specfic:

In the erofs-utils,
 1) fill .checksum to 0;
 2) calculate crc32c of the entire erofs_super_block;
 3) fill the real checksum to .checksum;

In the kernel,
 1) read .checksum to a variable;
 2) fill .checksum to 0;
 3) calculate crc32c of the entire erofs_super_block;
 4) compare the given one and the calculated one;

That is all :)

> 
> We can write our own crc32() function. :) There is no problem. I thought
> zlib already provides one & we can use it.

I think we can use crc32c() since I already wrote comments for erofs in 4.19.

Looking forward to your next version :)

Thanks,
Gao Xiang

> anyways , I will write.
> 
> --Pratik.
> 
> On Sat, Aug 24, 2019 at 2:16 PM Gao Xiang <hsiangkao@gmx.com> wrote:
> 
> > Hi Pratik,
> >
> > On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:
> > > Adding code for superblock checksum calculation.
> > >
> > > This patch adds following things:
> > > 1)Handle suboptions('-o') to mkfs utility.
> >
> > Thanks for your patch. :)
> >
> > Can we use "-O feature" instead in order to keep in line with mke2fs?
> >
> > > 2)Add superblock checksum calculation(-o sb_cksum) as suboption.
> >
> > ditto. and I think we can enable sbcrc by default since it is a compat
> > feature,
> > and add "-O nosbcrc" to disable it.
> >
> > > 3)Calculate superblock checksum if feature is enabled.
> > >
> > > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
> >
> > And could you please also read my following comments and fix them.
> > and I'd like to accept your erofs-utils modification in advance. :)
> >
> >
> > But now you can see we are moving EROFS out of staging now as
> > the "real" part of Linux, this is the fundamental stuff of other
> > new features if we want to develop more actively... So we can wait
> > for the final result and add this new feature to kernel then...
> >
> > > ---
> > >  include/erofs/config.h |  1 +
> > >  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------
> > >  mkfs/main.c            | 53
> > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > >  3 files changed, 76 insertions(+), 18 deletions(-)
> > >
> > > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > > index 05fe6b2..40cd466 100644
> > > --- a/include/erofs/config.h
> > > +++ b/include/erofs/config.h
> > > @@ -22,6 +22,7 @@ struct erofs_configure {
> > >       char *c_src_path;
> > >       char *c_compr_alg_master;
> > >       int c_compr_level_master;
> > > +     int c_feature_flags;
> >
> > we can add this to sbi like requirements...
> >
> > >  };
> > >
> > >  extern struct erofs_configure cfg;
> > > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > > index 601b477..c9ef057 100644
> > > --- a/include/erofs_fs.h
> > > +++ b/include/erofs_fs.h
> > > @@ -20,25 +20,31 @@
> > >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> > >  #define EROFS_ALL_REQUIREMENTS
> >  EROFS_REQUIREMENT_LZ4_0PADDING
> > >
> > > +/*
> > > + * feature definations.
> > > + */
> > > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > > +
> > > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > > +     ( le32_to_cpu((super)->features) & (mask) )
> > > +
> > >  struct erofs_super_block {
> > >  /*  0 */__le32 magic;           /* in the little endian */
> > > -/*  4 */__le32 checksum;        /* crc32c(super_block) */
> > > -/*  8 */__le32 features;        /* (aka. feature_compat) */
> > > -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only
> > */
> > > -/* 13 */__u8 reserved;
> > > -
> > > -/* 14 */__le16 root_nid;
> > > -/* 16 */__le64 inos;            /* total valid ino # (== f_files -
> > f_favail) */
> > > -
> > > -/* 24 */__le64 build_time;      /* inode v1 time derivation */
> > > -/* 32 */__le32 build_time_nsec;
> > > -/* 36 */__le32 blocks;          /* used for statfs */
> > > -/* 40 */__le32 meta_blkaddr;
> > > -/* 44 */__le32 xattr_blkaddr;
> > > -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */
> > > -/* 64 */__u8 volume_name[16];   /* volume name */
> > > -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */
> > > -
> > > +/*  4 */__le32 features;        /* (aka. feature_compat) */
> > > +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only
> > */
> > > +/*  9 */__u8 reserved;
> > > +
> > > +/* 10 */__le16 root_nid;
> > > +/* 12 */__le64 inos;            /* total valid ino # (== f_files -
> > f_favail) */
> > > +/* 20 */__le64 build_time;      /* inode v1 time derivation */
> > > +/* 28 */__le32 build_time_nsec;
> > > +/* 32 */__le32 blocks;          /* used for statfs */
> > > +/* 36 */__le32 meta_blkaddr;
> > > +/* 40 */__le32 xattr_blkaddr;
> > > +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */
> > > +/* 60 */__u8 volume_name[16];   /* volume name */
> > > +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */
> > > +/* 80 */__le32 checksum;        /* crc32c(super_block) */
> > >  /* 84 */__u8 reserved2[44];
> >
> > Why modifying the above?
> >
> > >  } __packed;                     /* 128 bytes */
> > >
> > > diff --git a/mkfs/main.c b/mkfs/main.c
> > > index f127fe1..26e14a3 100644
> > > --- a/mkfs/main.c
> > > +++ b/mkfs/main.c
> > > @@ -13,12 +13,14 @@
> > >  #include <limits.h>
> > >  #include <libgen.h>
> > >  #include <sys/stat.h>
> > > +#include <zlib.h>
> >
> > I have no idea that we should introduce "zlib" just for crc32c currently...
> > Maybe we can add some independent crc32 function..
> >
> > Thanks,
> > Gao Xiang
> >
> > >  #include "erofs/config.h"
> > >  #include "erofs/print.h"
> > >  #include "erofs/cache.h"
> > >  #include "erofs/inode.h"
> > >  #include "erofs/io.h"
> > >  #include "erofs/compress.h"
> > > +#include "erofs/defs.h"
> > >
> > >  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct
> > erofs_super_block))
> > >
> > > @@ -31,6 +33,28 @@ static void usage(void)
> > >       fprintf(stderr, " -EX[,...] X=extended options\n");
> > >  }
> > >
> > > +char *feature_opts[] = {
> > > +     "sb_cksum", NULL
> > > +};
> > > +#define O_SB_CKSUM   0
> > > +
> > > +static int parse_feature_subopts(char *opts)
> > > +{
> > > +     char *arg;
> > > +
> > > +     while (*opts != '\0') {
> > > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > > +             case O_SB_CKSUM:
> > > +                     cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;
> > > +                     break;
> > > +             default:
> > > +                     erofs_err("incorrect suboption");
> > > +                     return -EINVAL;
> > > +             }
> > > +     }
> > > +     return 0;
> > > +}
> > > +
> > >  static int parse_extended_opts(const char *opts)
> > >  {
> > >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > > @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >  {
> > >       int opt, i;
> > >
> > > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> > >               switch (opt) {
> > >               case 'z':
> > >                       if (!optarg) {
> > > @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >                               return opt;
> > >                       break;
> > >
> > > +             case 'o':
> > > +                     opt = parse_feature_subopts(optarg);
> > > +                     if (opt)
> > > +                             return opt;
> > > +                     break;
> > > +
> > >               default: /* '?' */
> > >                       return -EINVAL;
> > >               }
> > > @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char
> > *argv[])
> > >       return 0;
> > >  }
> > >
> > > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > > +{
> > > +     int offset;
> > > +     u32 crc;
> > > +
> > > +     offset = offsetof(struct erofs_super_block, checksum);
> > > +     if (offset < 0 || offset > sizeof(struct erofs_super_block)) {
> > > +             erofs_err("Invalid offset of checksum field: %d", offset);
> > > +             return -1;
> > > +     }
> > > +     crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);
> > > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > > +     return 0;
> > > +}
> > > +
> > >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> > >                                 erofs_nid_t root_nid)
> > >  {
> > > @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct
> > erofs_buffer_head *bh,
> > >               .meta_blkaddr  = sbi.meta_blkaddr,
> > >               .xattr_blkaddr = 0,
> > >               .requirements = cpu_to_le32(sbi.requirements),
> > > +             .features = cpu_to_le32(cfg.c_feature_flags),
> > >       };
> > >       const unsigned int sb_blksize =
> > >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > > @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct
> > erofs_buffer_head *bh,
> > >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> > >       sb.root_nid     = cpu_to_le16(root_nid);
> > >
> > > +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > > +             u32 crc = erofs_superblock_checksum(&sb);
> > > +             sb.checksum = cpu_to_le32(crc);
> > > +     }
> > > +
> > >       buf = calloc(sb_blksize, 1);
> > >       if (!buf) {
> > >               erofs_err("Failed to allocate memory for sb: %s",
> > > --
> > > 2.9.3
> > >
> >

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24  8:46 ` Gao Xiang
@ 2019-08-24  9:22   ` Pratik Shinde
  2019-08-24  9:49     ` Gao Xiang via Linux-erofs
  0 siblings, 1 reply; 19+ messages in thread
From: Pratik Shinde @ 2019-08-24  9:22 UTC (permalink / raw)
  To: Gao Xiang; +Cc: miaoxie, linux-erofs

[-- Attachment #1: Type: text/plain, Size: 8934 bytes --]

Hi Gao,
Yes I will make the suboption naming similar to that of mk2fs.

The reason I changed the position of 'checksum' field :

Since we are calculating the checksum of erofs_super_block structure and
storing it in the same structure; we cannot include
this field for actual crc calculations. Keeping it at the end makes it easy
for me to calculate length of the data of which
checksum needs to be calculated. I saw similar logic in other filesystems
like ext4.

We can write our own crc32() function. :) There is no problem. I thought
zlib already provides one & we can use it.
anyways , I will write.

--Pratik.

On Sat, Aug 24, 2019 at 2:16 PM Gao Xiang <hsiangkao@gmx.com> wrote:

> Hi Pratik,
>
> On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:
> > Adding code for superblock checksum calculation.
> >
> > This patch adds following things:
> > 1)Handle suboptions('-o') to mkfs utility.
>
> Thanks for your patch. :)
>
> Can we use "-O feature" instead in order to keep in line with mke2fs?
>
> > 2)Add superblock checksum calculation(-o sb_cksum) as suboption.
>
> ditto. and I think we can enable sbcrc by default since it is a compat
> feature,
> and add "-O nosbcrc" to disable it.
>
> > 3)Calculate superblock checksum if feature is enabled.
> >
> > Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
>
> And could you please also read my following comments and fix them.
> and I'd like to accept your erofs-utils modification in advance. :)
>
>
> But now you can see we are moving EROFS out of staging now as
> the "real" part of Linux, this is the fundamental stuff of other
> new features if we want to develop more actively... So we can wait
> for the final result and add this new feature to kernel then...
>
> > ---
> >  include/erofs/config.h |  1 +
> >  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------
> >  mkfs/main.c            | 53
> +++++++++++++++++++++++++++++++++++++++++++++++++-
> >  3 files changed, 76 insertions(+), 18 deletions(-)
> >
> > diff --git a/include/erofs/config.h b/include/erofs/config.h
> > index 05fe6b2..40cd466 100644
> > --- a/include/erofs/config.h
> > +++ b/include/erofs/config.h
> > @@ -22,6 +22,7 @@ struct erofs_configure {
> >       char *c_src_path;
> >       char *c_compr_alg_master;
> >       int c_compr_level_master;
> > +     int c_feature_flags;
>
> we can add this to sbi like requirements...
>
> >  };
> >
> >  extern struct erofs_configure cfg;
> > diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> > index 601b477..c9ef057 100644
> > --- a/include/erofs_fs.h
> > +++ b/include/erofs_fs.h
> > @@ -20,25 +20,31 @@
> >  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001
> >  #define EROFS_ALL_REQUIREMENTS
>  EROFS_REQUIREMENT_LZ4_0PADDING
> >
> > +/*
> > + * feature definations.
> > + */
> > +#define EROFS_FEATURE_SB_CHKSUM              0x0001
> > +
> > +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \
> > +     ( le32_to_cpu((super)->features) & (mask) )
> > +
> >  struct erofs_super_block {
> >  /*  0 */__le32 magic;           /* in the little endian */
> > -/*  4 */__le32 checksum;        /* crc32c(super_block) */
> > -/*  8 */__le32 features;        /* (aka. feature_compat) */
> > -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only
> */
> > -/* 13 */__u8 reserved;
> > -
> > -/* 14 */__le16 root_nid;
> > -/* 16 */__le64 inos;            /* total valid ino # (== f_files -
> f_favail) */
> > -
> > -/* 24 */__le64 build_time;      /* inode v1 time derivation */
> > -/* 32 */__le32 build_time_nsec;
> > -/* 36 */__le32 blocks;          /* used for statfs */
> > -/* 40 */__le32 meta_blkaddr;
> > -/* 44 */__le32 xattr_blkaddr;
> > -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */
> > -/* 64 */__u8 volume_name[16];   /* volume name */
> > -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */
> > -
> > +/*  4 */__le32 features;        /* (aka. feature_compat) */
> > +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only
> */
> > +/*  9 */__u8 reserved;
> > +
> > +/* 10 */__le16 root_nid;
> > +/* 12 */__le64 inos;            /* total valid ino # (== f_files -
> f_favail) */
> > +/* 20 */__le64 build_time;      /* inode v1 time derivation */
> > +/* 28 */__le32 build_time_nsec;
> > +/* 32 */__le32 blocks;          /* used for statfs */
> > +/* 36 */__le32 meta_blkaddr;
> > +/* 40 */__le32 xattr_blkaddr;
> > +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */
> > +/* 60 */__u8 volume_name[16];   /* volume name */
> > +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */
> > +/* 80 */__le32 checksum;        /* crc32c(super_block) */
> >  /* 84 */__u8 reserved2[44];
>
> Why modifying the above?
>
> >  } __packed;                     /* 128 bytes */
> >
> > diff --git a/mkfs/main.c b/mkfs/main.c
> > index f127fe1..26e14a3 100644
> > --- a/mkfs/main.c
> > +++ b/mkfs/main.c
> > @@ -13,12 +13,14 @@
> >  #include <limits.h>
> >  #include <libgen.h>
> >  #include <sys/stat.h>
> > +#include <zlib.h>
>
> I have no idea that we should introduce "zlib" just for crc32c currently...
> Maybe we can add some independent crc32 function..
>
> Thanks,
> Gao Xiang
>
> >  #include "erofs/config.h"
> >  #include "erofs/print.h"
> >  #include "erofs/cache.h"
> >  #include "erofs/inode.h"
> >  #include "erofs/io.h"
> >  #include "erofs/compress.h"
> > +#include "erofs/defs.h"
> >
> >  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct
> erofs_super_block))
> >
> > @@ -31,6 +33,28 @@ static void usage(void)
> >       fprintf(stderr, " -EX[,...] X=extended options\n");
> >  }
> >
> > +char *feature_opts[] = {
> > +     "sb_cksum", NULL
> > +};
> > +#define O_SB_CKSUM   0
> > +
> > +static int parse_feature_subopts(char *opts)
> > +{
> > +     char *arg;
> > +
> > +     while (*opts != '\0') {
> > +             switch(getsubopt(&opts, feature_opts, &arg)) {
> > +             case O_SB_CKSUM:
> > +                     cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;
> > +                     break;
> > +             default:
> > +                     erofs_err("incorrect suboption");
> > +                     return -EINVAL;
> > +             }
> > +     }
> > +     return 0;
> > +}
> > +
> >  static int parse_extended_opts(const char *opts)
> >  {
> >  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> > @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char
> *argv[])
> >  {
> >       int opt, i;
> >
> > -     while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> > +     while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
> >               switch (opt) {
> >               case 'z':
> >                       if (!optarg) {
> > @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char
> *argv[])
> >                               return opt;
> >                       break;
> >
> > +             case 'o':
> > +                     opt = parse_feature_subopts(optarg);
> > +                     if (opt)
> > +                             return opt;
> > +                     break;
> > +
> >               default: /* '?' */
> >                       return -EINVAL;
> >               }
> > @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char
> *argv[])
> >       return 0;
> >  }
> >
> > +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> > +{
> > +     int offset;
> > +     u32 crc;
> > +
> > +     offset = offsetof(struct erofs_super_block, checksum);
> > +     if (offset < 0 || offset > sizeof(struct erofs_super_block)) {
> > +             erofs_err("Invalid offset of checksum field: %d", offset);
> > +             return -1;
> > +     }
> > +     crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);
> > +     erofs_dump("superblock checksum: 0x%x\n", crc);
> > +     return 0;
> > +}
> > +
> >  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
> >                                 erofs_nid_t root_nid)
> >  {
> > @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct
> erofs_buffer_head *bh,
> >               .meta_blkaddr  = sbi.meta_blkaddr,
> >               .xattr_blkaddr = 0,
> >               .requirements = cpu_to_le32(sbi.requirements),
> > +             .features = cpu_to_le32(cfg.c_feature_flags),
> >       };
> >       const unsigned int sb_blksize =
> >               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> > @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct
> erofs_buffer_head *bh,
> >       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
> >       sb.root_nid     = cpu_to_le16(root_nid);
> >
> > +     if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> > +             u32 crc = erofs_superblock_checksum(&sb);
> > +             sb.checksum = cpu_to_le32(crc);
> > +     }
> > +
> >       buf = calloc(sb_blksize, 1);
> >       if (!buf) {
> >               erofs_err("Failed to allocate memory for sb: %s",
> > --
> > 2.9.3
> >
>

[-- Attachment #2: Type: text/html, Size: 11578 bytes --]

<div dir="ltr"><div>Hi Gao,</div><div>Yes I will make the suboption naming similar to that of mk2fs.</div><div><br></div><div>The reason I changed the position of &#39;checksum&#39; field :</div><div><br></div><div>Since we are calculating the checksum of erofs_super_block structure and storing it in the same structure; we cannot include <br></div><div>this field for actual crc calculations. Keeping it at the end makes it easy for me to calculate length of the data of which</div><div>checksum needs to be calculated. I saw similar logic in other filesystems like ext4.</div><div><br></div><div>We can write our own crc32() function. :) There is no problem. I thought zlib already provides one &amp; we can use it.</div><div>anyways , I will write.</div><div><br></div><div>--Pratik.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Aug 24, 2019 at 2:16 PM Gao Xiang &lt;<a href="mailto:hsiangkao@gmx.com">hsiangkao@gmx.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Pratik,<br>
<br>
On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:<br>
&gt; Adding code for superblock checksum calculation.<br>
&gt;<br>
&gt; This patch adds following things:<br>
&gt; 1)Handle suboptions(&#39;-o&#39;) to mkfs utility.<br>
<br>
Thanks for your patch. :)<br>
<br>
Can we use &quot;-O feature&quot; instead in order to keep in line with mke2fs?<br>
<br>
&gt; 2)Add superblock checksum calculation(-o sb_cksum) as suboption.<br>
<br>
ditto. and I think we can enable sbcrc by default since it is a compat feature,<br>
and add &quot;-O nosbcrc&quot; to disable it.<br>
<br>
&gt; 3)Calculate superblock checksum if feature is enabled.<br>
&gt;<br>
&gt; Signed-off-by: Pratik Shinde &lt;<a href="mailto:pratikshinde320@gmail.com" target="_blank">pratikshinde320@gmail.com</a>&gt;<br>
<br>
And could you please also read my following comments and fix them.<br>
and I&#39;d like to accept your erofs-utils modification in advance. :)<br>
<br>
<br>
But now you can see we are moving EROFS out of staging now as<br>
the &quot;real&quot; part of Linux, this is the fundamental stuff of other<br>
new features if we want to develop more actively... So we can wait<br>
for the final result and add this new feature to kernel then...<br>
<br>
&gt; ---<br>
&gt;  include/erofs/config.h |  1 +<br>
&gt;  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------<br>
&gt;  mkfs/main.c            | 53 +++++++++++++++++++++++++++++++++++++++++++++++++-<br>
&gt;  3 files changed, 76 insertions(+), 18 deletions(-)<br>
&gt;<br>
&gt; diff --git a/include/erofs/config.h b/include/erofs/config.h<br>
&gt; index 05fe6b2..40cd466 100644<br>
&gt; --- a/include/erofs/config.h<br>
&gt; +++ b/include/erofs/config.h<br>
&gt; @@ -22,6 +22,7 @@ struct erofs_configure {<br>
&gt;       char *c_src_path;<br>
&gt;       char *c_compr_alg_master;<br>
&gt;       int c_compr_level_master;<br>
&gt; +     int c_feature_flags;<br>
<br>
we can add this to sbi like requirements...<br>
<br>
&gt;  };<br>
&gt;<br>
&gt;  extern struct erofs_configure cfg;<br>
&gt; diff --git a/include/erofs_fs.h b/include/erofs_fs.h<br>
&gt; index 601b477..c9ef057 100644<br>
&gt; --- a/include/erofs_fs.h<br>
&gt; +++ b/include/erofs_fs.h<br>
&gt; @@ -20,25 +20,31 @@<br>
&gt;  #define EROFS_REQUIREMENT_LZ4_0PADDING       0x00000001<br>
&gt;  #define EROFS_ALL_REQUIREMENTS               EROFS_REQUIREMENT_LZ4_0PADDING<br>
&gt;<br>
&gt; +/*<br>
&gt; + * feature definations.<br>
&gt; + */<br>
&gt; +#define EROFS_FEATURE_SB_CHKSUM              0x0001<br>
&gt; +<br>
&gt; +#define EROFS_HAS_COMPAT_FEATURE(super,mask) \<br>
&gt; +     ( le32_to_cpu((super)-&gt;features) &amp; (mask) )<br>
&gt; +<br>
&gt;  struct erofs_super_block {<br>
&gt;  /*  0 */__le32 magic;           /* in the little endian */<br>
&gt; -/*  4 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt; -/*  8 */__le32 features;        /* (aka. feature_compat) */<br>
&gt; -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only */<br>
&gt; -/* 13 */__u8 reserved;<br>
&gt; -<br>
&gt; -/* 14 */__le16 root_nid;<br>
&gt; -/* 16 */__le64 inos;            /* total valid ino # (== f_files - f_favail) */<br>
&gt; -<br>
&gt; -/* 24 */__le64 build_time;      /* inode v1 time derivation */<br>
&gt; -/* 32 */__le32 build_time_nsec;<br>
&gt; -/* 36 */__le32 blocks;          /* used for statfs */<br>
&gt; -/* 40 */__le32 meta_blkaddr;<br>
&gt; -/* 44 */__le32 xattr_blkaddr;<br>
&gt; -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */<br>
&gt; -/* 64 */__u8 volume_name[16];   /* volume name */<br>
&gt; -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */<br>
&gt; -<br>
&gt; +/*  4 */__le32 features;        /* (aka. feature_compat) */<br>
&gt; +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only */<br>
&gt; +/*  9 */__u8 reserved;<br>
&gt; +<br>
&gt; +/* 10 */__le16 root_nid;<br>
&gt; +/* 12 */__le64 inos;            /* total valid ino # (== f_files - f_favail) */<br>
&gt; +/* 20 */__le64 build_time;      /* inode v1 time derivation */<br>
&gt; +/* 28 */__le32 build_time_nsec;<br>
&gt; +/* 32 */__le32 blocks;          /* used for statfs */<br>
&gt; +/* 36 */__le32 meta_blkaddr;<br>
&gt; +/* 40 */__le32 xattr_blkaddr;<br>
&gt; +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */<br>
&gt; +/* 60 */__u8 volume_name[16];   /* volume name */<br>
&gt; +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */<br>
&gt; +/* 80 */__le32 checksum;        /* crc32c(super_block) */<br>
&gt;  /* 84 */__u8 reserved2[44];<br>
<br>
Why modifying the above?<br>
<br>
&gt;  } __packed;                     /* 128 bytes */<br>
&gt;<br>
&gt; diff --git a/mkfs/main.c b/mkfs/main.c<br>
&gt; index f127fe1..26e14a3 100644<br>
&gt; --- a/mkfs/main.c<br>
&gt; +++ b/mkfs/main.c<br>
&gt; @@ -13,12 +13,14 @@<br>
&gt;  #include &lt;limits.h&gt;<br>
&gt;  #include &lt;libgen.h&gt;<br>
&gt;  #include &lt;sys/stat.h&gt;<br>
&gt; +#include &lt;zlib.h&gt;<br>
<br>
I have no idea that we should introduce &quot;zlib&quot; just for crc32c currently...<br>
Maybe we can add some independent crc32 function..<br>
<br>
Thanks,<br>
Gao Xiang<br>
<br>
&gt;  #include &quot;erofs/config.h&quot;<br>
&gt;  #include &quot;erofs/print.h&quot;<br>
&gt;  #include &quot;erofs/cache.h&quot;<br>
&gt;  #include &quot;erofs/inode.h&quot;<br>
&gt;  #include &quot;erofs/io.h&quot;<br>
&gt;  #include &quot;erofs/compress.h&quot;<br>
&gt; +#include &quot;erofs/defs.h&quot;<br>
&gt;<br>
&gt;  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block))<br>
&gt;<br>
&gt; @@ -31,6 +33,28 @@ static void usage(void)<br>
&gt;       fprintf(stderr, &quot; -EX[,...] X=extended options\n&quot;);<br>
&gt;  }<br>
&gt;<br>
&gt; +char *feature_opts[] = {<br>
&gt; +     &quot;sb_cksum&quot;, NULL<br>
&gt; +};<br>
&gt; +#define O_SB_CKSUM   0<br>
&gt; +<br>
&gt; +static int parse_feature_subopts(char *opts)<br>
&gt; +{<br>
&gt; +     char *arg;<br>
&gt; +<br>
&gt; +     while (*opts != &#39;\0&#39;) {<br>
&gt; +             switch(getsubopt(&amp;opts, feature_opts, &amp;arg)) {<br>
&gt; +             case O_SB_CKSUM:<br>
&gt; +                     cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;<br>
&gt; +                     break;<br>
&gt; +             default:<br>
&gt; +                     erofs_err(&quot;incorrect suboption&quot;);<br>
&gt; +                     return -EINVAL;<br>
&gt; +             }<br>
&gt; +     }<br>
&gt; +     return 0;<br>
&gt; +}<br>
&gt; +<br>
&gt;  static int parse_extended_opts(const char *opts)<br>
&gt;  {<br>
&gt;  #define MATCH_EXTENTED_OPT(opt, token, keylen) \<br>
&gt; @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])<br>
&gt;  {<br>
&gt;       int opt, i;<br>
&gt;<br>
&gt; -     while ((opt = getopt(argc, argv, &quot;d:z:E:&quot;)) != -1) {<br>
&gt; +     while ((opt = getopt(argc, argv, &quot;d:z:E:o:&quot;)) != -1) {<br>
&gt;               switch (opt) {<br>
&gt;               case &#39;z&#39;:<br>
&gt;                       if (!optarg) {<br>
&gt; @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])<br>
&gt;                               return opt;<br>
&gt;                       break;<br>
&gt;<br>
&gt; +             case &#39;o&#39;:<br>
&gt; +                     opt = parse_feature_subopts(optarg);<br>
&gt; +                     if (opt)<br>
&gt; +                             return opt;<br>
&gt; +                     break;<br>
&gt; +<br>
&gt;               default: /* &#39;?&#39; */<br>
&gt;                       return -EINVAL;<br>
&gt;               }<br>
&gt; @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])<br>
&gt;       return 0;<br>
&gt;  }<br>
&gt;<br>
&gt; +u32 erofs_superblock_checksum(struct erofs_super_block *sb)<br>
&gt; +{<br>
&gt; +     int offset;<br>
&gt; +     u32 crc;<br>
&gt; +<br>
&gt; +     offset = offsetof(struct erofs_super_block, checksum);<br>
&gt; +     if (offset &lt; 0 || offset &gt; sizeof(struct erofs_super_block)) {<br>
&gt; +             erofs_err(&quot;Invalid offset of checksum field: %d&quot;, offset);<br>
&gt; +             return -1;<br>
&gt; +     }<br>
&gt; +     crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);<br>
&gt; +     erofs_dump(&quot;superblock checksum: 0x%x\n&quot;, crc);<br>
&gt; +     return 0;<br>
&gt; +}<br>
&gt; +<br>
&gt;  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt;                                 erofs_nid_t root_nid)<br>
&gt;  {<br>
&gt; @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt;               .meta_blkaddr  = sbi.meta_blkaddr,<br>
&gt;               .xattr_blkaddr = 0,<br>
&gt;               .requirements = cpu_to_le32(sbi.requirements),<br>
&gt; +             .features = cpu_to_le32(cfg.c_feature_flags),<br>
&gt;       };<br>
&gt;       const unsigned int sb_blksize =<br>
&gt;               round_up(EROFS_SUPER_END, EROFS_BLKSIZ);<br>
&gt; @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,<br>
&gt;       sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));<br>
&gt;       sb.root_nid     = cpu_to_le16(root_nid);<br>
&gt;<br>
&gt; +     if (EROFS_HAS_COMPAT_FEATURE(&amp;sb, EROFS_FEATURE_SB_CHKSUM)) {<br>
&gt; +             u32 crc = erofs_superblock_checksum(&amp;sb);<br>
&gt; +             sb.checksum = cpu_to_le32(crc);<br>
&gt; +     }<br>
&gt; +<br>
&gt;       buf = calloc(sb_blksize, 1);<br>
&gt;       if (!buf) {<br>
&gt;               erofs_err(&quot;Failed to allocate memory for sb: %s&quot;,<br>
&gt; --<br>
&gt; 2.9.3<br>
&gt;<br>
</blockquote></div>

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

* Re: [PATCH] erofs-utils: code for superblock checksum calculation.
  2019-08-24  7:41 Pratik Shinde
@ 2019-08-24  8:46 ` Gao Xiang
  2019-08-24  9:22   ` Pratik Shinde
  0 siblings, 1 reply; 19+ messages in thread
From: Gao Xiang @ 2019-08-24  8:46 UTC (permalink / raw)
  To: Pratik Shinde; +Cc: miaoxie, linux-erofs

Hi Pratik,

On Sat, Aug 24, 2019 at 01:11:58PM +0530, Pratik Shinde wrote:
> Adding code for superblock checksum calculation.
>
> This patch adds following things:
> 1)Handle suboptions('-o') to mkfs utility.

Thanks for your patch. :)

Can we use "-O feature" instead in order to keep in line with mke2fs?

> 2)Add superblock checksum calculation(-o sb_cksum) as suboption.

ditto. and I think we can enable sbcrc by default since it is a compat feature,
and add "-O nosbcrc" to disable it.

> 3)Calculate superblock checksum if feature is enabled.
>
> Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>

And could you please also read my following comments and fix them.
and I'd like to accept your erofs-utils modification in advance. :)


But now you can see we are moving EROFS out of staging now as
the "real" part of Linux, this is the fundamental stuff of other
new features if we want to develop more actively... So we can wait
for the final result and add this new feature to kernel then...

> ---
>  include/erofs/config.h |  1 +
>  include/erofs_fs.h     | 40 +++++++++++++++++++++----------------
>  mkfs/main.c            | 53 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 76 insertions(+), 18 deletions(-)
>
> diff --git a/include/erofs/config.h b/include/erofs/config.h
> index 05fe6b2..40cd466 100644
> --- a/include/erofs/config.h
> +++ b/include/erofs/config.h
> @@ -22,6 +22,7 @@ struct erofs_configure {
>  	char *c_src_path;
>  	char *c_compr_alg_master;
>  	int c_compr_level_master;
> +	int c_feature_flags;

we can add this to sbi like requirements...

>  };
>
>  extern struct erofs_configure cfg;
> diff --git a/include/erofs_fs.h b/include/erofs_fs.h
> index 601b477..c9ef057 100644
> --- a/include/erofs_fs.h
> +++ b/include/erofs_fs.h
> @@ -20,25 +20,31 @@
>  #define EROFS_REQUIREMENT_LZ4_0PADDING	0x00000001
>  #define EROFS_ALL_REQUIREMENTS		EROFS_REQUIREMENT_LZ4_0PADDING
>
> +/*
> + * feature definations.
> + */
> +#define EROFS_FEATURE_SB_CHKSUM		0x0001
> +
> +#define EROFS_HAS_COMPAT_FEATURE(super,mask)	\
> +	( le32_to_cpu((super)->features) & (mask) )
> +
>  struct erofs_super_block {
>  /*  0 */__le32 magic;           /* in the little endian */
> -/*  4 */__le32 checksum;        /* crc32c(super_block) */
> -/*  8 */__le32 features;        /* (aka. feature_compat) */
> -/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only */
> -/* 13 */__u8 reserved;
> -
> -/* 14 */__le16 root_nid;
> -/* 16 */__le64 inos;            /* total valid ino # (== f_files - f_favail) */
> -
> -/* 24 */__le64 build_time;      /* inode v1 time derivation */
> -/* 32 */__le32 build_time_nsec;
> -/* 36 */__le32 blocks;          /* used for statfs */
> -/* 40 */__le32 meta_blkaddr;
> -/* 44 */__le32 xattr_blkaddr;
> -/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */
> -/* 64 */__u8 volume_name[16];   /* volume name */
> -/* 80 */__le32 requirements;    /* (aka. feature_incompat) */
> -
> +/*  4 */__le32 features;        /* (aka. feature_compat) */
> +/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only */
> +/*  9 */__u8 reserved;
> +
> +/* 10 */__le16 root_nid;
> +/* 12 */__le64 inos;            /* total valid ino # (== f_files - f_favail) */
> +/* 20 */__le64 build_time;      /* inode v1 time derivation */
> +/* 28 */__le32 build_time_nsec;
> +/* 32 */__le32 blocks;          /* used for statfs */
> +/* 36 */__le32 meta_blkaddr;
> +/* 40 */__le32 xattr_blkaddr;
> +/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */
> +/* 60 */__u8 volume_name[16];   /* volume name */
> +/* 76 */__le32 requirements;    /* (aka. feature_incompat) */
> +/* 80 */__le32 checksum;        /* crc32c(super_block) */
>  /* 84 */__u8 reserved2[44];

Why modifying the above?

>  } __packed;                     /* 128 bytes */
>
> diff --git a/mkfs/main.c b/mkfs/main.c
> index f127fe1..26e14a3 100644
> --- a/mkfs/main.c
> +++ b/mkfs/main.c
> @@ -13,12 +13,14 @@
>  #include <limits.h>
>  #include <libgen.h>
>  #include <sys/stat.h>
> +#include <zlib.h>

I have no idea that we should introduce "zlib" just for crc32c currently...
Maybe we can add some independent crc32 function..

Thanks,
Gao Xiang

>  #include "erofs/config.h"
>  #include "erofs/print.h"
>  #include "erofs/cache.h"
>  #include "erofs/inode.h"
>  #include "erofs/io.h"
>  #include "erofs/compress.h"
> +#include "erofs/defs.h"
>
>  #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block))
>
> @@ -31,6 +33,28 @@ static void usage(void)
>  	fprintf(stderr, " -EX[,...] X=extended options\n");
>  }
>
> +char *feature_opts[] = {
> +	"sb_cksum", NULL
> +};
> +#define O_SB_CKSUM	0
> +
> +static int parse_feature_subopts(char *opts)
> +{
> +	char *arg;
> +
> +	while (*opts != '\0') {
> +		switch(getsubopt(&opts, feature_opts, &arg)) {
> +		case O_SB_CKSUM:
> +			cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;
> +			break;
> +		default:
> +			erofs_err("incorrect suboption");
> +			return -EINVAL;
> +		}
> +	}
> +	return 0;
> +}
> +
>  static int parse_extended_opts(const char *opts)
>  {
>  #define MATCH_EXTENTED_OPT(opt, token, keylen) \
> @@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
>  {
>  	int opt, i;
>
> -	while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
> +	while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
>  		switch (opt) {
>  		case 'z':
>  			if (!optarg) {
> @@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
>  				return opt;
>  			break;
>
> +		case 'o':
> +			opt = parse_feature_subopts(optarg);
> +			if (opt)
> +				return opt;
> +			break;
> +
>  		default: /* '?' */
>  			return -EINVAL;
>  		}
> @@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
>  	return 0;
>  }
>
> +u32 erofs_superblock_checksum(struct erofs_super_block *sb)
> +{
> +	int offset;
> +	u32 crc;
> +
> +	offset = offsetof(struct erofs_super_block, checksum);
> +	if (offset < 0 || offset > sizeof(struct erofs_super_block)) {
> +		erofs_err("Invalid offset of checksum field: %d", offset);
> +		return -1;
> +	}
> +	crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);
> +	erofs_dump("superblock checksum: 0x%x\n", crc);
> +	return 0;
> +}
> +
>  int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
>  				  erofs_nid_t root_nid)
>  {
> @@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
>  		.meta_blkaddr  = sbi.meta_blkaddr,
>  		.xattr_blkaddr = 0,
>  		.requirements = cpu_to_le32(sbi.requirements),
> +		.features = cpu_to_le32(cfg.c_feature_flags),
>  	};
>  	const unsigned int sb_blksize =
>  		round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
> @@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
>  	sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
>  	sb.root_nid     = cpu_to_le16(root_nid);
>
> +	if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
> +		u32 crc = erofs_superblock_checksum(&sb);
> +		sb.checksum = cpu_to_le32(crc);
> +	}
> +
>  	buf = calloc(sb_blksize, 1);
>  	if (!buf) {
>  		erofs_err("Failed to allocate memory for sb: %s",
> --
> 2.9.3
>

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

* [PATCH] erofs-utils: code for superblock checksum calculation.
@ 2019-08-24  7:41 Pratik Shinde
  2019-08-24  8:46 ` Gao Xiang
  0 siblings, 1 reply; 19+ messages in thread
From: Pratik Shinde @ 2019-08-24  7:41 UTC (permalink / raw)
  To: linux-erofs, bluce.liguifu, miaoxie, fangwei1

Adding code for superblock checksum calculation.

This patch adds following things:
1)Handle suboptions('-o') to mkfs utility.
2)Add superblock checksum calculation(-o sb_cksum) as suboption.
3)Calculate superblock checksum if feature is enabled.

Signed-off-by: Pratik Shinde <pratikshinde320@gmail.com>
---
 include/erofs/config.h |  1 +
 include/erofs_fs.h     | 40 +++++++++++++++++++++----------------
 mkfs/main.c            | 53 +++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/include/erofs/config.h b/include/erofs/config.h
index 05fe6b2..40cd466 100644
--- a/include/erofs/config.h
+++ b/include/erofs/config.h
@@ -22,6 +22,7 @@ struct erofs_configure {
 	char *c_src_path;
 	char *c_compr_alg_master;
 	int c_compr_level_master;
+	int c_feature_flags;
 };
 
 extern struct erofs_configure cfg;
diff --git a/include/erofs_fs.h b/include/erofs_fs.h
index 601b477..c9ef057 100644
--- a/include/erofs_fs.h
+++ b/include/erofs_fs.h
@@ -20,25 +20,31 @@
 #define EROFS_REQUIREMENT_LZ4_0PADDING	0x00000001
 #define EROFS_ALL_REQUIREMENTS		EROFS_REQUIREMENT_LZ4_0PADDING
 
+/*
+ * feature definations.
+ */
+#define EROFS_FEATURE_SB_CHKSUM		0x0001
+
+#define EROFS_HAS_COMPAT_FEATURE(super,mask)	\
+	( le32_to_cpu((super)->features) & (mask) )
+
 struct erofs_super_block {
 /*  0 */__le32 magic;           /* in the little endian */
-/*  4 */__le32 checksum;        /* crc32c(super_block) */
-/*  8 */__le32 features;        /* (aka. feature_compat) */
-/* 12 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only */
-/* 13 */__u8 reserved;
-
-/* 14 */__le16 root_nid;
-/* 16 */__le64 inos;            /* total valid ino # (== f_files - f_favail) */
-
-/* 24 */__le64 build_time;      /* inode v1 time derivation */
-/* 32 */__le32 build_time_nsec;
-/* 36 */__le32 blocks;          /* used for statfs */
-/* 40 */__le32 meta_blkaddr;
-/* 44 */__le32 xattr_blkaddr;
-/* 48 */__u8 uuid[16];          /* 128-bit uuid for volume */
-/* 64 */__u8 volume_name[16];   /* volume name */
-/* 80 */__le32 requirements;    /* (aka. feature_incompat) */
-
+/*  4 */__le32 features;        /* (aka. feature_compat) */
+/*  8 */__u8 blkszbits;         /* support block_size == PAGE_SIZE only */
+/*  9 */__u8 reserved;
+
+/* 10 */__le16 root_nid;
+/* 12 */__le64 inos;            /* total valid ino # (== f_files - f_favail) */
+/* 20 */__le64 build_time;      /* inode v1 time derivation */
+/* 28 */__le32 build_time_nsec;
+/* 32 */__le32 blocks;          /* used for statfs */
+/* 36 */__le32 meta_blkaddr;
+/* 40 */__le32 xattr_blkaddr;
+/* 44 */__u8 uuid[16];          /* 128-bit uuid for volume */
+/* 60 */__u8 volume_name[16];   /* volume name */
+/* 76 */__le32 requirements;    /* (aka. feature_incompat) */
+/* 80 */__le32 checksum;        /* crc32c(super_block) */
 /* 84 */__u8 reserved2[44];
 } __packed;                     /* 128 bytes */
 
diff --git a/mkfs/main.c b/mkfs/main.c
index f127fe1..26e14a3 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -13,12 +13,14 @@
 #include <limits.h>
 #include <libgen.h>
 #include <sys/stat.h>
+#include <zlib.h>
 #include "erofs/config.h"
 #include "erofs/print.h"
 #include "erofs/cache.h"
 #include "erofs/inode.h"
 #include "erofs/io.h"
 #include "erofs/compress.h"
+#include "erofs/defs.h"
 
 #define EROFS_SUPER_END (EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block))
 
@@ -31,6 +33,28 @@ static void usage(void)
 	fprintf(stderr, " -EX[,...] X=extended options\n");
 }
 
+char *feature_opts[] = {
+	"sb_cksum", NULL
+};
+#define O_SB_CKSUM	0
+
+static int parse_feature_subopts(char *opts)
+{
+	char *arg;
+
+	while (*opts != '\0') {
+		switch(getsubopt(&opts, feature_opts, &arg)) {
+		case O_SB_CKSUM:
+			cfg.c_feature_flags |= EROFS_FEATURE_SB_CHKSUM;
+			break;
+		default:
+			erofs_err("incorrect suboption");
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
 static int parse_extended_opts(const char *opts)
 {
 #define MATCH_EXTENTED_OPT(opt, token, keylen) \
@@ -79,7 +103,7 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 {
 	int opt, i;
 
-	while ((opt = getopt(argc, argv, "d:z:E:")) != -1) {
+	while ((opt = getopt(argc, argv, "d:z:E:o:")) != -1) {
 		switch (opt) {
 		case 'z':
 			if (!optarg) {
@@ -113,6 +137,12 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 				return opt;
 			break;
 
+		case 'o':
+			opt = parse_feature_subopts(optarg);
+			if (opt)
+				return opt;
+			break;
+
 		default: /* '?' */
 			return -EINVAL;
 		}
@@ -144,6 +174,21 @@ static int mkfs_parse_options_cfg(int argc, char *argv[])
 	return 0;
 }
 
+u32 erofs_superblock_checksum(struct erofs_super_block *sb)
+{
+	int offset;
+	u32 crc;
+
+	offset = offsetof(struct erofs_super_block, checksum);
+	if (offset < 0 || offset > sizeof(struct erofs_super_block)) {
+		erofs_err("Invalid offset of checksum field: %d", offset);
+		return -1;
+	}
+	crc = crc32(~0, (const unsigned char *)sb,(size_t)offset);
+	erofs_dump("superblock checksum: 0x%x\n", crc);
+	return 0;
+}
+
 int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
 				  erofs_nid_t root_nid)
 {
@@ -155,6 +200,7 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
 		.meta_blkaddr  = sbi.meta_blkaddr,
 		.xattr_blkaddr = 0,
 		.requirements = cpu_to_le32(sbi.requirements),
+		.features = cpu_to_le32(cfg.c_feature_flags),
 	};
 	const unsigned int sb_blksize =
 		round_up(EROFS_SUPER_END, EROFS_BLKSIZ);
@@ -169,6 +215,11 @@ int erofs_mkfs_update_super_block(struct erofs_buffer_head *bh,
 	sb.blocks       = cpu_to_le32(erofs_mapbh(NULL, true));
 	sb.root_nid     = cpu_to_le16(root_nid);
 
+	if (EROFS_HAS_COMPAT_FEATURE(&sb, EROFS_FEATURE_SB_CHKSUM)) {
+		u32 crc = erofs_superblock_checksum(&sb);
+		sb.checksum = cpu_to_le32(crc);
+	}
+
 	buf = calloc(sb_blksize, 1);
 	if (!buf) {
 		erofs_err("Failed to allocate memory for sb: %s",
-- 
2.9.3


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

end of thread, back to index

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-24 12:38 [PATCH] erofs-utils: code for superblock checksum calculation Pratik Shinde
2019-08-24 14:00 ` Gao Xiang via Linux-erofs
2019-08-24 14:12   ` Gao Xiang via Linux-erofs
2019-08-24 14:56   ` Pratik Shinde
2019-08-24 15:16     ` Gao Xiang via Linux-erofs
2019-10-06  5:39     ` Gao Xiang via Linux-erofs
2019-10-09  6:29       ` Pratik Shinde
2019-10-09  6:57         ` Gao Xiang
2019-10-09  8:24           ` Pratik Shinde
2019-10-09  8:48             ` Gao Xiang
2019-10-09 14:14               ` Pratik Shinde
2019-10-09 14:27                 ` Gao Xiang via Linux-erofs
  -- strict thread matches above, loose matches on Subject: below --
2019-08-24  7:41 Pratik Shinde
2019-08-24  8:46 ` Gao Xiang
2019-08-24  9:22   ` Pratik Shinde
2019-08-24  9:49     ` Gao Xiang via Linux-erofs
2019-08-24 10:01       ` Chao Yu
2019-08-24 10:05         ` Pratik Shinde
2019-08-24 10:14           ` Gao Xiang via Linux-erofs

Linux-EROFS Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-erofs/0 linux-erofs/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-erofs linux-erofs/ https://lore.kernel.org/linux-erofs \
		linux-erofs@lists.ozlabs.org linux-erofs@ozlabs.org
	public-inbox-index linux-erofs

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.ozlabs.lists.linux-erofs


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git