aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr_remote.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-05-21 04:02:04 -0400
committerBen Myers <bpm@sgi.com>2013-05-30 18:26:08 -0400
commit58a72281555bf301f6dff24db2db205c87ef8db1 (patch)
tree08167ec47b27c14dcf71744557a0edaac73d2bdd /fs/xfs/xfs_attr_remote.c
parent26f714450c3907ce07c41a0bd1bea40368e0b4da (diff)
xfs: correctly map remote attr buffers during removal
If we don't map the buffers correctly (same as for get/set operations) then the incore buffer lookup will fail. If a block number matches but a length is wrong, then debug kernels will ASSERT fail in _xfs_buf_find() due to the length mismatch. Ensure that we map the buffers correctly by basing the length of the buffer on the attribute data length rather than the remote block count. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com> (cherry picked from commit 6863ef8449f1908c19f43db572e4474f24a1e9da)
Diffstat (limited to 'fs/xfs/xfs_attr_remote.c')
-rw-r--r--fs/xfs/xfs_attr_remote.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c
index e207bf0004b6..d8bcb2d742d1 100644
--- a/fs/xfs/xfs_attr_remote.c
+++ b/fs/xfs/xfs_attr_remote.c
@@ -468,19 +468,25 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
468 mp = args->dp->i_mount; 468 mp = args->dp->i_mount;
469 469
470 /* 470 /*
471 * Roll through the "value", invalidating the attribute value's 471 * Roll through the "value", invalidating the attribute value's blocks.
472 * blocks. 472 * Note that args->rmtblkcnt is the minimum number of data blocks we'll
473 * see for a CRC enabled remote attribute. Each extent will have a
474 * header, and so we may have more blocks than we realise here. If we
475 * fail to map the blocks correctly, we'll have problems with the buffer
476 * lookups.
473 */ 477 */
474 lblkno = args->rmtblkno; 478 lblkno = args->rmtblkno;
475 valuelen = args->rmtblkcnt; 479 valuelen = args->valuelen;
480 blkcnt = xfs_attr3_rmt_blocks(mp, valuelen);
476 while (valuelen > 0) { 481 while (valuelen > 0) {
482 int dblkcnt;
483
477 /* 484 /*
478 * Try to remember where we decided to put the value. 485 * Try to remember where we decided to put the value.
479 */ 486 */
480 nmap = 1; 487 nmap = 1;
481 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, 488 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
482 args->rmtblkcnt, &map, &nmap, 489 blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
483 XFS_BMAPI_ATTRFORK);
484 if (error) 490 if (error)
485 return(error); 491 return(error);
486 ASSERT(nmap == 1); 492 ASSERT(nmap == 1);
@@ -488,28 +494,31 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args)
488 (map.br_startblock != HOLESTARTBLOCK)); 494 (map.br_startblock != HOLESTARTBLOCK));
489 495
490 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), 496 dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
491 blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); 497 dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
492 498
493 /* 499 /*
494 * If the "remote" value is in the cache, remove it. 500 * If the "remote" value is in the cache, remove it.
495 */ 501 */
496 bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK); 502 bp = xfs_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK);
497 if (bp) { 503 if (bp) {
498 xfs_buf_stale(bp); 504 xfs_buf_stale(bp);
499 xfs_buf_relse(bp); 505 xfs_buf_relse(bp);
500 bp = NULL; 506 bp = NULL;
501 } 507 }
502 508
503 valuelen -= map.br_blockcount; 509 valuelen -= XFS_ATTR3_RMT_BUF_SPACE(mp,
510 XFS_FSB_TO_B(mp, map.br_blockcount));
504 511
505 lblkno += map.br_blockcount; 512 lblkno += map.br_blockcount;
513 blkcnt -= map.br_blockcount;
514 blkcnt = max(blkcnt, xfs_attr3_rmt_blocks(mp, valuelen));
506 } 515 }
507 516
508 /* 517 /*
509 * Keep de-allocating extents until the remote-value region is gone. 518 * Keep de-allocating extents until the remote-value region is gone.
510 */ 519 */
520 blkcnt = lblkno - args->rmtblkno;
511 lblkno = args->rmtblkno; 521 lblkno = args->rmtblkno;
512 blkcnt = args->rmtblkcnt;
513 done = 0; 522 done = 0;
514 while (!done) { 523 while (!done) {
515 xfs_bmap_init(args->flist, args->firstblock); 524 xfs_bmap_init(args->flist, args->firstblock);