tags 348778 + patch
thanks

I got this answer on the ext2resize-devel mailing list:

[Andreas Dilger]
> That's because ext2prepare was never updated to support the "new"
> ext3 resize inode format.  There was actually a patch posted on
> ext2-devel which may fix this from Takashi Sato, but I haven't had
> time to look at it yet:
> 
> [Ext2-devel] [RFC][17/21]ext2resize fix resize_inode format

I found the diff on
<URL:http://www.ussg.iu.edu/hypermail/linux/kernel/0604.1/1090.html>,
and manually applied it to my copy of the source as the HTML version
didn't apply using patch.

Can you test it and let me know if it solve the problem for you?  I've
tested it and e2fsck no longer complains when I run it on a fresh file
system.

#! /bin/sh /usr/share/dpatch/dpatch-run
## 05_ext3newformat.dpatch
##
## DP: Update to use the new resize-inode format.  Patch from Takashi
## DP: Sato <[EMAIL PROTECTED]> found on
## DP: <URL:http://www.ussg.iu.edu/hypermail/linux/kernel/0604.1/1090.html>
## DP: and manually applied.

Summary of this patch:
  [17/21] fix the bug related to the option "resize_inode"
          - A format of resize-inode in ext2prepare is different from
            the one in mke2fs, so ext2prepare fails.  Then I adapt
            ext2prepare's to mke2fs's.

--- ext2resize-1.1.19.orig/src/ext2.c
+++ ext2resize-1.1.19/src/ext2.c
@@ -286,6 +286,7 @@
 	}
 }
 
+/* Remind: prototype returns int, but it may return blk_t */
 int ext2_block_iterate(struct ext2_fs *fs, struct ext2_inode *inode,
 		       blk_t block, int action)
 {
@@ -295,6 +296,9 @@
 	int			 count = 0;
 	int			 i;
 	int			 i512perblock = 1 << (fs->logsize - 9);
+	unsigned		 long long apb;
+
+	apb = fs->u32perblock;
 
 	if (block == 0 || inode->i_mode == 0)
 		return -1;
@@ -313,114 +317,66 @@
 		}
 	}
 
-	/* Direct blocks for first 12 blocks */
-	for (i = 0, curblock = 0; i < EXT2_NDIR_BLOCKS; i++, curblock++) {
-		if (action == EXT2_ACTION_ADD && !inode->i_block[i]) {
-			size_t new_size = (curblock + 1) * fs->blocksize;
-
-			if (fs->flags & FL_DEBUG)
-				printf("add %d as direct block\n", curblock);
-			inode->i_block[i] = block;
-			/* i_blocks is in 512 byte blocks */
-			inode->i_blocks += i512perblock;
-			if (new_size > inode->i_size)
-				inode->i_size = new_size;
-
-			inode->i_mtime = time(NULL);
-			ext2_set_block_state(fs, block, 1,
-					     !(fs->flags & FL_ONLINE));
-			return curblock;
-		}
-		if (inode->i_block[i] == block) {
-			if (action == EXT2_ACTION_DELETE) {
-				if (fs->flags & FL_DEBUG)
-					printf("del %d as direct block\n",
-					      curblock);
-				inode->i_block[i] = 0;
-				inode->i_blocks -= i512perblock;
-				inode->i_mtime = time(NULL);
-				if (!(fs->flags & FL_ONLINE))
-					ext2_set_block_state(fs, block, 0, 1);
-			}
-			return i;
-		}
-		if (inode->i_block[i])
-			count += i512perblock;
-	}
-
-	count += inode->i_block[EXT2_IND_BLOCK] ? i512perblock : 0;
-	count += inode->i_block[EXT2_DIND_BLOCK] ? i512perblock : 0;
-	count += inode->i_block[EXT2_TIND_BLOCK] ? i512perblock : 0;
-
-	if (!inode->i_block[EXT2_IND_BLOCK] ||
-	    (count >= inode->i_blocks && action != EXT2_ACTION_ADD))
+	if(!inode->i_block[EXT2_DIND_BLOCK] && action != EXT2_ACTION_ADD)
 		return -1;
 
-	bh = ext2_bread(fs, inode->i_block[EXT2_IND_BLOCK]);
-	udata = (__u32 *)bh->data;
+	if (!inode->i_block[EXT2_DIND_BLOCK]) {
+		unsigned long long	 inode_size;
+		blk_t			 dindblk;
 
-	/* Indirect blocks for next 256/512/1024 blocks (for 1k/2k/4k blocks) */
-	for (i = 0; i < fs->u32perblock; i++, curblock++) {
-		if (action == EXT2_ACTION_ADD && !udata[i]) {
-			size_t new_size = (curblock + 1) * fs->blocksize;
-
-			if (fs->flags & FL_DEBUG)
-				printf("add %d to ind block %d\n", curblock,
-				       inode->i_block[EXT2_IND_BLOCK]);
-			bh->dirty = 1;
-			udata[i] = block;
-			inode->i_blocks += i512perblock;
-			if (new_size > inode->i_size)
-				inode->i_size = new_size;
-			inode->i_mtime = time(NULL);
-			ext2_set_block_state(fs, block, 1,
-					     !(fs->flags & FL_ONLINE));
-			ext2_brelse(bh, 0);
-			return curblock;
-		}
-		if (udata[i] == block) {
-			if (action == EXT2_ACTION_DELETE) {
-				if (fs->flags & FL_DEBUG)
-					printf("del %d from ind block %d\n",
-					      curblock,
-					      inode->i_block[EXT2_IND_BLOCK]);
-				bh->dirty = 1;
-				udata[i] = 0;
-				inode->i_blocks -= i512perblock;
-				inode->i_mtime = time(NULL);
-				if (!(fs->flags & FL_ONLINE))
-					ext2_set_block_state(fs, block, 0, 1);
-			}
-			ext2_brelse(bh, 0);
-			return curblock;
-		}
-		if (udata[i]) {
-			count += i512perblock;
-			if (count >= inode->i_blocks &&
-			    action != EXT2_ACTION_ADD)
-				return -1;
-		}
+		dindblk = ext2_find_free_block(fs);
+		if(!dindblk)
+			return -1;
+		ext2_set_block_state(fs, dindblk, 1, 1);
+		inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS;
+		inode_size *= fs->blocksize;
+		inode->i_size = inode_size & 0xFFFFFFFF;
+		inode->i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
+		if(inode->i_size_high) {
+			fs->sb.s_feature_ro_compat |=
+			  EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+		}
+		inode->i_mtime = time(NULL);
+
+		inode->i_block[EXT2_DIND_BLOCK] = dindblk;
+		bh = ext2_bread(fs, inode->i_block[EXT2_DIND_BLOCK]);
+		memset(bh->data, 0, fs->blocksize);
+		inode->i_blocks += i512perblock;
 	}
+	else
+		bh = ext2_bread(fs, inode->i_block[EXT2_DIND_BLOCK]);
 
-	ext2_brelse(bh, 0);
-
-	if (!inode->i_block[EXT2_DIND_BLOCK] ||
-	    (count >= inode->i_blocks && action != EXT2_ACTION_ADD))
-		return -1;
-	bh = ext2_bread(fs, inode->i_block[EXT2_DIND_BLOCK]);
 	udata = (__u32 *)bh->data;
+	curblock = apb*apb + apb + EXT2_NDIR_BLOCKS;
 
 	/* Double indirect blocks for next 2^16/2^18/2^20 1k/2k/4k blocks */
 	for (i = 0; i < fs->u32perblock; i++) {
 		struct ext2_buffer_head	*bh2;
 		__u32			*udata2;
 		int			 j;
+		int			 grp, gdb_offset;
 
-		if (!udata[i]) {
+		gdb_offset = fs->sb.s_first_data_block + 1;
+		grp = block/fs->sb.s_blocks_per_group;
+		if(grp == 0 && action == EXT2_ACTION_ADD) {
+			udata[(block - gdb_offset)%fs->u32perblock] = block;
+			ext2_zero_blocks(fs, block, 1);
+			ext2_set_block_state(fs, block, 1, 1);
+			bh->dirty = 1;
+			inode->i_blocks += i512perblock;
+			inode->i_mtime = time(NULL);
 			ext2_brelse(bh, 0);
-			ext2_brelse(bh2, 0);
-			return -1;
+			return 1;
+		}
+		if (!udata[i])
+			continue;
+		if(udata[i] == block){
+			ext2_brelse(bh, 0);
+			return 1;
 		}
+		if(((block - gdb_offset)%fs->u32perblock) != i)
+			continue;
+
 		bh2 = ext2_bread(fs, udata[i]);
 		udata2 = (__u32 *)bh2->data;
 		count += i512perblock;
@@ -1044,3 +1000,51 @@
 error:
 	return NULL;
 }
+
+/* Update resize_inode's blocks */
+void ext2_fix_resize_inode(struct ext2_fs *fs) {
+	if (fs->sb.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) {
+	  int			 i;
+	  blk_t			 block;
+	  struct ext2_inode	*inode;
+
+	  ext2_read_inode(fs, EXT2_RESIZE_INO, &fs->resize);
+	  inode = &fs->resize;
+	  inode->i_mtime = 0;
+
+	  if (inode->i_block[EXT2_DIND_BLOCK]) {
+	  	ext2_zero_blocks(fs, inode->i_block[EXT2_DIND_BLOCK], 1);
+		inode->i_blocks = 1 << (fs->logsize - 9);
+	  }
+
+	  for (i = 0, block = fs->sb.s_first_data_block + fs->newgdblocks + 1;
+	       i < fs->newgroups; i++, block += fs->sb.s_blocks_per_group) {
+	  	int j;
+
+		if (!ext2_bg_has_super(fs, i))
+			continue;
+		for (j = 0; j < fs->resgdblocks; j++) {
+			if(i == 0)
+				ext2_zero_blocks(fs, block + j, 1);
+
+			if (j < fs->blocksize / 4){
+				if (ext2_get_block_state(fs, block + j))
+					ext2_set_block_state(fs, block + j, 0, 1);
+				ext2_block_iterate(fs, inode, block + j, EXT2_ACTION_ADD);
+			}
+			else{
+				if (ext2_get_block_state(fs, block + j))
+					ext2_set_block_state(fs, block + j, 0, 1);
+			}
+		}
+	  }
+
+	  fs->sb.s_reserved_gdt_blocks = fs->resgdblocks;
+	  if (fs->resgdblocks > fs->blocksize / 4)
+	  	fs->sb.s_reserved_gdt_blocks = fs->blocksize / 4;
+	  fs->metadirty |= EXT2_META_SB;
+
+	  if (inode->i_mtime)
+	  	ext2_write_inode(fs, EXT2_RESIZE_INO, inode);
+	}
+}
--- ext2resize-1.1.19.orig/src/ext2.h
+++ ext2resize-1.1.19/src/ext2.h
@@ -242,6 +242,8 @@
 struct ext2_dev_handle *ext2_make_dev_handle_from_file(char *dev, char *dir,
 						       char *prog);
 
+void ext2_fix_resize_inode(struct ext2_fs *fs);
+
 #define set_bit(buf, offset)	buf[(offset)>>3] |= _bitmap[(offset)&7]
 #define clear_bit(buf, offset)	buf[(offset)>>3] &= ~_bitmap[(offset)&7]
 #define check_bit(buf, offset)	(buf[(offset)>>3] & _bitmap[(offset)&7])
--- ext2resize-1.1.19.orig/src/ext2online.c
+++ ext2resize-1.1.19/src/ext2online.c
@@ -551,24 +551,7 @@
  */
 static void ext2_online_finish(struct ext2_fs *fs)
 {
-	int			 group;
-	blk_t			 block;
-	blk_t			 gdb;
-
-	/* Remove blocks as required from Bond inode */
-	for (group = 0, gdb = fs->sb.s_first_data_block + 1;
-	     group < fs->numgroups;
-	     group++, gdb += fs->sb.s_blocks_per_group)
-		if (ext2_bg_has_super(fs, group))
-			for (block = fs->gdblocks;
-			     block < fs->newgdblocks;
-			     block++) {
-				if (fs->flags & FL_DEBUG)
-					printf("Checking for group block %d "
-					       "in Bond\n", gdb);
-				ext2_block_iterate(fs, &fs->resize, gdb + block,
-						   EXT2_ACTION_DELETE);
-			}
+	ext2_fix_resize_inode(fs);
 
 	/* Save the new number of reserved GDT blocks in the resize inode */
 	fs->resize.i_generation = fs->resgdblocks + fs->gdblocks -
--- ext2resize-1.1.19.orig/src/ext2_resize.c
+++ ext2resize-1.1.19/src/ext2_resize.c
@@ -78,8 +78,9 @@
 					ext2_block_iterate(fs, inode,
 							   start+fs->gdblocks+1,
 							   EXT2_ACTION_DELETE);
-				ext2_set_block_state(fs, start +fs->gdblocks +1,
-						     1, 1);
+				if(group!=0 || !ext2_get_block_state(fs, start + fs->gdblocks + 1))
+					ext2_set_block_state(fs, start + fs->gdblocks + 1,
+							     1, 1);
 			}
 		}
 		if (inode->i_mtime)
@@ -480,6 +481,9 @@
 	else
 		status = ext2_grow_fs(fs);
 
+	if (status)
+		ext2_fix_resize_inode(fs);
+
 	free(fs->relocator_pool);
 	fs->relocator_pool = NULL;
 	fs->relocator_pool_end = NULL;
--- ext2resize-1.1.19.orig/src/ext2prepare.c
+++ ext2resize-1.1.19/src/ext2prepare.c
@@ -155,6 +155,7 @@
 	fs->sb.s_feature_compat |= EXT2_FEATURE_COMPAT_RESIZE_INODE;
 
 	diff = fs->newgdblocks - fs->gdblocks;
+	fs->resgdblocks = fs->sb.s_reserved_gdt_blocks = diff;
 	/* we store the number of reserved blocks in the inode version field */
 	inode->i_generation = diff;
 

Reply via email to