[RFC][17/21]ext2resize fix resize_inode format

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

Signed-off-by: Takashi Sato [email protected]
---
diff -Nurp old/ext2resize-1.1.19/src/ext2.c ext2resize-1.1.19/src/ext2.c
--- old/ext2resize-1.1.19/src/ext2.c	2004-09-30 22:01:40.000000000 +0800
+++ ext2resize-1.1.19/src/ext2.c	2006-03-20 21:45:13.000000000 +0800
@@ -286,6 +286,7 @@ void ext2_set_inode_state(struct ext2_fs
 	}
 }
 
+/* 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 ext2_block_iterate(struct ext2_fs *f
 	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 @@ int ext2_block_iterate(struct ext2_fs *f
 		}
 	}
 
-	/* 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_free_fs:
 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);
+	}
+}
diff -Nurp old/ext2resize-1.1.19/src/ext2.h ext2resize-1.1.19/src/ext2.h
--- old/ext2resize-1.1.19/src/ext2.h	2002-12-11 08:05:12.000000000 +0800
+++ ext2resize-1.1.19/src/ext2.h	2006-03-20 21:45:13.000000000 +0800
@@ -242,6 +242,8 @@ loff_t ext2_llseek(unsigned int fd, loff
 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])
diff -Nurp old/ext2resize-1.1.19/src/ext2online.c ext2resize-1.1.19/src/ext2online.c
--- old/ext2resize-1.1.19/src/ext2online.c	2004-09-30 22:12:01.000000000 +0800
+++ ext2resize-1.1.19/src/ext2online.c	2006-03-20 21:45:13.000000000 +0800
@@ -551,24 +551,7 @@ static blk_t ext2_online_primary(struct 
  */
 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 -
diff -Nurp old/ext2resize-1.1.19/src/ext2prepare.c ext2resize-1.1.19/src/ext2prepare.c
--- old/ext2resize-1.1.19/src/ext2prepare.c	2004-09-30 22:04:05.000000000 +0800
+++ ext2resize-1.1.19/src/ext2prepare.c	2006-03-20 21:45:13.000000000 +0800
@@ -155,6 +155,7 @@ int create_resize_inode(struct ext2_fs *
 	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;
 
diff -Nurp old/ext2resize-1.1.19/src/ext2_resize.c ext2resize-1.1.19/src/ext2_resize.c
--- old/ext2resize-1.1.19/src/ext2_resize.c	2004-09-30 22:01:41.000000000 +0800
+++ ext2resize-1.1.19/src/ext2_resize.c	2006-03-20 21:45:13.000000000 +0800
@@ -78,7 +78,8 @@ static int ext2_add_group(struct ext2_fs
 					ext2_block_iterate(fs, inode,
 							   start+fs->gdblocks+1,
 							   EXT2_ACTION_DELETE);
-				ext2_set_block_state(fs, start +fs->gdblocks +1,
+				if(group!=0 || !ext2_get_block_state(fs, start + fs->gdblocks + 1))
+					ext2_set_block_state(fs, start + fs->gdblocks + 1,
 						     1, 1);
 			}
 		}
@@ -480,6 +481,9 @@ int ext2_resize_fs(struct ext2_fs *fs)
 	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;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux