linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/4] 64k pagesize/blocksize fixes
@ 2007-09-25 23:30 Christoph Lameter
  2007-09-25 23:30 ` [patch 1/4] Increase limits for 64k page size support for Ext2/3/4 Christoph Lameter
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Christoph Lameter @ 2007-09-25 23:30 UTC (permalink / raw)
  To: Mingming Cao; +Cc: Takashi Sato, linux-fsdevel

Attached the fixes necessary to support 64k pagesize/blocksize. I think these are useful
independent of the large blocksize patchset since there are architectures that support
64k page size and that could use these large buffer sizes without the large buffersize
patchset.

Are these patches in the right shape to be merged? I rediffed these against 2.6.32-rc8-mm1.

I had to fix some things in the second patch (ext2) that may need some review since the
way that commits work changed.

-- 

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

* [patch 1/4] Increase limits for 64k page size support for Ext2/3/4
  2007-09-25 23:30 [patch 0/4] 64k pagesize/blocksize fixes Christoph Lameter
@ 2007-09-25 23:30 ` Christoph Lameter
  2007-09-25 23:30 ` [patch 2/4] ext2: fix rec_len overflow for 64KB block size Christoph Lameter
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Christoph Lameter @ 2007-09-25 23:30 UTC (permalink / raw)
  To: Mingming Cao; +Cc: Takashi Sato, linux-fsdevel

[-- Attachment #1: lbs_ext2-3-4 --]
[-- Type: text/plain, Size: 5035 bytes --]

[This patch allows architectures that use 64k blocksizes--like IA64 and
PPC64--to use 64k blocks on ext filesystems]

The patches to support blocksizes up to PAGESIZE, max 64KB for ext2/3/4,\
were originally from Takashi Sato.
http://marc.info/?l=linux-ext4&m=115768873518400&w=2

It's quite simple to support large block size in ext2/3/4, mostly just
enlarge the block size limit.  But it is NOT possible to have 64kB
blocksize on ext2/3/4 without some changes to the directory handling
code.  The reason is that an empty 64kB directory block would have a
rec_len == (__u16)2^16 == 0, and this would cause an error to be hit in
the filesystem.  The proposed solution is to put 2 empty records in such
a directory, or to special-case an impossible value like rec_len =
0xffff to handle this.

Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 fs/ext2/super.c         |    2 +-
 fs/ext3/super.c         |    5 ++++-
 fs/ext4/super.c         |    5 +++++
 include/linux/ext2_fs.h |    4 ++--
 include/linux/ext3_fs.h |    4 ++--
 include/linux/ext4_fs.h |    4 ++--
 6 files changed, 16 insertions(+), 8 deletions(-)

Index: linux-2.6.23-rc8-mm1/fs/ext2/super.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext2/super.c	2007-09-25 14:53:57.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext2/super.c	2007-09-25 15:37:34.000000000 -0700
@@ -856,7 +856,7 @@ static int ext2_fill_super(struct super_
 		brelse(bh);
 
 		if (!sb_set_blocksize(sb, blocksize)) {
-			printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n");
+			printk(KERN_ERR "EXT2-fs: bad blocksize %d.\n", blocksize);
 			goto failed_sbi;
 		}
 
Index: linux-2.6.23-rc8-mm1/fs/ext3/super.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext3/super.c	2007-09-25 14:53:57.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext3/super.c	2007-09-25 15:37:34.000000000 -0700
@@ -1625,7 +1625,10 @@ static int ext3_fill_super (struct super
 		}
 
 		brelse (bh);
-		sb_set_blocksize(sb, blocksize);
+		if (!sb_set_blocksize(sb, blocksize)) {
+			printk(KERN_ERR "EXT3-fs: bad blocksize %d.\n", blocksize);
+			goto out_fail;
+		}
 		logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;
 		offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
 		bh = sb_bread(sb, logic_sb_block);
Index: linux-2.6.23-rc8-mm1/fs/ext4/super.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext4/super.c	2007-09-25 14:53:57.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext4/super.c	2007-09-25 15:37:34.000000000 -0700
@@ -1652,6 +1652,11 @@ static int ext4_fill_super (struct super
 		goto out_fail;
 	}
 
+	if (!sb_set_blocksize(sb, blocksize)) {
+		printk(KERN_ERR "EXT4-fs: bad blocksize %d.\n", blocksize);
+		goto out_fail;
+	}
+
 	/*
 	 * The ext4 superblock will not be buffer aligned for other than 1kB
 	 * block sizes.  We need to calculate the offset from buffer start.
Index: linux-2.6.23-rc8-mm1/include/linux/ext2_fs.h
===================================================================
--- linux-2.6.23-rc8-mm1.orig/include/linux/ext2_fs.h	2007-09-25 14:53:58.000000000 -0700
+++ linux-2.6.23-rc8-mm1/include/linux/ext2_fs.h	2007-09-25 15:37:34.000000000 -0700
@@ -87,8 +87,8 @@ static inline struct ext2_sb_info *EXT2_
  * Macro-instructions used to manage several block sizes
  */
 #define EXT2_MIN_BLOCK_SIZE		1024
-#define	EXT2_MAX_BLOCK_SIZE		4096
-#define EXT2_MIN_BLOCK_LOG_SIZE		  10
+#define EXT2_MAX_BLOCK_SIZE		65536
+#define EXT2_MIN_BLOCK_LOG_SIZE		10
 #ifdef __KERNEL__
 # define EXT2_BLOCK_SIZE(s)		((s)->s_blocksize)
 #else
Index: linux-2.6.23-rc8-mm1/include/linux/ext3_fs.h
===================================================================
--- linux-2.6.23-rc8-mm1.orig/include/linux/ext3_fs.h	2007-09-24 17:33:10.000000000 -0700
+++ linux-2.6.23-rc8-mm1/include/linux/ext3_fs.h	2007-09-25 15:37:34.000000000 -0700
@@ -76,8 +76,8 @@
  * Macro-instructions used to manage several block sizes
  */
 #define EXT3_MIN_BLOCK_SIZE		1024
-#define	EXT3_MAX_BLOCK_SIZE		4096
-#define EXT3_MIN_BLOCK_LOG_SIZE		  10
+#define	EXT3_MAX_BLOCK_SIZE		65536
+#define EXT3_MIN_BLOCK_LOG_SIZE		10
 #ifdef __KERNEL__
 # define EXT3_BLOCK_SIZE(s)		((s)->s_blocksize)
 #else
Index: linux-2.6.23-rc8-mm1/include/linux/ext4_fs.h
===================================================================
--- linux-2.6.23-rc8-mm1.orig/include/linux/ext4_fs.h	2007-09-25 14:53:58.000000000 -0700
+++ linux-2.6.23-rc8-mm1/include/linux/ext4_fs.h	2007-09-25 15:37:34.000000000 -0700
@@ -77,8 +77,8 @@
  * Macro-instructions used to manage several block sizes
  */
 #define EXT4_MIN_BLOCK_SIZE		1024
-#define	EXT4_MAX_BLOCK_SIZE		4096
-#define EXT4_MIN_BLOCK_LOG_SIZE		  10
+#define	EXT4_MAX_BLOCK_SIZE		65536
+#define EXT4_MIN_BLOCK_LOG_SIZE		10
 #ifdef __KERNEL__
 # define EXT4_BLOCK_SIZE(s)		((s)->s_blocksize)
 #else

-- 

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

* [patch 2/4] ext2: fix rec_len overflow for 64KB block size
  2007-09-25 23:30 [patch 0/4] 64k pagesize/blocksize fixes Christoph Lameter
  2007-09-25 23:30 ` [patch 1/4] Increase limits for 64k page size support for Ext2/3/4 Christoph Lameter
