aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c69
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;