diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 09d86388bb71..51ba689a4552 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include "xfs_quota.h" | 52 | #include "xfs_quota.h" |
53 | #include "xfs_trans_space.h" | 53 | #include "xfs_trans_space.h" |
54 | #include "xfs_buf_item.h" | 54 | #include "xfs_buf_item.h" |
55 | #include "xfs_filestream.h" | ||
55 | 56 | ||
56 | 57 | ||
57 | #ifdef DEBUG | 58 | #ifdef DEBUG |
@@ -2725,9 +2726,15 @@ xfs_bmap_btalloc( | |||
2725 | } | 2726 | } |
2726 | nullfb = ap->firstblock == NULLFSBLOCK; | 2727 | nullfb = ap->firstblock == NULLFSBLOCK; |
2727 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); | 2728 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); |
2728 | if (nullfb) | 2729 | if (nullfb) { |
2729 | ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); | 2730 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) { |
2730 | else | 2731 | ag = xfs_filestream_lookup_ag(ap->ip); |
2732 | ag = (ag != NULLAGNUMBER) ? ag : 0; | ||
2733 | ap->rval = XFS_AGB_TO_FSB(mp, ag, 0); | ||
2734 | } else { | ||
2735 | ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); | ||
2736 | } | ||
2737 | } else | ||
2731 | ap->rval = ap->firstblock; | 2738 | ap->rval = ap->firstblock; |
2732 | 2739 | ||
2733 | xfs_bmap_adjacent(ap); | 2740 | xfs_bmap_adjacent(ap); |
@@ -2751,13 +2758,22 @@ xfs_bmap_btalloc( | |||
2751 | args.firstblock = ap->firstblock; | 2758 | args.firstblock = ap->firstblock; |
2752 | blen = 0; | 2759 | blen = 0; |
2753 | if (nullfb) { | 2760 | if (nullfb) { |
2754 | args.type = XFS_ALLOCTYPE_START_BNO; | 2761 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) |
2762 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | ||
2763 | else | ||
2764 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
2755 | args.total = ap->total; | 2765 | args.total = ap->total; |
2766 | |||
2756 | /* | 2767 | /* |
2757 | * Find the longest available space. | 2768 | * Search for an allocation group with a single extent |
2758 | * We're going to try for the whole allocation at once. | 2769 | * large enough for the request. |
2770 | * | ||
2771 | * If one isn't found, then adjust the minimum allocation | ||
2772 | * size to the largest space found. | ||
2759 | */ | 2773 | */ |
2760 | startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno); | 2774 | startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno); |
2775 | if (startag == NULLAGNUMBER) | ||
2776 | startag = ag = 0; | ||
2761 | notinit = 0; | 2777 | notinit = 0; |
2762 | down_read(&mp->m_peraglock); | 2778 | down_read(&mp->m_peraglock); |
2763 | while (blen < ap->alen) { | 2779 | while (blen < ap->alen) { |
@@ -2783,6 +2799,35 @@ xfs_bmap_btalloc( | |||
2783 | blen = longest; | 2799 | blen = longest; |
2784 | } else | 2800 | } else |
2785 | notinit = 1; | 2801 | notinit = 1; |
2802 | |||
2803 | if (xfs_inode_is_filestream(ap->ip)) { | ||
2804 | if (blen >= ap->alen) | ||
2805 | break; | ||
2806 | |||
2807 | if (ap->userdata) { | ||
2808 | /* | ||
2809 | * If startag is an invalid AG, we've | ||
2810 | * come here once before and | ||
2811 | * xfs_filestream_new_ag picked the | ||
2812 | * best currently available. | ||
2813 | * | ||
2814 | * Don't continue looping, since we | ||
2815 | * could loop forever. | ||
2816 | */ | ||
2817 | if (startag == NULLAGNUMBER) | ||
2818 | break; | ||
2819 | |||
2820 | error = xfs_filestream_new_ag(ap, &ag); | ||
2821 | if (error) { | ||
2822 | up_read(&mp->m_peraglock); | ||
2823 | return error; | ||
2824 | } | ||
2825 | |||
2826 | /* loop again to set 'blen'*/ | ||
2827 | startag = NULLAGNUMBER; | ||
2828 | continue; | ||
2829 | } | ||
2830 | } | ||
2786 | if (++ag == mp->m_sb.sb_agcount) | 2831 | if (++ag == mp->m_sb.sb_agcount) |
2787 | ag = 0; | 2832 | ag = 0; |
2788 | if (ag == startag) | 2833 | if (ag == startag) |
@@ -2807,8 +2852,18 @@ xfs_bmap_btalloc( | |||
2807 | */ | 2852 | */ |
2808 | else | 2853 | else |
2809 | args.minlen = ap->alen; | 2854 | args.minlen = ap->alen; |
2855 | |||
2856 | /* | ||
2857 | * set the failure fallback case to look in the selected | ||
2858 | * AG as the stream may have moved. | ||
2859 | */ | ||
2860 | if (xfs_inode_is_filestream(ap->ip)) | ||
2861 | ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0); | ||
2810 | } else if (ap->low) { | 2862 | } else if (ap->low) { |
2811 | args.type = XFS_ALLOCTYPE_START_BNO; | 2863 | if (xfs_inode_is_filestream(ap->ip)) |
2864 | args.type = XFS_ALLOCTYPE_FIRST_AG; | ||
2865 | else | ||
2866 | args.type = XFS_ALLOCTYPE_START_BNO; | ||
2812 | args.total = args.minlen = ap->minlen; | 2867 | args.total = args.minlen = ap->minlen; |
2813 | } else { | 2868 | } else { |
2814 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 2869 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |