aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2009-08-17 23:43:59 -0400
committerJoel Becker <joel.becker@oracle.com>2009-09-22 23:09:45 -0400
commitce9c5a54c0f06b0efb4db8720a0616cc6aa0e5b2 (patch)
tree617a8f4eb0d30c71691f5e786417a32c1c95cecb
parent2999d12f4d5529b282ce201b21444590c3f9f723 (diff)
ocfs2: Modify removing xattr process for refcount.
The old xattr value remove is quite simple, it just erase the tree and free the clusters. But as we have added refcount support, The process is a little complicated. We have to lock the refcount tree at the beginning, what's more, we may split the refcount tree in some cases, so meta/credits are needed. Signed-off-by: Tao Ma <tao.ma@oracle.com>
-rw-r--r--fs/ocfs2/xattr.c190
1 files changed, 154 insertions, 36 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 661ed9b85dbf..8d1a0abc105c 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -199,6 +199,11 @@ static int ocfs2_prepare_refcount_xattr(struct inode *inode,
199 struct ocfs2_refcount_tree **ref_tree, 199 struct ocfs2_refcount_tree **ref_tree,
200 int *meta_need, 200 int *meta_need,
201 int *credits); 201 int *credits);
202static int ocfs2_get_xattr_tree_value_root(struct super_block *sb,
203 struct ocfs2_xattr_bucket *bucket,
204 int offset,
205 struct ocfs2_xattr_value_root **xv,
206 struct buffer_head **bh);
202 207
203static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb) 208static inline u16 ocfs2_xattr_buckets_per_cluster(struct ocfs2_super *osb)
204{ 209{
@@ -1752,51 +1757,112 @@ out:
1752 return ret; 1757 return ret;
1753} 1758}
1754 1759
1760/*
1761 * In xattr remove, if it is stored outside and refcounted, we may have
1762 * the chance to split the refcount tree. So need the allocators.
1763 */
1764static int ocfs2_lock_xattr_remove_allocators(struct inode *inode,
1765 struct ocfs2_xattr_value_root *xv,
1766 struct ocfs2_caching_info *ref_ci,
1767 struct buffer_head *ref_root_bh,
1768 struct ocfs2_alloc_context **meta_ac,
1769 int *ref_credits)
1770{
1771 int ret, meta_add = 0;
1772 u32 p_cluster, num_clusters;
1773 unsigned int ext_flags;
1774
1775 *ref_credits = 0;
1776 ret = ocfs2_xattr_get_clusters(inode, 0, &p_cluster,
1777 &num_clusters,
1778 &xv->xr_list,
1779 &ext_flags);
1780 if (ret) {
1781 mlog_errno(ret);
1782 goto out;
1783 }
1784
1785 if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
1786 goto out;
1787
1788 ret = ocfs2_refcounted_xattr_delete_need(inode, ref_ci,
1789 ref_root_bh, xv,
1790 &meta_add, ref_credits);
1791 if (ret) {
1792 mlog_errno(ret);
1793 goto out;
1794 }
1795
1796 ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(inode->i_sb),
1797 meta_add, meta_ac);
1798 if (ret)
1799 mlog_errno(ret);
1800
1801out:
1802 return ret;
1803}
1804
1755static int ocfs2_remove_value_outside(struct inode*inode, 1805static int ocfs2_remove_value_outside(struct inode*inode,
1756 struct ocfs2_xattr_value_buf *vb, 1806 struct ocfs2_xattr_value_buf *vb,
1757 struct ocfs2_xattr_header *header) 1807 struct ocfs2_xattr_header *header,
1808 struct ocfs2_caching_info *ref_ci,
1809 struct buffer_head *ref_root_bh)
1758{ 1810{
1759 int ret = 0, i; 1811 int ret = 0, i, ref_credits;
1760 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 1812 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1761 struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, }; 1813 struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, };
1814 void *val;
1762 1815
1763 ocfs2_init_dealloc_ctxt(&ctxt.dealloc); 1816 ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
1764 1817
1765 ctxt.handle = ocfs2_start_trans(osb,
1766 ocfs2_remove_extent_credits(osb->sb));
1767 if (IS_ERR(ctxt.handle)) {
1768 ret = PTR_ERR(ctxt.handle);
1769 mlog_errno(ret);
1770 goto out;
1771 }
1772
1773 for (i = 0; i < le16_to_cpu(header->xh_count); i++) { 1818 for (i = 0; i < le16_to_cpu(header->xh_count); i++) {
1774 struct ocfs2_xattr_entry *entry = &header->xh_entries[i]; 1819 struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
1775 1820
1776 if (!ocfs2_xattr_is_local(entry)) { 1821 if (ocfs2_xattr_is_local(entry))
1777 void *val; 1822 continue;
1778 1823
1779 val = (void *)header + 1824 val = (void *)header +
1780 le16_to_cpu(entry->xe_name_offset); 1825 le16_to_cpu(entry->xe_name_offset);
1781 vb->vb_xv = (struct ocfs2_xattr_value_root *) 1826 vb->vb_xv = (struct ocfs2_xattr_value_root *)
1782 (val + OCFS2_XATTR_SIZE(entry->xe_name_len)); 1827 (val + OCFS2_XATTR_SIZE(entry->xe_name_len));
1783 ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt); 1828
1784 if (ret < 0) { 1829 ret = ocfs2_lock_xattr_remove_allocators(inode, vb->vb_xv,
1785 mlog_errno(ret); 1830 ref_ci, ref_root_bh,
1786 break; 1831 &ctxt.meta_ac,
1787 } 1832 &ref_credits);
1833
1834 ctxt.handle = ocfs2_start_trans(osb, ref_credits +
1835 ocfs2_remove_extent_credits(osb->sb));
1836 if (IS_ERR(ctxt.handle)) {
1837 ret = PTR_ERR(ctxt.handle);
1838 mlog_errno(ret);
1839 break;
1840 }
1841
1842 ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt);
1843 if (ret < 0) {
1844 mlog_errno(ret);
1845 break;
1846 }
1847
1848 ocfs2_commit_trans(osb, ctxt.handle);
1849 if (ctxt.meta_ac) {
1850 ocfs2_free_alloc_context(ctxt.meta_ac);
1851 ctxt.meta_ac = NULL;
1788 } 1852 }
1789 } 1853 }
1790 1854
1791 ocfs2_commit_trans(osb, ctxt.handle); 1855 if (ctxt.meta_ac)
1856 ocfs2_free_alloc_context(ctxt.meta_ac);
1792 ocfs2_schedule_truncate_log_flush(osb, 1); 1857 ocfs2_schedule_truncate_log_flush(osb, 1);
1793 ocfs2_run_deallocs(osb, &ctxt.dealloc); 1858 ocfs2_run_deallocs(osb, &ctxt.dealloc);
1794out:
1795 return ret; 1859 return ret;
1796} 1860}
1797 1861
1798static int ocfs2_xattr_ibody_remove(struct inode *inode, 1862static int ocfs2_xattr_ibody_remove(struct inode *inode,
1799 struct buffer_head *di_bh) 1863 struct buffer_head *di_bh,
1864 struct ocfs2_caching_info *ref_ci,
1865 struct buffer_head *ref_root_bh)
1800{ 1866{
1801 1867
1802 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; 1868 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
@@ -1811,13 +1877,21 @@ static int ocfs2_xattr_ibody_remove(struct inode *inode,
1811 ((void *)di + inode->i_sb->s_blocksize - 1877 ((void *)di + inode->i_sb->s_blocksize -
1812 le16_to_cpu(di->i_xattr_inline_size)); 1878 le16_to_cpu(di->i_xattr_inline_size));
1813 1879
1814 ret = ocfs2_remove_value_outside(inode, &vb, header); 1880 ret = ocfs2_remove_value_outside(inode, &vb, header,
1881 ref_ci, ref_root_bh);
1815 1882
1816 return ret; 1883 return ret;
1817} 1884}
1818 1885
1886struct ocfs2_rm_xattr_bucket_para {
1887 struct ocfs2_caching_info *ref_ci;
1888 struct buffer_head *ref_root_bh;
1889};
1890
1819static int ocfs2_xattr_block_remove(struct inode *inode, 1891static int ocfs2_xattr_block_remove(struct inode *inode,
1820 struct buffer_head *blk_bh) 1892 struct buffer_head *blk_bh,
1893 struct ocfs2_caching_info *ref_ci,
1894 struct buffer_head *ref_root_bh)
1821{ 1895{
1822 struct ocfs2_xattr_block *xb; 1896 struct ocfs2_xattr_block *xb;
1823 int ret = 0; 1897 int ret = 0;
@@ -1825,22 +1899,29 @@ static int ocfs2_xattr_block_remove(struct inode *inode,
1825 .vb_bh = blk_bh, 1899 .vb_bh = blk_bh,
1826 .vb_access = ocfs2_journal_access_xb, 1900 .vb_access = ocfs2_journal_access_xb,
1827 }; 1901 };
1902 struct ocfs2_rm_xattr_bucket_para args = {
1903 .ref_ci = ref_ci,
1904 .ref_root_bh = ref_root_bh,
1905 };
1828 1906
1829 xb = (struct ocfs2_xattr_block *)blk_bh->b_data; 1907 xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
1830 if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { 1908 if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) {
1831 struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header); 1909 struct ocfs2_xattr_header *header = &(xb->xb_attrs.xb_header);
1832 ret = ocfs2_remove_value_outside(inode, &vb, header); 1910 ret = ocfs2_remove_value_outside(inode, &vb, header,
1911 ref_ci, ref_root_bh);
1833 } else 1912 } else
1834 ret = ocfs2_iterate_xattr_index_block(inode, 1913 ret = ocfs2_iterate_xattr_index_block(inode,
1835 blk_bh, 1914 blk_bh,
1836 ocfs2_rm_xattr_cluster, 1915 ocfs2_rm_xattr_cluster,
1837 NULL); 1916 &args);
1838 1917
1839 return ret; 1918 return ret;
1840} 1919}
1841 1920
1842static int ocfs2_xattr_free_block(struct inode *inode, 1921static int ocfs2_xattr_free_block(struct inode *inode,
1843 u64 block) 1922 u64 block,
1923 struct ocfs2_caching_info *ref_ci,
1924 struct buffer_head *ref_root_bh)
1844{ 1925{
1845 struct inode *xb_alloc_inode; 1926 struct inode *xb_alloc_inode;
1846 struct buffer_head *xb_alloc_bh = NULL; 1927 struct buffer_head *xb_alloc_bh = NULL;
@@ -1858,7 +1939,7 @@ static int ocfs2_xattr_free_block(struct inode *inode,
1858 goto out; 1939 goto out;
1859 } 1940 }
1860 1941
1861 ret = ocfs2_xattr_block_remove(inode, blk_bh); 1942 ret = ocfs2_xattr_block_remove(inode, blk_bh, ref_ci, ref_root_bh);
1862 if (ret < 0) { 1943 if (ret < 0) {
1863 mlog_errno(ret); 1944 mlog_errno(ret);
1864 goto out; 1945 goto out;
@@ -1918,6 +1999,9 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
1918{ 1999{
1919 struct ocfs2_inode_info *oi = OCFS2_I(inode); 2000 struct ocfs2_inode_info *oi = OCFS2_I(inode);
1920 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; 2001 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
2002 struct ocfs2_refcount_tree *ref_tree = NULL;
2003 struct buffer_head *ref_root_bh = NULL;
2004 struct ocfs2_caching_info *ref_ci = NULL;
1921 handle_t *handle; 2005 handle_t *handle;
1922 int ret; 2006 int ret;
1923 2007
@@ -1927,8 +2011,21 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
1927 if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL)) 2011 if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
1928 return 0; 2012 return 0;
1929 2013
2014 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) {
2015 ret = ocfs2_lock_refcount_tree(OCFS2_SB(inode->i_sb),
2016 le64_to_cpu(di->i_refcount_loc),
2017 1, &ref_tree, &ref_root_bh);
2018 if (ret) {
2019 mlog_errno(ret);
2020 goto out;
2021 }
2022 ref_ci = &ref_tree->rf_ci;
2023
2024 }
2025
1930 if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) { 2026 if (oi->ip_dyn_features & OCFS2_INLINE_XATTR_FL) {
1931 ret = ocfs2_xattr_ibody_remove(inode, di_bh); 2027 ret = ocfs2_xattr_ibody_remove(inode, di_bh,
2028 ref_ci, ref_root_bh);
1932 if (ret < 0) { 2029 if (ret < 0) {
1933 mlog_errno(ret); 2030 mlog_errno(ret);
1934 goto out; 2031 goto out;
@@ -1937,7 +2034,8 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
1937 2034
1938 if (di->i_xattr_loc) { 2035 if (di->i_xattr_loc) {
1939 ret = ocfs2_xattr_free_block(inode, 2036 ret = ocfs2_xattr_free_block(inode,
1940 le64_to_cpu(di->i_xattr_loc)); 2037 le64_to_cpu(di->i_xattr_loc),
2038 ref_ci, ref_root_bh);
1941 if (ret < 0) { 2039 if (ret < 0) {
1942 mlog_errno(ret); 2040 mlog_errno(ret);
1943 goto out; 2041 goto out;
@@ -1971,6 +2069,9 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
1971out_commit: 2069out_commit:
1972 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); 2070 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
1973out: 2071out:
2072 if (ref_tree)
2073 ocfs2_unlock_refcount_tree(OCFS2_SB(inode->i_sb), ref_tree, 1);
2074 brelse(ref_root_bh);
1974 return ret; 2075 return ret;
1975} 2076}
1976 2077
@@ -4989,7 +5090,7 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode,
4989 struct ocfs2_extent_tree et; 5090 struct ocfs2_extent_tree et;
4990 5091
4991 ret = ocfs2_iterate_xattr_buckets(inode, blkno, len, 5092 ret = ocfs2_iterate_xattr_buckets(inode, blkno, len,
4992 ocfs2_delete_xattr_in_bucket, NULL); 5093 ocfs2_delete_xattr_in_bucket, para);
4993 if (ret) { 5094 if (ret) {
4994 mlog_errno(ret); 5095 mlog_errno(ret);
4995 return ret; 5096 return ret;
@@ -5378,7 +5479,7 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
5378 struct ocfs2_xattr_bucket *bucket, 5479 struct ocfs2_xattr_bucket *bucket,
5379 void *para) 5480 void *para)
5380{ 5481{
5381 int ret = 0; 5482 int ret = 0, ref_credits;
5382 struct ocfs2_xattr_header *xh = bucket_xh(bucket); 5483 struct ocfs2_xattr_header *xh = bucket_xh(bucket);
5383 u16 i; 5484 u16 i;
5384 struct ocfs2_xattr_entry *xe; 5485 struct ocfs2_xattr_entry *xe;
@@ -5386,7 +5487,9 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
5386 struct ocfs2_xattr_set_ctxt ctxt = {NULL, NULL,}; 5487 struct ocfs2_xattr_set_ctxt ctxt = {NULL, NULL,};
5387 int credits = ocfs2_remove_extent_credits(osb->sb) + 5488 int credits = ocfs2_remove_extent_credits(osb->sb) +
5388 ocfs2_blocks_per_xattr_bucket(inode->i_sb); 5489 ocfs2_blocks_per_xattr_bucket(inode->i_sb);
5389 5490 struct ocfs2_xattr_value_root *xv;
5491 struct ocfs2_rm_xattr_bucket_para *args =
5492 (struct ocfs2_rm_xattr_bucket_para *)para;
5390 5493
5391 ocfs2_init_dealloc_ctxt(&ctxt.dealloc); 5494 ocfs2_init_dealloc_ctxt(&ctxt.dealloc);
5392 5495
@@ -5395,7 +5498,16 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
5395 if (ocfs2_xattr_is_local(xe)) 5498 if (ocfs2_xattr_is_local(xe))
5396 continue; 5499 continue;
5397 5500
5398 ctxt.handle = ocfs2_start_trans(osb, credits); 5501 ret = ocfs2_get_xattr_tree_value_root(inode->i_sb, bucket,
5502 i, &xv, NULL);
5503
5504 ret = ocfs2_lock_xattr_remove_allocators(inode, xv,
5505 args->ref_ci,
5506 args->ref_root_bh,
5507 &ctxt.meta_ac,
5508 &ref_credits);
5509
5510 ctxt.handle = ocfs2_start_trans(osb, credits + ref_credits);
5399 if (IS_ERR(ctxt.handle)) { 5511 if (IS_ERR(ctxt.handle)) {
5400 ret = PTR_ERR(ctxt.handle); 5512 ret = PTR_ERR(ctxt.handle);
5401 mlog_errno(ret); 5513 mlog_errno(ret);
@@ -5406,12 +5518,18 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode,
5406 i, 0, &ctxt); 5518 i, 0, &ctxt);
5407 5519
5408 ocfs2_commit_trans(osb, ctxt.handle); 5520 ocfs2_commit_trans(osb, ctxt.handle);
5521 if (ctxt.meta_ac) {
5522 ocfs2_free_alloc_context(ctxt.meta_ac);
5523 ctxt.meta_ac = NULL;
5524 }
5409 if (ret) { 5525 if (ret) {
5410 mlog_errno(ret); 5526 mlog_errno(ret);
5411 break; 5527 break;
5412 } 5528 }
5413 } 5529 }
5414 5530
5531 if (ctxt.meta_ac)
5532 ocfs2_free_alloc_context(ctxt.meta_ac);
5415 ocfs2_schedule_truncate_log_flush(osb, 1); 5533 ocfs2_schedule_truncate_log_flush(osb, 1);
5416 ocfs2_run_deallocs(osb, &ctxt.dealloc); 5534 ocfs2_run_deallocs(osb, &ctxt.dealloc);
5417 return ret; 5535 return ret;