diff options
author | Jiri Kosina <jkosina@suse.cz> | 2011-04-26 04:22:15 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-04-26 04:22:59 -0400 |
commit | 07f9479a40cc778bc1462ada11f95b01360ae4ff (patch) | |
tree | 0676cf38df3844004bb3ebfd99dfa67a4a8998f5 /fs/xfs/xfs_alloc.c | |
parent | 9d5e6bdb3013acfb311ab407eeca0b6a6a3dedbf (diff) | |
parent | cd2e49e90f1cae7726c9a2c54488d881d7f1cd1c (diff) |
Merge branch 'master' into for-next
Fast-forwarded to current state of Linus' tree as there are patches to be
applied for files that didn't exist on the old branch.
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/xfs_alloc.c | 188 |
1 files changed, 104 insertions, 84 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index f3227984a9bf..27d64d752eab 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -147,10 +147,9 @@ xfs_alloc_get_rec( | |||
147 | */ | 147 | */ |
148 | STATIC void | 148 | STATIC void |
149 | xfs_alloc_compute_aligned( | 149 | xfs_alloc_compute_aligned( |
150 | xfs_alloc_arg_t *args, /* allocation argument structure */ | ||
150 | xfs_agblock_t foundbno, /* starting block in found extent */ | 151 | xfs_agblock_t foundbno, /* starting block in found extent */ |
151 | xfs_extlen_t foundlen, /* length in found extent */ | 152 | xfs_extlen_t foundlen, /* length in found extent */ |
152 | xfs_extlen_t alignment, /* alignment for allocation */ | ||
153 | xfs_extlen_t minlen, /* minimum length for allocation */ | ||
154 | xfs_agblock_t *resbno, /* result block number */ | 153 | xfs_agblock_t *resbno, /* result block number */ |
155 | xfs_extlen_t *reslen) /* result length */ | 154 | xfs_extlen_t *reslen) /* result length */ |
156 | { | 155 | { |
@@ -158,8 +157,8 @@ xfs_alloc_compute_aligned( | |||
158 | xfs_extlen_t diff; | 157 | xfs_extlen_t diff; |
159 | xfs_extlen_t len; | 158 | xfs_extlen_t len; |
160 | 159 | ||
161 | if (alignment > 1 && foundlen >= minlen) { | 160 | if (args->alignment > 1 && foundlen >= args->minlen) { |
162 | bno = roundup(foundbno, alignment); | 161 | bno = roundup(foundbno, args->alignment); |
163 | diff = bno - foundbno; | 162 | diff = bno - foundbno; |
164 | len = diff >= foundlen ? 0 : foundlen - diff; | 163 | len = diff >= foundlen ? 0 : foundlen - diff; |
165 | } else { | 164 | } else { |
@@ -464,6 +463,27 @@ xfs_alloc_read_agfl( | |||
464 | return 0; | 463 | return 0; |
465 | } | 464 | } |
466 | 465 | ||
466 | STATIC int | ||
467 | xfs_alloc_update_counters( | ||
468 | struct xfs_trans *tp, | ||
469 | struct xfs_perag *pag, | ||
470 | struct xfs_buf *agbp, | ||
471 | long len) | ||
472 | { | ||
473 | struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); | ||
474 | |||
475 | pag->pagf_freeblks += len; | ||
476 | be32_add_cpu(&agf->agf_freeblks, len); | ||
477 | |||
478 | xfs_trans_agblocks_delta(tp, len); | ||
479 | if (unlikely(be32_to_cpu(agf->agf_freeblks) > | ||
480 | be32_to_cpu(agf->agf_length))) | ||
481 | return EFSCORRUPTED; | ||
482 | |||
483 | xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); | ||
484 | return 0; | ||
485 | } | ||
486 | |||
467 | /* | 487 | /* |
468 | * Allocation group level functions. | 488 | * Allocation group level functions. |
469 | */ | 489 | */ |
@@ -505,49 +525,44 @@ xfs_alloc_ag_vextent( | |||
505 | ASSERT(0); | 525 | ASSERT(0); |
506 | /* NOTREACHED */ | 526 | /* NOTREACHED */ |
507 | } | 527 | } |
508 | if (error) | 528 | |
529 | if (error || args->agbno == NULLAGBLOCK) | ||
509 | return error; | 530 | return error; |
510 | /* | ||
511 | * If the allocation worked, need to change the agf structure | ||
512 | * (and log it), and the superblock. | ||
513 | */ | ||
514 | if (args->agbno != NULLAGBLOCK) { | ||
515 | xfs_agf_t *agf; /* allocation group freelist header */ | ||
516 | long slen = (long)args->len; | ||
517 | 531 | ||
518 | ASSERT(args->len >= args->minlen && args->len <= args->maxlen); | 532 | ASSERT(args->len >= args->minlen); |
519 | ASSERT(!(args->wasfromfl) || !args->isfl); | 533 | ASSERT(args->len <= args->maxlen); |
520 | ASSERT(args->agbno % args->alignment == 0); | 534 | ASSERT(!args->wasfromfl || !args->isfl); |
521 | if (!(args->wasfromfl)) { | 535 | ASSERT(args->agbno % args->alignment == 0); |
522 | 536 | ||
523 | agf = XFS_BUF_TO_AGF(args->agbp); | 537 | if (!args->wasfromfl) { |
524 | be32_add_cpu(&agf->agf_freeblks, -(args->len)); | 538 | error = xfs_alloc_update_counters(args->tp, args->pag, |
525 | xfs_trans_agblocks_delta(args->tp, | 539 | args->agbp, |
526 | -((long)(args->len))); | 540 | -((long)(args->len))); |
527 | args->pag->pagf_freeblks -= args->len; | 541 | if (error) |
528 | ASSERT(be32_to_cpu(agf->agf_freeblks) <= | 542 | return error; |
529 | be32_to_cpu(agf->agf_length)); | 543 | |
530 | xfs_alloc_log_agf(args->tp, args->agbp, | 544 | /* |
531 | XFS_AGF_FREEBLKS); | 545 | * Search the busylist for these blocks and mark the |
532 | /* | 546 | * transaction as synchronous if blocks are found. This |
533 | * Search the busylist for these blocks and mark the | 547 | * avoids the need to block due to a synchronous log |
534 | * transaction as synchronous if blocks are found. This | 548 | * force to ensure correct ordering as the synchronous |
535 | * avoids the need to block due to a synchronous log | 549 | * transaction will guarantee that for us. |
536 | * force to ensure correct ordering as the synchronous | 550 | */ |
537 | * transaction will guarantee that for us. | 551 | if (xfs_alloc_busy_search(args->mp, args->agno, |
538 | */ | 552 | args->agbno, args->len)) |
539 | if (xfs_alloc_busy_search(args->mp, args->agno, | 553 | xfs_trans_set_sync(args->tp); |
540 | args->agbno, args->len)) | ||
541 | xfs_trans_set_sync(args->tp); | ||
542 | } | ||
543 | if (!args->isfl) | ||
544 | xfs_trans_mod_sb(args->tp, | ||
545 | args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : | ||
546 | XFS_TRANS_SB_FDBLOCKS, -slen); | ||
547 | XFS_STATS_INC(xs_allocx); | ||
548 | XFS_STATS_ADD(xs_allocb, args->len); | ||
549 | } | 554 | } |
550 | return 0; | 555 | |
556 | if (!args->isfl) { | ||
557 | xfs_trans_mod_sb(args->tp, args->wasdel ? | ||
558 | XFS_TRANS_SB_RES_FDBLOCKS : | ||
559 | XFS_TRANS_SB_FDBLOCKS, | ||
560 | -((long)(args->len))); | ||
561 | } | ||
562 | |||
563 | XFS_STATS_INC(xs_allocx); | ||
564 | XFS_STATS_ADD(xs_allocb, args->len); | ||
565 | return error; | ||
551 | } | 566 | } |
552 | 567 | ||
553 | /* | 568 | /* |
@@ -693,8 +708,7 @@ xfs_alloc_find_best_extent( | |||
693 | if (error) | 708 | if (error) |
694 | goto error0; | 709 | goto error0; |
695 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 710 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
696 | xfs_alloc_compute_aligned(*sbno, *slen, args->alignment, | 711 | xfs_alloc_compute_aligned(args, *sbno, *slen, &bno, slena); |
697 | args->minlen, &bno, slena); | ||
698 | 712 | ||
699 | /* | 713 | /* |
700 | * The good extent is closer than this one. | 714 | * The good extent is closer than this one. |
@@ -866,8 +880,8 @@ xfs_alloc_ag_vextent_near( | |||
866 | if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) | 880 | if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) |
867 | goto error0; | 881 | goto error0; |
868 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 882 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
869 | xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, | 883 | xfs_alloc_compute_aligned(args, ltbno, ltlen, |
870 | args->minlen, <bnoa, <lena); | 884 | <bnoa, <lena); |
871 | if (ltlena < args->minlen) | 885 | if (ltlena < args->minlen) |
872 | continue; | 886 | continue; |
873 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); | 887 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); |
@@ -987,8 +1001,8 @@ xfs_alloc_ag_vextent_near( | |||
987 | if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) | 1001 | if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) |
988 | goto error0; | 1002 | goto error0; |
989 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1003 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
990 | xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, | 1004 | xfs_alloc_compute_aligned(args, ltbno, ltlen, |
991 | args->minlen, <bnoa, <lena); | 1005 | <bnoa, <lena); |
992 | if (ltlena >= args->minlen) | 1006 | if (ltlena >= args->minlen) |
993 | break; | 1007 | break; |
994 | if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) | 1008 | if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) |
@@ -1003,8 +1017,8 @@ xfs_alloc_ag_vextent_near( | |||
1003 | if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) | 1017 | if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) |
1004 | goto error0; | 1018 | goto error0; |
1005 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1019 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1006 | xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment, | 1020 | xfs_alloc_compute_aligned(args, gtbno, gtlen, |
1007 | args->minlen, >bnoa, >lena); | 1021 | >bnoa, >lena); |
1008 | if (gtlena >= args->minlen) | 1022 | if (gtlena >= args->minlen) |
1009 | break; | 1023 | break; |
1010 | if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) | 1024 | if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) |
@@ -1183,8 +1197,7 @@ xfs_alloc_ag_vextent_size( | |||
1183 | * once aligned; if not, we search left for something better. | 1197 | * once aligned; if not, we search left for something better. |
1184 | * This can't happen in the second case above. | 1198 | * This can't happen in the second case above. |
1185 | */ | 1199 | */ |
1186 | xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen, | 1200 | xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen); |
1187 | &rbno, &rlen); | ||
1188 | rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); | 1201 | rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); |
1189 | XFS_WANT_CORRUPTED_GOTO(rlen == 0 || | 1202 | XFS_WANT_CORRUPTED_GOTO(rlen == 0 || |
1190 | (rlen <= flen && rbno + rlen <= fbno + flen), error0); | 1203 | (rlen <= flen && rbno + rlen <= fbno + flen), error0); |
@@ -1209,8 +1222,8 @@ xfs_alloc_ag_vextent_size( | |||
1209 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1222 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1210 | if (flen < bestrlen) | 1223 | if (flen < bestrlen) |
1211 | break; | 1224 | break; |
1212 | xfs_alloc_compute_aligned(fbno, flen, args->alignment, | 1225 | xfs_alloc_compute_aligned(args, fbno, flen, |
1213 | args->minlen, &rbno, &rlen); | 1226 | &rbno, &rlen); |
1214 | rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); | 1227 | rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); |
1215 | XFS_WANT_CORRUPTED_GOTO(rlen == 0 || | 1228 | XFS_WANT_CORRUPTED_GOTO(rlen == 0 || |
1216 | (rlen <= flen && rbno + rlen <= fbno + flen), | 1229 | (rlen <= flen && rbno + rlen <= fbno + flen), |
@@ -1388,6 +1401,7 @@ xfs_free_ag_extent( | |||
1388 | xfs_mount_t *mp; /* mount point struct for filesystem */ | 1401 | xfs_mount_t *mp; /* mount point struct for filesystem */ |
1389 | xfs_agblock_t nbno; /* new starting block of freespace */ | 1402 | xfs_agblock_t nbno; /* new starting block of freespace */ |
1390 | xfs_extlen_t nlen; /* new length of freespace */ | 1403 | xfs_extlen_t nlen; /* new length of freespace */ |
1404 | xfs_perag_t *pag; /* per allocation group data */ | ||
1391 | 1405 | ||
1392 | mp = tp->t_mountp; | 1406 | mp = tp->t_mountp; |
1393 | /* | 1407 | /* |
@@ -1586,30 +1600,20 @@ xfs_free_ag_extent( | |||
1586 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1600 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1587 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); | 1601 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
1588 | cnt_cur = NULL; | 1602 | cnt_cur = NULL; |
1603 | |||
1589 | /* | 1604 | /* |
1590 | * Update the freespace totals in the ag and superblock. | 1605 | * Update the freespace totals in the ag and superblock. |
1591 | */ | 1606 | */ |
1592 | { | 1607 | pag = xfs_perag_get(mp, agno); |
1593 | xfs_agf_t *agf; | 1608 | error = xfs_alloc_update_counters(tp, pag, agbp, len); |
1594 | xfs_perag_t *pag; /* per allocation group data */ | 1609 | xfs_perag_put(pag); |
1595 | 1610 | if (error) | |
1596 | pag = xfs_perag_get(mp, agno); | 1611 | goto error0; |
1597 | pag->pagf_freeblks += len; | 1612 | |
1598 | xfs_perag_put(pag); | 1613 | if (!isfl) |
1599 | 1614 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); | |
1600 | agf = XFS_BUF_TO_AGF(agbp); | 1615 | XFS_STATS_INC(xs_freex); |
1601 | be32_add_cpu(&agf->agf_freeblks, len); | 1616 | XFS_STATS_ADD(xs_freeb, len); |
1602 | xfs_trans_agblocks_delta(tp, len); | ||
1603 | XFS_WANT_CORRUPTED_GOTO( | ||
1604 | be32_to_cpu(agf->agf_freeblks) <= | ||
1605 | be32_to_cpu(agf->agf_length), | ||
1606 | error0); | ||
1607 | xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); | ||
1608 | if (!isfl) | ||
1609 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); | ||
1610 | XFS_STATS_INC(xs_freex); | ||
1611 | XFS_STATS_ADD(xs_freeb, len); | ||
1612 | } | ||
1613 | 1617 | ||
1614 | trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); | 1618 | trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); |
1615 | 1619 | ||
@@ -2391,17 +2395,33 @@ xfs_free_extent( | |||
2391 | memset(&args, 0, sizeof(xfs_alloc_arg_t)); | 2395 | memset(&args, 0, sizeof(xfs_alloc_arg_t)); |
2392 | args.tp = tp; | 2396 | args.tp = tp; |
2393 | args.mp = tp->t_mountp; | 2397 | args.mp = tp->t_mountp; |
2398 | |||
2399 | /* | ||
2400 | * validate that the block number is legal - the enables us to detect | ||
2401 | * and handle a silent filesystem corruption rather than crashing. | ||
2402 | */ | ||
2394 | args.agno = XFS_FSB_TO_AGNO(args.mp, bno); | 2403 | args.agno = XFS_FSB_TO_AGNO(args.mp, bno); |
2395 | ASSERT(args.agno < args.mp->m_sb.sb_agcount); | 2404 | if (args.agno >= args.mp->m_sb.sb_agcount) |
2405 | return EFSCORRUPTED; | ||
2406 | |||
2396 | args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); | 2407 | args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); |
2408 | if (args.agbno >= args.mp->m_sb.sb_agblocks) | ||
2409 | return EFSCORRUPTED; | ||
2410 | |||
2397 | args.pag = xfs_perag_get(args.mp, args.agno); | 2411 | args.pag = xfs_perag_get(args.mp, args.agno); |
2398 | if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) | 2412 | ASSERT(args.pag); |
2413 | |||
2414 | error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); | ||
2415 | if (error) | ||
2399 | goto error0; | 2416 | goto error0; |
2400 | #ifdef DEBUG | 2417 | |
2401 | ASSERT(args.agbp != NULL); | 2418 | /* validate the extent size is legal now we have the agf locked */ |
2402 | ASSERT((args.agbno + len) <= | 2419 | if (args.agbno + len > |
2403 | be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)); | 2420 | be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) { |
2404 | #endif | 2421 | error = EFSCORRUPTED; |
2422 | goto error0; | ||
2423 | } | ||
2424 | |||
2405 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); | 2425 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); |
2406 | error0: | 2426 | error0: |
2407 | xfs_perag_put(args.pag); | 2427 | xfs_perag_put(args.pag); |