aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-06-22 04:50:13 -0400
committerBen Myers <bpm@sgi.com>2012-07-01 15:50:07 -0400
commit3605431fb9739a30ccd0c6380ae8e3c6f8e670a5 (patch)
tree629f4966d5dd71f117eca562bf238275e8e0addc /fs/xfs
parent372cc85ec6820c91b4eeff303880f25cb5a00ab5 (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.c538
-rw-r--r--fs/xfs/xfs_da_btree.h6
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 */
86STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count); 86STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
87STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp); 87STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
88STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps); 88STATIC xfs_dabuf_t *xfs_da_buf_make(xfs_buf_t *bp);
89STATIC int xfs_da_blk_unlink(xfs_da_state_t *state, 89STATIC 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 */
1973STATIC int 1977static int
1974xfs_da_do_buf( 1978xfs_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 */
2017static int
2018xfs_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 = &map; 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 = &map; 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); 2087out:
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 2096int
2057 mappedbno = XFS_FSB_TO_DADDR(mp, mapp[i].br_startblock); 2097xfs_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 = &map;
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
2133out_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 */
2143int
2144xfs_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 = &map;
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); 2215out_free:
2137 }
2138 if (mapp != &map) {
2139 kmem_free(mapp);
2140 }
2141 if (bpp)
2142 *bpp = rbp;
2143 return 0;
2144exit1:
2145 if (bplist) {
2146 for (i = 0; i < nbplist; i++)
2147 xfs_trans_brelse(trans, bplist[i]);
2148 kmem_free(bplist);
2149 }
2150exit0:
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 */
2161int
2162xfs_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 */
2176int
2177xfs_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 */
2191xfs_daddr_t 2225xfs_daddr_t
2192xfs_da_reada_buf( 2226xfs_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 = &map;
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
2252out_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
2207kmem_zone_t *xfs_da_state_zone; /* anchor for state struct zone */ 2261kmem_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 */
2263STATIC xfs_dabuf_t * 2317STATIC xfs_dabuf_t *
2264xfs_da_buf_make(int nbuf, xfs_buf_t **bps) 2318xfs_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 */
2301STATIC void
2302xfs_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 */
2323void 2332void
2324xfs_da_buf_done(xfs_dabuf_t *dabuf) 2333xfs_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)
2341void 2342void
2342xfs_da_log_buf(xfs_trans_t *tp, xfs_dabuf_t *dabuf, uint first, uint last) 2343xfs_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)
2386void 2355void
2387xfs_da_brelse(xfs_trans_t *tp, xfs_dabuf_t *dabuf) 2356xfs_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)
2412void 2366void
2413xfs_da_binval(xfs_trans_t *tp, xfs_dabuf_t *dabuf) 2367xfs_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)
2438xfs_daddr_t 2377xfs_daddr_t
2439xfs_da_blkno(xfs_dabuf_t *dabuf) 2378xfs_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 */
143typedef struct xfs_dabuf { 143typedef 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.