aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_bmap_util.c')
-rw-r--r--fs/xfs/xfs_bmap_util.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index b9abce524c33..c1417919ab0a 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -528,7 +528,6 @@ xfs_getbmap(
528 xfs_bmbt_irec_t *map; /* buffer for user's data */ 528 xfs_bmbt_irec_t *map; /* buffer for user's data */
529 xfs_mount_t *mp; /* file system mount point */ 529 xfs_mount_t *mp; /* file system mount point */
530 int nex; /* # of user extents can do */ 530 int nex; /* # of user extents can do */
531 int nexleft; /* # of user extents left */
532 int subnex; /* # of bmapi's can do */ 531 int subnex; /* # of bmapi's can do */
533 int nmap; /* number of map entries */ 532 int nmap; /* number of map entries */
534 struct getbmapx *out; /* output structure */ 533 struct getbmapx *out; /* output structure */
@@ -686,10 +685,8 @@ xfs_getbmap(
686 goto out_free_map; 685 goto out_free_map;
687 } 686 }
688 687
689 nexleft = nex;
690
691 do { 688 do {
692 nmap = (nexleft > subnex) ? subnex : nexleft; 689 nmap = (nex> subnex) ? subnex : nex;
693 error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), 690 error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
694 XFS_BB_TO_FSB(mp, bmv->bmv_length), 691 XFS_BB_TO_FSB(mp, bmv->bmv_length),
695 map, &nmap, bmapi_flags); 692 map, &nmap, bmapi_flags);
@@ -697,8 +694,8 @@ xfs_getbmap(
697 goto out_free_map; 694 goto out_free_map;
698 ASSERT(nmap <= subnex); 695 ASSERT(nmap <= subnex);
699 696
700 for (i = 0; i < nmap && nexleft && bmv->bmv_length && 697 for (i = 0; i < nmap && bmv->bmv_length &&
701 cur_ext < bmv->bmv_count; i++) { 698 cur_ext < bmv->bmv_count - 1; i++) {
702 out[cur_ext].bmv_oflags = 0; 699 out[cur_ext].bmv_oflags = 0;
703 if (map[i].br_state == XFS_EXT_UNWRITTEN) 700 if (map[i].br_state == XFS_EXT_UNWRITTEN)
704 out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC; 701 out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
@@ -760,16 +757,27 @@ xfs_getbmap(
760 continue; 757 continue;
761 } 758 }
762 759
760 /*
761 * In order to report shared extents accurately,
762 * we report each distinct shared/unshared part
763 * of a single bmbt record using multiple bmap
764 * extents. To make that happen, we iterate the
765 * same map array item multiple times, each
766 * time trimming out the subextent that we just
767 * reported.
768 *
769 * Because of this, we must check the out array
770 * index (cur_ext) directly against bmv_count-1
771 * to avoid overflows.
772 */
763 if (inject_map.br_startblock != NULLFSBLOCK) { 773 if (inject_map.br_startblock != NULLFSBLOCK) {
764 map[i] = inject_map; 774 map[i] = inject_map;
765 i--; 775 i--;
766 } else 776 }
767 nexleft--;
768 bmv->bmv_entries++; 777 bmv->bmv_entries++;
769 cur_ext++; 778 cur_ext++;
770 } 779 }
771 } while (nmap && nexleft && bmv->bmv_length && 780 } while (nmap && bmv->bmv_length && cur_ext < bmv->bmv_count - 1);
772 cur_ext < bmv->bmv_count);
773 781
774 out_free_map: 782 out_free_map:
775 kmem_free(map); 783 kmem_free(map);