[kernel] r12360 - in dists/sid/linux-2.6/debian: . patches/bugfix/all patches/series

Martin Michlmayr tbm at alioth.debian.org
Wed Oct 29 06:27:35 UTC 2008


Author: tbm
Date: Wed Oct 29 06:27:33 2008
New Revision: 12360

Log:
ext3/ext4: Add support for non-native signed/unsigned htree hash
algorithms (Theodore Ts'o). (closes: 493957)


Added:
   dists/sid/linux-2.6/debian/patches/bugfix/all/ext3-add-support-for-non-native-signed-unsigned-htr.patch
   dists/sid/linux-2.6/debian/patches/bugfix/all/ext4-add-support-for-non-native-signed-unsigned-htr.patch
Modified:
   dists/sid/linux-2.6/debian/changelog
   dists/sid/linux-2.6/debian/patches/series/10

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog	(original)
+++ dists/sid/linux-2.6/debian/changelog	Wed Oct 29 06:27:33 2008
@@ -5,6 +5,8 @@
 
   [ Martin Michlmayr ]
   * DNS-323: add support for revision B1 machines (Matthew Palmer).
+  * ext3/ext4: Add support for non-native signed/unsigned htree hash
+    algorithms (Theodore Ts'o). (closes: 493957)
 
   [ Bastian Blank ]
   * agp: Fix stolen memory counting on Intel G4X. (closes: #502606)

Added: dists/sid/linux-2.6/debian/patches/bugfix/all/ext3-add-support-for-non-native-signed-unsigned-htr.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/all/ext3-add-support-for-non-native-signed-unsigned-htr.patch	Wed Oct 29 06:27:33 2008
@@ -0,0 +1,230 @@
+From: Theodore Ts'o <tytso at mit.edu>
+Date: Mon, 20 Oct 2008 23:16:21 -0400
+Subject: [PATCH] ext3: Add support for non-native signed/unsigned htree hash algorithms
+
+The original ext3 hash algorithms assumed that variables of type char
+were signed, as God and K&R intended.  Unfortunately, this assumption
+is not true on some architectures.  Userspace support for marking
+filesystems with non-native signed/unsigned chars was added two years
+ago, but the kernel-side support was never added (until now).
+
+Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
+
+diff -urN a/fs/ext3/hash.c b/fs/ext3/hash.c
+--- a/fs/ext3/hash.c	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext3/hash.c	2008-10-28 19:44:22.000000000 +0000
+@@ -35,11 +35,20 @@
+ 
+ 
+ /* The old legacy hash */
+-static __u32 dx_hack_hash (const char *name, int len)
++static __u32 dx_hack_hash (const char *name, int len, int unsigned_flag)
+ {
+-	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++ 	const unsigned char *ucp = (const unsigned char *) name;
++	const signed char *scp = (const signed char *) name;
++	int c;
++
+ 	while (len--) {
+-		__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
++		if (unsigned_flag)
++			c = (int) *ucp++;
++		else
++			c = (int) *scp++;
++
++		hash = hash1 + (hash0 ^ (c * 7152373));
+ 
+ 		if (hash & 0x80000000) hash -= 0x7fffffff;
+ 		hash1 = hash0;
+@@ -48,10 +57,13 @@
+ 	return (hash0 << 1);
+ }
+ 
+-static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
++static void str2hashbuf(const char *msg, int len, __u32 *buf, int num,
++			int unsigned_flag)
+ {
+ 	__u32	pad, val;
+-	int	i;
++	int	i, c;
++	const unsigned char *ucp = (const unsigned char *) msg;
++	const signed char *scp = (const signed char *) msg;
+ 
+ 	pad = (__u32)len | ((__u32)len << 8);
+ 	pad |= pad << 16;
+@@ -62,7 +74,12 @@
+ 	for (i=0; i < len; i++) {
+ 		if ((i % 4) == 0)
+ 			val = pad;
+-		val = msg[i] + (val << 8);
++		if (unsigned_flag)
++			c = (int) ucp[i];
++		else
++			c = (int) scp[i];
++
++		val = c + (val << 8);
+ 		if ((i % 4) == 3) {
+ 			*buf++ = val;
+ 			val = pad;
+@@ -95,6 +112,7 @@
+ 	const char	*p;
+ 	int		i;
+ 	__u32		in[8], buf[4];
++	int		unsigned_flag = 0;
+ 
+ 	/* Initialize the default seed for the hash checksum functions */
+ 	buf[0] = 0x67452301;
+@@ -113,13 +131,17 @@
+ 	}
+ 
+ 	switch (hinfo->hash_version) {
++	case DX_HASH_LEGACY_UNSIGNED:
++		unsigned_flag++;
+ 	case DX_HASH_LEGACY:
+-		hash = dx_hack_hash(name, len);
++		hash = dx_hack_hash(name, len, unsigned_flag);
+ 		break;
++	case DX_HASH_HALF_MD4_UNSIGNED:
++		unsigned_flag++;
+ 	case DX_HASH_HALF_MD4:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 8);
++			str2hashbuf(p, len, in, 8, unsigned_flag);
+ 			half_md4_transform(buf, in);
+ 			len -= 32;
+ 			p += 32;
+@@ -127,10 +149,12 @@
+ 		minor_hash = buf[2];
+ 		hash = buf[1];
+ 		break;
++	case DX_HASH_TEA_UNSIGNED:
++		unsigned_flag++;
+ 	case DX_HASH_TEA:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 4);
++			str2hashbuf(p, len, in, 4, unsigned_flag);
+ 			TEA_transform(buf, in);
+ 			len -= 16;
+ 			p += 16;
+diff -urN a/fs/ext3/namei.c b/fs/ext3/namei.c
+--- a/fs/ext3/namei.c	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext3/namei.c	2008-10-28 19:44:22.000000000 +0000
+@@ -369,6 +369,8 @@
+ 		goto fail;
+ 	}
+ 	hinfo->hash_version = root->info.hash_version;
++	if (hinfo->hash_version <= DX_HASH_TEA)
++		hinfo->hash_version += EXT3_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo->seed = EXT3_SB(dir->i_sb)->s_hash_seed;
+ 	if (dentry)
+ 		ext3fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
+@@ -637,6 +639,9 @@
+ 	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(EXT3_I(dir)->i_flags & EXT3_INDEX_FL)) {
+ 		hinfo.hash_version = EXT3_SB(dir->i_sb)->s_def_hash_version;
++		if (hinfo.hash_version <= DX_HASH_TEA)
++			hinfo.hash_version +=
++				EXT3_SB(dir->i_sb)->s_hash_unsigned;
+ 		hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
+ 		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
+ 					       start_hash, start_minor_hash);
+@@ -1413,6 +1418,8 @@
+ 
+ 	/* Initialize as for dx_probe */
+ 	hinfo.hash_version = root->info.hash_version;
++	if (hinfo.hash_version <= DX_HASH_TEA)
++		hinfo.hash_version += EXT3_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo.seed = EXT3_SB(dir->i_sb)->s_hash_seed;
+ 	ext3fs_dirhash(name, namelen, &hinfo);
+ 	frame = frames;
+diff -urN a/fs/ext3/super.c b/fs/ext3/super.c
+--- a/fs/ext3/super.c	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext3/super.c	2008-10-28 19:44:22.000000000 +0000
+@@ -1712,6 +1712,21 @@
+ 	for (i=0; i < 4; i++)
+ 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+ 	sbi->s_def_hash_version = es->s_def_hash_version;
++	i = le32_to_cpu(es->s_flags);
++	if (i & EXT2_FLAGS_UNSIGNED_HASH)
++		sbi->s_hash_unsigned = 3;
++	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
++		char	c;
++
++		c = (char) 255;
++		if (((int) c) == -1) {
++			es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
++		} else {
++			es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
++			sbi->s_hash_unsigned = 3;
++		}
++		sb->s_dirt = 1;
++	}
+ 
+ 	if (sbi->s_blocks_per_group > blocksize * 8) {
+ 		printk (KERN_ERR
+diff -urN a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
+--- a/include/linux/ext3_fs.h	2008-10-28 19:43:42.000000000 +0000
++++ b/include/linux/ext3_fs.h	2008-10-28 19:44:22.000000000 +0000
+@@ -354,6 +354,13 @@
+ #define	EXT3_ORPHAN_FS			0x0004	/* Orphans being recovered */
+ 
+ /*
++ * Misc. filesystem flags
++ */
++#define EXT2_FLAGS_SIGNED_HASH		0x0001  /* Signed dirhash in use */
++#define EXT2_FLAGS_UNSIGNED_HASH	0x0002  /* Unsigned dirhash in use */
++#define EXT2_FLAGS_TEST_FILESYS		0x0004	/* to test development code */
++
++/*
+  * Mount flags
+  */
+ #define EXT3_MOUNT_CHECK		0x00001	/* Do mount-time checks */
+@@ -487,7 +494,23 @@
+ 	__u16	s_reserved_word_pad;
+ 	__le32	s_default_mount_opts;
+ 	__le32	s_first_meta_bg;	/* First metablock block group */
+-	__u32	s_reserved[190];	/* Padding to the end of the block */
++	__le32	s_mkfs_time;		/* When the filesystem was created */
++	__le32	s_jnl_blocks[17];	/* Backup of the journal inode */
++	/* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
++/*150*/	__le32	s_blocks_count_hi;	/* Blocks count */
++	__le32	s_r_blocks_count_hi;	/* Reserved blocks count */
++	__le32	s_free_blocks_count_hi;	/* Free blocks count */
++	__le16	s_min_extra_isize;	/* All inodes have at least # bytes */
++	__le16	s_want_extra_isize; 	/* New inodes should reserve # bytes */
++	__le32	s_flags;		/* Miscellaneous flags */
++	__le16  s_raid_stride;		/* RAID stride */
++	__le16  s_mmp_interval;         /* # seconds to wait in MMP checking */
++	__le64  s_mmp_block;            /* Block for multi-mount protection */
++	__le32  s_raid_stripe_width;    /* blocks on all data disks (N*stride)*/
++	__u8	s_log_groups_per_flex;  /* FLEX_BG group size */
++	__u8	s_reserved_char_pad2;
++	__le16  s_reserved_pad;
++	__u32   s_reserved[162];        /* Padding to the end of the block */
+ };
+ 
+ #ifdef __KERNEL__
+@@ -692,6 +715,9 @@
+ #define DX_HASH_LEGACY		0
+ #define DX_HASH_HALF_MD4	1
+ #define DX_HASH_TEA		2
++#define DX_HASH_LEGACY_UNSIGNED	3
++#define DX_HASH_HALF_MD4_UNSIGNED	4
++#define DX_HASH_TEA_UNSIGNED		5
+ 
+ #ifdef __KERNEL__
+ 
+diff -urN a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
+--- a/include/linux/ext3_fs_sb.h	2008-10-28 19:43:42.000000000 +0000
++++ b/include/linux/ext3_fs_sb.h	2008-10-28 19:44:22.000000000 +0000
+@@ -57,6 +57,7 @@
+ 	u32 s_next_generation;
+ 	u32 s_hash_seed[4];
+ 	int s_def_hash_version;
++	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
+ 	struct percpu_counter s_freeblocks_counter;
+ 	struct percpu_counter s_freeinodes_counter;
+ 	struct percpu_counter s_dirs_counter;

Added: dists/sid/linux-2.6/debian/patches/bugfix/all/ext4-add-support-for-non-native-signed-unsigned-htr.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/bugfix/all/ext4-add-support-for-non-native-signed-unsigned-htr.patch	Wed Oct 29 06:27:33 2008
@@ -0,0 +1,191 @@
+From: Theodore Ts'o <tytso at mit.edu>
+Date: Mon, 20 Oct 2008 22:57:37 -0400
+Subject: [PATCH] ext4: Add support for non-native signed/unsigned htree hash algorithms
+
+The original ext3 hash algorithms assumed that variables of type char
+were signed, as God and K&R intended.  Unfortunately, this assumption
+is not true on some architectures.  Userspace support for marking
+filesystems with non-native signed/unsigned chars was added two years
+ago, but the kernel-side support was never added (until now).
+
+Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
+
+diff -urN a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+--- a/fs/ext4/ext4.h	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext4/ext4.h	2008-10-28 19:48:22.000000000 +0000
+@@ -872,6 +872,9 @@
+ #define DX_HASH_LEGACY		0
+ #define DX_HASH_HALF_MD4	1
+ #define DX_HASH_TEA		2
++#define DX_HASH_LEGACY_UNSIGNED	3
++#define DX_HASH_HALF_MD4_UNSIGNED	4
++#define DX_HASH_TEA_UNSIGNED		5
+ 
+ #ifdef __KERNEL__
+ 
+diff -urN a/fs/ext4/ext4_sb.h b/fs/ext4/ext4_sb.h
+--- a/fs/ext4/ext4_sb.h	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext4/ext4_sb.h	2008-10-28 19:48:22.000000000 +0000
+@@ -56,6 +56,7 @@
+ 	u32 s_next_generation;
+ 	u32 s_hash_seed[4];
+ 	int s_def_hash_version;
++	int s_hash_unsigned;	/* 3 if hash should be signed, 0 if not */
+ 	struct percpu_counter s_freeblocks_counter;
+ 	struct percpu_counter s_freeinodes_counter;
+ 	struct percpu_counter s_dirs_counter;
+diff -urN a/fs/ext4/hash.c b/fs/ext4/hash.c
+--- a/fs/ext4/hash.c	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext4/hash.c	2008-10-28 19:59:19.000000000 +0000
+@@ -35,11 +35,20 @@
+ 
+ 
+ /* The old legacy hash */
+-static __u32 dx_hack_hash (const char *name, int len)
++static __u32 dx_hack_hash(const char *name, int len, int unsigned_flag)
+ {
+-	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
++	const unsigned char *ucp = (const unsigned char *) name;
++	const signed char *scp = (const signed char *) name;
++	int c;
++
+ 	while (len--) {
+-		__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
++		if (unsigned_flag)
++			c = (int) *ucp++;
++		else
++			c = (int) *scp++;
++
++		hash = hash1 + (hash0 ^ (c * 7152373));
+ 
+ 		if (hash & 0x80000000) hash -= 0x7fffffff;
+ 		hash1 = hash0;
+@@ -48,10 +57,13 @@
+ 	return (hash0 << 1);
+ }
+ 
+-static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
++static void str2hashbuf(const char *msg, int len, __u32 *buf, int num,
++			int unsigned_flag)
+ {
+ 	__u32	pad, val;
+-	int	i;
++	int	i, c;
++	const unsigned char *ucp = (const unsigned char *) msg;
++	const signed char *scp = (const signed char *) msg;
+ 
+ 	pad = (__u32)len | ((__u32)len << 8);
+ 	pad |= pad << 16;
+@@ -62,7 +74,12 @@
+ 	for (i=0; i < len; i++) {
+ 		if ((i % 4) == 0)
+ 			val = pad;
+-		val = msg[i] + (val << 8);
++		if (unsigned_flag)
++			c = (int) ucp[i];
++		else
++			c = (int) scp[i];
++
++		val = c + (val << 8);
+ 		if ((i % 4) == 3) {
+ 			*buf++ = val;
+ 			val = pad;
+@@ -95,6 +112,7 @@
+ 	const char	*p;
+ 	int		i;
+ 	__u32		in[8], buf[4];
++	int		unsigned_flag = 0;
+ 
+ 	/* Initialize the default seed for the hash checksum functions */
+ 	buf[0] = 0x67452301;
+@@ -113,13 +131,17 @@
+ 	}
+ 
+ 	switch (hinfo->hash_version) {
++	case DX_HASH_LEGACY_UNSIGNED:
++		unsigned_flag++;
+ 	case DX_HASH_LEGACY:
+-		hash = dx_hack_hash(name, len);
++		hash = dx_hack_hash(name, len, unsigned_flag);
+ 		break;
++	case DX_HASH_HALF_MD4_UNSIGNED:
++		unsigned_flag++;
+ 	case DX_HASH_HALF_MD4:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 8);
++			str2hashbuf(p, len, in, 8, unsigned_flag);
+ 			half_md4_transform(buf, in);
+ 			len -= 32;
+ 			p += 32;
+@@ -127,10 +149,12 @@
+ 		minor_hash = buf[2];
+ 		hash = buf[1];
+ 		break;
++	case DX_HASH_TEA_UNSIGNED:
++		unsigned_flag++;
+ 	case DX_HASH_TEA:
+ 		p = name;
+ 		while (len > 0) {
+-			str2hashbuf(p, len, in, 4);
++			str2hashbuf(p, len, in, 4, unsigned_flag);
+ 			TEA_transform(buf, in);
+ 			len -= 16;
+ 			p += 16;
+diff -urN a/fs/ext4/namei.c b/fs/ext4/namei.c
+--- a/fs/ext4/namei.c	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext4/namei.c	2008-10-28 19:48:22.000000000 +0000
+@@ -361,6 +361,8 @@
+ 		goto fail;
+ 	}
+ 	hinfo->hash_version = root->info.hash_version;
++	if (hinfo->hash_version <= DX_HASH_TEA)
++		hinfo->hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 	if (dentry)
+ 		ext4fs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
+@@ -639,6 +641,9 @@
+ 	dir = dir_file->f_path.dentry->d_inode;
+ 	if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
+ 		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
++		if (hinfo.hash_version <= DX_HASH_TEA)
++			hinfo.hash_version +=
++				EXT4_SB(dir->i_sb)->s_hash_unsigned;
+ 		hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
+ 					       start_hash, start_minor_hash);
+@@ -1415,6 +1420,8 @@
+ 
+ 	/* Initialize as for dx_probe */
+ 	hinfo.hash_version = root->info.hash_version;
++	if (hinfo.hash_version <= DX_HASH_TEA)
++		hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
+ 	hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
+ 	ext4fs_dirhash(name, namelen, &hinfo);
+ 	frame = frames;
+diff -urN a/fs/ext4/super.c b/fs/ext4/super.c
+--- a/fs/ext4/super.c	2008-10-28 19:43:40.000000000 +0000
++++ b/fs/ext4/super.c	2008-10-28 19:48:22.000000000 +0000
+@@ -2071,6 +2071,21 @@
+ 	for (i=0; i < 4; i++)
+ 		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+ 	sbi->s_def_hash_version = es->s_def_hash_version;
++	i = le32_to_cpu(es->s_flags);
++	if (i & EXT2_FLAGS_UNSIGNED_HASH)
++		sbi->s_hash_unsigned = 3;
++	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
++		char	c;
++
++		c = (char) 255;
++		if (((int) c) == -1) {
++			es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
++		} else {
++			es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
++			sbi->s_hash_unsigned = 3;
++		}
++		sb->s_dirt = 1;
++	}
+ 
+ 	if (sbi->s_blocks_per_group > blocksize * 8) {
+ 		printk (KERN_ERR

Modified: dists/sid/linux-2.6/debian/patches/series/10
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/10	(original)
+++ dists/sid/linux-2.6/debian/patches/series/10	Wed Oct 29 06:27:33 2008
@@ -1,3 +1,5 @@
 + bugfix/all/sctp-fix-kernel-panic-while-process-protocol-violation-parameter.patch
 + features/arm/dns323_revb1.patch
 + bugfix/all/drivers-char-agp-intel-correct-gm4x-stolen.patch
++ bugfix/all/ext3-add-support-for-non-native-signed-unsigned-htr.patch
++ bugfix/all/ext4-add-support-for-non-native-signed-unsigned-htr.patch



More information about the Kernel-svn-changes mailing list