diff options
| -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_vnodeops.c | 7 |
4 files changed, 31 insertions, 6 deletions
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_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) |
