Skip to contentSkip to conversation

FAILED: patch "[PATCH] ext4: fix data exposure after a crash" failed to apply to 3.14-stable tree

PATCH In review [email protected] 6 participants 12 messages Jun 4, 2016 – Oct 19, 2017

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 3.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

Quoted 1 line

From 06bd3c36a733ac27962fea7d6f47168841376824 Mon Sep 17 00:00:00 2001

From: Jan Kara <[email protected]>
Date: Sun, 24 Apr 2016 00:56:03 -0400
Subject: [PATCH] ext4: fix data exposure after a crash

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed.

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

The only exception to the above rule are extending direct IO writes where blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

fs/ext4/inode.c +15 -9
index 981a1fc30eaa..250c2df04a92 100644
@@ -684,6 +684,21 @@ out_sem:
 		ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !(flags & EXT4_GET_BLOCKS_ZERO) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1289,15 +1304,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);
-		if (ret) {
-			unlock_page(page);
-			put_page(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);
#1 lore raw

Hi backports team,

Could you please apply the below patch to the 3.14-stable tree ?

Thanks.
Best regards

Weller HUANG

Quoted 89 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: Sunday, June 05, 2016 5:47 AM
To: [email protected]; HUANG Weller (CM/ESW12-CN) <[email protected]>; [email protected]
Cc: [email protected]
Subject: FAILED: patch "[PATCH] ext4: fix data exposure after a crash" failed to apply to 3.14-stable tree

The patch below does not apply to the 3.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 06bd3c36a733ac27962fea7d6f47168841376824 Mon Sep 17 00:00:00 2001
From: Jan Kara <[email protected]>
Date: Sun, 24 Apr 2016 00:56:03 -0400
Subject: [PATCH] ext4: fix data exposure after a crash

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts
ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed.

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

The only exception to the above rule are extending direct IO writes where blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

fs/ext4/inode.c index 981a1fc30eaa..250c2df04a92 renamed from fs/ext4/inode.c +0 -0

100644

fs/ext4/inode.c +15 -2
@@ -684,6 +684,21 @@ out_sem:
 		ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !(flags & EXT4_GET_BLOCKS_ZERO) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1289,15 +1304,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);

fs/ext4/inode.c static int ext4_write_end(struct file *file, · line 1309

Quoted 10 lines
fs/ext4/inode.c +0 -7
-		if (ret) {
-			unlock_page(page);
-			put_page(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);

--
To unsubscribe from this list: send the line "unsubscribe backports" in

#2 lore raw
Quoted 3 lines · On 06-06-16 02:02, HUANG Weller (CM/ESW12-CN) wrote:

Hi backports team,

Could you please apply the below patch to the 3.14-stable tree ?

Hi Huang,

I suspect you are talking to the wrong crowd. Backports is a project to generate a source package of latest kernel code which can be compiled against older target kernels.

What is meant in Greg's (automated) response is that the patch should be backported manually so it applies to 3.14-stable tree. This is something Jan Kara should take care of if he cares about getting this patch in 3.14-stable.

Regards,
Arend

Quoted 93 lines

Thanks.
Best regards

Weller HUANG

Quoted 86 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: Sunday, June 05, 2016 5:47 AM
To: [email protected]; HUANG Weller (CM/ESW12-CN) <[email protected]>; [email protected]
Cc: [email protected]
Subject: FAILED: patch "[PATCH] ext4: fix data exposure after a crash" failed to apply to 3.14-stable tree

The patch below does not apply to the 3.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 06bd3c36a733ac27962fea7d6f47168841376824 Mon Sep 17 00:00:00 2001
From: Jan Kara <[email protected]>
Date: Sun, 24 Apr 2016 00:56:03 -0400
Subject: [PATCH] ext4: fix data exposure after a crash

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts
ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed.

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

The only exception to the above rule are extending direct IO writes where blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

fs/ext4/inode.c index 981a1fc30eaa..250c2df04a92 renamed from fs/ext4/inode.c +0 -0

100644

fs/ext4/inode.c +15 -0
@@ -684,6 +684,21 @@ out_sem:
 		ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !(flags & EXT4_GET_BLOCKS_ZERO) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1289,15 +1304,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
Quoted 17 lines

fs/ext4/inode.c static int ext4_write_end(struct file *file, · line 1309

Quoted 13 lines
fs/ext4/inode.c +0 -9
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);
-		if (ret) {
-			unlock_page(page);
-			put_page(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);

--
To unsubscribe from this list: send the line "unsubscribe backports" in

--
To unsubscribe from this list: send the line "unsubscribe backports" in

#3 lore raw

Hi Arend,

I am sorry for this misunderstanding.
Yes, I remember Jan Kara told me before.

Best regards

Weller HUANG

Quoted 82 lines

-----Original Message-----
From: Arend van Spriel [mailto:[email protected]]
Sent: Monday, June 06, 2016 1:17 PM
To: HUANG Weller (CM/ESW12-CN) <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]
Cc: [email protected]; Behme Dirk (CM/ESO2) <[email protected]>; Juergens Dirk (CM/ESO2) <[email protected]>
Subject: Re: FAILED: patch "[PATCH] ext4: fix data exposure after a crash" failed to apply to 3.14-stable tree

Quoted 3 lines · On 06-06-16 02:02, HUANG Weller (CM/ESW12-CN) wrote:

Hi backports team,

Could you please apply the below patch to the 3.14-stable tree ?

Hi Huang,

I suspect you are talking to the wrong crowd. Backports is a project to generate a source package of latest kernel code which can be compiled against older target kernels.

What is meant in Greg's (automated) response is that the patch should be backported manually so it applies to 3.14-stable tree. This is something Jan Kara should take care of if he cares about getting this patch in 3.14-stable.

Regards,
Arend

Quoted 41 lines

Thanks.
Best regards

Weller HUANG

Quoted 34 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]]
Sent: Sunday, June 05, 2016 5:47 AM
To: [email protected]; HUANG Weller (CM/ESW12-CN) <[email protected]>; [email protected]
Cc: [email protected]
Subject: FAILED: patch "[PATCH] ext4: fix data exposure after a crash" failed to apply to 3.14-stable tree

