From: Andrew Morton <akpm@linux-foundation.org>
To: Artem Bityutskiy <dedekind1@gmail.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>,
LKML <linux-kernel@vger.kernel.org>,
Jens Axboe <jens.axboe@oracle.com>,
linux-fsdevel@vger.kernel.org
Subject: Re: [PATCHv4 17/17] writeback: lessen sync_supers wakeup count
Date: Fri, 28 May 2010 13:29:53 -0700 [thread overview]
Message-ID: <20100528132953.7af88c08.akpm@linux-foundation.org> (raw)
In-Reply-To: <1274795352-3551-18-git-send-email-dedekind1@gmail.com>
On Tue, 25 May 2010 16:49:12 +0300
Artem Bityutskiy <dedekind1@gmail.com> wrote:
> From: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
>
> The 'sync_supers' thread wakes up every 5 seconds (by default) and
> writes back all super blocks. It keeps waking up even if there
> are no dirty super-blocks. For many file-systems the superblock
> becomes dirty very rarely, if ever, so 'sync_supers' does not do
> anything most of the time.
>
> This patch improves 'sync_supers' and makes sleep if all superblocks
> are clean and there is nothing to do. This helps saving the power.
> This optimization is important for small battery-powered devices.
>
> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
> ---
> include/linux/fs.h | 5 +----
> mm/backing-dev.c | 36 +++++++++++++++++++++++++++++++++++-
> 2 files changed, 36 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index c2ddeee..2d2560b 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1786,10 +1786,7 @@ extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
> * Note, VFS does not provide any serialization for the super block clean/dirty
> * state changes, file-systems should take care of this.
> */
> -static inline void mark_sb_dirty(struct super_block *sb)
> -{
> - sb->s_dirty = 1;
> -}
> +void mark_sb_dirty(struct super_block *sb);
> static inline void mark_sb_clean(struct super_block *sb)
> {
> sb->s_dirty = 0;
> diff --git a/mm/backing-dev.c b/mm/backing-dev.c
> index 660a87a..14f3eb7 100644
> --- a/mm/backing-dev.c
> +++ b/mm/backing-dev.c
> @@ -45,6 +45,8 @@ LIST_HEAD(bdi_pending_list);
>
> static struct task_struct *sync_supers_tsk;
> static struct timer_list sync_supers_timer;
> +static int supers_timer_armed;
This thing's a bit ugly.
> +static DEFINE_SPINLOCK(supers_timer_lock);
>
> static int bdi_sync_supers(void *);
> static void sync_supers_timer_fn(unsigned long);
> @@ -355,6 +357,11 @@ static void bdi_flush_io(struct backing_dev_info *bdi)
> * or we risk deadlocking on ->s_umount. The longer term solution would be
> * to implement sync_supers_bdi() or similar and simply do it from the
> * bdi writeback tasks individually.
> + *
> + * Historically this thread woke up periodically, regardless of whether
> + * there was any dirty superblock. However, nowadays it is optimized to
> + * wake up only when there is something to synchronize - this helps to save
> + * power.
> */
> static int bdi_sync_supers(void *unused)
> {
> @@ -364,10 +371,24 @@ static int bdi_sync_supers(void *unused)
> set_current_state(TASK_INTERRUPTIBLE);
> schedule();
>
> + spin_lock(&supers_timer_lock);
> + /* Indicate that 'sync_supers' is in progress */
> + supers_timer_armed = -1;
> + spin_unlock(&supers_timer_lock);
> +
> /*
> * Do this periodically, like kupdated() did before.
> */
> sync_supers();
> +
> + spin_lock(&supers_timer_lock);
> + if (supers_timer_armed == 1)
> + /* A super block was marked as dirty meanwhile */
> + bdi_arm_supers_timer();
> + else
> + /* No more dirty superblocks - we've synced'em all */
> + supers_timer_armed = 0;
> + spin_unlock(&supers_timer_lock);
> }
I suspect the spinlock could be removed if you switched to bitops:
test_and_set_bit(0, supers_timer_armed);
Ahother possibility is to nuke supers_timer_armed() and use
timer_pending(), mod_timer(), etc directly.
> return 0;
> @@ -387,9 +408,22 @@ void bdi_arm_supers_timer(void)
> static void sync_supers_timer_fn(unsigned long unused)
> {
> wake_up_process(sync_supers_tsk);
> - bdi_arm_supers_timer();
> }
>
> +void mark_sb_dirty(struct super_block *sb)
> +{
> + sb->s_dirty = 1;
> +
> + spin_lock(&supers_timer_lock);
> + if (!supers_timer_armed) {
> + bdi_arm_supers_timer();
> + supers_timer_armed = 1;
> + } else if (supers_timer_armed == -1)
> + supers_timer_armed = 1;
> + spin_unlock(&supers_timer_lock);
> +}
> +EXPORT_SYMBOL(mark_sb_dirty);
This looks inefficient. Could we not do
void mark_sb_dirty(struct super_block *sb)
{
sb->s_dirty = 1;
if (!supers_timer_armed) {
spin_lock(&supers_timer_lock);
if (!supers_timer_armed) {
bdi_arm_supers_timer();
supers_timer_armed = 1;
}
} else if (supers_timer_armed == -1)
spin_lock(&supers_timer_lock);
if (supers_timer_armed == -1)
supers_timer_armed = 1;
spin_unlock(&supers_timer_lock);
}
}
I didn't try very hard there, but you get the idea: examine the state
before taking that expensive global spinlock, so we only end up taking
the lock once per five seconds, rather than once per possible
superblock dirtying. That's like a six-orders-of-magnitude reduction
in locking frequency, which is worth putting some effort into.
next prev parent reply other threads:[~2010-05-28 20:30 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-25 13:48 [PATCHv4 00/17] kill unnecessary SB sync wake-ups Artem Bityutskiy
2010-05-25 13:48 ` [PATCHv4 01/17] VFS: introduce helpers for the s_dirty flag Artem Bityutskiy
2010-05-28 20:23 ` Andrew Morton
2010-05-28 21:14 ` Al Viro
2010-05-28 21:17 ` Andrew Morton
2010-05-29 8:11 ` Artem Bityutskiy
2010-05-29 8:11 ` Artem Bityutskiy
2010-06-09 15:44 ` tytso
2010-06-09 15:49 ` Artem Bityutskiy
2010-06-09 15:49 ` Artem Bityutskiy
2010-06-09 16:31 ` Andrew Morton
2010-06-09 22:33 ` Al Viro
2010-05-29 7:59 ` Artem Bityutskiy
2010-05-29 7:59 ` Artem Bityutskiy
2010-05-25 13:48 ` [PATCHv4 02/17] AFFS: do not manipulate s_dirt directly Artem Bityutskiy
2010-05-25 13:48 ` [PATCHv4 03/17] BFS: " Artem Bityutskiy
2010-05-25 13:48 ` [PATCHv4 04/17] BTRFS: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 05/17] EXOFS: " Artem Bityutskiy
2010-05-26 15:12 ` Boaz Harrosh
2010-05-25 13:49 ` [PATCHv4 06/17] EXT2: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 07/17] EXT4: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 08/17] FAT: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 09/17] HFS: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 10/17] HFSPLUS: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 11/17] JFFS2: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 12/17] reiserfs: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 13/17] SYSV: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 14/17] UDF: " Artem Bityutskiy
2010-05-25 14:06 ` Jan Kara
2010-05-25 13:49 ` [PATCHv4 15/17] UFS: " Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 16/17] VFS: rename s_dirt to s_dirty Artem Bityutskiy
2010-05-25 13:49 ` [PATCHv4 17/17] writeback: lessen sync_supers wakeup count Artem Bityutskiy
2010-05-27 6:50 ` Al Viro
2010-05-27 7:22 ` Nick Piggin
2010-05-27 9:08 ` Al Viro
2010-05-27 10:51 ` Artem Bityutskiy
2010-05-27 10:51 ` Artem Bityutskiy
2010-05-27 12:07 ` Nick Piggin
2010-05-27 15:21 ` Artem Bityutskiy
2010-05-27 15:44 ` Nick Piggin
2010-05-27 16:04 ` Artem Bityutskiy
2010-05-31 8:25 ` Artem Bityutskiy
2010-05-31 8:38 ` Nick Piggin
2010-05-31 9:04 ` Artem Bityutskiy
2010-05-31 9:04 ` Artem Bityutskiy
2010-05-31 12:47 ` Nick Piggin
2010-05-31 13:03 ` Artem Bityutskiy
2010-05-31 13:03 ` Artem Bityutskiy
2010-05-27 10:19 ` Artem Bityutskiy
2010-05-31 14:07 ` Artem Bityutskiy
2010-05-31 14:07 ` Artem Bityutskiy
2010-06-04 4:26 ` Al Viro
2010-06-04 5:13 ` Artem Bityutskiy
2010-05-28 20:29 ` Andrew Morton [this message]
2010-05-29 8:03 ` Artem Bityutskiy
2010-05-29 8:03 ` Artem Bityutskiy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100528132953.7af88c08.akpm@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=dedekind1@gmail.com \
--cc=jens.axboe@oracle.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=viro@ZenIV.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.