diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 274 |
1 files changed, 35 insertions, 239 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 6650601c64f7..70702a60b4bb 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -76,132 +76,6 @@ xfs_open( | |||
76 | } | 76 | } |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * xfs_getattr | ||
80 | */ | ||
81 | int | ||
82 | xfs_getattr( | ||
83 | xfs_inode_t *ip, | ||
84 | bhv_vattr_t *vap, | ||
85 | int flags) | ||
86 | { | ||
87 | bhv_vnode_t *vp = XFS_ITOV(ip); | ||
88 | xfs_mount_t *mp = ip->i_mount; | ||
89 | |||
90 | xfs_itrace_entry(ip); | ||
91 | |||
92 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
93 | return XFS_ERROR(EIO); | ||
94 | |||
95 | if (!(flags & ATTR_LAZY)) | ||
96 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
97 | |||
98 | vap->va_size = XFS_ISIZE(ip); | ||
99 | if (vap->va_mask == XFS_AT_SIZE) | ||
100 | goto all_done; | ||
101 | |||
102 | vap->va_nblocks = | ||
103 | XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks); | ||
104 | vap->va_nodeid = ip->i_ino; | ||
105 | #if XFS_BIG_INUMS | ||
106 | vap->va_nodeid += mp->m_inoadd; | ||
107 | #endif | ||
108 | vap->va_nlink = ip->i_d.di_nlink; | ||
109 | |||
110 | /* | ||
111 | * Quick exit for non-stat callers | ||
112 | */ | ||
113 | if ((vap->va_mask & | ||
114 | ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID| | ||
115 | XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0) | ||
116 | goto all_done; | ||
117 | |||
118 | /* | ||
119 | * Copy from in-core inode. | ||
120 | */ | ||
121 | vap->va_mode = ip->i_d.di_mode; | ||
122 | vap->va_uid = ip->i_d.di_uid; | ||
123 | vap->va_gid = ip->i_d.di_gid; | ||
124 | vap->va_projid = ip->i_d.di_projid; | ||
125 | |||
126 | /* | ||
127 | * Check vnode type block/char vs. everything else. | ||
128 | */ | ||
129 | switch (ip->i_d.di_mode & S_IFMT) { | ||
130 | case S_IFBLK: | ||
131 | case S_IFCHR: | ||
132 | vap->va_rdev = ip->i_df.if_u2.if_rdev; | ||
133 | vap->va_blocksize = BLKDEV_IOSIZE; | ||
134 | break; | ||
135 | default: | ||
136 | vap->va_rdev = 0; | ||
137 | |||
138 | if (!(XFS_IS_REALTIME_INODE(ip))) { | ||
139 | vap->va_blocksize = xfs_preferred_iosize(mp); | ||
140 | } else { | ||
141 | |||
142 | /* | ||
143 | * If the file blocks are being allocated from a | ||
144 | * realtime partition, then return the inode's | ||
145 | * realtime extent size or the realtime volume's | ||
146 | * extent size. | ||
147 | */ | ||
148 | vap->va_blocksize = | ||
149 | xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog; | ||
150 | } | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | vn_atime_to_timespec(vp, &vap->va_atime); | ||
155 | vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec; | ||
156 | vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; | ||
157 | vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec; | ||
158 | vap->va_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; | ||
159 | |||
160 | /* | ||
161 | * Exit for stat callers. See if any of the rest of the fields | ||
162 | * to be filled in are needed. | ||
163 | */ | ||
164 | if ((vap->va_mask & | ||
165 | (XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS| | ||
166 | XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0) | ||
167 | goto all_done; | ||
168 | |||
169 | /* | ||
170 | * Convert di_flags to xflags. | ||
171 | */ | ||
172 | vap->va_xflags = xfs_ip2xflags(ip); | ||
173 | |||
174 | /* | ||
175 | * Exit for inode revalidate. See if any of the rest of | ||
176 | * the fields to be filled in are needed. | ||
177 | */ | ||
178 | if ((vap->va_mask & | ||
179 | (XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS| | ||
180 | XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0) | ||
181 | goto all_done; | ||
182 | |||
183 | vap->va_extsize = ip->i_d.di_extsize << mp->m_sb.sb_blocklog; | ||
184 | vap->va_nextents = | ||
185 | (ip->i_df.if_flags & XFS_IFEXTENTS) ? | ||
186 | ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) : | ||
187 | ip->i_d.di_nextents; | ||
188 | if (ip->i_afp) | ||
189 | vap->va_anextents = | ||
190 | (ip->i_afp->if_flags & XFS_IFEXTENTS) ? | ||
191 | ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) : | ||
192 | ip->i_d.di_anextents; | ||
193 | else | ||
194 | vap->va_anextents = 0; | ||
195 | vap->va_gen = ip->i_d.di_gen; | ||
196 | |||
197 | all_done: | ||
198 | if (!(flags & ATTR_LAZY)) | ||
199 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | |||
204 | /* | ||
205 | * xfs_setattr | 79 | * xfs_setattr |
206 | */ | 80 | */ |
207 | int | 81 | int |
@@ -211,7 +85,6 @@ xfs_setattr( | |||
211 | int flags, | 85 | int flags, |
212 | cred_t *credp) | 86 | cred_t *credp) |
213 | { | 87 | { |
214 | bhv_vnode_t *vp = XFS_ITOV(ip); | ||
215 | xfs_mount_t *mp = ip->i_mount; | 88 | xfs_mount_t *mp = ip->i_mount; |
216 | xfs_trans_t *tp; | 89 | xfs_trans_t *tp; |
217 | int mask; | 90 | int mask; |
@@ -222,7 +95,6 @@ xfs_setattr( | |||
222 | gid_t gid=0, igid=0; | 95 | gid_t gid=0, igid=0; |
223 | int timeflags = 0; | 96 | int timeflags = 0; |
224 | xfs_prid_t projid=0, iprojid=0; | 97 | xfs_prid_t projid=0, iprojid=0; |
225 | int mandlock_before, mandlock_after; | ||
226 | struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; | 98 | struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; |
227 | int file_owner; | 99 | int file_owner; |
228 | int need_iolock = 1; | 100 | int need_iolock = 1; |
@@ -383,7 +255,7 @@ xfs_setattr( | |||
383 | m |= S_ISGID; | 255 | m |= S_ISGID; |
384 | #if 0 | 256 | #if 0 |
385 | /* Linux allows this, Irix doesn't. */ | 257 | /* Linux allows this, Irix doesn't. */ |
386 | if ((vap->va_mode & S_ISVTX) && !VN_ISDIR(vp)) | 258 | if ((vap->va_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode)) |
387 | m |= S_ISVTX; | 259 | m |= S_ISVTX; |
388 | #endif | 260 | #endif |
389 | if (m && !capable(CAP_FSETID)) | 261 | if (m && !capable(CAP_FSETID)) |
@@ -461,10 +333,10 @@ xfs_setattr( | |||
461 | goto error_return; | 333 | goto error_return; |
462 | } | 334 | } |
463 | 335 | ||
464 | if (VN_ISDIR(vp)) { | 336 | if (S_ISDIR(ip->i_d.di_mode)) { |
465 | code = XFS_ERROR(EISDIR); | 337 | code = XFS_ERROR(EISDIR); |
466 | goto error_return; | 338 | goto error_return; |
467 | } else if (!VN_ISREG(vp)) { | 339 | } else if (!S_ISREG(ip->i_d.di_mode)) { |
468 | code = XFS_ERROR(EINVAL); | 340 | code = XFS_ERROR(EINVAL); |
469 | goto error_return; | 341 | goto error_return; |
470 | } | 342 | } |
@@ -626,9 +498,6 @@ xfs_setattr( | |||
626 | xfs_trans_ihold(tp, ip); | 498 | xfs_trans_ihold(tp, ip); |
627 | } | 499 | } |
628 | 500 | ||
629 | /* determine whether mandatory locking mode changes */ | ||
630 | mandlock_before = MANDLOCK(vp, ip->i_d.di_mode); | ||
631 | |||
632 | /* | 501 | /* |
633 | * Truncate file. Must have write permission and not be a directory. | 502 | * Truncate file. Must have write permission and not be a directory. |
634 | */ | 503 | */ |
@@ -858,13 +727,6 @@ xfs_setattr( | |||
858 | code = xfs_trans_commit(tp, commit_flags); | 727 | code = xfs_trans_commit(tp, commit_flags); |
859 | } | 728 | } |
860 | 729 | ||
861 | /* | ||
862 | * If the (regular) file's mandatory locking mode changed, then | ||
863 | * notify the vnode. We do this under the inode lock to prevent | ||
864 | * racing calls to vop_vnode_change. | ||
865 | */ | ||
866 | mandlock_after = MANDLOCK(vp, ip->i_d.di_mode); | ||
867 | |||
868 | xfs_iunlock(ip, lock_flags); | 730 | xfs_iunlock(ip, lock_flags); |
869 | 731 | ||
870 | /* | 732 | /* |
@@ -1443,7 +1305,7 @@ xfs_inactive_attrs( | |||
1443 | int error; | 1305 | int error; |
1444 | xfs_mount_t *mp; | 1306 | xfs_mount_t *mp; |
1445 | 1307 | ||
1446 | ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE)); | 1308 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); |
1447 | tp = *tpp; | 1309 | tp = *tpp; |
1448 | mp = ip->i_mount; | 1310 | mp = ip->i_mount; |
1449 | ASSERT(ip->i_d.di_forkoff != 0); | 1311 | ASSERT(ip->i_d.di_forkoff != 0); |
@@ -1491,7 +1353,7 @@ xfs_release( | |||
1491 | xfs_mount_t *mp = ip->i_mount; | 1353 | xfs_mount_t *mp = ip->i_mount; |
1492 | int error; | 1354 | int error; |
1493 | 1355 | ||
1494 | if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) | 1356 | if (!S_ISREG(ip->i_d.di_mode) || (ip->i_d.di_mode == 0)) |
1495 | return 0; | 1357 | return 0; |
1496 | 1358 | ||
1497 | /* If this is a read-only mount, don't do this (would generate I/O) */ | 1359 | /* If this is a read-only mount, don't do this (would generate I/O) */ |
@@ -1774,8 +1636,7 @@ xfs_lookup( | |||
1774 | struct xfs_name *name, | 1636 | struct xfs_name *name, |
1775 | xfs_inode_t **ipp) | 1637 | xfs_inode_t **ipp) |
1776 | { | 1638 | { |
1777 | xfs_inode_t *ip; | 1639 | xfs_ino_t inum; |
1778 | xfs_ino_t e_inum; | ||
1779 | int error; | 1640 | int error; |
1780 | uint lock_mode; | 1641 | uint lock_mode; |
1781 | 1642 | ||
@@ -1785,12 +1646,21 @@ xfs_lookup( | |||
1785 | return XFS_ERROR(EIO); | 1646 | return XFS_ERROR(EIO); |
1786 | 1647 | ||
1787 | lock_mode = xfs_ilock_map_shared(dp); | 1648 | lock_mode = xfs_ilock_map_shared(dp); |
1788 | error = xfs_dir_lookup_int(dp, lock_mode, name, &e_inum, &ip); | 1649 | error = xfs_dir_lookup(NULL, dp, name, &inum); |
1789 | if (!error) { | ||
1790 | *ipp = ip; | ||
1791 | xfs_itrace_ref(ip); | ||
1792 | } | ||
1793 | xfs_iunlock_map_shared(dp, lock_mode); | 1650 | xfs_iunlock_map_shared(dp, lock_mode); |
1651 | |||
1652 | if (error) | ||
1653 | goto out; | ||
1654 | |||
1655 | error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0); | ||
1656 | if (error) | ||
1657 | goto out; | ||
1658 | |||
1659 | xfs_itrace_ref(*ipp); | ||
1660 | return 0; | ||
1661 | |||
1662 | out: | ||
1663 | *ipp = NULL; | ||
1794 | return error; | 1664 | return error; |
1795 | } | 1665 | } |
1796 | 1666 | ||
@@ -1906,7 +1776,7 @@ xfs_create( | |||
1906 | * It is locked (and joined to the transaction). | 1776 | * It is locked (and joined to the transaction). |
1907 | */ | 1777 | */ |
1908 | 1778 | ||
1909 | ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE)); | 1779 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
1910 | 1780 | ||
1911 | /* | 1781 | /* |
1912 | * Now we join the directory inode to the transaction. We do not do it | 1782 | * Now we join the directory inode to the transaction. We do not do it |
@@ -2112,7 +1982,7 @@ again: | |||
2112 | 1982 | ||
2113 | ips[0] = ip; | 1983 | ips[0] = ip; |
2114 | ips[1] = dp; | 1984 | ips[1] = dp; |
2115 | xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL); | 1985 | xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); |
2116 | } | 1986 | } |
2117 | /* else e_inum == dp->i_ino */ | 1987 | /* else e_inum == dp->i_ino */ |
2118 | /* This can happen if we're asked to lock /x/.. | 1988 | /* This can happen if we're asked to lock /x/.. |
@@ -2160,7 +2030,6 @@ void | |||
2160 | xfs_lock_inodes( | 2030 | xfs_lock_inodes( |
2161 | xfs_inode_t **ips, | 2031 | xfs_inode_t **ips, |
2162 | int inodes, | 2032 | int inodes, |
2163 | int first_locked, | ||
2164 | uint lock_mode) | 2033 | uint lock_mode) |
2165 | { | 2034 | { |
2166 | int attempts = 0, i, j, try_lock; | 2035 | int attempts = 0, i, j, try_lock; |
@@ -2168,13 +2037,8 @@ xfs_lock_inodes( | |||
2168 | 2037 | ||
2169 | ASSERT(ips && (inodes >= 2)); /* we need at least two */ | 2038 | ASSERT(ips && (inodes >= 2)); /* we need at least two */ |
2170 | 2039 | ||
2171 | if (first_locked) { | 2040 | try_lock = 0; |
2172 | try_lock = 1; | 2041 | i = 0; |
2173 | i = 1; | ||
2174 | } else { | ||
2175 | try_lock = 0; | ||
2176 | i = 0; | ||
2177 | } | ||
2178 | 2042 | ||
2179 | again: | 2043 | again: |
2180 | for (; i < inodes; i++) { | 2044 | for (; i < inodes; i++) { |
@@ -2298,29 +2162,14 @@ xfs_remove( | |||
2298 | return error; | 2162 | return error; |
2299 | } | 2163 | } |
2300 | 2164 | ||
2301 | /* | ||
2302 | * We need to get a reference to ip before we get our log | ||
2303 | * reservation. The reason for this is that we cannot call | ||
2304 | * xfs_iget for an inode for which we do not have a reference | ||
2305 | * once we've acquired a log reservation. This is because the | ||
2306 | * inode we are trying to get might be in xfs_inactive going | ||
2307 | * for a log reservation. Since we'll have to wait for the | ||
2308 | * inactive code to complete before returning from xfs_iget, | ||
2309 | * we need to make sure that we don't have log space reserved | ||
2310 | * when we call xfs_iget. Instead we get an unlocked reference | ||
2311 | * to the inode before getting our log reservation. | ||
2312 | */ | ||
2313 | IHOLD(ip); | ||
2314 | |||
2315 | xfs_itrace_entry(ip); | 2165 | xfs_itrace_entry(ip); |
2316 | xfs_itrace_ref(ip); | 2166 | xfs_itrace_ref(ip); |
2317 | 2167 | ||
2318 | error = XFS_QM_DQATTACH(mp, dp, 0); | 2168 | error = XFS_QM_DQATTACH(mp, dp, 0); |
2319 | if (!error && dp != ip) | 2169 | if (!error) |
2320 | error = XFS_QM_DQATTACH(mp, ip, 0); | 2170 | error = XFS_QM_DQATTACH(mp, ip, 0); |
2321 | if (error) { | 2171 | if (error) { |
2322 | REMOVE_DEBUG_TRACE(__LINE__); | 2172 | REMOVE_DEBUG_TRACE(__LINE__); |
2323 | IRELE(ip); | ||
2324 | goto std_return; | 2173 | goto std_return; |
2325 | } | 2174 | } |
2326 | 2175 | ||
@@ -2347,7 +2196,6 @@ xfs_remove( | |||
2347 | ASSERT(error != ENOSPC); | 2196 | ASSERT(error != ENOSPC); |
2348 | REMOVE_DEBUG_TRACE(__LINE__); | 2197 | REMOVE_DEBUG_TRACE(__LINE__); |
2349 | xfs_trans_cancel(tp, 0); | 2198 | xfs_trans_cancel(tp, 0); |
2350 | IRELE(ip); | ||
2351 | return error; | 2199 | return error; |
2352 | } | 2200 | } |
2353 | 2201 | ||
@@ -2355,7 +2203,6 @@ xfs_remove( | |||
2355 | if (error) { | 2203 | if (error) { |
2356 | REMOVE_DEBUG_TRACE(__LINE__); | 2204 | REMOVE_DEBUG_TRACE(__LINE__); |
2357 | xfs_trans_cancel(tp, cancel_flags); | 2205 | xfs_trans_cancel(tp, cancel_flags); |
2358 | IRELE(ip); | ||
2359 | goto std_return; | 2206 | goto std_return; |
2360 | } | 2207 | } |
2361 | 2208 | ||
@@ -2363,23 +2210,18 @@ xfs_remove( | |||
2363 | * At this point, we've gotten both the directory and the entry | 2210 | * At this point, we've gotten both the directory and the entry |
2364 | * inodes locked. | 2211 | * inodes locked. |
2365 | */ | 2212 | */ |
2213 | IHOLD(ip); | ||
2366 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | 2214 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); |
2367 | if (dp != ip) { | 2215 | |
2368 | /* | 2216 | IHOLD(dp); |
2369 | * Increment vnode ref count only in this case since | 2217 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
2370 | * there's an extra vnode reference in the case where | ||
2371 | * dp == ip. | ||
2372 | */ | ||
2373 | IHOLD(dp); | ||
2374 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
2375 | } | ||
2376 | 2218 | ||
2377 | /* | 2219 | /* |
2378 | * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. | 2220 | * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. |
2379 | */ | 2221 | */ |
2380 | XFS_BMAP_INIT(&free_list, &first_block); | 2222 | XFS_BMAP_INIT(&free_list, &first_block); |
2381 | error = xfs_dir_removename(tp, dp, name, ip->i_ino, | 2223 | error = xfs_dir_removename(tp, dp, name, ip->i_ino, |
2382 | &first_block, &free_list, 0); | 2224 | &first_block, &free_list, resblks); |
2383 | if (error) { | 2225 | if (error) { |
2384 | ASSERT(error != ENOENT); | 2226 | ASSERT(error != ENOENT); |
2385 | REMOVE_DEBUG_TRACE(__LINE__); | 2227 | REMOVE_DEBUG_TRACE(__LINE__); |
@@ -2402,12 +2244,6 @@ xfs_remove( | |||
2402 | link_zero = (ip)->i_d.di_nlink==0; | 2244 | link_zero = (ip)->i_d.di_nlink==0; |
2403 | 2245 | ||
2404 | /* | 2246 | /* |
2405 | * Take an extra ref on the inode so that it doesn't | ||
2406 | * go to xfs_inactive() from within the commit. | ||
2407 | */ | ||
2408 | IHOLD(ip); | ||
2409 | |||
2410 | /* | ||
2411 | * If this is a synchronous mount, make sure that the | 2247 | * If this is a synchronous mount, make sure that the |
2412 | * remove transaction goes to disk before returning to | 2248 | * remove transaction goes to disk before returning to |
2413 | * the user. | 2249 | * the user. |
@@ -2423,10 +2259,8 @@ xfs_remove( | |||
2423 | } | 2259 | } |
2424 | 2260 | ||
2425 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 2261 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
2426 | if (error) { | 2262 | if (error) |
2427 | IRELE(ip); | ||
2428 | goto std_return; | 2263 | goto std_return; |
2429 | } | ||
2430 | 2264 | ||
2431 | /* | 2265 | /* |
2432 | * If we are using filestreams, kill the stream association. | 2266 | * If we are using filestreams, kill the stream association. |
@@ -2438,7 +2272,6 @@ xfs_remove( | |||
2438 | xfs_filestream_deassociate(ip); | 2272 | xfs_filestream_deassociate(ip); |
2439 | 2273 | ||
2440 | xfs_itrace_exit(ip); | 2274 | xfs_itrace_exit(ip); |
2441 | IRELE(ip); | ||
2442 | 2275 | ||
2443 | /* Fall through to std_return with error = 0 */ | 2276 | /* Fall through to std_return with error = 0 */ |
2444 | std_return: | 2277 | std_return: |
@@ -2467,8 +2300,6 @@ xfs_remove( | |||
2467 | cancel_flags |= XFS_TRANS_ABORT; | 2300 | cancel_flags |= XFS_TRANS_ABORT; |
2468 | xfs_trans_cancel(tp, cancel_flags); | 2301 | xfs_trans_cancel(tp, cancel_flags); |
2469 | 2302 | ||
2470 | IRELE(ip); | ||
2471 | |||
2472 | goto std_return; | 2303 | goto std_return; |
2473 | } | 2304 | } |
2474 | 2305 | ||
@@ -2536,7 +2367,7 @@ xfs_link( | |||
2536 | ips[1] = sip; | 2367 | ips[1] = sip; |
2537 | } | 2368 | } |
2538 | 2369 | ||
2539 | xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL); | 2370 | xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL); |
2540 | 2371 | ||
2541 | /* | 2372 | /* |
2542 | * Increment vnode ref counts since xfs_trans_commit & | 2373 | * Increment vnode ref counts since xfs_trans_commit & |
@@ -2840,7 +2671,6 @@ xfs_rmdir( | |||
2840 | struct xfs_name *name, | 2671 | struct xfs_name *name, |
2841 | xfs_inode_t *cdp) | 2672 | xfs_inode_t *cdp) |
2842 | { | 2673 | { |
2843 | bhv_vnode_t *dir_vp = XFS_ITOV(dp); | ||
2844 | xfs_mount_t *mp = dp->i_mount; | 2674 | xfs_mount_t *mp = dp->i_mount; |
2845 | xfs_trans_t *tp; | 2675 | xfs_trans_t *tp; |
2846 | int error; | 2676 | int error; |
@@ -2866,27 +2696,12 @@ xfs_rmdir( | |||
2866 | } | 2696 | } |
2867 | 2697 | ||
2868 | /* | 2698 | /* |
2869 | * We need to get a reference to cdp before we get our log | ||
2870 | * reservation. The reason for this is that we cannot call | ||
2871 | * xfs_iget for an inode for which we do not have a reference | ||
2872 | * once we've acquired a log reservation. This is because the | ||
2873 | * inode we are trying to get might be in xfs_inactive going | ||
2874 | * for a log reservation. Since we'll have to wait for the | ||
2875 | * inactive code to complete before returning from xfs_iget, | ||
2876 | * we need to make sure that we don't have log space reserved | ||
2877 | * when we call xfs_iget. Instead we get an unlocked reference | ||
2878 | * to the inode before getting our log reservation. | ||
2879 | */ | ||
2880 | IHOLD(cdp); | ||
2881 | |||
2882 | /* | ||
2883 | * Get the dquots for the inodes. | 2699 | * Get the dquots for the inodes. |
2884 | */ | 2700 | */ |
2885 | error = XFS_QM_DQATTACH(mp, dp, 0); | 2701 | error = XFS_QM_DQATTACH(mp, dp, 0); |
2886 | if (!error && dp != cdp) | 2702 | if (!error) |
2887 | error = XFS_QM_DQATTACH(mp, cdp, 0); | 2703 | error = XFS_QM_DQATTACH(mp, cdp, 0); |
2888 | if (error) { | 2704 | if (error) { |
2889 | IRELE(cdp); | ||
2890 | REMOVE_DEBUG_TRACE(__LINE__); | 2705 | REMOVE_DEBUG_TRACE(__LINE__); |
2891 | goto std_return; | 2706 | goto std_return; |
2892 | } | 2707 | } |
@@ -2913,7 +2728,6 @@ xfs_rmdir( | |||
2913 | if (error) { | 2728 | if (error) { |
2914 | ASSERT(error != ENOSPC); | 2729 | ASSERT(error != ENOSPC); |
2915 | cancel_flags = 0; | 2730 | cancel_flags = 0; |
2916 | IRELE(cdp); | ||
2917 | goto error_return; | 2731 | goto error_return; |
2918 | } | 2732 | } |
2919 | XFS_BMAP_INIT(&free_list, &first_block); | 2733 | XFS_BMAP_INIT(&free_list, &first_block); |
@@ -2927,21 +2741,13 @@ xfs_rmdir( | |||
2927 | error = xfs_lock_dir_and_entry(dp, cdp); | 2741 | error = xfs_lock_dir_and_entry(dp, cdp); |
2928 | if (error) { | 2742 | if (error) { |
2929 | xfs_trans_cancel(tp, cancel_flags); | 2743 | xfs_trans_cancel(tp, cancel_flags); |
2930 | IRELE(cdp); | ||
2931 | goto std_return; | 2744 | goto std_return; |
2932 | } | 2745 | } |
2933 | 2746 | ||
2747 | IHOLD(dp); | ||
2934 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | 2748 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); |
2935 | if (dp != cdp) { | ||
2936 | /* | ||
2937 | * Only increment the parent directory vnode count if | ||
2938 | * we didn't bump it in looking up cdp. The only time | ||
2939 | * we don't bump it is when we're looking up ".". | ||
2940 | */ | ||
2941 | VN_HOLD(dir_vp); | ||
2942 | } | ||
2943 | 2749 | ||
2944 | xfs_itrace_ref(cdp); | 2750 | IHOLD(cdp); |
2945 | xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL); | 2751 | xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL); |
2946 | 2752 | ||
2947 | ASSERT(cdp->i_d.di_nlink >= 2); | 2753 | ASSERT(cdp->i_d.di_nlink >= 2); |
@@ -2995,12 +2801,6 @@ xfs_rmdir( | |||
2995 | last_cdp_link = (cdp)->i_d.di_nlink==0; | 2801 | last_cdp_link = (cdp)->i_d.di_nlink==0; |
2996 | 2802 | ||
2997 | /* | 2803 | /* |
2998 | * Take an extra ref on the child vnode so that it | ||
2999 | * does not go to xfs_inactive() from within the commit. | ||
3000 | */ | ||
3001 | IHOLD(cdp); | ||
3002 | |||
3003 | /* | ||
3004 | * If this is a synchronous mount, make sure that the | 2804 | * If this is a synchronous mount, make sure that the |
3005 | * rmdir transaction goes to disk before returning to | 2805 | * rmdir transaction goes to disk before returning to |
3006 | * the user. | 2806 | * the user. |
@@ -3014,19 +2814,15 @@ xfs_rmdir( | |||
3014 | xfs_bmap_cancel(&free_list); | 2814 | xfs_bmap_cancel(&free_list); |
3015 | xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | | 2815 | xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES | |
3016 | XFS_TRANS_ABORT)); | 2816 | XFS_TRANS_ABORT)); |
3017 | IRELE(cdp); | ||
3018 | goto std_return; | 2817 | goto std_return; |
3019 | } | 2818 | } |
3020 | 2819 | ||
3021 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 2820 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
3022 | if (error) { | 2821 | if (error) { |
3023 | IRELE(cdp); | ||
3024 | goto std_return; | 2822 | goto std_return; |
3025 | } | 2823 | } |
3026 | 2824 | ||
3027 | 2825 | ||
3028 | IRELE(cdp); | ||
3029 | |||
3030 | /* Fall through to std_return with error = 0 or the errno | 2826 | /* Fall through to std_return with error = 0 or the errno |
3031 | * from xfs_trans_commit. */ | 2827 | * from xfs_trans_commit. */ |
3032 | std_return: | 2828 | std_return: |