diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 104 |
1 files changed, 97 insertions, 7 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 59f63949d3b..fc5acf0b921 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -4350,6 +4350,98 @@ xfs_bmapi_update_map( | |||
4350 | } | 4350 | } |
4351 | 4351 | ||
4352 | /* | 4352 | /* |
4353 | * Map file blocks to filesystem blocks without allocation. | ||
4354 | */ | ||
4355 | int | ||
4356 | xfs_bmapi_read( | ||
4357 | struct xfs_inode *ip, | ||
4358 | xfs_fileoff_t bno, | ||
4359 | xfs_filblks_t len, | ||
4360 | struct xfs_bmbt_irec *mval, | ||
4361 | int *nmap, | ||
4362 | int flags) | ||
4363 | { | ||
4364 | struct xfs_mount *mp = ip->i_mount; | ||
4365 | struct xfs_ifork *ifp; | ||
4366 | struct xfs_bmbt_irec got; | ||
4367 | struct xfs_bmbt_irec prev; | ||
4368 | xfs_fileoff_t obno; | ||
4369 | xfs_fileoff_t end; | ||
4370 | xfs_extnum_t lastx; | ||
4371 | int error; | ||
4372 | int eof; | ||
4373 | int n = 0; | ||
4374 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | ||
4375 | XFS_ATTR_FORK : XFS_DATA_FORK; | ||
4376 | |||
4377 | ASSERT(*nmap >= 1); | ||
4378 | ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE| | ||
4379 | XFS_BMAPI_IGSTATE))); | ||
4380 | |||
4381 | if (unlikely(XFS_TEST_ERROR( | ||
4382 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | ||
4383 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), | ||
4384 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | ||
4385 | XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp); | ||
4386 | return XFS_ERROR(EFSCORRUPTED); | ||
4387 | } | ||
4388 | |||
4389 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
4390 | return XFS_ERROR(EIO); | ||
4391 | |||
4392 | XFS_STATS_INC(xs_blk_mapr); | ||
4393 | |||
4394 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
4395 | ASSERT(ifp->if_ext_max == | ||
4396 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | ||
4397 | |||
4398 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
4399 | error = xfs_iread_extents(NULL, ip, whichfork); | ||
4400 | if (error) | ||
4401 | return error; | ||
4402 | } | ||
4403 | |||
4404 | xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); | ||
4405 | end = bno + len; | ||
4406 | obno = bno; | ||
4407 | |||
4408 | while (bno < end && n < *nmap) { | ||
4409 | /* Reading past eof, act as though there's a hole up to end. */ | ||
4410 | if (eof) | ||
4411 | got.br_startoff = end; | ||
4412 | if (got.br_startoff > bno) { | ||
4413 | /* Reading in a hole. */ | ||
4414 | mval->br_startoff = bno; | ||
4415 | mval->br_startblock = HOLESTARTBLOCK; | ||
4416 | mval->br_blockcount = | ||
4417 | XFS_FILBLKS_MIN(len, got.br_startoff - bno); | ||
4418 | mval->br_state = XFS_EXT_NORM; | ||
4419 | bno += mval->br_blockcount; | ||
4420 | len -= mval->br_blockcount; | ||
4421 | mval++; | ||
4422 | n++; | ||
4423 | continue; | ||
4424 | } | ||
4425 | |||
4426 | /* set up the extent map to return. */ | ||
4427 | xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); | ||
4428 | xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); | ||
4429 | |||
4430 | /* If we're done, stop now. */ | ||
4431 | if (bno >= end || n >= *nmap) | ||
4432 | break; | ||
4433 | |||
4434 | /* Else go on to the next record. */ | ||
4435 | if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) | ||
4436 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got); | ||
4437 | else | ||
4438 | eof = 1; | ||
4439 | } | ||
4440 | *nmap = n; | ||
4441 | return 0; | ||
4442 | } | ||
4443 | |||
4444 | /* | ||
4353 | * Map file blocks to filesystem blocks. | 4445 | * Map file blocks to filesystem blocks. |
4354 | * File range is given by the bno/len pair. | 4446 | * File range is given by the bno/len pair. |
4355 | * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set) | 4447 | * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set) |
@@ -5490,10 +5582,9 @@ xfs_getbmap( | |||
5490 | 5582 | ||
5491 | do { | 5583 | do { |
5492 | nmap = (nexleft > subnex) ? subnex : nexleft; | 5584 | nmap = (nexleft > subnex) ? subnex : nexleft; |
5493 | error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), | 5585 | error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), |
5494 | XFS_BB_TO_FSB(mp, bmv->bmv_length), | 5586 | XFS_BB_TO_FSB(mp, bmv->bmv_length), |
5495 | bmapi_flags, NULL, 0, map, &nmap, | 5587 | map, &nmap, bmapi_flags); |
5496 | NULL); | ||
5497 | if (error) | 5588 | if (error) |
5498 | goto out_free_map; | 5589 | goto out_free_map; |
5499 | ASSERT(nmap <= subnex); | 5590 | ASSERT(nmap <= subnex); |
@@ -6084,9 +6175,8 @@ xfs_bmap_punch_delalloc_range( | |||
6084 | * trying to remove a real extent (which requires a | 6175 | * trying to remove a real extent (which requires a |
6085 | * transaction) or a hole, which is probably a bad idea... | 6176 | * transaction) or a hole, which is probably a bad idea... |
6086 | */ | 6177 | */ |
6087 | error = xfs_bmapi(NULL, ip, start_fsb, 1, | 6178 | error = xfs_bmapi_read(ip, start_fsb, 1, &imap, &nimaps, |
6088 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | 6179 | XFS_BMAPI_ENTIRE); |
6089 | &nimaps, NULL); | ||
6090 | 6180 | ||
6091 | if (error) { | 6181 | if (error) { |
6092 | /* something screwed, just bail */ | 6182 | /* something screwed, just bail */ |