diff options
-rw-r--r-- | fs/xfs/libxfs/xfs_alloc.c | 69 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_alloc.h | 8 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_filestream.c | 3 |
4 files changed, 37 insertions, 46 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 516162be1398..9b3e3681dfa9 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c | |||
@@ -1825,11 +1825,11 @@ xfs_alloc_compute_maxlevels( | |||
1825 | xfs_extlen_t | 1825 | xfs_extlen_t |
1826 | xfs_alloc_longest_free_extent( | 1826 | xfs_alloc_longest_free_extent( |
1827 | struct xfs_mount *mp, | 1827 | struct xfs_mount *mp, |
1828 | struct xfs_perag *pag) | 1828 | struct xfs_perag *pag, |
1829 | xfs_extlen_t need) | ||
1829 | { | 1830 | { |
1830 | xfs_extlen_t need, delta = 0; | 1831 | xfs_extlen_t delta = 0; |
1831 | 1832 | ||
1832 | need = XFS_MIN_FREELIST_PAG(pag, mp); | ||
1833 | if (need > pag->pagf_flcount) | 1833 | if (need > pag->pagf_flcount) |
1834 | delta = need - pag->pagf_flcount; | 1834 | delta = need - pag->pagf_flcount; |
1835 | 1835 | ||
@@ -1848,10 +1848,8 @@ xfs_alloc_fix_freelist( | |||
1848 | int flags) /* XFS_ALLOC_FLAG_... */ | 1848 | int flags) /* XFS_ALLOC_FLAG_... */ |
1849 | { | 1849 | { |
1850 | xfs_buf_t *agbp; /* agf buffer pointer */ | 1850 | xfs_buf_t *agbp; /* agf buffer pointer */ |
1851 | xfs_agf_t *agf; /* a.g. freespace structure pointer */ | ||
1852 | xfs_buf_t *agflbp;/* agfl buffer pointer */ | 1851 | xfs_buf_t *agflbp;/* agfl buffer pointer */ |
1853 | xfs_agblock_t bno; /* freelist block */ | 1852 | xfs_agblock_t bno; /* freelist block */ |
1854 | xfs_extlen_t delta; /* new blocks needed in freelist */ | ||
1855 | int error; /* error result code */ | 1853 | int error; /* error result code */ |
1856 | xfs_extlen_t longest;/* longest extent in allocation group */ | 1854 | xfs_extlen_t longest;/* longest extent in allocation group */ |
1857 | xfs_mount_t *mp; /* file system mount point structure */ | 1855 | xfs_mount_t *mp; /* file system mount point structure */ |
@@ -1895,7 +1893,7 @@ xfs_alloc_fix_freelist( | |||
1895 | * total blocks, reject it. | 1893 | * total blocks, reject it. |
1896 | */ | 1894 | */ |
1897 | need = XFS_MIN_FREELIST_PAG(pag, mp); | 1895 | need = XFS_MIN_FREELIST_PAG(pag, mp); |
1898 | longest = xfs_alloc_longest_free_extent(mp, pag); | 1896 | longest = xfs_alloc_longest_free_extent(mp, pag, need); |
1899 | if ((args->minlen + args->alignment + args->minalignslop - 1) > | 1897 | if ((args->minlen + args->alignment + args->minalignslop - 1) > |
1900 | longest || | 1898 | longest || |
1901 | ((int)(pag->pagf_freeblks + pag->pagf_flcount - | 1899 | ((int)(pag->pagf_freeblks + pag->pagf_flcount - |
@@ -1922,25 +1920,16 @@ xfs_alloc_fix_freelist( | |||
1922 | return 0; | 1920 | return 0; |
1923 | } | 1921 | } |
1924 | } | 1922 | } |
1925 | /* | 1923 | |
1926 | * Figure out how many blocks we should have in the freelist. | 1924 | |
1927 | */ | 1925 | /* If there isn't enough total space or single-extent, reject it. */ |
1928 | agf = XFS_BUF_TO_AGF(agbp); | 1926 | need = XFS_MIN_FREELIST_PAG(pag, mp); |
1929 | need = XFS_MIN_FREELIST(agf, mp); | ||
1930 | /* | ||
1931 | * If there isn't enough total or single-extent, reject it. | ||
1932 | */ | ||
1933 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { | 1927 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { |
1934 | delta = need > be32_to_cpu(agf->agf_flcount) ? | 1928 | longest = xfs_alloc_longest_free_extent(mp, pag, need); |
1935 | (need - be32_to_cpu(agf->agf_flcount)) : 0; | ||
1936 | longest = be32_to_cpu(agf->agf_longest); | ||
1937 | longest = (longest > delta) ? (longest - delta) : | ||
1938 | (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); | ||
1939 | if ((args->minlen + args->alignment + args->minalignslop - 1) > | 1929 | if ((args->minlen + args->alignment + args->minalignslop - 1) > |
1940 | longest || | 1930 | longest || |
1941 | ((int)(be32_to_cpu(agf->agf_freeblks) + | 1931 | ((int)(pag->pagf_freeblks + pag->pagf_flcount - |
1942 | be32_to_cpu(agf->agf_flcount) - need - args->total) < | 1932 | need - args->total) < (int)args->minleft)) { |
1943 | (int)args->minleft)) { | ||
1944 | xfs_trans_brelse(tp, agbp); | 1933 | xfs_trans_brelse(tp, agbp); |
1945 | args->agbp = NULL; | 1934 | args->agbp = NULL; |
1946 | return 0; | 1935 | return 0; |
@@ -1948,21 +1937,25 @@ xfs_alloc_fix_freelist( | |||
1948 | } | 1937 | } |
1949 | /* | 1938 | /* |
1950 | * Make the freelist shorter if it's too long. | 1939 | * Make the freelist shorter if it's too long. |
1940 | * | ||
1941 | * XXX (dgc): When we have lots of free space, does this buy us | ||
1942 | * anything other than extra overhead when we need to put more blocks | ||
1943 | * back on the free list? Maybe we should only do this when space is | ||
1944 | * getting low or the AGFL is more than half full? | ||
1951 | */ | 1945 | */ |
1952 | while (be32_to_cpu(agf->agf_flcount) > need) { | 1946 | while (pag->pagf_flcount > need) { |
1953 | xfs_buf_t *bp; | 1947 | struct xfs_buf *bp; |
1954 | 1948 | ||
1955 | error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); | 1949 | error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); |
1956 | if (error) | 1950 | if (error) |
1957 | return error; | 1951 | return error; |
1958 | if ((error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1))) | 1952 | error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1); |
1953 | if (error) | ||
1959 | return error; | 1954 | return error; |
1960 | bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); | 1955 | bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); |
1961 | xfs_trans_binval(tp, bp); | 1956 | xfs_trans_binval(tp, bp); |
1962 | } | 1957 | } |
1963 | /* | 1958 | |
1964 | * Initialize the args structure. | ||
1965 | */ | ||
1966 | memset(&targs, 0, sizeof(targs)); | 1959 | memset(&targs, 0, sizeof(targs)); |
1967 | targs.tp = tp; | 1960 | targs.tp = tp; |
1968 | targs.mp = mp; | 1961 | targs.mp = mp; |
@@ -1971,18 +1964,18 @@ xfs_alloc_fix_freelist( | |||
1971 | targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; | 1964 | targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; |
1972 | targs.type = XFS_ALLOCTYPE_THIS_AG; | 1965 | targs.type = XFS_ALLOCTYPE_THIS_AG; |
1973 | targs.pag = pag; | 1966 | targs.pag = pag; |
1974 | if ((error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp))) | 1967 | error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp); |
1968 | if (error) | ||
1975 | return error; | 1969 | return error; |
1976 | /* | 1970 | |
1977 | * Make the freelist longer if it's too short. | 1971 | /* Make the freelist longer if it's too short. */ |
1978 | */ | 1972 | while (pag->pagf_flcount < need) { |
1979 | while (be32_to_cpu(agf->agf_flcount) < need) { | ||
1980 | targs.agbno = 0; | 1973 | targs.agbno = 0; |
1981 | targs.maxlen = need - be32_to_cpu(agf->agf_flcount); | 1974 | targs.maxlen = need - pag->pagf_flcount; |
1982 | /* | 1975 | |
1983 | * Allocate as many blocks as possible at once. | 1976 | /* Allocate as many blocks as possible at once. */ |
1984 | */ | 1977 | error = xfs_alloc_ag_vextent(&targs); |
1985 | if ((error = xfs_alloc_ag_vextent(&targs))) { | 1978 | if (error) { |
1986 | xfs_trans_brelse(tp, agflbp); | 1979 | xfs_trans_brelse(tp, agflbp); |
1987 | return error; | 1980 | return error; |
1988 | } | 1981 | } |
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index d1b4b6a5c894..8815fc30f83d 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h | |||
@@ -128,12 +128,8 @@ typedef struct xfs_alloc_arg { | |||
128 | #define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/ | 128 | #define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/ |
129 | #define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */ | 129 | #define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */ |
130 | 130 | ||
131 | /* | 131 | xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp, |
132 | * Find the length of the longest extent in an AG. | 132 | struct xfs_perag *pag, xfs_extlen_t need); |
133 | */ | ||
134 | xfs_extlen_t | ||
135 | xfs_alloc_longest_free_extent(struct xfs_mount *mp, | ||
136 | struct xfs_perag *pag); | ||
137 | 133 | ||
138 | /* | 134 | /* |
139 | * Compute and fill in value of m_ag_maxlevels. | 135 | * Compute and fill in value of m_ag_maxlevels. |
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index aeffeaaac0ec..1ad4f1a62ce0 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -3507,7 +3507,8 @@ xfs_bmap_longest_free_extent( | |||
3507 | } | 3507 | } |
3508 | } | 3508 | } |
3509 | 3509 | ||
3510 | longest = xfs_alloc_longest_free_extent(mp, pag); | 3510 | longest = xfs_alloc_longest_free_extent(mp, pag, |
3511 | XFS_MIN_FREELIST_PAG(pag, mp)); | ||
3511 | if (*blen < longest) | 3512 | if (*blen < longest) |
3512 | *blen = longest; | 3513 | *blen = longest; |
3513 | 3514 | ||
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index da82f1cb4b9b..9ac5eaad47bc 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c | |||
@@ -196,7 +196,8 @@ xfs_filestream_pick_ag( | |||
196 | goto next_ag; | 196 | goto next_ag; |
197 | } | 197 | } |
198 | 198 | ||
199 | longest = xfs_alloc_longest_free_extent(mp, pag); | 199 | longest = xfs_alloc_longest_free_extent(mp, pag, |
200 | XFS_MIN_FREELIST_PAG(pag, mp)); | ||
200 | if (((minlen && longest >= minlen) || | 201 | if (((minlen && longest >= minlen) || |
201 | (!minlen && pag->pagf_freeblks >= minfree)) && | 202 | (!minlen && pag->pagf_freeblks >= minfree)) && |
202 | (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) || | 203 | (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) || |