diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index d41b230..b214f72 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -735,6 +735,108 @@ static void finish_processing_inode(e2fsck_t ctx, ext2_ino_t ino,
 			return; \
 	} while (0)
 
+static int could_be_block_map(ext2_filsys fs, struct ext2_inode *inode)
+{
+	__u32 x;
+	int i;
+
+	for (i = 0; i < EXT2_N_BLOCKS; i++) {
+		x = inode->i_block[i];
+#ifdef WORDS_BIGENDIAN
+		x = ext2fs_swab32(x);
+#endif
+		if (x >= ext2fs_blocks_count(fs->super))
+			return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * Figure out what to do with an inode that has both extents and inline data
+ * inode flags set.  Returns -1 if we decide to erase the inode, 0 otherwise.
+ */
+static int fix_inline_data_extents_file(e2fsck_t ctx,
+					ext2_ino_t ino,
+					struct ext2_inode *inode,
+					int inode_size,
+					struct problem_context *pctx)
+{
+	size_t max_inline_ea_size;
+	ext2_filsys fs = ctx->fs;
+	int dirty = 0;
+
+	/* Both feature flags not set?  Just run the regular checks */
+	if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+				       EXT3_FEATURE_INCOMPAT_EXTENTS) &&
+	    !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+				       EXT4_FEATURE_INCOMPAT_INLINE_DATA))
+		return 0;
+
+	/* Clear both flags if it's a special file */
+	if (LINUX_S_ISCHR(inode->i_mode) ||
+	    LINUX_S_ISBLK(inode->i_mode) ||
+	    LINUX_S_ISFIFO(inode->i_mode) ||
+	    LINUX_S_ISSOCK(inode->i_mode)) {
+		check_extents_inlinedata(ctx, pctx);
+		return 0;
+	}
+
+	/* If it looks like an extent tree, try to clear inlinedata */
+	if (ext2fs_extent_header_verify(inode->i_block,
+				 sizeof(inode->i_block)) == 0 &&
+	    fix_problem(ctx, PR_1_CLEAR_INLINE_DATA_FOR_EXTENT, pctx)) {
+		inode->i_flags &= ~EXT4_INLINE_DATA_FL;
+		dirty = 1;
+		goto out;
+	}
+
+	/* If it looks short enough to be inline data, try to clear extents */
+	if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE)
+		max_inline_ea_size = EXT2_INODE_SIZE(fs->super) -
+				     (EXT2_GOOD_OLD_INODE_SIZE +
+				      ((struct ext2_inode_large *)inode)->i_extra_isize);
+	else
+		max_inline_ea_size = 0;
+	if (EXT2_I_SIZE(inode) <
+	    EXT4_MIN_INLINE_DATA_SIZE + max_inline_ea_size &&
+	    fix_problem(ctx, PR_1_CLEAR_EXTENT_FOR_INLINE_DATA, pctx)) {
+		inode->i_flags &= ~EXT4_EXTENTS_FL;
+		dirty = 1;
+		goto out;
+	}
+
+	/*
+	 * Too big for inline data, but no evidence of extent tree -
+	 * maybe it's a block map file?  If the mappings all look valid?
+	 */
+	if (could_be_block_map(fs, inode) &&
+	    fix_problem(ctx, PR_1_CLEAR_EXTENT_INLINE_DATA_FLAGS, pctx)) {
+		int i;
+
+#ifdef WORDS_BIGENDIAN
+		for (i = 0; i < EXT2_N_BLOCKS; i++)
+			inode->i_block[i] = ext2fs_swab32(inode->i_block[i]);
+#endif
+
+		inode->i_flags &= ~(EXT4_EXTENTS_FL | EXT4_INLINE_DATA_FL);
+		dirty = 1;
+		goto out;
+	}
+
+	/* Oh well, just clear the busted inode. */
+	if (fix_problem(ctx, PR_1_CLEAR_EXTENT_INLINE_DATA_INODE, pctx)) {
+		e2fsck_clear_inode(ctx, ino, inode, 0, "pass1");
+		return -1;
+	}
+
+out:
+	if (dirty)
+		e2fsck_write_inode(ctx, ino, inode, "pass1");
+
+	return 0;
+}
+
 void e2fsck_pass1(e2fsck_t ctx)
 {
 	int	i;
@@ -983,6 +1085,18 @@ void e2fsck_pass1(e2fsck_t ctx)
 			}
 		}
 
