diff options
| -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 | /* |
