f2fs: fix data corruption issue with hardware encryption
PATCH 1/1 f2fs: fix data corruption issue with hardware encryption
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO
-> GC gets kicked in
-> GC submitted bio on meta mapping
for file#1, but pending completion
-> write file#1 again with new data
in direct IO
-> GC bio gets completed now
-> GC writes old data to the new
location and thus file#1 is
corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in f2fs_map_blocks().
--- fs/f2fs/data.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
fs/f2fs/data.c +12 -0
@@ -1028,6 +1028,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len =min ((pgoff_t )maxblocks, ei.fofs + ei.len - pgofs); map->m_flags =F2FS_MAP_MAPPED ; +/* for HW encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr); + }if (map->m_next_extent) *map->m_next_extent = pgofs + map->m_len; goto out;
@@ -1188,6 +1194,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO && map->m_flags &F2FS_MAP_MAPPED ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr); + }if (flag ==F2FS_GET_BLOCK_PRECACHE ) {if (map->m_flags &F2FS_MAP_MAPPED ) {unsigned int ofs = start_pgofs - map->m_lblk;
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Jaegeuk Kim
maintainerQuoted 28 lines · Sahitya Tummala
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>--- fs/f2fs/data.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)fs/f2fs/data.c +0
-0
fs/f2fs/data.c int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, · line 1035
Quoted 8 lines
fs/f2fs/data.c +5
-0@@ -1028,6 +1028,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len =min ((pgoff_t )maxblocks, ei.fofs + ei.len - pgofs); map->m_flags =F2FS_MAP_MAPPED ; +/* for HW encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr);
Do we need this? IIRC, DIO would give create=1.
Quoted 20 lines
fs/f2fs/data.c +7
-0+ }if (map->m_next_extent) *map->m_next_extent = pgofs + map->m_len; goto out;@@ -1188,6 +1194,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO && map->m_flags &F2FS_MAP_MAPPED ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr); + }if (flag ==F2FS_GET_BLOCK_PRECACHE ) {if (map->m_flags &F2FS_MAP_MAPPED ) {unsigned int ofs = start_pgofs - map->m_lblk;Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Quoted 24 lines · Jaegeuk Kim
Quoted 23 lines · Sahitya Tummala
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>--- fs/f2fs/data.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
Quoted 15 lines
fs/f2fs/data.c int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, · line 1035
Quoted 13 lines
fs/f2fs/data.c +5
-0@@ -1028,6 +1028,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len =min ((pgoff_t )maxblocks, ei.fofs + ei.len - pgofs); map->m_flags =F2FS_MAP_MAPPED ; +/* for HW encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr);Do we need this? IIRC, DIO would give create=1.
Yes, we need it. When we are overwriting an existing file, DIO calls f2fs_map_blocks() with create=0. From the DIO code, I see that this happens because blockdev_direct_IO() passes this dio flag DIO_SKIP_HOLES. And then in get_more_blocks(), below code updates create=0, when we are overwriting an existing file.
create = dio->op == REQ_OP_WRITE;
if (dio->flags & DIO_SKIP_HOLES) {
if (fs_startblk <= ((i_size_read(dio->inode) - 1) >>
i_blkbits))
create = 0;
}
ret = (*sdio->get_block)(dio->inode, fs_startblk,
map_bh, create);Quoted 21 lines
Quoted 21 lines
fs/f2fs/data.c +7
-0+ }if (map->m_next_extent) *map->m_next_extent = pgofs + map->m_len; goto out;@@ -1188,6 +1194,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO && map->m_flags &F2FS_MAP_MAPPED ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr); + }if (flag ==F2FS_GET_BLOCK_PRECACHE ) {if (map->m_flags &F2FS_MAP_MAPPED ) {unsigned int ofs = start_pgofs - map->m_lblk;Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
Signature · 3 lines
-- Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Jaegeuk Kim
maintainerQuoted 47 lines · Sahitya Tummala
Quoted 24 lines · Jaegeuk Kim
Quoted 23 lines · Sahitya Tummala
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>--- fs/f2fs/data.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)Quoted 15 lines
fs/f2fs/data.c int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, · line 1035
Quoted 13 lines
fs/f2fs/data.c +5
-0@@ -1028,6 +1028,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len =min ((pgoff_t )maxblocks, ei.fofs + ei.len - pgofs); map->m_flags =F2FS_MAP_MAPPED ; +/* for HW encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr);Do we need this? IIRC, DIO would give create=1.
Yes, we need it. When we are overwriting an existing file, DIO calls
f2fs_map_blocks()with create=0. From the DIO code, I see that this happens becauseblockdev_direct_IO()passes this dio flagDIO_SKIP_HOLES. And then inget_more_blocks(), below code updates create=0, when we are overwriting an existing file.
Quoted 10 lines
create = dio->op == REQ_OP_WRITE;
if (dio->flags & DIO_SKIP_HOLES) {
if (fs_startblk <= ((i_size_read(dio->inode) - 1) >>
i_blkbits))
create = 0;
}
ret = (*sdio->get_block)(dio->inode, fs_startblk,
map_bh, create);Got it.
How about this?
Quoted 1 line
From
216037253e6c21530ced716940fa01978d801f0dMon Sep 17 00:00:00 2001
From: Sahitya Tummala <[email protected]>
Date: Wed, 10 Oct 2018 10:56:22 +0530
Subject: [PATCH] f2fs: fix data corruption issue with hardware encryption
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO
-> GC gets kicked in
-> GC submitted bio on meta mapping
for file#1, but pending completion
-> write file#1 again with new data
in direct IO
-> GC bio gets completed now
-> GC writes old data to the new
location and thus file#1 is
corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in f2fs_map_blocks().
--- fs/f2fs/data.c | 11 +++++++++++ fs/f2fs/f2fs.h | 2 ++ fs/f2fs/segment.c | 7 +++++++ 3 files changed, 20 insertions(+)
fs/f2fs/data.c +11 -0
@@ -1030,6 +1030,11 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_flags =F2FS_MAP_MAPPED ;if (map->m_next_extent) *map->m_next_extent = pgofs + map->m_len; + +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) +f2fs_wait_on_block_writeback_range (inode, + map->m_pblk, map->m_len); goto out; }
@@ -1188,6 +1193,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO && map->m_flags &F2FS_MAP_MAPPED ) +f2fs_wait_on_block_writeback_range (inode, + map->m_pblk, map->m_len); +if (flag ==F2FS_GET_BLOCK_PRECACHE ) {if (map->m_flags &F2FS_MAP_MAPPED ) {unsigned int ofs = start_pgofs - map->m_lblk;
fs/f2fs/f2fs.h +2 -0
@@ -2986,6 +2986,8 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,void f2fs_wait_on_page_writeback (struct page *page,enum page_type type,bool ordered);void f2fs_wait_on_block_writeback (struct inode *inode,block_t blkaddr); +void f2fs_wait_on_block_writeback_range (struct inode *inode,block_t blkaddr, +block_t len);void f2fs_write_data_summaries (struct f2fs_sb_info *sbi,block_t start_blk);void f2fs_write_node_summaries (struct f2fs_sb_info *sbi,block_t start_blk); int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
fs/f2fs/segment.c +7 -0
@@ -3301,6 +3301,13 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr) } } +void f2fs_wait_on_block_writeback_range (struct inode *inode,block_t blkaddr, +block_t len) +{ +for (; blkaddr < blkaddr + len; blkaddr++) +f2fs_wait_on_block_writeback (inode, blkaddr); +} +static int read_compacted_summaries (struct f2fs_sb_info *sbi) {struct f2fs_checkpoint *ckpt =F2FS_CKPT (sbi);
Signature · 1 line
2.19.0.605.g01d371f741-goog
Jaegeuk Kim
maintainerQuoted 55 lines · Jaegeuk Kim
Quoted 54 lines · Sahitya Tummala
Quoted 24 lines · Jaegeuk Kim
Quoted 23 lines · Sahitya Tummala
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>--- fs/f2fs/data.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)Quoted 15 lines
fs/f2fs/data.c int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, · line 1035
Quoted 13 lines
fs/f2fs/data.c +5
-0@@ -1028,6 +1028,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len =min ((pgoff_t )maxblocks, ei.fofs + ei.len - pgofs); map->m_flags =F2FS_MAP_MAPPED ; +/* for HW encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr);Do we need this? IIRC, DIO would give create=1.
Yes, we need it. When we are overwriting an existing file, DIO calls
f2fs_map_blocks()with create=0. From the DIO code, I see that this happens becauseblockdev_direct_IO()passes this dio flagDIO_SKIP_HOLES. And then inget_more_blocks(), below code updates create=0, when we are overwriting an existing file.create = dio->op == REQ_OP_WRITE; if (dio->flags & DIO_SKIP_HOLES) { if (fs_startblk <= ((i_size_read(dio->inode) - 1) >> i_blkbits)) create = 0; }
Quoted 7 lines
Quoted 3 lines
ret = (*sdio->get_block)(dio->inode, fs_startblk, map_bh, create);Got it.
How about this?
Sorry, this is v2.
Quoted 1 line
From
b78dd7b2e0317be18716b9496269e9792829f63eMon Sep 17 00:00:00 2001
From: Sahitya Tummala <[email protected]>
Date: Wed, 10 Oct 2018 10:56:22 +0530
Subject: [PATCH] f2fs: fix data corruption issue with hardware encryption
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO
-> GC gets kicked in
-> GC submitted bio on meta mapping
for file#1, but pending completion
-> write file#1 again with new data
in direct IO
-> GC bio gets completed now
-> GC writes old data to the new
location and thus file#1 is
corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in f2fs_map_blocks().
--- fs/f2fs/data.c | 11 +++++++++++ fs/f2fs/f2fs.h | 2 ++ fs/f2fs/segment.c | 9 +++++++++ 3 files changed, 22 insertions(+)
fs/f2fs/data.c +11 -0
@@ -1030,6 +1030,11 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_flags =F2FS_MAP_MAPPED ;if (map->m_next_extent) *map->m_next_extent = pgofs + map->m_len; + +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) +f2fs_wait_on_block_writeback_range (inode, + map->m_pblk, map->m_len); goto out; }
@@ -1188,6 +1193,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO && map->m_flags &F2FS_MAP_MAPPED ) +f2fs_wait_on_block_writeback_range (inode, + map->m_pblk, map->m_len); +if (flag ==F2FS_GET_BLOCK_PRECACHE ) {if (map->m_flags &F2FS_MAP_MAPPED ) {unsigned int ofs = start_pgofs - map->m_lblk;
fs/f2fs/f2fs.h +2 -0
@@ -2986,6 +2986,8 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,void f2fs_wait_on_page_writeback (struct page *page,enum page_type type,bool ordered);void f2fs_wait_on_block_writeback (struct inode *inode,block_t blkaddr); +void f2fs_wait_on_block_writeback_range (struct inode *inode,block_t blkaddr, +block_t len);void f2fs_write_data_summaries (struct f2fs_sb_info *sbi,block_t start_blk);void f2fs_write_node_summaries (struct f2fs_sb_info *sbi,block_t start_blk); int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
fs/f2fs/segment.c +9 -0
@@ -3301,6 +3301,15 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr) } } +void f2fs_wait_on_block_writeback_range (struct inode *inode,block_t blkaddr, +block_t len) +{ +block_t i; + +for (i =0 ; i < len; i++) +f2fs_wait_on_block_writeback (inode, blkaddr + i); +} +static int read_compacted_summaries (struct f2fs_sb_info *sbi) {struct f2fs_checkpoint *ckpt =F2FS_CKPT (sbi);
Signature · 1 line
2.19.0.605.g01d371f741-goog
Quoted 60 lines · Jaegeuk Kim
Quoted 59 lines · Jaegeuk Kim
Quoted 57 lines · Sahitya Tummala
Quoted 24 lines · Jaegeuk Kim
Quoted 23 lines · Sahitya Tummala
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>--- fs/f2fs/data.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)Quoted 15 lines
fs/f2fs/data.c int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, · line 1035
Quoted 13 lines
fs/f2fs/data.c +5
-0@@ -1028,6 +1028,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len =min ((pgoff_t )maxblocks, ei.fofs + ei.len - pgofs); map->m_flags =F2FS_MAP_MAPPED ; +/* for HW encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr);Do we need this? IIRC, DIO would give create=1.
Yes, we need it. When we are overwriting an existing file, DIO calls
f2fs_map_blocks()with create=0. From the DIO code, I see that this happens becauseblockdev_direct_IO()passes this dio flagDIO_SKIP_HOLES. And then inget_more_blocks(), below code updates create=0, when we are overwriting an existing file.create = dio->op == REQ_OP_WRITE; if (dio->flags & DIO_SKIP_HOLES) { if (fs_startblk <= ((i_size_read(dio->inode) - 1) >> i_blkbits)) create = 0; } ret = (*sdio->get_block)(dio->inode, fs_startblk, map_bh, create);
Quoted 5 lines
Quoted 3 lines
Got it.
How about this?Sorry, this is v2.
Looks good to me. Thanks for updating it :)
Quoted 97 lines
From
b78dd7b2e0317be18716b9496269e9792829f63eMon Sep 17 00:00:00 2001
From: Sahitya Tummala <[email protected]>
Date: Wed, 10 Oct 2018 10:56:22 +0530
Subject: [PATCH] f2fs: fix data corruption issue with hardware encryptionDirect IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>Signed-off-by Jaegeuk Kim <[email protected]>--- fs/f2fs/data.c | 11 +++++++++++ fs/f2fs/f2fs.h | 2 ++ fs/f2fs/segment.c | 9 +++++++++ 3 files changed, 22 insertions(+)fs/f2fs/data.c +11
-0@@ -1030,6 +1030,11 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_flags =F2FS_MAP_MAPPED ;if (map->m_next_extent) *map->m_next_extent = pgofs + map->m_len; + +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) +f2fs_wait_on_block_writeback_range (inode, + map->m_pblk, map->m_len); goto out; }@@ -1188,6 +1193,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + +/* for hardware encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO && map->m_flags &F2FS_MAP_MAPPED ) +f2fs_wait_on_block_writeback_range (inode, + map->m_pblk, map->m_len); +if (flag ==F2FS_GET_BLOCK_PRECACHE ) {if (map->m_flags &F2FS_MAP_MAPPED ) {unsigned int ofs = start_pgofs - map->m_lblk;fs/f2fs/f2fs.h +2
-0@@ -2986,6 +2986,8 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,void f2fs_wait_on_page_writeback (struct page *page,enum page_type type,bool ordered);void f2fs_wait_on_block_writeback (struct inode *inode,block_t blkaddr); +void f2fs_wait_on_block_writeback_range (struct inode *inode,block_t blkaddr, +block_t len);void f2fs_write_data_summaries (struct f2fs_sb_info *sbi,block_t start_blk);void f2fs_write_node_summaries (struct f2fs_sb_info *sbi,block_t start_blk); int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,fs/f2fs/segment.c +9
-0@@ -3301,6 +3301,15 @@ void f2fs_wait_on_block_writeback(struct inode *inode, block_t blkaddr) } } +void f2fs_wait_on_block_writeback_range (struct inode *inode,block_t blkaddr, +block_t len) +{ +block_t i; + +for (i =0 ; i < len; i++) +f2fs_wait_on_block_writeback (inode, blkaddr + i); +} +static int read_compacted_summaries (struct f2fs_sb_info *sbi) {struct f2fs_checkpoint *ckpt =F2FS_CKPT (sbi);Signature · 1 line
2.19.0.605.g01d371f741-goog
Signature · 3 lines
-- Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Chao Yu
Reviewed-byQuoted 86 lines · Jaegeuk Kim
Quoted 55 lines · Jaegeuk Kim
Quoted 54 lines · Sahitya Tummala
Quoted 24 lines · Jaegeuk Kim
Quoted 23 lines · Sahitya Tummala
Direct IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>--- fs/f2fs/data.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)Quoted 15 lines
fs/f2fs/data.c int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, · line 1035
Quoted 13 lines
fs/f2fs/data.c +5
-0@@ -1028,6 +1028,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, map->m_pblk = ei.blk + pgofs - ei.fofs; map->m_len =min ((pgoff_t )maxblocks, ei.fofs + ei.len - pgofs); map->m_flags =F2FS_MAP_MAPPED ; +/* for HW encryption, but to avoid potential issue in future */ +if (flag ==F2FS_GET_BLOCK_DIO ) { + blkaddr = map->m_pblk; +for (; blkaddr < map->m_pblk + map->m_len; blkaddr++) +f2fs_wait_on_block_writeback (sbi, blkaddr);Do we need this? IIRC, DIO would give create=1.
Yes, we need it. When we are overwriting an existing file, DIO calls
f2fs_map_blocks()with create=0. From the DIO code, I see that this happens becauseblockdev_direct_IO()passes this dio flagDIO_SKIP_HOLES. And then inget_more_blocks(), below code updates create=0, when we are overwriting an existing file.create = dio->op == REQ_OP_WRITE; if (dio->flags & DIO_SKIP_HOLES) { if (fs_startblk <= ((i_size_read(dio->inode) - 1) >> i_blkbits)) create = 0; }Quoted 7 lines
Quoted 3 lines
ret = (*sdio->get_block)(dio->inode, fs_startblk, map_bh, create);Got it.
How about this?Sorry, this is v2.
Quoted 1 line
From
b78dd7b2e0317be18716b9496269e9792829f63eMon Sep 17 00:00:00 2001From: Sahitya Tummala <[email protected]>
Date: Wed, 10 Oct 2018 10:56:22 +0530
Subject: [PATCH] f2fs: fix data corruption issue with hardware encryptionDirect IO can be used in case of hardware encryption. The following scenario results into data corruption issue in this path -
Thread A - Thread B-
-> write file#1 in direct IO-> GC gets kicked in -> GC submitted bio on meta mapping for file#1, but pending completion -> write file#1 again with new data in direct IO -> GC bio gets completed now -> GC writes old data to the new location and thus file#1 is corrupted.
Quoted 5 lines
Fix this by submitting and waiting for pending io on meta mapping for direct IO case in
f2fs_map_blocks().Signed-off-by Sahitya Tummala <[email protected]>Signed-off-by Jaegeuk Kim <[email protected]>
Nice catch!
Thanks,