Re: [PATCH v7 1/1] f2fs: dax: implement direct access
Hi Jaegeuk, Thank you for the edits and comments. I will accept them, except that f2fs_iomap_end() does not need to return any error. See below for details. Hi Qiuyang, On 07/18, sunqiuyang wrote: From: Qiuyang SunThis patch implements Direct Access (DAX) in F2FS, including: - a mount option to choose whether to enable DAX or not - read/write and mmap of regular files in the DAX way - zero-out of unaligned partial blocks in the DAX way - garbage collection of DAX files, by mapping both old and new physical addresses of a data page into memory and copy data between them directly - incompatibility of DAX with inline data, atomic or volatile write, etc. Signed-off-by: Qiuyang Sun --- Changlog v6 -> v7: - Document the mount option "dax" for this feature in f2fs.txt - Minor cleanup in dax_move_data_page() --- Documentation/filesystems/f2fs.txt | 2 + fs/f2fs/data.c | 132 +++-- fs/f2fs/f2fs.h | 9 ++ fs/f2fs/file.c | 192 - fs/f2fs/gc.c | 105 +++- fs/f2fs/inline.c | 4 + fs/f2fs/inode.c| 8 +- fs/f2fs/namei.c| 5 + fs/f2fs/super.c| 15 +++ 9 files changed, 459 insertions(+), 13 deletions(-) diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 273ccb2..c86c421 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -164,6 +164,8 @@ io_bits=%u Set the bit size of write IO requests. It should be set with "mode=lfs". usrquota Enable plain user disk quota accounting. grpquota Enable plain group disk quota accounting. +daxUse direct access (no page cache). See + Documentation/filesystems/dax.txt. DEBUGFS ENTRIES diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 87c1f41..26b908a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -910,6 +910,15 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, err = -EIO; goto sync_out; } + /* +* If newly allocated blocks are to be zeroed out later, +* a single f2fs_map_blocks must not contain both old +* and new blocks at the same time. +*/ + if (flag == F2FS_GET_BLOCK_ZERO + && (map->m_flags & F2FS_MAP_MAPPED) + && !(map->m_flags & F2FS_MAP_NEW)) + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (blkaddr == NULL_ADDR) { prealloc++; @@ -938,7 +947,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, blkaddr != NEW_ADDR) goto sync_out; } - } + } else if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) } else if () { } + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) goto skip; @@ -996,6 +1006,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) { + clean_bdev_aliases(inode->i_sb->s_bdev, + map->m_pblk, map->m_len); + err = sb_issue_zeroout(inode->i_sb, map->m_pblk, + map->m_len, GFP_NOFS); + } f2fs_put_dnode(); unlock_out: if (create) { @@ -1808,16 +1824,19 @@ static int f2fs_write_data_pages(struct address_space *mapping, return 0; } -static void f2fs_write_failed(struct address_space *mapping, loff_t to) +static void f2fs_write_failed(struct address_space *mapping, loff_t to, + bool lock) { struct inode *inode = mapping->host; loff_t i_size = i_size_read(inode); if (to > i_size) { - down_write(_I(inode)->i_mmap_sem); + if (lock) + down_write(_I(inode)->i_mmap_sem); truncate_pagecache(inode, i_size); truncate_blocks(inode, i_size, true); - up_write(_I(inode)->i_mmap_sem); + if (lock) + up_write(_I(inode)->i_mmap_sem); } } @@ -2000,7 +2019,7 @@ static int f2fs_write_begin(struct file
Re: [PATCH v7 1/1] f2fs: dax: implement direct access
Hi Jaegeuk, Thank you for the edits and comments. I will accept them, except that f2fs_iomap_end() does not need to return any error. See below for details. Hi Qiuyang, On 07/18, sunqiuyang wrote: From: Qiuyang Sun This patch implements Direct Access (DAX) in F2FS, including: - a mount option to choose whether to enable DAX or not - read/write and mmap of regular files in the DAX way - zero-out of unaligned partial blocks in the DAX way - garbage collection of DAX files, by mapping both old and new physical addresses of a data page into memory and copy data between them directly - incompatibility of DAX with inline data, atomic or volatile write, etc. Signed-off-by: Qiuyang Sun --- Changlog v6 -> v7: - Document the mount option "dax" for this feature in f2fs.txt - Minor cleanup in dax_move_data_page() --- Documentation/filesystems/f2fs.txt | 2 + fs/f2fs/data.c | 132 +++-- fs/f2fs/f2fs.h | 9 ++ fs/f2fs/file.c | 192 - fs/f2fs/gc.c | 105 +++- fs/f2fs/inline.c | 4 + fs/f2fs/inode.c| 8 +- fs/f2fs/namei.c| 5 + fs/f2fs/super.c| 15 +++ 9 files changed, 459 insertions(+), 13 deletions(-) diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 273ccb2..c86c421 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -164,6 +164,8 @@ io_bits=%u Set the bit size of write IO requests. It should be set with "mode=lfs". usrquota Enable plain user disk quota accounting. grpquota Enable plain group disk quota accounting. +daxUse direct access (no page cache). See + Documentation/filesystems/dax.txt. DEBUGFS ENTRIES diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 87c1f41..26b908a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -910,6 +910,15 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, err = -EIO; goto sync_out; } + /* +* If newly allocated blocks are to be zeroed out later, +* a single f2fs_map_blocks must not contain both old +* and new blocks at the same time. +*/ + if (flag == F2FS_GET_BLOCK_ZERO + && (map->m_flags & F2FS_MAP_MAPPED) + && !(map->m_flags & F2FS_MAP_NEW)) + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (blkaddr == NULL_ADDR) { prealloc++; @@ -938,7 +947,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, blkaddr != NEW_ADDR) goto sync_out; } - } + } else if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) } else if () { } + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) goto skip; @@ -996,6 +1006,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) { + clean_bdev_aliases(inode->i_sb->s_bdev, + map->m_pblk, map->m_len); + err = sb_issue_zeroout(inode->i_sb, map->m_pblk, + map->m_len, GFP_NOFS); + } f2fs_put_dnode(); unlock_out: if (create) { @@ -1808,16 +1824,19 @@ static int f2fs_write_data_pages(struct address_space *mapping, return 0; } -static void f2fs_write_failed(struct address_space *mapping, loff_t to) +static void f2fs_write_failed(struct address_space *mapping, loff_t to, + bool lock) { struct inode *inode = mapping->host; loff_t i_size = i_size_read(inode); if (to > i_size) { - down_write(_I(inode)->i_mmap_sem); + if (lock) + down_write(_I(inode)->i_mmap_sem); truncate_pagecache(inode, i_size); truncate_blocks(inode, i_size, true); - up_write(_I(inode)->i_mmap_sem); + if (lock) + up_write(_I(inode)->i_mmap_sem); } } @@ -2000,7 +2019,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, fail:
Re: [PATCH v7 1/1] f2fs: dax: implement direct access
Hi Qiuyang, On 07/18, sunqiuyang wrote: > From: Qiuyang Sun> > This patch implements Direct Access (DAX) in F2FS, including: > - a mount option to choose whether to enable DAX or not > - read/write and mmap of regular files in the DAX way > - zero-out of unaligned partial blocks in the DAX way > - garbage collection of DAX files, by mapping both old and new physical > addresses of a data page into memory and copy data between them directly > - incompatibility of DAX with inline data, atomic or volatile write, etc. > > Signed-off-by: Qiuyang Sun > --- > Changlog v6 -> v7: > - Document the mount option "dax" for this feature in f2fs.txt > - Minor cleanup in dax_move_data_page() > > --- > Documentation/filesystems/f2fs.txt | 2 + > fs/f2fs/data.c | 132 +++-- > fs/f2fs/f2fs.h | 9 ++ > fs/f2fs/file.c | 192 > - > fs/f2fs/gc.c | 105 +++- > fs/f2fs/inline.c | 4 + > fs/f2fs/inode.c| 8 +- > fs/f2fs/namei.c| 5 + > fs/f2fs/super.c| 15 +++ > 9 files changed, 459 insertions(+), 13 deletions(-) > > diff --git a/Documentation/filesystems/f2fs.txt > b/Documentation/filesystems/f2fs.txt > index 273ccb2..c86c421 100644 > --- a/Documentation/filesystems/f2fs.txt > +++ b/Documentation/filesystems/f2fs.txt > @@ -164,6 +164,8 @@ io_bits=%u Set the bit size of write IO > requests. It should be set > with "mode=lfs". > usrquota Enable plain user disk quota accounting. > grpquota Enable plain group disk quota accounting. > +daxUse direct access (no page cache). See > + Documentation/filesystems/dax.txt. > > > > DEBUGFS ENTRIES > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c > index 87c1f41..26b908a 100644 > --- a/fs/f2fs/data.c > +++ b/fs/f2fs/data.c > @@ -910,6 +910,15 @@ int f2fs_map_blocks(struct inode *inode, struct > f2fs_map_blocks *map, > err = -EIO; > goto sync_out; > } > + /* > + * If newly allocated blocks are to be zeroed out later, > + * a single f2fs_map_blocks must not contain both old > + * and new blocks at the same time. > + */ > + if (flag == F2FS_GET_BLOCK_ZERO > + && (map->m_flags & F2FS_MAP_MAPPED) > + && !(map->m_flags & F2FS_MAP_NEW)) > + goto sync_out; > if (flag == F2FS_GET_BLOCK_PRE_AIO) { > if (blkaddr == NULL_ADDR) { > prealloc++; > @@ -938,7 +947,8 @@ int f2fs_map_blocks(struct inode *inode, struct > f2fs_map_blocks *map, > blkaddr != NEW_ADDR) > goto sync_out; > } > - } > + } else if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) } else if () { } > + goto sync_out; > > if (flag == F2FS_GET_BLOCK_PRE_AIO) > goto skip; > @@ -996,6 +1006,12 @@ int f2fs_map_blocks(struct inode *inode, struct > f2fs_map_blocks *map, > goto next_dnode; > > sync_out: > + if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) { > + clean_bdev_aliases(inode->i_sb->s_bdev, > + map->m_pblk, map->m_len); > + err = sb_issue_zeroout(inode->i_sb, map->m_pblk, > + map->m_len, GFP_NOFS); > + } > f2fs_put_dnode(); > unlock_out: > if (create) { > @@ -1808,16 +1824,19 @@ static int f2fs_write_data_pages(struct address_space > *mapping, > return 0; > } > > -static void f2fs_write_failed(struct address_space *mapping, loff_t to) > +static void f2fs_write_failed(struct address_space *mapping, loff_t to, > + bool lock) > { > struct inode *inode = mapping->host; > loff_t i_size = i_size_read(inode); > > if (to > i_size) { > - down_write(_I(inode)->i_mmap_sem); > + if (lock) > + down_write(_I(inode)->i_mmap_sem); > truncate_pagecache(inode, i_size); > truncate_blocks(inode, i_size, true); > - up_write(_I(inode)->i_mmap_sem); > + if (lock) > + up_write(_I(inode)->i_mmap_sem); > } > } > > @@ -2000,7 +2019,7 @@ static int f2fs_write_begin(struct file *file, struct >
Re: [PATCH v7 1/1] f2fs: dax: implement direct access
Hi Qiuyang, On 07/18, sunqiuyang wrote: > From: Qiuyang Sun > > This patch implements Direct Access (DAX) in F2FS, including: > - a mount option to choose whether to enable DAX or not > - read/write and mmap of regular files in the DAX way > - zero-out of unaligned partial blocks in the DAX way > - garbage collection of DAX files, by mapping both old and new physical > addresses of a data page into memory and copy data between them directly > - incompatibility of DAX with inline data, atomic or volatile write, etc. > > Signed-off-by: Qiuyang Sun > --- > Changlog v6 -> v7: > - Document the mount option "dax" for this feature in f2fs.txt > - Minor cleanup in dax_move_data_page() > > --- > Documentation/filesystems/f2fs.txt | 2 + > fs/f2fs/data.c | 132 +++-- > fs/f2fs/f2fs.h | 9 ++ > fs/f2fs/file.c | 192 > - > fs/f2fs/gc.c | 105 +++- > fs/f2fs/inline.c | 4 + > fs/f2fs/inode.c| 8 +- > fs/f2fs/namei.c| 5 + > fs/f2fs/super.c| 15 +++ > 9 files changed, 459 insertions(+), 13 deletions(-) > > diff --git a/Documentation/filesystems/f2fs.txt > b/Documentation/filesystems/f2fs.txt > index 273ccb2..c86c421 100644 > --- a/Documentation/filesystems/f2fs.txt > +++ b/Documentation/filesystems/f2fs.txt > @@ -164,6 +164,8 @@ io_bits=%u Set the bit size of write IO > requests. It should be set > with "mode=lfs". > usrquota Enable plain user disk quota accounting. > grpquota Enable plain group disk quota accounting. > +daxUse direct access (no page cache). See > + Documentation/filesystems/dax.txt. > > > > DEBUGFS ENTRIES > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c > index 87c1f41..26b908a 100644 > --- a/fs/f2fs/data.c > +++ b/fs/f2fs/data.c > @@ -910,6 +910,15 @@ int f2fs_map_blocks(struct inode *inode, struct > f2fs_map_blocks *map, > err = -EIO; > goto sync_out; > } > + /* > + * If newly allocated blocks are to be zeroed out later, > + * a single f2fs_map_blocks must not contain both old > + * and new blocks at the same time. > + */ > + if (flag == F2FS_GET_BLOCK_ZERO > + && (map->m_flags & F2FS_MAP_MAPPED) > + && !(map->m_flags & F2FS_MAP_NEW)) > + goto sync_out; > if (flag == F2FS_GET_BLOCK_PRE_AIO) { > if (blkaddr == NULL_ADDR) { > prealloc++; > @@ -938,7 +947,8 @@ int f2fs_map_blocks(struct inode *inode, struct > f2fs_map_blocks *map, > blkaddr != NEW_ADDR) > goto sync_out; > } > - } > + } else if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) } else if () { } > + goto sync_out; > > if (flag == F2FS_GET_BLOCK_PRE_AIO) > goto skip; > @@ -996,6 +1006,12 @@ int f2fs_map_blocks(struct inode *inode, struct > f2fs_map_blocks *map, > goto next_dnode; > > sync_out: > + if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) { > + clean_bdev_aliases(inode->i_sb->s_bdev, > + map->m_pblk, map->m_len); > + err = sb_issue_zeroout(inode->i_sb, map->m_pblk, > + map->m_len, GFP_NOFS); > + } > f2fs_put_dnode(); > unlock_out: > if (create) { > @@ -1808,16 +1824,19 @@ static int f2fs_write_data_pages(struct address_space > *mapping, > return 0; > } > > -static void f2fs_write_failed(struct address_space *mapping, loff_t to) > +static void f2fs_write_failed(struct address_space *mapping, loff_t to, > + bool lock) > { > struct inode *inode = mapping->host; > loff_t i_size = i_size_read(inode); > > if (to > i_size) { > - down_write(_I(inode)->i_mmap_sem); > + if (lock) > + down_write(_I(inode)->i_mmap_sem); > truncate_pagecache(inode, i_size); > truncate_blocks(inode, i_size, true); > - up_write(_I(inode)->i_mmap_sem); > + if (lock) > + up_write(_I(inode)->i_mmap_sem); > } > } > > @@ -2000,7 +2019,7 @@ static int f2fs_write_begin(struct file *file, struct > address_space *mapping, > > fail: >
Re: [PATCH v7 1/1] f2fs: dax: implement direct access
On 2017/7/18 11:45, sunqiuyang wrote: > From: Qiuyang Sun> > This patch implements Direct Access (DAX) in F2FS, including: > - a mount option to choose whether to enable DAX or not > - read/write and mmap of regular files in the DAX way > - zero-out of unaligned partial blocks in the DAX way > - garbage collection of DAX files, by mapping both old and new physical > addresses of a data page into memory and copy data between them directly > - incompatibility of DAX with inline data, atomic or volatile write, etc. > > Signed-off-by: Qiuyang Sun Reviewed-by: Chao Yu
Re: [PATCH v7 1/1] f2fs: dax: implement direct access
On 2017/7/18 11:45, sunqiuyang wrote: > From: Qiuyang Sun > > This patch implements Direct Access (DAX) in F2FS, including: > - a mount option to choose whether to enable DAX or not > - read/write and mmap of regular files in the DAX way > - zero-out of unaligned partial blocks in the DAX way > - garbage collection of DAX files, by mapping both old and new physical > addresses of a data page into memory and copy data between them directly > - incompatibility of DAX with inline data, atomic or volatile write, etc. > > Signed-off-by: Qiuyang Sun Reviewed-by: Chao Yu
[PATCH v7 1/1] f2fs: dax: implement direct access
From: Qiuyang SunThis patch implements Direct Access (DAX) in F2FS, including: - a mount option to choose whether to enable DAX or not - read/write and mmap of regular files in the DAX way - zero-out of unaligned partial blocks in the DAX way - garbage collection of DAX files, by mapping both old and new physical addresses of a data page into memory and copy data between them directly - incompatibility of DAX with inline data, atomic or volatile write, etc. Signed-off-by: Qiuyang Sun --- Changlog v6 -> v7: - Document the mount option "dax" for this feature in f2fs.txt - Minor cleanup in dax_move_data_page() --- Documentation/filesystems/f2fs.txt | 2 + fs/f2fs/data.c | 132 +++-- fs/f2fs/f2fs.h | 9 ++ fs/f2fs/file.c | 192 - fs/f2fs/gc.c | 105 +++- fs/f2fs/inline.c | 4 + fs/f2fs/inode.c| 8 +- fs/f2fs/namei.c| 5 + fs/f2fs/super.c| 15 +++ 9 files changed, 459 insertions(+), 13 deletions(-) diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 273ccb2..c86c421 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -164,6 +164,8 @@ io_bits=%u Set the bit size of write IO requests. It should be set with "mode=lfs". usrquota Enable plain user disk quota accounting. grpquota Enable plain group disk quota accounting. +daxUse direct access (no page cache). See + Documentation/filesystems/dax.txt. DEBUGFS ENTRIES diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 87c1f41..26b908a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -910,6 +910,15 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, err = -EIO; goto sync_out; } + /* +* If newly allocated blocks are to be zeroed out later, +* a single f2fs_map_blocks must not contain both old +* and new blocks at the same time. +*/ + if (flag == F2FS_GET_BLOCK_ZERO + && (map->m_flags & F2FS_MAP_MAPPED) + && !(map->m_flags & F2FS_MAP_NEW)) + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (blkaddr == NULL_ADDR) { prealloc++; @@ -938,7 +947,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, blkaddr != NEW_ADDR) goto sync_out; } - } + } else if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) goto skip; @@ -996,6 +1006,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) { + clean_bdev_aliases(inode->i_sb->s_bdev, + map->m_pblk, map->m_len); + err = sb_issue_zeroout(inode->i_sb, map->m_pblk, + map->m_len, GFP_NOFS); + } f2fs_put_dnode(); unlock_out: if (create) { @@ -1808,16 +1824,19 @@ static int f2fs_write_data_pages(struct address_space *mapping, return 0; } -static void f2fs_write_failed(struct address_space *mapping, loff_t to) +static void f2fs_write_failed(struct address_space *mapping, loff_t to, + bool lock) { struct inode *inode = mapping->host; loff_t i_size = i_size_read(inode); if (to > i_size) { - down_write(_I(inode)->i_mmap_sem); + if (lock) + down_write(_I(inode)->i_mmap_sem); truncate_pagecache(inode, i_size); truncate_blocks(inode, i_size, true); - up_write(_I(inode)->i_mmap_sem); + if (lock) + up_write(_I(inode)->i_mmap_sem); } } @@ -2000,7 +2019,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, fail: f2fs_put_page(page, 1); - f2fs_write_failed(mapping, pos + len); + f2fs_write_failed(mapping, pos + len, true); return err; } @@ -2077,7 +2096,7 @@ static
[PATCH v7 1/1] f2fs: dax: implement direct access
From: Qiuyang Sun This patch implements Direct Access (DAX) in F2FS, including: - a mount option to choose whether to enable DAX or not - read/write and mmap of regular files in the DAX way - zero-out of unaligned partial blocks in the DAX way - garbage collection of DAX files, by mapping both old and new physical addresses of a data page into memory and copy data between them directly - incompatibility of DAX with inline data, atomic or volatile write, etc. Signed-off-by: Qiuyang Sun --- Changlog v6 -> v7: - Document the mount option "dax" for this feature in f2fs.txt - Minor cleanup in dax_move_data_page() --- Documentation/filesystems/f2fs.txt | 2 + fs/f2fs/data.c | 132 +++-- fs/f2fs/f2fs.h | 9 ++ fs/f2fs/file.c | 192 - fs/f2fs/gc.c | 105 +++- fs/f2fs/inline.c | 4 + fs/f2fs/inode.c| 8 +- fs/f2fs/namei.c| 5 + fs/f2fs/super.c| 15 +++ 9 files changed, 459 insertions(+), 13 deletions(-) diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 273ccb2..c86c421 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt @@ -164,6 +164,8 @@ io_bits=%u Set the bit size of write IO requests. It should be set with "mode=lfs". usrquota Enable plain user disk quota accounting. grpquota Enable plain group disk quota accounting. +daxUse direct access (no page cache). See + Documentation/filesystems/dax.txt. DEBUGFS ENTRIES diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 87c1f41..26b908a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -910,6 +910,15 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, err = -EIO; goto sync_out; } + /* +* If newly allocated blocks are to be zeroed out later, +* a single f2fs_map_blocks must not contain both old +* and new blocks at the same time. +*/ + if (flag == F2FS_GET_BLOCK_ZERO + && (map->m_flags & F2FS_MAP_MAPPED) + && !(map->m_flags & F2FS_MAP_NEW)) + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) { if (blkaddr == NULL_ADDR) { prealloc++; @@ -938,7 +947,8 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, blkaddr != NEW_ADDR) goto sync_out; } - } + } else if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) + goto sync_out; if (flag == F2FS_GET_BLOCK_PRE_AIO) goto skip; @@ -996,6 +1006,12 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, goto next_dnode; sync_out: + if (flag == F2FS_GET_BLOCK_ZERO && map->m_flags & F2FS_MAP_NEW) { + clean_bdev_aliases(inode->i_sb->s_bdev, + map->m_pblk, map->m_len); + err = sb_issue_zeroout(inode->i_sb, map->m_pblk, + map->m_len, GFP_NOFS); + } f2fs_put_dnode(); unlock_out: if (create) { @@ -1808,16 +1824,19 @@ static int f2fs_write_data_pages(struct address_space *mapping, return 0; } -static void f2fs_write_failed(struct address_space *mapping, loff_t to) +static void f2fs_write_failed(struct address_space *mapping, loff_t to, + bool lock) { struct inode *inode = mapping->host; loff_t i_size = i_size_read(inode); if (to > i_size) { - down_write(_I(inode)->i_mmap_sem); + if (lock) + down_write(_I(inode)->i_mmap_sem); truncate_pagecache(inode, i_size); truncate_blocks(inode, i_size, true); - up_write(_I(inode)->i_mmap_sem); + if (lock) + up_write(_I(inode)->i_mmap_sem); } } @@ -2000,7 +2019,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, fail: f2fs_put_page(page, 1); - f2fs_write_failed(mapping, pos + len); + f2fs_write_failed(mapping, pos + len, true); return err; } @@ -2077,7 +2096,7 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct