diff options
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/alloc.c | 12 | ||||
-rw-r--r-- | fs/ocfs2/alloc.h | 6 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 7 | ||||
-rw-r--r-- | fs/ocfs2/refcounttree.c | 39 |
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 | */ |
5172 | static int ocfs2_change_extent_flag(handle_t *handle, | 5172 | int 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); |
131 | int 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); | ||
131 | int ocfs2_remove_extent(handle_t *handle, struct ocfs2_extent_tree *et, | 137 | int 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 | ||
519 | static 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 | */ | ||
2166 | static 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 | |||
2192 | out: | ||
2193 | return ret; | ||
2194 | } | ||