aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2009-04-06 12:44:54 -0400
committerChristoph Hellwig <hch@brick.lst.de>2009-04-06 12:44:54 -0400
commita8d770d987ee20b59fba6c37d7f0f2a351913c4b (patch)
tree3da37edba537ca5860eae97f47fb1204bc5a55b3 /fs
parent9d7fef74b23fe57803c5f71fab11630d9ec2cb4b (diff)
xfs: use xfs_sync_inodes() for device flushing
Currently xfs_device_flush calls sync_blockdev() which is a no-op for XFS as all it's metadata is held in a different address to the one sync_blockdev() works on. Call xfs_sync_inodes() instead to flush all the delayed allocation blocks out. To do this as efficiently as possible, do it via two passes - one to do an async flush of all the dirty blocks and a second to wait for all the IO to complete. This requires some modification to the xfs-sync_inodes_ag() flush code to do efficiently. Signed-off-by: Dave Chinner <david@fromorbit.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c14
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c43
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h7
-rw-r--r--fs/xfs/xfs_iomap.c2
-rw-r--r--fs/xfs/xfs_mount.h2
5 files changed, 38 insertions, 30 deletions
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index 5aeb77776961..08be36d7326c 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -74,14 +74,14 @@ xfs_flush_pages(
74 74
75 if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { 75 if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) {
76 xfs_iflags_clear(ip, XFS_ITRUNCATED); 76 xfs_iflags_clear(ip, XFS_ITRUNCATED);
77 ret = filemap_fdatawrite(mapping); 77 ret = -filemap_fdatawrite(mapping);
78 if (flags & XFS_B_ASYNC)
79 return -ret;
80 ret2 = filemap_fdatawait(mapping);
81 if (!ret)
82 ret = ret2;
83 } 78 }
84 return -ret; 79 if (flags & XFS_B_ASYNC)
80 return ret;
81 ret2 = xfs_wait_on_pages(ip, first, last);
82 if (!ret)
83 ret = ret2;
84 return ret;
85} 85}
86 86
87int 87int
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index a608e72fa405..88caafc8ef1b 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -62,12 +62,6 @@ xfs_sync_inodes_ag(
62 uint32_t first_index = 0; 62 uint32_t first_index = 0;
63 int error = 0; 63 int error = 0;
64 int last_error = 0; 64 int last_error = 0;
65 int fflag = XFS_B_ASYNC;
66
67 if (flags & SYNC_DELWRI)
68 fflag = XFS_B_DELWRI;
69 if (flags & SYNC_WAIT)
70 fflag = 0; /* synchronous overrides all */
71 65
72 do { 66 do {
73 struct inode *inode; 67 struct inode *inode;
@@ -128,11 +122,23 @@ xfs_sync_inodes_ag(
128 * If we have to flush data or wait for I/O completion 122 * If we have to flush data or wait for I/O completion
129 * we need to hold the iolock. 123 * we need to hold the iolock.
130 */ 124 */
131 if ((flags & SYNC_DELWRI) && VN_DIRTY(inode)) { 125 if (flags & SYNC_DELWRI) {
132 xfs_ilock(ip, XFS_IOLOCK_SHARED); 126 if (VN_DIRTY(inode)) {
133 lock_flags |= XFS_IOLOCK_SHARED; 127 if (flags & SYNC_TRYLOCK) {
134 error = xfs_flush_pages(ip, 0, -1, fflag, FI_NONE); 128 if (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
135 if (flags & SYNC_IOWAIT) 129 lock_flags |= XFS_IOLOCK_SHARED;
130 } else {
131 xfs_ilock(ip, XFS_IOLOCK_SHARED);
132 lock_flags |= XFS_IOLOCK_SHARED;
133 }
134 if (lock_flags & XFS_IOLOCK_SHARED) {
135 error = xfs_flush_pages(ip, 0, -1,
136 (flags & SYNC_WAIT) ? 0
137 : XFS_B_ASYNC,
138 FI_NONE);
139 }
140 }
141 if (VN_CACHED(inode) && (flags & SYNC_IOWAIT))
136 xfs_ioend_wait(ip); 142 xfs_ioend_wait(ip);
137 } 143 }
138 xfs_ilock(ip, XFS_ILOCK_SHARED); 144 xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -400,9 +406,9 @@ xfs_syncd_queue_work(
400 void *data, 406 void *data,
401 void (*syncer)(struct xfs_mount *, void *)) 407 void (*syncer)(struct xfs_mount *, void *))
402{ 408{
403 struct bhv_vfs_sync_work *work; 409 struct xfs_sync_work *work;
404 410
405 work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP); 411 work = kmem_alloc(sizeof(struct xfs_sync_work), KM_SLEEP);
406 INIT_LIST_HEAD(&work->w_list); 412 INIT_LIST_HEAD(&work->w_list);
407 work->w_syncer = syncer; 413 work->w_syncer = syncer;
408 work->w_data = data; 414 work->w_data = data;
@@ -445,23 +451,24 @@ xfs_flush_inode(
445 * (IOW, "If at first you don't succeed, use a Bigger Hammer"). 451 * (IOW, "If at first you don't succeed, use a Bigger Hammer").
446 */ 452 */
447STATIC void 453STATIC void
448xfs_flush_device_work( 454xfs_flush_inodes_work(
449 struct xfs_mount *mp, 455 struct xfs_mount *mp,
450 void *arg) 456 void *arg)
451{ 457{
452 struct inode *inode = arg; 458 struct inode *inode = arg;
453 sync_blockdev(mp->m_super->s_bdev); 459 xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK);
460 xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK | SYNC_IOWAIT);
454 iput(inode); 461 iput(inode);
455} 462}
456 463
457void 464void
458xfs_flush_device( 465xfs_flush_inodes(
459 xfs_inode_t *ip) 466 xfs_inode_t *ip)
460{ 467{
461 struct inode *inode = VFS_I(ip); 468 struct inode *inode = VFS_I(ip);
462 469
463 igrab(inode); 470 igrab(inode);
464 xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); 471 xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work);
465 delay(msecs_to_jiffies(500)); 472 delay(msecs_to_jiffies(500));
466 xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); 473 xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
467} 474}
@@ -497,7 +504,7 @@ xfssyncd(
497{ 504{
498 struct xfs_mount *mp = arg; 505 struct xfs_mount *mp = arg;
499 long timeleft; 506 long timeleft;
500 bhv_vfs_sync_work_t *work, *n; 507 xfs_sync_work_t *work, *n;
501 LIST_HEAD (tmp); 508 LIST_HEAD (tmp);
502 509
503 set_freezable(); 510 set_freezable();
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index 04f058c848ae..ec95e264805b 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -21,18 +21,19 @@
21struct xfs_mount; 21struct xfs_mount;
22struct xfs_perag; 22struct xfs_perag;
23 23
24typedef struct bhv_vfs_sync_work { 24typedef struct xfs_sync_work {
25 struct list_head w_list; 25 struct list_head w_list;
26 struct xfs_mount *w_mount; 26 struct xfs_mount *w_mount;
27 void *w_data; /* syncer routine argument */ 27 void *w_data; /* syncer routine argument */
28 void (*w_syncer)(struct xfs_mount *, void *); 28 void (*w_syncer)(struct xfs_mount *, void *);
29} bhv_vfs_sync_work_t; 29} xfs_sync_work_t;
30 30
31#define SYNC_ATTR 0x0001 /* sync attributes */ 31#define SYNC_ATTR 0x0001 /* sync attributes */
32#define SYNC_DELWRI 0x0002 /* look at delayed writes */ 32#define SYNC_DELWRI 0x0002 /* look at delayed writes */
33#define SYNC_WAIT 0x0004 /* wait for i/o to complete */ 33#define SYNC_WAIT 0x0004 /* wait for i/o to complete */
34#define SYNC_BDFLUSH 0x0008 /* BDFLUSH is calling -- don't block */ 34#define SYNC_BDFLUSH 0x0008 /* BDFLUSH is calling -- don't block */
35#define SYNC_IOWAIT 0x0010 /* wait for all I/O to complete */ 35#define SYNC_IOWAIT 0x0010 /* wait for all I/O to complete */
36#define SYNC_TRYLOCK 0x0020 /* only try to lock inodes */
36 37
37int xfs_syncd_init(struct xfs_mount *mp); 38int xfs_syncd_init(struct xfs_mount *mp);
38void xfs_syncd_stop(struct xfs_mount *mp); 39void xfs_syncd_stop(struct xfs_mount *mp);
@@ -44,7 +45,7 @@ int xfs_quiesce_data(struct xfs_mount *mp);
44void xfs_quiesce_attr(struct xfs_mount *mp); 45void xfs_quiesce_attr(struct xfs_mount *mp);
45 46
46void xfs_flush_inode(struct xfs_inode *ip); 47void xfs_flush_inode(struct xfs_inode *ip);
47void xfs_flush_device(struct xfs_inode *ip); 48void xfs_flush_inodes(struct xfs_inode *ip);
48 49
49int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); 50int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode);
50int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode); 51int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 08ce72316bfe..8b97d82d7a88 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -361,7 +361,7 @@ xfs_flush_space(
361 return 0; 361 return 0;
362 case 2: 362 case 2:
363 xfs_iunlock(ip, XFS_ILOCK_EXCL); 363 xfs_iunlock(ip, XFS_ILOCK_EXCL);
364 xfs_flush_device(ip); 364 xfs_flush_inodes(ip);
365 xfs_ilock(ip, XFS_ILOCK_EXCL); 365 xfs_ilock(ip, XFS_ILOCK_EXCL);
366 *fsynced = 3; 366 *fsynced = 3;
367 return 0; 367 return 0;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 7af44adffc8f..d6a64392f983 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -313,7 +313,7 @@ typedef struct xfs_mount {
313#endif 313#endif
314 struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ 314 struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
315 struct task_struct *m_sync_task; /* generalised sync thread */ 315 struct task_struct *m_sync_task; /* generalised sync thread */
316 bhv_vfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */ 316 xfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */
317 struct list_head m_sync_list; /* sync thread work item list */ 317 struct list_head m_sync_list; /* sync thread work item list */
318 spinlock_t m_sync_lock; /* work item list lock */ 318 spinlock_t m_sync_lock; /* work item list lock */
319 int m_sync_seq; /* sync thread generation no. */ 319 int m_sync_seq; /* sync thread generation no. */