Re: [PATCH v7 1/1] f2fs: dax: implement direct access

2017-07-18 Thread Sun Qiuyang

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 

Re: [PATCH v7 1/1] f2fs: dax: implement direct access

2017-07-18 Thread Sun Qiuyang

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

2017-07-18 Thread Jaegeuk Kim
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

2017-07-18 Thread Jaegeuk Kim
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

2017-07-18 Thread Chao Yu
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

2017-07-18 Thread Chao Yu
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

2017-07-17 Thread sunqiuyang
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 

[PATCH v7 1/1] f2fs: dax: implement direct access

2017-07-17 Thread sunqiuyang
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