aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_sync.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-04-07 22:45:07 -0400
committerDave Chinner <david@fromorbit.com>2011-04-07 22:45:07 -0400
commitc6d09b666de11eb272326a6eb6cd3246da571014 (patch)
tree74951ec04191b47a1fb75f9e79de6c00837a7c17 /fs/xfs/linux-2.6/xfs_sync.c
parente828776a8abe6b9bae7ed9638710bff7642c568a (diff)
xfs: introduce a xfssyncd workqueue
All of the work xfssyncd does is background functionality. There is no need for a thread per filesystem to do this work - it can al be managed by a global workqueue now they manage concurrency effectively. Introduce a new gglobal xfssyncd workqueue, and convert the periodic work to use this new functionality. To do this, use a delayed work construct to schedule the next running of the periodic sync work for the filesystem. When the sync work is complete, queue a new delayed work for the next running of the sync work. For laptop mode, we wait on completion for the sync works, so ensure that the sync work queuing interface can flush and wait for work to complete to enable the work queue infrastructure to replace the current sequence number and wakeup that is used. Because the sync work does non-trivial amounts of work, mark the new work queue as CPU intensive. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_sync.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c88
1 files changed, 43 insertions, 45 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 594cd822d84d..4a582d8100e4 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -39,6 +39,8 @@
39#include <linux/kthread.h> 39#include <linux/kthread.h>
40#include <linux/freezer.h> 40#include <linux/freezer.h>
41 41
42struct workqueue_struct *xfs_syncd_wq; /* sync workqueue */
43
42/* 44/*
43 * The inode lookup is done in batches to keep the amount of lock traffic and 45 * The inode lookup is done in batches to keep the amount of lock traffic and
44 * radix tree lookups to a minimum. The batch size is a trade off between 46 * radix tree lookups to a minimum. The batch size is a trade off between
@@ -489,32 +491,6 @@ xfs_flush_inodes(
489 xfs_log_force(ip->i_mount, XFS_LOG_SYNC); 491 xfs_log_force(ip->i_mount, XFS_LOG_SYNC);
490} 492}
491 493
492/*
493 * Every sync period we need to unpin all items, reclaim inodes and sync
494 * disk quotas. We might need to cover the log to indicate that the
495 * filesystem is idle and not frozen.
496 */
497STATIC void
498xfs_sync_worker(
499 struct xfs_mount *mp,
500 void *unused)
501{
502 int error;
503
504 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
505 /* dgc: errors ignored here */
506 if (mp->m_super->s_frozen == SB_UNFROZEN &&
507 xfs_log_need_covered(mp))
508 error = xfs_fs_log_dummy(mp);
509 else
510 xfs_log_force(mp, 0);
511 xfs_reclaim_inodes(mp, 0);
512 error = xfs_qm_sync(mp, SYNC_TRYLOCK);
513 }
514 mp->m_sync_seq++;
515 wake_up(&mp->m_wait_single_sync_task);
516}
517
518STATIC int 494STATIC int
519xfssyncd( 495xfssyncd(
520 void *arg) 496 void *arg)
@@ -528,34 +504,19 @@ xfssyncd(
528 timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); 504 timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
529 for (;;) { 505 for (;;) {
530 if (list_empty(&mp->m_sync_list)) 506 if (list_empty(&mp->m_sync_list))
531 timeleft = schedule_timeout_interruptible(timeleft); 507 schedule_timeout_interruptible(timeleft);
532 /* swsusp */ 508 /* swsusp */
533 try_to_freeze(); 509 try_to_freeze();
534 if (kthread_should_stop() && list_empty(&mp->m_sync_list)) 510 if (kthread_should_stop() && list_empty(&mp->m_sync_list))
535 break; 511 break;
536 512
537 spin_lock(&mp->m_sync_lock); 513 spin_lock(&mp->m_sync_lock);
538 /*
539 * We can get woken by laptop mode, to do a sync -
540 * that's the (only!) case where the list would be
541 * empty with time remaining.
542 */
543 if (!timeleft || list_empty(&mp->m_sync_list)) {
544 if (!timeleft)
545 timeleft = xfs_syncd_centisecs *
546 msecs_to_jiffies(10);
547 INIT_LIST_HEAD(&mp->m_sync_work.w_list);
548 list_add_tail(&mp->m_sync_work.w_list,
549 &mp->m_sync_list);
550 }
551 list_splice_init(&mp->m_sync_list, &tmp); 514 list_splice_init(&mp->m_sync_list, &tmp);
552 spin_unlock(&mp->m_sync_lock); 515 spin_unlock(&mp->m_sync_lock);
553 516
554 list_for_each_entry_safe(work, n, &tmp, w_list) { 517 list_for_each_entry_safe(work, n, &tmp, w_list) {
555 (*work->w_syncer)(mp, work->w_data); 518 (*work->w_syncer)(mp, work->w_data);
556 list_del(&work->w_list); 519 list_del(&work->w_list);
557 if (work == &mp->m_sync_work)
558 continue;
559 if (work->w_completion) 520 if (work->w_completion)
560 complete(work->w_completion); 521 complete(work->w_completion);
561 kmem_free(work); 522 kmem_free(work);
@@ -565,13 +526,49 @@ xfssyncd(
565 return 0; 526 return 0;
566} 527}
567 528
529static void
530xfs_syncd_queue_sync(
531 struct xfs_mount *mp)
532{
533 queue_delayed_work(xfs_syncd_wq, &mp->m_sync_work,
534 msecs_to_jiffies(xfs_syncd_centisecs * 10));
535}
536
537/*
538 * Every sync period we need to unpin all items, reclaim inodes and sync
539 * disk quotas. We might need to cover the log to indicate that the
540 * filesystem is idle and not frozen.
541 */
542STATIC void
543xfs_sync_worker(
544 struct work_struct *work)
545{
546 struct xfs_mount *mp = container_of(to_delayed_work(work),
547 struct xfs_mount, m_sync_work);
548 int error;
549
550 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
551 /* dgc: errors ignored here */
552 if (mp->m_super->s_frozen == SB_UNFROZEN &&
553 xfs_log_need_covered(mp))
554 error = xfs_fs_log_dummy(mp);
555 else
556 xfs_log_force(mp, 0);
557 xfs_reclaim_inodes(mp, 0);
558 error = xfs_qm_sync(mp, SYNC_TRYLOCK);
559 }
560
561 /* queue us up again */
562 xfs_syncd_queue_sync(mp);
563}
564
568int 565int
569xfs_syncd_init( 566xfs_syncd_init(
570 struct xfs_mount *mp) 567 struct xfs_mount *mp)
571{ 568{
572 mp->m_sync_work.w_syncer = xfs_sync_worker; 569 INIT_DELAYED_WORK(&mp->m_sync_work, xfs_sync_worker);
573 mp->m_sync_work.w_mount = mp; 570 xfs_syncd_queue_sync(mp);
574 mp->m_sync_work.w_completion = NULL; 571
575 mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd/%s", mp->m_fsname); 572 mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd/%s", mp->m_fsname);
576 if (IS_ERR(mp->m_sync_task)) 573 if (IS_ERR(mp->m_sync_task))
577 return -PTR_ERR(mp->m_sync_task); 574 return -PTR_ERR(mp->m_sync_task);
@@ -582,6 +579,7 @@ void
582xfs_syncd_stop( 579xfs_syncd_stop(
583 struct xfs_mount *mp) 580 struct xfs_mount *mp)
584{ 581{
582 cancel_delayed_work_sync(&mp->m_sync_work);
585 kthread_stop(mp->m_sync_task); 583 kthread_stop(mp->m_sync_task);
586} 584}
587 585