Miao Xie
2012-Dec-20 10:09 UTC
[PATCH RESEND] vfs: re-implement writeback_inodes_sb(_nr)_if_idle() and rename them
writeback_inodes_sb(_nr)_if_idle() is re-implemented by replacing down_read() with down_read_trylock() because - If ->s_umount is write locked, then the sb is not idle. That is writeback_inodes_sb(_nr)_if_idle() needn''t wait for the lock. - writeback_inodes_sb(_nr)_if_idle() grabs s_umount lock when it want to start writeback, it may bring us deadlock problem when doing umount. In order to fix the problem, ext4 and btrfs implemented their own writeback functions instead of writeback_inodes_sb(_nr)_if_idle(), but it introduced the redundant code, it is better to implement a new writeback_inodes_sb(_nr)_if_idle(). The name of these two functions is cumbersome, so rename them to try_to_writeback_inodes_sb(_nr). This idea came from Christoph Hellwig. Some code is from the patch of Kamal Mostafa. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> --- fs/btrfs/extent-tree.c | 20 +++----------------- fs/ext4/inode.c | 8 ++------ fs/fs-writeback.c | 45 ++++++++++++++++++++------------------------- include/linux/writeback.h | 6 +++--- 4 files changed, 28 insertions(+), 51 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index d133edf..994e18e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3689,20 +3689,6 @@ static int can_overcommit(struct btrfs_root *root, return 0; } -static int writeback_inodes_sb_nr_if_idle_safe(struct super_block *sb, - unsigned long nr_pages, - enum wb_reason reason) -{ - if (!writeback_in_progress(sb->s_bdi) && - down_read_trylock(&sb->s_umount)) { - writeback_inodes_sb_nr(sb, nr_pages, reason); - up_read(&sb->s_umount); - return 1; - } - - return 0; -} - /* * shrink metadata reservation for delalloc */ @@ -3735,9 +3721,9 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, while (delalloc_bytes && loops < 3) { max_reclaim = min(delalloc_bytes, to_reclaim); nr_pages = max_reclaim >> PAGE_CACHE_SHIFT; - writeback_inodes_sb_nr_if_idle_safe(root->fs_info->sb, - nr_pages, - WB_REASON_FS_FREE_SPACE); + try_to_writeback_inodes_sb_nr(root->fs_info->sb, + nr_pages, + WB_REASON_FS_FREE_SPACE); /* * We need to wait for the async pages to actually start before diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index b3c243b..f82d60e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2465,12 +2465,8 @@ static int ext4_nonda_switch(struct super_block *sb) /* * Start pushing delalloc when 1/2 of free blocks are dirty. */ - if (dirty_blocks && (free_blocks < 2 * dirty_blocks) && - !writeback_in_progress(sb->s_bdi) && - down_read_trylock(&sb->s_umount)) { - writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); - up_read(&sb->s_umount); - } + if (dirty_blocks && (free_blocks < 2 * dirty_blocks)) + try_to_writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); if (2 * free_blocks < 3 * dirty_blocks || free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 3e3422f..9a04ef2 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1314,7 +1314,6 @@ void writeback_inodes_sb_nr(struct super_block *sb, bdi_queue_work(sb->s_bdi, &work); wait_for_completion(&done); } -EXPORT_SYMBOL(writeback_inodes_sb_nr); /** * writeback_inodes_sb - writeback dirty inodes from given super_block @@ -1332,47 +1331,43 @@ void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) EXPORT_SYMBOL(writeback_inodes_sb); /** - * writeback_inodes_sb_if_idle - start writeback if none underway + * try_to_writeback_inodes_sb_nr - try to start writeback if none underway * @sb: the superblock - * @reason: reason why some writeback work was initiated + * @nr: the number of pages to write + * @reason: the reason of writeback * - * Invoke writeback_inodes_sb if no writeback is currently underway. + * Invoke writeback_inodes_sb_nr if no writeback is currently underway. * Returns 1 if writeback was started, 0 if not. */ -int writeback_inodes_sb_if_idle(struct super_block *sb, enum wb_reason reason) +int try_to_writeback_inodes_sb_nr(struct super_block *sb, + unsigned long nr, + enum wb_reason reason) { - if (!writeback_in_progress(sb->s_bdi)) { - down_read(&sb->s_umount); - writeback_inodes_sb(sb, reason); - up_read(&sb->s_umount); + if (writeback_in_progress(sb->s_bdi)) return 1; - } else + + if (!down_read_trylock(&sb->s_umount)) return 0; + + writeback_inodes_sb_nr(sb, nr, reason); + up_read(&sb->s_umount); + return 1; } -EXPORT_SYMBOL(writeback_inodes_sb_if_idle); +EXPORT_SYMBOL(try_to_writeback_inodes_sb_nr); /** - * writeback_inodes_sb_nr_if_idle - start writeback if none underway + * try_to_writeback_inodes_sb - try to start writeback if none underway * @sb: the superblock - * @nr: the number of pages to write * @reason: reason why some writeback work was initiated * - * Invoke writeback_inodes_sb if no writeback is currently underway. + * Implement by try_to_writeback_inodes_sb_nr() * Returns 1 if writeback was started, 0 if not. */ -int writeback_inodes_sb_nr_if_idle(struct super_block *sb, - unsigned long nr, - enum wb_reason reason) +int try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) { - if (!writeback_in_progress(sb->s_bdi)) { - down_read(&sb->s_umount); - writeback_inodes_sb_nr(sb, nr, reason); - up_read(&sb->s_umount); - return 1; - } else - return 0; + return try_to_writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason); } -EXPORT_SYMBOL(writeback_inodes_sb_nr_if_idle); +EXPORT_SYMBOL(try_to_writeback_inodes_sb); /** * sync_inodes_sb - sync sb inode pages diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 50c3e8f..ecdd0e0 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -87,9 +87,9 @@ int inode_wait(void *); void writeback_inodes_sb(struct super_block *, enum wb_reason reason); void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, enum wb_reason reason); -int writeback_inodes_sb_if_idle(struct super_block *, enum wb_reason reason); -int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr, - enum wb_reason reason); +int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason); +int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr, + enum wb_reason reason); void sync_inodes_sb(struct super_block *); long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, enum wb_reason reason); -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Sterba
2012-Dec-28 14:33 UTC
Re: [PATCH RESEND] vfs: re-implement writeback_inodes_sb(_nr)_if_idle() and rename them
On Thu, Dec 20, 2012 at 06:09:35PM +0800, Miao Xie wrote:> --- a/fs/fs-writeback.c > +++ b/fs/fs-writeback.c > @@ -1314,7 +1314,6 @@ void writeback_inodes_sb_nr(struct super_block *sb, > bdi_queue_work(sb->s_bdi, &work); > wait_for_completion(&done); > } > -EXPORT_SYMBOL(writeback_inodes_sb_nr);Why do you remove the export? writeback_inodes_sb is exported as well. Originally the _nr variant has been introduced for btrfs (3259f8bed2f0f57c2fdcdac1b510c3fa319ef97e) and there are no other users now, so from that point it would make sense. From the other side, the change is not strictly necessary for this patch and keeps the writeback API a bit more flexible. I vote for keeping it. Otherwise (for the btrfs part), Tested-by: David Sterba <dsterba@suse.cz> thanks, david -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Miao Xie
2013-Jan-10 03:24 UTC
Re: [PATCH RESEND] vfs: re-implement writeback_inodes_sb(_nr)_if_idle() and rename them
On Fri, 28 Dec 2012 15:33:38 +0100, David Sterba wrote:> On Thu, Dec 20, 2012 at 06:09:35PM +0800, Miao Xie wrote: >> --- a/fs/fs-writeback.c >> +++ b/fs/fs-writeback.c >> @@ -1314,7 +1314,6 @@ void writeback_inodes_sb_nr(struct super_block *sb, >> bdi_queue_work(sb->s_bdi, &work); >> wait_for_completion(&done); >> } >> -EXPORT_SYMBOL(writeback_inodes_sb_nr); > > Why do you remove the export? writeback_inodes_sb is exported as well.As you said below, there is no user now.> Originally the _nr variant has been introduced for btrfs > (3259f8bed2f0f57c2fdcdac1b510c3fa319ef97e) and there are no other users > now, so from that point it would make sense. From the other side, the > change is not strictly necessary for this patch and keeps the writeback > API a bit more flexible. I vote for keeping it.Maybe you are right, I''ll send out a new one.> Otherwise (for the btrfs part), > Tested-by: David Sterba <dsterba@suse.cz>Thanks for your test and review. Miao -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Miao Xie
2013-Jan-10 05:47 UTC
[PATCH V2] vfs: re-implement writeback_inodes_sb(_nr)_if_idle() and rename them
writeback_inodes_sb(_nr)_if_idle() is re-implemented by replacing down_read() with down_read_trylock() because - If ->s_umount is write locked, then the sb is not idle. That is writeback_inodes_sb(_nr)_if_idle() needn''t wait for the lock. - writeback_inodes_sb(_nr)_if_idle() grabs s_umount lock when it want to start writeback, it may bring us deadlock problem when doing umount. In order to fix the problem, ext4 and btrfs implemented their own writeback functions instead of writeback_inodes_sb(_nr)_if_idle(), but it introduced the redundant code, it is better to implement a new writeback_inodes_sb(_nr)_if_idle(). The name of these two functions is cumbersome, so rename them to try_to_writeback_inodes_sb(_nr). This idea came from Christoph Hellwig. Some code is from the patch of Kamal Mostafa. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> --- Changelog v1 -> v2: - do not remove EXPORT_SYMBOL of writeback_inodes_sb_br() --- fs/btrfs/extent-tree.c | 20 +++----------------- fs/ext4/inode.c | 8 ++------ fs/fs-writeback.c | 44 ++++++++++++++++++++------------------------ include/linux/writeback.h | 6 +++--- 4 files changed, 28 insertions(+), 50 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 521e9d4..f31abb1 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3689,20 +3689,6 @@ static int can_overcommit(struct btrfs_root *root, return 0; } -static int writeback_inodes_sb_nr_if_idle_safe(struct super_block *sb, - unsigned long nr_pages, - enum wb_reason reason) -{ - if (!writeback_in_progress(sb->s_bdi) && - down_read_trylock(&sb->s_umount)) { - writeback_inodes_sb_nr(sb, nr_pages, reason); - up_read(&sb->s_umount); - return 1; - } - - return 0; -} - /* * shrink metadata reservation for delalloc */ @@ -3735,9 +3721,9 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, while (delalloc_bytes && loops < 3) { max_reclaim = min(delalloc_bytes, to_reclaim); nr_pages = max_reclaim >> PAGE_CACHE_SHIFT; - writeback_inodes_sb_nr_if_idle_safe(root->fs_info->sb, - nr_pages, - WB_REASON_FS_FREE_SPACE); + try_to_writeback_inodes_sb_nr(root->fs_info->sb, + nr_pages, + WB_REASON_FS_FREE_SPACE); /* * We need to wait for the async pages to actually start before diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cbfe13b..5f6eef7 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2512,12 +2512,8 @@ static int ext4_nonda_switch(struct super_block *sb) /* * Start pushing delalloc when 1/2 of free blocks are dirty. */ - if (dirty_blocks && (free_blocks < 2 * dirty_blocks) && - !writeback_in_progress(sb->s_bdi) && - down_read_trylock(&sb->s_umount)) { - writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); - up_read(&sb->s_umount); - } + if (dirty_blocks && (free_blocks < 2 * dirty_blocks)) + try_to_writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); if (2 * free_blocks < 3 * dirty_blocks || free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 310972b..ad3cc46 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1332,47 +1332,43 @@ void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) EXPORT_SYMBOL(writeback_inodes_sb); /** - * writeback_inodes_sb_if_idle - start writeback if none underway + * try_to_writeback_inodes_sb_nr - try to start writeback if none underway * @sb: the superblock - * @reason: reason why some writeback work was initiated + * @nr: the number of pages to write + * @reason: the reason of writeback * - * Invoke writeback_inodes_sb if no writeback is currently underway. + * Invoke writeback_inodes_sb_nr if no writeback is currently underway. * Returns 1 if writeback was started, 0 if not. */ -int writeback_inodes_sb_if_idle(struct super_block *sb, enum wb_reason reason) +int try_to_writeback_inodes_sb_nr(struct super_block *sb, + unsigned long nr, + enum wb_reason reason) { - if (!writeback_in_progress(sb->s_bdi)) { - down_read(&sb->s_umount); - writeback_inodes_sb(sb, reason); - up_read(&sb->s_umount); + if (writeback_in_progress(sb->s_bdi)) return 1; - } else + + if (!down_read_trylock(&sb->s_umount)) return 0; + + writeback_inodes_sb_nr(sb, nr, reason); + up_read(&sb->s_umount); + return 1; } -EXPORT_SYMBOL(writeback_inodes_sb_if_idle); +EXPORT_SYMBOL(try_to_writeback_inodes_sb_nr); /** - * writeback_inodes_sb_nr_if_idle - start writeback if none underway + * try_to_writeback_inodes_sb - try to start writeback if none underway * @sb: the superblock - * @nr: the number of pages to write * @reason: reason why some writeback work was initiated * - * Invoke writeback_inodes_sb if no writeback is currently underway. + * Implement by try_to_writeback_inodes_sb_nr() * Returns 1 if writeback was started, 0 if not. */ -int writeback_inodes_sb_nr_if_idle(struct super_block *sb, - unsigned long nr, - enum wb_reason reason) +int try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) { - if (!writeback_in_progress(sb->s_bdi)) { - down_read(&sb->s_umount); - writeback_inodes_sb_nr(sb, nr, reason); - up_read(&sb->s_umount); - return 1; - } else - return 0; + return try_to_writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason); } -EXPORT_SYMBOL(writeback_inodes_sb_nr_if_idle); +EXPORT_SYMBOL(try_to_writeback_inodes_sb); /** * sync_inodes_sb - sync sb inode pages diff --git a/include/linux/writeback.h b/include/linux/writeback.h index b82a83a..9a9367c 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -87,9 +87,9 @@ int inode_wait(void *); void writeback_inodes_sb(struct super_block *, enum wb_reason reason); void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, enum wb_reason reason); -int writeback_inodes_sb_if_idle(struct super_block *, enum wb_reason reason); -int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr, - enum wb_reason reason); +int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason); +int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr, + enum wb_reason reason); void sync_inodes_sb(struct super_block *); long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, enum wb_reason reason); -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jan Kara
2013-Jan-11 20:12 UTC
Re: [PATCH V2] vfs: re-implement writeback_inodes_sb(_nr)_if_idle() and rename them
On Thu 10-01-13 13:47:57, Miao Xie wrote:> writeback_inodes_sb(_nr)_if_idle() is re-implemented by replacing down_read() > with down_read_trylock() because > - If ->s_umount is write locked, then the sb is not idle. That is > writeback_inodes_sb(_nr)_if_idle() needn''t wait for the lock. > - writeback_inodes_sb(_nr)_if_idle() grabs s_umount lock when it want to start > writeback, it may bring us deadlock problem when doing umount. In order to > fix the problem, ext4 and btrfs implemented their own writeback functions > instead of writeback_inodes_sb(_nr)_if_idle(), but it introduced the redundant > code, it is better to implement a new writeback_inodes_sb(_nr)_if_idle(). > > The name of these two functions is cumbersome, so rename them to > try_to_writeback_inodes_sb(_nr). > > This idea came from Christoph Hellwig. > Some code is from the patch of Kamal Mostafa.The patch looks good. Thanks! You can add: Reviewed-by: Jan Kara <jack@suse.cz> BTW, since changes to filesystems are minimal, maybe Fengguang can take the patch through his writeback tree? Fengguang? Honza> > Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> > --- > Changelog v1 -> v2: > - do not remove EXPORT_SYMBOL of writeback_inodes_sb_br() > --- > fs/btrfs/extent-tree.c | 20 +++----------------- > fs/ext4/inode.c | 8 ++------ > fs/fs-writeback.c | 44 ++++++++++++++++++++------------------------ > include/linux/writeback.h | 6 +++--- > 4 files changed, 28 insertions(+), 50 deletions(-) > > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > index 521e9d4..f31abb1 100644 > --- a/fs/btrfs/extent-tree.c > +++ b/fs/btrfs/extent-tree.c > @@ -3689,20 +3689,6 @@ static int can_overcommit(struct btrfs_root *root, > return 0; > } > > -static int writeback_inodes_sb_nr_if_idle_safe(struct super_block *sb, > - unsigned long nr_pages, > - enum wb_reason reason) > -{ > - if (!writeback_in_progress(sb->s_bdi) && > - down_read_trylock(&sb->s_umount)) { > - writeback_inodes_sb_nr(sb, nr_pages, reason); > - up_read(&sb->s_umount); > - return 1; > - } > - > - return 0; > -} > - > /* > * shrink metadata reservation for delalloc > */ > @@ -3735,9 +3721,9 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig, > while (delalloc_bytes && loops < 3) { > max_reclaim = min(delalloc_bytes, to_reclaim); > nr_pages = max_reclaim >> PAGE_CACHE_SHIFT; > - writeback_inodes_sb_nr_if_idle_safe(root->fs_info->sb, > - nr_pages, > - WB_REASON_FS_FREE_SPACE); > + try_to_writeback_inodes_sb_nr(root->fs_info->sb, > + nr_pages, > + WB_REASON_FS_FREE_SPACE); > > /* > * We need to wait for the async pages to actually start before > diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c > index cbfe13b..5f6eef7 100644 > --- a/fs/ext4/inode.c > +++ b/fs/ext4/inode.c > @@ -2512,12 +2512,8 @@ static int ext4_nonda_switch(struct super_block *sb) > /* > * Start pushing delalloc when 1/2 of free blocks are dirty. > */ > - if (dirty_blocks && (free_blocks < 2 * dirty_blocks) && > - !writeback_in_progress(sb->s_bdi) && > - down_read_trylock(&sb->s_umount)) { > - writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); > - up_read(&sb->s_umount); > - } > + if (dirty_blocks && (free_blocks < 2 * dirty_blocks)) > + try_to_writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); > > if (2 * free_blocks < 3 * dirty_blocks || > free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { > diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c > index 310972b..ad3cc46 100644 > --- a/fs/fs-writeback.c > +++ b/fs/fs-writeback.c > @@ -1332,47 +1332,43 @@ void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) > EXPORT_SYMBOL(writeback_inodes_sb); > > /** > - * writeback_inodes_sb_if_idle - start writeback if none underway > + * try_to_writeback_inodes_sb_nr - try to start writeback if none underway > * @sb: the superblock > - * @reason: reason why some writeback work was initiated > + * @nr: the number of pages to write > + * @reason: the reason of writeback > * > - * Invoke writeback_inodes_sb if no writeback is currently underway. > + * Invoke writeback_inodes_sb_nr if no writeback is currently underway. > * Returns 1 if writeback was started, 0 if not. > */ > -int writeback_inodes_sb_if_idle(struct super_block *sb, enum wb_reason reason) > +int try_to_writeback_inodes_sb_nr(struct super_block *sb, > + unsigned long nr, > + enum wb_reason reason) > { > - if (!writeback_in_progress(sb->s_bdi)) { > - down_read(&sb->s_umount); > - writeback_inodes_sb(sb, reason); > - up_read(&sb->s_umount); > + if (writeback_in_progress(sb->s_bdi)) > return 1; > - } else > + > + if (!down_read_trylock(&sb->s_umount)) > return 0; > + > + writeback_inodes_sb_nr(sb, nr, reason); > + up_read(&sb->s_umount); > + return 1; > } > -EXPORT_SYMBOL(writeback_inodes_sb_if_idle); > +EXPORT_SYMBOL(try_to_writeback_inodes_sb_nr); > > /** > - * writeback_inodes_sb_nr_if_idle - start writeback if none underway > + * try_to_writeback_inodes_sb - try to start writeback if none underway > * @sb: the superblock > - * @nr: the number of pages to write > * @reason: reason why some writeback work was initiated > * > - * Invoke writeback_inodes_sb if no writeback is currently underway. > + * Implement by try_to_writeback_inodes_sb_nr() > * Returns 1 if writeback was started, 0 if not. > */ > -int writeback_inodes_sb_nr_if_idle(struct super_block *sb, > - unsigned long nr, > - enum wb_reason reason) > +int try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason) > { > - if (!writeback_in_progress(sb->s_bdi)) { > - down_read(&sb->s_umount); > - writeback_inodes_sb_nr(sb, nr, reason); > - up_read(&sb->s_umount); > - return 1; > - } else > - return 0; > + return try_to_writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason); > } > -EXPORT_SYMBOL(writeback_inodes_sb_nr_if_idle); > +EXPORT_SYMBOL(try_to_writeback_inodes_sb); > > /** > * sync_inodes_sb - sync sb inode pages > diff --git a/include/linux/writeback.h b/include/linux/writeback.h > index b82a83a..9a9367c 100644 > --- a/include/linux/writeback.h > +++ b/include/linux/writeback.h > @@ -87,9 +87,9 @@ int inode_wait(void *); > void writeback_inodes_sb(struct super_block *, enum wb_reason reason); > void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, > enum wb_reason reason); > -int writeback_inodes_sb_if_idle(struct super_block *, enum wb_reason reason); > -int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr, > - enum wb_reason reason); > +int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason); > +int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr, > + enum wb_reason reason); > void sync_inodes_sb(struct super_block *); > long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, > enum wb_reason reason); > -- > 1.7.11.7 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/-- Jan Kara <jack@suse.cz> SUSE Labs, CR
Fengguang Wu
2013-Jan-12 02:54 UTC
Re: [PATCH V2] vfs: re-implement writeback_inodes_sb(_nr)_if_idle() and rename them
On Fri, Jan 11, 2013 at 09:12:11PM +0100, Jan Kara wrote:> On Thu 10-01-13 13:47:57, Miao Xie wrote: > > writeback_inodes_sb(_nr)_if_idle() is re-implemented by replacing down_read() > > with down_read_trylock() because > > - If ->s_umount is write locked, then the sb is not idle. That is > > writeback_inodes_sb(_nr)_if_idle() needn''t wait for the lock. > > - writeback_inodes_sb(_nr)_if_idle() grabs s_umount lock when it want to start > > writeback, it may bring us deadlock problem when doing umount. In order to > > fix the problem, ext4 and btrfs implemented their own writeback functions > > instead of writeback_inodes_sb(_nr)_if_idle(), but it introduced the redundant > > code, it is better to implement a new writeback_inodes_sb(_nr)_if_idle(). > > > > The name of these two functions is cumbersome, so rename them to > > try_to_writeback_inodes_sb(_nr). > > > > This idea came from Christoph Hellwig. > > Some code is from the patch of Kamal Mostafa. > The patch looks good. Thanks! You can add: > Reviewed-by: Jan Kara <jack@suse.cz> > > BTW, since changes to filesystems are minimal, maybe Fengguang can take > the patch through his writeback tree? Fengguang?OK, done. The patch looks good, thanks! Fengguang