Commit 55d6af64cb8bf8c7e9a84b254d2c3479be8c067c

Authored by Christoph Hellwig
Committed by Ben Myers
1 parent 4bb61069d2

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>

Showing 1 changed file with 44 additions and 51 deletions Side-by-side Diff

... ... @@ -442,14 +442,13 @@
442 442 * Select an allocation group to look for a free inode in, based on the parent
443 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 446 xfs_ialloc_ag_select(
447 447 xfs_trans_t *tp, /* transaction pointer */
448 448 xfs_ino_t parent, /* parent directory inode number */
449 449 umode_t mode, /* bits set to indicate file type */
450 450 int okalloc) /* ok to allocate more space */
451 451 {
452   - xfs_buf_t *agbp; /* allocation group header buffer */
453 452 xfs_agnumber_t agcount; /* number of ag's in the filesystem */
454 453 xfs_agnumber_t agno; /* current ag number */
455 454 int flags; /* alloc buffer locking flags */
... ... @@ -459,6 +458,7 @@
459 458 int needspace; /* file mode implies space allocated */
460 459 xfs_perag_t *pag; /* per allocation group data */
461 460 xfs_agnumber_t pagno; /* parent (starting) ag number */
  461 + int error;
462 462  
463 463 /*
464 464 * Files of these types need at least one block if length > 0
465 465  
... ... @@ -474,7 +474,9 @@
474 474 if (pagno >= agcount)
475 475 pagno = 0;
476 476 }
  477 +
477 478 ASSERT(pagno < agcount);
  479 +
478 480 /*
479 481 * Loop through allocation groups, looking for one with a little
480 482 * free space in it. Note we don't look for free inodes, exactly.
481 483  
482 484  
483 485  
484 486  
485 487  
486 488  
487 489  
... ... @@ -486,51 +488,45 @@
486 488 flags = XFS_ALLOC_FLAG_TRYLOCK;
487 489 for (;;) {
488 490 pag = xfs_perag_get(mp, agno);
  491 + if (!pag->pagi_inodeok) {
  492 + xfs_ialloc_next_ag(mp);
  493 + goto nextag;
  494 + }
  495 +
489 496 if (!pag->pagi_init) {
490   - if (xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
491   - agbp = NULL;
  497 + error = xfs_ialloc_pagi_init(mp, tp, agno);
  498 + if (error)
492 499 goto nextag;
493   - }
494   - } else
495   - agbp = NULL;
  500 + }
496 501  
497   - if (!pag->pagi_inodeok) {
498   - xfs_ialloc_next_ag(mp);
499   - goto unlock_nextag;
  502 + if (pag->pagi_freecount) {
  503 + xfs_perag_put(pag);
  504 + return agno;
500 505 }
501 506  
  507 + if (!okalloc)
  508 + goto nextag;
  509 +
  510 + if (!pag->pagf_init) {
  511 + error = xfs_alloc_pagf_init(mp, tp, agno, flags);
  512 + if (error)
  513 + goto nextag;
  514 + }
  515 +
502 516 /*
503   - * Is there enough free space for the file plus a block
504   - * of inodes (if we need to allocate some)?
  517 + * Is there enough free space for the file plus a block of
  518 + * inodes? (if we need to allocate some)?
505 519 */
506   - ineed = pag->pagi_freecount ? 0 : XFS_IALLOC_BLOCKS(mp);
507   - if (ineed && !pag->pagf_init) {
508   - if (agbp == NULL &&
509   - xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
510   - agbp = NULL;
511   - goto nextag;
512   - }
513   - (void)xfs_alloc_pagf_init(mp, tp, agno, flags);
  520 + ineed = XFS_IALLOC_BLOCKS(mp);
  521 + longest = pag->pagf_longest;
  522 + if (!longest)
  523 + longest = pag->pagf_flcount > 0;
  524 +
  525 + if (pag->pagf_freeblks >= needspace + ineed &&
  526 + longest >= ineed) {
  527 + xfs_perag_put(pag);
  528 + return agno;
514 529 }
515   - if (!ineed || pag->pagf_init) {
516   - if (ineed && !(longest = pag->pagf_longest))
517   - longest = pag->pagf_flcount > 0;
518   - if (!ineed ||
519   - (pag->pagf_freeblks >= needspace + ineed &&
520   - longest >= ineed &&
521   - okalloc)) {
522   - if (agbp == NULL &&
523   - xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
524   - agbp = NULL;
525   - goto nextag;
526   - }
527   - xfs_perag_put(pag);
528   - return agbp;
529   - }
530   - }
531   -unlock_nextag:
532   - if (agbp)
533   - xfs_trans_brelse(tp, agbp);
534 530 nextag:
535 531 xfs_perag_put(pag);
536 532 /*
537 533  
... ... @@ -538,13 +534,13 @@
538 534 * down.
539 535 */
540 536 if (XFS_FORCED_SHUTDOWN(mp))
541   - return NULL;
  537 + return NULLAGNUMBER;
542 538 agno++;
543 539 if (agno >= agcount)
544 540 agno = 0;
545 541 if (agno == pagno) {
546 542 if (flags == 0)
547   - return NULL;
  543 + return NULLAGNUMBER;
548 544 flags = 0;
549 545 }
550 546 }
551 547  
... ... @@ -901,13 +897,13 @@
901 897 struct xfs_buf **IO_agbp,
902 898 xfs_ino_t *inop)
903 899 {
  900 + struct xfs_mount *mp = tp->t_mountp;
904 901 struct xfs_buf *agbp;
905 902 xfs_agnumber_t agno;
906 903 struct xfs_agi *agi;
907 904 int error;
908 905 int ialloced;
909 906 int noroom = 0;
910   - struct xfs_mount *mp;
911 907 xfs_agnumber_t tagno;
912 908 struct xfs_perag *pag;
913 909  
914 910  
915 911  
... ... @@ -925,20 +921,17 @@
925 921 * We do not have an agbp, so select an initial allocation
926 922 * group for inode allocation.
927 923 */
928   - agbp = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
929   -
930   - /*
931   - * Couldn't find an allocation group satisfying the
932   - * criteria, give up.
933   - */
934   - if (!agbp) {
  924 + agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
  925 + if (agno == NULLAGNUMBER) {
935 926 *inop = NULLFSINO;
936 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 933 agi = XFS_BUF_TO_AGI(agbp);
939 934  
940   - mp = tp->t_mountp;
941   - agno = be32_to_cpu(agi->agi_seqno);
942 935 tagno = agno;
943 936  
944 937 /*