aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/alloc.c12
-rw-r--r--fs/ocfs2/alloc.h6
-rw-r--r--fs/ocfs2/ocfs2.h7
-rw-r--r--fs/ocfs2/refcounttree.c39
4 files changed, 58 insertions, 6 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 9dd68cd7b0ad..96f8ca6b3aba 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -5169,12 +5169,12 @@ out:
5169 * 5169 *
5170 * The caller is responsible for passing down meta_ac if we'll need it. 5170 * The caller is responsible for passing down meta_ac if we'll need it.
5171 */ 5171 */
5172static int ocfs2_change_extent_flag(handle_t *handle, 5172int ocfs2_change_extent_flag(handle_t *handle,
5173 struct ocfs2_extent_tree *et, 5173 struct ocfs2_extent_tree *et,
5174 u32 cpos, u32 len, u32 phys, 5174 u32 cpos, u32 len, u32 phys,
5175 struct ocfs2_alloc_context *meta_ac, 5175 struct ocfs2_alloc_context *meta_ac,
5176 struct ocfs2_cached_dealloc_ctxt *dealloc, 5176 struct ocfs2_cached_dealloc_ctxt *dealloc,
5177 int new_flags, int clear_flags) 5177 int new_flags, int clear_flags)
5178{ 5178{
5179 int ret, index; 5179 int ret, index;
5180 struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci); 5180 struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci);
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
index 0610ba148ea0..19d5b88a93df 100644
--- a/fs/ocfs2/alloc.h
+++ b/fs/ocfs2/alloc.h
@@ -128,6 +128,12 @@ int ocfs2_mark_extent_written(struct inode *inode,
128 handle_t *handle, u32 cpos, u32 len, u32 phys, 128 handle_t *handle, u32 cpos, u32 len, u32 phys,
129 struct ocfs2_alloc_context *meta_ac, 129 struct ocfs2_alloc_context *meta_ac,
130 struct ocfs2_cached_dealloc_ctxt *dealloc); 130 struct ocfs2_cached_dealloc_ctxt *dealloc);
131int ocfs2_change_extent_flag(handle_t *handle,
132 struct ocfs2_extent_tree *et,
133 u32 cpos, u32 len, u32 phys,
134 struct ocfs2_alloc_context *meta_ac,
135 struct ocfs2_cached_dealloc_ctxt *dealloc,
136 int new_flags, int clear_flags);
131int ocfs2_remove_extent(handle_t *handle, struct ocfs2_extent_tree *et, 137int ocfs2_remove_extent(handle_t *handle, struct ocfs2_extent_tree *et,
132 u32 cpos, u32 len, 138 u32 cpos, u32 len,
133 struct ocfs2_alloc_context *meta_ac, 139 struct ocfs2_alloc_context *meta_ac,
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index bb5357376ef5..eae404602424 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -516,6 +516,13 @@ static inline void ocfs2_add_links_count(struct ocfs2_dinode *di, int n)
516 ocfs2_set_links_count(di, links); 516 ocfs2_set_links_count(di, links);
517} 517}
518 518
519static inline int ocfs2_refcount_tree(struct ocfs2_super *osb)
520{
521 if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE)
522 return 1;
523 return 0;
524}
525
519/* set / clear functions because cluster events can make these happen 526/* set / clear functions because cluster events can make these happen
520 * in parallel so we want the transitions to be atomic. this also 527 * in parallel so we want the transitions to be atomic. this also
521 * means that any future flags osb_flags must be protected by spinlock 528 * means that any future flags osb_flags must be protected by spinlock
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 2c7974cccaf8..f7d19f4db897 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -2153,3 +2153,42 @@ out:
2153 brelse(ref_root_bh); 2153 brelse(ref_root_bh);
2154 return ret; 2154 return ret;
2155} 2155}
2156
2157/*
2158 * Mark the already-existing extent at cpos as refcounted for len clusters.
2159 * This adds the refcount extent flag.
2160 *
2161 * If the existing extent is larger than the request, initiate a
2162 * split. An attempt will be made at merging with adjacent extents.
2163 *
2164 * The caller is responsible for passing down meta_ac if we'll need it.
2165 */
2166static int ocfs2_mark_extent_refcounted(struct inode *inode,
2167 struct ocfs2_extent_tree *et,
2168 handle_t *handle, u32 cpos,
2169 u32 len, u32 phys,
2170 struct ocfs2_alloc_context *meta_ac,
2171 struct ocfs2_cached_dealloc_ctxt *dealloc)
2172{
2173 int ret;
2174
2175 mlog(0, "Inode %lu refcount tree cpos %u, len %u, phys cluster %u\n",
2176 inode->i_ino, cpos, len, phys);
2177
2178 if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) {
2179 ocfs2_error(inode->i_sb, "Inode %lu want to use refcount "
2180 "tree, but the feature bit is not set in the "
2181 "super block.", inode->i_ino);
2182 ret = -EROFS;
2183 goto out;
2184 }
2185
2186 ret = ocfs2_change_extent_flag(handle, et, cpos,
2187 len, phys, meta_ac, dealloc,
2188 OCFS2_EXT_REFCOUNTED, 0);
2189 if (ret)
2190 mlog_errno(ret);
2191
2192out:
2193 return ret;
2194}