lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 21 Mar 2011 20:35:20 +0100 (CET)
From:	Lukas Czerner <lczerner@...hat.com>
To:	"Theodore Ts'o" <tytso@....edu>
cc:	linux-ext4@...r.kernel.org
Subject: Re: [PATCH, RFC 01/12] ext4: read-only support for bigalloc file
 systems

On Sat, 19 Mar 2011, Theodore Ts'o wrote:

> This adds supports for bigalloc file systems.  It teaches the mount
> code just enough about bigalloc superblock fields that it will mount
> the file system without freaking out that the number of blocks per
> group is too big.
> 
> Signed-off-by: "Theodore Ts'o" <tytso@....edu>
> ---
>  fs/ext4/ext4.h  |   18 ++++++++++++++--
>  fs/ext4/super.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++-------
>  2 files changed, 65 insertions(+), 11 deletions(-)
> 
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 3aa0b72..94a7a7b 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -231,12 +231,16 @@ struct ext4_io_submit {
>  #define EXT4_MAX_BLOCK_LOG_SIZE		16
>  #ifdef __KERNEL__
>  # define EXT4_BLOCK_SIZE(s)		((s)->s_blocksize)
> +# define EXT4_CLUSTER_SIZE(s)		(EXT4_SB(s)->s_clustersize)
>  #else
> +# define EXT2_CLUSTER_SIZE(s)		(EXT2_MIN_BLOCK_SIZE << \
> +						(s)->s_log_cluster_size)
>  # define EXT4_BLOCK_SIZE(s)		(EXT4_MIN_BLOCK_SIZE << (s)->s_log_block_size)
>  #endif
>  #define	EXT4_ADDR_PER_BLOCK(s)		(EXT4_BLOCK_SIZE(s) / sizeof(__u32))
>  #ifdef __KERNEL__
>  # define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
> +# define EXT4_CLUSTER_SIZE_BITS(s)	(EXT4_SB(s)->s_clustersize_bits)
>  #else
>  # define EXT4_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
>  #endif
> @@ -302,6 +306,7 @@ struct flex_groups {
>  #define EXT4_DESC_SIZE(s)		(EXT4_SB(s)->s_desc_size)
>  #ifdef __KERNEL__
>  # define EXT4_BLOCKS_PER_GROUP(s)	(EXT4_SB(s)->s_blocks_per_group)
> +# define EXT4_CLUSTERS_PER_GROUP(s)	(EXT4_SB(s)->s_clusters_per_group)
>  # define EXT4_DESC_PER_BLOCK(s)		(EXT4_SB(s)->s_desc_per_block)
>  # define EXT4_INODES_PER_GROUP(s)	(EXT4_SB(s)->s_inodes_per_group)
>  # define EXT4_DESC_PER_BLOCK_BITS(s)	(EXT4_SB(s)->s_desc_per_block_bits)
> @@ -957,9 +962,9 @@ struct ext4_super_block {
>  /*10*/	__le32	s_free_inodes_count;	/* Free inodes count */
>  	__le32	s_first_data_block;	/* First Data Block */
>  	__le32	s_log_block_size;	/* Block size */
> -	__le32	s_obso_log_frag_size;	/* Obsoleted fragment size */
> +	__le32	s_log_cluster_size;	/* Allocation cluster size */
>  /*20*/	__le32	s_blocks_per_group;	/* # Blocks per group */
> -	__le32	s_obso_frags_per_group;	/* Obsoleted fragments per group */
> +	__le32	s_clusters_per_group;	/* # Clusters per group */
>  	__le32	s_inodes_per_group;	/* # Inodes per group */
>  	__le32	s_mtime;		/* Mount time */
>  /*30*/	__le32	s_wtime;		/* Write time */
> @@ -1055,7 +1060,10 @@ struct ext4_super_block {
>  	__u8	s_last_error_func[32];	/* function where the error happened */
>  #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
>  	__u8	s_mount_opts[64];
> -	__le32	s_reserved[112];        /* Padding to the end of the block */
> +	__le32	s_usr_quota_inum;	/* inode for tracking user quota */
> +	__le32	s_grp_quota_inum;	/* inode for tracking group quota */
> +	__le32	s_overhead_blocks;	/* overhead blocks/clusters in fs */
> +	__le32  s_reserved[109];        /* Padding to the end of the block */
>  };
>  
>  #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START)
> @@ -1075,6 +1083,7 @@ struct ext4_sb_info {
>  	unsigned long s_desc_size;	/* Size of a group descriptor in bytes */
>  	unsigned long s_inodes_per_block;/* Number of inodes per block */
>  	unsigned long s_blocks_per_group;/* Number of blocks in a group */
> +	unsigned long s_clusters_per_group; /* Number of clusters in a group */
>  	unsigned long s_inodes_per_group;/* Number of inodes in a group */
>  	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
>  	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
> @@ -1083,6 +1092,8 @@ struct ext4_sb_info {
>  	ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
>  	unsigned long s_overhead_last;  /* Last calculated overhead */
>  	unsigned long s_blocks_last;    /* Last seen block count */
> +	unsigned int s_cluster_ratio;	/* Number of blocks per group */
> +	unsigned int s_cluster_bits;	/* log2 of s_cluster_ratio */
>  	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
>  	struct buffer_head * s_sbh;	/* Buffer containing the super block */
>  	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
> @@ -1338,6 +1349,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei)
>  #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM		0x0010
>  #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK	0x0020
>  #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE	0x0040
> +#define EXT4_FEATURE_RO_COMPAT_BIGALLOC		0x0200
>  
>  #define EXT4_FEATURE_INCOMPAT_COMPRESSION	0x0001
>  #define EXT4_FEATURE_INCOMPAT_FILETYPE		0x0002
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index b357c27..7273728 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -1875,7 +1875,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
>  		res = MS_RDONLY;
>  	}
>  	if (read_only)
> -		return res;
> +		goto done;
>  	if (!(sbi->s_mount_state & EXT4_VALID_FS))
>  		ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "
>  			 "running e2fsck is recommended");
> @@ -1906,6 +1906,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
>  		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
>  
>  	ext4_commit_super(sb, 1);
> +done:
>  	if (test_opt(sb, DEBUG))
>  		printk(KERN_INFO "[EXT4 FS bs=%lu, gc=%u, "
>  				"bpg=%lu, ipg=%lu, mo=%04x, mo2=%04x]\n",

Maybe this is a bit nitpicky, but should not this be rather done in
separate commit as it has nothing to do with bigalloc ?

> @@ -3022,10 +3023,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
>  	char *cp;
>  	const char *descr;
>  	int ret = -ENOMEM;
> -	int blocksize;
> +	int blocksize, clustersize;
>  	unsigned int db_count;
>  	unsigned int i;
> -	int needs_recovery, has_huge_files;
> +	int needs_recovery, has_huge_files, has_bigalloc;
>  	__u64 blocks_count;
>  	int err;
>  	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
> @@ -3276,12 +3277,53 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
>  		sb->s_dirt = 1;
>  	}
>  
> -	if (sbi->s_blocks_per_group > blocksize * 8) {
> -		ext4_msg(sb, KERN_ERR,
> -		       "#blocks per group too big: %lu",
> -		       sbi->s_blocks_per_group);
> -		goto failed_mount;
> +	/* Handle clustersize */
> +	clustersize = BLOCK_SIZE << le32_to_cpu(es->s_log_cluster_size);
> +	has_bigalloc = EXT4_HAS_RO_COMPAT_FEATURE(sb,
> +				EXT4_FEATURE_RO_COMPAT_BIGALLOC);
> +	if (has_bigalloc) {
> +		if (clustersize < blocksize) {
> +			ext4_msg(sb, KERN_ERR,
> +				 "cluster size (%d) smaller than "
> +				 "block size (%d)", clustersize, blocksize);
> +			goto failed_mount;
> +		}
> +		sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
> +			le32_to_cpu(es->s_log_block_size);
> +		sbi->s_clusters_per_group =
> +			le32_to_cpu(es->s_clusters_per_group);
> +		if (sbi->s_clusters_per_group > blocksize * 8) {
> +			ext4_msg(sb, KERN_ERR,
> +				 "#clusters per group too big: %lu",
> +				 sbi->s_clusters_per_group);
> +			goto failed_mount;
> +		}
> +		if (sbi->s_blocks_per_group !=
> +		    (sbi->s_clusters_per_group * (clustersize / blocksize))) {
> +			ext4_msg(sb, KERN_ERR, "blocks per group (%lu) and "
> +				 "clusters per group (%lu) inconsistent",
> +				 sbi->s_blocks_per_group,
> +				 sbi->s_clusters_per_group);
> +			goto failed_mount;
> +		}
> +	} else {
> +		if (clustersize != blocksize) {
> +			ext4_warning(sb, "fragment/cluster size (%d) != "
> +				     "block size (%d)", clustersize,
> +				     blocksize);
> +			clustersize = blocksize;

I wonder if we should continue at this point, because something
definitely went wrong as it has not biballoc feature but yet
s_log_cluster_size does not match s_log_block_size which means
definitely corruption or an error somewhere.

> +		}
> +		if (sbi->s_blocks_per_group > blocksize * 8) {
> +			ext4_msg(sb, KERN_ERR,
> +				 "#blocks per group too big: %lu",
> +				 sbi->s_blocks_per_group);
> +			goto failed_mount;
> +		}
> +		sbi->s_clusters_per_group = sbi->s_blocks_per_group;
> +		sbi->s_cluster_bits = 0;
>  	}
> +	sbi->s_cluster_ratio = clustersize / blocksize;
> +
>  	if (sbi->s_inodes_per_group > blocksize * 8) {
>  		ext4_msg(sb, KERN_ERR,
>  		       "#inodes per group too big: %lu",
> 

Thanks!
-Lukas
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