debugfs: teach seti and freei to free a block of inodes

In order to the inode allocation functions, it's useful to set and
clear a range of inodes.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/debugfs/debugfs.8.in b/debugfs/debugfs.8.in
index 08d9068..ea3375e 100644
--- a/debugfs/debugfs.8.in
+++ b/debugfs/debugfs.8.in
@@ -311,9 +311,12 @@
 can be found in the file system.  The chunk size must be a power of two
 and be larger than the file system block size.
 .TP
-.I freei filespec
+.I freei filespec [num]
 Free the inode specified by 
 .IR filespec .
+If
+.I num
+is specified, also clear num-1 inodes after the specified inode.
 .TP
 .I help
 Print a list of commands understood by 
@@ -506,10 +509,12 @@
 has value
 .I value.
 .TP
-.I seti filespec
+.I seti filespec [num]
 Mark inode 
 .I filespec
-as in use in the inode bitmap.
+as in use in the inode bitmap.  If
+.I num
+is specified, also set num-1 inodes after the specified inode.
 .TP
 .I set_inode_field filespec field value
 Modify the inode specified by 
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 574759b..e82dddb 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -994,29 +994,61 @@
 
 void do_freei(int argc, char *argv[])
 {
-	ext2_ino_t inode;
+	unsigned int	len = 1;
+	int		err = 0;
+	ext2_ino_t	inode;
 
-	if (common_inode_args_process(argc, argv, &inode,
-				      CHECK_FS_RW | CHECK_FS_BITMAPS))
+	if (common_args_process(argc, argv, 2, 3, argv[0], "<file> [num]",
+				CHECK_FS_RW | CHECK_FS_BITMAPS))
+		return 1;
+	if (check_fs_read_write(argv[0]))
 		return;
 
-	if (!ext2fs_test_inode_bitmap2(current_fs->inode_map,inode))
+	inode = string_to_inode(argv[1]);
+	if (!inode)
+		return;
+
+	if (argc == 3) {
+		len = parse_ulong(argv[2], argv[0], "length", &err);
+		if (err)
+			return;
+	}
+
+	if (len == 1 &&
+	    !ext2fs_test_inode_bitmap2(current_fs->inode_map,inode))
 		com_err(argv[0], 0, "Warning: inode already clear");
-	ext2fs_unmark_inode_bitmap2(current_fs->inode_map,inode);
+	while (len-- > 0)
+		ext2fs_unmark_inode_bitmap2(current_fs->inode_map, inode);
 	ext2fs_mark_ib_dirty(current_fs);
 }
 
 void do_seti(int argc, char *argv[])
 {
-	ext2_ino_t inode;
+	unsigned int	len = 1;
+	int		err = 0;
+	ext2_ino_t	inode;
 
-	if (common_inode_args_process(argc, argv, &inode,
-				      CHECK_FS_RW | CHECK_FS_BITMAPS))
+	if (common_args_process(argc, argv, 2, 3, argv[0], "<file> [num]",
+				CHECK_FS_RW | CHECK_FS_BITMAPS))
+		return;
+	if (check_fs_read_write(argv[0]))
 		return;
 
-	if (ext2fs_test_inode_bitmap2(current_fs->inode_map,inode))
+	inode = string_to_inode(argv[1]);
+	if (!inode)
+		return;
+
+	if (argc == 3) {
+		len = parse_ulong(argv[2], argv[0], "length", &err);
+		if (err)
+			return;
+	}
+
+	if ((len == 1) &&
+	    ext2fs_test_inode_bitmap2(current_fs->inode_map,inode))
 		com_err(argv[0], 0, "Warning: inode already set");
-	ext2fs_mark_inode_bitmap2(current_fs->inode_map,inode);
+	while (len-- > 0)
+		ext2fs_mark_inode_bitmap2(current_fs->inode_map, inode++);
 	ext2fs_mark_ib_dirty(current_fs);
 }
 #endif /* READ_ONLY */