aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-09-18 16:40:45 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:15:03 -0400
commit5c8ed2021ff291f5e399a9b43c4f699b2fc58fbb (patch)
tree36d8375935324279fb27e50daa7fc6873ff68cea /fs/xfs/xfs_bmap.c
parentaef9a89586fc8475bf0333b8736d5aa8aa6f4897 (diff)
xfs: introduce xfs_bmapi_read()
xfs_bmapi() currently handles both extent map reading and allocation. As a result, the code is littered with "if (wr)" branches to conditionally do allocation operations if required. This makes the code much harder to follow and causes significant indent issues with the code. Given that read mapping is much simpler than allocation, we can split out read mapping from xfs_bmapi() and reuse the logic that we have already factored out do do all the hard work of handling the extent map manipulations. The results in a much simpler function for the common extent read operations, and will allow the allocation code to be simplified in another commit. Once xfs_bmapi_read() is implemented, convert all the callers of xfs_bmapi() that are only reading extents to use the new function. Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c104
1 files changed, 97 insertions, 7 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 59f63949d3bc..fc5acf0b921e 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 */
4355int
4356xfs_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 */