aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Chinner <david@fromorbit.com>2008-10-30 02:06:18 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 02:06:18 -0400
commita167b17e899a930758506bbc18748078d6fd8c89 (patch)
tree698f8efbe5085ae75e0b46e1b71c7bfc7186d3b2
parentfe4fa4b8e463fa5848ef9e86ed75d27501d0da1e (diff)
[XFS] move xfssyncd code to xfs_sync.c
Move all the xfssyncd code to the new xfs_sync.c file. This places it closer to the actual code that it interacts with, rather than just being associated with high level VFS code. SGI-PV: 988139 SGI-Modid: xfs-linux-melb:xfs-kern:32283a Signed-off-by: David Chinner <david@fromorbit.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org>
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c151
-rw-r--r--fs/xfs/linux-2.6/xfs_super.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c163
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h56
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h31
-rw-r--r--fs/xfs/xfs_mount.h1
6 files changed, 223 insertions, 182 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 727d0e47e80f..767f38e0e0bb 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -979,146 +979,6 @@ xfs_fs_clear_inode(
979 ASSERT(XFS_I(inode) == NULL); 979 ASSERT(XFS_I(inode) == NULL);
980} 980}
981 981
982/*
983 * Enqueue a work item to be picked up by the vfs xfssyncd thread.
984 * Doing this has two advantages:
985 * - It saves on stack space, which is tight in certain situations
986 * - It can be used (with care) as a mechanism to avoid deadlocks.
987 * Flushing while allocating in a full filesystem requires both.
988 */
989STATIC void
990xfs_syncd_queue_work(
991 struct xfs_mount *mp,
992 void *data,
993 void (*syncer)(struct xfs_mount *, void *))
994{
995 struct bhv_vfs_sync_work *work;
996
997 work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP);
998 INIT_LIST_HEAD(&work->w_list);
999 work->w_syncer = syncer;
1000 work->w_data = data;
1001 work->w_mount = mp;
1002 spin_lock(&mp->m_sync_lock);
1003 list_add_tail(&work->w_list, &mp->m_sync_list);
1004 spin_unlock(&mp->m_sync_lock);
1005 wake_up_process(mp->m_sync_task);
1006}
1007
1008/*
1009 * Flush delayed allocate data, attempting to free up reserved space
1010 * from existing allocations. At this point a new allocation attempt
1011 * has failed with ENOSPC and we are in the process of scratching our
1012 * heads, looking about for more room...
1013 */
1014STATIC void
1015xfs_flush_inode_work(
1016 struct xfs_mount *mp,
1017 void *arg)
1018{
1019 struct inode *inode = arg;
1020 filemap_flush(inode->i_mapping);
1021 iput(inode);
1022}
1023
1024void
1025xfs_flush_inode(
1026 xfs_inode_t *ip)
1027{
1028 struct inode *inode = VFS_I(ip);
1029
1030 igrab(inode);
1031 xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
1032 delay(msecs_to_jiffies(500));
1033}
1034
1035/*
1036 * This is the "bigger hammer" version of xfs_flush_inode_work...
1037 * (IOW, "If at first you don't succeed, use a Bigger Hammer").
1038 */
1039STATIC void
1040xfs_flush_device_work(
1041 struct xfs_mount *mp,
1042 void *arg)
1043{
1044 struct inode *inode = arg;
1045 sync_blockdev(mp->m_super->s_bdev);
1046 iput(inode);
1047}
1048
1049void
1050xfs_flush_device(
1051 xfs_inode_t *ip)
1052{
1053 struct inode *inode = VFS_I(ip);
1054
1055 igrab(inode);
1056 xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
1057 delay(msecs_to_jiffies(500));
1058 xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
1059}
1060
1061STATIC void
1062xfs_sync_worker(
1063 struct xfs_mount *mp,
1064 void *unused)
1065{
1066 int error;
1067
1068 if (!(mp->m_flags & XFS_MOUNT_RDONLY))
1069 error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR);
1070 mp->m_sync_seq++;
1071 wake_up(&mp->m_wait_single_sync_task);
1072}
1073
1074STATIC int
1075xfssyncd(
1076 void *arg)
1077{
1078 struct xfs_mount *mp = arg;
1079 long timeleft;
1080 bhv_vfs_sync_work_t *work, *n;
1081 LIST_HEAD (tmp);
1082
1083 set_freezable();
1084 timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
1085 for (;;) {
1086 timeleft = schedule_timeout_interruptible(timeleft);
1087 /* swsusp */
1088 try_to_freeze();
1089 if (kthread_should_stop() && list_empty(&mp->m_sync_list))
1090 break;
1091
1092 spin_lock(&mp->m_sync_lock);
1093 /*
1094 * We can get woken by laptop mode, to do a sync -
1095 * that's the (only!) case where the list would be
1096 * empty with time remaining.
1097 */
1098 if (!timeleft || list_empty(&mp->m_sync_list)) {
1099 if (!timeleft)
1100 timeleft = xfs_syncd_centisecs *
1101 msecs_to_jiffies(10);
1102 INIT_LIST_HEAD(&mp->m_sync_work.w_list);
1103 list_add_tail(&mp->m_sync_work.w_list,
1104 &mp->m_sync_list);
1105 }
1106 list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
1107 list_move(&work->w_list, &tmp);
1108 spin_unlock(&mp->m_sync_lock);
1109
1110 list_for_each_entry_safe(work, n, &tmp, w_list) {
1111 (*work->w_syncer)(mp, work->w_data);
1112 list_del(&work->w_list);
1113 if (work == &mp->m_sync_work)
1114 continue;
1115 kmem_free(work);
1116 }
1117 }
1118
1119 return 0;
1120}
1121
1122STATIC void 982STATIC void
1123xfs_free_fsname( 983xfs_free_fsname(
1124 struct xfs_mount *mp) 984 struct xfs_mount *mp)
@@ -1137,8 +997,7 @@ xfs_fs_put_super(
1137 int unmount_event_flags = 0; 997 int unmount_event_flags = 0;
1138 int error; 998 int error;
1139 999
1140 kthread_stop(mp->m_sync_task); 1000 xfs_syncd_stop(mp);
1141
1142 xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI); 1001 xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI);
1143 1002
1144#ifdef HAVE_DMAPI 1003#ifdef HAVE_DMAPI
@@ -1808,13 +1667,9 @@ xfs_fs_fill_super(
1808 goto fail_vnrele; 1667 goto fail_vnrele;
1809 } 1668 }
1810 1669
1811 mp->m_sync_work.w_syncer = xfs_sync_worker; 1670 error = xfs_syncd_init(mp);
1812 mp->m_sync_work.w_mount = mp; 1671 if (error)
1813 mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
1814 if (IS_ERR(mp->m_sync_task)) {
1815 error = -PTR_ERR(mp->m_sync_task);
1816 goto fail_vnrele; 1672 goto fail_vnrele;
1817 }
1818 1673
1819 xfs_itrace_exit(XFS_I(sb->s_root->d_inode)); 1674 xfs_itrace_exit(XFS_I(sb->s_root->d_inode));
1820 1675
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index fe2ef4e6a0f9..56dc48a76fab 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -101,9 +101,6 @@ struct block_device;
101 101
102extern __uint64_t xfs_max_file_offset(unsigned int); 102extern __uint64_t xfs_max_file_offset(unsigned int);
103 103
104extern void xfs_flush_inode(struct xfs_inode *);
105extern void xfs_flush_device(struct xfs_inode *);
106
107extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); 104extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
108 105
109extern const struct export_operations xfs_export_operations; 106extern const struct export_operations xfs_export_operations;
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index c765eb2a8dca..a51534c71b36 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -44,6 +44,9 @@
44#include "xfs_inode_item.h" 44#include "xfs_inode_item.h"
45#include "xfs_rw.h" 45#include "xfs_rw.h"
46 46
47#include <linux/kthread.h>
48#include <linux/freezer.h>
49
47/* 50/*
48 * xfs_sync flushes any pending I/O to file system vfsp. 51 * xfs_sync flushes any pending I/O to file system vfsp.
49 * 52 *
@@ -603,3 +606,163 @@ xfs_syncsub(
603 606
604 return XFS_ERROR(last_error); 607 return XFS_ERROR(last_error);
605} 608}
609
610/*
611 * Enqueue a work item to be picked up by the vfs xfssyncd thread.
612 * Doing this has two advantages:
613 * - It saves on stack space, which is tight in certain situations
614 * - It can be used (with care) as a mechanism to avoid deadlocks.
615 * Flushing while allocating in a full filesystem requires both.
616 */
617STATIC void
618xfs_syncd_queue_work(
619 struct xfs_mount *mp,
620 void *data,
621 void (*syncer)(struct xfs_mount *, void *))
622{
623 struct bhv_vfs_sync_work *work;
624
625 work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP);
626 INIT_LIST_HEAD(&work->w_list);
627 work->w_syncer = syncer;
628 work->w_data = data;
629 work->w_mount = mp;
630 spin_lock(&mp->m_sync_lock);
631 list_add_tail(&work->w_list, &mp->m_sync_list);
632 spin_unlock(&mp->m_sync_lock);
633 wake_up_process(mp->m_sync_task);
634}
635
636/*
637 * Flush delayed allocate data, attempting to free up reserved space
638 * from existing allocations. At this point a new allocation attempt
639 * has failed with ENOSPC and we are in the process of scratching our
640 * heads, looking about for more room...
641 */
642STATIC void
643xfs_flush_inode_work(
644 struct xfs_mount *mp,
645 void *arg)
646{
647 struct inode *inode = arg;
648 filemap_flush(inode->i_mapping);
649 iput(inode);
650}
651
652void
653xfs_flush_inode(
654 xfs_inode_t *ip)
655{
656 struct inode *inode = VFS_I(ip);
657
658 igrab(inode);
659 xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
660 delay(msecs_to_jiffies(500));
661}
662
663/*
664 * This is the "bigger hammer" version of xfs_flush_inode_work...
665 * (IOW, "If at first you don't succeed, use a Bigger Hammer").
666 */
667STATIC void
668xfs_flush_device_work(
669 struct xfs_mount *mp,
670 void *arg)
671{
672 struct inode *inode = arg;
673 sync_blockdev(mp->m_super->s_bdev);
674 iput(inode);
675}
676
677void
678xfs_flush_device(
679 xfs_inode_t *ip)
680{
681 struct inode *inode = VFS_I(ip);
682
683 igrab(inode);
684 xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
685 delay(msecs_to_jiffies(500));
686 xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
687}
688
689STATIC void
690xfs_sync_worker(
691 struct xfs_mount *mp,
692 void *unused)
693{
694 int error;
695
696 if (!(mp->m_flags & XFS_MOUNT_RDONLY))
697 error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR);
698 mp->m_sync_seq++;
699 wake_up(&mp->m_wait_single_sync_task);
700}
701
702STATIC int
703xfssyncd(
704 void *arg)
705{
706 struct xfs_mount *mp = arg;
707 long timeleft;
708 bhv_vfs_sync_work_t *work, *n;
709 LIST_HEAD (tmp);
710
711 set_freezable();
712 timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
713 for (;;) {
714 timeleft = schedule_timeout_interruptible(timeleft);
715 /* swsusp */
716 try_to_freeze();
717 if (kthread_should_stop() && list_empty(&mp->m_sync_list))
718 break;
719
720 spin_lock(&mp->m_sync_lock);
721 /*
722 * We can get woken by laptop mode, to do a sync -
723 * that's the (only!) case where the list would be
724 * empty with time remaining.
725 */
726 if (!timeleft || list_empty(&mp->m_sync_list)) {
727 if (!timeleft)
728 timeleft = xfs_syncd_centisecs *
729 msecs_to_jiffies(10);
730 INIT_LIST_HEAD(&mp->m_sync_work.w_list);
731 list_add_tail(&mp->m_sync_work.w_list,
732 &mp->m_sync_list);
733 }
734 list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
735 list_move(&work->w_list, &tmp);
736 spin_unlock(&mp->m_sync_lock);
737
738 list_for_each_entry_safe(work, n, &tmp, w_list) {
739 (*work->w_syncer)(mp, work->w_data);
740 list_del(&work->w_list);
741 if (work == &mp->m_sync_work)
742 continue;
743 kmem_free(work);
744 }
745 }
746
747 return 0;
748}
749
750int
751xfs_syncd_init(
752 struct xfs_mount *mp)
753{
754 mp->m_sync_work.w_syncer = xfs_sync_worker;
755 mp->m_sync_work.w_mount = mp;
756 mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
757 if (IS_ERR(mp->m_sync_task))
758 return -PTR_ERR(mp->m_sync_task);
759 return 0;
760}
761
762void
763xfs_syncd_stop(
764 struct xfs_mount *mp)
765{
766 kthread_stop(mp->m_sync_task);
767}
768
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index f4c3b1ea64c0..3746d153ec8e 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -1,7 +1,63 @@
1/*
2 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
1#ifndef XFS_SYNC_H 18#ifndef XFS_SYNC_H
2#define XFS_SYNC_H 1 19#define XFS_SYNC_H 1
3 20
21struct xfs_mount;
22
23typedef struct bhv_vfs_sync_work {
24 struct list_head w_list;
25 struct xfs_mount *w_mount;
26 void *w_data; /* syncer routine argument */
27 void (*w_syncer)(struct xfs_mount *, void *);
28} bhv_vfs_sync_work_t;
29
30#define SYNC_ATTR 0x0001 /* sync attributes */
31#define SYNC_CLOSE 0x0002 /* close file system down */
32#define SYNC_DELWRI 0x0004 /* look at delayed writes */
33#define SYNC_WAIT 0x0008 /* wait for i/o to complete */
34#define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */
35#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
36#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
37#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
38#define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */
39
40/*
41 * When remounting a filesystem read-only or freezing the filesystem,
42 * we have two phases to execute. This first phase is syncing the data
43 * before we quiesce the fielsystem, and the second is flushing all the
44 * inodes out after we've waited for all the transactions created by
45 * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
46 * to ensure that the inodes are written to their location on disk
47 * rather than just existing in transactions in the log. This means
48 * after a quiesce there is no log replay required to write the inodes
49 * to disk (this is the main difference between a sync and a quiesce).
50 */
51#define SYNC_DATA_QUIESCE (SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
52#define SYNC_INODE_QUIESCE (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
53
54int xfs_syncd_init(struct xfs_mount *mp);
55void xfs_syncd_stop(struct xfs_mount *mp);
56
4int xfs_sync(struct xfs_mount *mp, int flags); 57int xfs_sync(struct xfs_mount *mp, int flags);
5int xfs_syncsub(struct xfs_mount *mp, int flags, int *bypassed); 58int xfs_syncsub(struct xfs_mount *mp, int flags, int *bypassed);
6 59
60void xfs_flush_inode(struct xfs_inode *ip);
61void xfs_flush_device(struct xfs_inode *ip);
62
7#endif 63#endif
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 7e60c7776b1c..0ab60bc2e761 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -33,37 +33,6 @@ struct xfs_mount_args;
33 33
34typedef struct kstatfs bhv_statvfs_t; 34typedef struct kstatfs bhv_statvfs_t;
35 35
36typedef struct bhv_vfs_sync_work {
37 struct list_head w_list;
38 struct xfs_mount *w_mount;
39 void *w_data; /* syncer routine argument */
40 void (*w_syncer)(struct xfs_mount *, void *);
41} bhv_vfs_sync_work_t;
42
43#define SYNC_ATTR 0x0001 /* sync attributes */
44#define SYNC_CLOSE 0x0002 /* close file system down */
45#define SYNC_DELWRI 0x0004 /* look at delayed writes */
46#define SYNC_WAIT 0x0008 /* wait for i/o to complete */
47#define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */
48#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
49#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
50#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
51#define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */
52
53/*
54 * When remounting a filesystem read-only or freezing the filesystem,
55 * we have two phases to execute. This first phase is syncing the data
56 * before we quiesce the fielsystem, and the second is flushing all the
57 * inodes out after we've waited for all the transactions created by
58 * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
59 * to ensure that the inodes are written to their location on disk
60 * rather than just existing in transactions in the log. This means
61 * after a quiesce there is no log replay required to write the inodes
62 * to disk (this is the main difference between a sync and a quiesce).
63 */
64#define SYNC_DATA_QUIESCE (SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
65#define SYNC_INODE_QUIESCE (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
66
67#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */ 36#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */
68#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */ 37#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */
69#define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */ 38#define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 56c3b122e532..c6846810936a 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -18,6 +18,7 @@
18#ifndef __XFS_MOUNT_H__ 18#ifndef __XFS_MOUNT_H__
19#define __XFS_MOUNT_H__ 19#define __XFS_MOUNT_H__
20 20
21#include "xfs_sync.h"
21 22
22typedef struct xfs_trans_reservations { 23typedef struct xfs_trans_reservations {
23 uint tr_write; /* extent alloc trans */ 24 uint tr_write; /* extent alloc trans */