diff options
author | Nathan Scott <nathans@sgi.com> | 2006-01-10 23:28:28 -0500 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2006-01-10 23:28:28 -0500 |
commit | dd9f438e32900d67def49fa1b8961b3e19b6fefc (patch) | |
tree | a0a51110a13445f3a27b72303e36ef6ef48db0eb /fs/xfs/xfs_bmap.c | |
parent | 061f7209bdfb0193b306f88b4ff36b2574b001d3 (diff) |
[XFS] Implement the di_extsize allocator hint for non-realtime files as
well. Also provides a mechanism for inheriting this property from the
parent directory for new files.
SGI-PV: 945264
SGI-Modid: xfs-linux-melb:xfs-kern:24367a
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 373 |
1 files changed, 231 insertions, 142 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index e415a4698e9c..8a32d65211b0 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -2146,13 +2146,176 @@ xfs_bmap_add_extent_hole_real( | |||
2146 | return 0; /* keep gcc quite */ | 2146 | return 0; /* keep gcc quite */ |
2147 | } | 2147 | } |
2148 | 2148 | ||
2149 | /* | ||
2150 | * Adjust the size of the new extent based on di_extsize and rt extsize. | ||
2151 | */ | ||
2152 | STATIC int | ||
2153 | xfs_bmap_extsize_align( | ||
2154 | xfs_mount_t *mp, | ||
2155 | xfs_bmbt_irec_t *gotp, /* next extent pointer */ | ||
2156 | xfs_bmbt_irec_t *prevp, /* previous extent pointer */ | ||
2157 | xfs_extlen_t extsz, /* align to this extent size */ | ||
2158 | int rt, /* is this a realtime inode? */ | ||
2159 | int eof, /* is extent at end-of-file? */ | ||
2160 | int delay, /* creating delalloc extent? */ | ||
2161 | int convert, /* overwriting unwritten extent? */ | ||
2162 | xfs_fileoff_t *offp, /* in/out: aligned offset */ | ||
2163 | xfs_extlen_t *lenp) /* in/out: aligned length */ | ||
2164 | { | ||
2165 | xfs_fileoff_t orig_off; /* original offset */ | ||
2166 | xfs_extlen_t orig_alen; /* original length */ | ||
2167 | xfs_fileoff_t orig_end; /* original off+len */ | ||
2168 | xfs_fileoff_t nexto; /* next file offset */ | ||
2169 | xfs_fileoff_t prevo; /* previous file offset */ | ||
2170 | xfs_fileoff_t align_off; /* temp for offset */ | ||
2171 | xfs_extlen_t align_alen; /* temp for length */ | ||
2172 | xfs_extlen_t temp; /* temp for calculations */ | ||
2173 | |||
2174 | if (convert) | ||
2175 | return 0; | ||
2176 | |||
2177 | orig_off = align_off = *offp; | ||
2178 | orig_alen = align_alen = *lenp; | ||
2179 | orig_end = orig_off + orig_alen; | ||
2180 | |||
2181 | /* | ||
2182 | * If this request overlaps an existing extent, then don't | ||
2183 | * attempt to perform any additional alignment. | ||
2184 | */ | ||
2185 | if (!delay && !eof && | ||
2186 | (orig_off >= gotp->br_startoff) && | ||
2187 | (orig_end <= gotp->br_startoff + gotp->br_blockcount)) { | ||
2188 | return 0; | ||
2189 | } | ||
2190 | |||
2191 | /* | ||
2192 | * If the file offset is unaligned vs. the extent size | ||
2193 | * we need to align it. This will be possible unless | ||
2194 | * the file was previously written with a kernel that didn't | ||
2195 | * perform this alignment, or if a truncate shot us in the | ||
2196 | * foot. | ||
2197 | */ | ||
2198 | temp = do_mod(orig_off, extsz); | ||
2199 | if (temp) { | ||
2200 | align_alen += temp; | ||
2201 | align_off -= temp; | ||
2202 | } | ||
2203 | /* | ||
2204 | * Same adjustment for the end of the requested area. | ||
2205 | */ | ||
2206 | if ((temp = (align_alen % extsz))) { | ||
2207 | align_alen += extsz - temp; | ||
2208 | } | ||
2209 | /* | ||
2210 | * If the previous block overlaps with this proposed allocation | ||
2211 | * then move the start forward without adjusting the length. | ||
2212 | */ | ||
2213 | if (prevp->br_startoff != NULLFILEOFF) { | ||
2214 | if (prevp->br_startblock == HOLESTARTBLOCK) | ||
2215 | prevo = prevp->br_startoff; | ||
2216 | else | ||
2217 | prevo = prevp->br_startoff + prevp->br_blockcount; | ||
2218 | } else | ||
2219 | prevo = 0; | ||
2220 | if (align_off != orig_off && align_off < prevo) | ||
2221 | align_off = prevo; | ||
2222 | /* | ||
2223 | * If the next block overlaps with this proposed allocation | ||
2224 | * then move the start back without adjusting the length, | ||
2225 | * but not before offset 0. | ||
2226 | * This may of course make the start overlap previous block, | ||
2227 | * and if we hit the offset 0 limit then the next block | ||
2228 | * can still overlap too. | ||
2229 | */ | ||
2230 | if (!eof && gotp->br_startoff != NULLFILEOFF) { | ||
2231 | if ((delay && gotp->br_startblock == HOLESTARTBLOCK) || | ||
2232 | (!delay && gotp->br_startblock == DELAYSTARTBLOCK)) | ||
2233 | nexto = gotp->br_startoff + gotp->br_blockcount; | ||
2234 | else | ||
2235 | nexto = gotp->br_startoff; | ||
2236 | } else | ||
2237 | nexto = NULLFILEOFF; | ||
2238 | if (!eof && | ||
2239 | align_off + align_alen != orig_end && | ||
2240 | align_off + align_alen > nexto) | ||
2241 | align_off = nexto > align_alen ? nexto - align_alen : 0; | ||
2242 | /* | ||
2243 | * If we're now overlapping the next or previous extent that | ||
2244 | * means we can't fit an extsz piece in this hole. Just move | ||
2245 | * the start forward to the first valid spot and set | ||
2246 | * the length so we hit the end. | ||
2247 | */ | ||
2248 | if (align_off != orig_off && align_off < prevo) | ||
2249 | align_off = prevo; | ||
2250 | if (align_off + align_alen != orig_end && | ||
2251 | align_off + align_alen > nexto && | ||
2252 | nexto != NULLFILEOFF) { | ||
2253 | ASSERT(nexto > prevo); | ||
2254 | align_alen = nexto - align_off; | ||
2255 | } | ||
2256 | |||
2257 | /* | ||
2258 | * If realtime, and the result isn't a multiple of the realtime | ||
2259 | * extent size we need to remove blocks until it is. | ||
2260 | */ | ||
2261 | if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) { | ||
2262 | /* | ||
2263 | * We're not covering the original request, or | ||
2264 | * we won't be able to once we fix the length. | ||
2265 | */ | ||
2266 | if (orig_off < align_off || | ||
2267 | orig_end > align_off + align_alen || | ||
2268 | align_alen - temp < orig_alen) | ||
2269 | return XFS_ERROR(EINVAL); | ||
2270 | /* | ||
2271 | * Try to fix it by moving the start up. | ||
2272 | */ | ||
2273 | if (align_off + temp <= orig_off) { | ||
2274 | align_alen -= temp; | ||
2275 | align_off += temp; | ||
2276 | } | ||
2277 | /* | ||
2278 | * Try to fix it by moving the end in. | ||
2279 | */ | ||
2280 | else if (align_off + align_alen - temp >= orig_end) | ||
2281 | align_alen -= temp; | ||
2282 | /* | ||
2283 | * Set the start to the minimum then trim the length. | ||
2284 | */ | ||
2285 | else { | ||
2286 | align_alen -= orig_off - align_off; | ||
2287 | align_off = orig_off; | ||
2288 | align_alen -= align_alen % mp->m_sb.sb_rextsize; | ||
2289 | } | ||
2290 | /* | ||
2291 | * Result doesn't cover the request, fail it. | ||
2292 | */ | ||
2293 | if (orig_off < align_off || orig_end > align_off + align_alen) | ||
2294 | return XFS_ERROR(EINVAL); | ||
2295 | } else { | ||
2296 | ASSERT(orig_off >= align_off); | ||
2297 | ASSERT(orig_end <= align_off + align_alen); | ||
2298 | } | ||
2299 | |||
2300 | #ifdef DEBUG | ||
2301 | if (!eof && gotp->br_startoff != NULLFILEOFF) | ||
2302 | ASSERT(align_off + align_alen <= gotp->br_startoff); | ||
2303 | if (prevp->br_startoff != NULLFILEOFF) | ||
2304 | ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount); | ||
2305 | #endif | ||
2306 | |||
2307 | *lenp = align_alen; | ||
2308 | *offp = align_off; | ||
2309 | return 0; | ||
2310 | } | ||
2311 | |||
2149 | #define XFS_ALLOC_GAP_UNITS 4 | 2312 | #define XFS_ALLOC_GAP_UNITS 4 |
2150 | 2313 | ||
2151 | /* | 2314 | /* |
2152 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. | 2315 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. |
2153 | * It figures out where to ask the underlying allocator to put the new extent. | 2316 | * It figures out where to ask the underlying allocator to put the new extent. |
2154 | */ | 2317 | */ |
2155 | STATIC int /* error */ | 2318 | STATIC int |
2156 | xfs_bmap_alloc( | 2319 | xfs_bmap_alloc( |
2157 | xfs_bmalloca_t *ap) /* bmap alloc argument struct */ | 2320 | xfs_bmalloca_t *ap) /* bmap alloc argument struct */ |
2158 | { | 2321 | { |
@@ -2163,10 +2326,10 @@ xfs_bmap_alloc( | |||
2163 | xfs_mount_t *mp; /* mount point structure */ | 2326 | xfs_mount_t *mp; /* mount point structure */ |
2164 | int nullfb; /* true if ap->firstblock isn't set */ | 2327 | int nullfb; /* true if ap->firstblock isn't set */ |
2165 | int rt; /* true if inode is realtime */ | 2328 | int rt; /* true if inode is realtime */ |
2166 | #ifdef __KERNEL__ | 2329 | xfs_extlen_t prod = 0; /* product factor for allocators */ |
2167 | xfs_extlen_t prod=0; /* product factor for allocators */ | 2330 | xfs_extlen_t ralen = 0; /* realtime allocation length */ |
2168 | xfs_extlen_t ralen=0; /* realtime allocation length */ | 2331 | xfs_extlen_t align; /* minimum allocation alignment */ |
2169 | #endif | 2332 | xfs_rtblock_t rtx; |
2170 | 2333 | ||
2171 | #define ISVALID(x,y) \ | 2334 | #define ISVALID(x,y) \ |
2172 | (rt ? \ | 2335 | (rt ? \ |
@@ -2182,125 +2345,25 @@ xfs_bmap_alloc( | |||
2182 | nullfb = ap->firstblock == NULLFSBLOCK; | 2345 | nullfb = ap->firstblock == NULLFSBLOCK; |
2183 | rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; | 2346 | rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; |
2184 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); | 2347 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); |
2185 | #ifdef __KERNEL__ | ||
2186 | if (rt) { | 2348 | if (rt) { |
2187 | xfs_extlen_t extsz; /* file extent size for rt */ | 2349 | align = ap->ip->i_d.di_extsize ? |
2188 | xfs_fileoff_t nexto; /* next file offset */ | 2350 | ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize; |
2189 | xfs_extlen_t orig_alen; /* original ap->alen */ | 2351 | /* Set prod to match the extent size */ |
2190 | xfs_fileoff_t orig_end; /* original off+len */ | 2352 | prod = align / mp->m_sb.sb_rextsize; |
2191 | xfs_fileoff_t orig_off; /* original ap->off */ | 2353 | |
2192 | xfs_extlen_t mod_off; /* modulus calculations */ | 2354 | error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, |
2193 | xfs_fileoff_t prevo; /* previous file offset */ | 2355 | align, rt, ap->eof, 0, |
2194 | xfs_rtblock_t rtx; /* realtime extent number */ | 2356 | ap->conv, &ap->off, &ap->alen); |
2195 | xfs_extlen_t temp; /* temp for rt calculations */ | 2357 | if (error) |
2196 | 2358 | return error; | |
2197 | /* | 2359 | ASSERT(ap->alen); |
2198 | * Set prod to match the realtime extent size. | ||
2199 | */ | ||
2200 | if (!(extsz = ap->ip->i_d.di_extsize)) | ||
2201 | extsz = mp->m_sb.sb_rextsize; | ||
2202 | prod = extsz / mp->m_sb.sb_rextsize; | ||
2203 | orig_off = ap->off; | ||
2204 | orig_alen = ap->alen; | ||
2205 | orig_end = orig_off + orig_alen; | ||
2206 | /* | ||
2207 | * If the file offset is unaligned vs. the extent size | ||
2208 | * we need to align it. This will be possible unless | ||
2209 | * the file was previously written with a kernel that didn't | ||
2210 | * perform this alignment. | ||
2211 | */ | ||
2212 | mod_off = do_mod(orig_off, extsz); | ||
2213 | if (mod_off) { | ||
2214 | ap->alen += mod_off; | ||
2215 | ap->off -= mod_off; | ||
2216 | } | ||
2217 | /* | ||
2218 | * Same adjustment for the end of the requested area. | ||
2219 | */ | ||
2220 | if ((temp = (ap->alen % extsz))) | ||
2221 | ap->alen += extsz - temp; | ||
2222 | /* | ||
2223 | * If the previous block overlaps with this proposed allocation | ||
2224 | * then move the start forward without adjusting the length. | ||
2225 | */ | ||
2226 | prevo = | ||
2227 | ap->prevp->br_startoff == NULLFILEOFF ? | ||
2228 | 0 : | ||
2229 | (ap->prevp->br_startoff + | ||
2230 | ap->prevp->br_blockcount); | ||
2231 | if (ap->off != orig_off && ap->off < prevo) | ||
2232 | ap->off = prevo; | ||
2233 | /* | ||
2234 | * If the next block overlaps with this proposed allocation | ||
2235 | * then move the start back without adjusting the length, | ||
2236 | * but not before offset 0. | ||
2237 | * This may of course make the start overlap previous block, | ||
2238 | * and if we hit the offset 0 limit then the next block | ||
2239 | * can still overlap too. | ||
2240 | */ | ||
2241 | nexto = (ap->eof || ap->gotp->br_startoff == NULLFILEOFF) ? | ||
2242 | NULLFILEOFF : ap->gotp->br_startoff; | ||
2243 | if (!ap->eof && | ||
2244 | ap->off + ap->alen != orig_end && | ||
2245 | ap->off + ap->alen > nexto) | ||
2246 | ap->off = nexto > ap->alen ? nexto - ap->alen : 0; | ||
2247 | /* | ||
2248 | * If we're now overlapping the next or previous extent that | ||
2249 | * means we can't fit an extsz piece in this hole. Just move | ||
2250 | * the start forward to the first valid spot and set | ||
2251 | * the length so we hit the end. | ||
2252 | */ | ||
2253 | if ((ap->off != orig_off && ap->off < prevo) || | ||
2254 | (ap->off + ap->alen != orig_end && | ||
2255 | ap->off + ap->alen > nexto)) { | ||
2256 | ap->off = prevo; | ||
2257 | ap->alen = nexto - prevo; | ||
2258 | } | ||
2259 | /* | ||
2260 | * If the result isn't a multiple of rtextents we need to | ||
2261 | * remove blocks until it is. | ||
2262 | */ | ||
2263 | if ((temp = (ap->alen % mp->m_sb.sb_rextsize))) { | ||
2264 | /* | ||
2265 | * We're not covering the original request, or | ||
2266 | * we won't be able to once we fix the length. | ||
2267 | */ | ||
2268 | if (orig_off < ap->off || | ||
2269 | orig_end > ap->off + ap->alen || | ||
2270 | ap->alen - temp < orig_alen) | ||
2271 | return XFS_ERROR(EINVAL); | ||
2272 | /* | ||
2273 | * Try to fix it by moving the start up. | ||
2274 | */ | ||
2275 | if (ap->off + temp <= orig_off) { | ||
2276 | ap->alen -= temp; | ||
2277 | ap->off += temp; | ||
2278 | } | ||
2279 | /* | ||
2280 | * Try to fix it by moving the end in. | ||
2281 | */ | ||
2282 | else if (ap->off + ap->alen - temp >= orig_end) | ||
2283 | ap->alen -= temp; | ||
2284 | /* | ||
2285 | * Set the start to the minimum then trim the length. | ||
2286 | */ | ||
2287 | else { | ||
2288 | ap->alen -= orig_off - ap->off; | ||
2289 | ap->off = orig_off; | ||
2290 | ap->alen -= ap->alen % mp->m_sb.sb_rextsize; | ||
2291 | } | ||
2292 | /* | ||
2293 | * Result doesn't cover the request, fail it. | ||
2294 | */ | ||
2295 | if (orig_off < ap->off || orig_end > ap->off + ap->alen) | ||
2296 | return XFS_ERROR(EINVAL); | ||
2297 | } | ||
2298 | ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0); | 2360 | ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0); |
2361 | |||
2299 | /* | 2362 | /* |
2300 | * If the offset & length are not perfectly aligned | 2363 | * If the offset & length are not perfectly aligned |
2301 | * then kill prod, it will just get us in trouble. | 2364 | * then kill prod, it will just get us in trouble. |
2302 | */ | 2365 | */ |
2303 | if (do_mod(ap->off, extsz) || ap->alen % extsz) | 2366 | if (do_mod(ap->off, align) || ap->alen % align) |
2304 | prod = 1; | 2367 | prod = 1; |
2305 | /* | 2368 | /* |
2306 | * Set ralen to be the actual requested length in rtextents. | 2369 | * Set ralen to be the actual requested length in rtextents. |
@@ -2326,15 +2389,24 @@ xfs_bmap_alloc( | |||
2326 | ap->rval = rtx * mp->m_sb.sb_rextsize; | 2389 | ap->rval = rtx * mp->m_sb.sb_rextsize; |
2327 | } else | 2390 | } else |
2328 | ap->rval = 0; | 2391 | ap->rval = 0; |
2392 | } else { | ||
2393 | align = (ap->userdata && ap->ip->i_d.di_extsize && | ||
2394 | (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ? | ||
2395 | ap->ip->i_d.di_extsize : 0; | ||
2396 | if (unlikely(align)) { | ||
2397 | error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, | ||
2398 | align, rt, | ||
2399 | ap->eof, 0, ap->conv, | ||
2400 | &ap->off, &ap->alen); | ||
2401 | ASSERT(!error); | ||
2402 | ASSERT(ap->alen); | ||
2403 | } | ||
2404 | if (nullfb) | ||
2405 | ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); | ||
2406 | else | ||
2407 | ap->rval = ap->firstblock; | ||
2329 | } | 2408 | } |
2330 | #else | 2409 | |
2331 | if (rt) | ||
2332 | ap->rval = 0; | ||
2333 | #endif /* __KERNEL__ */ | ||
2334 | else if (nullfb) | ||
2335 | ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); | ||
2336 | else | ||
2337 | ap->rval = ap->firstblock; | ||
2338 | /* | 2410 | /* |
2339 | * If allocating at eof, and there's a previous real block, | 2411 | * If allocating at eof, and there's a previous real block, |
2340 | * try to use it's last block as our starting point. | 2412 | * try to use it's last block as our starting point. |
@@ -2598,11 +2670,12 @@ xfs_bmap_alloc( | |||
2598 | args.total = ap->total; | 2670 | args.total = ap->total; |
2599 | args.minlen = ap->minlen; | 2671 | args.minlen = ap->minlen; |
2600 | } | 2672 | } |
2601 | if (ap->ip->i_d.di_extsize) { | 2673 | if (unlikely(ap->userdata && ap->ip->i_d.di_extsize && |
2674 | (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) { | ||
2602 | args.prod = ap->ip->i_d.di_extsize; | 2675 | args.prod = ap->ip->i_d.di_extsize; |
2603 | if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) | 2676 | if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) |
2604 | args.mod = (xfs_extlen_t)(args.prod - args.mod); | 2677 | args.mod = (xfs_extlen_t)(args.prod - args.mod); |
2605 | } else if (mp->m_sb.sb_blocksize >= NBPP) { | 2678 | } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) { |
2606 | args.prod = 1; | 2679 | args.prod = 1; |
2607 | args.mod = 0; | 2680 | args.mod = 0; |
2608 | } else { | 2681 | } else { |
@@ -4590,6 +4663,7 @@ xfs_bmapi( | |||
4590 | char contig; /* allocation must be one extent */ | 4663 | char contig; /* allocation must be one extent */ |
4591 | char delay; /* this request is for delayed alloc */ | 4664 | char delay; /* this request is for delayed alloc */ |
4592 | char exact; /* don't do all of wasdelayed extent */ | 4665 | char exact; /* don't do all of wasdelayed extent */ |
4666 | char convert; /* unwritten extent I/O completion */ | ||
4593 | xfs_bmbt_rec_t *ep; /* extent list entry pointer */ | 4667 | xfs_bmbt_rec_t *ep; /* extent list entry pointer */ |
4594 | int error; /* error return */ | 4668 | int error; /* error return */ |
4595 | xfs_bmbt_irec_t got; /* current extent list record */ | 4669 | xfs_bmbt_irec_t got; /* current extent list record */ |
@@ -4643,7 +4717,7 @@ xfs_bmapi( | |||
4643 | } | 4717 | } |
4644 | if (XFS_FORCED_SHUTDOWN(mp)) | 4718 | if (XFS_FORCED_SHUTDOWN(mp)) |
4645 | return XFS_ERROR(EIO); | 4719 | return XFS_ERROR(EIO); |
4646 | rt = XFS_IS_REALTIME_INODE(ip); | 4720 | rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); |
4647 | ifp = XFS_IFORK_PTR(ip, whichfork); | 4721 | ifp = XFS_IFORK_PTR(ip, whichfork); |
4648 | ASSERT(ifp->if_ext_max == | 4722 | ASSERT(ifp->if_ext_max == |
4649 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | 4723 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); |
@@ -4654,6 +4728,7 @@ xfs_bmapi( | |||
4654 | delay = (flags & XFS_BMAPI_DELAY) != 0; | 4728 | delay = (flags & XFS_BMAPI_DELAY) != 0; |
4655 | trim = (flags & XFS_BMAPI_ENTIRE) == 0; | 4729 | trim = (flags & XFS_BMAPI_ENTIRE) == 0; |
4656 | userdata = (flags & XFS_BMAPI_METADATA) == 0; | 4730 | userdata = (flags & XFS_BMAPI_METADATA) == 0; |
4731 | convert = (flags & XFS_BMAPI_CONVERT) != 0; | ||
4657 | exact = (flags & XFS_BMAPI_EXACT) != 0; | 4732 | exact = (flags & XFS_BMAPI_EXACT) != 0; |
4658 | rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0; | 4733 | rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0; |
4659 | contig = (flags & XFS_BMAPI_CONTIG) != 0; | 4734 | contig = (flags & XFS_BMAPI_CONTIG) != 0; |
@@ -4748,16 +4823,26 @@ xfs_bmapi( | |||
4748 | } | 4823 | } |
4749 | minlen = contig ? alen : 1; | 4824 | minlen = contig ? alen : 1; |
4750 | if (delay) { | 4825 | if (delay) { |
4751 | xfs_extlen_t extsz = 0; | 4826 | xfs_extlen_t extsz; |
4752 | 4827 | ||
4753 | /* Figure out the extent size, adjust alen */ | 4828 | /* Figure out the extent size, adjust alen */ |
4754 | if (rt) { | 4829 | if (rt) { |
4755 | if (!(extsz = ip->i_d.di_extsize)) | 4830 | if (!(extsz = ip->i_d.di_extsize)) |
4756 | extsz = mp->m_sb.sb_rextsize; | 4831 | extsz = mp->m_sb.sb_rextsize; |
4757 | alen = roundup(alen, extsz); | 4832 | } else { |
4758 | extsz = alen / mp->m_sb.sb_rextsize; | 4833 | extsz = ip->i_d.di_extsize; |
4834 | } | ||
4835 | if (extsz) { | ||
4836 | error = xfs_bmap_extsize_align(mp, | ||
4837 | &got, &prev, extsz, | ||
4838 | rt, eof, delay, convert, | ||
4839 | &aoff, &alen); | ||
4840 | ASSERT(!error); | ||
4759 | } | 4841 | } |
4760 | 4842 | ||
4843 | if (rt) | ||
4844 | extsz = alen / mp->m_sb.sb_rextsize; | ||
4845 | |||
4761 | /* | 4846 | /* |
4762 | * Make a transaction-less quota reservation for | 4847 | * Make a transaction-less quota reservation for |
4763 | * delayed allocation blocks. This number gets | 4848 | * delayed allocation blocks. This number gets |
@@ -4785,14 +4870,15 @@ xfs_bmapi( | |||
4785 | xfs_bmap_worst_indlen(ip, alen); | 4870 | xfs_bmap_worst_indlen(ip, alen); |
4786 | ASSERT(indlen > 0); | 4871 | ASSERT(indlen > 0); |
4787 | 4872 | ||
4788 | if (rt) | 4873 | if (rt) { |
4789 | error = xfs_mod_incore_sb(mp, | 4874 | error = xfs_mod_incore_sb(mp, |
4790 | XFS_SBS_FREXTENTS, | 4875 | XFS_SBS_FREXTENTS, |
4791 | -(extsz), rsvd); | 4876 | -(extsz), rsvd); |
4792 | else | 4877 | } else { |
4793 | error = xfs_mod_incore_sb(mp, | 4878 | error = xfs_mod_incore_sb(mp, |
4794 | XFS_SBS_FDBLOCKS, | 4879 | XFS_SBS_FDBLOCKS, |
4795 | -(alen), rsvd); | 4880 | -(alen), rsvd); |
4881 | } | ||
4796 | if (!error) { | 4882 | if (!error) { |
4797 | error = xfs_mod_incore_sb(mp, | 4883 | error = xfs_mod_incore_sb(mp, |
4798 | XFS_SBS_FDBLOCKS, | 4884 | XFS_SBS_FDBLOCKS, |
@@ -4811,6 +4897,7 @@ xfs_bmapi( | |||
4811 | if (error) { | 4897 | if (error) { |
4812 | if (XFS_IS_QUOTA_ON(ip->i_mount)) | 4898 | if (XFS_IS_QUOTA_ON(ip->i_mount)) |
4813 | /* unreserve the blocks now */ | 4899 | /* unreserve the blocks now */ |
4900 | (void) | ||
4814 | XFS_TRANS_UNRESERVE_QUOTA_NBLKS( | 4901 | XFS_TRANS_UNRESERVE_QUOTA_NBLKS( |
4815 | mp, NULL, ip, | 4902 | mp, NULL, ip, |
4816 | (long)alen, 0, rt ? | 4903 | (long)alen, 0, rt ? |
@@ -4849,6 +4936,7 @@ xfs_bmapi( | |||
4849 | bma.firstblock = *firstblock; | 4936 | bma.firstblock = *firstblock; |
4850 | bma.alen = alen; | 4937 | bma.alen = alen; |
4851 | bma.off = aoff; | 4938 | bma.off = aoff; |
4939 | bma.conv = convert; | ||
4852 | bma.wasdel = wasdelay; | 4940 | bma.wasdel = wasdelay; |
4853 | bma.minlen = minlen; | 4941 | bma.minlen = minlen; |
4854 | bma.low = flist->xbf_low; | 4942 | bma.low = flist->xbf_low; |
@@ -5270,8 +5358,7 @@ xfs_bunmapi( | |||
5270 | return 0; | 5358 | return 0; |
5271 | } | 5359 | } |
5272 | XFS_STATS_INC(xs_blk_unmap); | 5360 | XFS_STATS_INC(xs_blk_unmap); |
5273 | isrt = (whichfork == XFS_DATA_FORK) && | 5361 | isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); |
5274 | (ip->i_d.di_flags & XFS_DIFLAG_REALTIME); | ||
5275 | start = bno; | 5362 | start = bno; |
5276 | bno = start + len - 1; | 5363 | bno = start + len - 1; |
5277 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, | 5364 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, |
@@ -5443,7 +5530,7 @@ xfs_bunmapi( | |||
5443 | } | 5530 | } |
5444 | if (wasdel) { | 5531 | if (wasdel) { |
5445 | ASSERT(STARTBLOCKVAL(del.br_startblock) > 0); | 5532 | ASSERT(STARTBLOCKVAL(del.br_startblock) > 0); |
5446 | /* Update realtim/data freespace, unreserve quota */ | 5533 | /* Update realtime/data freespace, unreserve quota */ |
5447 | if (isrt) { | 5534 | if (isrt) { |
5448 | xfs_filblks_t rtexts; | 5535 | xfs_filblks_t rtexts; |
5449 | 5536 | ||
@@ -5451,14 +5538,14 @@ xfs_bunmapi( | |||
5451 | do_div(rtexts, mp->m_sb.sb_rextsize); | 5538 | do_div(rtexts, mp->m_sb.sb_rextsize); |
5452 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, | 5539 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, |
5453 | (int)rtexts, rsvd); | 5540 | (int)rtexts, rsvd); |
5454 | XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip, | 5541 | (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, |
5455 | -((long)del.br_blockcount), 0, | 5542 | NULL, ip, -((long)del.br_blockcount), 0, |
5456 | XFS_QMOPT_RES_RTBLKS); | 5543 | XFS_QMOPT_RES_RTBLKS); |
5457 | } else { | 5544 | } else { |
5458 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, | 5545 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, |
5459 | (int)del.br_blockcount, rsvd); | 5546 | (int)del.br_blockcount, rsvd); |
5460 | XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip, | 5547 | (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, |
5461 | -((long)del.br_blockcount), 0, | 5548 | NULL, ip, -((long)del.br_blockcount), 0, |
5462 | XFS_QMOPT_RES_REGBLKS); | 5549 | XFS_QMOPT_RES_REGBLKS); |
5463 | } | 5550 | } |
5464 | ip->i_delayed_blks -= del.br_blockcount; | 5551 | ip->i_delayed_blks -= del.br_blockcount; |
@@ -5652,7 +5739,9 @@ xfs_getbmap( | |||
5652 | ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) | 5739 | ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) |
5653 | return XFS_ERROR(EINVAL); | 5740 | return XFS_ERROR(EINVAL); |
5654 | if (whichfork == XFS_DATA_FORK) { | 5741 | if (whichfork == XFS_DATA_FORK) { |
5655 | if (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) { | 5742 | if ((ip->i_d.di_extsize && (ip->i_d.di_flags & |
5743 | (XFS_DIFLAG_REALTIME|XFS_DIFLAG_EXTSIZE))) || | ||
5744 | ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){ | ||
5656 | prealloced = 1; | 5745 | prealloced = 1; |
5657 | fixlen = XFS_MAXIOFFSET(mp); | 5746 | fixlen = XFS_MAXIOFFSET(mp); |
5658 | } else { | 5747 | } else { |