The patch below does not apply to the 3.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 06bd3c36a733ac27962fea7d6f47168841376824 Mon Sep 17 00:00:00 2001
From: Jan Kara <[email protected]>
Date: Sun, 24 Apr 2016 00:56:03 -0400
Subject: [PATCH] ext4: fix data exposure after a crash

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts
ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with

a flawed argument that it is not needed.

Quoted 10 lines
Quoted 10 lines

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other

Quoted 66 lines

cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

Quoted 64 lines
Quoted 49 lines

The only exception to the above rule are extending direct IO writes where
blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

fs/ext4/inode.c index renamed from fs/ext4/inode.c +0 -0

981a1fc30eaa..250c2df04a92
100644

fs/ext4/inode.c +15 -2
@@ -684,6 +684,21 @@ out_sem:
 		ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !(flags & EXT4_GET_BLOCKS_ZERO) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1289,15 +1304,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);

fs/ext4/inode.c static int ext4_write_end(struct file *file, · line 1309

Quoted 10 lines
fs/ext4/inode.c +0 -7
-		if (ret) {
-			unlock_page(page);
-			put_page(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);

--
To unsubscribe from this list: send the line "unsubscribe backports" in

--
To unsubscribe from this list: send the line "unsubscribe backports" in

#4 lore raw

PATCH 1/1 ext4: fix data exposure after a crash

In reply to [email protected]

From: Jan Kara <[email protected]>

From: Jan Kara <[email protected]>

commit 06bd3c36a733ac27962fea7d6f47168841376824 upstream

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed.

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

The only exception to the above rule are extending direct IO writes where blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

Fixes f3b59291a69d0b734be1fc8be489fef2dd846d3d
[weller: fix conflict with 3.14 kernel]

---
gdavis: Confirmed that backport conflicts are due to lack of upstream
commits c86d8db ("ext4: implement allocation of pre-zeroed blocks") and 09cbfea ("mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros") in v3.14.37. The conflict resolution therefore appears to be correct.

---
 fs/ext4/inode.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)
fs/ext4/inode.c +14 -9
index 58001fc..d33a80e 100644
@@ -695,6 +695,20 @@ has_zeroout:
 		int ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1059,15 +1073,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);
