diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-07-04 10:54:49 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-07-29 17:08:13 -0400 |
commit | 55d6af64cb8bf8c7e9a84b254d2c3479be8c067c (patch) | |
tree | 81aa38aee76d5133e12485ee7f47a5309582fac3 /fs/xfs/xfs_ialloc.c | |
parent | 4bb61069d2019dea2a7e4e0f4432101f03a9b820 (diff) |
xfs: refactor xfs_ialloc_ag_select
Loop over the in-core perag structures and prefer using pagi_freecount over
going out to the AGI buffer where possible.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_ialloc.c')
-rw-r--r-- | fs/xfs/xfs_ialloc.c | 95 |
1 files changed, 44 insertions, 51 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 7aa8a02b7937..ecb9f22a7f35 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -442,14 +442,13 @@ xfs_ialloc_next_ag( | |||
442 | * Select an allocation group to look for a free inode in, based on the parent | 442 | * Select an allocation group to look for a free inode in, based on the parent |
443 | * inode and then mode. Return the allocation group buffer. | 443 | * inode and then mode. Return the allocation group buffer. |
444 | */ | 444 | */ |
445 | STATIC xfs_buf_t * /* allocation group buffer */ | 445 | STATIC xfs_agnumber_t |
446 | xfs_ialloc_ag_select( | 446 | xfs_ialloc_ag_select( |
447 | xfs_trans_t *tp, /* transaction pointer */ | 447 | xfs_trans_t *tp, /* transaction pointer */ |
448 | xfs_ino_t parent, /* parent directory inode number */ | 448 | xfs_ino_t parent, /* parent directory inode number */ |
449 | umode_t mode, /* bits set to indicate file type */ | 449 | umode_t mode, /* bits set to indicate file type */ |
450 | int okalloc) /* ok to allocate more space */ | 450 | int okalloc) /* ok to allocate more space */ |
451 | { | 451 | { |
452 | xfs_buf_t *agbp; /* allocation group header buffer */ | ||
453 | xfs_agnumber_t agcount; /* number of ag's in the filesystem */ | 452 | xfs_agnumber_t agcount; /* number of ag's in the filesystem */ |
454 | xfs_agnumber_t agno; /* current ag number */ | 453 | xfs_agnumber_t agno; /* current ag number */ |
455 | int flags; /* alloc buffer locking flags */ | 454 | int flags; /* alloc buffer locking flags */ |
@@ -459,6 +458,7 @@ xfs_ialloc_ag_select( | |||
459 | int needspace; /* file mode implies space allocated */ | 458 | int needspace; /* file mode implies space allocated */ |
460 | xfs_perag_t *pag; /* per allocation group data */ | 459 | xfs_perag_t *pag; /* per allocation group data */ |
461 | xfs_agnumber_t pagno; /* parent (starting) ag number */ | 460 | xfs_agnumber_t pagno; /* parent (starting) ag number */ |
461 | int error; | ||
462 | 462 | ||
463 | /* | 463 | /* |
464 | * Files of these types need at least one block if length > 0 | 464 | * Files of these types need at least one block if length > 0 |
@@ -474,7 +474,9 @@ xfs_ialloc_ag_select( | |||
474 | if (pagno >= agcount) | 474 | if (pagno >= agcount) |
475 | pagno = 0; | 475 | pagno = 0; |
476 | } | 476 | } |
477 | |||
477 | ASSERT(pagno < agcount); | 478 | ASSERT(pagno < agcount); |
479 | |||
478 | /* | 480 | /* |
479 | * Loop through allocation groups, looking for one with a little | 481 | * Loop through allocation groups, looking for one with a little |
480 | * free space in it. Note we don't look for free inodes, exactly. | 482 | * free space in it. Note we don't look for free inodes, exactly. |
@@ -486,51 +488,45 @@ xfs_ialloc_ag_select( | |||
486 | flags = XFS_ALLOC_FLAG_TRYLOCK; | 488 | flags = XFS_ALLOC_FLAG_TRYLOCK; |
487 | for (;;) { | 489 | for (;;) { |
488 | pag = xfs_perag_get(mp, agno); | 490 | pag = xfs_perag_get(mp, agno); |
491 | if (!pag->pagi_inodeok) { | ||
492 | xfs_ialloc_next_ag(mp); | ||
493 | goto nextag; | ||
494 | } | ||
495 | |||
489 | if (!pag->pagi_init) { | 496 | if (!pag->pagi_init) { |
490 | if (xfs_ialloc_read_agi(mp, tp, agno, &agbp)) { | 497 | error = xfs_ialloc_pagi_init(mp, tp, agno); |
491 | agbp = NULL; | 498 | if (error) |
492 | goto nextag; | 499 | goto nextag; |
493 | } | 500 | } |
494 | } else | ||
495 | agbp = NULL; | ||
496 | 501 | ||
497 | if (!pag->pagi_inodeok) { | 502 | if (pag->pagi_freecount) { |
498 | xfs_ialloc_next_ag(mp); | 503 | xfs_perag_put(pag); |
499 | goto unlock_nextag; | 504 | return agno; |
500 | } | 505 | } |
501 | 506 | ||
502 | /* | 507 | if (!okalloc) |
503 | * Is there enough free space for the file plus a block | 508 | goto nextag; |
504 | * of inodes (if we need to allocate some)? | 509 | |
505 | */ | 510 | if (!pag->pagf_init) { |
506 | ineed = pag->pagi_freecount ? 0 : XFS_IALLOC_BLOCKS(mp); | 511 | error = xfs_alloc_pagf_init(mp, tp, agno, flags); |
507 | if (ineed && !pag->pagf_init) { | 512 | if (error) |
508 | if (agbp == NULL && | ||
509 | xfs_ialloc_read_agi(mp, tp, agno, &agbp)) { | ||
510 | agbp = NULL; | ||
511 | goto nextag; | 513 | goto nextag; |
512 | } | ||
513 | (void)xfs_alloc_pagf_init(mp, tp, agno, flags); | ||
514 | } | 514 | } |
515 | if (!ineed || pag->pagf_init) { | 515 | |
516 | if (ineed && !(longest = pag->pagf_longest)) | 516 | /* |
517 | longest = pag->pagf_flcount > 0; | 517 | * Is there enough free space for the file plus a block of |
518 | if (!ineed || | 518 | * inodes? (if we need to allocate some)? |
519 | (pag->pagf_freeblks >= needspace + ineed && | 519 | */ |
520 | longest >= ineed && | 520 | ineed = XFS_IALLOC_BLOCKS(mp); |
521 | okalloc)) { | 521 | longest = pag->pagf_longest; |
522 | if (agbp == NULL && | 522 | if (!longest) |
523 | xfs_ialloc_read_agi(mp, tp, agno, &agbp)) { | 523 | longest = pag->pagf_flcount > 0; |
524 | agbp = NULL; | 524 | |
525 | goto nextag; | 525 | if (pag->pagf_freeblks >= needspace + ineed && |
526 | } | 526 | longest >= ineed) { |
527 | xfs_perag_put(pag); | 527 | xfs_perag_put(pag); |
528 | return agbp; | 528 | return agno; |
529 | } | ||
530 | } | 529 | } |
531 | unlock_nextag: | ||
532 | if (agbp) | ||
533 | xfs_trans_brelse(tp, agbp); | ||
534 | nextag: | 530 | nextag: |
535 | xfs_perag_put(pag); | 531 | xfs_perag_put(pag); |
536 | /* | 532 | /* |
@@ -538,13 +534,13 @@ nextag: | |||
538 | * down. | 534 | * down. |
539 | */ | 535 | */ |
540 | if (XFS_FORCED_SHUTDOWN(mp)) | 536 | if (XFS_FORCED_SHUTDOWN(mp)) |
541 | return NULL; | 537 | return NULLAGNUMBER; |
542 | agno++; | 538 | agno++; |
543 | if (agno >= agcount) | 539 | if (agno >= agcount) |
544 | agno = 0; | 540 | agno = 0; |
545 | if (agno == pagno) { | 541 | if (agno == pagno) { |
546 | if (flags == 0) | 542 | if (flags == 0) |
547 | return NULL; | 543 | return NULLAGNUMBER; |
548 | flags = 0; | 544 | flags = 0; |
549 | } | 545 | } |
550 | } | 546 | } |
@@ -901,13 +897,13 @@ xfs_dialloc( | |||
901 | struct xfs_buf **IO_agbp, | 897 | struct xfs_buf **IO_agbp, |
902 | xfs_ino_t *inop) | 898 | xfs_ino_t *inop) |
903 | { | 899 | { |
900 | struct xfs_mount *mp = tp->t_mountp; | ||
904 | struct xfs_buf *agbp; | 901 | struct xfs_buf *agbp; |
905 | xfs_agnumber_t agno; | 902 | xfs_agnumber_t agno; |
906 | struct xfs_agi *agi; | 903 | struct xfs_agi *agi; |
907 | int error; | 904 | int error; |
908 | int ialloced; | 905 | int ialloced; |
909 | int noroom = 0; | 906 | int noroom = 0; |
910 | struct xfs_mount *mp; | ||
911 | xfs_agnumber_t tagno; | 907 | xfs_agnumber_t tagno; |
912 | struct xfs_perag *pag; | 908 | struct xfs_perag *pag; |
913 | 909 | ||
@@ -925,20 +921,17 @@ xfs_dialloc( | |||
925 | * We do not have an agbp, so select an initial allocation | 921 | * We do not have an agbp, so select an initial allocation |
926 | * group for inode allocation. | 922 | * group for inode allocation. |
927 | */ | 923 | */ |
928 | agbp = xfs_ialloc_ag_select(tp, parent, mode, okalloc); | 924 | agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc); |
929 | 925 | if (agno == NULLAGNUMBER) { | |
930 | /* | ||
931 | * Couldn't find an allocation group satisfying the | ||
932 | * criteria, give up. | ||
933 | */ | ||
934 | if (!agbp) { | ||
935 | *inop = NULLFSINO; | 926 | *inop = NULLFSINO; |
936 | return 0; | 927 | return 0; |
937 | } | 928 | } |
929 | |||
930 | error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); | ||
931 | if (error) | ||
932 | return XFS_ERROR(error); | ||
938 | agi = XFS_BUF_TO_AGI(agbp); | 933 | agi = XFS_BUF_TO_AGI(agbp); |
939 | 934 | ||
940 | mp = tp->t_mountp; | ||
941 | agno = be32_to_cpu(agi->agi_seqno); | ||
942 | tagno = agno; | 935 | tagno = agno; |
943 | 936 | ||
944 | /* | 937 | /* |