Hi Jaegeuk, Pengyang,

On 2017/4/26 9:27, Jaegeuk Kim wrote:
> On 04/25, Jaegeuk Kim wrote:
>> Hi Pengyang,
>>
>> This makes xfstests/generic/013 stuck on fsstress.
> 
> Oh, it seems lock inversion problem between f2fs_lock_op and 
> get_dnode_of_data.
> The basic rule is get_dnode_of_data is covered by f2fs_lock_op.
> I'll drop this patch at this moment.

Seems we need to change as below?

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9ec9eace05df..f3564a948293 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1364,12 +1364,17 @@ int do_write_data_page(struct f2fs_io_info *fio)

                if (valid_ipu_blkaddr(fio)) {
                        ipu_force = true;
+                       fio->need_lock = false;
                        goto got_it;
                }
        }
+
+       if (fio->need_lock)
+               f2fs_lock_op(fio->sbi);
+
        err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
        if (err)
-               return err;
+               goto out;

        fio->old_blkaddr = dn.data_blkaddr;

@@ -1400,17 +1405,16 @@ int do_write_data_page(struct f2fs_io_info *fio)
        }

        /* LFS mode write path */
-       if (!fio->cp_rwsem_locked)
-               f2fs_lock_op(fio->sbi);
        write_data_page(&dn, fio);
        trace_f2fs_do_write_data_page(page, OPU);
        set_inode_flag(inode, FI_APPEND_WRITE);
        if (page->index == 0)
                set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
-       if (!fio->cp_rwsem_locked)
-               f2fs_unlock_op(fio->sbi);
 out_writepage:
        f2fs_put_dnode(&dn);
+out:
+       if (fio->need_lock)
+               f2fs_unlock_op(fio->sbi);
        return err;
 }

@@ -1435,7 +1439,7 @@ static int __write_data_page(struct page *page, bool 
*submitted,
                .page = page,
                .encrypted_page = NULL,
                .submitted = false,
-               .cp_rwsem_locked = true,
+               .need_lock = true,
        };

        trace_f2fs_writepage(page, DATA);