@ 2007-09-25 23:30 ` Christoph Lameter
  2007-09-26  0:42   ` Andreas Dilger
  2007-09-25 23:30 ` [patch 3/4] ext3: fix rec_len overflow with " Christoph Lameter
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Christoph Lameter @ 2007-09-25 23:30 UTC (permalink / raw)
  To: Mingming Cao; +Cc: Takashi Sato, linux-fsdevel

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

[2/4]  ext2: fix rec_len overflow
         - prevent rec_len from overflow with 64KB blocksize

Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 fs/ext2/dir.c           |   46 ++++++++++++++++++++++++++++++++++++----------
 include/linux/ext2_fs.h |   13 +++++++++++++
 2 files changed, 49 insertions(+), 10 deletions(-)

Index: linux-2.6.23-rc8-mm1/fs/ext2/dir.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext2/dir.c	2007-09-25 15:59:34.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext2/dir.c	2007-09-25 16:02:51.000000000 -0700
@@ -105,9 +105,9 @@ static void ext2_check_page(struct page 
 			goto out;
 	}
 	for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
+		offs = EXT2_DIR_ADJUST_TAIL_OFFS(offs, chunk_size);
 		p = (ext2_dirent *)(kaddr + offs);
 		rec_len = le16_to_cpu(p->rec_len);
-
 		if (rec_len < EXT2_DIR_REC_LEN(1))
 			goto Eshort;
 		if (rec_len & 3)
@@ -119,6 +119,7 @@ static void ext2_check_page(struct page 
 		if (le32_to_cpu(p->inode) > max_inumber)
 			goto Einumber;
 	}
+	offs = EXT2_DIR_ADJUST_TAIL_OFFS(offs, chunk_size);
 	if (offs != limit)
 		goto Eend;
 out:
@@ -294,6 +295,7 @@ ext2_readdir (struct file * filp, void *
 		de = (ext2_dirent *)(kaddr+offset);
 		limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1);
 		for ( ;(char*)de <= limit; de = ext2_next_entry(de)) {
+			de = EXT2_DIR_ADJUST_TAIL_ADDR(kaddr, de, sb->s_blocksize);
 			if (de->rec_len == 0) {
 				ext2_error(sb, __FUNCTION__,
 					"zero-length directory entry");
@@ -316,8 +318,10 @@ ext2_readdir (struct file * filp, void *
 					return 0;
 				}
 			}
+			filp->f_pos = EXT2_DIR_ADJUST_TAIL_OFFS(filp->f_pos, sb->s_blocksize);
 			filp->f_pos += le16_to_cpu(de->rec_len);
 		}
+		filp->f_pos = EXT2_DIR_ADJUST_TAIL_OFFS(filp->f_pos, sb->s_blocksize);
 		ext2_put_page(page);
 	}
 	return 0;
@@ -354,13 +358,14 @@ struct ext2_dir_entry_2 * ext2_find_entr
 		start = 0;
 	n = start;
 	do {
-		char *kaddr;
+		char *kaddr, *page_start;
 		page = ext2_get_page(dir, n);
 		if (!IS_ERR(page)) {
-			kaddr = page_address(page);
+			kaddr = page_start = page_address(page);
 			de = (ext2_dirent *) kaddr;
 			kaddr += ext2_last_byte(dir, n) - reclen;
 			while ((char *) de <= kaddr) {
+				de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de, dir->i_sb->s_blocksize);
 				if (de->rec_len == 0) {
 					ext2_error(dir->i_sb, __FUNCTION__,
 						"zero-length directory entry");
@@ -428,6 +433,7 @@ void ext2_set_link(struct inode *dir, st
 	unsigned len = le16_to_cpu(de->rec_len);
 	int err;
 
+	len = EXT2_DIR_ADJUST_TAIL_OFFS(pos, len);
 	lock_page(page);
 	err = __ext2_write_begin(NULL, page->mapping, pos, len,
 				AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
@@ -459,6 +465,7 @@ int ext2_add_link (struct dentry *dentry
 	char *kaddr;
 	loff_t pos;
 	int err;
+	char *page_start = NULL;
 
 	/*
 	 * We take care of directory expansion in the same loop.
@@ -473,16 +480,29 @@ int ext2_add_link (struct dentry *dentry
 		if (IS_ERR(page))
 			goto out;
 		lock_page(page);
-		kaddr = page_address(page);
+		kaddr = page_start = page_address(page);
 		dir_end = kaddr + ext2_last_byte(dir, n);
 		de = (ext2_dirent *)kaddr;
-		kaddr += PAGE_CACHE_SIZE - reclen;
+		if (chunk_size < EXT2_DIR_MAX_REC_LEN)
+			kaddr += PAGE_CACHE_SIZE - reclen;
+		else
+			kaddr += PAGE_CACHE_SIZE -
+				(chunk_size - EXT2_DIR_MAX_REC_LEN) - reclen;
+
 		while ((char *)de <= kaddr) {
+			de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de, chunk_size);
 			if ((char *)de == dir_end) {
 				/* We hit i_size */
 				name_len = 0;
-				rec_len = chunk_size;
-				de->rec_len = cpu_to_le16(chunk_size);
+				if (chunk_size  < EXT2_DIR_MAX_REC_LEN) {
+					rec_len = chunk_size;
+					de->rec_len = cpu_to_le16(chunk_size);
+				} else {
+					rec_len = EXT2_DIR_MAX_REC_LEN;
+					de->rec_len =
+						cpu_to_le16(EXT2_DIR_MAX_REC_LEN);
+				}
+
 				de->inode = 0;
 				goto got_it;
 			}
@@ -512,6 +532,7 @@ int ext2_add_link (struct dentry *dentry
 got_it:
 	pos = page_offset(page) +
 		(char*)de - (char*)page_address(page);
+	reclen = EXT2_DIR_ADJUST_TAIL_OFFS(pos + rec_len, chunk_size) - pos;
 	err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0,
 							&page, NULL);
 	if (err)
@@ -556,6 +577,7 @@ int ext2_delete_entry (struct ext2_dir_e
 	ext2_dirent * de = (ext2_dirent *) (kaddr + from);
 	int err;
 
+	to = EXT2_DIR_ADJUST_TAIL_OFFS(to, inode->i_sb->s_blocksize);
 	while ((char*)de < (char*)dir) {
 		if (de->rec_len == 0) {
 			ext2_error(inode->i_sb, __FUNCTION__,
@@ -617,7 +639,11 @@ int ext2_make_empty(struct inode *inode,
 
 	de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
 	de->name_len = 2;
-	de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
+	if (chunk_size < EXT2_DIR_MAX_REC_LEN) {
+		de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
+	} else {
+		de->rec_len = cpu_to_le16(EXT2_DIR_MAX_REC_LEN - EXT2_DIR_REC_LEN(1));
+	}
 	de->inode = cpu_to_le32(parent->i_ino);
 	memcpy (de->name, "..\0", 4);
 	ext2_set_de_type (de, inode);
@@ -637,18 +663,19 @@ int ext2_empty_dir (struct inode * inode
 	unsigned long i, npages = dir_pages(inode);
 
 	for (i = 0; i < npages; i++) {
-		char *kaddr;
+		char *kaddr, *page_start;
 		ext2_dirent * de;
 		page = ext2_get_page(inode, i);
 
 		if (IS_ERR(page))
 			continue;
 
-		kaddr = page_address(page);
+		kaddr = page_start = page_address(page);
 		de = (ext2_dirent *)kaddr;
 		kaddr += ext2_last_byte(inode, i) - EXT2_DIR_REC_LEN(1);
 
 		while ((char *)de <= kaddr) {
+			de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de, inode->i_sb->s_blocksize);
 			if (de->rec_len == 0) {
 				ext2_error(inode->i_sb, __FUNCTION__,
 					"zero-length directory entry");
Index: linux-2.6.23-rc8-mm1/include/linux/ext2_fs.h
===================================================================
--- linux-2.6.23-rc8-mm1.orig/include/linux/ext2_fs.h	2007-09-25 15:59:34.000000000 -0700
+++ linux-2.6.23-rc8-mm1/include/linux/ext2_fs.h	2007-09-25 16:01:38.000000000 -0700
@@ -561,6 +561,18 @@ enum {
 #define EXT2_DIR_ROUND 			(EXT2_DIR_PAD - 1)
 #define EXT2_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT2_DIR_ROUND) & \
 					 ~EXT2_DIR_ROUND)
+#define EXT2_DIR_MAX_REC_LEN            65532
+
+/*
+ * Align a tail offset(address) to the end of a directory block
+ */
+#define EXT2_DIR_ADJUST_TAIL_OFFS(offs, bsize) \
+	((((offs) & ((bsize) -1)) == EXT2_DIR_MAX_REC_LEN) ? \
+	((offs) + (bsize) - EXT2_DIR_MAX_REC_LEN):(offs))
+
+#define EXT2_DIR_ADJUST_TAIL_ADDR(page, de, bsize) \
+	(((((char*)(de) - (page)) & ((bsize) - 1)) == EXT2_DIR_MAX_REC_LEN) ? \
+	((ext2_dirent*)((char*)(de) + (bsize) - EXT2_DIR_MAX_REC_LEN)):(de))
 
 static inline ext2_fsblk_t
 ext2_group_first_block_no(struct super_block *sb, unsigned long group_no)

-- 

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

* [patch 3/4] ext3: fix rec_len overflow with 64KB block size
  2007-09-25 23:30 [patch 0/4] 64k pagesize/blocksize fixes Christoph Lameter
  2007-09-25 23:30 ` [patch 1/4] Increase limits for 64k page size support for Ext2/3/4 Christoph Lameter
  2007-09-25 23:30 ` [patch 2/4] ext2: fix rec_len overflow for 64KB block size Christoph Lameter
@ 2007-09-25 23:30 ` Christoph Lameter
  2007-09-25 23:30 ` [patch 4/4] ext4: fix rec_len overflow for " Christoph Lameter
  2007-09-26 17:58 ` [patch 0/4] 64k pagesize/blocksize fixes Mingming Cao
  4 siblings, 0 replies; 8+ messages in thread
