aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-10-09 16:29:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-10-09 16:29:42 -0400
commita372bf8b6a12f23f68e716113ccaea4bf646dd0f (patch)
tree3852e11c78e5dea779f49e9a94288c8ac827e821 /fs/xfs/linux-2.6
parent0d5d1aadc8e299874a6a014d65b6bb903b12424d (diff)
parente09d39968bd8befa087f10f970fa236e8694b643 (diff)
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: xfs: stop calling filemap_fdatawait inside ->fsync fix readahead calculations in xfs_dir2_leaf_getdents() xfs: make sure xfs_sync_fsdata covers the log xfs: mark inodes dirty before issuing I/O xfs: cleanup ->sync_fs xfs: fix xfs_quiesce_data xfs: implement ->dirty_inode to fix timestamp handling
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c38
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c9
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c41
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c59
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c36
6 files changed, 112 insertions, 73 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 381854461b28..c2e30eea74dc 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -186,19 +186,37 @@ xfs_destroy_ioend(
186} 186}
187 187
188/* 188/*
189 * If the end of the current ioend is beyond the current EOF,
190 * return the new EOF value, otherwise zero.
191 */
192STATIC xfs_fsize_t
193xfs_ioend_new_eof(
194 xfs_ioend_t *ioend)
195{
196 xfs_inode_t *ip = XFS_I(ioend->io_inode);
197 xfs_fsize_t isize;
198 xfs_fsize_t bsize;
199
200 bsize = ioend->io_offset + ioend->io_size;
201 isize = MAX(ip->i_size, ip->i_new_size);
202 isize = MIN(isize, bsize);
203 return isize > ip->i_d.di_size ? isize : 0;
204}
205
206/*
189 * Update on-disk file size now that data has been written to disk. 207 * Update on-disk file size now that data has been written to disk.
190 * The current in-memory file size is i_size. If a write is beyond 208 * The current in-memory file size is i_size. If a write is beyond
191 * eof i_new_size will be the intended file size until i_size is 209 * eof i_new_size will be the intended file size until i_size is
192 * updated. If this write does not extend all the way to the valid 210 * updated. If this write does not extend all the way to the valid
193 * file size then restrict this update to the end of the write. 211 * file size then restrict this update to the end of the write.
194 */ 212 */
213
195STATIC void 214STATIC void
196xfs_setfilesize( 215xfs_setfilesize(
197 xfs_ioend_t *ioend) 216 xfs_ioend_t *ioend)
198{ 217{
199 xfs_inode_t *ip = XFS_I(ioend->io_inode); 218 xfs_inode_t *ip = XFS_I(ioend->io_inode);
200 xfs_fsize_t isize; 219 xfs_fsize_t isize;
201 xfs_fsize_t bsize;
202 220
203 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG); 221 ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
204 ASSERT(ioend->io_type != IOMAP_READ); 222 ASSERT(ioend->io_type != IOMAP_READ);
@@ -206,16 +224,10 @@ xfs_setfilesize(
206 if (unlikely(ioend->io_error)) 224 if (unlikely(ioend->io_error))
207 return; 225 return;
208 226
209 bsize = ioend->io_offset + ioend->io_size;
210
211 xfs_ilock(ip, XFS_ILOCK_EXCL); 227 xfs_ilock(ip, XFS_ILOCK_EXCL);
212 228 isize = xfs_ioend_new_eof(ioend);
213 isize = MAX(ip->i_size, ip->i_new_size); 229 if (isize) {
214 isize = MIN(isize, bsize);
215
216 if (ip->i_d.di_size < isize) {
217 ip->i_d.di_size = isize; 230 ip->i_d.di_size = isize;
218 ip->i_update_core = 1;
219 xfs_mark_inode_dirty_sync(ip); 231 xfs_mark_inode_dirty_sync(ip);
220 } 232 }
221 233
@@ -404,10 +416,16 @@ xfs_submit_ioend_bio(
404 struct bio *bio) 416 struct bio *bio)
405{ 417{
406 atomic_inc(&ioend->io_remaining); 418 atomic_inc(&ioend->io_remaining);
407
408 bio->bi_private = ioend; 419 bio->bi_private = ioend;
409 bio->bi_end_io = xfs_end_bio; 420 bio->bi_end_io = xfs_end_bio;
410 421
422 /*
423 * If the I/O is beyond EOF we mark the inode dirty immediately
424 * but don't update the inode size until I/O completion.
425 */
426 if (xfs_ioend_new_eof(ioend))
427 xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode));
428
411 submit_bio(WRITE, bio); 429 submit_bio(WRITE, bio);
412 ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP)); 430 ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
413 bio_put(bio); 431 bio_put(bio);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 629370974e57..eff61e2732af 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -176,14 +176,7 @@ xfs_file_fsync(
176 struct dentry *dentry, 176 struct dentry *dentry,
177 int datasync) 177 int datasync)
178{ 178{
179 struct inode *inode = dentry->d_inode; 179 struct xfs_inode *ip = XFS_I(dentry->d_inode);
180 struct xfs_inode *ip = XFS_I(inode);
181 int error;
182
183 /* capture size updates in I/O completion before writing the inode. */
184 error = filemap_fdatawait(inode->i_mapping);
185 if (error)
186 return error;
187 180
188 xfs_iflags_clear(ip, XFS_ITRUNCATED); 181 xfs_iflags_clear(ip, XFS_ITRUNCATED);
189 return -xfs_fsync(ip); 182 return -xfs_fsync(ip);
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index da0159d99f82..cd42ef78f6b5 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -57,19 +57,22 @@
57#include <linux/fiemap.h> 57#include <linux/fiemap.h>
58 58
59/* 59/*
60 * Bring the atime in the XFS inode uptodate. 60 * Bring the timestamps in the XFS inode uptodate.
61 * Used before logging the inode to disk or when the Linux inode goes away. 61 *
62 * Used before writing the inode to disk.
62 */ 63 */
63void 64void
64xfs_synchronize_atime( 65xfs_synchronize_times(
65 xfs_inode_t *ip) 66 xfs_inode_t *ip)
66{ 67{
67 struct inode *inode = VFS_I(ip); 68 struct inode *inode = VFS_I(ip);
68 69
69 if (!(inode->i_state & I_CLEAR)) { 70 ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
70 ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; 71 ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
71 ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; 72 ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec;
72 } 73 ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec;
74 ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec;
75 ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec;
73} 76}
74 77
75/* 78/*
@@ -106,32 +109,20 @@ xfs_ichgtime(
106 if ((flags & XFS_ICHGTIME_MOD) && 109 if ((flags & XFS_ICHGTIME_MOD) &&
107 !timespec_equal(&inode->i_mtime, &tv)) { 110 !timespec_equal(&inode->i_mtime, &tv)) {
108 inode->i_mtime = tv; 111 inode->i_mtime = tv;
109 ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
110 ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
111 sync_it = 1; 112 sync_it = 1;
112 } 113 }
113 if ((flags & XFS_ICHGTIME_CHG) && 114 if ((flags & XFS_ICHGTIME_CHG) &&
114 !timespec_equal(&inode->i_ctime, &tv)) { 115 !timespec_equal(&inode->i_ctime, &tv)) {
115 inode->i_ctime = tv; 116 inode->i_ctime = tv;
116 ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
117 ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
118 sync_it = 1; 117 sync_it = 1;
119 } 118 }
120 119
121 /* 120 /*
122 * We update the i_update_core field _after_ changing 121 * Update complete - now make sure everyone knows that the inode
123 * the timestamps in order to coordinate properly with 122 * is dirty.
124 * xfs_iflush() so that we don't lose timestamp updates.
125 * This keeps us from having to hold the inode lock
126 * while doing this. We use the SYNCHRONIZE macro to
127 * ensure that the compiler does not reorder the update
128 * of i_update_core above the timestamp updates above.
129 */ 123 */
130 if (sync_it) { 124 if (sync_it)
131 SYNCHRONIZE();
132 ip->i_update_core = 1;
133 xfs_mark_inode_dirty_sync(ip); 125 xfs_mark_inode_dirty_sync(ip);
134 }
135} 126}
136 127
137/* 128/*
@@ -506,10 +497,8 @@ xfs_vn_getattr(
506 stat->gid = ip->i_d.di_gid; 497 stat->gid = ip->i_d.di_gid;
507 stat->ino = ip->i_ino; 498 stat->ino = ip->i_ino;
508 stat->atime = inode->i_atime; 499 stat->atime = inode->i_atime;
509 stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec; 500 stat->mtime = inode->i_mtime;
510 stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; 501 stat->ctime = inode->i_ctime;
511 stat->ctime.tv_sec = ip->i_d.di_ctime.t_sec;
512 stat->ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
513 stat->blocks = 502 stat->blocks =
514 XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); 503 XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
515 504
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 49e4a6aea73c..072050f8d346 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -667,7 +667,7 @@ start:
667 xip->i_new_size = new_size; 667 xip->i_new_size = new_size;
668 668
669 if (likely(!(ioflags & IO_INVIS))) 669 if (likely(!(ioflags & IO_INVIS)))
670 xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 670 file_update_time(file);
671 671
672 /* 672 /*
673 * If the offset is beyond the size of the file, we have a couple 673 * If the offset is beyond the size of the file, we have a couple
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index bdd41c8c342f..18a4b8e11df2 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -977,6 +977,28 @@ xfs_fs_inode_init_once(
977} 977}
978 978
979/* 979/*
980 * Dirty the XFS inode when mark_inode_dirty_sync() is called so that
981 * we catch unlogged VFS level updates to the inode. Care must be taken
982 * here - the transaction code calls mark_inode_dirty_sync() to mark the
983 * VFS inode dirty in a transaction and clears the i_update_core field;
984 * it must clear the field after calling mark_inode_dirty_sync() to
985 * correctly indicate that the dirty state has been propagated into the
986 * inode log item.
987 *
988 * We need the barrier() to maintain correct ordering between unlogged
989 * updates and the transaction commit code that clears the i_update_core
990 * field. This requires all updates to be completed before marking the
991 * inode dirty.
992 */
993STATIC void
994xfs_fs_dirty_inode(
995 struct inode *inode)
996{
997 barrier();
998 XFS_I(inode)->i_update_core = 1;
999}
1000
1001/*
980 * Attempt to flush the inode, this will actually fail 1002 * Attempt to flush the inode, this will actually fail
981 * if the inode is pinned, but we dirty the inode again 1003 * if the inode is pinned, but we dirty the inode again
982 * at the point when it is unpinned after a log write, 1004 * at the point when it is unpinned after a log write,
@@ -1126,7 +1148,7 @@ xfs_fs_put_super(
1126} 1148}
1127 1149
1128STATIC int 1150STATIC int
1129xfs_fs_sync_super( 1151xfs_fs_sync_fs(
1130 struct super_block *sb, 1152 struct super_block *sb,
1131 int wait) 1153 int wait)
1132{ 1154{
@@ -1134,23 +1156,23 @@ xfs_fs_sync_super(
1134 int error; 1156 int error;
1135 1157
1136 /* 1158 /*
1137 * Treat a sync operation like a freeze. This is to work 1159 * Not much we can do for the first async pass. Writing out the
1138 * around a race in sync_inodes() which works in two phases 1160 * superblock would be counter-productive as we are going to redirty
1139 * - an asynchronous flush, which can write out an inode 1161 * when writing out other data and metadata (and writing out a single
1140 * without waiting for file size updates to complete, and a 1162 * block is quite fast anyway).
1141 * synchronous flush, which wont do anything because the 1163 *
1142 * async flush removed the inode's dirty flag. Also 1164 * Try to asynchronously kick off quota syncing at least.
1143 * sync_inodes() will not see any files that just have
1144 * outstanding transactions to be flushed because we don't
1145 * dirty the Linux inode until after the transaction I/O
1146 * completes.
1147 */ 1165 */
1148 if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) 1166 if (!wait) {
1149 error = xfs_quiesce_data(mp); 1167 xfs_qm_sync(mp, SYNC_TRYLOCK);
1150 else 1168 return 0;
1151 error = xfs_sync_fsdata(mp, 0); 1169 }
1170
1171 error = xfs_quiesce_data(mp);
1172 if (error)
1173 return -error;
1152 1174
1153 if (unlikely(laptop_mode)) { 1175 if (laptop_mode) {
1154 int prev_sync_seq = mp->m_sync_seq; 1176 int prev_sync_seq = mp->m_sync_seq;
1155 1177
1156 /* 1178 /*
@@ -1169,7 +1191,7 @@ xfs_fs_sync_super(
1169 mp->m_sync_seq != prev_sync_seq); 1191 mp->m_sync_seq != prev_sync_seq);
1170 } 1192 }
1171 1193
1172 return -error; 1194 return 0;
1173} 1195}
1174 1196
1175STATIC int 1197STATIC int
@@ -1539,10 +1561,11 @@ xfs_fs_get_sb(
1539static const struct super_operations xfs_super_operations = { 1561static const struct super_operations xfs_super_operations = {
1540 .alloc_inode = xfs_fs_alloc_inode, 1562 .alloc_inode = xfs_fs_alloc_inode,
1541 .destroy_inode = xfs_fs_destroy_inode, 1563 .destroy_inode = xfs_fs_destroy_inode,
1564 .dirty_inode = xfs_fs_dirty_inode,
1542 .write_inode = xfs_fs_write_inode, 1565 .write_inode = xfs_fs_write_inode,
1543 .clear_inode = xfs_fs_clear_inode, 1566 .clear_inode = xfs_fs_clear_inode,
1544 .put_super = xfs_fs_put_super, 1567 .put_super = xfs_fs_put_super,
1545 .sync_fs = xfs_fs_sync_super, 1568 .sync_fs = xfs_fs_sync_fs,
1546 .freeze_fs = xfs_fs_freeze, 1569 .freeze_fs = xfs_fs_freeze,
1547 .statfs = xfs_fs_statfs, 1570 .statfs = xfs_fs_statfs,
1548 .remount_fs = xfs_fs_remount, 1571 .remount_fs = xfs_fs_remount,
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index 320be6aea492..961df0a22c78 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -309,11 +309,15 @@ xfs_sync_attr(
309STATIC int 309STATIC int
310xfs_commit_dummy_trans( 310xfs_commit_dummy_trans(
311 struct xfs_mount *mp, 311 struct xfs_mount *mp,
312 uint log_flags) 312 uint flags)
313{ 313{
314 struct xfs_inode *ip = mp->m_rootip; 314 struct xfs_inode *ip = mp->m_rootip;
315 struct xfs_trans *tp; 315 struct xfs_trans *tp;
316 int error; 316 int error;
317 int log_flags = XFS_LOG_FORCE;
318
319 if (flags & SYNC_WAIT)
320 log_flags |= XFS_LOG_SYNC;
317 321
318 /* 322 /*
319 * Put a dummy transaction in the log to tell recovery 323 * Put a dummy transaction in the log to tell recovery
@@ -331,13 +335,12 @@ xfs_commit_dummy_trans(
331 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 335 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
332 xfs_trans_ihold(tp, ip); 336 xfs_trans_ihold(tp, ip);
333 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 337 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
334 /* XXX(hch): ignoring the error here.. */
335 error = xfs_trans_commit(tp, 0); 338 error = xfs_trans_commit(tp, 0);
336
337 xfs_iunlock(ip, XFS_ILOCK_EXCL); 339 xfs_iunlock(ip, XFS_ILOCK_EXCL);
338 340
341 /* the log force ensures this transaction is pushed to disk */
339 xfs_log_force(mp, 0, log_flags); 342 xfs_log_force(mp, 0, log_flags);
340 return 0; 343 return error;
341} 344}
342 345
343int 346int
@@ -385,7 +388,20 @@ xfs_sync_fsdata(
385 else 388 else
386 XFS_BUF_ASYNC(bp); 389 XFS_BUF_ASYNC(bp);
387 390
388 return xfs_bwrite(mp, bp); 391 error = xfs_bwrite(mp, bp);
392 if (error)
393 return error;
394
395 /*
396 * If this is a data integrity sync make sure all pending buffers
397 * are flushed out for the log coverage check below.
398 */
399 if (flags & SYNC_WAIT)
400 xfs_flush_buftarg(mp->m_ddev_targp, 1);
401
402 if (xfs_log_need_covered(mp))
403 error = xfs_commit_dummy_trans(mp, flags);
404 return error;
389 405
390 out_brelse: 406 out_brelse:
391 xfs_buf_relse(bp); 407 xfs_buf_relse(bp);
@@ -419,14 +435,16 @@ xfs_quiesce_data(
419 /* push non-blocking */ 435 /* push non-blocking */
420 xfs_sync_data(mp, 0); 436 xfs_sync_data(mp, 0);
421 xfs_qm_sync(mp, SYNC_TRYLOCK); 437 xfs_qm_sync(mp, SYNC_TRYLOCK);
422 xfs_filestream_flush(mp);
423 438
424 /* push and block */ 439 /* push and block till complete */
425 xfs_sync_data(mp, SYNC_WAIT); 440 xfs_sync_data(mp, SYNC_WAIT);
426 xfs_qm_sync(mp, SYNC_WAIT); 441 xfs_qm_sync(mp, SYNC_WAIT);
427 442
443 /* drop inode references pinned by filestreams */
444 xfs_filestream_flush(mp);
445
428 /* write superblock and hoover up shutdown errors */ 446 /* write superblock and hoover up shutdown errors */
429 error = xfs_sync_fsdata(mp, 0); 447 error = xfs_sync_fsdata(mp, SYNC_WAIT);
430 448
431 /* flush data-only devices */ 449 /* flush data-only devices */
432 if (mp->m_rtdev_targp) 450 if (mp->m_rtdev_targp)
@@ -570,8 +588,6 @@ xfs_sync_worker(
570 /* dgc: errors ignored here */ 588 /* dgc: errors ignored here */
571 error = xfs_qm_sync(mp, SYNC_TRYLOCK); 589 error = xfs_qm_sync(mp, SYNC_TRYLOCK);
572 error = xfs_sync_fsdata(mp, SYNC_TRYLOCK); 590 error = xfs_sync_fsdata(mp, SYNC_TRYLOCK);
573 if (xfs_log_need_covered(mp))
574 error = xfs_commit_dummy_trans(mp, XFS_LOG_FORCE);
575 } 591 }
576 mp->m_sync_seq++; 592 mp->m_sync_seq++;
577 wake_up(&mp->m_wait_single_sync_task); 593 wake_up(&mp->m_wait_single_sync_task);