diff options
-rw-r--r-- | fs/xfs/xfs_attr_remote.c | 27 |
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); |