-		if (ret) {
-			unlock_page(page);
-			page_cache_release(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);
Signature · 1 line
1.9.3
reviewer
#5 lore raw

Re: [PATCH 3.14] ext4: fix data exposure after a crash

The backport looks good to me.

Honza

Quoted 95 lines · George G. Davis

From: Jan Kara <[email protected]>

From: Jan Kara <[email protected]>

commit 06bd3c36a733ac27962fea7d6f47168841376824 upstream

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed.

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

The only exception to the above rule are extending direct IO writes where blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

Fixes f3b59291a69d0b734be1fc8be489fef2dd846d3d
[weller: fix conflict with 3.14 kernel]

---
gdavis: Confirmed that backport conflicts are due to lack of upstream
commits c86d8db ("ext4: implement allocation of pre-zeroed blocks") and 09cbfea ("mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros") in v3.14.37. The conflict resolution therefore appears to be correct.

---
 fs/ext4/inode.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)
fs/ext4/inode.c +14 -9
index 58001fc..d33a80e 100644
@@ -695,6 +695,20 @@ has_zeroout:
 		int ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1059,15 +1073,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);
-		if (ret) {
-			unlock_page(page);
-			page_cache_release(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);
Signature · 1 line
1.9.3
Signature · 2 lines
Jan Kara <[email protected]>
SUSE Labs, CR
#6 lore raw

RE: [PATCH 3.14] ext4: fix data exposure after a crash

Hello Mr. Davis and Mr. Kara,

I checked the latest 3.14 source code 3.14.79. I didn't found the below patch.

It should be there , right ?

Quoted 114 lines

-----Original Message-----
From: Jan Kara [mailto:[email protected]]
Sent: Wednesday, June 29, 2016 3:46 PM
To: George G. Davis <[email protected]>
Cc: [email protected]; Greg KH <[email protected]>; Behme Dirk (CM/ESO2) <[email protected]>; Jan Kara <[email protected]>; Theodore Ts'o <[email protected]>; HUANG Weller (CM/ESW12-CN) <[email protected]>
Subject: Re: [PATCH 3.14] ext4: fix data exposure after a crash

The backport looks good to me.

Honza

Quoted 94 lines · George G. Davis

From: Jan Kara <[email protected]>

From: Jan Kara <[email protected]>

commit 06bd3c36a733ac27962fea7d6f47168841376824 upstream

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed.

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

The only exception to the above rule are extending direct IO writes where
blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

Fixes f3b59291a69d0b734be1fc8be489fef2dd846d3d
[weller: fix conflict with 3.14 kernel]

---
gdavis: Confirmed that backport conflicts are due to lack of upstream
commits c86d8db ("ext4: implement allocation of pre-zeroed blocks") and 09cbfea ("mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros") in v3.14.37. The conflict resolution therefore appears to be correct.

---
 fs/ext4/inode.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)
fs/ext4/inode.c index 58001fc..d33a80e renamed from fs/ext4/inode.c +0 -0

100644

fs/ext4/inode.c +14 -10
@@ -695,6 +695,20 @@ has_zeroout:
 		int ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1059,15 +1073,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);
-		if (ret) {
-			unlock_page(page);
-			page_cache_release(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);
--
Quoted 2 lines

1.9.3

--
Jan Kara <[email protected]>
SUSE Labs, CR

reviewer
#7 lore raw

Re: [PATCH 3.14] ext4: fix data exposure after a crash

Quoted 5 lines · On Fri 06-10-17 10:04:41, HUANG Weller (CM/ESW12-CN) wrote:

Hello Mr. Davis and Mr. Kara,

I checked the latest 3.14 source code 3.14.79. I didn't found the below patch.

It should be there , right ?

Well, I'm not sure who runs the 3.14 stable tree (it's not listed at kernel.org). It's up to him to pick up patches...

Honza

Quoted 114 lines
Quoted 114 lines

-----Original Message-----
From: Jan Kara [mailto:[email protected]]
Sent: Wednesday, June 29, 2016 3:46 PM
To: George G. Davis <[email protected]>
Cc: [email protected]; Greg KH <[email protected]>; Behme Dirk (CM/ESO2) <[email protected]>; Jan Kara <[email protected]>; Theodore Ts'o <[email protected]>; HUANG Weller (CM/ESW12-CN) <[email protected]>
Subject: Re: [PATCH 3.14] ext4: fix data exposure after a crash

The backport looks good to me.

Honza

Quoted 94 lines · George G. Davis

