backref.c (1f422417945d08731e2915e0addb976f11b3a85a) backref.c (a37f232b7b65789cadc9834d389f6390de11b583)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2011 STRATO. All rights reserved.
4 */
5
6#include <linux/mm.h>
7#include <linux/rbtree.h>
8#include <trace/events/btrfs.h>

--- 377 unchanged lines hidden (view full) ---

386 wanted_disk_byte, count, sc, gfp_mask);
387}
388
389static int is_shared_data_backref(struct preftrees *preftrees, u64 bytenr)
390{
391 struct rb_node **p = &preftrees->direct.root.rb_root.rb_node;
392 struct rb_node *parent = NULL;
393 struct prelim_ref *ref = NULL;
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2011 STRATO. All rights reserved.
4 */
5
6#include <linux/mm.h>
7#include <linux/rbtree.h>
8#include <trace/events/btrfs.h>

--- 377 unchanged lines hidden (view full) ---

386 wanted_disk_byte, count, sc, gfp_mask);
387}
388
389static int is_shared_data_backref(struct preftrees *preftrees, u64 bytenr)
390{
391 struct rb_node **p = &preftrees->direct.root.rb_root.rb_node;
392 struct rb_node *parent = NULL;
393 struct prelim_ref *ref = NULL;
394 struct prelim_ref target = {0};
394 struct prelim_ref target = {};
395 int result;
396
397 target.parent = bytenr;
398
399 while (*p) {
400 parent = *p;
401 ref = rb_entry(parent, struct prelim_ref, rbnode);
402 result = prelim_ref_compare(ref, &target);

--- 1887 unchanged lines hidden (view full) ---

2290
2291void free_ipath(struct inode_fs_paths *ipath)
2292{
2293 if (!ipath)
2294 return;
2295 kvfree(ipath->fspath);
2296 kfree(ipath);
2297}
395 int result;
396
397 target.parent = bytenr;
398
399 while (*p) {
400 parent = *p;
401 ref = rb_entry(parent, struct prelim_ref, rbnode);
402 result = prelim_ref_compare(ref, &target);

--- 1887 unchanged lines hidden (view full) ---

2290
2291void free_ipath(struct inode_fs_paths *ipath)
2292{
2293 if (!ipath)
2294 return;
2295 kvfree(ipath->fspath);
2296 kfree(ipath);
2297}
2298
2299struct btrfs_backref_iter *btrfs_backref_iter_alloc(
2300 struct btrfs_fs_info *fs_info, gfp_t gfp_flag)
2301{
2302 struct btrfs_backref_iter *ret;
2303
2304 ret = kzalloc(sizeof(*ret), gfp_flag);
2305 if (!ret)
2306 return NULL;
2307
2308 ret->path = btrfs_alloc_path();
2309 if (!ret) {
2310 kfree(ret);
2311 return NULL;
2312 }
2313
2314 /* Current backref iterator only supports iteration in commit root */
2315 ret->path->search_commit_root = 1;
2316 ret->path->skip_locking = 1;
2317 ret->fs_info = fs_info;
2318
2319 return ret;
2320}
2321
2322int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
2323{
2324 struct btrfs_fs_info *fs_info = iter->fs_info;
2325 struct btrfs_path *path = iter->path;
2326 struct btrfs_extent_item *ei;
2327 struct btrfs_key key;
2328 int ret;
2329
2330 key.objectid = bytenr;
2331 key.type = BTRFS_METADATA_ITEM_KEY;
2332 key.offset = (u64)-1;
2333 iter->bytenr = bytenr;
2334
2335 ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
2336 if (ret < 0)
2337 return ret;
2338 if (ret == 0) {
2339 ret = -EUCLEAN;
2340 goto release;
2341 }
2342 if (path->slots[0] == 0) {
2343 WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
2344 ret = -EUCLEAN;
2345 goto release;
2346 }
2347 path->slots[0]--;
2348
2349 btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
2350 if ((key.type != BTRFS_EXTENT_ITEM_KEY &&
2351 key.type != BTRFS_METADATA_ITEM_KEY) || key.objectid != bytenr) {
2352 ret = -ENOENT;
2353 goto release;
2354 }
2355 memcpy(&iter->cur_key, &key, sizeof(key));
2356 iter->item_ptr = (u32)btrfs_item_ptr_offset(path->nodes[0],
2357 path->slots[0]);
2358 iter->end_ptr = (u32)(iter->item_ptr +
2359 btrfs_item_size_nr(path->nodes[0], path->slots[0]));
2360 ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
2361 struct btrfs_extent_item);
2362
2363 /*
2364 * Only support iteration on tree backref yet.
2365 *
2366 * This is an extra precaution for non skinny-metadata, where
2367 * EXTENT_ITEM is also used for tree blocks, that we can only use
2368 * extent flags to determine if it's a tree block.
2369 */
2370 if (btrfs_extent_flags(path->nodes[0], ei) & BTRFS_EXTENT_FLAG_DATA) {
2371 ret = -ENOTSUPP;
2372 goto release;
2373 }
2374 iter->cur_ptr = (u32)(iter->item_ptr + sizeof(*ei));
2375
2376 /* If there is no inline backref, go search for keyed backref */
2377 if (iter->cur_ptr >= iter->end_ptr) {
2378 ret = btrfs_next_item(fs_info->extent_root, path);
2379
2380 /* No inline nor keyed ref */
2381 if (ret > 0) {
2382 ret = -ENOENT;
2383 goto release;
2384 }
2385 if (ret < 0)
2386 goto release;
2387
2388 btrfs_item_key_to_cpu(path->nodes[0], &iter->cur_key,
2389 path->slots[0]);
2390 if (iter->cur_key.objectid != bytenr ||
2391 (iter->cur_key.type != BTRFS_SHARED_BLOCK_REF_KEY &&
2392 iter->cur_key.type != BTRFS_TREE_BLOCK_REF_KEY)) {
2393 ret = -ENOENT;
2394 goto release;
2395 }
2396 iter->cur_ptr = (u32)btrfs_item_ptr_offset(path->nodes[0],
2397 path->slots[0]);
2398 iter->item_ptr = iter->cur_ptr;
2399 iter->end_ptr = (u32)(iter->item_ptr + btrfs_item_size_nr(
2400 path->nodes[0], path->slots[0]));
2401 }
2402
2403 return 0;
2404release:
2405 btrfs_backref_iter_release(iter);
2406 return ret;
2407}