Hi Pengyang,

This incurs locking the node page twice, resulting in performance regression.
Please think about other way to improve the performance.

Thanks,

On 05/05, Hou Pengyang wrote:
> Currently, if we do get_node_of_data before f2fs_lock_op, there may be dead 
> lock
> as follows, where process A would be in infinite loop, and B will NOT be 
> awaked.
> 
> Process A(cp):            Process B:
> f2fs_lock_all(sbi)
>                         get_dnode_of_data <---- lock dn.node_page
> flush_nodes             f2fs_lock_op
> 
> However, in do_write_data_page path, we had better do get_node_of_data first, 
> since
> we can check IPU in prior and do IPU without f2fs_lock_op. It make senses for 
> our 
> current FSYNC IPU to avoid being blocked by cp. 
> 
> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
> ---
>  fs/f2fs/data.c | 38 +++++++++++++++++++++++++++-----------
>  fs/f2fs/f2fs.h |  1 +
>  fs/f2fs/node.c |  1 +
>  3 files changed, 29 insertions(+), 11 deletions(-)
> 
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 1254986..075d159 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1373,20 +1373,37 @@ int do_write_data_page(struct f2fs_io_info *fio)
>               }
>       }
>  
> -     if (fio->need_lock)
> -             f2fs_lock_op(fio->sbi);
> -
>       err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
> -     if (err)
> -             goto out;
> +     if (!err) {
> +             fio->old_blkaddr  = dn.data_blkaddr;
> +             /* This page is already truncated */
> +             if (fio->old_blkaddr == NULL_ADDR) {
> +                     ClearPageUptodate(page);
> +                     goto out_writepage;
> +             }
> +             unlock_page(dn.node_page);
> +             dn.node_page_locked = false;
> +     } else
> +             return err;
>  
> -     fio->old_blkaddr = dn.data_blkaddr;
> +     if (fio->need_lock)
> +             f2fs_lock_op(fio->sbi);
>  
> -     /* This page is already truncated */
> -     if (fio->old_blkaddr == NULL_ADDR) {
> -             ClearPageUptodate(page);
> -             goto out_writepage;
> +     if (!dn.node_page_locked) {
> +             /*
> +              * It is safe to lock_page here, since we've hold
> +              * reference of this page, but there may be conflict
> +              * with trucate/fallocate(FL_ZERO_RANGE/PUNCH_HOLE)
> +              * so after lock_page, we check dn->old_addr if is
> +              * NULL_ADDR.
> +              */
> +             lock_page(dn.node_page);
> +             fio->old_blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node);
> +             if (fio->old_blkaddr == NULL_ADDR) {
> +                     goto out_writepage;
> +             }
>       }
> +
>  got_it:
>       err = encrypt_one_page(fio);
>       if (err)
> @@ -1416,7 +1433,6 @@ int do_write_data_page(struct f2fs_io_info *fio)
>               set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
>  out_writepage:
>       f2fs_put_dnode(&dn);
> -out:
>       if (fio->need_lock)
>               f2fs_unlock_op(fio->sbi);
>       return err;
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index baefe37..2d50d7b 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -651,6 +651,7 @@ struct dnode_of_data {
>       nid_t nid;                      /* node id of the direct node block */
>       unsigned int ofs_in_node;       /* data offset in the node page */
>       bool inode_page_locked;         /* inode page is locked or not */
> +     bool node_page_locked;          /* dnode page is locked or not */
>       bool node_changed;              /* is node block changed */
>       char cur_level;                 /* level of hole node page */
>       char max_level;                 /* level of current page located */
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 98351a4..7cc6114 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -650,6 +650,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t 
> index, int mode)
>       dn->ofs_in_node = offset[level];
>       dn->node_page = npage[level];
>       dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
> +     dn->node_page_locked = true;
>       return 0;
>  
>  release_pages:
> -- 
> 2.10.1
> 
> 
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to