Hi Chao,

On 2018/1/25 16:18, Chao Yu wrote:
> On 2018/1/25 15:05, Gaoxiang (OS) wrote:
>> Previously, we attempt to flush the whole cp pack in a single bio,
>> however, when suddenly powering off at this time, we could get into
>> an extreme scenario that cp page1 and cp page2 are updated and
>> latest, but payload or current summaries are still partially outdated.
>> (see reliable write in the UFS specification)
>>
>> This patch submits the whole cp pack except cp page2 at first,
>> and then writes the cp page2 with an extra independent
>> bio with pre-io barrier.
>>
>> Signed-off-by: Gao Xiang <[email protected]>
>> ---
>> Change log from v1:
>>    - Apply the review comments from Chao
>>    - time data from "finish block_ops" to " finish checkpoint" (tested on 
>> ARM64 with TOSHIBA 128GB UFS):
>>       Before patch: 0.002273  0.001973  0.002789  0.005159  0.002050
>>       After patch: 0.002502  0.001624  0.002487  0.003049  0.002696
> 
> Looks not very stable.
> 
The raw time is as follows, actually I think the time depends on the CPU 
, CPU schedule and some other conditions...

We drop REQ_PREFLUSH and REQ_FUA in the first bio and the second bio is
only 4k..  It would not have obvious performance difference, I think.

before:
    kworker/u16:3-220   [003] ...1   378.093580: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:3-220   [003] ...1   378.095468: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:3-220   [003] ...1   378.097741: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (1)
    kworker/u16:1-97    [003] ...1   438.190720: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-97    [003] ...1   438.192693: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-97    [003] ...1   438.195540: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (2)
    kworker/u16:4-238   [001] ...1   498.301875: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:4-238   [001] ...1   498.304664: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:4-238   [001] ...1   498.308997: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (3)
    kworker/u16:4-238   [002] ...1   558.414151: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:4-238   [002] ...1   558.417236: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:4-238   [002] ...1   558.422395: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (4)
    kworker/u16:4-238   [001] ...1   618.525854: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:4-238   [001] ...1   618.527882: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:4-238   [000] ...1   618.529932: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (5)
    kworker/u16:4-238   [002] ...1   678.639271: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:4-238   [002] ...1   678.644787: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:4-238   [003] ...1   678.651480: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (6)
    kworker/u16:1-97    [002] ...1   738.765589: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-97    [002] ...1   738.767638: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-97    [000] ...1   738.770752: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (7)
    kworker/u16:4-238   [003] ...1   798.895281: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:4-238   [003] ...1   798.897615: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:4-238   [001] ...1   798.902006: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (8)
    kworker/u16:1-97    [003] ...1   859.021172: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-97    [003] ...1   859.022934: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-97    [003] ...1   859.024095: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (9)
    kworker/u16:3-220   [002] ...1   919.133620: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:3-220   [002] ...1   919.135558: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:3-220   [002] ...1   919.137182: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (10)

after:
    kworker/u16:3-222   [000] ...1   137.820152: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:3-222   [000] ...1   137.822471: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:3-222   [000] ...1   137.824973: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (1)
    kworker/u16:1-96    [002] ...1   197.917060: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-96    [002] ...1   197.919031: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-96    [002] ...1   197.920655: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (2)
    kworker/u16:1-96    [002] ...1   258.013014: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-96    [002] ...1   258.014914: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-96    [002] ...1   258.017401: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (3)
    kworker/u16:0-6     [002] ...1   318.109930: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:0-6     [002] ...1   318.111908: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:0-6     [002] ...1   318.114957: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (4)
    kworker/u16:1-96    [003] ...1   378.222490: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-96    [003] ...1   378.224729: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-96    [002] ...1   378.227425: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (5)
    kworker/u16:1-96    [001] ...1   438.334204: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-96    [001] ...1   438.337002: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-96    [001] ...1   438.341479: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (6)
    kworker/u16:1-96    [002] ...1   498.462207: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:1-96    [002] ...1   498.465213: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:1-96    [003] ...1   498.469858: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (7)
    kworker/u16:0-6     [003] ...1   558.589039: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:0-6     [003] ...1   558.591138: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:0-6     [002] ...1   558.594847: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (8)
    kworker/u16:3-222   [003] ...1   618.702535: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:3-222   [003] ...1   618.708222: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:3-222   [003] ...1   618.724619: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (9)
    kworker/u16:3-222   [002] ...1   678.830550: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = start block_ops
    kworker/u16:3-222   [002] ...1   678.832785: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish block_ops
    kworker/u16:3-222   [002] ...1   678.835356: f2fs_write_checkpoint: 