+		/* Conflicting inlinedata/extents inode flags? */
+		if ((inode->i_flags & EXT4_INLINE_DATA_FL) &&
+		    (inode->i_flags & EXT4_EXTENTS_FL)) {
+			int res = fix_inline_data_extents_file(ctx, ino, inode,
+							       inode_size,
+							       &pctx);
+			if (res < 0) {
+				/* skip FINISH_INODE_LOOP */
+				continue;
+			}
+		}
+
 		/* Test for incorrect inline_data flags settings. */
 		if ((inode->i_flags & EXT4_INLINE_DATA_FL) && !inlinedata_fs &&
 		    (ino >= EXT2_FIRST_INODE(fs->super))) {
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 26ee51b..4245244 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1056,6 +1056,26 @@ static struct e2fsck_problem problem_table[] = {
 	     "or inline-data flag set.  "),
 	  PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
 
+	/* Inode has extent header but inline data flag is set */
+	{ PR_1_CLEAR_INLINE_DATA_FOR_EXTENT,
+	  N_("@i %i has @x header but inline data flag is set.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Inode seems to have inline data but extent flag is set */
+	{ PR_1_CLEAR_EXTENT_FOR_INLINE_DATA,
+	  N_("@i %i seems to have inline data but @x flag is set.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Inode seems to have block map but inline data and extent flags set */
+	{ PR_1_CLEAR_EXTENT_INLINE_DATA_FLAGS,
+	  N_("@i %i seems to have @b map but inline data and @x flags set.\n"),
+	  PROMPT_FIX, 0 },
+
+	/* Inode has inline data and extent flags but i_block contains junk */
+	{ PR_1_CLEAR_EXTENT_INLINE_DATA_INODE,
+	  N_("@i %i has inline data and @x flags set but i_block contains junk.\n"),
+	  PROMPT_CLEAR_INODE, 0 },
+
 	/* Pass 1b errors */
 
 	/* Pass 1B: Rescan for duplicate/bad blocks */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 3c5e11a..22c86c5 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -615,6 +615,18 @@ struct problem_context {
 /* extents/inlinedata set on fifo/socket/device */
 #define PR_1_SPECIAL_EXTENTS_IDATA	0x010076
 
+/* idata/extent flag set and extent header found, clear idata flag */
+#define PR_1_CLEAR_INLINE_DATA_FOR_EXTENT	0x010077
+
+/* inlinedata/extent set and no extent header found, clear extent flag */
+#define PR_1_CLEAR_EXTENT_FOR_INLINE_DATA	0x010078
+
+/* inlinedata/extent set, clear both flags */
+#define PR_1_CLEAR_EXTENT_INLINE_DATA_FLAGS	0x010079
+
+/* inlinedata/extent set, clear inode */
+#define PR_1_CLEAR_EXTENT_INLINE_DATA_INODE	0x01007A
+
 /*
  * Pass 1b errors
  */
diff --git a/tests/f_idata_and_extents/expect.1 b/tests/f_idata_and_extents/expect.1
new file mode 100644
index 0000000..7f7fbf3
--- /dev/null
+++ b/tests/f_idata_and_extents/expect.1
@@ -0,0 +1,35 @@
+Pass 1: Checking inodes, blocks, and sizes
+Special (device/socket/fifo) file (inode 19) has extents
+or inline-data flag set.  Clear? yes
+
+Inode 20 has extent header but inline data flag is set.
+Fix? yes
+
+Inode 21 has inline data and extent flags set but i_block contains junk.
+Clear inode? yes
+
+Inode 22 seems to have block map but inline data and extent flags set.
+Fix? yes
+
+Inode 23 seems to have inline data but extent flag is set.
+Fix? yes
+
+Pass 2: Checking directory structure
+Entry 'garbage' in /bad (18) has deleted/unused inode 21.  Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Inode bitmap differences:  -21
+Fix? yes
+
+Free inodes count wrong for group #0 (105, counted=106).
+Fix? yes
+
+Free inodes count wrong (105, counted=106).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 22/128 files (0.0% non-contiguous), 21/512 blocks
+Exit status is 1
diff --git a/tests/f_idata_and_extents/expect.2 b/tests/f_idata_and_extents/expect.2
new file mode 100644
index 0000000..307d3f6
--- /dev/null
+++ b/tests/f_idata_and_extents/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 22/128 files (0.0% non-contiguous), 21/512 blocks
+Exit status is 0
diff --git a/tests/f_idata_and_extents/image.gz b/tests/f_idata_and_extents/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..5187ba14138568a1ccd3540228b092f93186d109
GIT binary patch
diff --git a/tests/f_idata_and_extents/name b/tests/f_idata_and_extents/name
new file mode 100644
index 0000000..362ce0e
--- /dev/null
+++ b/tests/f_idata_and_extents/name
@@ -0,0 +1 @@
+conflicting extents and inline_data inode flags
