|
14 | 14 | #include "xfs_inode.h"
|
15 | 15 | #include "xfs_bmap.h"
|
16 | 16 | #include "xfs_bmap_btree.h"
|
| 17 | +#include "xfs_bmap_util.h" |
17 | 18 | #include "xfs_trans.h"
|
18 | 19 | #include "xfs_trans_space.h"
|
19 | 20 | #include "xfs_icache.h"
|
20 | 21 | #include "xfs_rtalloc.h"
|
21 | 22 | #include "xfs_sb.h"
|
22 | 23 | #include "xfs_rtbitmap.h"
|
| 24 | +#include "xfs_quota.h" |
23 | 25 |
|
24 | 26 | /*
|
25 | 27 | * Read and return the summary information for a given extent size,
|
@@ -1171,7 +1173,7 @@ xfs_growfs_rt(
|
1171 | 1173 | * parameters. The length units are all in realtime extents, as is the
|
1172 | 1174 | * result block number.
|
1173 | 1175 | */
|
1174 |
| -int |
| 1176 | +static int |
1175 | 1177 | xfs_rtallocate_extent(
|
1176 | 1178 | struct xfs_trans *tp,
|
1177 | 1179 | xfs_rtxnum_t start, /* starting rtext number to allocate */
|
@@ -1419,7 +1421,7 @@ xfs_rtunmount_inodes(
|
1419 | 1421 | * of rtextents and the fraction.
|
1420 | 1422 | * The fraction sequence is 0, 1/2, 1/4, 3/4, 1/8, ..., 7/8, 1/16, ...
|
1421 | 1423 | */
|
1422 |
| -int /* error */ |
| 1424 | +static int |
1423 | 1425 | xfs_rtpick_extent(
|
1424 | 1426 | xfs_mount_t *mp, /* file system mount point */
|
1425 | 1427 | xfs_trans_t *tp, /* transaction pointer */
|
@@ -1458,3 +1460,132 @@ xfs_rtpick_extent(
|
1458 | 1460 | *pick = b;
|
1459 | 1461 | return 0;
|
1460 | 1462 | }
|
| 1463 | + |
| 1464 | +int |
| 1465 | +xfs_bmap_rtalloc( |
| 1466 | + struct xfs_bmalloca *ap) |
| 1467 | +{ |
| 1468 | + struct xfs_mount *mp = ap->ip->i_mount; |
| 1469 | + xfs_fileoff_t orig_offset = ap->offset; |
| 1470 | + xfs_rtxnum_t rtx; |
| 1471 | + xfs_rtxlen_t prod = 0; /* product factor for allocators */ |
| 1472 | + xfs_extlen_t mod = 0; /* product factor for allocators */ |
| 1473 | + xfs_rtxlen_t ralen = 0; /* realtime allocation length */ |
| 1474 | + xfs_extlen_t align; /* minimum allocation alignment */ |
| 1475 | + xfs_extlen_t orig_length = ap->length; |
| 1476 | + xfs_extlen_t minlen = mp->m_sb.sb_rextsize; |
| 1477 | + xfs_rtxlen_t raminlen; |
| 1478 | + bool rtlocked = false; |
| 1479 | + bool ignore_locality = false; |
| 1480 | + int error; |
| 1481 | + |
| 1482 | + align = xfs_get_extsz_hint(ap->ip); |
| 1483 | +retry: |
| 1484 | + prod = xfs_extlen_to_rtxlen(mp, align); |
| 1485 | + error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, |
| 1486 | + align, 1, ap->eof, 0, |
| 1487 | + ap->conv, &ap->offset, &ap->length); |
| 1488 | + if (error) |
| 1489 | + return error; |
| 1490 | + ASSERT(ap->length); |
| 1491 | + ASSERT(xfs_extlen_to_rtxmod(mp, ap->length) == 0); |
| 1492 | + |
| 1493 | + /* |
| 1494 | + * If we shifted the file offset downward to satisfy an extent size |
| 1495 | + * hint, increase minlen by that amount so that the allocator won't |
| 1496 | + * give us an allocation that's too short to cover at least one of the |
| 1497 | + * blocks that the caller asked for. |
| 1498 | + */ |
| 1499 | + if (ap->offset != orig_offset) |
| 1500 | + minlen += orig_offset - ap->offset; |
| 1501 | + |
| 1502 | + /* |
| 1503 | + * If the offset & length are not perfectly aligned |
| 1504 | + * then kill prod, it will just get us in trouble. |
| 1505 | + */ |
| 1506 | + div_u64_rem(ap->offset, align, &mod); |
| 1507 | + if (mod || ap->length % align) |
| 1508 | + prod = 1; |
| 1509 | + /* |
| 1510 | + * Set ralen to be the actual requested length in rtextents. |
| 1511 | + * |
| 1512 | + * If the old value was close enough to XFS_BMBT_MAX_EXTLEN that |
| 1513 | + * we rounded up to it, cut it back so it's valid again. |
| 1514 | + * Note that if it's a really large request (bigger than |
| 1515 | + * XFS_BMBT_MAX_EXTLEN), we don't hear about that number, and can't |
| 1516 | + * adjust the starting point to match it. |
| 1517 | + */ |
| 1518 | + ralen = xfs_extlen_to_rtxlen(mp, min(ap->length, XFS_MAX_BMBT_EXTLEN)); |
| 1519 | + |
| 1520 | + /* |
| 1521 | + * Lock out modifications to both the RT bitmap and summary inodes |
| 1522 | + */ |
| 1523 | + if (!rtlocked) { |
| 1524 | + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP); |
| 1525 | + xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); |
| 1526 | + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL|XFS_ILOCK_RTSUM); |
| 1527 | + xfs_trans_ijoin(ap->tp, mp->m_rsumip, XFS_ILOCK_EXCL); |
| 1528 | + rtlocked = true; |
| 1529 | + } |
| 1530 | + |
| 1531 | + /* |
| 1532 | + * If it's an allocation to an empty file at offset 0, |
| 1533 | + * pick an extent that will space things out in the rt area. |
| 1534 | + */ |
| 1535 | + if (ap->eof && ap->offset == 0) { |
| 1536 | + error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); |
| 1537 | + if (error) |
| 1538 | + return error; |
| 1539 | + ap->blkno = xfs_rtx_to_rtb(mp, rtx); |
| 1540 | + } else { |
| 1541 | + ap->blkno = 0; |
| 1542 | + } |
| 1543 | + |
| 1544 | + xfs_bmap_adjacent(ap); |
| 1545 | + |
| 1546 | + /* |
| 1547 | + * Realtime allocation, done through xfs_rtallocate_extent. |
| 1548 | + */ |
| 1549 | + if (ignore_locality) |
| 1550 | + rtx = 0; |
| 1551 | + else |
| 1552 | + rtx = xfs_rtb_to_rtx(mp, ap->blkno); |
| 1553 | + raminlen = max_t(xfs_rtxlen_t, 1, xfs_extlen_to_rtxlen(mp, minlen)); |
| 1554 | + error = xfs_rtallocate_extent(ap->tp, rtx, raminlen, ralen, &ralen, |
| 1555 | + ap->wasdel, prod, &rtx); |
| 1556 | + if (error) |
| 1557 | + return error; |
| 1558 | + |
| 1559 | + if (rtx != NULLRTEXTNO) { |
| 1560 | + ap->blkno = xfs_rtx_to_rtb(mp, rtx); |
| 1561 | + ap->length = xfs_rtxlen_to_extlen(mp, ralen); |
| 1562 | + xfs_bmap_alloc_account(ap); |
| 1563 | + return 0; |
| 1564 | + } |
| 1565 | + |
| 1566 | + if (align > mp->m_sb.sb_rextsize) { |
| 1567 | + /* |
| 1568 | + * We previously enlarged the request length to try to satisfy |
| 1569 | + * an extent size hint. The allocator didn't return anything, |
| 1570 | + * so reset the parameters to the original values and try again |
| 1571 | + * without alignment criteria. |
| 1572 | + */ |
| 1573 | + ap->offset = orig_offset; |
| 1574 | + ap->length = orig_length; |
| 1575 | + minlen = align = mp->m_sb.sb_rextsize; |
| 1576 | + goto retry; |
| 1577 | + } |
| 1578 | + |
| 1579 | + if (!ignore_locality && ap->blkno != 0) { |
| 1580 | + /* |
| 1581 | + * If we can't allocate near a specific rt extent, try again |
| 1582 | + * without locality criteria. |
| 1583 | + */ |
| 1584 | + ignore_locality = true; |
| 1585 | + goto retry; |
| 1586 | + } |
| 1587 | + |
| 1588 | + ap->blkno = NULLFSBLOCK; |
| 1589 | + ap->length = 0; |
| 1590 | + return 0; |
| 1591 | +} |
0 commit comments