aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2006-03-13 21:34:16 -0500
committerNathan Scott <nathans@sgi.com>2006-03-13 21:34:16 -0500
commita365bdd5e8fae9c592b9e4851d931016f9fdd868 (patch)
treea7f1692ad72f93526177c9d989c31427eef315e9 /fs/xfs/xfs_bmap.c
parent39269e29d4aad04252e0debec4c9b01bac16a257 (diff)
[XFS] Reduce stack usage within xfs_bmapi by rearranging some code,
splitting realtime/btree allocators apart. Based on Glens original patches. SGI-PV: 947312 SGI-Modid: xfs-linux-melb:xfs-kern:25372a Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c668
1 files changed, 345 insertions, 323 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index da8fa0cd79c1..9f0ed4869d47 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2294,25 +2294,15 @@ xfs_bmap_extsize_align(
2294 2294
2295#define XFS_ALLOC_GAP_UNITS 4 2295#define XFS_ALLOC_GAP_UNITS 4
2296 2296
2297/*
2298 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
2299 * It figures out where to ask the underlying allocator to put the new extent.
2300 */
2301STATIC int 2297STATIC int
2302xfs_bmap_alloc( 2298xfs_bmap_adjacent(
2303 xfs_bmalloca_t *ap) /* bmap alloc argument struct */ 2299 xfs_bmalloca_t *ap) /* bmap alloc argument struct */
2304{ 2300{
2305 xfs_fsblock_t adjust; /* adjustment to block numbers */ 2301 xfs_fsblock_t adjust; /* adjustment to block numbers */
2306 xfs_alloctype_t atype=0; /* type for allocation routines */
2307 int error; /* error return value */
2308 xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */ 2302 xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */
2309 xfs_mount_t *mp; /* mount point structure */ 2303 xfs_mount_t *mp; /* mount point structure */
2310 int nullfb; /* true if ap->firstblock isn't set */ 2304 int nullfb; /* true if ap->firstblock isn't set */
2311 int rt; /* true if inode is realtime */ 2305 int rt; /* true if inode is realtime */
2312 xfs_extlen_t prod = 0; /* product factor for allocators */
2313 xfs_extlen_t ralen = 0; /* realtime allocation length */
2314 xfs_extlen_t align; /* minimum allocation alignment */
2315 xfs_rtblock_t rtx;
2316 2306
2317#define ISVALID(x,y) \ 2307#define ISVALID(x,y) \
2318 (rt ? \ 2308 (rt ? \
@@ -2321,75 +2311,10 @@ xfs_bmap_alloc(
2321 XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \ 2311 XFS_FSB_TO_AGNO(mp, x) < mp->m_sb.sb_agcount && \
2322 XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) 2312 XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks)
2323 2313
2324 /*
2325 * Set up variables.
2326 */
2327 mp = ap->ip->i_mount; 2314 mp = ap->ip->i_mount;
2328 nullfb = ap->firstblock == NULLFSBLOCK; 2315 nullfb = ap->firstblock == NULLFSBLOCK;
2329 rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; 2316 rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
2330 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); 2317 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2331 if (rt) {
2332 align = ap->ip->i_d.di_extsize ?
2333 ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
2334 /* Set prod to match the extent size */
2335 prod = align / mp->m_sb.sb_rextsize;
2336
2337 error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2338 align, rt, ap->eof, 0,
2339 ap->conv, &ap->off, &ap->alen);
2340 if (error)
2341 return error;
2342 ASSERT(ap->alen);
2343 ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
2344
2345 /*
2346 * If the offset & length are not perfectly aligned
2347 * then kill prod, it will just get us in trouble.
2348 */
2349 if (do_mod(ap->off, align) || ap->alen % align)
2350 prod = 1;
2351 /*
2352 * Set ralen to be the actual requested length in rtextents.
2353 */
2354 ralen = ap->alen / mp->m_sb.sb_rextsize;
2355 /*
2356 * If the old value was close enough to MAXEXTLEN that
2357 * we rounded up to it, cut it back so it's valid again.
2358 * Note that if it's a really large request (bigger than
2359 * MAXEXTLEN), we don't hear about that number, and can't
2360 * adjust the starting point to match it.
2361 */
2362 if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
2363 ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
2364 /*
2365 * If it's an allocation to an empty file at offset 0,
2366 * pick an extent that will space things out in the rt area.
2367 */
2368 if (ap->eof && ap->off == 0) {
2369 error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
2370 if (error)
2371 return error;
2372 ap->rval = rtx * mp->m_sb.sb_rextsize;
2373 } else
2374 ap->rval = 0;
2375 } else {
2376 align = (ap->userdata && ap->ip->i_d.di_extsize &&
2377 (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
2378 ap->ip->i_d.di_extsize : 0;
2379 if (unlikely(align)) {
2380 error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2381 align, rt,
2382 ap->eof, 0, ap->conv,
2383 &ap->off, &ap->alen);
2384 ASSERT(!error);
2385 ASSERT(ap->alen);
2386 }
2387 if (nullfb)
2388 ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
2389 else
2390 ap->rval = ap->firstblock;
2391 }
2392
2393 /* 2318 /*
2394 * If allocating at eof, and there's a previous real block, 2319 * If allocating at eof, and there's a previous real block,
2395 * try to use it's last block as our starting point. 2320 * try to use it's last block as our starting point.
@@ -2514,281 +2439,378 @@ xfs_bmap_alloc(
2514 else if (gotbno != NULLFSBLOCK) 2439 else if (gotbno != NULLFSBLOCK)
2515 ap->rval = gotbno; 2440 ap->rval = gotbno;
2516 } 2441 }
2442#undef ISVALID
2443 return 0;
2444}
2445
2446STATIC int
2447xfs_bmap_rtalloc(
2448 xfs_bmalloca_t *ap) /* bmap alloc argument struct */
2449{
2450 xfs_alloctype_t atype = 0; /* type for allocation routines */
2451 int error; /* error return value */
2452 xfs_mount_t *mp; /* mount point structure */
2453 xfs_extlen_t prod = 0; /* product factor for allocators */
2454 xfs_extlen_t ralen = 0; /* realtime allocation length */
2455 xfs_extlen_t align; /* minimum allocation alignment */
2456 xfs_rtblock_t rtx; /* realtime extent number */
2457 xfs_rtblock_t rtb;
2458
2459 mp = ap->ip->i_mount;
2460 align = ap->ip->i_d.di_extsize ?
2461 ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
2462 prod = align / mp->m_sb.sb_rextsize;
2463 error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2464 align, 1, ap->eof, 0,
2465 ap->conv, &ap->off, &ap->alen);
2466 if (error)
2467 return error;
2468 ASSERT(ap->alen);
2469 ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
2470
2471 /*
2472 * If the offset & length are not perfectly aligned
2473 * then kill prod, it will just get us in trouble.
2474 */
2475 if (do_mod(ap->off, align) || ap->alen % align)
2476 prod = 1;
2477 /*
2478 * Set ralen to be the actual requested length in rtextents.
2479 */
2480 ralen = ap->alen / mp->m_sb.sb_rextsize;
2481 /*
2482 * If the old value was close enough to MAXEXTLEN that
2483 * we rounded up to it, cut it back so it's valid again.
2484 * Note that if it's a really large request (bigger than
2485 * MAXEXTLEN), we don't hear about that number, and can't
2486 * adjust the starting point to match it.
2487 */
2488 if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
2489 ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
2490 /*
2491 * If it's an allocation to an empty file at offset 0,
2492 * pick an extent that will space things out in the rt area.
2493 */
2494 if (ap->eof && ap->off == 0) {
2495 error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
2496 if (error)
2497 return error;
2498 ap->rval = rtx * mp->m_sb.sb_rextsize;
2499 } else {
2500 ap->rval = 0;
2501 }
2502
2503 xfs_bmap_adjacent(ap);
2504
2505 /*
2506 * Realtime allocation, done through xfs_rtallocate_extent.
2507 */
2508 atype = ap->rval == 0 ? XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO;
2509 do_div(ap->rval, mp->m_sb.sb_rextsize);
2510 rtb = ap->rval;
2511 ap->alen = ralen;
2512 if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen,
2513 &ralen, atype, ap->wasdel, prod, &rtb)))
2514 return error;
2515 if (rtb == NULLFSBLOCK && prod > 1 &&
2516 (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1,
2517 ap->alen, &ralen, atype,
2518 ap->wasdel, 1, &rtb)))
2519 return error;
2520 ap->rval = rtb;
2521 if (ap->rval != NULLFSBLOCK) {
2522 ap->rval *= mp->m_sb.sb_rextsize;
2523 ralen *= mp->m_sb.sb_rextsize;
2524 ap->alen = ralen;
2525 ap->ip->i_d.di_nblocks += ralen;
2526 xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2527 if (ap->wasdel)
2528 ap->ip->i_delayed_blks -= ralen;
2529 /*
2530 * Adjust the disk quota also. This was reserved
2531 * earlier.
2532 */
2533 XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
2534 ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
2535 XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
2536 } else {
2537 ap->alen = 0;
2538 }
2539 return 0;
2540}
2541
2542STATIC int
2543xfs_bmap_btalloc(
2544 xfs_bmalloca_t *ap) /* bmap alloc argument struct */
2545{
2546 xfs_mount_t *mp; /* mount point structure */
2547 xfs_alloctype_t atype = 0; /* type for allocation routines */
2548 xfs_extlen_t align; /* minimum allocation alignment */
2549 xfs_agnumber_t ag;
2550 xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */
2551 xfs_agnumber_t startag;
2552 xfs_alloc_arg_t args;
2553 xfs_extlen_t blen;
2554 xfs_extlen_t delta;
2555 xfs_extlen_t longest;
2556 xfs_extlen_t need;
2557 xfs_extlen_t nextminlen = 0;
2558 xfs_perag_t *pag;
2559 int nullfb; /* true if ap->firstblock isn't set */
2560 int isaligned;
2561 int notinit;
2562 int tryagain;
2563 int error;
2564
2565 mp = ap->ip->i_mount;
2566 align = (ap->userdata && ap->ip->i_d.di_extsize &&
2567 (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
2568 ap->ip->i_d.di_extsize : 0;
2569 if (unlikely(align)) {
2570 error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
2571 align, 0, ap->eof, 0, ap->conv,
2572 &ap->off, &ap->alen);
2573 ASSERT(!error);
2574 ASSERT(ap->alen);
2575 }
2576 nullfb = ap->firstblock == NULLFSBLOCK;
2577 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
2578 if (nullfb)
2579 ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
2580 else
2581 ap->rval = ap->firstblock;
2582
2583 xfs_bmap_adjacent(ap);
2584
2517 /* 2585 /*
2518 * If allowed, use ap->rval; otherwise must use firstblock since 2586 * If allowed, use ap->rval; otherwise must use firstblock since
2519 * it's in the right allocation group. 2587 * it's in the right allocation group.
2520 */ 2588 */
2521 if (nullfb || rt || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno) 2589 if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno)
2522 ; 2590 ;
2523 else 2591 else
2524 ap->rval = ap->firstblock; 2592 ap->rval = ap->firstblock;
2525 /* 2593 /*
2526 * Realtime allocation, done through xfs_rtallocate_extent. 2594 * Normal allocation, done through xfs_alloc_vextent.
2527 */ 2595 */
2528 if (rt) { 2596 tryagain = isaligned = 0;
2529#ifndef __KERNEL__ 2597 args.tp = ap->tp;
2530 ASSERT(0); 2598 args.mp = mp;
2531#else 2599 args.fsbno = ap->rval;
2532 xfs_rtblock_t rtb; 2600 args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
2533 2601 blen = 0;
2534 atype = ap->rval == 0 ? 2602 if (nullfb) {
2535 XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO; 2603 args.type = XFS_ALLOCTYPE_START_BNO;
2536 do_div(ap->rval, mp->m_sb.sb_rextsize); 2604 args.total = ap->total;
2537 rtb = ap->rval; 2605 /*
2538 ap->alen = ralen; 2606 * Find the longest available space.
2539 if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen, 2607 * We're going to try for the whole allocation at once.
2540 &ralen, atype, ap->wasdel, prod, &rtb))) 2608 */
2541 return error; 2609 startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
2542 if (rtb == NULLFSBLOCK && prod > 1 && 2610 notinit = 0;
2543 (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, 2611 down_read(&mp->m_peraglock);
2544 ap->alen, &ralen, atype, 2612 while (blen < ap->alen) {
2545 ap->wasdel, 1, &rtb))) 2613 pag = &mp->m_perag[ag];
2546 return error; 2614 if (!pag->pagf_init &&
2547 ap->rval = rtb; 2615 (error = xfs_alloc_pagf_init(mp, args.tp,
2548 if (ap->rval != NULLFSBLOCK) { 2616 ag, XFS_ALLOC_FLAG_TRYLOCK))) {
2549 ap->rval *= mp->m_sb.sb_rextsize; 2617 up_read(&mp->m_peraglock);
2550 ralen *= mp->m_sb.sb_rextsize; 2618 return error;
2551 ap->alen = ralen; 2619 }
2552 ap->ip->i_d.di_nblocks += ralen;
2553 xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2554 if (ap->wasdel)
2555 ap->ip->i_delayed_blks -= ralen;
2556 /* 2620 /*
2557 * Adjust the disk quota also. This was reserved 2621 * See xfs_alloc_fix_freelist...
2558 * earlier.
2559 */ 2622 */
2560 XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip, 2623 if (pag->pagf_init) {
2561 ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : 2624 need = XFS_MIN_FREELIST_PAG(pag, mp);
2562 XFS_TRANS_DQ_RTBCOUNT, 2625 delta = need > pag->pagf_flcount ?
2563 (long) ralen); 2626 need - pag->pagf_flcount : 0;
2564 } else 2627 longest = (pag->pagf_longest > delta) ?
2565 ap->alen = 0; 2628 (pag->pagf_longest - delta) :
2566#endif /* __KERNEL__ */ 2629 (pag->pagf_flcount > 0 ||
2630 pag->pagf_longest > 0);
2631 if (blen < longest)
2632 blen = longest;
2633 } else
2634 notinit = 1;
2635 if (++ag == mp->m_sb.sb_agcount)
2636 ag = 0;
2637 if (ag == startag)
2638 break;
2639 }
2640 up_read(&mp->m_peraglock);
2641 /*
2642 * Since the above loop did a BUF_TRYLOCK, it is
2643 * possible that there is space for this request.
2644 */
2645 if (notinit || blen < ap->minlen)
2646 args.minlen = ap->minlen;
2647 /*
2648 * If the best seen length is less than the request
2649 * length, use the best as the minimum.
2650 */
2651 else if (blen < ap->alen)
2652 args.minlen = blen;
2653 /*
2654 * Otherwise we've seen an extent as big as alen,
2655 * use that as the minimum.
2656 */
2657 else
2658 args.minlen = ap->alen;
2659 } else if (ap->low) {
2660 args.type = XFS_ALLOCTYPE_FIRST_AG;
2661 args.total = args.minlen = ap->minlen;
2662 } else {
2663 args.type = XFS_ALLOCTYPE_NEAR_BNO;
2664 args.total = ap->total;
2665 args.minlen = ap->minlen;
2666 }
2667 if (unlikely(ap->userdata && ap->ip->i_d.di_extsize &&
2668 (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) {
2669 args.prod = ap->ip->i_d.di_extsize;
2670 if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
2671 args.mod = (xfs_extlen_t)(args.prod - args.mod);
2672 } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) {
2673 args.prod = 1;
2674 args.mod = 0;
2675 } else {
2676 args.prod = NBPP >> mp->m_sb.sb_blocklog;
2677 if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
2678 args.mod = (xfs_extlen_t)(args.prod - args.mod);
2567 } 2679 }
2568 /* 2680 /*
2569 * Normal allocation, done through xfs_alloc_vextent. 2681 * If we are not low on available data blocks, and the
2682 * underlying logical volume manager is a stripe, and
2683 * the file offset is zero then try to allocate data
2684 * blocks on stripe unit boundary.
2685 * NOTE: ap->aeof is only set if the allocation length
2686 * is >= the stripe unit and the allocation offset is
2687 * at the end of file.
2570 */ 2688 */
2571 else { 2689 if (!ap->low && ap->aeof) {
2572 xfs_agnumber_t ag; 2690 if (!ap->off) {
2573 xfs_alloc_arg_t args; 2691 args.alignment = mp->m_dalign;
2574 xfs_extlen_t blen; 2692 atype = args.type;
2575 xfs_extlen_t delta; 2693 isaligned = 1;
2576 int isaligned;
2577 xfs_extlen_t longest;
2578 xfs_extlen_t need;
2579 xfs_extlen_t nextminlen=0;
2580 int notinit;
2581 xfs_perag_t *pag;
2582 xfs_agnumber_t startag;
2583 int tryagain;
2584
2585 tryagain = isaligned = 0;
2586 args.tp = ap->tp;
2587 args.mp = mp;
2588 args.fsbno = ap->rval;
2589 args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
2590 blen = 0;
2591 if (nullfb) {
2592 args.type = XFS_ALLOCTYPE_START_BNO;
2593 args.total = ap->total;
2594 /*
2595 * Find the longest available space.
2596 * We're going to try for the whole allocation at once.
2597 */
2598 startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
2599 notinit = 0;
2600 down_read(&mp->m_peraglock);
2601 while (blen < ap->alen) {
2602 pag = &mp->m_perag[ag];
2603 if (!pag->pagf_init &&
2604 (error = xfs_alloc_pagf_init(mp, args.tp,
2605 ag, XFS_ALLOC_FLAG_TRYLOCK))) {
2606 up_read(&mp->m_peraglock);
2607 return error;
2608 }
2609 /*
2610 * See xfs_alloc_fix_freelist...
2611 */
2612 if (pag->pagf_init) {
2613 need = XFS_MIN_FREELIST_PAG(pag, mp);
2614 delta = need > pag->pagf_flcount ?
2615 need - pag->pagf_flcount : 0;
2616 longest = (pag->pagf_longest > delta) ?
2617 (pag->pagf_longest - delta) :
2618 (pag->pagf_flcount > 0 ||
2619 pag->pagf_longest > 0);
2620 if (blen < longest)
2621 blen = longest;
2622 } else
2623 notinit = 1;
2624 if (++ag == mp->m_sb.sb_agcount)
2625 ag = 0;
2626 if (ag == startag)
2627 break;
2628 }
2629 up_read(&mp->m_peraglock);
2630 /* 2694 /*
2631 * Since the above loop did a BUF_TRYLOCK, it is 2695 * Adjust for alignment
2632 * possible that there is space for this request.
2633 */ 2696 */
2634 if (notinit || blen < ap->minlen) 2697 if (blen > args.alignment && blen <= ap->alen)
2635 args.minlen = ap->minlen; 2698 args.minlen = blen - args.alignment;
2699 args.minalignslop = 0;
2700 } else {
2636 /* 2701 /*
2637 * If the best seen length is less than the request 2702 * First try an exact bno allocation.
2638 * length, use the best as the minimum. 2703 * If it fails then do a near or start bno
2704 * allocation with alignment turned on.
2639 */ 2705 */
2640 else if (blen < ap->alen) 2706 atype = args.type;
2641 args.minlen = blen; 2707 tryagain = 1;
2708 args.type = XFS_ALLOCTYPE_THIS_BNO;
2709 args.alignment = 1;
2642 /* 2710 /*
2643 * Otherwise we've seen an extent as big as alen, 2711 * Compute the minlen+alignment for the
2644 * use that as the minimum. 2712 * next case. Set slop so that the value
2713 * of minlen+alignment+slop doesn't go up
2714 * between the calls.
2645 */ 2715 */
2716 if (blen > mp->m_dalign && blen <= ap->alen)
2717 nextminlen = blen - mp->m_dalign;
2646 else 2718 else
2647 args.minlen = ap->alen; 2719 nextminlen = args.minlen;
2648 } else if (ap->low) { 2720 if (nextminlen + mp->m_dalign > args.minlen + 1)
2649 args.type = XFS_ALLOCTYPE_FIRST_AG; 2721 args.minalignslop =
2650 args.total = args.minlen = ap->minlen; 2722 nextminlen + mp->m_dalign -
2651 } else { 2723 args.minlen - 1;
2652 args.type = XFS_ALLOCTYPE_NEAR_BNO; 2724 else
2653 args.total = ap->total; 2725 args.minalignslop = 0;
2654 args.minlen = ap->minlen;
2655 }
2656 if (unlikely(ap->userdata && ap->ip->i_d.di_extsize &&
2657 (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) {
2658 args.prod = ap->ip->i_d.di_extsize;
2659 if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
2660 args.mod = (xfs_extlen_t)(args.prod - args.mod);
2661 } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) {
2662 args.prod = 1;
2663 args.mod = 0;
2664 } else {
2665 args.prod = NBPP >> mp->m_sb.sb_blocklog;
2666 if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod))))
2667 args.mod = (xfs_extlen_t)(args.prod - args.mod);
2668 } 2726 }
2727 } else {
2728 args.alignment = 1;
2729 args.minalignslop = 0;
2730 }
2731 args.minleft = ap->minleft;
2732 args.wasdel = ap->wasdel;
2733 args.isfl = 0;
2734 args.userdata = ap->userdata;
2735 if ((error = xfs_alloc_vextent(&args)))
2736 return error;
2737 if (tryagain && args.fsbno == NULLFSBLOCK) {
2669 /* 2738 /*
2670 * If we are not low on available data blocks, and the 2739 * Exact allocation failed. Now try with alignment
2671 * underlying logical volume manager is a stripe, and 2740 * turned on.
2672 * the file offset is zero then try to allocate data
2673 * blocks on stripe unit boundary.
2674 * NOTE: ap->aeof is only set if the allocation length
2675 * is >= the stripe unit and the allocation offset is
2676 * at the end of file.
2677 */ 2741 */
2678 if (!ap->low && ap->aeof) { 2742 args.type = atype;
2679 if (!ap->off) { 2743 args.fsbno = ap->rval;
2680 args.alignment = mp->m_dalign; 2744 args.alignment = mp->m_dalign;
2681 atype = args.type; 2745 args.minlen = nextminlen;
2682 isaligned = 1; 2746 args.minalignslop = 0;
2683 /* 2747 isaligned = 1;
2684 * Adjust for alignment 2748 if ((error = xfs_alloc_vextent(&args)))
2685 */ 2749 return error;
2686 if (blen > args.alignment && blen <= ap->alen) 2750 }
2687 args.minlen = blen - args.alignment; 2751 if (isaligned && args.fsbno == NULLFSBLOCK) {
2688 args.minalignslop = 0; 2752 /*
2689 } else { 2753 * allocation failed, so turn off alignment and
2690 /* 2754 * try again.
2691 * First try an exact bno allocation. 2755 */
2692 * If it fails then do a near or start bno 2756 args.type = atype;
2693 * allocation with alignment turned on. 2757 args.fsbno = ap->rval;
2694 */ 2758 args.alignment = 0;
2695 atype = args.type; 2759 if ((error = xfs_alloc_vextent(&args)))
2696 tryagain = 1; 2760 return error;
2697 args.type = XFS_ALLOCTYPE_THIS_BNO; 2761 }
2698 args.alignment = 1; 2762 if (args.fsbno == NULLFSBLOCK && nullfb &&
2699 /* 2763 args.minlen > ap->minlen) {
2700 * Compute the minlen+alignment for the 2764 args.minlen = ap->minlen;
2701 * next case. Set slop so that the value 2765 args.type = XFS_ALLOCTYPE_START_BNO;
2702 * of minlen+alignment+slop doesn't go up 2766 args.fsbno = ap->rval;
2703 * between the calls.
2704 */
2705 if (blen > mp->m_dalign && blen <= ap->alen)
2706 nextminlen = blen - mp->m_dalign;
2707 else
2708 nextminlen = args.minlen;
2709 if (nextminlen + mp->m_dalign > args.minlen + 1)
2710 args.minalignslop =
2711 nextminlen + mp->m_dalign -
2712 args.minlen - 1;
2713 else
2714 args.minalignslop = 0;
2715 }
2716 } else {
2717 args.alignment = 1;
2718 args.minalignslop = 0;
2719 }
2720 args.minleft = ap->minleft;
2721 args.wasdel = ap->wasdel;
2722 args.isfl = 0;
2723 args.userdata = ap->userdata;
2724 if ((error = xfs_alloc_vextent(&args))) 2767 if ((error = xfs_alloc_vextent(&args)))
2725 return error; 2768 return error;
2726 if (tryagain && args.fsbno == NULLFSBLOCK) { 2769 }
2727 /* 2770 if (args.fsbno == NULLFSBLOCK && nullfb) {
2728 * Exact allocation failed. Now try with alignment 2771 args.fsbno = 0;
2729 * turned on. 2772 args.type = XFS_ALLOCTYPE_FIRST_AG;
2730 */ 2773 args.total = ap->minlen;
2731 args.type = atype; 2774 args.minleft = 0;
2732 args.fsbno = ap->rval; 2775 if ((error = xfs_alloc_vextent(&args)))
2733 args.alignment = mp->m_dalign; 2776 return error;
2734 args.minlen = nextminlen; 2777 ap->low = 1;
2735 args.minalignslop = 0; 2778 }
2736 isaligned = 1; 2779 if (args.fsbno != NULLFSBLOCK) {
2737 if ((error = xfs_alloc_vextent(&args))) 2780 ap->firstblock = ap->rval = args.fsbno;
2738 return error; 2781 ASSERT(nullfb || fb_agno == args.agno ||
2739 } 2782 (ap->low && fb_agno < args.agno));
2740 if (isaligned && args.fsbno == NULLFSBLOCK) { 2783 ap->alen = args.len;
2741 /* 2784 ap->ip->i_d.di_nblocks += args.len;
2742 * allocation failed, so turn off alignment and 2785 xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2743 * try again. 2786 if (ap->wasdel)
2744 */ 2787 ap->ip->i_delayed_blks -= args.len;
2745 args.type = atype; 2788 /*
2746 args.fsbno = ap->rval; 2789 * Adjust the disk quota also. This was reserved
2747 args.alignment = 0; 2790 * earlier.
2748 if ((error = xfs_alloc_vextent(&args))) 2791 */
2749 return error; 2792 XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
2750 } 2793 ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
2751 if (args.fsbno == NULLFSBLOCK && nullfb && 2794 XFS_TRANS_DQ_BCOUNT,
2752 args.minlen > ap->minlen) { 2795 (long) args.len);
2753 args.minlen = ap->minlen; 2796 } else {
2754 args.type = XFS_ALLOCTYPE_START_BNO; 2797 ap->rval = NULLFSBLOCK;
2755 args.fsbno = ap->rval; 2798 ap->alen = 0;
2756 if ((error = xfs_alloc_vextent(&args)))
2757 return error;
2758 }
2759 if (args.fsbno == NULLFSBLOCK && nullfb) {
2760 args.fsbno = 0;
2761 args.type = XFS_ALLOCTYPE_FIRST_AG;
2762 args.total = ap->minlen;
2763 args.minleft = 0;
2764 if ((error = xfs_alloc_vextent(&args)))
2765 return error;
2766 ap->low = 1;
2767 }
2768 if (args.fsbno != NULLFSBLOCK) {
2769 ap->firstblock = ap->rval = args.fsbno;
2770 ASSERT(nullfb || fb_agno == args.agno ||
2771 (ap->low && fb_agno < args.agno));
2772 ap->alen = args.len;
2773 ap->ip->i_d.di_nblocks += args.len;
2774 xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
2775 if (ap->wasdel)
2776 ap->ip->i_delayed_blks -= args.len;
2777 /*
2778 * Adjust the disk quota also. This was reserved
2779 * earlier.
2780 */
2781 XFS_TRANS_MOD_DQUOT_BYINO(mp, ap->tp, ap->ip,
2782 ap->wasdel ? XFS_TRANS_DQ_DELBCOUNT :
2783 XFS_TRANS_DQ_BCOUNT,
2784 (long) args.len);
2785 } else {
2786 ap->rval = NULLFSBLOCK;
2787 ap->alen = 0;
2788 }
2789 } 2799 }
2790 return 0; 2800 return 0;
2791#undef ISVALID 2801}
2802
2803/*
2804 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
2805 * It figures out where to ask the underlying allocator to put the new extent.
2806 */
2807STATIC int
2808xfs_bmap_alloc(
2809 xfs_bmalloca_t *ap) /* bmap alloc argument struct */
2810{
2811 if ((ap->ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && ap->userdata)
2812 return xfs_bmap_rtalloc(ap);
2813 return xfs_bmap_btalloc(ap);
2792} 2814}
2793 2815
2794/* 2816/*