aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/refcounttree.c
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2009-08-17 23:29:12 -0400
committerJoel Becker <joel.becker@oracle.com>2009-09-22 23:09:35 -0400
commitbcbbb24a6a5c5b3e7b8e5284e0bfa23f45c32377 (patch)
treee45a6cfd75cd8005fdf280c2f5f57c09186249dd /fs/ocfs2/refcounttree.c
parent1aa75fea64bc26bda9be9b1b20ae253d7a481877 (diff)
ocfs2: Decrement refcount when truncating refcounted extents.
Add 'Decrement refcount for delete' in to the normal truncate process. So for a refcounted extent record, call refcount rec decrementation instead of cluster free. Signed-off-by: Tao Ma <tao.ma@oracle.com>
Diffstat (limited to 'fs/ocfs2/refcounttree.c')
-rw-r--r--fs/ocfs2/refcounttree.c212
1 files changed, 212 insertions, 0 deletions
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index f7d19f4db897..e72dbdd3b6e8 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -2192,3 +2192,215 @@ static int ocfs2_mark_extent_refcounted(struct inode *inode,
2192out: 2192out:
2193 return ret; 2193 return ret;
2194} 2194}
2195
2196/*
2197 * Given some contiguous physical clusters, calculate what we need
2198 * for modifying their refcount.
2199 */
2200static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
2201 struct ocfs2_caching_info *ci,
2202 struct buffer_head *ref_root_bh,
2203 u64 start_cpos,
2204 u32 clusters,
2205 int *meta_add,
2206 int *credits)
2207{
2208 int ret = 0, index, ref_blocks = 0, recs_add = 0;
2209 u64 cpos = start_cpos;
2210 struct ocfs2_refcount_block *rb;
2211 struct ocfs2_refcount_rec rec;
2212 struct buffer_head *ref_leaf_bh = NULL, *prev_bh = NULL;
2213 u32 len;
2214
2215 mlog(0, "start_cpos %llu, clusters %u\n",
2216 (unsigned long long)start_cpos, clusters);
2217 while (clusters) {
2218 ret = ocfs2_get_refcount_rec(ci, ref_root_bh,
2219 cpos, clusters, &rec,
2220 &index, &ref_leaf_bh);
2221 if (ret) {
2222 mlog_errno(ret);
2223 goto out;
2224 }
2225
2226 if (ref_leaf_bh != prev_bh) {
2227 /*
2228 * Now we encounter a new leaf block, so calculate
2229 * whether we need to extend the old leaf.
2230 */
2231 if (prev_bh) {
2232 rb = (struct ocfs2_refcount_block *)
2233 prev_bh->b_data;
2234
2235 if (le64_to_cpu(rb->rf_records.rl_used) +
2236 recs_add >
2237 le16_to_cpu(rb->rf_records.rl_count))
2238 ref_blocks++;
2239 }
2240
2241 recs_add = 0;
2242 *credits += 1;
2243 brelse(prev_bh);
2244 prev_bh = ref_leaf_bh;
2245 get_bh(prev_bh);
2246 }
2247
2248 rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data;
2249
2250 mlog(0, "recs_add %d,cpos %llu, clusters %u, rec->r_cpos %llu,"
2251 "rec->r_clusters %u, rec->r_refcount %u, index %d\n",
2252 recs_add, (unsigned long long)cpos, clusters,
2253 (unsigned long long)le64_to_cpu(rec.r_cpos),
2254 le32_to_cpu(rec.r_clusters),
2255 le32_to_cpu(rec.r_refcount), index);
2256
2257 len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) +
2258 le32_to_cpu(rec.r_clusters)) - cpos;
2259 /*
2260 * If the refcount rec already exist, cool. We just need
2261 * to check whether there is a split. Otherwise we just need
2262 * to increase the refcount.
2263 * If we will insert one, increases recs_add.
2264 *
2265 * We record all the records which will be inserted to the
2266 * same refcount block, so that we can tell exactly whether
2267 * we need a new refcount block or not.
2268 */
2269 if (rec.r_refcount) {
2270 /* Check whether we need a split at the beginning. */
2271 if (cpos == start_cpos &&
2272 cpos != le64_to_cpu(rec.r_cpos))
2273 recs_add++;
2274
2275 /* Check whether we need a split in the end. */
2276 if (cpos + clusters < le64_to_cpu(rec.r_cpos) +
2277 le32_to_cpu(rec.r_clusters))
2278 recs_add++;
2279 } else
2280 recs_add++;
2281
2282 brelse(ref_leaf_bh);
2283 ref_leaf_bh = NULL;
2284 clusters -= len;
2285 cpos += len;
2286 }
2287
2288 if (prev_bh) {
2289 rb = (struct ocfs2_refcount_block *)prev_bh->b_data;
2290
2291 if (le64_to_cpu(rb->rf_records.rl_used) + recs_add >
2292 le16_to_cpu(rb->rf_records.rl_count))
2293 ref_blocks++;
2294
2295 *credits += 1;
2296 }
2297
2298 if (!ref_blocks)
2299 goto out;
2300
2301 mlog(0, "we need ref_blocks %d\n", ref_blocks);
2302 *meta_add += ref_blocks;
2303 *credits += ref_blocks;
2304
2305 /*
2306 * So we may need ref_blocks to insert into the tree.
2307 * That also means we need to change the b-tree and add that number
2308 * of records since we never merge them.
2309 * We need one more block for expansion since the new created leaf
2310 * block is also full and needs split.
2311 */
2312 rb = (struct ocfs2_refcount_block *)ref_root_bh->b_data;
2313 if (le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL) {
2314 struct ocfs2_extent_tree et;
2315
2316 ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh);
2317 *meta_add += ocfs2_extend_meta_needed(et.et_root_el);
2318 *credits += ocfs2_calc_extend_credits(sb,
2319 et.et_root_el,
2320 ref_blocks);
2321 } else {
2322 *credits += OCFS2_EXPAND_REFCOUNT_TREE_CREDITS;
2323 *meta_add += 1;
2324 }
2325
2326out:
2327 brelse(ref_leaf_bh);
2328 brelse(prev_bh);
2329 return ret;
2330}
2331
2332/*
2333 * For refcount tree, we will decrease some contiguous clusters
2334 * refcount count, so just go through it to see how many blocks
2335 * we gonna touch and whether we need to create new blocks.
2336 *
2337 * Normally the refcount blocks store these refcount should be
2338 * continguous also, so that we can get the number easily.
2339 * As for meta_ac, we will at most add split 2 refcount record and
2340 * 2 more refcount block, so just check it in a rough way.
2341 *
2342 * Caller must hold refcount tree lock.
2343 */
2344int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
2345 struct buffer_head *di_bh,
2346 u64 phys_blkno,
2347 u32 clusters,
2348 int *credits,
2349 struct ocfs2_alloc_context **meta_ac)
2350{
2351 int ret, ref_blocks = 0;
2352 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
2353 struct ocfs2_inode_info *oi = OCFS2_I(inode);
2354 struct buffer_head *ref_root_bh = NULL;
2355 struct ocfs2_refcount_tree *tree;
2356 u64 start_cpos = ocfs2_blocks_to_clusters(inode->i_sb, phys_blkno);
2357
2358 if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) {
2359 ocfs2_error(inode->i_sb, "Inode %lu want to use refcount "
2360 "tree, but the feature bit is not set in the "
2361 "super block.", inode->i_ino);
2362 ret = -EROFS;
2363 goto out;
2364 }
2365
2366 BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
2367
2368 ret = ocfs2_get_refcount_tree(OCFS2_SB(inode->i_sb),
2369 le64_to_cpu(di->i_refcount_loc), &tree);
2370 if (ret) {
2371 mlog_errno(ret);
2372 goto out;
2373 }
2374
2375 ret = ocfs2_read_refcount_block(&tree->rf_ci,
2376 le64_to_cpu(di->i_refcount_loc),
2377 &ref_root_bh);
2378 if (ret) {
2379 mlog_errno(ret);
2380 goto out;
2381 }
2382
2383 ret = ocfs2_calc_refcount_meta_credits(inode->i_sb,
2384 &tree->rf_ci,
2385 ref_root_bh,
2386 start_cpos, clusters,
2387 &ref_blocks, credits);
2388 if (ret) {
2389 mlog_errno(ret);
2390 goto out;
2391 }
2392
2393 mlog(0, "reserve new metadata %d, credits = %d\n",
2394 ref_blocks, *credits);
2395
2396 if (ref_blocks) {
2397 ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(inode->i_sb),
2398 ref_blocks, meta_ac);
2399 if (ret)
2400 mlog_errno(ret);
2401 }
2402
2403out:
2404 brelse(ref_root_bh);
2405 return ret;
2406}