diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct
index 1ff6c9dcd6b5..4ed613627258 100644
--- a/debugfs/debug_cmds.ct
+++ b/debugfs/debug_cmds.ct
@@ -49,6 +49,12 @@ request do_stat, "Show inode information ",
 request do_dump_extents, "Dump extents information ",
 	dump_extents, extents, ex;
 
+request do_dump_extent_header, "Dump extent header information",
+	dump_extent_header, deh;
+
+request do_set_extent_header_field, "Sets an extent header field",
+	set_extent_header_field, seh;
+
 request do_blocks, "Dump blocks used by an inode ",
 	blocks;
 
diff --git a/debugfs/debugfs.8.in b/debugfs/debugfs.8.in
index a3227a80ab24..f50fd6d9e987 100644
--- a/debugfs/debugfs.8.in
+++ b/debugfs/debugfs.8.in
@@ -298,6 +298,13 @@ not stored in file system data structures.   Hence, the values displayed
 may not necessarily by accurate and does not indicate a problem or
 corruption in the file system.)
 .TP
+.BI dump_extent_header " block"
+Dump the contents of the extent header at the beginning of block
+.IR block .
+A warning will be emitted if the block doesn't start with a valid extent
+header (for example, if the extent header doesn't start with the '0xf30a'
+magic value).
+.TP
 .B dump_unused
 Dump unused blocks which contain non-null bytes.
 .TP
@@ -739,6 +746,23 @@ can be displayed by using the command:
 Also available as
 .BR ssv .
 .TP
+.BI set_extent_header_field " -l | block field value"
+Change the value of
+.IR field
+to
+.IR value
+in the extent header at the beginning of
+.IR block.
+If
+.IR block
+doesn't start with a valid extent header, a warning will be emitted and field
+isn't changed.  To force the change, the
+.IR -f
+flag can be used.
+The fields that may be changed with this command can be listed by using the
+.IR -l
+flag.
+.TP
 .B show_debugfs_params
 Display
 .B debugfs
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 78b93eda7b61..f9fb0dc9b347 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -1079,6 +1079,56 @@ void do_dump_extents(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)),
 	return;
 }
 
+void do_dump_extent_header(int argc, char **argv,
+			   int sci_idx EXT2FS_ATTR((unused)),
+			   void *infop EXT2FS_ATTR((unused)))
+{
+	struct ext3_extent_header *eh;
+	errcode_t	errcode;
+	blk64_t		block;
+	unsigned char	*buf;
+	int		err;
+
+	if (check_fs_open(argv[0]))
+		return;
+
+	if (common_args_process(argc, argv, 2, 2, argv[0], "<block>",
+				CHECK_FS_BITMAPS)) {
+		return;
+	}
+	err = strtoblk(argv[0], argv[1], "physical block", &block);
+	if (err)
+		return;
+
+	buf = malloc(current_fs->blocksize);
+	if (!buf) {
+		com_err(argv[0], 0, "Couldn't allocate block buffer");
+		return;
+	}
+
+	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
+	if (errcode) {
+		com_err(argv[0], errcode, "while reading block %llu\n",
+			(unsigned long long) block);
+		goto errout;
+	}
+
+	eh = (struct ext3_extent_header *)buf;
+	if (ext2fs_extent_header_verify(eh, current_fs->blocksize))
+		fprintf(stdout, "Warning: block %llu doesn't seem to contain a "
+			"valid extent header\n", block);
+	fprintf(stdout,
+		"header: magic=%x entries=%u max=%u depth=%u generation=%u\n",
+		ext2fs_le16_to_cpu(eh->eh_magic),
+		ext2fs_le16_to_cpu(eh->eh_entries),
+		ext2fs_le16_to_cpu(eh->eh_max),
+		ext2fs_le16_to_cpu(eh->eh_depth),
+		ext2fs_le32_to_cpu(eh->eh_generation));
+
+errout:
+	free(buf);
+}
+
 static int print_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)),
 			     blk64_t *blocknr,
 			     e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h
index 39bc0247f527..f1797c660f55 100644
--- a/debugfs/debugfs.h
+++ b/debugfs/debugfs.h
@@ -144,6 +144,8 @@ extern void do_find_free_block(int argc, char **argv, int sci_idx, void *infop);
 extern void do_find_free_inode(int argc, char **argv, int sci_idx, void *infop);
 extern void do_stat(int argc, char **argv, int sci_idx, void *infop);
 extern void do_dump_extents(int argc, char **argv, int sci_idx, void *infop);
