diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-09 16:29:42 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-10-09 16:29:42 -0400 | 
| commit | a372bf8b6a12f23f68e716113ccaea4bf646dd0f (patch) | |
| tree | 3852e11c78e5dea779f49e9a94288c8ac827e821 /fs/xfs | |
| parent | 0d5d1aadc8e299874a6a014d65b6bb903b12424d (diff) | |
| parent | e09d39968bd8befa087f10f970fa236e8694b643 (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')
| -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 | 
