diff options
-rw-r--r-- | fs/xfs/xfs_bmap.c | 373 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap.h | 7 | ||||
-rw-r--r-- | fs/xfs/xfs_dinode.h | 11 | ||||
-rw-r--r-- | fs/xfs/xfs_fs.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 16 | ||||
-rw-r--r-- | fs/xfs/xfs_iomap.c | 390 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 158 |
7 files changed, 547 insertions, 410 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 { |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 2e0717a01309..12cc63dfc2c4 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -62,6 +62,10 @@ typedef struct xfs_bmap_free | |||
62 | #define XFS_BMAPI_IGSTATE 0x200 /* Ignore state - */ | 62 | #define XFS_BMAPI_IGSTATE 0x200 /* Ignore state - */ |
63 | /* combine contig. space */ | 63 | /* combine contig. space */ |
64 | #define XFS_BMAPI_CONTIG 0x400 /* must allocate only one extent */ | 64 | #define XFS_BMAPI_CONTIG 0x400 /* must allocate only one extent */ |
65 | /* XFS_BMAPI_DIRECT_IO 0x800 */ | ||
66 | #define XFS_BMAPI_CONVERT 0x1000 /* unwritten extent conversion - */ | ||
67 | /* need write cache flushing and no */ | ||
68 | /* additional allocation alignments */ | ||
65 | 69 | ||
66 | #define XFS_BMAPI_AFLAG(w) xfs_bmapi_aflag(w) | 70 | #define XFS_BMAPI_AFLAG(w) xfs_bmapi_aflag(w) |
67 | static inline int xfs_bmapi_aflag(int w) | 71 | static inline int xfs_bmapi_aflag(int w) |
@@ -101,7 +105,8 @@ typedef struct xfs_bmalloca { | |||
101 | char wasdel; /* replacing a delayed allocation */ | 105 | char wasdel; /* replacing a delayed allocation */ |
102 | char userdata;/* set if is user data */ | 106 | char userdata;/* set if is user data */ |
103 | char low; /* low on space, using seq'l ags */ | 107 | char low; /* low on space, using seq'l ags */ |
104 | char aeof; /* allocated space at eof */ | 108 | char aeof; /* allocated space at eof */ |
109 | char conv; /* overwriting unwritten extents */ | ||
105 | } xfs_bmalloca_t; | 110 | } xfs_bmalloca_t; |
106 | 111 | ||
107 | #ifdef __KERNEL__ | 112 | #ifdef __KERNEL__ |
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index c5a0e537ff1a..f697aab8a3d2 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h | |||
@@ -246,8 +246,10 @@ typedef enum xfs_dinode_fmt | |||
246 | #define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */ | 246 | #define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */ |
247 | #define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */ | 247 | #define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */ |
248 | #define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */ | 248 | #define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */ |
249 | #define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */ | 249 | #define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */ |
250 | #define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ | 250 | #define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ |
251 | #define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ | ||
252 | #define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ | ||
251 | #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) | 253 | #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) |
252 | #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) | 254 | #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) |
253 | #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) | 255 | #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) |
@@ -259,11 +261,14 @@ typedef enum xfs_dinode_fmt | |||
259 | #define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT) | 261 | #define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT) |
260 | #define XFS_DIFLAG_PROJINHERIT (1 << XFS_DIFLAG_PROJINHERIT_BIT) | 262 | #define XFS_DIFLAG_PROJINHERIT (1 << XFS_DIFLAG_PROJINHERIT_BIT) |
261 | #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) | 263 | #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) |
264 | #define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) | ||
265 | #define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) | ||
262 | 266 | ||
263 | #define XFS_DIFLAG_ANY \ | 267 | #define XFS_DIFLAG_ANY \ |
264 | (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ | 268 | (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ |
265 | XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ | 269 | XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ |
266 | XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ | 270 | XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ |
267 | XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS) | 271 | XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ |
272 | XFS_DIFLAG_EXTSZINHERIT) | ||
268 | 273 | ||
269 | #endif /* __XFS_DINODE_H__ */ | 274 | #endif /* __XFS_DINODE_H__ */ |
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index ba096f80f48d..3280f49496ba 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h | |||
@@ -65,6 +65,8 @@ struct fsxattr { | |||
65 | #define XFS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ | 65 | #define XFS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */ |
66 | #define XFS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ | 66 | #define XFS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ |
67 | #define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ | 67 | #define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ |
68 | #define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ | ||
69 | #define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ | ||
68 | #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ | 70 | #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ |
69 | 71 | ||
70 | /* | 72 | /* |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index df0d4572d70a..e486c7d244c2 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -809,6 +809,10 @@ _xfs_dic2xflags( | |||
809 | flags |= XFS_XFLAG_PROJINHERIT; | 809 | flags |= XFS_XFLAG_PROJINHERIT; |
810 | if (di_flags & XFS_DIFLAG_NOSYMLINKS) | 810 | if (di_flags & XFS_DIFLAG_NOSYMLINKS) |
811 | flags |= XFS_XFLAG_NOSYMLINKS; | 811 | flags |= XFS_XFLAG_NOSYMLINKS; |
812 | if (di_flags & XFS_DIFLAG_EXTSIZE) | ||
813 | flags |= XFS_XFLAG_EXTSIZE; | ||
814 | if (di_flags & XFS_DIFLAG_EXTSZINHERIT) | ||
815 | flags |= XFS_XFLAG_EXTSZINHERIT; | ||
812 | } | 816 | } |
813 | 817 | ||
814 | return flags; | 818 | return flags; |
@@ -1192,11 +1196,19 @@ xfs_ialloc( | |||
1192 | if ((mode & S_IFMT) == S_IFDIR) { | 1196 | if ((mode & S_IFMT) == S_IFDIR) { |
1193 | if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) | 1197 | if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) |
1194 | di_flags |= XFS_DIFLAG_RTINHERIT; | 1198 | di_flags |= XFS_DIFLAG_RTINHERIT; |
1195 | } else { | 1199 | if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { |
1200 | di_flags |= XFS_DIFLAG_EXTSZINHERIT; | ||
1201 | ip->i_d.di_extsize = pip->i_d.di_extsize; | ||
1202 | } | ||
1203 | } else if ((mode & S_IFMT) == S_IFREG) { | ||
1196 | if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) { | 1204 | if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) { |
1197 | di_flags |= XFS_DIFLAG_REALTIME; | 1205 | di_flags |= XFS_DIFLAG_REALTIME; |
1198 | ip->i_iocore.io_flags |= XFS_IOCORE_RT; | 1206 | ip->i_iocore.io_flags |= XFS_IOCORE_RT; |
1199 | } | 1207 | } |
1208 | if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) { | ||
1209 | di_flags |= XFS_DIFLAG_EXTSIZE; | ||
1210 | ip->i_d.di_extsize = pip->i_d.di_extsize; | ||
1211 | } | ||
1200 | } | 1212 | } |
1201 | if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) && | 1213 | if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) && |
1202 | xfs_inherit_noatime) | 1214 | xfs_inherit_noatime) |
@@ -1262,7 +1274,7 @@ xfs_isize_check( | |||
1262 | if ((ip->i_d.di_mode & S_IFMT) != S_IFREG) | 1274 | if ((ip->i_d.di_mode & S_IFMT) != S_IFREG) |
1263 | return; | 1275 | return; |
1264 | 1276 | ||
1265 | if ( ip->i_d.di_flags & XFS_DIFLAG_REALTIME ) | 1277 | if (ip->i_d.di_flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_EXTSIZE)) |
1266 | return; | 1278 | return; |
1267 | 1279 | ||
1268 | nimaps = 2; | 1280 | nimaps = 2; |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 45a77a3a6c07..5ecf3e3e86aa 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -263,7 +263,7 @@ phase2: | |||
263 | case BMAPI_WRITE: | 263 | case BMAPI_WRITE: |
264 | /* If we found an extent, return it */ | 264 | /* If we found an extent, return it */ |
265 | if (nimaps && | 265 | if (nimaps && |
266 | (imap.br_startblock != HOLESTARTBLOCK) && | 266 | (imap.br_startblock != HOLESTARTBLOCK) && |
267 | (imap.br_startblock != DELAYSTARTBLOCK)) { | 267 | (imap.br_startblock != DELAYSTARTBLOCK)) { |
268 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, | 268 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, |
269 | offset, count, iomapp, &imap, flags); | 269 | offset, count, iomapp, &imap, flags); |
@@ -318,6 +318,58 @@ out: | |||
318 | } | 318 | } |
319 | 319 | ||
320 | STATIC int | 320 | STATIC int |
321 | xfs_iomap_eof_align_last_fsb( | ||
322 | xfs_mount_t *mp, | ||
323 | xfs_iocore_t *io, | ||
324 | xfs_fsize_t isize, | ||
325 | xfs_extlen_t extsize, | ||
326 | xfs_fileoff_t *last_fsb) | ||
327 | { | ||
328 | xfs_fileoff_t new_last_fsb = 0; | ||
329 | xfs_extlen_t align; | ||
330 | int eof, error; | ||
331 | |||
332 | if (io->io_flags & XFS_IOCORE_RT) | ||
333 | ; | ||
334 | /* | ||
335 | * If mounted with the "-o swalloc" option, roundup the allocation | ||
336 | * request to a stripe width boundary if the file size is >= | ||
337 | * stripe width and we are allocating past the allocation eof. | ||
338 | */ | ||
339 | else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) && | ||
340 | (isize >= XFS_FSB_TO_B(mp, mp->m_swidth))) | ||
341 | new_last_fsb = roundup_64(*last_fsb, mp->m_swidth); | ||
342 | /* | ||
343 | * Roundup the allocation request to a stripe unit (m_dalign) boundary | ||
344 | * if the file size is >= stripe unit size, and we are allocating past | ||
345 | * the allocation eof. | ||
346 | */ | ||
347 | else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign))) | ||
348 | new_last_fsb = roundup_64(*last_fsb, mp->m_dalign); | ||
349 | |||
350 | /* | ||
351 | * Always round up the allocation request to an extent boundary | ||
352 | * (when file on a real-time subvolume or has di_extsize hint). | ||
353 | */ | ||
354 | if (extsize) { | ||
355 | if (new_last_fsb) | ||
356 | align = roundup_64(new_last_fsb, extsize); | ||
357 | else | ||
358 | align = extsize; | ||
359 | new_last_fsb = roundup_64(*last_fsb, align); | ||
360 | } | ||
361 | |||
362 | if (new_last_fsb) { | ||
363 | error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); | ||
364 | if (error) | ||
365 | return error; | ||
366 | if (eof) | ||
367 | *last_fsb = new_last_fsb; | ||
368 | } | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | STATIC int | ||
321 | xfs_flush_space( | 373 | xfs_flush_space( |
322 | xfs_inode_t *ip, | 374 | xfs_inode_t *ip, |
323 | int *fsynced, | 375 | int *fsynced, |
@@ -363,19 +415,20 @@ xfs_iomap_write_direct( | |||
363 | xfs_iocore_t *io = &ip->i_iocore; | 415 | xfs_iocore_t *io = &ip->i_iocore; |
364 | xfs_fileoff_t offset_fsb; | 416 | xfs_fileoff_t offset_fsb; |
365 | xfs_fileoff_t last_fsb; | 417 | xfs_fileoff_t last_fsb; |
366 | xfs_filblks_t count_fsb; | 418 | xfs_filblks_t count_fsb, resaligned; |
367 | xfs_fsblock_t firstfsb; | 419 | xfs_fsblock_t firstfsb; |
420 | xfs_extlen_t extsz, temp; | ||
421 | xfs_fsize_t isize; | ||
368 | int nimaps; | 422 | int nimaps; |
369 | int error; | ||
370 | int bmapi_flag; | 423 | int bmapi_flag; |
371 | int quota_flag; | 424 | int quota_flag; |
372 | int rt; | 425 | int rt; |
373 | xfs_trans_t *tp; | 426 | xfs_trans_t *tp; |
374 | xfs_bmbt_irec_t imap; | 427 | xfs_bmbt_irec_t imap; |
375 | xfs_bmap_free_t free_list; | 428 | xfs_bmap_free_t free_list; |
376 | xfs_filblks_t qblocks, resblks; | 429 | uint qblocks, resblks, resrtextents; |
377 | int committed; | 430 | int committed; |
378 | int resrtextents; | 431 | int error; |
379 | 432 | ||
380 | /* | 433 | /* |
381 | * Make sure that the dquots are there. This doesn't hold | 434 | * Make sure that the dquots are there. This doesn't hold |
@@ -385,37 +438,52 @@ xfs_iomap_write_direct( | |||
385 | if (error) | 438 | if (error) |
386 | return XFS_ERROR(error); | 439 | return XFS_ERROR(error); |
387 | 440 | ||
388 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 441 | rt = XFS_IS_REALTIME_INODE(ip); |
389 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | 442 | if (unlikely(rt)) { |
390 | count_fsb = last_fsb - offset_fsb; | 443 | if (!(extsz = ip->i_d.di_extsize)) |
391 | if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) { | 444 | extsz = mp->m_sb.sb_rextsize; |
392 | xfs_fileoff_t map_last_fsb; | 445 | } else { |
393 | 446 | extsz = ip->i_d.di_extsize; | |
394 | map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; | ||
395 | if (map_last_fsb < last_fsb) { | ||
396 | last_fsb = map_last_fsb; | ||
397 | count_fsb = last_fsb - offset_fsb; | ||
398 | } | ||
399 | ASSERT(count_fsb > 0); | ||
400 | } | 447 | } |
401 | 448 | ||
402 | /* | 449 | isize = ip->i_d.di_size; |
403 | * Determine if reserving space on the data or realtime partition. | 450 | if (io->io_new_size > isize) |
404 | */ | 451 | isize = io->io_new_size; |
405 | if ((rt = XFS_IS_REALTIME_INODE(ip))) { | ||
406 | xfs_extlen_t extsz; | ||
407 | 452 | ||
408 | if (!(extsz = ip->i_d.di_extsize)) | 453 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
409 | extsz = mp->m_sb.sb_rextsize; | 454 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); |
410 | resrtextents = qblocks = (count_fsb + extsz - 1); | 455 | if ((offset + count) > isize) { |
411 | do_div(resrtextents, mp->m_sb.sb_rextsize); | 456 | error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, |
412 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); | 457 | &last_fsb); |
413 | quota_flag = XFS_QMOPT_RES_RTBLKS; | 458 | if (error) |
459 | goto error_out; | ||
414 | } else { | 460 | } else { |
415 | resrtextents = 0; | 461 | if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) |
416 | resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, count_fsb); | 462 | last_fsb = MIN(last_fsb, (xfs_fileoff_t) |
417 | quota_flag = XFS_QMOPT_RES_REGBLKS; | 463 | ret_imap->br_blockcount + |
464 | ret_imap->br_startoff); | ||
418 | } | 465 | } |
466 | count_fsb = last_fsb - offset_fsb; | ||
467 | ASSERT(count_fsb > 0); | ||
468 | |||
469 | resaligned = count_fsb; | ||
470 | if (unlikely(extsz)) { | ||
471 | if ((temp = do_mod(offset_fsb, extsz))) | ||
472 | resaligned += temp; | ||
473 | if ((temp = do_mod(resaligned, extsz))) | ||
474 | resaligned += extsz - temp; | ||
475 | } | ||
476 | |||
477 | if (unlikely(rt)) { | ||
478 | resrtextents = qblocks = resaligned; | ||
479 | resrtextents /= mp->m_sb.sb_rextsize; | ||
480 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); | ||
481 | quota_flag = XFS_QMOPT_RES_RTBLKS; | ||
482 | } else { | ||
483 | resrtextents = 0; | ||
484 | resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned); | ||
485 | quota_flag = XFS_QMOPT_RES_REGBLKS; | ||
486 | } | ||
419 | 487 | ||
420 | /* | 488 | /* |
421 | * Allocate and setup the transaction | 489 | * Allocate and setup the transaction |
@@ -426,7 +494,6 @@ xfs_iomap_write_direct( | |||
426 | XFS_WRITE_LOG_RES(mp), resrtextents, | 494 | XFS_WRITE_LOG_RES(mp), resrtextents, |
427 | XFS_TRANS_PERM_LOG_RES, | 495 | XFS_TRANS_PERM_LOG_RES, |
428 | XFS_WRITE_LOG_COUNT); | 496 | XFS_WRITE_LOG_COUNT); |
429 | |||
430 | /* | 497 | /* |
431 | * Check for running out of space, note: need lock to return | 498 | * Check for running out of space, note: need lock to return |
432 | */ | 499 | */ |
@@ -436,20 +503,20 @@ xfs_iomap_write_direct( | |||
436 | if (error) | 503 | if (error) |
437 | goto error_out; | 504 | goto error_out; |
438 | 505 | ||
439 | if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) { | 506 | error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, |
440 | error = (EDQUOT); | 507 | qblocks, 0, quota_flag); |
508 | if (error) | ||
441 | goto error1; | 509 | goto error1; |
442 | } | ||
443 | 510 | ||
444 | bmapi_flag = XFS_BMAPI_WRITE; | ||
445 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 511 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
446 | xfs_trans_ihold(tp, ip); | 512 | xfs_trans_ihold(tp, ip); |
447 | 513 | ||
448 | if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt)) | 514 | bmapi_flag = XFS_BMAPI_WRITE; |
515 | if ((flags & BMAPI_DIRECT) && (offset < ip->i_d.di_size || extsz)) | ||
449 | bmapi_flag |= XFS_BMAPI_PREALLOC; | 516 | bmapi_flag |= XFS_BMAPI_PREALLOC; |
450 | 517 | ||
451 | /* | 518 | /* |
452 | * Issue the bmapi() call to allocate the blocks | 519 | * Issue the xfs_bmapi() call to allocate the blocks |
453 | */ | 520 | */ |
454 | XFS_BMAP_INIT(&free_list, &firstfsb); | 521 | XFS_BMAP_INIT(&free_list, &firstfsb); |
455 | nimaps = 1; | 522 | nimaps = 1; |
@@ -501,6 +568,62 @@ error_out: | |||
501 | return XFS_ERROR(error); | 568 | return XFS_ERROR(error); |
502 | } | 569 | } |
503 | 570 | ||
571 | /* | ||
572 | * If the caller is doing a write at the end of the file, | ||
573 | * then extend the allocation out to the file system's write | ||
574 | * iosize. We clean up any extra space left over when the | ||
575 | * file is closed in xfs_inactive(). | ||
576 | * | ||
577 | * For sync writes, we are flushing delayed allocate space to | ||
578 | * try to make additional space available for allocation near | ||
579 | * the filesystem full boundary - preallocation hurts in that | ||
580 | * situation, of course. | ||
581 | */ | ||
582 | STATIC int | ||
583 | xfs_iomap_eof_want_preallocate( | ||
584 | xfs_mount_t *mp, | ||
585 | xfs_iocore_t *io, | ||
586 | xfs_fsize_t isize, | ||
587 | xfs_off_t offset, | ||
588 | size_t count, | ||
589 | int ioflag, | ||
590 | xfs_bmbt_irec_t *imap, | ||
591 | int nimaps, | ||
592 | int *prealloc) | ||
593 | { | ||
594 | xfs_fileoff_t start_fsb; | ||
595 | xfs_filblks_t count_fsb; | ||
596 | xfs_fsblock_t firstblock; | ||
597 | int n, error, imaps; | ||
598 | |||
599 | *prealloc = 0; | ||
600 | if ((ioflag & BMAPI_SYNC) || (offset + count) <= isize) | ||
601 | return 0; | ||
602 | |||
603 | /* | ||
604 | * If there are any real blocks past eof, then don't | ||
605 | * do any speculative allocation. | ||
606 | */ | ||
607 | start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1))); | ||
608 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); | ||
609 | while (count_fsb > 0) { | ||
610 | imaps = nimaps; | ||
611 | error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, | ||
612 | 0, &firstblock, 0, imap, &imaps, NULL); | ||
613 | if (error) | ||
614 | return error; | ||
615 | for (n = 0; n < imaps; n++) { | ||
616 | if ((imap[n].br_startblock != HOLESTARTBLOCK) && | ||
617 | (imap[n].br_startblock != DELAYSTARTBLOCK)) | ||
618 | return 0; | ||
619 | start_fsb += imap[n].br_blockcount; | ||
620 | count_fsb -= imap[n].br_blockcount; | ||
621 | } | ||
622 | } | ||
623 | *prealloc = 1; | ||
624 | return 0; | ||
625 | } | ||
626 | |||
504 | int | 627 | int |
505 | xfs_iomap_write_delay( | 628 | xfs_iomap_write_delay( |
506 | xfs_inode_t *ip, | 629 | xfs_inode_t *ip, |
@@ -514,13 +637,15 @@ xfs_iomap_write_delay( | |||
514 | xfs_iocore_t *io = &ip->i_iocore; | 637 | xfs_iocore_t *io = &ip->i_iocore; |
515 | xfs_fileoff_t offset_fsb; | 638 | xfs_fileoff_t offset_fsb; |
516 | xfs_fileoff_t last_fsb; | 639 | xfs_fileoff_t last_fsb; |
517 | xfs_fsize_t isize; | 640 | xfs_off_t aligned_offset; |
641 | xfs_fileoff_t ioalign; | ||
518 | xfs_fsblock_t firstblock; | 642 | xfs_fsblock_t firstblock; |
643 | xfs_extlen_t extsz; | ||
644 | xfs_fsize_t isize; | ||
519 | int nimaps; | 645 | int nimaps; |
520 | int error; | ||
521 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; | 646 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; |
522 | int aeof; | 647 | int prealloc, fsynced = 0; |
523 | int fsynced = 0; | 648 | int error; |
524 | 649 | ||
525 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); | 650 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0); |
526 | 651 | ||
@@ -528,152 +653,57 @@ xfs_iomap_write_delay( | |||
528 | * Make sure that the dquots are there. This doesn't hold | 653 | * Make sure that the dquots are there. This doesn't hold |
529 | * the ilock across a disk read. | 654 | * the ilock across a disk read. |
530 | */ | 655 | */ |
531 | |||
532 | error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); | 656 | error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED); |
533 | if (error) | 657 | if (error) |
534 | return XFS_ERROR(error); | 658 | return XFS_ERROR(error); |
535 | 659 | ||
660 | if (XFS_IS_REALTIME_INODE(ip)) { | ||
661 | if (!(extsz = ip->i_d.di_extsize)) | ||
662 | extsz = mp->m_sb.sb_rextsize; | ||
663 | } else { | ||
664 | extsz = ip->i_d.di_extsize; | ||
665 | } | ||
666 | |||
667 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
668 | |||
536 | retry: | 669 | retry: |
537 | isize = ip->i_d.di_size; | 670 | isize = ip->i_d.di_size; |
538 | if (io->io_new_size > isize) { | 671 | if (io->io_new_size > isize) |
539 | isize = io->io_new_size; | 672 | isize = io->io_new_size; |
540 | } | ||
541 | 673 | ||
542 | aeof = 0; | 674 | error = xfs_iomap_eof_want_preallocate(mp, io, isize, offset, count, |
543 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 675 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); |
544 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | 676 | if (error) |
545 | /* | 677 | return error; |
546 | * If the caller is doing a write at the end of the file, | ||
547 | * then extend the allocation (and the buffer used for the write) | ||
548 | * out to the file system's write iosize. We clean up any extra | ||
549 | * space left over when the file is closed in xfs_inactive(). | ||
550 | * | ||
551 | * For sync writes, we are flushing delayed allocate space to | ||
552 | * try to make additional space available for allocation near | ||
553 | * the filesystem full boundary - preallocation hurts in that | ||
554 | * situation, of course. | ||
555 | */ | ||
556 | if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { | ||
557 | xfs_off_t aligned_offset; | ||
558 | xfs_filblks_t count_fsb; | ||
559 | unsigned int iosize; | ||
560 | xfs_fileoff_t ioalign; | ||
561 | int n; | ||
562 | xfs_fileoff_t start_fsb; | ||
563 | 678 | ||
564 | /* | 679 | if (prealloc) { |
565 | * If there are any real blocks past eof, then don't | ||
566 | * do any speculative allocation. | ||
567 | */ | ||
568 | start_fsb = XFS_B_TO_FSBT(mp, | ||
569 | ((xfs_ufsize_t)(offset + count - 1))); | ||
570 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); | ||
571 | while (count_fsb > 0) { | ||
572 | nimaps = XFS_WRITE_IMAPS; | ||
573 | error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, | ||
574 | 0, &firstblock, 0, imap, &nimaps, NULL); | ||
575 | if (error) { | ||
576 | return error; | ||
577 | } | ||
578 | for (n = 0; n < nimaps; n++) { | ||
579 | if ( !(io->io_flags & XFS_IOCORE_RT) && | ||
580 | !imap[n].br_startblock) { | ||
581 | cmn_err(CE_PANIC,"Access to block " | ||
582 | "zero: fs <%s> inode: %lld " | ||
583 | "start_block : %llx start_off " | ||
584 | ": %llx blkcnt : %llx " | ||
585 | "extent-state : %x \n", | ||
586 | (ip->i_mount)->m_fsname, | ||
587 | (long long)ip->i_ino, | ||
588 | imap[n].br_startblock, | ||
589 | imap[n].br_startoff, | ||
590 | imap[n].br_blockcount, | ||
591 | imap[n].br_state); | ||
592 | } | ||
593 | if ((imap[n].br_startblock != HOLESTARTBLOCK) && | ||
594 | (imap[n].br_startblock != DELAYSTARTBLOCK)) { | ||
595 | goto write_map; | ||
596 | } | ||
597 | start_fsb += imap[n].br_blockcount; | ||
598 | count_fsb -= imap[n].br_blockcount; | ||
599 | } | ||
600 | } | ||
601 | iosize = mp->m_writeio_blocks; | ||
602 | aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); | 680 | aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); |
603 | ioalign = XFS_B_TO_FSBT(mp, aligned_offset); | 681 | ioalign = XFS_B_TO_FSBT(mp, aligned_offset); |
604 | last_fsb = ioalign + iosize; | 682 | last_fsb = ioalign + mp->m_writeio_blocks; |
605 | aeof = 1; | 683 | } else { |
684 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | ||
606 | } | 685 | } |
607 | write_map: | ||
608 | nimaps = XFS_WRITE_IMAPS; | ||
609 | firstblock = NULLFSBLOCK; | ||
610 | 686 | ||
611 | /* | 687 | if (prealloc || extsz) { |
612 | * If mounted with the "-o swalloc" option, roundup the allocation | 688 | error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, |
613 | * request to a stripe width boundary if the file size is >= | 689 | &last_fsb); |
614 | * stripe width and we are allocating past the allocation eof. | 690 | if (error) |
615 | */ | ||
616 | if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth | ||
617 | && (mp->m_flags & XFS_MOUNT_SWALLOC) | ||
618 | && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) { | ||
619 | int eof; | ||
620 | xfs_fileoff_t new_last_fsb; | ||
621 | |||
622 | new_last_fsb = roundup_64(last_fsb, mp->m_swidth); | ||
623 | error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); | ||
624 | if (error) { | ||
625 | return error; | ||
626 | } | ||
627 | if (eof) { | ||
628 | last_fsb = new_last_fsb; | ||
629 | } | ||
630 | /* | ||
631 | * Roundup the allocation request to a stripe unit (m_dalign) boundary | ||
632 | * if the file size is >= stripe unit size, and we are allocating past | ||
633 | * the allocation eof. | ||
634 | */ | ||
635 | } else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign && | ||
636 | (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) { | ||
637 | int eof; | ||
638 | xfs_fileoff_t new_last_fsb; | ||
639 | new_last_fsb = roundup_64(last_fsb, mp->m_dalign); | ||
640 | error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); | ||
641 | if (error) { | ||
642 | return error; | ||
643 | } | ||
644 | if (eof) { | ||
645 | last_fsb = new_last_fsb; | ||
646 | } | ||
647 | /* | ||
648 | * Round up the allocation request to a real-time extent boundary | ||
649 | * if the file is on the real-time subvolume. | ||
650 | */ | ||
651 | } else if (io->io_flags & XFS_IOCORE_RT && aeof) { | ||
652 | int eof; | ||
653 | xfs_fileoff_t new_last_fsb; | ||
654 | |||
655 | new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize); | ||
656 | error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); | ||
657 | if (error) { | ||
658 | return error; | 691 | return error; |
659 | } | ||
660 | if (eof) | ||
661 | last_fsb = new_last_fsb; | ||
662 | } | 692 | } |
693 | |||
694 | nimaps = XFS_WRITE_IMAPS; | ||
695 | firstblock = NULLFSBLOCK; | ||
663 | error = xfs_bmapi(NULL, ip, offset_fsb, | 696 | error = xfs_bmapi(NULL, ip, offset_fsb, |
664 | (xfs_filblks_t)(last_fsb - offset_fsb), | 697 | (xfs_filblks_t)(last_fsb - offset_fsb), |
665 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | | 698 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | |
666 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, | 699 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, |
667 | &nimaps, NULL); | 700 | &nimaps, NULL); |
668 | /* | 701 | if (error && (error != ENOSPC)) |
669 | * This can be EDQUOT, if nimaps == 0 | ||
670 | */ | ||
671 | if (error && (error != ENOSPC)) { | ||
672 | return XFS_ERROR(error); | 702 | return XFS_ERROR(error); |
673 | } | 703 | |
674 | /* | 704 | /* |
675 | * If bmapi returned us nothing, and if we didn't get back EDQUOT, | 705 | * If bmapi returned us nothing, and if we didn't get back EDQUOT, |
676 | * then we must have run out of space. | 706 | * then we must have run out of space - flush delalloc, and retry.. |
677 | */ | 707 | */ |
678 | if (nimaps == 0) { | 708 | if (nimaps == 0) { |
679 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, | 709 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, |
@@ -685,9 +715,7 @@ write_map: | |||
685 | goto retry; | 715 | goto retry; |
686 | } | 716 | } |
687 | 717 | ||
688 | *ret_imap = imap[0]; | 718 | if (!(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { |
689 | *nmaps = 1; | ||
690 | if ( !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) { | ||
691 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld " | 719 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld " |
692 | "start_block : %llx start_off : %llx blkcnt : %llx " | 720 | "start_block : %llx start_off : %llx blkcnt : %llx " |
693 | "extent-state : %x \n", | 721 | "extent-state : %x \n", |
@@ -696,6 +724,10 @@ write_map: | |||
696 | ret_imap->br_startblock, ret_imap->br_startoff, | 724 | ret_imap->br_startblock, ret_imap->br_startoff, |
697 | ret_imap->br_blockcount,ret_imap->br_state); | 725 | ret_imap->br_blockcount,ret_imap->br_state); |
698 | } | 726 | } |
727 | |||
728 | *ret_imap = imap[0]; | ||
729 | *nmaps = 1; | ||
730 | |||
699 | return 0; | 731 | return 0; |
700 | } | 732 | } |
701 | 733 | ||
@@ -868,17 +900,17 @@ xfs_iomap_write_unwritten( | |||
868 | { | 900 | { |
869 | xfs_mount_t *mp = ip->i_mount; | 901 | xfs_mount_t *mp = ip->i_mount; |
870 | xfs_iocore_t *io = &ip->i_iocore; | 902 | xfs_iocore_t *io = &ip->i_iocore; |
871 | xfs_trans_t *tp; | ||
872 | xfs_fileoff_t offset_fsb; | 903 | xfs_fileoff_t offset_fsb; |
873 | xfs_filblks_t count_fsb; | 904 | xfs_filblks_t count_fsb; |
874 | xfs_filblks_t numblks_fsb; | 905 | xfs_filblks_t numblks_fsb; |
875 | xfs_bmbt_irec_t imap; | 906 | xfs_fsblock_t firstfsb; |
907 | int nimaps; | ||
908 | xfs_trans_t *tp; | ||
909 | xfs_bmbt_irec_t imap; | ||
910 | xfs_bmap_free_t free_list; | ||
911 | uint resblks; | ||
876 | int committed; | 912 | int committed; |
877 | int error; | 913 | int error; |
878 | int nres; | ||
879 | int nimaps; | ||
880 | xfs_fsblock_t firstfsb; | ||
881 | xfs_bmap_free_t free_list; | ||
882 | 914 | ||
883 | xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, | 915 | xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, |
884 | &ip->i_iocore, offset, count); | 916 | &ip->i_iocore, offset, count); |
@@ -887,9 +919,9 @@ xfs_iomap_write_unwritten( | |||
887 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 919 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
888 | count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); | 920 | count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); |
889 | 921 | ||
890 | do { | 922 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1; |
891 | nres = XFS_DIOSTRAT_SPACE_RES(mp, 0); | ||
892 | 923 | ||
924 | do { | ||
893 | /* | 925 | /* |
894 | * set up a transaction to convert the range of extents | 926 | * set up a transaction to convert the range of extents |
895 | * from unwritten to real. Do allocations in a loop until | 927 | * from unwritten to real. Do allocations in a loop until |
@@ -897,7 +929,7 @@ xfs_iomap_write_unwritten( | |||
897 | */ | 929 | */ |
898 | 930 | ||
899 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); | 931 | tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); |
900 | error = xfs_trans_reserve(tp, nres, | 932 | error = xfs_trans_reserve(tp, resblks, |
901 | XFS_WRITE_LOG_RES(mp), 0, | 933 | XFS_WRITE_LOG_RES(mp), 0, |
902 | XFS_TRANS_PERM_LOG_RES, | 934 | XFS_TRANS_PERM_LOG_RES, |
903 | XFS_WRITE_LOG_COUNT); | 935 | XFS_WRITE_LOG_COUNT); |
@@ -916,7 +948,7 @@ xfs_iomap_write_unwritten( | |||
916 | XFS_BMAP_INIT(&free_list, &firstfsb); | 948 | XFS_BMAP_INIT(&free_list, &firstfsb); |
917 | nimaps = 1; | 949 | nimaps = 1; |
918 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, | 950 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, |
919 | XFS_BMAPI_WRITE, &firstfsb, | 951 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, |
920 | 1, &imap, &nimaps, &free_list); | 952 | 1, &imap, &nimaps, &free_list); |
921 | if (error) | 953 | if (error) |
922 | goto error_on_bmapi_transaction; | 954 | goto error_on_bmapi_transaction; |
@@ -930,7 +962,7 @@ xfs_iomap_write_unwritten( | |||
930 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 962 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
931 | if (error) | 963 | if (error) |
932 | goto error0; | 964 | goto error0; |
933 | 965 | ||
934 | if ( !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock) { | 966 | if ( !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock) { |
935 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> " | 967 | cmn_err(CE_PANIC,"Access to block zero: fs <%s> " |
936 | "inode: %lld start_block : %llx start_off : " | 968 | "inode: %lld start_block : %llx start_off : " |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 5f6dce3b4fd6..a2b422c984f2 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -541,24 +541,6 @@ xfs_setattr( | |||
541 | } | 541 | } |
542 | 542 | ||
543 | /* | 543 | /* |
544 | * Can't set extent size unless the file is marked, or | ||
545 | * about to be marked as a realtime file. | ||
546 | * | ||
547 | * This check will be removed when fixed size extents | ||
548 | * with buffered data writes is implemented. | ||
549 | * | ||
550 | */ | ||
551 | if ((mask & XFS_AT_EXTSIZE) && | ||
552 | ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != | ||
553 | vap->va_extsize) && | ||
554 | (!((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) || | ||
555 | ((mask & XFS_AT_XFLAGS) && | ||
556 | (vap->va_xflags & XFS_XFLAG_REALTIME))))) { | ||
557 | code = XFS_ERROR(EINVAL); | ||
558 | goto error_return; | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * Can't change realtime flag if any extents are allocated. | 544 | * Can't change realtime flag if any extents are allocated. |
563 | */ | 545 | */ |
564 | if ((ip->i_d.di_nextents || ip->i_delayed_blks) && | 546 | if ((ip->i_d.di_nextents || ip->i_delayed_blks) && |
@@ -820,13 +802,17 @@ xfs_setattr( | |||
820 | di_flags |= XFS_DIFLAG_RTINHERIT; | 802 | di_flags |= XFS_DIFLAG_RTINHERIT; |
821 | if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS) | 803 | if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS) |
822 | di_flags |= XFS_DIFLAG_NOSYMLINKS; | 804 | di_flags |= XFS_DIFLAG_NOSYMLINKS; |
823 | } else { | 805 | if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT) |
806 | di_flags |= XFS_DIFLAG_EXTSZINHERIT; | ||
807 | } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) { | ||
824 | if (vap->va_xflags & XFS_XFLAG_REALTIME) { | 808 | if (vap->va_xflags & XFS_XFLAG_REALTIME) { |
825 | di_flags |= XFS_DIFLAG_REALTIME; | 809 | di_flags |= XFS_DIFLAG_REALTIME; |
826 | ip->i_iocore.io_flags |= XFS_IOCORE_RT; | 810 | ip->i_iocore.io_flags |= XFS_IOCORE_RT; |
827 | } else { | 811 | } else { |
828 | ip->i_iocore.io_flags &= ~XFS_IOCORE_RT; | 812 | ip->i_iocore.io_flags &= ~XFS_IOCORE_RT; |
829 | } | 813 | } |
814 | if (vap->va_xflags & XFS_XFLAG_EXTSIZE) | ||
815 | di_flags |= XFS_DIFLAG_EXTSIZE; | ||
830 | } | 816 | } |
831 | ip->i_d.di_flags = di_flags; | 817 | ip->i_d.di_flags = di_flags; |
832 | } | 818 | } |
@@ -1568,7 +1554,8 @@ xfs_release( | |||
1568 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && | 1554 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && |
1569 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && | 1555 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && |
1570 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && | 1556 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && |
1571 | (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) { | 1557 | (!(ip->i_d.di_flags & |
1558 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { | ||
1572 | if ((error = xfs_inactive_free_eofblocks(mp, ip))) | 1559 | if ((error = xfs_inactive_free_eofblocks(mp, ip))) |
1573 | return (error); | 1560 | return (error); |
1574 | /* Update linux inode block count after free above */ | 1561 | /* Update linux inode block count after free above */ |
@@ -1644,9 +1631,10 @@ xfs_inactive( | |||
1644 | if (ip->i_d.di_nlink != 0) { | 1631 | if (ip->i_d.di_nlink != 0) { |
1645 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && | 1632 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && |
1646 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && | 1633 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && |
1647 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && | 1634 | (ip->i_df.if_flags & XFS_IFEXTENTS) && |
1648 | (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) || | 1635 | (!(ip->i_d.di_flags & |
1649 | (ip->i_delayed_blks != 0))) { | 1636 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || |
1637 | (ip->i_delayed_blks != 0)))) { | ||
1650 | if ((error = xfs_inactive_free_eofblocks(mp, ip))) | 1638 | if ((error = xfs_inactive_free_eofblocks(mp, ip))) |
1651 | return (VN_INACTIVE_CACHE); | 1639 | return (VN_INACTIVE_CACHE); |
1652 | /* Update linux inode block count after free above */ | 1640 | /* Update linux inode block count after free above */ |
@@ -3998,42 +3986,36 @@ xfs_alloc_file_space( | |||
3998 | int alloc_type, | 3986 | int alloc_type, |
3999 | int attr_flags) | 3987 | int attr_flags) |
4000 | { | 3988 | { |
3989 | xfs_mount_t *mp = ip->i_mount; | ||
3990 | xfs_off_t count; | ||
4001 | xfs_filblks_t allocated_fsb; | 3991 | xfs_filblks_t allocated_fsb; |
4002 | xfs_filblks_t allocatesize_fsb; | 3992 | xfs_filblks_t allocatesize_fsb; |
4003 | int committed; | 3993 | xfs_extlen_t extsz, temp; |
4004 | xfs_off_t count; | 3994 | xfs_fileoff_t startoffset_fsb; |
4005 | xfs_filblks_t datablocks; | ||
4006 | int error; | ||
4007 | xfs_fsblock_t firstfsb; | 3995 | xfs_fsblock_t firstfsb; |
4008 | xfs_bmap_free_t free_list; | 3996 | int nimaps; |
4009 | xfs_bmbt_irec_t *imapp; | 3997 | int bmapi_flag; |
4010 | xfs_bmbt_irec_t imaps[1]; | 3998 | int quota_flag; |
4011 | xfs_mount_t *mp; | ||
4012 | int numrtextents; | ||
4013 | int reccount; | ||
4014 | uint resblks; | ||
4015 | int rt; | 3999 | int rt; |
4016 | int rtextsize; | ||
4017 | xfs_fileoff_t startoffset_fsb; | ||
4018 | xfs_trans_t *tp; | 4000 | xfs_trans_t *tp; |
4019 | int xfs_bmapi_flags; | 4001 | xfs_bmbt_irec_t imaps[1], *imapp; |
4002 | xfs_bmap_free_t free_list; | ||
4003 | uint qblocks, resblks, resrtextents; | ||
4004 | int committed; | ||
4005 | int error; | ||
4020 | 4006 | ||
4021 | vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); | 4007 | vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); |
4022 | mp = ip->i_mount; | ||
4023 | 4008 | ||
4024 | if (XFS_FORCED_SHUTDOWN(mp)) | 4009 | if (XFS_FORCED_SHUTDOWN(mp)) |
4025 | return XFS_ERROR(EIO); | 4010 | return XFS_ERROR(EIO); |
4026 | 4011 | ||
4027 | /* | 4012 | rt = XFS_IS_REALTIME_INODE(ip); |
4028 | * determine if this is a realtime file | 4013 | if (unlikely(rt)) { |
4029 | */ | 4014 | if (!(extsz = ip->i_d.di_extsize)) |
4030 | if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) { | 4015 | extsz = mp->m_sb.sb_rextsize; |
4031 | if (ip->i_d.di_extsize) | 4016 | } else { |
4032 | rtextsize = ip->i_d.di_extsize; | 4017 | extsz = ip->i_d.di_extsize; |
4033 | else | 4018 | } |
4034 | rtextsize = mp->m_sb.sb_rextsize; | ||
4035 | } else | ||
4036 | rtextsize = 0; | ||
4037 | 4019 | ||
4038 | if ((error = XFS_QM_DQATTACH(mp, ip, 0))) | 4020 | if ((error = XFS_QM_DQATTACH(mp, ip, 0))) |
4039 | return error; | 4021 | return error; |
@@ -4044,8 +4026,8 @@ xfs_alloc_file_space( | |||
4044 | count = len; | 4026 | count = len; |
4045 | error = 0; | 4027 | error = 0; |
4046 | imapp = &imaps[0]; | 4028 | imapp = &imaps[0]; |
4047 | reccount = 1; | 4029 | nimaps = 1; |
4048 | xfs_bmapi_flags = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); | 4030 | bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); |
4049 | startoffset_fsb = XFS_B_TO_FSBT(mp, offset); | 4031 | startoffset_fsb = XFS_B_TO_FSBT(mp, offset); |
4050 | allocatesize_fsb = XFS_B_TO_FSB(mp, count); | 4032 | allocatesize_fsb = XFS_B_TO_FSB(mp, count); |
4051 | 4033 | ||
@@ -4066,43 +4048,51 @@ xfs_alloc_file_space( | |||
4066 | } | 4048 | } |
4067 | 4049 | ||
4068 | /* | 4050 | /* |
4069 | * allocate file space until done or until there is an error | 4051 | * Allocate file space until done or until there is an error |
4070 | */ | 4052 | */ |
4071 | retry: | 4053 | retry: |
4072 | while (allocatesize_fsb && !error) { | 4054 | while (allocatesize_fsb && !error) { |
4055 | xfs_fileoff_t s, e; | ||
4056 | |||
4073 | /* | 4057 | /* |
4074 | * determine if reserving space on | 4058 | * Determine space reservations for data/realtime, |
4075 | * the data or realtime partition. | ||
4076 | */ | 4059 | */ |
4077 | if (rt) { | 4060 | if (unlikely(extsz)) { |
4078 | xfs_fileoff_t s, e; | ||
4079 | |||
4080 | s = startoffset_fsb; | 4061 | s = startoffset_fsb; |
4081 | do_div(s, rtextsize); | 4062 | do_div(s, extsz); |
4082 | s *= rtextsize; | 4063 | s *= extsz; |
4083 | e = roundup_64(startoffset_fsb + allocatesize_fsb, | 4064 | e = startoffset_fsb + allocatesize_fsb; |
4084 | rtextsize); | 4065 | if ((temp = do_mod(startoffset_fsb, extsz))) |
4085 | numrtextents = (int)(e - s) / mp->m_sb.sb_rextsize; | 4066 | e += temp; |
4086 | datablocks = 0; | 4067 | if ((temp = do_mod(e, extsz))) |
4068 | e += extsz - temp; | ||
4069 | } else { | ||
4070 | s = 0; | ||
4071 | e = allocatesize_fsb; | ||
4072 | } | ||
4073 | |||
4074 | if (unlikely(rt)) { | ||
4075 | resrtextents = qblocks = (uint)(e - s); | ||
4076 | resrtextents /= mp->m_sb.sb_rextsize; | ||
4077 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); | ||
4078 | quota_flag = XFS_QMOPT_RES_RTBLKS; | ||
4087 | } else { | 4079 | } else { |
4088 | datablocks = allocatesize_fsb; | 4080 | resrtextents = 0; |
4089 | numrtextents = 0; | 4081 | resblks = qblocks = \ |
4082 | XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s)); | ||
4083 | quota_flag = XFS_QMOPT_RES_REGBLKS; | ||
4090 | } | 4084 | } |
4091 | 4085 | ||
4092 | /* | 4086 | /* |
4093 | * allocate and setup the transaction | 4087 | * Allocate and setup the transaction. |
4094 | */ | 4088 | */ |
4095 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); | 4089 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); |
4096 | resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); | 4090 | error = xfs_trans_reserve(tp, resblks, |
4097 | error = xfs_trans_reserve(tp, | 4091 | XFS_WRITE_LOG_RES(mp), resrtextents, |
4098 | resblks, | ||
4099 | XFS_WRITE_LOG_RES(mp), | ||
4100 | numrtextents, | ||
4101 | XFS_TRANS_PERM_LOG_RES, | 4092 | XFS_TRANS_PERM_LOG_RES, |
4102 | XFS_WRITE_LOG_COUNT); | 4093 | XFS_WRITE_LOG_COUNT); |
4103 | |||
4104 | /* | 4094 | /* |
4105 | * check for running out of space | 4095 | * Check for running out of space |
4106 | */ | 4096 | */ |
4107 | if (error) { | 4097 | if (error) { |
4108 | /* | 4098 | /* |
@@ -4113,8 +4103,8 @@ retry: | |||
4113 | break; | 4103 | break; |
4114 | } | 4104 | } |
4115 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 4105 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
4116 | error = XFS_TRANS_RESERVE_QUOTA(mp, tp, | 4106 | error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, |
4117 | ip->i_udquot, ip->i_gdquot, resblks, 0, 0); | 4107 | qblocks, 0, quota_flag); |
4118 | if (error) | 4108 | if (error) |
4119 | goto error1; | 4109 | goto error1; |
4120 | 4110 | ||
@@ -4122,19 +4112,19 @@ retry: | |||
4122 | xfs_trans_ihold(tp, ip); | 4112 | xfs_trans_ihold(tp, ip); |
4123 | 4113 | ||
4124 | /* | 4114 | /* |
4125 | * issue the bmapi() call to allocate the blocks | 4115 | * Issue the xfs_bmapi() call to allocate the blocks |
4126 | */ | 4116 | */ |
4127 | XFS_BMAP_INIT(&free_list, &firstfsb); | 4117 | XFS_BMAP_INIT(&free_list, &firstfsb); |
4128 | error = xfs_bmapi(tp, ip, startoffset_fsb, | 4118 | error = xfs_bmapi(tp, ip, startoffset_fsb, |
4129 | allocatesize_fsb, xfs_bmapi_flags, | 4119 | allocatesize_fsb, bmapi_flag, |
4130 | &firstfsb, 0, imapp, &reccount, | 4120 | &firstfsb, 0, imapp, &nimaps, |
4131 | &free_list); | 4121 | &free_list); |
4132 | if (error) { | 4122 | if (error) { |
4133 | goto error0; | 4123 | goto error0; |
4134 | } | 4124 | } |
4135 | 4125 | ||
4136 | /* | 4126 | /* |
4137 | * complete the transaction | 4127 | * Complete the transaction |
4138 | */ | 4128 | */ |
4139 | error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); | 4129 | error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); |
4140 | if (error) { | 4130 | if (error) { |
@@ -4149,7 +4139,7 @@ retry: | |||
4149 | 4139 | ||
4150 | allocated_fsb = imapp->br_blockcount; | 4140 | allocated_fsb = imapp->br_blockcount; |
4151 | 4141 | ||
4152 | if (reccount == 0) { | 4142 | if (nimaps == 0) { |
4153 | error = XFS_ERROR(ENOSPC); | 4143 | error = XFS_ERROR(ENOSPC); |
4154 | break; | 4144 | break; |
4155 | } | 4145 | } |
@@ -4172,9 +4162,11 @@ dmapi_enospc_check: | |||
4172 | 4162 | ||
4173 | return error; | 4163 | return error; |
4174 | 4164 | ||
4175 | error0: | 4165 | error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ |
4176 | xfs_bmap_cancel(&free_list); | 4166 | xfs_bmap_cancel(&free_list); |
4177 | error1: | 4167 | XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag); |
4168 | |||
4169 | error1: /* Just cancel transaction */ | ||
4178 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | 4170 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); |
4179 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 4171 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
4180 | goto dmapi_enospc_check; | 4172 | goto dmapi_enospc_check; |
@@ -4419,8 +4411,8 @@ xfs_free_file_space( | |||
4419 | } | 4411 | } |
4420 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 4412 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
4421 | error = XFS_TRANS_RESERVE_QUOTA(mp, tp, | 4413 | error = XFS_TRANS_RESERVE_QUOTA(mp, tp, |
4422 | ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? | 4414 | ip->i_udquot, ip->i_gdquot, resblks, 0, |
4423 | XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); | 4415 | XFS_QMOPT_RES_REGBLKS); |
4424 | if (error) | 4416 | if (error) |
4425 | goto error1; | 4417 | goto error1; |
4426 | 4418 | ||