dev = (259,44), checkpoint for Sync, state = finish checkpoint (10)
>>   fs/f2fs/checkpoint.c | 41 ++++++++++++++++++++++++++++++++++++-----
>>   1 file changed, 36 insertions(+), 5 deletions(-)
>>
>> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
>> index 14d2fed..70deb09 100644
>> --- a/fs/f2fs/checkpoint.c
>> +++ b/fs/f2fs/checkpoint.c
>> @@ -300,6 +300,36 @@ static int f2fs_write_meta_pages(struct address_space 
>> *mapping,
>>      return 0;
>>   }
>>   
>> +static void commit_checkpoint_with_barrier(struct f2fs_sb_info *sbi,
> 
> Minor, {commit,sync}_checkpoint will be OK to me, since we will decide to
> keep barrier in more deep places according to NOBARRIER mount option,
> instead of this function.
OK, I agree.

> 
>> +    void *src, block_t blk_addr)
>> +{
>> +    struct writeback_control wbc = {
>> +            .for_reclaim = 0,
>> +    };
>> +    struct page *page = grab_meta_page(sbi, blk_addr);
>> +    int err;
>> +
>> +    memcpy(page_address(page), src, PAGE_SIZE);
>> +    set_page_dirty(page);
>> +
>> +    f2fs_wait_on_page_writeback(page, META, true);
>> +    BUG_ON(PageWriteback(page));
>> +    if (unlikely(!clear_page_dirty_for_io(page)))
>> +            BUG();
> 
> f2fs_bug_on(sbi, PageWriteback(page));
Will fix.

> f2fs_bug_on(sbi, unlikely(!clear_page_dirty_for_io(page)));
>

I attempt to use
if (unlikely(!clear_page_dirty_for_io(page))
     f2fs_bug_on(1);
since It is better to contain judgement only for assert-like functions 
(In case that clear_page_dirty_for_io could be omited by changing BUG_ON 
definition in the future).

>> +
>> +    /* writeout cp page2 */
> 
> Please keep defined terms as the same in all places:
> 
> s/cp page2/cp pack 2 page
> 
>> +    err = __f2fs_write_meta_page(page, &wbc, FS_CP_META_IO);
>> +    if (err) {
>> +            f2fs_put_page(page, 1);
>> +            f2fs_stop_checkpoint(sbi, false);
>> +            return;
> 
> How about f2fs_bug_on(sbi, err), since we should not fail in
> __f2fs_write_meta_page, right?
OK, will fix in that way.

> 
>> +    }
>> +    f2fs_put_page(page, 0);
>> +
>> +    /* submit checkpoint with barrier */
>> +    f2fs_submit_merged_write(sbi, META_FLUSH);
>> +}
>> +
>>   long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
>>                              long nr_to_write, enum iostat_type io_type)
>>   {
>> @@ -1297,9 +1327,6 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, 
>> struct cp_control *cpc)
>>              start_blk += NR_CURSEG_NODE_TYPE;
>>      }
>>   
>> -    /* writeout checkpoint block */
>> -    update_meta_page(sbi, ckpt, start_blk);
>> -
>>      /* wait for previous submitted node/meta pages writeback */
>>      wait_on_all_pages_writeback(sbi);
>>   
>> @@ -1313,12 +1340,16 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, 
>> struct cp_control *cpc)
>>      sbi->last_valid_block_count = sbi->total_valid_block_count;
>>      percpu_counter_set(&sbi->alloc_valid_block_count, 0);
>>   
>> -    /* Here, we only have one bio having CP pack */
>> -    sync_meta_pages(sbi, META_FLUSH, LONG_MAX, FS_CP_META_IO);
>> +    /* Here, we have one bio having CP pack except cp page2 */
>> +    sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
>>   
>>      /* wait for previous submitted meta pages writeback */
>>      wait_on_all_pages_writeback(sbi);
> 
> /* wait for previous submitted meta pages writeback */
> if (!test_opt(sbi, NOBARRIER)
>       wait_on_all_pages_writeback(sbi);
> 
OK.

Thanks,

> Thanks,
> 
>>   
>> +    /* barrier and flush checkpoint cp page2 */
>> +    commit_checkpoint_with_barrier(sbi, ckpt, start_blk);
>> +    wait_on_all_pages_writeback(sbi);
>> +
>>      release_ino_entry(sbi, false);
>>   
>>      if (unlikely(f2fs_cp_error(sbi)))
>>
> 

------------------------------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to