diff options
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 38 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 9 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 41 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 2 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 59 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 36 | ||||
-rw-r--r-- | fs/xfs/xfs_dfrag.c | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_inode_item.c | 18 | ||||
-rw-r--r-- | fs/xfs/xfs_itable.c | 21 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 6 |
13 files changed, 146 insertions, 102 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 | */ | ||
192 | STATIC xfs_fsize_t | ||
193 | xfs_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 | |||
195 | STATIC void | 214 | STATIC void |
196 | xfs_setfilesize( | 215 | xfs_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 | */ |
63 | void | 64 | void |
64 | xfs_synchronize_atime( | 65 | xfs_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 | */ | ||
993 | STATIC void | ||
994 | xfs_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 | ||
1128 | STATIC int | 1150 | STATIC int |
1129 | xfs_fs_sync_super( | 1151 | xfs_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 | ||
1175 | STATIC int | 1197 | STATIC int |
@@ -1539,10 +1561,11 @@ xfs_fs_get_sb( | |||
1539 | static const struct super_operations xfs_super_operations = { | 1561 | static 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( | |||
309 | STATIC int | 309 | STATIC int |
310 | xfs_commit_dummy_trans( | 310 | xfs_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 | ||
343 | int | 346 | int |
@@ -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); |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 7465f9ee125f..ab89a7e94a0f 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -206,10 +206,10 @@ xfs_swap_extents( | |||
206 | * process that the file was not changed out from | 206 | * process that the file was not changed out from |
207 | * under it. | 207 | * under it. |
208 | */ | 208 | */ |
209 | if ((sbp->bs_ctime.tv_sec != ip->i_d.di_ctime.t_sec) || | 209 | if ((sbp->bs_ctime.tv_sec != VFS_I(ip)->i_ctime.tv_sec) || |
210 | (sbp->bs_ctime.tv_nsec != ip->i_d.di_ctime.t_nsec) || | 210 | (sbp->bs_ctime.tv_nsec != VFS_I(ip)->i_ctime.tv_nsec) || |
211 | (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) || | 211 | (sbp->bs_mtime.tv_sec != VFS_I(ip)->i_mtime.tv_sec) || |
212 | (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) { | 212 | (sbp->bs_mtime.tv_nsec != VFS_I(ip)->i_mtime.tv_nsec)) { |
213 | error = XFS_ERROR(EBUSY); | 213 | error = XFS_ERROR(EBUSY); |
214 | goto out_unlock; | 214 | goto out_unlock; |
215 | } | 215 | } |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index fa913e459442..41ad537c49e9 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -854,6 +854,7 @@ xfs_dir2_leaf_getdents( | |||
854 | */ | 854 | */ |
855 | ra_want = howmany(bufsize + mp->m_dirblksize, | 855 | ra_want = howmany(bufsize + mp->m_dirblksize, |
856 | mp->m_sb.sb_blocksize) - 1; | 856 | mp->m_sb.sb_blocksize) - 1; |
857 | ASSERT(ra_want >= 0); | ||
857 | 858 | ||
858 | /* | 859 | /* |
859 | * If we don't have as many as we want, and we haven't | 860 | * If we don't have as many as we want, and we haven't |
@@ -1088,7 +1089,8 @@ xfs_dir2_leaf_getdents( | |||
1088 | */ | 1089 | */ |
1089 | ptr += length; | 1090 | ptr += length; |
1090 | curoff += length; | 1091 | curoff += length; |
1091 | bufsize -= length; | 1092 | /* bufsize may have just been a guess; don't go negative */ |
1093 | bufsize = bufsize > length ? bufsize - length : 0; | ||
1092 | } | 1094 | } |
1093 | 1095 | ||
1094 | /* | 1096 | /* |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c1dc7ef5a1d8..b92a4fa2a0a1 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -3068,9 +3068,9 @@ xfs_iflush_int( | |||
3068 | SYNCHRONIZE(); | 3068 | SYNCHRONIZE(); |
3069 | 3069 | ||
3070 | /* | 3070 | /* |
3071 | * Make sure to get the latest atime from the Linux inode. | 3071 | * Make sure to get the latest timestamps from the Linux inode. |
3072 | */ | 3072 | */ |
3073 | xfs_synchronize_atime(ip); | 3073 | xfs_synchronize_times(ip); |
3074 | 3074 | ||
3075 | if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC, | 3075 | if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC, |
3076 | mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { | 3076 | mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 0b38b9a869ec..41555de1d1db 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -504,7 +504,7 @@ void xfs_ichgtime(xfs_inode_t *, int); | |||
504 | void xfs_lock_inodes(xfs_inode_t **, int, uint); | 504 | void xfs_lock_inodes(xfs_inode_t **, int, uint); |
505 | void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); | 505 | void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); |
506 | 506 | ||
507 | void xfs_synchronize_atime(xfs_inode_t *); | 507 | void xfs_synchronize_times(xfs_inode_t *); |
508 | void xfs_mark_inode_dirty_sync(xfs_inode_t *); | 508 | void xfs_mark_inode_dirty_sync(xfs_inode_t *); |
509 | 509 | ||
510 | #if defined(XFS_INODE_TRACE) | 510 | #if defined(XFS_INODE_TRACE) |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 47d5b663c37e..9794b876d6ff 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -232,6 +232,15 @@ xfs_inode_item_format( | |||
232 | nvecs = 1; | 232 | nvecs = 1; |
233 | 233 | ||
234 | /* | 234 | /* |
235 | * Make sure the linux inode is dirty. We do this before | ||
236 | * clearing i_update_core as the VFS will call back into | ||
237 | * XFS here and set i_update_core, so we need to dirty the | ||
238 | * inode first so that the ordering of i_update_core and | ||
239 | * unlogged modifications still works as described below. | ||
240 | */ | ||
241 | xfs_mark_inode_dirty_sync(ip); | ||
242 | |||
243 | /* | ||
235 | * Clear i_update_core if the timestamps (or any other | 244 | * Clear i_update_core if the timestamps (or any other |
236 | * non-transactional modification) need flushing/logging | 245 | * non-transactional modification) need flushing/logging |
237 | * and we're about to log them with the rest of the core. | 246 | * and we're about to log them with the rest of the core. |
@@ -263,14 +272,9 @@ xfs_inode_item_format( | |||
263 | } | 272 | } |
264 | 273 | ||
265 | /* | 274 | /* |
266 | * Make sure to get the latest atime from the Linux inode. | 275 | * Make sure to get the latest timestamps from the Linux inode. |
267 | */ | 276 | */ |
268 | xfs_synchronize_atime(ip); | 277 | xfs_synchronize_times(ip); |
269 | |||
270 | /* | ||
271 | * make sure the linux inode is dirty | ||
272 | */ | ||
273 | xfs_mark_inode_dirty_sync(ip); | ||
274 | 278 | ||
275 | vecp->i_addr = (xfs_caddr_t)&ip->i_d; | 279 | vecp->i_addr = (xfs_caddr_t)&ip->i_d; |
276 | vecp->i_len = sizeof(struct xfs_icdinode); | 280 | vecp->i_len = sizeof(struct xfs_icdinode); |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index b68f9107e26c..62efab2f3839 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -59,6 +59,7 @@ xfs_bulkstat_one_iget( | |||
59 | { | 59 | { |
60 | xfs_icdinode_t *dic; /* dinode core info pointer */ | 60 | xfs_icdinode_t *dic; /* dinode core info pointer */ |
61 | xfs_inode_t *ip; /* incore inode pointer */ | 61 | xfs_inode_t *ip; /* incore inode pointer */ |
62 | struct inode *inode; | ||
62 | int error; | 63 | int error; |
63 | 64 | ||
64 | error = xfs_iget(mp, NULL, ino, | 65 | error = xfs_iget(mp, NULL, ino, |
@@ -72,6 +73,7 @@ xfs_bulkstat_one_iget( | |||
72 | ASSERT(ip->i_imap.im_blkno != 0); | 73 | ASSERT(ip->i_imap.im_blkno != 0); |
73 | 74 | ||
74 | dic = &ip->i_d; | 75 | dic = &ip->i_d; |
76 | inode = VFS_I(ip); | ||
75 | 77 | ||
76 | /* xfs_iget returns the following without needing | 78 | /* xfs_iget returns the following without needing |
77 | * further change. | 79 | * further change. |
@@ -83,16 +85,19 @@ xfs_bulkstat_one_iget( | |||
83 | buf->bs_uid = dic->di_uid; | 85 | buf->bs_uid = dic->di_uid; |
84 | buf->bs_gid = dic->di_gid; | 86 | buf->bs_gid = dic->di_gid; |
85 | buf->bs_size = dic->di_size; | 87 | buf->bs_size = dic->di_size; |
88 | |||
86 | /* | 89 | /* |
87 | * We are reading the atime from the Linux inode because the | 90 | * We need to read the timestamps from the Linux inode because |
88 | * dinode might not be uptodate. | 91 | * the VFS keeps writing directly into the inode structure instead |
92 | * of telling us about the updates. | ||
89 | */ | 93 | */ |
90 | buf->bs_atime.tv_sec = VFS_I(ip)->i_atime.tv_sec; | 94 | buf->bs_atime.tv_sec = inode->i_atime.tv_sec; |
91 | buf->bs_atime.tv_nsec = VFS_I(ip)->i_atime.tv_nsec; | 95 | buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec; |
92 | buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; | 96 | buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec; |
93 | buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; | 97 | buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec; |
94 | buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; | 98 | buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec; |
95 | buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec; | 99 | buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec; |
100 | |||
96 | buf->bs_xflags = xfs_ip2xflags(ip); | 101 | buf->bs_xflags = xfs_ip2xflags(ip); |
97 | buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; | 102 | buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; |
98 | buf->bs_extents = dic->di_nextents; | 103 | buf->bs_extents = dic->di_nextents; |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index a434f287962d..b572f7e840e0 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -2476,12 +2476,6 @@ xfs_reclaim( | |||
2476 | ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); | 2476 | ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); |
2477 | 2477 | ||
2478 | /* | 2478 | /* |
2479 | * Make sure the atime in the XFS inode is correct before freeing the | ||
2480 | * Linux inode. | ||
2481 | */ | ||
2482 | xfs_synchronize_atime(ip); | ||
2483 | |||
2484 | /* | ||
2485 | * If we have nothing to flush with this inode then complete the | 2479 | * If we have nothing to flush with this inode then complete the |
2486 | * teardown now, otherwise break the link between the xfs inode and the | 2480 | * teardown now, otherwise break the link between the xfs inode and the |
2487 | * linux inode and clean up the xfs inode later. This avoids flushing | 2481 | * linux inode and clean up the xfs inode later. This avoids flushing |