From: Jan Kara <[email protected]>

From: Jan Kara <[email protected]>

commit 06bd3c36a733ac27962fea7d6f47168841376824 upstream

Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed.

The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode.

The only exception to the above rule are extending direct IO writes where
blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks().

Fixes f3b59291a69d0b734be1fc8be489fef2dd846d3d
[weller: fix conflict with 3.14 kernel]

---
gdavis: Confirmed that backport conflicts are due to lack of upstream
commits c86d8db ("ext4: implement allocation of pre-zeroed blocks") and 09cbfea ("mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release} macros") in v3.14.37. The conflict resolution therefore appears to be correct.

---
 fs/ext4/inode.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)
fs/ext4/inode.c index 58001fc..d33a80e renamed from fs/ext4/inode.c +0 -0

100644

fs/ext4/inode.c +14 -10
@@ -695,6 +695,20 @@ has_zeroout:
 		int ret = check_block_validity(inode, map);
 		if (ret != 0)
 			return ret;
+
+		/*
+		 * Inodes with freshly allocated blocks where contents will be
+		 * visible after transaction commit must be on transaction's
+		 * ordered data list.
+		 */
+		if (map->m_flags & EXT4_MAP_NEW &&
+		    !(map->m_flags & EXT4_MAP_UNWRITTEN) &&
+		    !IS_NOQUOTA(inode) &&
+		    ext4_should_order_data(inode)) {
+			ret = ext4_jbd2_file_inode(handle, inode);
+			if (ret)
+				return ret;
+		}
 	}
 	return retval;
 }
@@ -1059,15 +1073,6 @@ static int ext4_write_end(struct file *file,
 	int i_size_changed = 0;
 
 	trace_ext4_write_end(inode, pos, len, copied);
-	if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) {
-		ret = ext4_jbd2_file_inode(handle, inode);
-		if (ret) {
-			unlock_page(page);
-			page_cache_release(page);
-			goto errout;
-		}
-	}
-
 	if (ext4_has_inline_data(inode)) {
 		ret = ext4_write_inline_data_end(inode, pos, len,
 						 copied, page);
--
Quoted 2 lines

1.9.3

--
Jan Kara <[email protected]>
SUSE Labs, CR

Signature · 2 lines
Jan Kara <[email protected]>
SUSE Labs, CR
maintainer
#8 lore raw

Ext4 support for LTS kernels (was: Re: [PATCH 3.14] ext4: fix data exposure after a crash)

Quoted 5 lines · Jan Kara
Quoted 1 line · On Fri 06-10-17 10:04:41, HUANG Weller (CM/ESW12-CN) wrote:

I checked the latest 3.14 source code 3.14.79. I didn't found the below patch.

Well, I'm not sure who runs the 3.14 stable tree (it's not listed at kernel.org). It's up to him to pick up patches...

The announcement of 3.14's End of Life as a stable kernel series was announced in September 2016. As far as I know, the fact that 3.14 is no longer listed on kernel.org means that no one is maintaining 3.14 after Greg K-H declared it to be EOL'ed.

On a side note, I just recently finished an effort to update the ext4 patches for 3.14, 4.1, 4.4, and 4.9. I've sent those backports and cherry pick requests to [email protected]. For details of my work, at:

https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git

There are testing notes in the signed git tags:

ext4-4.9.54-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.9.54-1
ext4-4.4.91-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.4.91-1
ext4-4.1.44-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.1.44-1
ext4-3.18.74-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-3.18.74-1

.... and on a "when Ted has time / interest basis", the ext4-3.18, ext4-4.1, ext4-4.4, and ext-4.9 branches in the above repo will be updated with a rebase against the latest LTS kernel and whatever patches are needed to minimize xfstests failures that haven't yet gotten accepted into the LTS kernel versions.

Getting changes into android-common and/or various SOC's BSP kernels is left as an exercise to the reader.

I suspect that at some point soon, when 4.14 becomes released and becomes a LTS kernel, I'm going to drop ext4-4.1 and replace it with ext4-4.14, since very few people seem to be using the 4.1 LTS kernel, and my time / effort is limited. If someone is interested in helping out, please contact me.

- Ted

author maintainer
#9 lore raw

Re: Ext4 support for LTS kernels (was: Re: [PATCH 3.14] ext4: fix data exposure after a crash)

