aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r--fs/xfs/xfs_inode.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 1f8ecff8553a..c27d7d495aa0 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -854,7 +854,8 @@ xfs_iread(
854 xfs_trans_t *tp, 854 xfs_trans_t *tp,
855 xfs_ino_t ino, 855 xfs_ino_t ino,
856 xfs_inode_t **ipp, 856 xfs_inode_t **ipp,
857 xfs_daddr_t bno) 857 xfs_daddr_t bno,
858 uint imap_flags)
858{ 859{
859 xfs_buf_t *bp; 860 xfs_buf_t *bp;
860 xfs_dinode_t *dip; 861 xfs_dinode_t *dip;
@@ -866,6 +867,7 @@ xfs_iread(
866 ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP); 867 ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
867 ip->i_ino = ino; 868 ip->i_ino = ino;
868 ip->i_mount = mp; 869 ip->i_mount = mp;
870 spin_lock_init(&ip->i_flags_lock);
869 871
870 /* 872 /*
871 * Get pointer's to the on-disk inode and the buffer containing it. 873 * Get pointer's to the on-disk inode and the buffer containing it.
@@ -874,7 +876,7 @@ xfs_iread(
874 * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will 876 * return NULL as well. Set i_blkno to 0 so that xfs_itobp() will
875 * know that this is a new incore inode. 877 * know that this is a new incore inode.
876 */ 878 */
877 error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, 0); 879 error = xfs_itobp(mp, tp, ip, &dip, &bp, bno, imap_flags);
878 if (error) { 880 if (error) {
879 kmem_zone_free(xfs_inode_zone, ip); 881 kmem_zone_free(xfs_inode_zone, ip);
880 return error; 882 return error;
@@ -1113,7 +1115,7 @@ xfs_ialloc(
1113 * to prevent others from looking at until we're done. 1115 * to prevent others from looking at until we're done.
1114 */ 1116 */
1115 error = xfs_trans_iget(tp->t_mountp, tp, ino, 1117 error = xfs_trans_iget(tp->t_mountp, tp, ino,
1116 IGET_CREATE, XFS_ILOCK_EXCL, &ip); 1118 XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip);
1117 if (error != 0) { 1119 if (error != 0) {
1118 return error; 1120 return error;
1119 } 1121 }
@@ -2213,7 +2215,9 @@ xfs_ifree_cluster(
2213 2215
2214 if (ip == free_ip) { 2216 if (ip == free_ip) {
2215 if (xfs_iflock_nowait(ip)) { 2217 if (xfs_iflock_nowait(ip)) {
2218 spin_lock(&ip->i_flags_lock);
2216 ip->i_flags |= XFS_ISTALE; 2219 ip->i_flags |= XFS_ISTALE;
2220 spin_unlock(&ip->i_flags_lock);
2217 2221
2218 if (xfs_inode_clean(ip)) { 2222 if (xfs_inode_clean(ip)) {
2219 xfs_ifunlock(ip); 2223 xfs_ifunlock(ip);
@@ -2227,7 +2231,9 @@ xfs_ifree_cluster(
2227 2231
2228 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { 2232 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) {
2229 if (xfs_iflock_nowait(ip)) { 2233 if (xfs_iflock_nowait(ip)) {
2234 spin_lock(&ip->i_flags_lock);
2230 ip->i_flags |= XFS_ISTALE; 2235 ip->i_flags |= XFS_ISTALE;
2236 spin_unlock(&ip->i_flags_lock);
2231 2237
2232 if (xfs_inode_clean(ip)) { 2238 if (xfs_inode_clean(ip)) {
2233 xfs_ifunlock(ip); 2239 xfs_ifunlock(ip);
@@ -2257,7 +2263,9 @@ xfs_ifree_cluster(
2257 AIL_LOCK(mp,s); 2263 AIL_LOCK(mp,s);
2258 iip->ili_flush_lsn = iip->ili_item.li_lsn; 2264 iip->ili_flush_lsn = iip->ili_item.li_lsn;
2259 AIL_UNLOCK(mp, s); 2265 AIL_UNLOCK(mp, s);
2266 spin_lock(&iip->ili_inode->i_flags_lock);
2260 iip->ili_inode->i_flags |= XFS_ISTALE; 2267 iip->ili_inode->i_flags |= XFS_ISTALE;
2268 spin_unlock(&iip->ili_inode->i_flags_lock);
2261 pre_flushed++; 2269 pre_flushed++;
2262 } 2270 }
2263 lip = lip->li_bio_list; 2271 lip = lip->li_bio_list;
@@ -2753,19 +2761,29 @@ xfs_iunpin(
2753 * call as the inode reclaim may be blocked waiting for 2761 * call as the inode reclaim may be blocked waiting for
2754 * the inode to become unpinned. 2762 * the inode to become unpinned.
2755 */ 2763 */
2764 struct inode *inode = NULL;
2765
2766 spin_lock(&ip->i_flags_lock);
2756 if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { 2767 if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
2757 bhv_vnode_t *vp = XFS_ITOV_NULL(ip); 2768 bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
2758 2769
2759 /* make sync come back and flush this inode */ 2770 /* make sync come back and flush this inode */
2760 if (vp) { 2771 if (vp) {
2761 struct inode *inode = vn_to_inode(vp); 2772 inode = vn_to_inode(vp);
2762 2773
2763 if (!(inode->i_state & 2774 if (!(inode->i_state &
2764 (I_NEW|I_FREEING|I_CLEAR))) 2775 (I_NEW|I_FREEING|I_CLEAR))) {
2765 mark_inode_dirty_sync(inode); 2776 inode = igrab(inode);
2777 if (inode)
2778 mark_inode_dirty_sync(inode);
2779 } else
2780 inode = NULL;
2766 } 2781 }
2767 } 2782 }
2783 spin_unlock(&ip->i_flags_lock);
2768 wake_up(&ip->i_ipin_wait); 2784 wake_up(&ip->i_ipin_wait);
2785 if (inode)
2786 iput(inode);
2769 } 2787 }
2770} 2788}
2771 2789