diff options
author | Joel Becker <joel.becker@oracle.com> | 2009-08-18 16:52:38 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-02-26 18:41:11 -0500 |
commit | cf2bc809403ae48a4a2bb5cc551d2ec35f2e4a47 (patch) | |
tree | 3e1a0e3b8be59354325b68a169c5e8e4b8f1bf18 /fs/ocfs2/xattr.c | |
parent | 3fc12afa0cea5dc8845487b685165c89934ca1eb (diff) |
ocfs2: Teach ocfs2_xa_loc how to do its own journal work
We're going to want to make sure our buffers get accessed and dirtied
correctly. So have the xa_loc do the work. This includes storing the
inode on ocfs2_xa_loc.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 115 |
1 files changed, 86 insertions, 29 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e0d0fa23a19b..fbec11610223 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -142,6 +142,13 @@ struct ocfs2_xattr_search { | |||
142 | struct ocfs2_xa_loc; | 142 | struct ocfs2_xa_loc; |
143 | struct ocfs2_xa_loc_operations { | 143 | struct ocfs2_xa_loc_operations { |
144 | /* | 144 | /* |
145 | * Journal functions | ||
146 | */ | ||
147 | int (*xlo_journal_access)(handle_t *handle, struct ocfs2_xa_loc *loc, | ||
148 | int type); | ||
149 | void (*xlo_journal_dirty)(handle_t *handle, struct ocfs2_xa_loc *loc); | ||
150 | |||
151 | /* | ||
145 | * Return a pointer to the appropriate buffer in loc->xl_storage | 152 | * Return a pointer to the appropriate buffer in loc->xl_storage |
146 | * at the given offset from loc->xl_header. | 153 | * at the given offset from loc->xl_header. |
147 | */ | 154 | */ |
@@ -186,6 +193,9 @@ struct ocfs2_xa_loc_operations { | |||
186 | * tracking the on-disk structure. | 193 | * tracking the on-disk structure. |
187 | */ | 194 | */ |
188 | struct ocfs2_xa_loc { | 195 | struct ocfs2_xa_loc { |
196 | /* This xattr belongs to this inode */ | ||
197 | struct inode *xl_inode; | ||
198 | |||
189 | /* The ocfs2_xattr_header inside the on-disk storage. Not NULL. */ | 199 | /* The ocfs2_xattr_header inside the on-disk storage. Not NULL. */ |
190 | struct ocfs2_xattr_header *xl_header; | 200 | struct ocfs2_xattr_header *xl_header; |
191 | 201 | ||
@@ -1540,6 +1550,17 @@ static int ocfs2_xa_check_space_helper(int needed_space, int free_start, | |||
1540 | return 0; | 1550 | return 0; |
1541 | } | 1551 | } |
1542 | 1552 | ||
1553 | static int ocfs2_xa_journal_access(handle_t *handle, struct ocfs2_xa_loc *loc, | ||
1554 | int type) | ||
1555 | { | ||
1556 | return loc->xl_ops->xlo_journal_access(handle, loc, type); | ||
1557 | } | ||
1558 | |||
1559 | static void ocfs2_xa_journal_dirty(handle_t *handle, struct ocfs2_xa_loc *loc) | ||
1560 | { | ||
1561 | loc->xl_ops->xlo_journal_dirty(handle, loc); | ||
1562 | } | ||
1563 | |||
1543 | /* Give a pointer into the storage for the given offset */ | 1564 | /* Give a pointer into the storage for the given offset */ |
1544 | static void *ocfs2_xa_offset_pointer(struct ocfs2_xa_loc *loc, int offset) | 1565 | static void *ocfs2_xa_offset_pointer(struct ocfs2_xa_loc *loc, int offset) |
1545 | { | 1566 | { |
@@ -1629,6 +1650,29 @@ static void ocfs2_xa_fill_value_buf(struct ocfs2_xa_loc *loc, | |||
1629 | name_size); | 1650 | name_size); |
1630 | } | 1651 | } |
1631 | 1652 | ||
1653 | static int ocfs2_xa_block_journal_access(handle_t *handle, | ||
1654 | struct ocfs2_xa_loc *loc, int type) | ||
1655 | { | ||
1656 | struct buffer_head *bh = loc->xl_storage; | ||
1657 | ocfs2_journal_access_func access; | ||
1658 | |||
1659 | if (loc->xl_size == (bh->b_size - | ||
1660 | offsetof(struct ocfs2_xattr_block, | ||
1661 | xb_attrs.xb_header))) | ||
1662 | access = ocfs2_journal_access_xb; | ||
1663 | else | ||
1664 | access = ocfs2_journal_access_di; | ||
1665 | return access(handle, INODE_CACHE(loc->xl_inode), bh, type); | ||
1666 | } | ||
1667 | |||
1668 | static void ocfs2_xa_block_journal_dirty(handle_t *handle, | ||
1669 | struct ocfs2_xa_loc *loc) | ||
1670 | { | ||
1671 | struct buffer_head *bh = loc->xl_storage; | ||
1672 | |||
1673 | ocfs2_journal_dirty(handle, bh); | ||
1674 | } | ||
1675 | |||
1632 | static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc, | 1676 | static void *ocfs2_xa_block_offset_pointer(struct ocfs2_xa_loc *loc, |
1633 | int offset) | 1677 | int offset) |
1634 | { | 1678 | { |
@@ -1755,6 +1799,8 @@ static void ocfs2_xa_block_fill_value_buf(struct ocfs2_xa_loc *loc, | |||
1755 | * storage and unindexed ocfs2_xattr_blocks. | 1799 | * storage and unindexed ocfs2_xattr_blocks. |
1756 | */ | 1800 | */ |
1757 | static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = { | 1801 | static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = { |
1802 | .xlo_journal_access = ocfs2_xa_block_journal_access, | ||
1803 | .xlo_journal_dirty = ocfs2_xa_block_journal_dirty, | ||
1758 | .xlo_offset_pointer = ocfs2_xa_block_offset_pointer, | 1804 | .xlo_offset_pointer = ocfs2_xa_block_offset_pointer, |
1759 | .xlo_check_space = ocfs2_xa_block_check_space, | 1805 | .xlo_check_space = ocfs2_xa_block_check_space, |
1760 | .xlo_can_reuse = ocfs2_xa_block_can_reuse, | 1806 | .xlo_can_reuse = ocfs2_xa_block_can_reuse, |
@@ -1765,6 +1811,22 @@ static const struct ocfs2_xa_loc_operations ocfs2_xa_block_loc_ops = { | |||
1765 | .xlo_fill_value_buf = ocfs2_xa_block_fill_value_buf, | 1811 | .xlo_fill_value_buf = ocfs2_xa_block_fill_value_buf, |
1766 | }; | 1812 | }; |
1767 | 1813 | ||
1814 | static int ocfs2_xa_bucket_journal_access(handle_t *handle, | ||
1815 | struct ocfs2_xa_loc *loc, int type) | ||
1816 | { | ||
1817 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | ||
1818 | |||
1819 | return ocfs2_xattr_bucket_journal_access(handle, bucket, type); | ||
1820 | } | ||
1821 | |||
1822 | static void ocfs2_xa_bucket_journal_dirty(handle_t *handle, | ||
1823 | struct ocfs2_xa_loc *loc) | ||
1824 | { | ||
1825 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | ||
1826 | |||
1827 | ocfs2_xattr_bucket_journal_dirty(handle, bucket); | ||
1828 | } | ||
1829 | |||
1768 | static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc, | 1830 | static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc, |
1769 | int offset) | 1831 | int offset) |
1770 | { | 1832 | { |
@@ -1772,8 +1834,8 @@ static void *ocfs2_xa_bucket_offset_pointer(struct ocfs2_xa_loc *loc, | |||
1772 | int block, block_offset; | 1834 | int block, block_offset; |
1773 | 1835 | ||
1774 | /* The header is at the front of the bucket */ | 1836 | /* The header is at the front of the bucket */ |
1775 | block = offset >> bucket->bu_inode->i_sb->s_blocksize_bits; | 1837 | block = offset >> loc->xl_inode->i_sb->s_blocksize_bits; |
1776 | block_offset = offset % bucket->bu_inode->i_sb->s_blocksize; | 1838 | block_offset = offset % loc->xl_inode->i_sb->s_blocksize; |
1777 | 1839 | ||
1778 | return bucket_block(bucket, block) + block_offset; | 1840 | return bucket_block(bucket, block) + block_offset; |
1779 | } | 1841 | } |
@@ -1813,8 +1875,7 @@ static int ocfs2_xa_bucket_check_space(struct ocfs2_xa_loc *loc, | |||
1813 | int free_start = ocfs2_xa_get_free_start(loc); | 1875 | int free_start = ocfs2_xa_get_free_start(loc); |
1814 | int needed_space = ocfs2_xi_entry_usage(xi); | 1876 | int needed_space = ocfs2_xi_entry_usage(xi); |
1815 | int size = namevalue_size_xi(xi); | 1877 | int size = namevalue_size_xi(xi); |
1816 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | 1878 | struct super_block *sb = loc->xl_inode->i_sb; |
1817 | struct super_block *sb = bucket->bu_inode->i_sb; | ||
1818 | 1879 | ||
1819 | /* | 1880 | /* |
1820 | * Bucket storage does not reclaim name+value pairs it cannot | 1881 | * Bucket storage does not reclaim name+value pairs it cannot |
@@ -1896,8 +1957,7 @@ static void ocfs2_xa_bucket_add_namevalue(struct ocfs2_xa_loc *loc, int size) | |||
1896 | { | 1957 | { |
1897 | int free_start = ocfs2_xa_get_free_start(loc); | 1958 | int free_start = ocfs2_xa_get_free_start(loc); |
1898 | struct ocfs2_xattr_header *xh = loc->xl_header; | 1959 | struct ocfs2_xattr_header *xh = loc->xl_header; |
1899 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | 1960 | struct super_block *sb = loc->xl_inode->i_sb; |
1900 | struct super_block *sb = bucket->bu_inode->i_sb; | ||
1901 | int nameval_offset; | 1961 | int nameval_offset; |
1902 | 1962 | ||
1903 | free_start = ocfs2_bucket_align_free_start(sb, free_start, size); | 1963 | free_start = ocfs2_bucket_align_free_start(sb, free_start, size); |
@@ -1912,7 +1972,7 @@ static void ocfs2_xa_bucket_fill_value_buf(struct ocfs2_xa_loc *loc, | |||
1912 | struct ocfs2_xattr_value_buf *vb) | 1972 | struct ocfs2_xattr_value_buf *vb) |
1913 | { | 1973 | { |
1914 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; | 1974 | struct ocfs2_xattr_bucket *bucket = loc->xl_storage; |
1915 | struct super_block *sb = bucket->bu_inode->i_sb; | 1975 | struct super_block *sb = loc->xl_inode->i_sb; |
1916 | int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); | 1976 | int nameval_offset = le16_to_cpu(loc->xl_entry->xe_name_offset); |
1917 | int size = namevalue_size_xe(loc->xl_entry); | 1977 | int size = namevalue_size_xe(loc->xl_entry); |
1918 | int block_offset = nameval_offset >> sb->s_blocksize_bits; | 1978 | int block_offset = nameval_offset >> sb->s_blocksize_bits; |
@@ -1929,6 +1989,8 @@ static void ocfs2_xa_bucket_fill_value_buf(struct ocfs2_xa_loc *loc, | |||
1929 | 1989 | ||
1930 | /* Operations for xattrs stored in buckets. */ | 1990 | /* Operations for xattrs stored in buckets. */ |
1931 | static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = { | 1991 | static const struct ocfs2_xa_loc_operations ocfs2_xa_bucket_loc_ops = { |
1992 | .xlo_journal_access = ocfs2_xa_bucket_journal_access, | ||
1993 | .xlo_journal_dirty = ocfs2_xa_bucket_journal_dirty, | ||
1932 | .xlo_offset_pointer = ocfs2_xa_bucket_offset_pointer, | 1994 | .xlo_offset_pointer = ocfs2_xa_bucket_offset_pointer, |
1933 | .xlo_check_space = ocfs2_xa_bucket_check_space, | 1995 | .xlo_check_space = ocfs2_xa_bucket_check_space, |
1934 | .xlo_can_reuse = ocfs2_xa_bucket_can_reuse, | 1996 | .xlo_can_reuse = ocfs2_xa_bucket_can_reuse, |
@@ -2049,6 +2111,7 @@ static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, | |||
2049 | { | 2111 | { |
2050 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; | 2112 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; |
2051 | 2113 | ||
2114 | loc->xl_inode = inode; | ||
2052 | loc->xl_ops = &ocfs2_xa_block_loc_ops; | 2115 | loc->xl_ops = &ocfs2_xa_block_loc_ops; |
2053 | loc->xl_storage = bh; | 2116 | loc->xl_storage = bh; |
2054 | loc->xl_entry = entry; | 2117 | loc->xl_entry = entry; |
@@ -2065,6 +2128,7 @@ static void ocfs2_init_dinode_xa_loc(struct ocfs2_xa_loc *loc, | |||
2065 | } | 2128 | } |
2066 | 2129 | ||
2067 | static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc, | 2130 | static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc, |
2131 | struct inode *inode, | ||
2068 | struct buffer_head *bh, | 2132 | struct buffer_head *bh, |
2069 | struct ocfs2_xattr_entry *entry) | 2133 | struct ocfs2_xattr_entry *entry) |
2070 | { | 2134 | { |
@@ -2073,6 +2137,7 @@ static void ocfs2_init_xattr_block_xa_loc(struct ocfs2_xa_loc *loc, | |||
2073 | 2137 | ||
2074 | BUG_ON(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED); | 2138 | BUG_ON(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED); |
2075 | 2139 | ||
2140 | loc->xl_inode = inode; | ||
2076 | loc->xl_ops = &ocfs2_xa_block_loc_ops; | 2141 | loc->xl_ops = &ocfs2_xa_block_loc_ops; |
2077 | loc->xl_storage = bh; | 2142 | loc->xl_storage = bh; |
2078 | loc->xl_header = &(xb->xb_attrs.xb_header); | 2143 | loc->xl_header = &(xb->xb_attrs.xb_header); |
@@ -2085,6 +2150,7 @@ static void ocfs2_init_xattr_bucket_xa_loc(struct ocfs2_xa_loc *loc, | |||
2085 | struct ocfs2_xattr_bucket *bucket, | 2150 | struct ocfs2_xattr_bucket *bucket, |
2086 | struct ocfs2_xattr_entry *entry) | 2151 | struct ocfs2_xattr_entry *entry) |
2087 | { | 2152 | { |
2153 | loc->xl_inode = bucket->bu_inode; | ||
2088 | loc->xl_ops = &ocfs2_xa_bucket_loc_ops; | 2154 | loc->xl_ops = &ocfs2_xa_bucket_loc_ops; |
2089 | loc->xl_storage = bucket; | 2155 | loc->xl_storage = bucket; |
2090 | loc->xl_header = bucket_xh(bucket); | 2156 | loc->xl_header = bucket_xh(bucket); |
@@ -2226,21 +2292,18 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
2226 | goto out; | 2292 | goto out; |
2227 | } | 2293 | } |
2228 | 2294 | ||
2229 | if (!(flag & OCFS2_INLINE_XATTR_FL)) { | ||
2230 | ret = vb.vb_access(handle, INODE_CACHE(inode), vb.vb_bh, | ||
2231 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2232 | if (ret) { | ||
2233 | mlog_errno(ret); | ||
2234 | goto out; | ||
2235 | } | ||
2236 | } | ||
2237 | |||
2238 | if (xs->xattr_bh == xs->inode_bh) | 2295 | if (xs->xattr_bh == xs->inode_bh) |
2239 | ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh, | 2296 | ocfs2_init_dinode_xa_loc(&loc, inode, xs->inode_bh, |
2240 | xs->not_found ? NULL : xs->here); | 2297 | xs->not_found ? NULL : xs->here); |
2241 | else | 2298 | else |
2242 | ocfs2_init_xattr_block_xa_loc(&loc, xs->xattr_bh, | 2299 | ocfs2_init_xattr_block_xa_loc(&loc, inode, xs->xattr_bh, |
2243 | xs->not_found ? NULL : xs->here); | 2300 | xs->not_found ? NULL : xs->here); |
2301 | ret = ocfs2_xa_journal_access(handle, &loc, | ||
2302 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
2303 | if (ret) { | ||
2304 | mlog_errno(ret); | ||
2305 | goto out; | ||
2306 | } | ||
2244 | 2307 | ||
2245 | /* | 2308 | /* |
2246 | * Prepare our entry and insert the inline value. This will | 2309 | * Prepare our entry and insert the inline value. This will |
@@ -2258,13 +2321,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
2258 | ocfs2_xa_store_inline_value(&loc, xi); | 2321 | ocfs2_xa_store_inline_value(&loc, xi); |
2259 | xs->here = loc.xl_entry; | 2322 | xs->here = loc.xl_entry; |
2260 | 2323 | ||
2261 | if (!(flag & OCFS2_INLINE_XATTR_FL)) { | 2324 | ocfs2_xa_journal_dirty(handle, &loc); |
2262 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); | ||
2263 | if (ret < 0) { | ||
2264 | mlog_errno(ret); | ||
2265 | goto out; | ||
2266 | } | ||
2267 | } | ||
2268 | 2325 | ||
2269 | if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) && | 2326 | if (!(oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) && |
2270 | (flag & OCFS2_INLINE_XATTR_FL)) { | 2327 | (flag & OCFS2_INLINE_XATTR_FL)) { |
@@ -5325,15 +5382,15 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | |||
5325 | } | 5382 | } |
5326 | } | 5383 | } |
5327 | 5384 | ||
5328 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, | 5385 | ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, |
5329 | OCFS2_JOURNAL_ACCESS_WRITE); | 5386 | xs->not_found ? NULL : xs->here); |
5387 | ret = ocfs2_xa_journal_access(handle, &loc, | ||
5388 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
5330 | if (ret < 0) { | 5389 | if (ret < 0) { |
5331 | mlog_errno(ret); | 5390 | mlog_errno(ret); |
5332 | goto out; | 5391 | goto out; |
5333 | } | 5392 | } |
5334 | 5393 | ||
5335 | ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, | ||
5336 | xs->not_found ? NULL : xs->here); | ||
5337 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash); | 5394 | ret = ocfs2_xa_prepare_entry(&loc, xi, name_hash); |
5338 | if (ret) { | 5395 | if (ret) { |
5339 | if (ret != -ENOSPC) | 5396 | if (ret != -ENOSPC) |
@@ -5345,7 +5402,7 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | |||
5345 | ocfs2_xa_store_inline_value(&loc, xi); | 5402 | ocfs2_xa_store_inline_value(&loc, xi); |
5346 | xs->here = loc.xl_entry; | 5403 | xs->here = loc.xl_entry; |
5347 | 5404 | ||
5348 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); | 5405 | ocfs2_xa_journal_dirty(handle, &loc); |
5349 | 5406 | ||
5350 | out: | 5407 | out: |
5351 | return ret; | 5408 | return ret; |