diff options
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 50 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 2 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 75 | ||||
| -rw-r--r-- | fs/xfs/xfs_attr.c | 7 | ||||
| -rw-r--r-- | fs/xfs/xfs_iget.c | 13 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.h | 10 | ||||
| -rw-r--r-- | fs/xfs/xfs_log.c | 11 | ||||
| -rw-r--r-- | fs/xfs/xfs_vnodeops.c | 7 |
8 files changed, 73 insertions, 102 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index f4213ba1ff85..7f782af286bf 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
| @@ -131,19 +131,34 @@ xfs_file_fsync( | |||
| 131 | { | 131 | { |
| 132 | struct inode *inode = file->f_mapping->host; | 132 | struct inode *inode = file->f_mapping->host; |
| 133 | struct xfs_inode *ip = XFS_I(inode); | 133 | struct xfs_inode *ip = XFS_I(inode); |
| 134 | struct xfs_mount *mp = ip->i_mount; | ||
| 134 | struct xfs_trans *tp; | 135 | struct xfs_trans *tp; |
| 135 | int error = 0; | 136 | int error = 0; |
| 136 | int log_flushed = 0; | 137 | int log_flushed = 0; |
| 137 | 138 | ||
| 138 | trace_xfs_file_fsync(ip); | 139 | trace_xfs_file_fsync(ip); |
| 139 | 140 | ||
| 140 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 141 | if (XFS_FORCED_SHUTDOWN(mp)) |
| 141 | return -XFS_ERROR(EIO); | 142 | return -XFS_ERROR(EIO); |
| 142 | 143 | ||
| 143 | xfs_iflags_clear(ip, XFS_ITRUNCATED); | 144 | xfs_iflags_clear(ip, XFS_ITRUNCATED); |
| 144 | 145 | ||
| 145 | xfs_ioend_wait(ip); | 146 | xfs_ioend_wait(ip); |
| 146 | 147 | ||
| 148 | if (mp->m_flags & XFS_MOUNT_BARRIER) { | ||
| 149 | /* | ||
| 150 | * If we have an RT and/or log subvolume we need to make sure | ||
| 151 | * to flush the write cache the device used for file data | ||
| 152 | * first. This is to ensure newly written file data make | ||
| 153 | * it to disk before logging the new inode size in case of | ||
| 154 | * an extending write. | ||
| 155 | */ | ||
| 156 | if (XFS_IS_REALTIME_INODE(ip)) | ||
| 157 | xfs_blkdev_issue_flush(mp->m_rtdev_targp); | ||
| 158 | else if (mp->m_logdev_targp != mp->m_ddev_targp) | ||
| 159 | xfs_blkdev_issue_flush(mp->m_ddev_targp); | ||
| 160 | } | ||
| 161 | |||
| 147 | /* | 162 | /* |
| 148 | * We always need to make sure that the required inode state is safe on | 163 | * We always need to make sure that the required inode state is safe on |
| 149 | * disk. The inode might be clean but we still might need to force the | 164 | * disk. The inode might be clean but we still might need to force the |
| @@ -175,9 +190,9 @@ xfs_file_fsync( | |||
| 175 | * updates. The sync transaction will also force the log. | 190 | * updates. The sync transaction will also force the log. |
| 176 | */ | 191 | */ |
| 177 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 192 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
| 178 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS); | 193 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); |
| 179 | error = xfs_trans_reserve(tp, 0, | 194 | error = xfs_trans_reserve(tp, 0, |
| 180 | XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0); | 195 | XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); |
| 181 | if (error) { | 196 | if (error) { |
| 182 | xfs_trans_cancel(tp, 0); | 197 | xfs_trans_cancel(tp, 0); |
| 183 | return -error; | 198 | return -error; |
| @@ -209,28 +224,25 @@ xfs_file_fsync( | |||
| 209 | * force the log. | 224 | * force the log. |
| 210 | */ | 225 | */ |
| 211 | if (xfs_ipincount(ip)) { | 226 | if (xfs_ipincount(ip)) { |
| 212 | error = _xfs_log_force_lsn(ip->i_mount, | 227 | error = _xfs_log_force_lsn(mp, |
| 213 | ip->i_itemp->ili_last_lsn, | 228 | ip->i_itemp->ili_last_lsn, |
| 214 | XFS_LOG_SYNC, &log_flushed); | 229 | XFS_LOG_SYNC, &log_flushed); |
| 215 | } | 230 | } |
| 216 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 231 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
| 217 | } | 232 | } |
| 218 | 233 | ||
| 219 | if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) { | 234 | /* |
| 220 | /* | 235 | * If we only have a single device, and the log force about was |
| 221 | * If the log write didn't issue an ordered tag we need | 236 | * a no-op we might have to flush the data device cache here. |
| 222 | * to flush the disk cache for the data device now. | 237 | * This can only happen for fdatasync/O_DSYNC if we were overwriting |
| 223 | */ | 238 | * an already allocated file and thus do not have any metadata to |
| 224 | if (!log_flushed) | 239 | * commit. |
| 225 | xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); | 240 | */ |
| 226 | 241 | if ((mp->m_flags & XFS_MOUNT_BARRIER) && | |
| 227 | /* | 242 | mp->m_logdev_targp == mp->m_ddev_targp && |
| 228 | * If this inode is on the RT dev we need to flush that | 243 | !XFS_IS_REALTIME_INODE(ip) && |
| 229 | * cache as well. | 244 | !log_flushed) |
| 230 | */ | 245 | xfs_blkdev_issue_flush(mp->m_ddev_targp); |
| 231 | if (XFS_IS_REALTIME_INODE(ip)) | ||
| 232 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); | ||
| 233 | } | ||
| 234 | 246 | ||
| 235 | return -error; | 247 | return -error; |
| 236 | } | 248 | } |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index dd21784525a8..d44d92cd12b1 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
| @@ -182,7 +182,7 @@ xfs_vn_mknod( | |||
| 182 | if (IS_POSIXACL(dir)) { | 182 | if (IS_POSIXACL(dir)) { |
| 183 | default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); | 183 | default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); |
| 184 | if (IS_ERR(default_acl)) | 184 | if (IS_ERR(default_acl)) |
| 185 | return -PTR_ERR(default_acl); | 185 | return PTR_ERR(default_acl); |
| 186 | 186 | ||
| 187 | if (!default_acl) | 187 | if (!default_acl) |
| 188 | mode &= ~current_umask(); | 188 | mode &= ~current_umask(); |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 1e3a7ce804dc..a1a881e68a9a 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
| @@ -627,68 +627,6 @@ xfs_blkdev_put( | |||
| 627 | blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); | 627 | blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); |
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | /* | ||
| 631 | * Try to write out the superblock using barriers. | ||
| 632 | */ | ||
| 633 | STATIC int | ||
| 634 | xfs_barrier_test( | ||
| 635 | xfs_mount_t *mp) | ||
| 636 | { | ||
| 637 | xfs_buf_t *sbp = xfs_getsb(mp, 0); | ||
| 638 | int error; | ||
| 639 | |||
| 640 | XFS_BUF_UNDONE(sbp); | ||
| 641 | XFS_BUF_UNREAD(sbp); | ||
| 642 | XFS_BUF_UNDELAYWRITE(sbp); | ||
| 643 | XFS_BUF_WRITE(sbp); | ||
| 644 | XFS_BUF_UNASYNC(sbp); | ||
| 645 | XFS_BUF_ORDERED(sbp); | ||
| 646 | |||
| 647 | xfsbdstrat(mp, sbp); | ||
| 648 | error = xfs_buf_iowait(sbp); | ||
| 649 | |||
| 650 | /* | ||
| 651 | * Clear all the flags we set and possible error state in the | ||
| 652 | * buffer. We only did the write to try out whether barriers | ||
| 653 | * worked and shouldn't leave any traces in the superblock | ||
| 654 | * buffer. | ||
| 655 | */ | ||
| 656 | XFS_BUF_DONE(sbp); | ||
| 657 | XFS_BUF_ERROR(sbp, 0); | ||
| 658 | XFS_BUF_UNORDERED(sbp); | ||
| 659 | |||
| 660 | xfs_buf_relse(sbp); | ||
| 661 | return error; | ||
| 662 | } | ||
| 663 | |||
| 664 | STATIC void | ||
| 665 | xfs_mountfs_check_barriers(xfs_mount_t *mp) | ||
| 666 | { | ||
| 667 | int error; | ||
| 668 | |||
| 669 | if (mp->m_logdev_targp != mp->m_ddev_targp) { | ||
| 670 | xfs_notice(mp, | ||
| 671 | "Disabling barriers, not supported with external log device"); | ||
| 672 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
| 673 | return; | ||
| 674 | } | ||
| 675 | |||
| 676 | if (xfs_readonly_buftarg(mp->m_ddev_targp)) { | ||
| 677 | xfs_notice(mp, | ||
| 678 | "Disabling barriers, underlying device is readonly"); | ||
| 679 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
| 680 | return; | ||
| 681 | } | ||
| 682 | |||
| 683 | error = xfs_barrier_test(mp); | ||
| 684 | if (error) { | ||
| 685 | xfs_notice(mp, | ||
| 686 | "Disabling barriers, trial barrier write failed"); | ||
| 687 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | } | ||
| 691 | |||
| 692 | void | 630 | void |
| 693 | xfs_blkdev_issue_flush( | 631 | xfs_blkdev_issue_flush( |
| 694 | xfs_buftarg_t *buftarg) | 632 | xfs_buftarg_t *buftarg) |
| @@ -1240,14 +1178,6 @@ xfs_fs_remount( | |||
| 1240 | switch (token) { | 1178 | switch (token) { |
| 1241 | case Opt_barrier: | 1179 | case Opt_barrier: |
| 1242 | mp->m_flags |= XFS_MOUNT_BARRIER; | 1180 | mp->m_flags |= XFS_MOUNT_BARRIER; |
| 1243 | |||
| 1244 | /* | ||
| 1245 | * Test if barriers are actually working if we can, | ||
| 1246 | * else delay this check until the filesystem is | ||
| 1247 | * marked writeable. | ||
| 1248 | */ | ||
| 1249 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) | ||
| 1250 | xfs_mountfs_check_barriers(mp); | ||
| 1251 | break; | 1181 | break; |
| 1252 | case Opt_nobarrier: | 1182 | case Opt_nobarrier: |
| 1253 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 1183 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
| @@ -1282,8 +1212,6 @@ xfs_fs_remount( | |||
| 1282 | /* ro -> rw */ | 1212 | /* ro -> rw */ |
| 1283 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { | 1213 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { |
| 1284 | mp->m_flags &= ~XFS_MOUNT_RDONLY; | 1214 | mp->m_flags &= ~XFS_MOUNT_RDONLY; |
| 1285 | if (mp->m_flags & XFS_MOUNT_BARRIER) | ||
| 1286 | xfs_mountfs_check_barriers(mp); | ||
| 1287 | 1215 | ||
| 1288 | /* | 1216 | /* |
| 1289 | * If this is the first remount to writeable state we | 1217 | * If this is the first remount to writeable state we |
| @@ -1465,9 +1393,6 @@ xfs_fs_fill_super( | |||
| 1465 | if (error) | 1393 | if (error) |
| 1466 | goto out_free_sb; | 1394 | goto out_free_sb; |
| 1467 | 1395 | ||
| 1468 | if (mp->m_flags & XFS_MOUNT_BARRIER) | ||
| 1469 | xfs_mountfs_check_barriers(mp); | ||
| 1470 | |||
| 1471 | error = xfs_filestream_mount(mp); | 1396 | error = xfs_filestream_mount(mp); |
| 1472 | if (error) | 1397 | if (error) |
| 1473 | goto out_free_sb; | 1398 | goto out_free_sb; |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index c86375378810..01d2072fb6d4 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
| @@ -490,6 +490,13 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
| 490 | args.whichfork = XFS_ATTR_FORK; | 490 | args.whichfork = XFS_ATTR_FORK; |
| 491 | 491 | ||
| 492 | /* | 492 | /* |
| 493 | * we have no control over the attribute names that userspace passes us | ||
| 494 | * to remove, so we have to allow the name lookup prior to attribute | ||
| 495 | * removal to fail. | ||
| 496 | */ | ||
| 497 | args.op_flags = XFS_DA_OP_OKNOENT; | ||
| 498 | |||
| 499 | /* | ||
| 493 | * Attach the dquots to the inode. | 500 | * Attach the dquots to the inode. |
| 494 | */ | 501 | */ |
| 495 | error = xfs_qm_dqattach(dp, 0); | 502 | error = xfs_qm_dqattach(dp, 0); |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index cb9b6d1469f7..3631783b2b53 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
| @@ -253,16 +253,21 @@ xfs_iget_cache_hit( | |||
| 253 | rcu_read_lock(); | 253 | rcu_read_lock(); |
| 254 | spin_lock(&ip->i_flags_lock); | 254 | spin_lock(&ip->i_flags_lock); |
| 255 | 255 | ||
| 256 | ip->i_flags &= ~XFS_INEW; | 256 | ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM); |
| 257 | ip->i_flags |= XFS_IRECLAIMABLE; | 257 | ASSERT(ip->i_flags & XFS_IRECLAIMABLE); |
| 258 | __xfs_inode_set_reclaim_tag(pag, ip); | ||
| 259 | trace_xfs_iget_reclaim_fail(ip); | 258 | trace_xfs_iget_reclaim_fail(ip); |
| 260 | goto out_error; | 259 | goto out_error; |
| 261 | } | 260 | } |
| 262 | 261 | ||
| 263 | spin_lock(&pag->pag_ici_lock); | 262 | spin_lock(&pag->pag_ici_lock); |
| 264 | spin_lock(&ip->i_flags_lock); | 263 | spin_lock(&ip->i_flags_lock); |
| 265 | ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM); | 264 | |
| 265 | /* | ||
| 266 | * Clear the per-lifetime state in the inode as we are now | ||
| 267 | * effectively a new inode and need to return to the initial | ||
| 268 | * state before reuse occurs. | ||
| 269 | */ | ||
| 270 | ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS; | ||
| 266 | ip->i_flags |= XFS_INEW; | 271 | ip->i_flags |= XFS_INEW; |
| 267 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | 272 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); |
| 268 | inode->i_state = I_NEW; | 273 | inode->i_state = I_NEW; |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 3ae6d58e5473..964cfea77686 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
| @@ -384,6 +384,16 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) | |||
| 384 | #define XFS_IDIRTY_RELEASE 0x0040 /* dirty release already seen */ | 384 | #define XFS_IDIRTY_RELEASE 0x0040 /* dirty release already seen */ |
| 385 | 385 | ||
| 386 | /* | 386 | /* |
| 387 | * Per-lifetime flags need to be reset when re-using a reclaimable inode during | ||
| 388 | * inode lookup. Thi prevents unintended behaviour on the new inode from | ||
| 389 | * ocurring. | ||
| 390 | */ | ||
| 391 | #define XFS_IRECLAIM_RESET_FLAGS \ | ||
| 392 | (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ | ||
| 393 | XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \ | ||
| 394 | XFS_IFILESTREAM); | ||
| 395 | |||
| 396 | /* | ||
| 387 | * Flags for inode locking. | 397 | * Flags for inode locking. |
| 388 | * Bit ranges: 1<<1 - 1<<16-1 -- iolock/ilock modes (bitfield) | 398 | * Bit ranges: 1<<1 - 1<<16-1 -- iolock/ilock modes (bitfield) |
| 389 | * 1<<16 - 1<<32-1 -- lockdep annotation (integers) | 399 | * 1<<16 - 1<<32-1 -- lockdep annotation (integers) |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 211930246f20..41d5b8f2bf92 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -1372,8 +1372,17 @@ xlog_sync(xlog_t *log, | |||
| 1372 | XFS_BUF_ASYNC(bp); | 1372 | XFS_BUF_ASYNC(bp); |
| 1373 | bp->b_flags |= XBF_LOG_BUFFER; | 1373 | bp->b_flags |= XBF_LOG_BUFFER; |
| 1374 | 1374 | ||
| 1375 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) | 1375 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) { |
| 1376 | /* | ||
| 1377 | * If we have an external log device, flush the data device | ||
| 1378 | * before flushing the log to make sure all meta data | ||
| 1379 | * written back from the AIL actually made it to disk | ||
| 1380 | * before writing out the new log tail LSN in the log buffer. | ||
| 1381 | */ | ||
| 1382 | if (log->l_mp->m_logdev_targp != log->l_mp->m_ddev_targp) | ||
| 1383 | xfs_blkdev_issue_flush(log->l_mp->m_ddev_targp); | ||
| 1376 | XFS_BUF_ORDERED(bp); | 1384 | XFS_BUF_ORDERED(bp); |
| 1385 | } | ||
| 1377 | 1386 | ||
| 1378 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); | 1387 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); |
| 1379 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); | 1388 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index b7a5fe7c52c8..619720705bc6 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -960,8 +960,11 @@ xfs_release( | |||
| 960 | * be exposed to that problem. | 960 | * be exposed to that problem. |
| 961 | */ | 961 | */ |
| 962 | truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); | 962 | truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); |
| 963 | if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) | 963 | if (truncated) { |
| 964 | xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE); | 964 | xfs_iflags_clear(ip, XFS_IDIRTY_RELEASE); |
| 965 | if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) | ||
| 966 | xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE); | ||
| 967 | } | ||
| 965 | } | 968 | } |
| 966 | 969 | ||
| 967 | if (ip->i_d.di_nlink == 0) | 970 | if (ip->i_d.di_nlink == 0) |
