diff options
author | Joel Becker <joel.becker@oracle.com> | 2009-08-17 15:24:39 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-02-26 18:41:10 -0500 |
commit | 69a3e539d083ac09aec92b8705b8ff2c2e5c810c (patch) | |
tree | 9b3193da2f261e7198c50acfce4fd7593a4b98df /fs/ocfs2/xattr.c | |
parent | 199799a3609f6d5bb231a75c2e702afaac805431 (diff) |
ocfs2: Set the xattr name+value pair in one place
We create two new functions on ocfs2_xa_loc, ocfs2_xa_prepare_entry()
and ocfs2_xa_store_inline_value().
ocfs2_xa_prepare_entry() makes sure that the xl_entry field of
ocfs2_xa_loc is ready to receive an xattr. The entry will point to an
appropriately sized name+value region in storage. If an existing entry
can be reused, it will be. If no entry already exists, it will be
allocated. If there isn't space to allocate it, -ENOSPC will be
returned.
ocfs2_xa_store_inline_value() stores the data that goes into the 'value'
part of the name+value pair. For values that don't fit directly, this
stores the value tree root.
A number of operations are added to ocfs2_xa_loc_operations to support
these functions. This reflects the disparate behaviors of xattr blocks
and buckets.
With these functions, the overlapping ocfs2_xattr_set_entry_local() and
ocfs2_xattr_set_entry_normal() can be replaced with a single call
scheme.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 634 |
1 files changed, 411 insertions, 223 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 064ec6d6c23c..4bf6ec849e19 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -147,11 +147,31 @@ struct ocfs2_xa_loc_operations { | |||
147 | */ | 147 | */ |
148 | void *(*xlo_offset_pointer)(struct ocfs2_xa_loc *loc, int offset); | 148 | void *(*xlo_offset_pointer)(struct ocfs2_xa_loc *loc, int offset); |
149 | 149 | ||
150 | /* Can we reuse the existing entry for the new value? */ | ||
151 | int (*xlo_can_reuse)(struct ocfs2_xa_loc *loc, | ||
152 | struct ocfs2_xattr_info *xi); | ||
153 | |||
154 | /* How much space is needed for the new value? */ | ||
155 | int (*xlo_check_space)(struct ocfs2_xa_loc *loc, | ||
156 | struct ocfs2_xattr_info *xi); | ||
157 | |||
158 | /* | ||
159 | * Return the offset of the first name+value pair. This is | ||
160 | * the start of our downward-filling free space. | ||
161 | */ | ||
162 | int (*xlo_get_free_start)(struct ocfs2_xa_loc *loc); | ||
163 | |||
150 | /* | 164 | /* |
151 | * Remove the name+value at this location. Do whatever is | 165 | * Remove the name+value at this location. Do whatever is |
152 | * appropriate with the remaining name+value pairs. | 166 | * appropriate with the remaining name+value pairs. |
153 | */ | 167 | */ |
154 | void (*xlo_wipe_namevalue)(struct ocfs2_xa_loc *loc); | 168 | void (*xlo_wipe_namevalue)(struct ocfs2_xa_loc *loc); |
169 | |||
170 | /* Fill xl_entry with a new entry */ | ||
171 | void (*xlo_add_entry)(struct ocfs2_xa_loc *loc, u32 name_hash); | ||
172 | |||
173 | /* Add name+value storage to an entry */ | ||
174 | void (*xlo_add_namevalue)(struct ocfs2_xa_loc *loc, int size); | ||
155 | }; | 175 | }; |
156 | 176 | ||
157 | /* | 177 | /* |
@@ -1493,6 +1513,33 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1493 | return ret; | 1513 | return ret; |
1494 | } | 1514 | } |
1495 | 1515 | ||
1516 | static int ocfs2_xa_check_space_helper(int needed_space, int free_start, | ||
1517 | int num_entries) | ||
1518 | { | ||
1519 | int free_space; | ||
1520 | |||
1521 | if (!needed_space) | ||
1522 | return 0; | ||
1523 | |||
1524 | free_space = free_start - | ||
1525 | sizeof(struct ocfs2_xattr_header) - | ||
1526 | (num_entries * sizeof(struct ocfs2_xattr_entry)) - | ||
1527 | OCFS2_XATTR_HEADER_GAP; | ||
1528 | if (free_space < 0) | ||
1529 | return -EIO; | ||
1530 | if (free_space < needed_space) | ||
1531 | return -ENOSPC; | ||
1532 | |||
1533 | return 0; | ||
1534 | } | ||
1535 | |||
1536 | /* Give a pointer into the storage for the given offset */ | ||
1537 | static void *ocfs2_xa_offset_pointer(struct ocfs2_xa_loc *loc, int offset) | ||
1538 | { | ||
1539 | BUG_ON(offset >= loc->xl_size); | ||
1540 | return loc->xl_ops->xlo_offset_pointer(loc, offset); | ||
1541 | } | ||
1542 | |||
1496 | /* | 1543 | /* |
1497 | * Wipe the name+value pair and allow the storage to reclaim it. This | 1544 | * Wipe the name+value pair and allow the storage to reclaim it. This |
1498 | * must be followed by either removal of the entry or a call to | 1545 | * must be followed by either removal of the entry or a call to |
@@ -1503,13 +1550,117 @@ static void ocfs2_xa_wipe_namevalue(struct ocfs2_xa_loc *loc) | |||
1503 | loc->xl_ops->xlo_wipe_namevalue(loc); | 1550 | loc->xl_ops->xlo_wipe_namevalue(loc); |
1504 | } | 1551 | } |
1505 | 1552 | ||
1553 | /* | ||
1554 | * Find lowest offset to a name+value pair. This is the start of our | ||
1555 | * downward-growing free space. | ||
1556 | */ | ||
1557 | static int ocfs2_xa_get_free_start(struct ocfs2_xa_loc *loc) | ||
1558 | { | ||
1559 | return loc->xl_ops->xlo_get_free_start(loc); | ||
1560 | } | ||
1561 | |||
1562 | /* Can we reuse loc->xl_entry for xi? */ | ||
1563 | static int ocfs2_xa_can_reuse_entry(struct ocfs2_xa_loc *loc, | ||
1564 | struct ocfs2_xattr_info *xi) | ||
1565 | { | ||
1566 | return loc->xl_ops->xlo_can_reuse(loc, xi); | ||
1567 | } | ||
1568 | |||
1569 | /* How much free space is needed to set the new value */ | ||
1570 | static int ocfs2_xa_check_space(struct ocfs2_xa_loc *loc, | ||
1571 | struct ocfs2_xattr_info *xi) | ||
1572 | { | ||
1573 | return loc->xl_ops->xlo_check_space(loc, xi); | ||
1574 | } | ||
1575 | |||
1576 | static void ocfs2_xa_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash) | ||
1577 | { | ||
1578 | loc->xl_ops->xlo_add_entry(loc, name_hash); | ||
1579 | loc->xl_entry->xe_name_hash = cpu_to_le32(name_hash); | ||
1580 | /* | ||
1581 | * We can't leave the new entry's xe_name_offset at zero or | ||
1582 | * add_namevalue() will go nuts. We set it to the size of our | ||
1583 | * storage so that it can never be less than any other entry. | ||
1584 | */ | ||
1585 | loc->xl_entry->xe_name_offset = cpu_to_le16(loc->xl_size); | ||
1586 | } | ||
1587 | |||
1588 | static void ocfs2_xa_add_namevalue(struct ocfs2_xa_loc *loc, | ||
1589 | struct ocfs2_xattr_info *xi) | ||
1590 | { | ||
1591 | int size = namevalue_size_xi(xi); | ||
1592 | int nameval_offset; | ||
1593 | char *nameval_buf; | ||
1594 | |||
1595 | loc->xl_ops->xlo_add_namevalue(loc, size); | ||
1596 | loc->xl_entry->xe_value_size = cpu_to_le64(xi->xi_value_len); | ||
1597 | loc->xl_entry->xe_name_len = xi->xi_name_len; | ||
1598 | ocfs2_xattr_set_type(loc->xl_entry, xi->xi_name_index); | ||
1599 | ocfs2_xattr_set_local(loc->xl_entry, | ||
1600 | xi->xi_value_len <= OCFS2_XATTR_INLINE_SIZE); | ||
1601 | |||
1602 | nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); | ||
1603 | nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset); | ||
1604 | memset(nameval_buf, 0, size); | ||
1605 | memcpy(nameval_buf, xi->xi_name, xi->xi_name_len); | ||
1606 | } | ||
1607 | |||
1506 | static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc, | 1608 | static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc, |
1507 | int offset) | 1609 | int offset) |
1508 | { | 1610 | { |
1509 | BUG_ON(offset >= loc->xl_size); | ||
1510 | return (char *)loc->xl_header + offset; | 1611 | return (char *)loc->xl_header + offset; |
1511 | } | 1612 | } |
1512 | 1613 | ||
1614 | static int ocfs2_xa_block_can_reuse(struct ocfs2_xa_loc *loc, | ||
1615 | struct ocfs2_xattr_info *xi) | ||
1616 | { | ||
1617 | /* | ||
1618 | * Block storage is strict. If the sizes aren't exact, we will | ||
1619 | * remove the old one and reinsert the new. | ||
1620 | */ | ||
1621 | return namevalue_size_xe(loc->xl_entry) == | ||
1622 | namevalue_size_xi(xi); | ||
1623 | } | ||
1624 | |||
1625 | static int ocfs2_xa_block_get_free_start(struct ocfs2_xa_loc *loc) | ||
1626 | { | ||
1627 | struct ocfs2_xattr_header *xh = loc->xl_header; | ||
1628 | int i, count = le16_to_cpu(xh->xh_count); | ||
1629 | int offset, free_start = loc->xl_size; | ||
1630 | |||
1631 | for (i = 0; i < count; i++) { | ||
1632 | offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset); | ||
1633 | if (offset < free_start) | ||
1634 | free_start = offset; | ||
1635 | } | ||
1636 | |||
1637 | return free_start; | ||
1638 | } | ||
1639 | |||
1640 | static int ocfs2_xa_block_check_space(struct ocfs2_xa_loc *loc, | ||
1641 | struct ocfs2_xattr_info *xi) | ||
1642 | { | ||
1643 | int count = le16_to_cpu(loc->xl_header->xh_count); | ||
1644 | int free_start = ocfs2_xa_get_free_start(loc); | ||
1645 | int needed_space = ocfs2_xi_entry_usage(xi); | ||
1646 | |||
1647 | /* | ||
1648 | * Block storage will reclaim the original entry before inserting | ||
1649 | * the new value, so we only need the difference. If the new | ||
1650 | * entry is smaller than the old one, we don't need anything. | ||
1651 | */ | ||
1652 | if (loc->xl_entry) { | ||
1653 | /* Don't need space if we're reusing! */ | ||
1654 | if (ocfs2_xa_can_reuse_entry(loc, xi)) | ||
1655 | needed_space = 0; | ||
1656 | else | ||
1657 | needed_space -= ocfs2_xe_entry_usage(loc->xl_entry); | ||
1658 | } | ||
1659 | if (needed_space < 0) | ||
1660 | needed_space = 0; | ||
1661 | return ocfs2_xa_check_space_helper(needed_space, free_start, count); | ||
1662 | } | ||
1663 | |||
1513 | /* | 1664 | /* |
1514 | * Block storage for xattrs keeps the name+value pairs compacted. When | 1665 | * Block storage for xattrs keeps the name+value pairs compacted. When |
1515 | * we remove one, we have to shift any that preceded it towards the end. | 1666 | * we remove one, we have to shift any that preceded it towards the end. |
@@ -1524,13 +1675,7 @@ static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc) | |||
1524 | 1675 | ||
1525 | namevalue_offset = le16_to_cpu(entry->xe_name_offset); | 1676 | namevalue_offset = le16_to_cpu(entry->xe_name_offset); |
1526 | namevalue_size = namevalue_size_xe(entry); | 1677 | namevalue_size = namevalue_size_xe(entry); |
1527 | 1678 | first_namevalue_offset = ocfs2_xa_get_free_start(loc); | |
1528 | for (i = 0, first_namevalue_offset = loc->xl_size; | ||
1529 | i < count; i++) { | ||
1530 | offset = le16_to_cpu(xh->xh_entries[i].xe_name_offset); | ||
1531 | if (offset < first_namevalue_offset) | ||
1532 | first_namevalue_offset = offset; | ||
1533 | } | ||
1534 | 1679 | ||
1535 | /* Shift the name+value pairs */ | 1680 | /* Shift the name+value pairs */ |
1536 | memmove((char *)xh + first_namevalue_offset + namevalue_size, | 1681 | memmove((char *)xh + first_namevalue_offset + namevalue_size, |
@@ -1552,13 +1697,33 @@ static void ocfs2_xa_block_wipe_namevalue(struct ocfs2_xa_loc *loc) | |||
1552 | */ | 1697 | */ |
1553 | } | 1698 | } |
1554 | 1699 | ||
1700 | static void ocfs2_xa_block_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash) | ||
1701 | { | ||
1702 | int count = le16_to_cpu(loc->xl_header->xh_count); | ||
1703 | loc->xl_entry = &(loc->xl_header->xh_entries[count]); | ||
1704 | le16_add_cpu(&loc->xl_header->xh_count, 1); | ||
1705 | memset(loc->xl_entry, 0, sizeof(struct ocfs2_xattr_entry)); | ||
1706 | } | ||
1707 | |||
1708 | static void ocfs2_xa_block_add_namevalue(struct ocfs2_xa_loc *loc, int size) | ||
1709 | { | ||
1710 | int free_start = ocfs2_xa_get_free_start(loc); | ||
1711 | |||
1712 | loc->xl_entry->xe_name_offset = cpu_to_le16(free_start - size); | ||
1713 | } | ||
1714 | |||
1555 | /* | 1715 | /* |
1556 | * Operations for xattrs stored in blocks. This includes inline inode | 1716 | * Operations for xattrs stored in blocks. This includes inline inode |
1557 | * storage and unindexed ocfs2_xattr_blocks. | 1717 | * storage and unindexed ocfs2_xattr_blocks. |
1558 | */ | 1718 | */ |
1559 | static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = { | 1719 | static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = { |
1560 | .xlo_offset_pointer = ocfs2_xa_block_offset_pointer, | 1720 | .xlo_offset_pointer = ocfs2_xa_block_offset_pointer, |
1721 | .xlo_check_space = ocfs2_xa_block_check_space, | ||
1722 | .xlo_can_reuse = ocfs2_xa_block_can_reuse, | ||
1723 | .xlo_get_free_start = ocfs2_xa_block_get_free_start, | ||
1561 | .xlo_wipe_namevalue = ocfs2_xa_block_wipe_namevalue, | 1724 | .xlo_wipe_namevalue = ocfs2_xa_block_wipe_namevalue, |
1725 | .xlo_add_entry = ocfs2_xa_block_add_entry, | ||
1726 | .xlo_add_namevalue = ocfs2_xa_block_add_namevalue, | ||
1562 | }; | 1727 | }; |
1563 | 1728 | ||
1564 | static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc, | 1729 | static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc, |
@@ -1567,8 +1732,6 @@ static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc, | |||
1567 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | 1732 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; |
1568 | int block, block_offset; | 1733 | int block, block_offset; |
1569 | 1734 | ||
1570 | BUG_ON(offset >= OCFS2_XATTR_BUCKET_SIZE); | ||
1571 | |||
1572 | /* The header is at the front of the bucket */ | 1735 | /* The header is at the front of the bucket */ |
1573 | block = offset >> bucket->bu_inode->i_sb->s_blocksize_bits; | 1736 | block = offset >> bucket->bu_inode->i_sb->s_blocksize_bits; |
1574 | block_offset = offset % bucket->bu_inode->i_sb->s_blocksize; | 1737 | block_offset = offset % bucket->bu_inode->i_sb->s_blocksize; |
@@ -1576,16 +1739,145 @@ static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc, | |||
1576 | return bucket_block(bucket, block) + block_offset; | 1739 | return bucket_block(bucket, block) + block_offset; |
1577 | } | 1740 | } |
1578 | 1741 | ||
1742 | static int ocfs2_xa_bucket_can_reuse(struct ocfs2_xa_loc *loc, | ||
1743 | struct ocfs2_xattr_info *xi) | ||
1744 | { | ||
1745 | return namevalue_size_xe(loc->xl_entry) >= | ||
1746 | namevalue_size_xi(xi); | ||
1747 | } | ||
1748 | |||
1749 | static int ocfs2_xa_bucket_get_free_start(struct ocfs2_xa_loc *loc) | ||
1750 | { | ||
1751 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | ||
1752 | return le16_to_cpu(bucket_xh(bucket)->xh_free_start); | ||
1753 | } | ||
1754 | |||
1755 | static int ocfs2_bucket_align_free_start(struct super_block *sb, | ||
1756 | int free_start, int size) | ||
1757 | { | ||
1758 | /* | ||
1759 | * We need to make sure that the name+value pair fits within | ||
1760 | * one block. | ||
1761 | */ | ||
1762 | if (((free_start - size) >> sb->s_blocksize_bits) != | ||
1763 | ((free_start - 1) >> sb->s_blocksize_bits)) | ||
1764 | free_start -= free_start % sb->s_blocksize; | ||
1765 | |||
1766 | return free_start; | ||
1767 | } | ||
1768 | |||
1769 | static int ocfs2_xa_bucket_check_space(struct ocfs2_xa_loc *loc, | ||
1770 | struct ocfs2_xattr_info *xi) | ||
1771 | { | ||
1772 | int rc; | ||
1773 | int count = le16_to_cpu(loc->xl_header->xh_count); | ||
1774 | int free_start = ocfs2_xa_get_free_start(loc); | ||
1775 | int needed_space = ocfs2_xi_entry_usage(xi); | ||
1776 | int size = namevalue_size_xi(xi); | ||
1777 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | ||
1778 | struct super_block *sb = bucket->bu_inode->i_sb; | ||
1779 | |||
1780 | /* | ||
1781 | * Bucket storage does not reclaim name+value pairs it cannot | ||
1782 | * reuse. They live as holes until the bucket fills, and then | ||
1783 | * the bucket is defragmented. However, the bucket can reclaim | ||
1784 | * the ocfs2_xattr_entry. | ||
1785 | */ | ||
1786 | if (loc->xl_entry) { | ||
1787 | /* Don't need space if we're reusing! */ | ||
1788 | if (ocfs2_xa_can_reuse_entry(loc, xi)) | ||
1789 | needed_space = 0; | ||
1790 | else | ||
1791 | needed_space -= sizeof(struct ocfs2_xattr_entry); | ||
1792 | } | ||
1793 | BUG_ON(needed_space < 0); | ||
1794 | |||
1795 | if (free_start < size) { | ||
1796 | if (needed_space) | ||
1797 | return -ENOSPC; | ||
1798 | } else { | ||
1799 | /* | ||
1800 | * First we check if it would fit in the first place. | ||
1801 | * Below, we align the free start to a block. This may | ||
1802 | * slide us below the minimum gap. By checking unaligned | ||
1803 | * first, we avoid that error. | ||
1804 | */ | ||
1805 | rc = ocfs2_xa_check_space_helper(needed_space, free_start, | ||
1806 | count); | ||
1807 | if (rc) | ||
1808 | return rc; | ||
1809 | free_start = ocfs2_bucket_align_free_start(sb, free_start, | ||
1810 | size); | ||
1811 | } | ||
1812 | return ocfs2_xa_check_space_helper(needed_space, free_start, count); | ||
1813 | } | ||
1814 | |||
1579 | static void ocfs2_xa_bucket_wipe_namevalue(struct ocfs2_xa_loc *loc) | 1815 | static void ocfs2_xa_bucket_wipe_namevalue(struct ocfs2_xa_loc *loc) |
1580 | { | 1816 | { |
1581 | le16_add_cpu(&loc->xl_header->xh_name_value_len, | 1817 | le16_add_cpu(&loc->xl_header->xh_name_value_len, |
1582 | -namevalue_size_xe(loc->xl_entry)); | 1818 | -namevalue_size_xe(loc->xl_entry)); |
1583 | } | 1819 | } |
1584 | 1820 | ||
1821 | static void ocfs2_xa_bucket_add_entry(struct ocfs2_xa_loc *loc, u32 name_hash) | ||
1822 | { | ||
1823 | struct ocfs2_xattr_header *xh = loc->xl_header; | ||
1824 | int count = le16_to_cpu(xh->xh_count); | ||
1825 | int low = 0, high = count - 1, tmp; | ||
1826 | struct ocfs2_xattr_entry *tmp_xe; | ||
1827 | |||
1828 | /* | ||
1829 | * We keep buckets sorted by name_hash, so we need to find | ||
1830 | * our insert place. | ||
1831 | */ | ||
1832 | while (low <= high && count) { | ||
1833 | tmp = (low + high) / 2; | ||
1834 | tmp_xe = &xh->xh_entries[tmp]; | ||
1835 | |||
1836 | if (name_hash > le32_to_cpu(tmp_xe->xe_name_hash)) | ||
1837 | low = tmp + 1; | ||
1838 | else if (name_hash < le32_to_cpu(tmp_xe->xe_name_hash)) | ||
1839 | high = tmp - 1; | ||
1840 | else { | ||
1841 | low = tmp; | ||
1842 | break; | ||
1843 | } | ||
1844 | } | ||
1845 | |||
1846 | if (low != count) | ||
1847 | memmove(&xh->xh_entries[low + 1], | ||
1848 | &xh->xh_entries[low], | ||
1849 | ((count - low) * sizeof(struct ocfs2_xattr_entry))); | ||
1850 | |||
1851 | le16_add_cpu(&xh->xh_count, 1); | ||
1852 | loc->xl_entry = &xh->xh_entries[low]; | ||
1853 | memset(loc->xl_entry, 0, sizeof(struct ocfs2_xattr_entry)); | ||
1854 | } | ||
1855 | |||
1856 | static void ocfs2_xa_bucket_add_namevalue(struct ocfs2_xa_loc *loc, int size) | ||
1857 | { | ||
1858 | int free_start = ocfs2_xa_get_free_start(loc); | ||
1859 | struct ocfs2_xattr_header *xh = loc->xl_header; | ||
1860 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | ||
1861 | struct super_block *sb = bucket->bu_inode->i_sb; | ||
1862 | int nameval_offset; | ||
1863 | |||
1864 | free_start = ocfs2_bucket_align_free_start(sb, free_start, size); | ||
1865 | nameval_offset = free_start - size; | ||
1866 | loc->xl_entry->xe_name_offset = cpu_to_le16(nameval_offset); | ||
1867 | xh->xh_free_start = cpu_to_le16(nameval_offset); | ||
1868 | le16_add_cpu(&xh->xh_name_value_len, size); | ||
1869 | |||
1870 | } | ||
1871 | |||
1585 | /* Operations for xattrs stored in buckets. */ | 1872 | /* Operations for xattrs stored in buckets. */ |
1586 | static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = { | 1873 | static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = { |
1587 | .xlo_offset_pointer = ocfs2_xa_bucket_offset_pointer, | 1874 | .xlo_offset_pointer = ocfs2_xa_bucket_offset_pointer, |
1875 | .xlo_check_space = ocfs2_xa_bucket_check_space, | ||
1876 | .xlo_can_reuse = ocfs2_xa_bucket_can_reuse, | ||
1877 | .xlo_get_free_start = ocfs2_xa_bucket_get_free_start, | ||
1588 | .xlo_wipe_namevalue = ocfs2_xa_bucket_wipe_namevalue, | 1878 | .xlo_wipe_namevalue = ocfs2_xa_bucket_wipe_namevalue, |
1879 | .xlo_add_entry = ocfs2_xa_bucket_add_entry, | ||
1880 | .xlo_add_namevalue = ocfs2_xa_bucket_add_namevalue, | ||
1589 | }; | 1881 | }; |
1590 | 1882 | ||
1591 | static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) | 1883 | static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) |
@@ -1615,6 +1907,77 @@ static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) | |||
1615 | } | 1907 | } |
1616 | } | 1908 | } |
1617 | 1909 | ||
1910 | /* | ||
1911 | * Prepares loc->xl_entry to receive the new xattr. This includes | ||
1912 | * properly setting up the name+value pair region. If loc->xl_entry | ||
1913 | * already exists, it will take care of modifying it appropriately. | ||
1914 | * This also includes deleting entries, but don't call this to remove | ||
1915 | * a non-existant entry. That's just a bug. | ||
1916 | * | ||
1917 | * Note that this modifies the data. You did journal_access already, | ||
1918 | * right? | ||
1919 | */ | ||
1920 | static int ocfs2_xa_prepare_entry(struct ocfs2_xa_loc *loc, | ||
1921 | struct ocfs2_xattr_info *xi, | ||
1922 | u32 name_hash) | ||
1923 | { | ||
1924 | int rc = 0; | ||
1925 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); | ||
1926 | char *nameval_buf; | ||
1927 | |||
1928 | if (!xi->xi_value) { | ||
1929 | ocfs2_xa_remove_entry(loc); | ||
1930 | goto out; | ||
1931 | } | ||
1932 | |||
1933 | rc = ocfs2_xa_check_space(loc, xi); | ||
1934 | if (rc) | ||
1935 | goto out; | ||
1936 | |||
1937 | if (loc->xl_entry) { | ||
1938 | if (ocfs2_xa_can_reuse_entry(loc, xi)) { | ||
1939 | nameval_buf = ocfs2_xa_offset_pointer(loc, | ||
1940 | le16_to_cpu(loc->xl_entry->xe_name_offset)); | ||
1941 | memset(nameval_buf + name_size, 0, | ||
1942 | namevalue_size_xe(loc->xl_entry) - name_size); | ||
1943 | loc->xl_entry->xe_value_size = | ||
1944 | cpu_to_le64(xi->xi_value_len); | ||
1945 | goto out; | ||
1946 | } | ||
1947 | |||
1948 | ocfs2_xa_wipe_namevalue(loc); | ||
1949 | } else | ||
1950 | ocfs2_xa_add_entry(loc, name_hash); | ||
1951 | |||
1952 | /* | ||
1953 | * If we get here, we have a blank entry. Fill it. We grow our | ||
1954 | * name+value pair back from the end. | ||
1955 | */ | ||
1956 | ocfs2_xa_add_namevalue(loc, xi); | ||
1957 | |||
1958 | out: | ||
1959 | return rc; | ||
1960 | } | ||
1961 | |||
1962 | /* | ||
1963 | * Store the value portion of the name+value pair. This is either an | ||
1964 | * inline value or the tree root of an external value. | ||
1965 | */ | ||
1966 | static void ocfs2_xa_store_inline_value(struct ocfs2_xa_loc *loc, | ||
1967 | struct ocfs2_xattr_info *xi) | ||
1968 | { | ||
1969 | int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); | ||
1970 | int name_size = OCFS2_XATTR_SIZE(xi->xi_name_len); | ||
1971 | int size = namevalue_size_xi(xi); | ||
1972 | char *nameval_buf; | ||
1973 | |||
1974 | if (!xi->xi_value) | ||
1975 | return; | ||
1976 | |||
1977 | nameval_buf = ocfs2_xa_offset_pointer(loc, nameval_offset); | ||
1978 | memcpy(nameval_buf + name_size, xi->xi_value, size - name_size); | ||
1979 | } | ||
1980 | |||
1618 | static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, | 1981 | static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, |
1619 | struct inode *inode, | 1982 | struct inode *inode, |
1620 | struct buffer_head *bh, | 1983 | struct buffer_head *bh, |
@@ -1665,81 +2028,6 @@ static void ocfs2_init_xattr_bucket_xa_loc(struct ocfs2_xa_loc *loc, | |||
1665 | loc->xl_size = OCFS2_XATTR_BUCKET_SIZE; | 2028 | loc->xl_size = OCFS2_XATTR_BUCKET_SIZE; |
1666 | } | 2029 | } |
1667 | 2030 | ||
1668 | /* | ||
1669 | * ocfs2_xattr_set_entry_local() | ||
1670 | * | ||
1671 | * Set, replace or remove extended attribute in local. | ||
1672 | */ | ||
1673 | static void ocfs2_xattr_set_entry_local(struct inode *inode, | ||
1674 | struct ocfs2_xattr_info *xi, | ||
1675 | struct ocfs2_xattr_search *xs, | ||
1676 | struct ocfs2_xattr_entry *last, | ||
1677 | size_t min_offs) | ||
1678 | { | ||
1679 | struct ocfs2_xa_loc loc; | ||
1680 | |||
1681 | if (xs->xattr_bh == xs->inode_bh) | ||
1682 | ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh, | ||
1683 | xs->not_found ? NULL : xs->here); | ||
1684 | else | ||
1685 | ocfs2_init_xattr_block_xa_loc(&loc, xs->xattr_bh, | ||
1686 | xs->not_found ? NULL : xs->here); | ||
1687 | if (xi->xi_value && xs->not_found) { | ||
1688 | /* Insert the new xattr entry. */ | ||
1689 | le16_add_cpu(&xs->header->xh_count, 1); | ||
1690 | ocfs2_xattr_set_type(last, xi->xi_name_index); | ||
1691 | ocfs2_xattr_set_local(last, 1); | ||
1692 | last->xe_name_len = xi->xi_name_len; | ||
1693 | } else { | ||
1694 | void *first_val; | ||
1695 | void *val; | ||
1696 | size_t offs, size; | ||
1697 | |||
1698 | first_val = xs->base + min_offs; | ||
1699 | offs = le16_to_cpu(xs->here->xe_name_offset); | ||
1700 | val = xs->base + offs; | ||
1701 | |||
1702 | size = namevalue_size_xe(xs->here); | ||
1703 | if (xi->xi_value && (size == namevalue_size_xi(xi))) { | ||
1704 | /* The old and the new value have the | ||
1705 | same size. Just replace the value. */ | ||
1706 | ocfs2_xattr_set_local(xs->here, 1); | ||
1707 | xs->here->xe_value_size = cpu_to_le64(xi->xi_value_len); | ||
1708 | /* Clear value bytes. */ | ||
1709 | memset(val + OCFS2_XATTR_SIZE(xi->xi_name_len), | ||
1710 | 0, | ||
1711 | OCFS2_XATTR_SIZE(xi->xi_value_len)); | ||
1712 | memcpy(val + OCFS2_XATTR_SIZE(xi->xi_name_len), | ||
1713 | xi->xi_value, | ||
1714 | xi->xi_value_len); | ||
1715 | return; | ||
1716 | } | ||
1717 | |||
1718 | if (!xi->xi_value) | ||
1719 | ocfs2_xa_remove_entry(&loc); | ||
1720 | else | ||
1721 | ocfs2_xa_wipe_namevalue(&loc); | ||
1722 | |||
1723 | min_offs += size; | ||
1724 | } | ||
1725 | if (xi->xi_value) { | ||
1726 | /* Insert the new name+value. */ | ||
1727 | size_t size = namevalue_size_xi(xi); | ||
1728 | void *val = xs->base + min_offs - size; | ||
1729 | |||
1730 | xs->here->xe_name_offset = cpu_to_le16(min_offs - size); | ||
1731 | memset(val, 0, size); | ||
1732 | memcpy(val, xi->xi_name, xi->xi_name_len); | ||
1733 | memcpy(val + OCFS2_XATTR_SIZE(xi->xi_name_len), | ||
1734 | xi->xi_value, | ||
1735 | xi->xi_value_len); | ||
1736 | xs->here->xe_value_size = cpu_to_le64(xi->xi_value_len); | ||
1737 | ocfs2_xattr_set_local(xs->here, 1); | ||
1738 | ocfs2_xattr_hash_entry(inode, xs->header, xs->here); | ||
1739 | } | ||
1740 | |||
1741 | return; | ||
1742 | } | ||
1743 | 2031 | ||
1744 | /* | 2032 | /* |
1745 | * ocfs2_xattr_set_entry() | 2033 | * ocfs2_xattr_set_entry() |
@@ -1747,7 +2035,7 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode, | |||
1747 | * Set extended attribute entry into inode or block. | 2035 | * Set extended attribute entry into inode or block. |
1748 | * | 2036 | * |
1749 | * If extended attribute value size > OCFS2_XATTR_INLINE_SIZE, | 2037 | * If extended attribute value size > OCFS2_XATTR_INLINE_SIZE, |
1750 | * We first insert tree root(ocfs2_xattr_value_root) with set_entry_local(), | 2038 | * We first insert tree root(ocfs2_xattr_value_root) like a normal value, |
1751 | * then set value in B tree with set_value_outside(). | 2039 | * then set value in B tree with set_value_outside(). |
1752 | */ | 2040 | */ |
1753 | static int ocfs2_xattr_set_entry(struct inode *inode, | 2041 | static int ocfs2_xattr_set_entry(struct inode *inode, |
@@ -1763,6 +2051,9 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1763 | size_t size_l = 0; | 2051 | size_t size_l = 0; |
1764 | handle_t *handle = ctxt->handle; | 2052 | handle_t *handle = ctxt->handle; |
1765 | int free, i, ret; | 2053 | int free, i, ret; |
2054 | u32 name_hash = ocfs2_xattr_name_hash(inode, xi->xi_name, | ||
2055 | xi->xi_name_len); | ||
2056 | struct ocfs2_xa_loc loc; | ||
1766 | struct ocfs2_xattr_info xi_l = { | 2057 | struct ocfs2_xattr_info xi_l = { |
1767 | .xi_name_index = xi->xi_name_index, | 2058 | .xi_name_index = xi->xi_name_index, |
1768 | .xi_name = xi->xi_name, | 2059 | .xi_name = xi->xi_name, |
@@ -1894,11 +2185,28 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1894 | } | 2185 | } |
1895 | } | 2186 | } |
1896 | 2187 | ||
2188 | if (xs->xattr_bh == xs->inode_bh) | ||
2189 | ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh, | ||
2190 | xs->not_found ? NULL : xs->here); | ||
2191 | else | ||
2192 | ocfs2_init_xattr_block_xa_loc(&loc, xs->xattr_bh, | ||
2193 | xs->not_found ? NULL : xs->here); | ||
2194 | |||
1897 | /* | 2195 | /* |
1898 | * Set value in local, include set tree root in local. | 2196 | * Prepare our entry and insert the inline value. This will |
1899 | * This is the first step for value size >INLINE_SIZE. | 2197 | * be a value tree root for values that are larger than |
2198 | * OCFS2_XATTR_INLINE_SIZE. | ||
1900 | */ | 2199 | */ |
1901 | ocfs2_xattr_set_entry_local(inode, &xi_l, xs, last, min_offs); | 2200 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash); |
2201 | if (ret) { | ||
2202 | if (ret != -ENOSPC) | ||
2203 | mlog_errno(ret); | ||
2204 | goto out; | ||
2205 | } | ||
2206 | /* XXX For now, until we make ocfs2_xa_prepare_entry() primary */ | ||
2207 | BUG_ON(ret == -ENOSPC); | ||
2208 | ocfs2_xa_store_inline_value(&loc, xi); | ||
2209 | xs->here = loc.xl_entry; | ||
1902 | 2210 | ||
1903 | if (!(flag & OCFS2_INLINE_XATTR_FL)) { | 2211 | if (!(flag & OCFS2_INLINE_XATTR_FL)) { |
1904 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); | 2212 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); |
@@ -4939,139 +5247,6 @@ static inline char *ocfs2_xattr_bucket_get_val(struct inode *inode, | |||
4939 | } | 5247 | } |
4940 | 5248 | ||
4941 | /* | 5249 | /* |
4942 | * Handle the normal xattr set, including replace, delete and new. | ||
4943 | * | ||
4944 | * Note: "local" indicates the real data's locality. So we can't | ||
4945 | * just its bucket locality by its length. | ||
4946 | */ | ||
4947 | static void ocfs2_xattr_set_entry_normal(struct inode *inode, | ||
4948 | struct ocfs2_xattr_info *xi, | ||
4949 | struct ocfs2_xattr_search *xs, | ||
4950 | u32 name_hash, | ||
4951 | int local) | ||
4952 | { | ||
4953 | struct ocfs2_xattr_entry *last, *xe; | ||
4954 | struct ocfs2_xattr_header *xh = xs->header; | ||
4955 | u16 count = le16_to_cpu(xh->xh_count), start; | ||
4956 | size_t blocksize = inode->i_sb->s_blocksize; | ||
4957 | char *val; | ||
4958 | size_t offs, size, new_size; | ||
4959 | struct ocfs2_xa_loc loc; | ||
4960 | |||
4961 | ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, | ||
4962 | xs->not_found ? NULL : xs->here); | ||
4963 | last = &xh->xh_entries[count]; | ||
4964 | if (!xs->not_found) { | ||
4965 | xe = xs->here; | ||
4966 | offs = le16_to_cpu(xe->xe_name_offset); | ||
4967 | size = namevalue_size_xe(xe); | ||
4968 | |||
4969 | /* | ||
4970 | * If the new value will be stored outside, xi->xi_value has | ||
4971 | * been initalized as an empty ocfs2_xattr_value_root, and | ||
4972 | * the same goes with xi->xi_value_len, so we can set | ||
4973 | * new_size safely here. | ||
4974 | * See ocfs2_xattr_set_in_bucket. | ||
4975 | */ | ||
4976 | new_size = namevalue_size_xi(xi); | ||
4977 | |||
4978 | if (xi->xi_value) { | ||
4979 | ocfs2_xa_wipe_namevalue(&loc); | ||
4980 | if (new_size > size) | ||
4981 | goto set_new_name_value; | ||
4982 | |||
4983 | /* Now replace the old value with new one. */ | ||
4984 | if (local) | ||
4985 | xe->xe_value_size = | ||
4986 | cpu_to_le64(xi->xi_value_len); | ||
4987 | else | ||
4988 | xe->xe_value_size = 0; | ||
4989 | |||
4990 | val = ocfs2_xattr_bucket_get_val(inode, | ||
4991 | xs->bucket, offs); | ||
4992 | memset(val + OCFS2_XATTR_SIZE(xi->xi_name_len), 0, | ||
4993 | size - OCFS2_XATTR_SIZE(xi->xi_name_len)); | ||
4994 | if (OCFS2_XATTR_SIZE(xi->xi_value_len) > 0) | ||
4995 | memcpy(val + OCFS2_XATTR_SIZE(xi->xi_name_len), | ||
4996 | xi->xi_value, xi->xi_value_len); | ||
4997 | |||
4998 | le16_add_cpu(&xh->xh_name_value_len, new_size); | ||
4999 | ocfs2_xattr_set_local(xe, local); | ||
5000 | return; | ||
5001 | } else { | ||
5002 | ocfs2_xa_remove_entry(&loc); | ||
5003 | if (!xh->xh_count) | ||
5004 | xh->xh_free_start = | ||
5005 | cpu_to_le16(OCFS2_XATTR_BUCKET_SIZE); | ||
5006 | |||
5007 | return; | ||
5008 | } | ||
5009 | } else { | ||
5010 | /* find a new entry for insert. */ | ||
5011 | int low = 0, high = count - 1, tmp; | ||
5012 | struct ocfs2_xattr_entry *tmp_xe; | ||
5013 | |||
5014 | while (low <= high && count) { | ||
5015 | tmp = (low + high) / 2; | ||
5016 | tmp_xe = &xh->xh_entries[tmp]; | ||
5017 | |||
5018 | if (name_hash > le32_to_cpu(tmp_xe->xe_name_hash)) | ||
5019 | low = tmp + 1; | ||
5020 | else if (name_hash < | ||
5021 | le32_to_cpu(tmp_xe->xe_name_hash)) | ||
5022 | high = tmp - 1; | ||
5023 | else { | ||
5024 | low = tmp; | ||
5025 | break; | ||
5026 | } | ||
5027 | } | ||
5028 | |||
5029 | xe = &xh->xh_entries[low]; | ||
5030 | if (low != count) | ||
5031 | memmove(xe + 1, xe, (void *)last - (void *)xe); | ||
5032 | |||
5033 | le16_add_cpu(&xh->xh_count, 1); | ||
5034 | memset(xe, 0, sizeof(struct ocfs2_xattr_entry)); | ||
5035 | xe->xe_name_hash = cpu_to_le32(name_hash); | ||
5036 | xe->xe_name_len = xi->xi_name_len; | ||
5037 | ocfs2_xattr_set_type(xe, xi->xi_name_index); | ||
5038 | } | ||
5039 | |||
5040 | set_new_name_value: | ||
5041 | /* Insert the new name+value. */ | ||
5042 | size = namevalue_size_xi(xi); | ||
5043 | |||
5044 | /* | ||
5045 | * We must make sure that the name/value pair | ||
5046 | * exists in the same block. | ||
5047 | */ | ||
5048 | offs = le16_to_cpu(xh->xh_free_start); | ||
5049 | start = offs - size; | ||
5050 | |||
5051 | if (start >> inode->i_sb->s_blocksize_bits != | ||
5052 | (offs - 1) >> inode->i_sb->s_blocksize_bits) { | ||
5053 | offs = offs - offs % blocksize; | ||
5054 | xh->xh_free_start = cpu_to_le16(offs); | ||
5055 | } | ||
5056 | |||
5057 | val = ocfs2_xattr_bucket_get_val(inode, xs->bucket, offs - size); | ||
5058 | xe->xe_name_offset = cpu_to_le16(offs - size); | ||
5059 | |||
5060 | memset(val, 0, size); | ||
5061 | memcpy(val, xi->xi_name, xi->xi_name_len); | ||
5062 | memcpy(val + OCFS2_XATTR_SIZE(xi->xi_name_len), xi->xi_value, | ||
5063 | xi->xi_value_len); | ||
5064 | |||
5065 | xe->xe_value_size = cpu_to_le64(xi->xi_value_len); | ||
5066 | ocfs2_xattr_set_local(xe, local); | ||
5067 | xs->here = xe; | ||
5068 | le16_add_cpu(&xh->xh_free_start, -size); | ||
5069 | le16_add_cpu(&xh->xh_name_value_len, size); | ||
5070 | |||
5071 | return; | ||
5072 | } | ||
5073 | |||
5074 | /* | ||
5075 | * Set the xattr entry in the specified bucket. | 5250 | * Set the xattr entry in the specified bucket. |
5076 | * The bucket is indicated by xs->bucket and it should have the enough | 5251 | * The bucket is indicated by xs->bucket and it should have the enough |
5077 | * space for the xattr insertion. | 5252 | * space for the xattr insertion. |
@@ -5085,6 +5260,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | |||
5085 | { | 5260 | { |
5086 | int ret; | 5261 | int ret; |
5087 | u64 blkno; | 5262 | u64 blkno; |
5263 | struct ocfs2_xa_loc loc; | ||
5088 | 5264 | ||
5089 | mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n", | 5265 | mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n", |
5090 | (unsigned long)xi->xi_value_len, xi->xi_name_index, | 5266 | (unsigned long)xi->xi_value_len, xi->xi_name_index, |
@@ -5107,7 +5283,19 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | |||
5107 | goto out; | 5283 | goto out; |
5108 | } | 5284 | } |
5109 | 5285 | ||
5110 | ocfs2_xattr_set_entry_normal(inode, xi, xs, name_hash, local); | 5286 | ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, |
5287 | xs->not_found ? NULL : xs->here); | ||
5288 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash); | ||
5289 | if (ret) { | ||
5290 | if (ret != -ENOSPC) | ||
5291 | mlog_errno(ret); | ||
5292 | goto out; | ||
5293 | } | ||
5294 | /* XXX For now, until we make ocfs2_xa_prepare_entry() primary */ | ||
5295 | BUG_ON(ret == -ENOSPC); | ||
5296 | ocfs2_xa_store_inline_value(&loc, xi); | ||
5297 | xs->here = loc.xl_entry; | ||
5298 | |||
5111 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); | 5299 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); |
5112 | 5300 | ||
5113 | out: | 5301 | out: |