From: Christoph Lameter @ 2007-09-25 23:30 UTC (permalink / raw)
  To: Mingming Cao; +Cc: Takashi Sato, linux-fsdevel

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

Prevent rec_len from overflow with 64KB blocksize

Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 fs/ext3/dir.c           |   13 ++++---
 fs/ext3/namei.c         |   88 +++++++++++++++++++++++++++++++++++++++---------
 include/linux/ext3_fs.h |    9 ++++
 3 files changed, 91 insertions(+), 19 deletions(-)

Index: linux-2.6.23-rc8-mm1/fs/ext3/dir.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext3/dir.c	2007-09-25 14:53:57.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext3/dir.c	2007-09-25 15:41:45.000000000 -0700
@@ -100,10 +100,11 @@ static int ext3_readdir(struct file * fi
 	unsigned long offset;
 	int i, stored;
 	struct ext3_dir_entry_2 *de;
-	struct super_block *sb;
 	int err;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	int ret = 0;
+	struct super_block *sb = inode->i_sb;
+	unsigned tail = sb->s_blocksize;
 
 	sb = inode->i_sb;
 
@@ -167,8 +168,11 @@ revalidate:
 		 * readdir(2), then we might be pointing to an invalid
 		 * dirent right now.  Scan from the start of the block
 		 * to make sure. */
-		if (filp->f_version != inode->i_version) {
-			for (i = 0; i < sb->s_blocksize && i < offset; ) {
+		if (tail >  EXT3_DIR_MAX_REC_LEN)
+			tail = EXT3_DIR_MAX_REC_LEN;
+
+               if (filp->f_version != inode->i_version) {
+			for (i = 0; i < tail && i < offset; ) {
 				de = (struct ext3_dir_entry_2 *)
 					(bh->b_data + i);
 				/* It's too expensive to do a full
@@ -189,7 +193,7 @@ revalidate:
 		}
 
 		while (!error && filp->f_pos < inode->i_size
-		       && offset < sb->s_blocksize) {
+		       && offset < tail) {
 			de = (struct ext3_dir_entry_2 *) (bh->b_data + offset);
 			if (!ext3_check_dir_entry ("ext3_readdir", inode, de,
 						   bh, offset)) {
@@ -225,6 +229,7 @@ revalidate:
 			}
 			filp->f_pos += le16_to_cpu(de->rec_len);
 		}
+		filp->f_pos = EXT3_DIR_ADJUST_TAIL_OFFS(filp->f_pos, sb->s_blocksize);
 		offset = 0;
 		brelse (bh);
 	}
Index: linux-2.6.23-rc8-mm1/fs/ext3/namei.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext3/namei.c	2007-09-24 17:33:10.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext3/namei.c	2007-09-25 15:41:45.000000000 -0700
@@ -263,9 +263,13 @@ static struct stats dx_show_leaf(struct 
 	unsigned names = 0, space = 0;
 	char *base = (char *) de;
 	struct dx_hash_info h = *hinfo;
+	unsigned tail = size;
 
 	printk("names: ");
-	while ((char *) de < base + size)
+	if (tail > EXT3_DIR_MAX_REC_LEN)
+		tail = EXT3_DIR_MAX_REC_LEN;
+
+	while ((char *) de < base + tail)
 	{
 		if (de->inode)
 		{
@@ -708,8 +712,12 @@ static int dx_make_map (struct ext3_dir_
 	int count = 0;
 	char *base = (char *) de;
 	struct dx_hash_info h = *hinfo;
+	unsigned tail = size;
+
+	if (tail > EXT3_DIR_MAX_REC_LEN)
+		tail = EXT3_DIR_MAX_REC_LEN;
 
-	while ((char *) de < base + size)
+	while ((char *) de < base + tail)
 	{
 		if (de->name_len && de->inode) {
 			ext3fs_dirhash(de->name, de->name_len, &h);
@@ -808,9 +816,13 @@ static inline int search_dirblock(struct
 	int de_len;
 	const char *name = dentry->d_name.name;
 	int namelen = dentry->d_name.len;
+	unsigned tail = dir->i_sb->s_blocksize;
 
 	de = (struct ext3_dir_entry_2 *) bh->b_data;
-	dlimit = bh->b_data + dir->i_sb->s_blocksize;
+	if (tail > EXT3_DIR_MAX_REC_LEN)
+		tail = EXT3_DIR_MAX_REC_LEN;
+
+	dlimit = bh->b_data + tail;
 	while ((char *) de < dlimit) {
 		/* this code is executed quadratically often */
 		/* do minimal checking `by hand' */
@@ -1156,6 +1168,9 @@ static struct ext3_dir_entry_2* dx_pack_
 	unsigned rec_len = 0;
 
 	prev = to = de;
+	if (size > EXT3_DIR_MAX_REC_LEN)
+		size = EXT3_DIR_MAX_REC_LEN;
+
 	while ((char*)de < base + size) {
 		next = (struct ext3_dir_entry_2 *) ((char *) de +
 						    le16_to_cpu(de->rec_len));
@@ -1237,8 +1252,15 @@ static struct ext3_dir_entry_2 *do_split
 	/* Fancy dance to stay within two buffers */
 	de2 = dx_move_dirents(data1, data2, map + split, count - split);
 	de = dx_pack_dirents(data1,blocksize);
-	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-	de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+	if (blocksize < EXT3_DIR_MAX_REC_LEN) {
+		de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+		de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+	} else {
+		de->rec_len = cpu_to_le16(data1 + EXT3_DIR_MAX_REC_LEN -
+							(char *) de);
+		de2->rec_len = cpu_to_le16(data2 + EXT3_DIR_MAX_REC_LEN -
+							(char *) de2);
+	}
 	dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data1, blocksize, 1));
 	dxtrace(dx_show_leaf (hinfo, (struct ext3_dir_entry_2 *) data2, blocksize, 1));
 
@@ -1293,11 +1315,15 @@ static int add_dirent_to_buf(handle_t *h
 	unsigned short	reclen;
 	int		nlen, rlen, err;
 	char		*top;
+	unsigned	tail = dir->i_sb->s_blocksize;
+
+	if (tail > EXT3_DIR_MAX_REC_LEN)
+		tail = EXT3_DIR_MAX_REC_LEN;
 
 	reclen = EXT3_DIR_REC_LEN(namelen);
 	if (!de) {
 		de = (struct ext3_dir_entry_2 *)bh->b_data;
-		top = bh->b_data + dir->i_sb->s_blocksize - reclen;
+		top = bh->b_data + tail - reclen;
 		while ((char *) de <= top) {
 			if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
 						  bh, offset)) {
@@ -1411,13 +1437,21 @@ static int make_indexed_dir(handle_t *ha
 	/* The 0th block becomes the root, move the dirents out */
 	fde = &root->dotdot;
 	de = (struct ext3_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len));
-	len = ((char *) root) + blocksize - (char *) de;
+	if (blocksize < EXT3_DIR_MAX_REC_LEN)
+		len = ((char *) root) + blocksize - (char *) de;
+	else
+		len = ((char *) root) + EXT3_DIR_MAX_REC_LEN - (char *) de;
+
 	memcpy (data1, de, len);
 	de = (struct ext3_dir_entry_2 *) data1;
 	top = data1 + len;
 	while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top)
 		de = de2;
-	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+	if (blocksize < EXT3_DIR_MAX_REC_LEN)
+		de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+	else
+		de->rec_len = cpu_to_le16(data1 + EXT3_DIR_MAX_REC_LEN - (char *) de);
+
 	/* Initialize the root; the dot dirents already exist */
 	de = (struct ext3_dir_entry_2 *) (&root->dotdot);
 	de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
@@ -1507,7 +1541,11 @@ static int ext3_add_entry (handle_t *han
 		return retval;
 	de = (struct ext3_dir_entry_2 *) bh->b_data;
 	de->inode = 0;
-	de->rec_len = cpu_to_le16(blocksize);
+	if (blocksize < EXT3_DIR_MAX_REC_LEN)
+		de->rec_len = cpu_to_le16(blocksize);
+	else
+		de->rec_len = cpu_to_le16(EXT3_DIR_MAX_REC_LEN);
+
 	return add_dirent_to_buf(handle, dentry, inode, de, bh);
 }
 
@@ -1571,7 +1609,12 @@ static int ext3_dx_add_entry(handle_t *h
 			goto cleanup;
 		node2 = (struct dx_node *)(bh2->b_data);
 		entries2 = node2->entries;
-		node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+		if (sb->s_blocksize < EXT3_DIR_MAX_REC_LEN)
+			node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+		else
+			node2->fake.rec_len =
+				cpu_to_le16(EXT3_DIR_MAX_REC_LEN);
+
 		node2->fake.inode = 0;
 		BUFFER_TRACE(frame->bh, "get_write_access");
 		err = ext3_journal_get_write_access(handle, frame->bh);
@@ -1659,11 +1702,15 @@ static int ext3_delete_entry (handle_t *
 {
 	struct ext3_dir_entry_2 * de, * pde;
 	int i;
+	unsigned tail = bh->b_size;
 
 	i = 0;
 	pde = NULL;
 	de = (struct ext3_dir_entry_2 *) bh->b_data;
-	while (i < bh->b_size) {
+	if (tail > EXT3_DIR_MAX_REC_LEN)
+		tail = EXT3_DIR_MAX_REC_LEN;
+
+	while (i < tail) {
 		if (!ext3_check_dir_entry("ext3_delete_entry", dir, de, bh, i))
 			return -EIO;
 		if (de == de_del)  {
@@ -1823,7 +1870,11 @@ retry:
 	de = (struct ext3_dir_entry_2 *)
 			((char *) de + le16_to_cpu(de->rec_len));
 	de->inode = cpu_to_le32(dir->i_ino);
-	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+	if (inode->i_sb->s_blocksize < EXT3_DIR_MAX_REC_LEN)
+		de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
+	else
+		de->rec_len = cpu_to_le16(EXT3_DIR_MAX_REC_LEN-EXT3_DIR_REC_LEN(1));
+
 	de->name_len = 2;
 	strcpy (de->name, "..");
 	ext3_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -1858,10 +1909,10 @@ static int empty_dir (struct inode * ino
 	unsigned long offset;
 	struct buffer_head * bh;
 	struct ext3_dir_entry_2 * de, * de1;
-	struct super_block * sb;
+	struct super_block * sb = inode->i_sb;
 	int err = 0;
+	unsigned tail = sb->s_blocksize;
 
-	sb = inode->i_sb;
 	if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
 	    !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
 		if (err)
@@ -1888,11 +1939,17 @@ static int empty_dir (struct inode * ino
 		return 1;
 	}
 	offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
+	if (offset == EXT3_DIR_MAX_REC_LEN)
+		offset += sb->s_blocksize - EXT3_DIR_MAX_REC_LEN;
+
 	de = (struct ext3_dir_entry_2 *)
 			((char *) de1 + le16_to_cpu(de1->rec_len));
+	if (tail > EXT3_DIR_MAX_REC_LEN)
+		tail = EXT3_DIR_MAX_REC_LEN;
+
 	while (offset < inode->i_size ) {
 		if (!bh ||
-			(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+			(void *) de >= (void *) (bh->b_data + tail)) {
 			err = 0;
 			brelse (bh);
 			bh = ext3_bread (NULL, inode,
@@ -1919,6 +1976,7 @@ static int empty_dir (struct inode * ino
 			return 0;
 		}
 		offset += le16_to_cpu(de->rec_len);
+		offset = EXT3_DIR_ADJUST_TAIL_OFFS(offset, sb->s_blocksize);
 		de = (struct ext3_dir_entry_2 *)
 				((char *) de + le16_to_cpu(de->rec_len));
 	}
Index: linux-2.6.23-rc8-mm1/include/linux/ext3_fs.h
===================================================================
--- linux-2.6.23-rc8-mm1.orig/include/linux/ext3_fs.h	2007-09-25 15:37:34.000000000 -0700
+++ linux-2.6.23-rc8-mm1/include/linux/ext3_fs.h	2007-09-25 15:41:45.000000000 -0700
@@ -660,6 +660,15 @@ struct ext3_dir_entry_2 {
 #define EXT3_DIR_ROUND			(EXT3_DIR_PAD - 1)
 #define EXT3_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT3_DIR_ROUND) & \
 					 ~EXT3_DIR_ROUND)
+#define EXT3_DIR_MAX_REC_LEN		65532
+
+/*
+ * Align a tail offset to the end of a directory block
+ */
+#define EXT3_DIR_ADJUST_TAIL_OFFS(offs, bsize) \
+	((((offs) & ((bsize) -1)) == EXT3_DIR_MAX_REC_LEN) ? \
+	((offs) + (bsize) - EXT3_DIR_MAX_REC_LEN):(offs))
+
 /*
  * Hash Tree Directory indexing
  * (c) Daniel Phillips, 2001

-- 

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

* [patch 4/4] ext4: fix rec_len overflow for 64KB block size
  2007-09-25 23:30 [patch 0/4] 64k pagesize/blocksize fixes Christoph Lameter
                   ` (2 preceding siblings ...)
  2007-09-25 23:30 ` [patch 3/4] ext3: fix rec_len overflow with " Christoph Lameter
@ 2007-09-25 23:30 ` Christoph Lameter
  2007-09-26 17:58 ` [patch 0/4] 64k pagesize/blocksize fixes Mingming Cao
  4 siblings, 0 replies; 8+ messages in thread
From: Christoph Lameter @ 2007-09-25 23:30 UTC (permalink / raw)
  To: Mingming Cao; +Cc: Takashi Sato, linux-fsdevel

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

[4/4]  ext4: fix rec_len overflow
         - prevent rec_len from overflow with 64KB blocksize

Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
---
 fs/ext4/dir.c           |   11 ++++--
 fs/ext4/namei.c         |   88 +++++++++++++++++++++++++++++++++++++++---------
 include/linux/ext4_fs.h |    9 ++++
 3 files changed, 90 insertions(+), 18 deletions(-)

Index: linux-2.6.23-rc8-mm1/fs/ext4/dir.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext4/dir.c	2007-09-25 14:53:57.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext4/dir.c	2007-09-25 15:45:09.000000000 -0700
@@ -100,10 +100,11 @@ static int ext4_readdir(struct file * fi
 	unsigned long offset;
 	int i, stored;
 	struct ext4_dir_entry_2 *de;
-	struct super_block *sb;
 	int err;
 	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
 	int ret = 0;
+	unsigned tail = sb->s_blocksize;
 
 	sb = inode->i_sb;
 
@@ -166,8 +167,11 @@ revalidate:
 		 * readdir(2), then we might be pointing to an invalid
 		 * dirent right now.  Scan from the start of the block
 		 * to make sure. */
+		if (tail >  EXT4_DIR_MAX_REC_LEN)
+			tail = EXT4_DIR_MAX_REC_LEN;
+
 		if (filp->f_version != inode->i_version) {
-			for (i = 0; i < sb->s_blocksize && i < offset; ) {
+			for (i = 0; i < tail && i < offset; ) {
 				de = (struct ext4_dir_entry_2 *)
 					(bh->b_data + i);
 				/* It's too expensive to do a full
@@ -188,7 +192,7 @@ revalidate:
 		}
 
 		while (!error && filp->f_pos < inode->i_size
-		       && offset < sb->s_blocksize) {
+		       && offset < tail) {
 			de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
 			if (!ext4_check_dir_entry ("ext4_readdir", inode, de,
 						   bh, offset)) {
@@ -225,6 +229,7 @@ revalidate:
 			}
 			filp->f_pos += le16_to_cpu(de->rec_len);
 		}
+		filp->f_pos = EXT4_DIR_ADJUST_TAIL_OFFS(filp->f_pos, sb->s_blocksize);
 		offset = 0;
 		brelse (bh);
 	}
Index: linux-2.6.23-rc8-mm1/fs/ext4/namei.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext4/namei.c	2007-09-25 14:53:57.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext4/namei.c	2007-09-25 15:45:09.000000000 -0700
@@ -263,9 +263,13 @@ static struct stats dx_show_leaf(struct 
 	unsigned names = 0, space = 0;
 	char *base = (char *) de;
 	struct dx_hash_info h = *hinfo;
+	unsigned tail = size;
 
 	printk("names: ");
-	while ((char *) de < base + size)
+	if (tail > EXT4_DIR_MAX_REC_LEN)
+		tail = EXT4_DIR_MAX_REC_LEN;
+
+	while ((char *) de < base + tail)
 	{
 		if (de->inode)
 		{
@@ -708,8 +712,12 @@ static int dx_make_map (struct ext4_dir_
 	int count = 0;
 	char *base = (char *) de;
 	struct dx_hash_info h = *hinfo;
+	unsigned tail = size;
+
+	if (tail > EXT4_DIR_MAX_REC_LEN)
+		tail = EXT4_DIR_MAX_REC_LEN;
 
-	while ((char *) de < base + size)
+	while ((char *) de < base + tail)
 	{
 		if (de->name_len && de->inode) {
 			ext4fs_dirhash(de->name, de->name_len, &h);
@@ -806,9 +814,13 @@ static inline int search_dirblock(struct
 	int de_len;
 	const char *name = dentry->d_name.name;
 	int namelen = dentry->d_name.len;
+	unsigned tail = dir->i_sb->s_blocksize;
 
 	de = (struct ext4_dir_entry_2 *) bh->b_data;
-	dlimit = bh->b_data + dir->i_sb->s_blocksize;
+	if (tail > EXT4_DIR_MAX_REC_LEN)
+		tail = EXT4_DIR_MAX_REC_LEN;
+
+	dlimit = bh->b_data + tail;
 	while ((char *) de < dlimit) {
 		/* this code is executed quadratically often */
 		/* do minimal checking `by hand' */
@@ -1154,6 +1166,9 @@ static struct ext4_dir_entry_2* dx_pack_
 	unsigned rec_len = 0;
 
 	prev = to = de;
+	if (size > EXT4_DIR_MAX_REC_LEN)
+		size = EXT4_DIR_MAX_REC_LEN;
+
 	while ((char*)de < base + size) {
 		next = (struct ext4_dir_entry_2 *) ((char *) de +
 						    le16_to_cpu(de->rec_len));
@@ -1235,8 +1250,15 @@ static struct ext4_dir_entry_2 *do_split
 	/* Fancy dance to stay within two buffers */
 	de2 = dx_move_dirents(data1, data2, map + split, count - split);
 	de = dx_pack_dirents(data1,blocksize);
-	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-	de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+	if (blocksize < EXT4_DIR_MAX_REC_LEN) {
+		de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+		de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
+	} else {
+		de->rec_len = cpu_to_le16(data1 + EXT4_DIR_MAX_REC_LEN -
+							(char *) de);
+		de2->rec_len = cpu_to_le16(data2 + EXT4_DIR_MAX_REC_LEN -
+							(char *) de2);
+	}
 	dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1));
 	dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1));
 
@@ -1291,11 +1313,15 @@ static int add_dirent_to_buf(handle_t *h
 	unsigned short	reclen;
 	int		nlen, rlen, err;
 	char		*top;
+	unsigned        tail = dir->i_sb->s_blocksize;
+
+	if (tail > EXT4_DIR_MAX_REC_LEN)
+		tail = EXT4_DIR_MAX_REC_LEN;
 
 	reclen = EXT4_DIR_REC_LEN(namelen);
 	if (!de) {
 		de = (struct ext4_dir_entry_2 *)bh->b_data;
-		top = bh->b_data + dir->i_sb->s_blocksize - reclen;
+		top = bh->b_data + tail - reclen;
 		while ((char *) de <= top) {
 			if (!ext4_check_dir_entry("ext4_add_entry", dir, de,
 						  bh, offset)) {
@@ -1408,13 +1434,21 @@ static int make_indexed_dir(handle_t *ha
 	/* The 0th block becomes the root, move the dirents out */
 	fde = &root->dotdot;
 	de = (struct ext4_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len));
-	len = ((char *) root) + blocksize - (char *) de;
+	if (blocksize < EXT4_DIR_MAX_REC_LEN)
+		len = ((char *) root) + blocksize - (char *) de;
+	else
+		len = ((char *) root) + EXT4_DIR_MAX_REC_LEN - (char *) de;
+
 	memcpy (data1, de, len);
 	de = (struct ext4_dir_entry_2 *) data1;
 	top = data1 + len;
 	while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top)
 		de = de2;
-	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+	if (blocksize < EXT4_DIR_MAX_REC_LEN)
+		de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
+	else
+		de->rec_len = cpu_to_le16(data1 + EXT4_DIR_MAX_REC_LEN - (char *) de);
+
 	/* Initialize the root; the dot dirents already exist */
 	de = (struct ext4_dir_entry_2 *) (&root->dotdot);
 	de->rec_len = cpu_to_le16(blocksize - EXT4_DIR_REC_LEN(2));
@@ -1504,7 +1538,11 @@ static int ext4_add_entry (handle_t *han
 		return retval;
 	de = (struct ext4_dir_entry_2 *) bh->b_data;
 	de->inode = 0;
-	de->rec_len = cpu_to_le16(blocksize);
+	if (blocksize < EXT4_DIR_MAX_REC_LEN)
+		de->rec_len = cpu_to_le16(blocksize);
+	else
+		de->rec_len = cpu_to_le16(EXT4_DIR_MAX_REC_LEN);
+
 	return add_dirent_to_buf(handle, dentry, inode, de, bh);
 }
 
@@ -1568,7 +1606,12 @@ static int ext4_dx_add_entry(handle_t *h
 			goto cleanup;
 		node2 = (struct dx_node *)(bh2->b_data);
 		entries2 = node2->entries;
-		node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+		if (sb->s_blocksize < EXT4_DIR_MAX_REC_LEN)
+			node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
+		else
+			node2->fake.rec_len =
+				cpu_to_le16(EXT4_DIR_MAX_REC_LEN);
+
 		node2->fake.inode = 0;
 		BUFFER_TRACE(frame->bh, "get_write_access");
 		err = ext4_journal_get_write_access(handle, frame->bh);
@@ -1656,11 +1699,15 @@ static int ext4_delete_entry (handle_t *
 {
 	struct ext4_dir_entry_2 * de, * pde;
 	int i;
+	unsigned tail = bh->b_size;
 
 	i = 0;
 	pde = NULL;
 	de = (struct ext4_dir_entry_2 *) bh->b_data;
-	while (i < bh->b_size) {
+	if (tail > EXT4_DIR_MAX_REC_LEN)
+		tail = EXT4_DIR_MAX_REC_LEN;
+
+	while (i < tail) {
 		if (!ext4_check_dir_entry("ext4_delete_entry", dir, de, bh, i))
 			return -EIO;
 		if (de == de_del)  {
@@ -1848,7 +1895,11 @@ retry:
 	de = (struct ext4_dir_entry_2 *)
 			((char *) de + le16_to_cpu(de->rec_len));
 	de->inode = cpu_to_le32(dir->i_ino);
-	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT4_DIR_REC_LEN(1));
+	if (inode->i_sb->s_blocksize < EXT4_DIR_MAX_REC_LEN)
+		de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT4_DIR_REC_LEN(1));
+	else
+		de->rec_len = cpu_to_le16(EXT4_DIR_MAX_REC_LEN-EXT4_DIR_REC_LEN(1));
+
 	de->name_len = 2;
 	strcpy (de->name, "..");
 	ext4_set_de_type(dir->i_sb, de, S_IFDIR);
@@ -1883,10 +1934,10 @@ static int empty_dir (struct inode * ino
 	unsigned long offset;
 	struct buffer_head * bh;
 	struct ext4_dir_entry_2 * de, * de1;
-	struct super_block * sb;
+	struct super_block * sb = inode->i_sb;
 	int err = 0;
+	unsigned tail = sb->s_blocksize;
 
-	sb = inode->i_sb;
 	if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
 	    !(bh = ext4_bread (NULL, inode, 0, 0, &err))) {
 		if (err)
@@ -1913,11 +1964,17 @@ static int empty_dir (struct inode * ino
 		return 1;
 	}
 	offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
+	if (offset == EXT4_DIR_MAX_REC_LEN)
+		offset += sb->s_blocksize - EXT4_DIR_MAX_REC_LEN;
+
 	de = (struct ext4_dir_entry_2 *)
 			((char *) de1 + le16_to_cpu(de1->rec_len));
+	if (tail > EXT4_DIR_MAX_REC_LEN)
+		tail = EXT4_DIR_MAX_REC_LEN;
+
 	while (offset < inode->i_size ) {
 		if (!bh ||
-			(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+			(void *) de >= (void *) (bh->b_data + tail)) {
 			err = 0;
 			brelse (bh);
 			bh = ext4_bread (NULL, inode,
@@ -1944,6 +2001,7 @@ static int empty_dir (struct inode * ino
 			return 0;
 		}
 		offset += le16_to_cpu(de->rec_len);
+		offset = EXT4_DIR_ADJUST_TAIL_OFFS(offset, sb->s_blocksize);
 		de = (struct ext4_dir_entry_2 *)
 				((char *) de + le16_to_cpu(de->rec_len));
 	}
Index: linux-2.6.23-rc8-mm1/include/linux/ext4_fs.h
===================================================================
--- linux-2.6.23-rc8-mm1.orig/include/linux/ext4_fs.h	2007-09-25 15:37:34.000000000 -0700
+++ linux-2.6.23-rc8-mm1/include/linux/ext4_fs.h	2007-09-25 15:45:09.000000000 -0700
@@ -779,6 +779,15 @@ struct ext4_dir_entry_2 {
 #define EXT4_DIR_ROUND			(EXT4_DIR_PAD - 1)
 #define EXT4_DIR_REC_LEN(name_len)	(((name_len) + 8 + EXT4_DIR_ROUND) & \
 					 ~EXT4_DIR_ROUND)
+#define	EXT4_DIR_MAX_REC_LEN		65532
+
+/*
+ * Align a tail offset to the end of a directory block
+ */
+#define EXT4_DIR_ADJUST_TAIL_OFFS(offs, bsize) \
+	((((offs) & ((bsize) -1)) == EXT4_DIR_MAX_REC_LEN) ? \
+	((offs) + (bsize) - EXT4_DIR_MAX_REC_LEN):(offs))
+
 /*
  * Hash Tree Directory indexing
  * (c) Daniel Phillips, 2001

-- 

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

* Re: [patch 2/4] ext2: fix rec_len overflow for 64KB block size
  2007-09-25 23:30 ` [patch 2/4] ext2: fix rec_len overflow for 64KB block size Christoph Lameter
@ 2007-09-26  0:42   ` Andreas Dilger
  2007-09-26 17:27     ` Christoph Lameter
  0 siblings, 1 reply; 8+ messages in thread
From: Andreas Dilger @ 2007-09-26  0:42 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Mingming Cao, Takashi Sato, linux-fsdevel

On Sep 25, 2007  16:30 -0700, Christoph Lameter wrote:
> [2/4]  ext2: fix rec_len overflow
>          - prevent rec_len from overflow with 64KB blocksize
> 
> Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
> Signed-off-by: Mingming Cao <cmm@us.ibm.com>
> Signed-off-by: Christoph Lameter <clameter@sgi.com>

Note that we just got a cleaner implemantation of this code on the ext4
mailing list from Jan Kara yesterday.  Please use that one instead, in
thread "Avoid rec_len overflow with 64KB block size" instead.

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.


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

* Re: [patch 2/4] ext2: fix rec_len overflow for 64KB block size
  2007-09-26  0:42   ` Andreas Dilger
@ 2007-09-26 17:27     ` Christoph Lameter
  0 siblings, 0 replies; 8+ messages in thread
From: Christoph Lameter @ 2007-09-26 17:27 UTC (permalink / raw)
  To: Andreas Dilger; +Cc: Mingming Cao, Takashi Sato, linux-fsdevel, jack

On Tue, 25 Sep 2007, Andreas Dilger wrote:

> On Sep 25, 2007  16:30 -0700, Christoph Lameter wrote:
> > [2/4]  ext2: fix rec_len overflow
> >          - prevent rec_len from overflow with 64KB blocksize
> > 
> > Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
> > Signed-off-by: Mingming Cao <cmm@us.ibm.com>
> > Signed-off-by: Christoph Lameter <clameter@sgi.com>
> 
> Note that we just got a cleaner implemantation of this code on the ext4
> mailing list from Jan Kara yesterday.  Please use that one instead, in
> thread "Avoid rec_len overflow with 64KB block size" instead.

Yes that looks much better. He is missing the first patch that changes the 
constants.

How can we get the 4 patches (the constant change and Jan's changes to ext 
2 3 4  merged?

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

* Re: [patch 0/4] 64k pagesize/blocksize fixes
  2007-09-25 23:30 [patch 0/4] 64k pagesize/blocksize fixes Christoph Lameter
                   ` (3 preceding siblings ...)
  2007-09-25 23:30 ` [patch 4/4] ext4: fix rec_len overflow for " Christoph Lameter
@ 2007-09-26 17:58 ` Mingming Cao
  4 siblings, 0 replies; 8+ messages in thread
From: Mingming Cao @ 2007-09-26 17:58 UTC (permalink / raw)
  To: Christoph Lameter; +Cc: Takashi Sato, linux-fsdevel

On Tue, 2007-09-25 at 16:30 -0700, Christoph Lameter wrote:
> Attached the fixes necessary to support 64k pagesize/blocksize. I think these are useful
> independent of the large blocksize patchset since there are architectures that support
> 64k page size and that could use these large buffer sizes without the large buffersize
> patchset.
> 
> Are these patches in the right shape to be merged? I rediffed these against 2.6.32-rc8-mm1.
> 
> I had to fix some things in the second patch (ext2) that may need some review since the
> way that commits work changed.
> 

Thanks,  As Andreas mentioned in another email there is a better way to
deal with rec_len issue on 64k block size. I will get those patches
merged in ext4 patch queue. I think the updated patches could get
merged.


Mingming


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

end of thread, other threads:[~2007-09-26 17:58 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-25 23:30 [patch 0/4] 64k pagesize/blocksize fixes Christoph Lameter
2007-09-25 23:30 ` [patch 1/4] Increase limits for 64k page size support for Ext2/3/4 Christoph Lameter
2007-09-25 23:30 ` [patch 2/4] ext2: fix rec_len overflow for 64KB block size Christoph Lameter
2007-09-26  0:42   ` Andreas Dilger
2007-09-26 17:27     ` Christoph Lameter
2007-09-25 23:30 ` [patch 3/4] ext3: fix rec_len overflow with " Christoph Lameter
2007-09-25 23:30 ` [patch 4/4] ext4: fix rec_len overflow for " Christoph Lameter
2007-09-26 17:58 ` [patch 0/4] 64k pagesize/blocksize fixes Mingming Cao

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