diff options
author | Dave Chinner <dchinner@redhat.com> | 2012-06-22 04:50:13 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-07-01 15:50:07 -0400 |
commit | 3605431fb9739a30ccd0c6380ae8e3c6f8e670a5 (patch) | |
tree | 629f4966d5dd71f117eca562bf238275e8e0addc /fs/xfs | |
parent | 372cc85ec6820c91b4eeff303880f25cb5a00ab5 (diff) |
xfs: use discontiguous xfs_buf support in dabuf wrappers
First step in converting the directory code to use native
discontiguous buffers and replacing the dabuf construct.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_da_btree.c | 538 | ||||
-rw-r--r-- | fs/xfs/xfs_da_btree.h | 6 |
2 files changed, 239 insertions, 305 deletions
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 015b946c5808..76e5dbaa95ea 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -85,7 +85,7 @@ STATIC void xfs_da_node_unbalance(xfs_da_state_t *state, | |||
85 | */ | 85 | */ |
86 | STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count); | 86 | STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count); |
87 | STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp); | 87 | STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp); |
88 | STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps); | 88 | STATIC xfs_dabuf_t *xfs_da_buf_make(xfs_buf_t *bp); |
89 | STATIC int xfs_da_blk_unlink(xfs_da_state_t *state, | 89 | STATIC int xfs_da_blk_unlink(xfs_da_state_t *state, |
90 | xfs_da_state_blk_t *drop_blk, | 90 | xfs_da_state_blk_t *drop_blk, |
91 | xfs_da_state_blk_t *save_blk); | 91 | xfs_da_state_blk_t *save_blk); |
@@ -1967,35 +1967,75 @@ xfs_da_map_covers_blocks( | |||
1967 | } | 1967 | } |
1968 | 1968 | ||
1969 | /* | 1969 | /* |
1970 | * Make a dabuf. | 1970 | * Convert a struct xfs_bmbt_irec to a struct xfs_buf_map. |
1971 | * Used for get_buf, read_buf, read_bufr, and reada_buf. | 1971 | * |
1972 | * For the single map case, it is assumed that the caller has provided a pointer | ||
1973 | * to a valid xfs_buf_map. For the multiple map case, this function will | ||
1974 | * allocate the xfs_buf_map to hold all the maps and replace the caller's single | ||
1975 | * map pointer with the allocated map. | ||
1972 | */ | 1976 | */ |
1973 | STATIC int | 1977 | static int |
1974 | xfs_da_do_buf( | 1978 | xfs_buf_map_from_irec( |
1975 | xfs_trans_t *trans, | 1979 | struct xfs_mount *mp, |
1976 | xfs_inode_t *dp, | 1980 | struct xfs_buf_map **mapp, |
1977 | xfs_dablk_t bno, | 1981 | unsigned int *nmaps, |
1978 | xfs_daddr_t *mappedbnop, | 1982 | struct xfs_bmbt_irec *irecs, |
1979 | xfs_dabuf_t **bpp, | 1983 | unsigned int nirecs) |
1980 | int whichfork, | ||
1981 | int caller) | ||
1982 | { | 1984 | { |
1983 | xfs_buf_t *bp = NULL; | 1985 | struct xfs_buf_map *map; |
1984 | xfs_buf_t **bplist; | 1986 | int i; |
1985 | int error=0; | 1987 | |
1986 | int i; | 1988 | ASSERT(*nmaps == 1); |
1987 | xfs_bmbt_irec_t map; | 1989 | ASSERT(nirecs >= 1); |
1988 | xfs_bmbt_irec_t *mapp; | 1990 | |
1989 | xfs_daddr_t mappedbno; | 1991 | if (nirecs > 1) { |
1990 | xfs_mount_t *mp; | 1992 | map = kmem_zalloc(nirecs * sizeof(struct xfs_buf_map), KM_SLEEP); |
1991 | int nbplist=0; | 1993 | if (!map) |
1992 | int nfsb; | 1994 | return ENOMEM; |
1993 | int nmap; | 1995 | *mapp = map; |
1994 | xfs_dabuf_t *rbp; | 1996 | } |
1997 | |||
1998 | *nmaps = nirecs; | ||
1999 | map = *mapp; | ||
2000 | for (i = 0; i < *nmaps; i++) { | ||
2001 | ASSERT(irecs[i].br_startblock != DELAYSTARTBLOCK && | ||
2002 | irecs[i].br_startblock != HOLESTARTBLOCK); | ||
2003 | map[i].bm_bn = XFS_FSB_TO_DADDR(mp, irecs[i].br_startblock); | ||
2004 | map[i].bm_len = XFS_FSB_TO_BB(mp, irecs[i].br_blockcount); | ||
2005 | } | ||
2006 | return 0; | ||
2007 | } | ||
2008 | |||
2009 | /* | ||
2010 | * Map the block we are given ready for reading. There are three possible return | ||
2011 | * values: | ||
2012 | * -1 - will be returned if we land in a hole and mappedbno == -2 so the | ||
2013 | * caller knows not to execute a subsequent read. | ||
2014 | * 0 - if we mapped the block successfully | ||
2015 | * >0 - positive error number if there was an error. | ||
2016 | */ | ||
2017 | static int | ||
2018 | xfs_dabuf_map( | ||
2019 | struct xfs_trans *trans, | ||
2020 | struct xfs_inode *dp, | ||
2021 | xfs_dablk_t bno, | ||
2022 | xfs_daddr_t mappedbno, | ||
2023 | int whichfork, | ||
2024 | struct xfs_buf_map **map, | ||
2025 | int *nmaps) | ||
2026 | { | ||
2027 | struct xfs_mount *mp = dp->i_mount; | ||
2028 | int nfsb; | ||
2029 | int error = 0; | ||
2030 | struct xfs_bmbt_irec irec; | ||
2031 | struct xfs_bmbt_irec *irecs = &irec; | ||
2032 | int nirecs; | ||
2033 | |||
2034 | ASSERT(map && *map); | ||
2035 | ASSERT(*nmaps == 1); | ||
1995 | 2036 | ||
1996 | mp = dp->i_mount; | ||
1997 | nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1; | 2037 | nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1; |
1998 | mappedbno = *mappedbnop; | 2038 | |
1999 | /* | 2039 | /* |
2000 | * Caller doesn't have a mapping. -2 means don't complain | 2040 | * Caller doesn't have a mapping. -2 means don't complain |
2001 | * if we land in a hole. | 2041 | * if we land in a hole. |
@@ -2004,112 +2044,152 @@ xfs_da_do_buf( | |||
2004 | /* | 2044 | /* |
2005 | * Optimize the one-block case. | 2045 | * Optimize the one-block case. |
2006 | */ | 2046 | */ |
2007 | if (nfsb == 1) | 2047 | if (nfsb != 1) |
2008 | mapp = ↦ | 2048 | irecs = kmem_zalloc(sizeof(irec) * nfsb, KM_SLEEP); |
2009 | else | ||
2010 | mapp = kmem_alloc(sizeof(*mapp) * nfsb, KM_SLEEP); | ||
2011 | 2049 | ||
2012 | nmap = nfsb; | 2050 | nirecs = nfsb; |
2013 | error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, mapp, | 2051 | error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, irecs, |
2014 | &nmap, xfs_bmapi_aflag(whichfork)); | 2052 | &nirecs, xfs_bmapi_aflag(whichfork)); |
2015 | if (error) | 2053 | if (error) |
2016 | goto exit0; | 2054 | goto out; |
2017 | } else { | 2055 | } else { |
2018 | map.br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); | 2056 | irecs->br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); |
2019 | map.br_startoff = (xfs_fileoff_t)bno; | 2057 | irecs->br_startoff = (xfs_fileoff_t)bno; |
2020 | map.br_blockcount = nfsb; | 2058 | irecs->br_blockcount = nfsb; |
2021 | mapp = ↦ | 2059 | irecs->br_state = 0; |
2022 | nmap = 1; | 2060 | nirecs = 1; |
2023 | } | 2061 | } |
2024 | if (!xfs_da_map_covers_blocks(nmap, mapp, bno, nfsb)) { | 2062 | |
2025 | error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED); | 2063 | if (!xfs_da_map_covers_blocks(nirecs, irecs, bno, nfsb)) { |
2064 | error = mappedbno == -2 ? -1 : XFS_ERROR(EFSCORRUPTED); | ||
2026 | if (unlikely(error == EFSCORRUPTED)) { | 2065 | if (unlikely(error == EFSCORRUPTED)) { |
2027 | if (xfs_error_level >= XFS_ERRLEVEL_LOW) { | 2066 | if (xfs_error_level >= XFS_ERRLEVEL_LOW) { |
2067 | int i; | ||
2028 | xfs_alert(mp, "%s: bno %lld dir: inode %lld", | 2068 | xfs_alert(mp, "%s: bno %lld dir: inode %lld", |
2029 | __func__, (long long)bno, | 2069 | __func__, (long long)bno, |
2030 | (long long)dp->i_ino); | 2070 | (long long)dp->i_ino); |
2031 | for (i = 0; i < nmap; i++) { | 2071 | for (i = 0; i < *nmaps; i++) { |
2032 | xfs_alert(mp, | 2072 | xfs_alert(mp, |
2033 | "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", | 2073 | "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", |
2034 | i, | 2074 | i, |
2035 | (long long)mapp[i].br_startoff, | 2075 | (long long)irecs[i].br_startoff, |
2036 | (long long)mapp[i].br_startblock, | 2076 | (long long)irecs[i].br_startblock, |
2037 | (long long)mapp[i].br_blockcount, | 2077 | (long long)irecs[i].br_blockcount, |
2038 | mapp[i].br_state); | 2078 | irecs[i].br_state); |
2039 | } | 2079 | } |
2040 | } | 2080 | } |
2041 | XFS_ERROR_REPORT("xfs_da_do_buf(1)", | 2081 | XFS_ERROR_REPORT("xfs_da_do_buf(1)", |
2042 | XFS_ERRLEVEL_LOW, mp); | 2082 | XFS_ERRLEVEL_LOW, mp); |
2043 | } | 2083 | } |
2044 | goto exit0; | 2084 | goto out; |
2045 | } | 2085 | } |
2046 | if (caller != 3 && nmap > 1) { | 2086 | error = xfs_buf_map_from_irec(mp, map, nmaps, irecs, nirecs); |
2047 | bplist = kmem_alloc(sizeof(*bplist) * nmap, KM_SLEEP); | 2087 | out: |
2048 | nbplist = 0; | 2088 | if (irecs != &irec) |
2049 | } else | 2089 | kmem_free(irecs); |
2050 | bplist = NULL; | 2090 | return error; |
2051 | /* | 2091 | } |
2052 | * Turn the mapping(s) into buffer(s). | 2092 | |
2053 | */ | 2093 | /* |
2054 | for (i = 0; i < nmap; i++) { | 2094 | * Get a buffer for the dir/attr block. |
2055 | int nmapped; | 2095 | */ |
2056 | 2096 | int | |
2057 | mappedbno = XFS_FSB_TO_DADDR(mp, mapp[i].br_startblock); | 2097 | xfs_da_get_buf( |
2058 | if (i == 0) | 2098 | struct xfs_trans *trans, |
2059 | *mappedbnop = mappedbno; | 2099 | struct xfs_inode *dp, |
2060 | nmapped = (int)XFS_FSB_TO_BB(mp, mapp[i].br_blockcount); | 2100 | xfs_dablk_t bno, |
2061 | switch (caller) { | 2101 | xfs_daddr_t mappedbno, |
2062 | case 0: | 2102 | xfs_dabuf_t **bpp, |
2063 | bp = xfs_trans_get_buf(trans, mp->m_ddev_targp, | 2103 | int whichfork) |
2064 | mappedbno, nmapped, 0); | 2104 | { |
2065 | error = bp ? bp->b_error : XFS_ERROR(EIO); | 2105 | struct xfs_buf *bp; |
2066 | break; | 2106 | struct xfs_buf_map map; |
2067 | case 1: | 2107 | struct xfs_buf_map *mapp; |
2068 | case 2: | 2108 | int nmap; |
2069 | bp = NULL; | 2109 | int error; |
2070 | error = xfs_trans_read_buf(mp, trans, mp->m_ddev_targp, | 2110 | |
2071 | mappedbno, nmapped, 0, &bp); | 2111 | *bpp = NULL; |
2072 | break; | 2112 | mapp = ↦ |
2073 | case 3: | 2113 | nmap = 1; |
2074 | xfs_buf_readahead(mp->m_ddev_targp, mappedbno, nmapped); | 2114 | error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork, |
2115 | &mapp, &nmap); | ||
2116 | if (error) { | ||
2117 | /* mapping a hole is not an error, but we don't continue */ | ||
2118 | if (error == -1) | ||
2075 | error = 0; | 2119 | error = 0; |
2076 | bp = NULL; | 2120 | goto out_free; |
2077 | break; | ||
2078 | } | ||
2079 | if (error) { | ||
2080 | if (bp) | ||
2081 | xfs_trans_brelse(trans, bp); | ||
2082 | goto exit1; | ||
2083 | } | ||
2084 | if (!bp) | ||
2085 | continue; | ||
2086 | if (caller == 1) { | ||
2087 | if (whichfork == XFS_ATTR_FORK) | ||
2088 | xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); | ||
2089 | else | ||
2090 | xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); | ||
2091 | } | ||
2092 | if (bplist) { | ||
2093 | bplist[nbplist++] = bp; | ||
2094 | } | ||
2095 | } | 2121 | } |
2096 | /* | 2122 | |
2097 | * Build a dabuf structure. | 2123 | bp = xfs_trans_get_buf_map(trans, dp->i_mount->m_ddev_targp, |
2098 | */ | 2124 | mapp, nmap, 0); |
2099 | if (bplist) { | 2125 | error = bp ? bp->b_error : XFS_ERROR(EIO); |
2100 | rbp = xfs_da_buf_make(nbplist, bplist); | 2126 | if (error) { |
2101 | } else if (bp) | 2127 | xfs_trans_brelse(trans, bp); |
2102 | rbp = xfs_da_buf_make(1, &bp); | 2128 | goto out_free; |
2129 | } | ||
2130 | |||
2131 | *bpp = xfs_da_buf_make(bp); | ||
2132 | |||
2133 | out_free: | ||
2134 | if (mapp != &map) | ||
2135 | kmem_free(mapp); | ||
2136 | |||
2137 | return error; | ||
2138 | } | ||
2139 | |||
2140 | /* | ||
2141 | * Get a buffer for the dir/attr block, fill in the contents. | ||
2142 | */ | ||
2143 | int | ||
2144 | xfs_da_read_buf( | ||
2145 | struct xfs_trans *trans, | ||
2146 | struct xfs_inode *dp, | ||
2147 | xfs_dablk_t bno, | ||
2148 | xfs_daddr_t mappedbno, | ||
2149 | xfs_dabuf_t **bpp, | ||
2150 | int whichfork) | ||
2151 | { | ||
2152 | struct xfs_buf *bp; | ||
2153 | struct xfs_buf_map map; | ||
2154 | struct xfs_buf_map *mapp; | ||
2155 | int nmap; | ||
2156 | int error; | ||
2157 | |||
2158 | *bpp = NULL; | ||
2159 | mapp = ↦ | ||
2160 | nmap = 1; | ||
2161 | error = xfs_dabuf_map(trans, dp, bno, mappedbno, whichfork, | ||
2162 | &mapp, &nmap); | ||
2163 | if (error) { | ||
2164 | /* mapping a hole is not an error, but we don't continue */ | ||
2165 | if (error == -1) | ||
2166 | error = 0; | ||
2167 | goto out_free; | ||
2168 | } | ||
2169 | |||
2170 | error = xfs_trans_read_buf_map(dp->i_mount, trans, | ||
2171 | dp->i_mount->m_ddev_targp, | ||
2172 | mapp, nmap, 0, &bp); | ||
2173 | if (error) | ||
2174 | goto out_free; | ||
2175 | |||
2176 | if (whichfork == XFS_ATTR_FORK) | ||
2177 | xfs_buf_set_ref(bp, XFS_ATTR_BTREE_REF); | ||
2103 | else | 2178 | else |
2104 | rbp = NULL; | 2179 | xfs_buf_set_ref(bp, XFS_DIR_BTREE_REF); |
2180 | |||
2181 | *bpp = xfs_da_buf_make(bp); | ||
2182 | |||
2105 | /* | 2183 | /* |
2106 | * For read_buf, check the magic number. | 2184 | * This verification code will be moved to a CRC verification callback |
2185 | * function so just leave it here unchanged until then. | ||
2107 | */ | 2186 | */ |
2108 | if (caller == 1) { | 2187 | { |
2109 | xfs_dir2_data_hdr_t *hdr = rbp->data; | 2188 | xfs_dir2_data_hdr_t *hdr = (*bpp)->data; |
2110 | xfs_dir2_free_t *free = rbp->data; | 2189 | xfs_dir2_free_t *free = (*bpp)->data; |
2111 | xfs_da_blkinfo_t *info = rbp->data; | 2190 | xfs_da_blkinfo_t *info = (*bpp)->data; |
2112 | uint magic, magic1; | 2191 | uint magic, magic1; |
2192 | struct xfs_mount *mp = dp->i_mount; | ||
2113 | 2193 | ||
2114 | magic = be16_to_cpu(info->magic); | 2194 | magic = be16_to_cpu(info->magic); |
2115 | magic1 = be32_to_cpu(hdr->magic); | 2195 | magic1 = be32_to_cpu(hdr->magic); |
@@ -2123,66 +2203,20 @@ xfs_da_do_buf( | |||
2123 | (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)), | 2203 | (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)), |
2124 | mp, XFS_ERRTAG_DA_READ_BUF, | 2204 | mp, XFS_ERRTAG_DA_READ_BUF, |
2125 | XFS_RANDOM_DA_READ_BUF))) { | 2205 | XFS_RANDOM_DA_READ_BUF))) { |
2126 | trace_xfs_da_btree_corrupt(rbp->bps[0], _RET_IP_); | 2206 | trace_xfs_da_btree_corrupt(bp, _RET_IP_); |
2127 | XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)", | 2207 | XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)", |
2128 | XFS_ERRLEVEL_LOW, mp, info); | 2208 | XFS_ERRLEVEL_LOW, mp, info); |
2129 | error = XFS_ERROR(EFSCORRUPTED); | 2209 | error = XFS_ERROR(EFSCORRUPTED); |
2130 | xfs_da_brelse(trans, rbp); | 2210 | xfs_da_brelse(trans, *bpp); |
2131 | nbplist = 0; | 2211 | goto out_free; |
2132 | goto exit1; | ||
2133 | } | 2212 | } |
2134 | } | 2213 | } |
2135 | if (bplist) { | 2214 | |
2136 | kmem_free(bplist); | 2215 | out_free: |
2137 | } | ||
2138 | if (mapp != &map) { | ||
2139 | kmem_free(mapp); | ||
2140 | } | ||
2141 | if (bpp) | ||
2142 | *bpp = rbp; | ||
2143 | return 0; | ||
2144 | exit1: | ||
2145 | if (bplist) { | ||
2146 | for (i = 0; i < nbplist; i++) | ||
2147 | xfs_trans_brelse(trans, bplist[i]); | ||
2148 | kmem_free(bplist); | ||
2149 | } | ||
2150 | exit0: | ||
2151 | if (mapp != &map) | 2216 | if (mapp != &map) |
2152 | kmem_free(mapp); | 2217 | kmem_free(mapp); |
2153 | if (bpp) | ||
2154 | *bpp = NULL; | ||
2155 | return error; | ||
2156 | } | ||
2157 | |||
2158 | /* | ||
2159 | * Get a buffer for the dir/attr block. | ||
2160 | */ | ||
2161 | int | ||
2162 | xfs_da_get_buf( | ||
2163 | xfs_trans_t *trans, | ||
2164 | xfs_inode_t *dp, | ||
2165 | xfs_dablk_t bno, | ||
2166 | xfs_daddr_t mappedbno, | ||
2167 | xfs_dabuf_t **bpp, | ||
2168 | int whichfork) | ||
2169 | { | ||
2170 | return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 0); | ||
2171 | } | ||
2172 | 2218 | ||
2173 | /* | 2219 | return error; |
2174 | * Get a buffer for the dir/attr block, fill in the contents. | ||
2175 | */ | ||
2176 | int | ||
2177 | xfs_da_read_buf( | ||
2178 | xfs_trans_t *trans, | ||
2179 | xfs_inode_t *dp, | ||
2180 | xfs_dablk_t bno, | ||
2181 | xfs_daddr_t mappedbno, | ||
2182 | xfs_dabuf_t **bpp, | ||
2183 | int whichfork) | ||
2184 | { | ||
2185 | return xfs_da_do_buf(trans, dp, bno, &mappedbno, bpp, whichfork, 1); | ||
2186 | } | 2220 | } |
2187 | 2221 | ||
2188 | /* | 2222 | /* |
@@ -2190,18 +2224,38 @@ xfs_da_read_buf( | |||
2190 | */ | 2224 | */ |
2191 | xfs_daddr_t | 2225 | xfs_daddr_t |
2192 | xfs_da_reada_buf( | 2226 | xfs_da_reada_buf( |
2193 | xfs_trans_t *trans, | 2227 | struct xfs_trans *trans, |
2194 | xfs_inode_t *dp, | 2228 | struct xfs_inode *dp, |
2195 | xfs_dablk_t bno, | 2229 | xfs_dablk_t bno, |
2196 | int whichfork) | 2230 | int whichfork) |
2197 | { | 2231 | { |
2198 | xfs_daddr_t rval; | 2232 | xfs_daddr_t mappedbno = -1; |
2233 | struct xfs_buf_map map; | ||
2234 | struct xfs_buf_map *mapp; | ||
2235 | int nmap; | ||
2236 | int error; | ||
2237 | |||
2238 | mapp = ↦ | ||
2239 | nmap = 1; | ||
2240 | error = xfs_dabuf_map(trans, dp, bno, -1, whichfork, | ||
2241 | &mapp, &nmap); | ||
2242 | if (error) { | ||
2243 | /* mapping a hole is not an error, but we don't continue */ | ||
2244 | if (error == -1) | ||
2245 | error = 0; | ||
2246 | goto out_free; | ||
2247 | } | ||
2199 | 2248 | ||
2200 | rval = -1; | 2249 | mappedbno = mapp[0].bm_bn; |
2201 | if (xfs_da_do_buf(trans, dp, bno, &rval, NULL, whichfork, 3)) | 2250 | xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap); |
2251 | |||
2252 | out_free: | ||
2253 | if (mapp != &map) | ||
2254 | kmem_free(mapp); | ||
2255 | |||
2256 | if (error) | ||
2202 | return -1; | 2257 | return -1; |
2203 | else | 2258 | return mappedbno; |
2204 | return rval; | ||
2205 | } | 2259 | } |
2206 | 2260 | ||
2207 | kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */ | 2261 | kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */ |
@@ -2261,78 +2315,25 @@ xfs_da_state_free(xfs_da_state_t *state) | |||
2261 | */ | 2315 | */ |
2262 | /* ARGSUSED */ | 2316 | /* ARGSUSED */ |
2263 | STATIC xfs_dabuf_t * | 2317 | STATIC xfs_dabuf_t * |
2264 | xfs_da_buf_make(int nbuf, xfs_buf_t **bps) | 2318 | xfs_da_buf_make(xfs_buf_t *bp) |
2265 | { | 2319 | { |
2266 | xfs_buf_t *bp; | ||
2267 | xfs_dabuf_t *dabuf; | 2320 | xfs_dabuf_t *dabuf; |
2268 | int i; | ||
2269 | int off; | ||
2270 | 2321 | ||
2271 | if (nbuf == 1) | 2322 | dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_NOFS); |
2272 | dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_NOFS); | 2323 | dabuf->bbcount = bp->b_length; |
2273 | else | 2324 | dabuf->data = bp->b_addr; |
2274 | dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_NOFS); | 2325 | dabuf->bp = bp; |
2275 | dabuf->dirty = 0; | ||
2276 | if (nbuf == 1) { | ||
2277 | dabuf->nbuf = 1; | ||
2278 | bp = bps[0]; | ||
2279 | dabuf->bbcount = bp->b_length; | ||
2280 | dabuf->data = bp->b_addr; | ||
2281 | dabuf->bps[0] = bp; | ||
2282 | } else { | ||
2283 | dabuf->nbuf = nbuf; | ||
2284 | for (i = 0, dabuf->bbcount = 0; i < nbuf; i++) { | ||
2285 | dabuf->bps[i] = bp = bps[i]; | ||
2286 | dabuf->bbcount += bp->b_length; | ||
2287 | } | ||
2288 | dabuf->data = kmem_alloc(BBTOB(dabuf->bbcount), KM_SLEEP); | ||
2289 | for (i = off = 0; i < nbuf; i++, off += BBTOB(bp->b_length)) { | ||
2290 | bp = bps[i]; | ||
2291 | memcpy((char *)dabuf->data + off, bp->b_addr, | ||
2292 | BBTOB(bp->b_length)); | ||
2293 | } | ||
2294 | } | ||
2295 | return dabuf; | 2326 | return dabuf; |
2296 | } | 2327 | } |
2297 | 2328 | ||
2298 | /* | 2329 | /* |
2299 | * Un-dirty a dabuf. | ||
2300 | */ | ||
2301 | STATIC void | ||
2302 | xfs_da_buf_clean(xfs_dabuf_t *dabuf) | ||
2303 | { | ||
2304 | xfs_buf_t *bp; | ||
2305 | int i; | ||
2306 | int off; | ||
2307 | |||
2308 | if (dabuf->dirty) { | ||
2309 | ASSERT(dabuf->nbuf > 1); | ||
2310 | dabuf->dirty = 0; | ||
2311 | for (i = off = 0; i < dabuf->nbuf; | ||
2312 | i++, off += BBTOB(bp->b_length)) { | ||
2313 | bp = dabuf->bps[i]; | ||
2314 | memcpy(bp->b_addr, dabuf->data + off, | ||
2315 | BBTOB(bp->b_length)); | ||
2316 | } | ||
2317 | } | ||
2318 | } | ||
2319 | |||
2320 | /* | ||
2321 | * Release a dabuf. | 2330 | * Release a dabuf. |
2322 | */ | 2331 | */ |
2323 | void | 2332 | void |
2324 | xfs_da_buf_done(xfs_dabuf_t *dabuf) | 2333 | xfs_da_buf_done(xfs_dabuf_t *dabuf) |
2325 | { | 2334 | { |
2326 | ASSERT(dabuf); | 2335 | ASSERT(dabuf->data && dabuf->bbcount && dabuf->bp); |
2327 | ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); | 2336 | kmem_zone_free(xfs_dabuf_zone, dabuf); |
2328 | if (dabuf->dirty) | ||
2329 | xfs_da_buf_clean(dabuf); | ||
2330 | if (dabuf->nbuf > 1) { | ||
2331 | kmem_free(dabuf->data); | ||
2332 | kmem_free(dabuf); | ||
2333 | } else { | ||
2334 | kmem_zone_free(xfs_dabuf_zone, dabuf); | ||
2335 | } | ||
2336 | } | 2337 | } |
2337 | 2338 | ||
2338 | /* | 2339 | /* |
@@ -2341,41 +2342,9 @@ xfs_da_buf_done(xfs_dabuf_t *dabuf) | |||
2341 | void | 2342 | void |
2342 | xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last) | 2343 | xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last) |
2343 | { | 2344 | { |
2344 | xfs_buf_t *bp; | 2345 | ASSERT(dabuf->data && dabuf->bbcount && dabuf->bp); |
2345 | uint f; | 2346 | ASSERT(dabuf->data == dabuf->bp->b_addr); |
2346 | int i; | 2347 | xfs_trans_log_buf(tp, dabuf->bp, first, last); |
2347 | uint l; | ||
2348 | int off; | ||
2349 | |||
2350 | ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); | ||
2351 | if (dabuf->nbuf == 1) { | ||
2352 | ASSERT(dabuf->data == dabuf->bps[0]->b_addr); | ||
2353 | xfs_trans_log_buf(tp, dabuf->bps[0], first, last); | ||
2354 | return; | ||
2355 | } | ||
2356 | dabuf->dirty = 1; | ||
2357 | ASSERT(first <= last); | ||
2358 | for (i = off = 0; i < dabuf->nbuf; i++, off += BBTOB(bp->b_length)) { | ||
2359 | bp = dabuf->bps[i]; | ||
2360 | f = off; | ||
2361 | l = f + BBTOB(bp->b_length) - 1; | ||
2362 | if (f < first) | ||
2363 | f = first; | ||
2364 | if (l > last) | ||
2365 | l = last; | ||
2366 | if (f <= l) | ||
2367 | xfs_trans_log_buf(tp, bp, f - off, l - off); | ||
2368 | /* | ||
2369 | * B_DONE is set by xfs_trans_log buf. | ||
2370 | * If we don't set it on a new buffer (get not read) | ||
2371 | * then if we don't put anything in the buffer it won't | ||
2372 | * be set, and at commit it it released into the cache, | ||
2373 | * and then a read will fail. | ||
2374 | */ | ||
2375 | else if (!(XFS_BUF_ISDONE(bp))) | ||
2376 | XFS_BUF_DONE(bp); | ||
2377 | } | ||
2378 | ASSERT(last < off); | ||
2379 | } | 2348 | } |
2380 | 2349 | ||
2381 | /* | 2350 | /* |
@@ -2386,24 +2355,9 @@ xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last) | |||
2386 | void | 2355 | void |
2387 | xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf) | 2356 | xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf) |
2388 | { | 2357 | { |
2389 | xfs_buf_t *bp; | 2358 | ASSERT(dabuf->data && dabuf->bbcount && dabuf->bp); |
2390 | xfs_buf_t **bplist; | 2359 | xfs_trans_brelse(tp, dabuf->bp); |
2391 | int i; | ||
2392 | int nbuf; | ||
2393 | |||
2394 | ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); | ||
2395 | if ((nbuf = dabuf->nbuf) == 1) { | ||
2396 | bplist = &bp; | ||
2397 | bp = dabuf->bps[0]; | ||
2398 | } else { | ||
2399 | bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP); | ||
2400 | memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist)); | ||
2401 | } | ||
2402 | xfs_da_buf_done(dabuf); | 2360 | xfs_da_buf_done(dabuf); |
2403 | for (i = 0; i < nbuf; i++) | ||
2404 | xfs_trans_brelse(tp, bplist[i]); | ||
2405 | if (bplist != &bp) | ||
2406 | kmem_free(bplist); | ||
2407 | } | 2361 | } |
2408 | 2362 | ||
2409 | /* | 2363 | /* |
@@ -2412,24 +2366,9 @@ xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf) | |||
2412 | void | 2366 | void |
2413 | xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf) | 2367 | xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf) |
2414 | { | 2368 | { |
2415 | xfs_buf_t *bp; | 2369 | ASSERT(dabuf->data && dabuf->bbcount && dabuf->bp); |
2416 | xfs_buf_t **bplist; | ||
2417 | int i; | ||
2418 | int nbuf; | ||
2419 | |||
2420 | ASSERT(dabuf->nbuf && dabuf->data && dabuf->bbcount && dabuf->bps[0]); | ||
2421 | if ((nbuf = dabuf->nbuf) == 1) { | ||
2422 | bplist = &bp; | ||
2423 | bp = dabuf->bps[0]; | ||
2424 | } else { | ||
2425 | bplist = kmem_alloc(nbuf * sizeof(*bplist), KM_SLEEP); | ||
2426 | memcpy(bplist, dabuf->bps, nbuf * sizeof(*bplist)); | ||
2427 | } | ||
2428 | xfs_da_buf_done(dabuf); | 2370 | xfs_da_buf_done(dabuf); |
2429 | for (i = 0; i < nbuf; i++) | 2371 | xfs_trans_binval(tp, dabuf->bp); |
2430 | xfs_trans_binval(tp, bplist[i]); | ||
2431 | if (bplist != &bp) | ||
2432 | kmem_free(bplist); | ||
2433 | } | 2372 | } |
2434 | 2373 | ||
2435 | /* | 2374 | /* |
@@ -2438,7 +2377,6 @@ xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf) | |||
2438 | xfs_daddr_t | 2377 | xfs_daddr_t |
2439 | xfs_da_blkno(xfs_dabuf_t *dabuf) | 2378 | xfs_da_blkno(xfs_dabuf_t *dabuf) |
2440 | { | 2379 | { |
2441 | ASSERT(dabuf->nbuf); | ||
2442 | ASSERT(dabuf->data); | 2380 | ASSERT(dabuf->data); |
2443 | return XFS_BUF_ADDR(dabuf->bps[0]); | 2381 | return XFS_BUF_ADDR(dabuf->bp); |
2444 | } | 2382 | } |
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index dbf7c074ae73..0b64c4a37afb 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -141,14 +141,10 @@ typedef struct xfs_da_args { | |||
141 | * same place as the b_addr field for the buffer, else to kmem_alloced memory. | 141 | * same place as the b_addr field for the buffer, else to kmem_alloced memory. |
142 | */ | 142 | */ |
143 | typedef struct xfs_dabuf { | 143 | typedef struct xfs_dabuf { |
144 | int nbuf; /* number of buffer pointers present */ | ||
145 | short dirty; /* data needs to be copied back */ | ||
146 | short bbcount; /* how large is data in bbs */ | 144 | short bbcount; /* how large is data in bbs */ |
147 | void *data; /* pointer for buffers' data */ | 145 | void *data; /* pointer for buffers' data */ |
148 | struct xfs_buf *bps[1]; /* actually nbuf of these */ | 146 | struct xfs_buf *bp; /* actually nbuf of these */ |
149 | } xfs_dabuf_t; | 147 | } xfs_dabuf_t; |
150 | #define XFS_DA_BUF_SIZE(n) \ | ||
151 | (sizeof(xfs_dabuf_t) + sizeof(struct xfs_buf *) * ((n) - 1)) | ||
152 | 148 | ||
153 | /* | 149 | /* |
154 | * Storage for holding state during Btree searches and split/join ops. | 150 | * Storage for holding state during Btree searches and split/join ops. |