@@ -1471,6 +1475,7 @@ static int __write_data_page(struct page *page, bool 
*submitted,

        /* Dentry blocks are controlled by checkpoint */
        if (S_ISDIR(inode->i_mode)) {
+               fio.need_lock = false,
                err = do_write_data_page(&fio);
                goto done;
        }
@@ -1488,13 +1493,12 @@ static int __write_data_page(struct page *page, bool 
*submitted,
                if (!err)
                        goto out;
        }
-       f2fs_lock_op(sbi);
+
        if (err == -EAGAIN)
                err = do_write_data_page(&fio);
        if (F2FS_I(inode)->last_disk_size < psize)
                F2FS_I(inode)->last_disk_size = psize;
-       if (fio.cp_rwsem_locked)
-               f2fs_unlock_op(sbi);
+
 done:
        if (err && err != -ENOENT)
                goto redirty_out;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index bf48213642ab..95fb347e7abe 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -802,7 +802,7 @@ struct f2fs_io_info {
        struct page *page;      /* page to be written */
        struct page *encrypted_page;    /* encrypted page */
        bool submitted;         /* indicate IO submission */
-       bool cp_rwsem_locked;   /* indicate cp_rwsem is held */
+       bool need_lock;         /* indicate we need to lock cp_rwsem */
 };

 #define is_read_io(rw) ((rw) == READ)
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index c2a9ae8397d3..ffabdcf52b85 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -717,6 +717,7 @@ static void move_data_page(struct inode *inode, block_t 
bidx, int gc_type,
                        .old_blkaddr = NULL_ADDR,
                        .page = page,
                        .encrypted_page = NULL,
+                       .need_lock = false,
                };
                bool is_dirty = PageDirty(page);
                int err;
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index ee9b56da0b7e..c155adbac8fc 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -293,6 +293,7 @@ static int __commit_inmem_pages(struct inode *inode,
                .op_flags = REQ_SYNC | REQ_PRIO,
                .old_blkaddr = NULL_ADDR,
                .encrypted_page = NULL,
+               .need_lock = false,
        };
        pgoff_t last_idx = ULONG_MAX;
        int err = 0;


> 
> Thanks,
> 
>>
>> Thanks,
>>
>> On 04/25, Hou Pengyang wrote:
>>> IPU checking is under f2fs_lock_op, as a result, some IPU page(such as 
>>> fsync/fdatasync IPU)
>>> may be blocked by a long time cp.
>>>
>>> This patch fix this by doing IPU checking before f2fs_lock_op, so fsync IPU 
>>> could go along with cp.
>>>
>>> Suggested-by: He Yunlei <heyun...@huawei.com>
>>> Signed-off-by: Hou Pengyang <houpengy...@huawei.com>
>>> ---
>>>  fs/f2fs/data.c    | 14 +++++++-------
>>>  fs/f2fs/gc.c      |  1 +
>>>  fs/f2fs/segment.c |  1 +
>>>  3 files changed, 9 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
>>> index 183a426..9bf9c7d 100644
>>> --- a/fs/f2fs/data.c
>>> +++ b/fs/f2fs/data.c
>>> @@ -1380,19 +1380,20 @@ int do_write_data_page(struct f2fs_io_info *fio)
>>>      * it had better in-place writes for updated data.
>>>      */
>>>     if (need_inplace_update(fio)) {
>>> -           f2fs_bug_on(fio->sbi, !fio->cp_rwsem_locked);
>>> -           f2fs_unlock_op(fio->sbi);
>>> -           fio->cp_rwsem_locked = false;
>>> -
>>> +           f2fs_bug_on(fio->sbi, fio->cp_rwsem_locked);
>>>             err = rewrite_data_page(fio);
>>>             trace_f2fs_do_write_data_page(fio->page, IPU);
>>>             set_inode_flag(inode, FI_UPDATE_WRITE);
>>>     } else {
>>> +           if (!fio->cp_rwsem_locked)
>>> +                   f2fs_lock_op(fio->sbi);
>>>             write_data_page(&dn, fio);
>>>             trace_f2fs_do_write_data_page(page, OPU);
>>>             set_inode_flag(inode, FI_APPEND_WRITE);
>>>             if (page->index == 0)
>>>                     set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
>>> +           if (!fio->cp_rwsem_locked)
>>> +                   f2fs_unlock_op(fio->sbi);
>>>     }
>>>  out_writepage:
>>>     f2fs_put_dnode(&dn);
>>> @@ -1473,13 +1474,12 @@ static int __write_data_page(struct page *page, 
>>> bool *submitted,
>>>             if (!err)
>>>                     goto out;
>>>     }
>>> -   f2fs_lock_op(sbi);
>>> +
>>> +   fio.cp_rwsem_locked = false;
>>>     if (err == -EAGAIN)
>>>             err = do_write_data_page(&fio);
>>>     if (F2FS_I(inode)->last_disk_size < psize)
>>>             F2FS_I(inode)->last_disk_size = psize;
>>> -   if (fio.cp_rwsem_locked)
>>> -           f2fs_unlock_op(sbi);
>>>  done:
>>>     if (err && err != -ENOENT)
>>>             goto redirty_out;
>>> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
>>> index e034857..b32cc30 100644
>>> --- a/fs/f2fs/gc.c
>>> +++ b/fs/f2fs/gc.c
>>> @@ -715,6 +715,7 @@ static void move_data_page(struct inode *inode, block_t 
>>> bidx, int gc_type,
>>>                     .old_blkaddr = NULL_ADDR,
>>>                     .page = page,
>>>                     .encrypted_page = NULL,
>>> +                   .cp_rwsem_locked = true,
>>>             };
>>>             bool is_dirty = PageDirty(page);
>>>             int err;
>>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>>> index 9f86b98..463a77b 100644
>>> --- a/fs/f2fs/segment.c
>>> +++ b/fs/f2fs/segment.c
>>> @@ -293,6 +293,7 @@ static int __commit_inmem_pages(struct inode *inode,
>>>             .op_flags = REQ_SYNC | REQ_PRIO,
>>>             .old_blkaddr = NULL_ADDR,
>>>             .encrypted_page = NULL,
>>> +           .cp_rwsem_locked = true,
>>>     };
>>>     pgoff_t last_idx = ULONG_MAX;
>>>     int err = 0;
>>> -- 
>>> 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
> 
> ------------------------------------------------------------------------------
> 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