diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
| -rw-r--r-- | fs/xfs/xfs_alloc.c | 113 |
1 files changed, 60 insertions, 53 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index eef6763f3a67..e80dda3437d1 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
| @@ -1477,8 +1477,10 @@ xfs_alloc_ag_vextent_small( | |||
| 1477 | /* | 1477 | /* |
| 1478 | * Can't allocate from the freelist for some reason. | 1478 | * Can't allocate from the freelist for some reason. |
| 1479 | */ | 1479 | */ |
| 1480 | else | 1480 | else { |
| 1481 | fbno = NULLAGBLOCK; | ||
| 1481 | flen = 0; | 1482 | flen = 0; |
| 1483 | } | ||
| 1482 | /* | 1484 | /* |
| 1483 | * Can't do the allocation, give up. | 1485 | * Can't do the allocation, give up. |
| 1484 | */ | 1486 | */ |
| @@ -1835,40 +1837,47 @@ xfs_alloc_fix_freelist( | |||
| 1835 | &agbp))) | 1837 | &agbp))) |
| 1836 | return error; | 1838 | return error; |
| 1837 | if (!pag->pagf_init) { | 1839 | if (!pag->pagf_init) { |
| 1840 | ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); | ||
| 1841 | ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); | ||
| 1838 | args->agbp = NULL; | 1842 | args->agbp = NULL; |
| 1839 | return 0; | 1843 | return 0; |
| 1840 | } | 1844 | } |
| 1841 | } else | 1845 | } else |
| 1842 | agbp = NULL; | 1846 | agbp = NULL; |
| 1843 | 1847 | ||
| 1844 | /* If this is a metadata preferred pag and we are user data | 1848 | /* |
| 1849 | * If this is a metadata preferred pag and we are user data | ||
| 1845 | * then try somewhere else if we are not being asked to | 1850 | * then try somewhere else if we are not being asked to |
| 1846 | * try harder at this point | 1851 | * try harder at this point |
| 1847 | */ | 1852 | */ |
| 1848 | if (pag->pagf_metadata && args->userdata && flags) { | 1853 | if (pag->pagf_metadata && args->userdata && |
| 1854 | (flags & XFS_ALLOC_FLAG_TRYLOCK)) { | ||
| 1855 | ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); | ||
| 1849 | args->agbp = NULL; | 1856 | args->agbp = NULL; |
| 1850 | return 0; | 1857 | return 0; |
| 1851 | } | 1858 | } |
| 1852 | 1859 | ||
| 1853 | need = XFS_MIN_FREELIST_PAG(pag, mp); | 1860 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { |
| 1854 | delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; | 1861 | need = XFS_MIN_FREELIST_PAG(pag, mp); |
| 1855 | /* | 1862 | delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; |
| 1856 | * If it looks like there isn't a long enough extent, or enough | 1863 | /* |
| 1857 | * total blocks, reject it. | 1864 | * If it looks like there isn't a long enough extent, or enough |
| 1858 | */ | 1865 | * total blocks, reject it. |
| 1859 | longest = (pag->pagf_longest > delta) ? | 1866 | */ |
| 1860 | (pag->pagf_longest - delta) : | 1867 | longest = (pag->pagf_longest > delta) ? |
| 1861 | (pag->pagf_flcount > 0 || pag->pagf_longest > 0); | 1868 | (pag->pagf_longest - delta) : |
| 1862 | if (args->minlen + args->alignment + args->minalignslop - 1 > longest || | 1869 | (pag->pagf_flcount > 0 || pag->pagf_longest > 0); |
| 1863 | (!(flags & XFS_ALLOC_FLAG_FREEING) && | 1870 | if ((args->minlen + args->alignment + args->minalignslop - 1) > |
| 1864 | (int)(pag->pagf_freeblks + pag->pagf_flcount - | 1871 | longest || |
| 1865 | need - args->total) < | 1872 | ((int)(pag->pagf_freeblks + pag->pagf_flcount - |
| 1866 | (int)args->minleft)) { | 1873 | need - args->total) < (int)args->minleft)) { |
| 1867 | if (agbp) | 1874 | if (agbp) |
| 1868 | xfs_trans_brelse(tp, agbp); | 1875 | xfs_trans_brelse(tp, agbp); |
| 1869 | args->agbp = NULL; | 1876 | args->agbp = NULL; |
| 1870 | return 0; | 1877 | return 0; |
| 1878 | } | ||
| 1871 | } | 1879 | } |
| 1880 | |||
| 1872 | /* | 1881 | /* |
| 1873 | * Get the a.g. freespace buffer. | 1882 | * Get the a.g. freespace buffer. |
| 1874 | * Can fail if we're not blocking on locks, and it's held. | 1883 | * Can fail if we're not blocking on locks, and it's held. |
| @@ -1878,6 +1887,8 @@ xfs_alloc_fix_freelist( | |||
| 1878 | &agbp))) | 1887 | &agbp))) |
| 1879 | return error; | 1888 | return error; |
| 1880 | if (agbp == NULL) { | 1889 | if (agbp == NULL) { |
| 1890 | ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); | ||
| 1891 | ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); | ||
| 1881 | args->agbp = NULL; | 1892 | args->agbp = NULL; |
| 1882 | return 0; | 1893 | return 0; |
| 1883 | } | 1894 | } |
| @@ -1887,22 +1898,24 @@ xfs_alloc_fix_freelist( | |||
| 1887 | */ | 1898 | */ |
| 1888 | agf = XFS_BUF_TO_AGF(agbp); | 1899 | agf = XFS_BUF_TO_AGF(agbp); |
| 1889 | need = XFS_MIN_FREELIST(agf, mp); | 1900 | need = XFS_MIN_FREELIST(agf, mp); |
| 1890 | delta = need > be32_to_cpu(agf->agf_flcount) ? | ||
| 1891 | (need - be32_to_cpu(agf->agf_flcount)) : 0; | ||
| 1892 | /* | 1901 | /* |
| 1893 | * If there isn't enough total or single-extent, reject it. | 1902 | * If there isn't enough total or single-extent, reject it. |
| 1894 | */ | 1903 | */ |
| 1895 | longest = be32_to_cpu(agf->agf_longest); | 1904 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { |
| 1896 | longest = (longest > delta) ? (longest - delta) : | 1905 | delta = need > be32_to_cpu(agf->agf_flcount) ? |
| 1897 | (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); | 1906 | (need - be32_to_cpu(agf->agf_flcount)) : 0; |
| 1898 | if (args->minlen + args->alignment + args->minalignslop - 1 > longest || | 1907 | longest = be32_to_cpu(agf->agf_longest); |
| 1899 | (!(flags & XFS_ALLOC_FLAG_FREEING) && | 1908 | longest = (longest > delta) ? (longest - delta) : |
| 1900 | (int)(be32_to_cpu(agf->agf_freeblks) + | 1909 | (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); |
| 1901 | be32_to_cpu(agf->agf_flcount) - need - args->total) < | 1910 | if ((args->minlen + args->alignment + args->minalignslop - 1) > |
| 1902 | (int)args->minleft)) { | 1911 | longest || |
| 1903 | xfs_trans_brelse(tp, agbp); | 1912 | ((int)(be32_to_cpu(agf->agf_freeblks) + |
| 1904 | args->agbp = NULL; | 1913 | be32_to_cpu(agf->agf_flcount) - need - args->total) < |
| 1905 | return 0; | 1914 | (int)args->minleft)) { |
| 1915 | xfs_trans_brelse(tp, agbp); | ||
| 1916 | args->agbp = NULL; | ||
| 1917 | return 0; | ||
| 1918 | } | ||
| 1906 | } | 1919 | } |
| 1907 | /* | 1920 | /* |
| 1908 | * Make the freelist shorter if it's too long. | 1921 | * Make the freelist shorter if it's too long. |
| @@ -1950,12 +1963,11 @@ xfs_alloc_fix_freelist( | |||
| 1950 | * on a completely full ag. | 1963 | * on a completely full ag. |
| 1951 | */ | 1964 | */ |
| 1952 | if (targs.agbno == NULLAGBLOCK) { | 1965 | if (targs.agbno == NULLAGBLOCK) { |
| 1953 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { | 1966 | if (flags & XFS_ALLOC_FLAG_FREEING) |
| 1954 | xfs_trans_brelse(tp, agflbp); | 1967 | break; |
| 1955 | args->agbp = NULL; | 1968 | xfs_trans_brelse(tp, agflbp); |
| 1956 | return 0; | 1969 | args->agbp = NULL; |
| 1957 | } | 1970 | return 0; |
| 1958 | break; | ||
| 1959 | } | 1971 | } |
| 1960 | /* | 1972 | /* |
| 1961 | * Put each allocated block on the list. | 1973 | * Put each allocated block on the list. |
| @@ -2011,7 +2023,7 @@ xfs_alloc_get_freelist( | |||
| 2011 | /* | 2023 | /* |
| 2012 | * Get the block number and update the data structures. | 2024 | * Get the block number and update the data structures. |
| 2013 | */ | 2025 | */ |
| 2014 | bno = INT_GET(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)], ARCH_CONVERT); | 2026 | bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]); |
| 2015 | be32_add(&agf->agf_flfirst, 1); | 2027 | be32_add(&agf->agf_flfirst, 1); |
| 2016 | xfs_trans_brelse(tp, agflbp); | 2028 | xfs_trans_brelse(tp, agflbp); |
| 2017 | if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) | 2029 | if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp)) |
| @@ -2098,7 +2110,7 @@ xfs_alloc_put_freelist( | |||
| 2098 | { | 2110 | { |
| 2099 | xfs_agf_t *agf; /* a.g. freespace structure */ | 2111 | xfs_agf_t *agf; /* a.g. freespace structure */ |
| 2100 | xfs_agfl_t *agfl; /* a.g. free block array */ | 2112 | xfs_agfl_t *agfl; /* a.g. free block array */ |
| 2101 | xfs_agblock_t *blockp;/* pointer to array entry */ | 2113 | __be32 *blockp;/* pointer to array entry */ |
| 2102 | int error; | 2114 | int error; |
| 2103 | #ifdef XFS_ALLOC_TRACE | 2115 | #ifdef XFS_ALLOC_TRACE |
| 2104 | static char fname[] = "xfs_alloc_put_freelist"; | 2116 | static char fname[] = "xfs_alloc_put_freelist"; |
| @@ -2122,7 +2134,7 @@ xfs_alloc_put_freelist( | |||
| 2122 | pag->pagf_flcount++; | 2134 | pag->pagf_flcount++; |
| 2123 | ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)); | 2135 | ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)); |
| 2124 | blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)]; | 2136 | blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)]; |
| 2125 | INT_SET(*blockp, ARCH_CONVERT, bno); | 2137 | *blockp = cpu_to_be32(bno); |
| 2126 | TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT); | 2138 | TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT); |
| 2127 | xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT); | 2139 | xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT); |
| 2128 | xfs_trans_log_buf(tp, agflbp, | 2140 | xfs_trans_log_buf(tp, agflbp, |
| @@ -2442,31 +2454,26 @@ xfs_free_extent( | |||
| 2442 | xfs_fsblock_t bno, /* starting block number of extent */ | 2454 | xfs_fsblock_t bno, /* starting block number of extent */ |
| 2443 | xfs_extlen_t len) /* length of extent */ | 2455 | xfs_extlen_t len) /* length of extent */ |
| 2444 | { | 2456 | { |
| 2445 | #ifdef DEBUG | 2457 | xfs_alloc_arg_t args; |
| 2446 | xfs_agf_t *agf; /* a.g. freespace header */ | ||
| 2447 | #endif | ||
| 2448 | xfs_alloc_arg_t args; /* allocation argument structure */ | ||
| 2449 | int error; | 2458 | int error; |
| 2450 | 2459 | ||
| 2451 | ASSERT(len != 0); | 2460 | ASSERT(len != 0); |
| 2461 | memset(&args, 0, sizeof(xfs_alloc_arg_t)); | ||
| 2452 | args.tp = tp; | 2462 | args.tp = tp; |
| 2453 | args.mp = tp->t_mountp; | 2463 | args.mp = tp->t_mountp; |
| 2454 | args.agno = XFS_FSB_TO_AGNO(args.mp, bno); | 2464 | args.agno = XFS_FSB_TO_AGNO(args.mp, bno); |
| 2455 | ASSERT(args.agno < args.mp->m_sb.sb_agcount); | 2465 | ASSERT(args.agno < args.mp->m_sb.sb_agcount); |
| 2456 | args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); | 2466 | args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); |
| 2457 | args.alignment = 1; | ||
| 2458 | args.minlen = args.minleft = args.minalignslop = 0; | ||
| 2459 | down_read(&args.mp->m_peraglock); | 2467 | down_read(&args.mp->m_peraglock); |
| 2460 | args.pag = &args.mp->m_perag[args.agno]; | 2468 | args.pag = &args.mp->m_perag[args.agno]; |
| 2461 | if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) | 2469 | if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) |
| 2462 | goto error0; | 2470 | goto error0; |
| 2463 | #ifdef DEBUG | 2471 | #ifdef DEBUG |
| 2464 | ASSERT(args.agbp != NULL); | 2472 | ASSERT(args.agbp != NULL); |
| 2465 | agf = XFS_BUF_TO_AGF(args.agbp); | 2473 | ASSERT((args.agbno + len) <= |
| 2466 | ASSERT(args.agbno + len <= be32_to_cpu(agf->agf_length)); | 2474 | be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)); |
| 2467 | #endif | 2475 | #endif |
| 2468 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, | 2476 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); |
| 2469 | len, 0); | ||
| 2470 | error0: | 2477 | error0: |
| 2471 | up_read(&args.mp->m_peraglock); | 2478 | up_read(&args.mp->m_peraglock); |
| 2472 | return error; | 2479 | return error; |
