aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_ialloc.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-07-04 10:54:49 -0400
committerBen Myers <bpm@sgi.com>2012-07-29 17:08:13 -0400
commit55d6af64cb8bf8c7e9a84b254d2c3479be8c067c (patch)
tree81aa38aee76d5133e12485ee7f47a5309582fac3 /fs/xfs/xfs_ialloc.c
parent4bb61069d2019dea2a7e4e0f4432101f03a9b820 (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.c95
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 */
445STATIC xfs_buf_t * /* allocation group buffer */ 445STATIC xfs_agnumber_t
446xfs_ialloc_ag_select( 446xfs_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 }
531unlock_nextag:
532 if (agbp)
533 xfs_trans_brelse(tp, agbp);
534nextag: 530nextag:
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 /*