+extern void do_dump_extent_header(int argc, char **argv, int sci_idx, void *infop);
+extern void do_set_extent_header_field(int argc, char **argv, int sci_idx, void *infop);
 extern void do_blocks(int argc, char *argv[], int sci_idx, void *infop);
 
 extern void do_chroot(int argc, char **argv, int sci_idx, void *infop);
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
index f916deab8cea..3f74331ae85c 100644
--- a/debugfs/set_fields.c
+++ b/debugfs/set_fields.c
@@ -47,6 +47,7 @@ static struct ext2_inode_large set_inode;
 static struct ext2_group_desc set_gd;
 static struct ext4_group_desc set_gd4;
 static struct mmp_struct set_mmp;
+static struct ext3_extent_header set_eh;
 static dgrp_t set_bg;
 static ext2_ino_t set_ino;
 static int array_idx;
@@ -297,6 +298,16 @@ static struct field_set_info mmp_fields[] = {
 	{ "checksum", &set_mmp.mmp_checksum, NULL, 4, parse_uint },
 	{ 0, 0, 0, 0 }
 };
+
+static struct field_set_info extent_header_fields[] = {
+	{"magic", &set_eh.eh_magic, NULL, 2, parse_uint },
+	{"entries", &set_eh.eh_entries, NULL, 2, parse_uint },
+	{"max", &set_eh.eh_max, NULL, 2, parse_uint },
+	{"depth", &set_eh.eh_depth, NULL, 2, parse_uint },
+	{"generation", &set_eh.eh_generation, NULL, 4, parse_uint },
+	{0, 0, 0, 0 }
+};
+
 #if __GNUC_PREREQ (4, 6)
 #pragma GCC diagnostic pop
 #endif
@@ -1022,3 +1033,86 @@ void do_set_mmp_value(int argc EXT2FS_ATTR((unused)),
 }
 #endif
 
+void do_set_extent_header_field(int argc, char **argv,
+				int sci_idx EXT2FS_ATTR((unused)),
+				void *infop EXT2FS_ATTR((unused)))
+{
+	struct ext3_extent_header *eh;
+	struct field_set_info	*ss;
+	const char		*usage = "-l | <block> <field> <value>";
+	errcode_t		errcode;
+	blk64_t			block;
+	unsigned char		*buf;
+	int			c, err, force = 0;
+
+	if (check_fs_open(argv[0]) || check_fs_read_write(argv[0]) ||
+	    check_fs_bitmaps(argv[0]))
+		return;
+
+	reset_getopt();
+	while ((c = getopt(argc, argv, "lf")) != EOF) {
+		switch (c) {
+		case 'l':
+			print_possible_fields(extent_header_fields);
+			return;
+			break;
+		case 'f':
+			force = 1;
+			break;
+		default:
+			com_err(argv[0], 0, usage);
+			return;
+		}
+	}
+	if (argc != optind + 3) {
+		com_err(argv[0], 0, usage);
+		return;
+	}
+
+	err = strtoblk(argv[0], argv[optind++], "physical block", &block);
+	if (err)
+		return;
+
+	ss = find_field(extent_header_fields, argv[optind]);
+	if (ss == 0) {
+		com_err(argv[0], 0, "invalid field specifier: %s",
+			argv[optind]);
+		return;
+	}
+
+	buf = malloc(current_fs->blocksize);
+	if (!buf) {
+		com_err(argv[0], 0, "Couldn't allocate block buffer");
+		return;
+	}
+
+	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
+	if (errcode) {
+		com_err(argv[0], errcode, "while reading block %llu\n",
+			(unsigned long long) block);
+		goto errout;
+	}
+
+	eh = (struct ext3_extent_header *)buf;
+	if (ext2fs_extent_header_verify(eh, current_fs->blocksize)) {
+		fprintf(stdout, "Warning: block %llu doesn't seem to contain a "
+			"valid extent header.  ", block);
+		if (!force) {
+			fprintf(stdout, "Use '-f' to force\n");
+			goto errout;
+		} else
+			fprintf(stdout, "Forcing write.\n");
+	}
+	memcpy(&set_eh, eh, sizeof(set_eh));
+	if (ss->func(ss, argv[optind], argv[optind + 1]) == 0) {
+		memcpy(eh, &set_eh, sizeof(set_eh));
+		errcode = io_channel_write_blk(current_fs->io, block, 1, buf);
+		if (errcode) {
+			com_err(argv[0], errcode, "while writing block %llu\n",
+				(unsigned long long) block);
+		}
+	}
+
+errout:
+	free(buf);
+}