Quoted 11 lines · Theodore Ts'o
Quoted 5 lines · Jan Kara
Quoted 1 line · On Fri 06-10-17 10:04:41, HUANG Weller (CM/ESW12-CN) wrote:

I checked the latest 3.14 source code 3.14.79. I didn't found the below patch.

Well, I'm not sure who runs the 3.14 stable tree (it's not listed at kernel.org). It's up to him to pick up patches...

The announcement of 3.14's End of Life as a stable kernel series was announced in September 2016. As far as I know, the fact that 3.14 is no longer listed on kernel.org means that no one is maintaining 3.14 after Greg K-H declared it to be EOL'ed.

Yes, 3.14 is dead :)

Quoted 18 lines

On a side note, I just recently finished an effort to update the ext4 patches for 3.14, 4.1, 4.4, and 4.9. I've sent those backports and cherry pick requests to [email protected]. For details of my work, at:

https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git

There are testing notes in the signed git tags:

ext4-4.9.54-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.9.54-1
ext4-4.4.91-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.4.91-1
ext4-4.1.44-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.1.44-1
ext4-3.18.74-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-3.18.74-1

Quoted 5 lines

.... and on a "when Ted has time / interest basis", the ext4-3.18, ext4-4.1, ext4-4.4, and ext-4.9 branches in the above repo will be updated with a rebase against the latest LTS kernel and whatever patches are needed to minimize xfstests failures that haven't yet gotten accepted into the LTS kernel versions.

Thanks so much for this work. I think I've gotten most of these for 4.9, 4.4, and 3.18, I've emailed about the ones that didn't apply.

Quoted 2 lines

Getting changes into android-common and/or various SOC's BSP kernels is left as an exercise to the reader.

android-common syncs with the lts stable releases, so they should get picked up by the SoC BSP kernels that way. As long as your SoC company is sane...

thanks,

greg k-h

author maintainer
#10 lore raw

Re: Ext4 support for LTS kernels (was: Re: [PATCH 3.14] ext4: fix data exposure after a crash)

Quoted 33 lines · Greg KH
Quoted 11 lines · Theodore Ts'o
Quoted 5 lines · Jan Kara
Quoted 1 line · On Fri 06-10-17 10:04:41, HUANG Weller (CM/ESW12-CN) wrote:

I checked the latest 3.14 source code 3.14.79. I didn't found the below patch.

Well, I'm not sure who runs the 3.14 stable tree (it's not listed at kernel.org). It's up to him to pick up patches...

The announcement of 3.14's End of Life as a stable kernel series was announced in September 2016. As far as I know, the fact that 3.14 is no longer listed on kernel.org means that no one is maintaining 3.14 after Greg K-H declared it to be EOL'ed.

Yes, 3.14 is dead :)

Quoted 18 lines

On a side note, I just recently finished an effort to update the ext4 patches for 3.14, 4.1, 4.4, and 4.9. I've sent those backports and cherry pick requests to [email protected]. For details of my work, at:

https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git

There are testing notes in the signed git tags:

ext4-4.9.54-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.9.54-1
ext4-4.4.91-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.4.91-1
ext4-4.1.44-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-4.1.44-1
ext4-3.18.74-1
- https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git/tag/?h=ext4-3.18.74-1

Quoted 8 lines
Quoted 5 lines

.... and on a "when Ted has time / interest basis", the ext4-3.18, ext4-4.1, ext4-4.4, and ext-4.9 branches in the above repo will be updated with a rebase against the latest LTS kernel and whatever patches are needed to minimize xfstests failures that haven't yet gotten accepted into the LTS kernel versions.

Thanks so much for this work. I think I've gotten most of these for 4.9, 4.4, and 3.18, I've emailed about the ones that didn't apply.

I dug in your branches above, and found the one missing patch for 3.18. So I think I am all caught up now.

If not, please let me know.

thanks,

greg k-h

author maintainer
#11 lore raw

Re: [PATCH 3.14] ext4: fix data exposure after a crash

In reply to George G. Davis
Quoted 5 lines · George G. Davis

From: Jan Kara <[email protected]>

From: Jan Kara <[email protected]>

commit 06bd3c36a733ac27962fea7d6f47168841376824 upstream

What about a 4.4-stable version of this? I don't want to take this into 3.14-stable without that.

thanks,

greg k-h