diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 208 |
1 files changed, 70 insertions, 138 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index a59eea09930a..2778258fcfa2 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -132,23 +132,28 @@ xfs_inobp_check( | |||
132 | #endif | 132 | #endif |
133 | 133 | ||
134 | /* | 134 | /* |
135 | * Find the buffer associated with the given inode map | 135 | * This routine is called to map an inode to the buffer containing the on-disk |
136 | * We do basic validation checks on the buffer once it has been | 136 | * version of the inode. It returns a pointer to the buffer containing the |
137 | * retrieved from disk. | 137 | * on-disk inode in the bpp parameter, and in the dipp parameter it returns a |
138 | * pointer to the on-disk inode within that buffer. | ||
139 | * | ||
140 | * If a non-zero error is returned, then the contents of bpp and dipp are | ||
141 | * undefined. | ||
138 | */ | 142 | */ |
139 | STATIC int | 143 | int |
140 | xfs_imap_to_bp( | 144 | xfs_imap_to_bp( |
141 | xfs_mount_t *mp, | 145 | struct xfs_mount *mp, |
142 | xfs_trans_t *tp, | 146 | struct xfs_trans *tp, |
143 | struct xfs_imap *imap, | 147 | struct xfs_imap *imap, |
144 | xfs_buf_t **bpp, | 148 | struct xfs_dinode **dipp, |
145 | uint buf_flags, | 149 | struct xfs_buf **bpp, |
146 | uint iget_flags) | 150 | uint buf_flags, |
151 | uint iget_flags) | ||
147 | { | 152 | { |
148 | int error; | 153 | struct xfs_buf *bp; |
149 | int i; | 154 | int error; |
150 | int ni; | 155 | int i; |
151 | xfs_buf_t *bp; | 156 | int ni; |
152 | 157 | ||
153 | buf_flags |= XBF_UNMAPPED; | 158 | buf_flags |= XBF_UNMAPPED; |
154 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno, | 159 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap->im_blkno, |
@@ -189,8 +194,8 @@ xfs_imap_to_bp( | |||
189 | xfs_trans_brelse(tp, bp); | 194 | xfs_trans_brelse(tp, bp); |
190 | return XFS_ERROR(EINVAL); | 195 | return XFS_ERROR(EINVAL); |
191 | } | 196 | } |
192 | XFS_CORRUPTION_ERROR("xfs_imap_to_bp", | 197 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, |
193 | XFS_ERRLEVEL_HIGH, mp, dip); | 198 | mp, dip); |
194 | #ifdef DEBUG | 199 | #ifdef DEBUG |
195 | xfs_emerg(mp, | 200 | xfs_emerg(mp, |
196 | "bad inode magic/vsn daddr %lld #%d (magic=%x)", | 201 | "bad inode magic/vsn daddr %lld #%d (magic=%x)", |
@@ -204,96 +209,9 @@ xfs_imap_to_bp( | |||
204 | } | 209 | } |
205 | 210 | ||
206 | xfs_inobp_check(mp, bp); | 211 | xfs_inobp_check(mp, bp); |
207 | *bpp = bp; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * This routine is called to map an inode number within a file | ||
213 | * system to the buffer containing the on-disk version of the | ||
214 | * inode. It returns a pointer to the buffer containing the | ||
215 | * on-disk inode in the bpp parameter, and in the dip parameter | ||
216 | * it returns a pointer to the on-disk inode within that buffer. | ||
217 | * | ||
218 | * If a non-zero error is returned, then the contents of bpp and | ||
219 | * dipp are undefined. | ||
220 | * | ||
221 | * Use xfs_imap() to determine the size and location of the | ||
222 | * buffer to read from disk. | ||
223 | */ | ||
224 | int | ||
225 | xfs_inotobp( | ||
226 | xfs_mount_t *mp, | ||
227 | xfs_trans_t *tp, | ||
228 | xfs_ino_t ino, | ||
229 | xfs_dinode_t **dipp, | ||
230 | xfs_buf_t **bpp, | ||
231 | int *offset, | ||
232 | uint imap_flags) | ||
233 | { | ||
234 | struct xfs_imap imap; | ||
235 | xfs_buf_t *bp; | ||
236 | int error; | ||
237 | |||
238 | imap.im_blkno = 0; | ||
239 | error = xfs_imap(mp, tp, ino, &imap, imap_flags); | ||
240 | if (error) | ||
241 | return error; | ||
242 | |||
243 | error = xfs_imap_to_bp(mp, tp, &imap, &bp, 0, imap_flags); | ||
244 | if (error) | ||
245 | return error; | ||
246 | |||
247 | *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset); | ||
248 | *bpp = bp; | ||
249 | *offset = imap.im_boffset; | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | |||
254 | /* | ||
255 | * This routine is called to map an inode to the buffer containing | ||
256 | * the on-disk version of the inode. It returns a pointer to the | ||
257 | * buffer containing the on-disk inode in the bpp parameter, and in | ||
258 | * the dip parameter it returns a pointer to the on-disk inode within | ||
259 | * that buffer. | ||
260 | * | ||
261 | * If a non-zero error is returned, then the contents of bpp and | ||
262 | * dipp are undefined. | ||
263 | * | ||
264 | * The inode is expected to already been mapped to its buffer and read | ||
265 | * in once, thus we can use the mapping information stored in the inode | ||
266 | * rather than calling xfs_imap(). This allows us to avoid the overhead | ||
267 | * of looking at the inode btree for small block file systems | ||
268 | * (see xfs_imap()). | ||
269 | */ | ||
270 | int | ||
271 | xfs_itobp( | ||
272 | xfs_mount_t *mp, | ||
273 | xfs_trans_t *tp, | ||
274 | xfs_inode_t *ip, | ||
275 | xfs_dinode_t **dipp, | ||
276 | xfs_buf_t **bpp, | ||
277 | uint buf_flags) | ||
278 | { | ||
279 | xfs_buf_t *bp; | ||
280 | int error; | ||
281 | |||
282 | ASSERT(ip->i_imap.im_blkno != 0); | ||
283 | |||
284 | error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, buf_flags, 0); | ||
285 | if (error) | ||
286 | return error; | ||
287 | 212 | ||
288 | if (!bp) { | ||
289 | ASSERT(buf_flags & XBF_TRYLOCK); | ||
290 | ASSERT(tp == NULL); | ||
291 | *bpp = NULL; | ||
292 | return EAGAIN; | ||
293 | } | ||
294 | |||
295 | *dipp = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); | ||
296 | *bpp = bp; | 213 | *bpp = bp; |
214 | *dipp = (struct xfs_dinode *)xfs_buf_offset(bp, imap->im_boffset); | ||
297 | return 0; | 215 | return 0; |
298 | } | 216 | } |
299 | 217 | ||
@@ -796,10 +714,9 @@ xfs_iread( | |||
796 | /* | 714 | /* |
797 | * Get pointers to the on-disk inode and the buffer containing it. | 715 | * Get pointers to the on-disk inode and the buffer containing it. |
798 | */ | 716 | */ |
799 | error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &bp, 0, iget_flags); | 717 | error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &bp, 0, iget_flags); |
800 | if (error) | 718 | if (error) |
801 | return error; | 719 | return error; |
802 | dip = (xfs_dinode_t *)xfs_buf_offset(bp, ip->i_imap.im_boffset); | ||
803 | 720 | ||
804 | /* | 721 | /* |
805 | * If we got something that isn't an inode it means someone | 722 | * If we got something that isn't an inode it means someone |
@@ -876,7 +793,7 @@ xfs_iread( | |||
876 | /* | 793 | /* |
877 | * Use xfs_trans_brelse() to release the buffer containing the | 794 | * Use xfs_trans_brelse() to release the buffer containing the |
878 | * on-disk inode, because it was acquired with xfs_trans_read_buf() | 795 | * on-disk inode, because it was acquired with xfs_trans_read_buf() |
879 | * in xfs_itobp() above. If tp is NULL, this is just a normal | 796 | * in xfs_imap_to_bp() above. If tp is NULL, this is just a normal |
880 | * brelse(). If we're within a transaction, then xfs_trans_brelse() | 797 | * brelse(). If we're within a transaction, then xfs_trans_brelse() |
881 | * will only release the buffer if it is not dirty within the | 798 | * will only release the buffer if it is not dirty within the |
882 | * transaction. It will be OK to release the buffer in this case, | 799 | * transaction. It will be OK to release the buffer in this case, |
@@ -970,7 +887,6 @@ xfs_ialloc( | |||
970 | prid_t prid, | 887 | prid_t prid, |
971 | int okalloc, | 888 | int okalloc, |
972 | xfs_buf_t **ialloc_context, | 889 | xfs_buf_t **ialloc_context, |
973 | boolean_t *call_again, | ||
974 | xfs_inode_t **ipp) | 890 | xfs_inode_t **ipp) |
975 | { | 891 | { |
976 | xfs_ino_t ino; | 892 | xfs_ino_t ino; |
@@ -985,10 +901,10 @@ xfs_ialloc( | |||
985 | * the on-disk inode to be allocated. | 901 | * the on-disk inode to be allocated. |
986 | */ | 902 | */ |
987 | error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, | 903 | error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, |
988 | ialloc_context, call_again, &ino); | 904 | ialloc_context, &ino); |
989 | if (error) | 905 | if (error) |
990 | return error; | 906 | return error; |
991 | if (*call_again || ino == NULLFSINO) { | 907 | if (*ialloc_context || ino == NULLFSINO) { |
992 | *ipp = NULL; | 908 | *ipp = NULL; |
993 | return 0; | 909 | return 0; |
994 | } | 910 | } |
@@ -1207,7 +1123,9 @@ xfs_itruncate_extents( | |||
1207 | int error = 0; | 1123 | int error = 0; |
1208 | int done = 0; | 1124 | int done = 0; |
1209 | 1125 | ||
1210 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); | 1126 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
1127 | ASSERT(!atomic_read(&VFS_I(ip)->i_count) || | ||
1128 | xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | ||
1211 | ASSERT(new_size <= XFS_ISIZE(ip)); | 1129 | ASSERT(new_size <= XFS_ISIZE(ip)); |
1212 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 1130 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
1213 | ASSERT(ip->i_itemp != NULL); | 1131 | ASSERT(ip->i_itemp != NULL); |
@@ -1226,7 +1144,7 @@ xfs_itruncate_extents( | |||
1226 | * then there is nothing to do. | 1144 | * then there is nothing to do. |
1227 | */ | 1145 | */ |
1228 | first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); | 1146 | first_unmap_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); |
1229 | last_block = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); | 1147 | last_block = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes); |
1230 | if (first_unmap_block == last_block) | 1148 | if (first_unmap_block == last_block) |
1231 | return 0; | 1149 | return 0; |
1232 | 1150 | ||
@@ -1355,7 +1273,8 @@ xfs_iunlink( | |||
1355 | * Here we put the head pointer into our next pointer, | 1273 | * Here we put the head pointer into our next pointer, |
1356 | * and then we fall through to point the head at us. | 1274 | * and then we fall through to point the head at us. |
1357 | */ | 1275 | */ |
1358 | error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); | 1276 | error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp, |
1277 | 0, 0); | ||
1359 | if (error) | 1278 | if (error) |
1360 | return error; | 1279 | return error; |
1361 | 1280 | ||
@@ -1429,16 +1348,16 @@ xfs_iunlink_remove( | |||
1429 | 1348 | ||
1430 | if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) { | 1349 | if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) { |
1431 | /* | 1350 | /* |
1432 | * We're at the head of the list. Get the inode's | 1351 | * We're at the head of the list. Get the inode's on-disk |
1433 | * on-disk buffer to see if there is anyone after us | 1352 | * buffer to see if there is anyone after us on the list. |
1434 | * on the list. Only modify our next pointer if it | 1353 | * Only modify our next pointer if it is not already NULLAGINO. |
1435 | * is not already NULLAGINO. This saves us the overhead | 1354 | * This saves us the overhead of dealing with the buffer when |
1436 | * of dealing with the buffer when there is no need to | 1355 | * there is no need to change it. |
1437 | * change it. | ||
1438 | */ | 1356 | */ |
1439 | error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); | 1357 | error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp, |
1358 | 0, 0); | ||
1440 | if (error) { | 1359 | if (error) { |
1441 | xfs_warn(mp, "%s: xfs_itobp() returned error %d.", | 1360 | xfs_warn(mp, "%s: xfs_imap_to_bp returned error %d.", |
1442 | __func__, error); | 1361 | __func__, error); |
1443 | return error; | 1362 | return error; |
1444 | } | 1363 | } |
@@ -1472,34 +1391,45 @@ xfs_iunlink_remove( | |||
1472 | next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); | 1391 | next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); |
1473 | last_ibp = NULL; | 1392 | last_ibp = NULL; |
1474 | while (next_agino != agino) { | 1393 | while (next_agino != agino) { |
1475 | /* | 1394 | struct xfs_imap imap; |
1476 | * If the last inode wasn't the one pointing to | 1395 | |
1477 | * us, then release its buffer since we're not | 1396 | if (last_ibp) |
1478 | * going to do anything with it. | ||
1479 | */ | ||
1480 | if (last_ibp != NULL) { | ||
1481 | xfs_trans_brelse(tp, last_ibp); | 1397 | xfs_trans_brelse(tp, last_ibp); |
1482 | } | 1398 | |
1399 | imap.im_blkno = 0; | ||
1483 | next_ino = XFS_AGINO_TO_INO(mp, agno, next_agino); | 1400 | next_ino = XFS_AGINO_TO_INO(mp, agno, next_agino); |
1484 | error = xfs_inotobp(mp, tp, next_ino, &last_dip, | 1401 | |
1485 | &last_ibp, &last_offset, 0); | 1402 | error = xfs_imap(mp, tp, next_ino, &imap, 0); |
1403 | if (error) { | ||
1404 | xfs_warn(mp, | ||
1405 | "%s: xfs_imap returned error %d.", | ||
1406 | __func__, error); | ||
1407 | return error; | ||
1408 | } | ||
1409 | |||
1410 | error = xfs_imap_to_bp(mp, tp, &imap, &last_dip, | ||
1411 | &last_ibp, 0, 0); | ||
1486 | if (error) { | 1412 | if (error) { |
1487 | xfs_warn(mp, | 1413 | xfs_warn(mp, |
1488 | "%s: xfs_inotobp() returned error %d.", | 1414 | "%s: xfs_imap_to_bp returned error %d.", |
1489 | __func__, error); | 1415 | __func__, error); |
1490 | return error; | 1416 | return error; |
1491 | } | 1417 | } |
1418 | |||
1419 | last_offset = imap.im_boffset; | ||
1492 | next_agino = be32_to_cpu(last_dip->di_next_unlinked); | 1420 | next_agino = be32_to_cpu(last_dip->di_next_unlinked); |
1493 | ASSERT(next_agino != NULLAGINO); | 1421 | ASSERT(next_agino != NULLAGINO); |
1494 | ASSERT(next_agino != 0); | 1422 | ASSERT(next_agino != 0); |
1495 | } | 1423 | } |
1424 | |||
1496 | /* | 1425 | /* |
1497 | * Now last_ibp points to the buffer previous to us on | 1426 | * Now last_ibp points to the buffer previous to us on the |
1498 | * the unlinked list. Pull us from the list. | 1427 | * unlinked list. Pull us from the list. |
1499 | */ | 1428 | */ |
1500 | error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0); | 1429 | error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &dip, &ibp, |
1430 | 0, 0); | ||
1501 | if (error) { | 1431 | if (error) { |
1502 | xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.", | 1432 | xfs_warn(mp, "%s: xfs_imap_to_bp(2) returned error %d.", |
1503 | __func__, error); | 1433 | __func__, error); |
1504 | return error; | 1434 | return error; |
1505 | } | 1435 | } |
@@ -1749,7 +1679,8 @@ xfs_ifree( | |||
1749 | 1679 | ||
1750 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 1680 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
1751 | 1681 | ||
1752 | error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0); | 1682 | error = xfs_imap_to_bp(ip->i_mount, tp, &ip->i_imap, &dip, &ibp, |
1683 | 0, 0); | ||
1753 | if (error) | 1684 | if (error) |
1754 | return error; | 1685 | return error; |
1755 | 1686 | ||
@@ -2428,7 +2359,7 @@ xfs_iflush( | |||
2428 | /* | 2359 | /* |
2429 | * For stale inodes we cannot rely on the backing buffer remaining | 2360 | * For stale inodes we cannot rely on the backing buffer remaining |
2430 | * stale in cache for the remaining life of the stale inode and so | 2361 | * stale in cache for the remaining life of the stale inode and so |
2431 | * xfs_itobp() below may give us a buffer that no longer contains | 2362 | * xfs_imap_to_bp() below may give us a buffer that no longer contains |
2432 | * inodes below. We have to check this after ensuring the inode is | 2363 | * inodes below. We have to check this after ensuring the inode is |
2433 | * unpinned so that it is safe to reclaim the stale inode after the | 2364 | * unpinned so that it is safe to reclaim the stale inode after the |
2434 | * flush call. | 2365 | * flush call. |
@@ -2454,7 +2385,8 @@ xfs_iflush( | |||
2454 | /* | 2385 | /* |
2455 | * Get the buffer containing the on-disk inode. | 2386 | * Get the buffer containing the on-disk inode. |
2456 | */ | 2387 | */ |
2457 | error = xfs_itobp(mp, NULL, ip, &dip, &bp, XBF_TRYLOCK); | 2388 | error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK, |
2389 | 0); | ||
2458 | if (error || !bp) { | 2390 | if (error || !bp) { |
2459 | xfs_ifunlock(ip); | 2391 | xfs_ifunlock(ip); |
2460 | return error; | 2392 | return error; |