brintos

brintos / linux-shallow public Read only

0
0
Text · 14.4 KiB · 3396267 Raw
550 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2007 Oracle.  All rights reserved.4 */5 6#include <linux/err.h>7#include <linux/uuid.h>8#include "ctree.h"9#include "fs.h"10#include "messages.h"11#include "transaction.h"12#include "disk-io.h"13#include "qgroup.h"14#include "space-info.h"15#include "accessors.h"16#include "root-tree.h"17#include "orphan.h"18 19/*20 * Read a root item from the tree. In case we detect a root item smaller then21 * sizeof(root_item), we know it's an old version of the root structure and22 * initialize all new fields to zero. The same happens if we detect mismatching23 * generation numbers as then we know the root was once mounted with an older24 * kernel that was not aware of the root item structure change.25 */26static void btrfs_read_root_item(struct extent_buffer *eb, int slot,27				struct btrfs_root_item *item)28{29	u32 len;30	int need_reset = 0;31 32	len = btrfs_item_size(eb, slot);33	read_extent_buffer(eb, item, btrfs_item_ptr_offset(eb, slot),34			   min_t(u32, len, sizeof(*item)));35	if (len < sizeof(*item))36		need_reset = 1;37	if (!need_reset && btrfs_root_generation(item)38		!= btrfs_root_generation_v2(item)) {39		if (btrfs_root_generation_v2(item) != 0) {40			btrfs_warn(eb->fs_info,41					"mismatching generation and generation_v2 found in root item. This root was probably mounted with an older kernel. Resetting all new fields.");42		}43		need_reset = 1;44	}45	if (need_reset) {46		/* Clear all members from generation_v2 onwards. */47		memset_startat(item, 0, generation_v2);48		generate_random_guid(item->uuid);49	}50}51 52/*53 * Lookup the root by the key.54 *55 * root: the root of the root tree56 * search_key: the key to search57 * path: the path we search58 * root_item: the root item of the tree we look for59 * root_key: the root key of the tree we look for60 *61 * If ->offset of 'search_key' is -1ULL, it means we are not sure the offset62 * of the search key, just lookup the root with the highest offset for a63 * given objectid.64 *65 * If we find something return 0, otherwise > 0, < 0 on error.66 */67int btrfs_find_root(struct btrfs_root *root, const struct btrfs_key *search_key,68		    struct btrfs_path *path, struct btrfs_root_item *root_item,69		    struct btrfs_key *root_key)70{71	struct btrfs_key found_key;72	struct extent_buffer *l;73	int ret;74	int slot;75 76	ret = btrfs_search_slot(NULL, root, search_key, path, 0, 0);77	if (ret < 0)78		return ret;79 80	if (search_key->offset != -1ULL) {	/* the search key is exact */81		if (ret > 0)82			goto out;83	} else {84		/*85		 * Key with offset -1 found, there would have to exist a root86		 * with such id, but this is out of the valid range.87		 */88		if (ret == 0) {89			ret = -EUCLEAN;90			goto out;91		}92		if (path->slots[0] == 0)93			goto out;94		path->slots[0]--;95		ret = 0;96	}97 98	l = path->nodes[0];99	slot = path->slots[0];100 101	btrfs_item_key_to_cpu(l, &found_key, slot);102	if (found_key.objectid != search_key->objectid ||103	    found_key.type != BTRFS_ROOT_ITEM_KEY) {104		ret = 1;105		goto out;106	}107 108	if (root_item)109		btrfs_read_root_item(l, slot, root_item);110	if (root_key)111		memcpy(root_key, &found_key, sizeof(found_key));112out:113	btrfs_release_path(path);114	return ret;115}116 117void btrfs_set_root_node(struct btrfs_root_item *item,118			 struct extent_buffer *node)119{120	btrfs_set_root_bytenr(item, node->start);121	btrfs_set_root_level(item, btrfs_header_level(node));122	btrfs_set_root_generation(item, btrfs_header_generation(node));123}124 125/*126 * copy the data in 'item' into the btree127 */128int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root129		      *root, struct btrfs_key *key, struct btrfs_root_item130		      *item)131{132	struct btrfs_fs_info *fs_info = root->fs_info;133	struct btrfs_path *path;134	struct extent_buffer *l;135	int ret;136	int slot;137	unsigned long ptr;138	u32 old_len;139 140	path = btrfs_alloc_path();141	if (!path)142		return -ENOMEM;143 144	ret = btrfs_search_slot(trans, root, key, path, 0, 1);145	if (ret < 0)146		goto out;147 148	if (ret > 0) {149		btrfs_crit(fs_info,150			"unable to find root key (%llu %u %llu) in tree %llu",151			key->objectid, key->type, key->offset, btrfs_root_id(root));152		ret = -EUCLEAN;153		btrfs_abort_transaction(trans, ret);154		goto out;155	}156 157	l = path->nodes[0];158	slot = path->slots[0];159	ptr = btrfs_item_ptr_offset(l, slot);160	old_len = btrfs_item_size(l, slot);161 162	/*163	 * If this is the first time we update the root item which originated164	 * from an older kernel, we need to enlarge the item size to make room165	 * for the added fields.166	 */167	if (old_len < sizeof(*item)) {168		btrfs_release_path(path);169		ret = btrfs_search_slot(trans, root, key, path,170				-1, 1);171		if (ret < 0) {172			btrfs_abort_transaction(trans, ret);173			goto out;174		}175 176		ret = btrfs_del_item(trans, root, path);177		if (ret < 0) {178			btrfs_abort_transaction(trans, ret);179			goto out;180		}181		btrfs_release_path(path);182		ret = btrfs_insert_empty_item(trans, root, path,183				key, sizeof(*item));184		if (ret < 0) {185			btrfs_abort_transaction(trans, ret);186			goto out;187		}188		l = path->nodes[0];189		slot = path->slots[0];190		ptr = btrfs_item_ptr_offset(l, slot);191	}192 193	/*194	 * Update generation_v2 so at the next mount we know the new root195	 * fields are valid.196	 */197	btrfs_set_root_generation_v2(item, btrfs_root_generation(item));198 199	write_extent_buffer(l, item, ptr, sizeof(*item));200	btrfs_mark_buffer_dirty(trans, path->nodes[0]);201out:202	btrfs_free_path(path);203	return ret;204}205 206int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,207		      const struct btrfs_key *key, struct btrfs_root_item *item)208{209	/*210	 * Make sure generation v1 and v2 match. See update_root for details.211	 */212	btrfs_set_root_generation_v2(item, btrfs_root_generation(item));213	return btrfs_insert_item(trans, root, key, item, sizeof(*item));214}215 216int btrfs_find_orphan_roots(struct btrfs_fs_info *fs_info)217{218	struct btrfs_root *tree_root = fs_info->tree_root;219	struct extent_buffer *leaf;220	struct btrfs_path *path;221	struct btrfs_key key;222	struct btrfs_root *root;223	int err = 0;224	int ret;225 226	path = btrfs_alloc_path();227	if (!path)228		return -ENOMEM;229 230	key.objectid = BTRFS_ORPHAN_OBJECTID;231	key.type = BTRFS_ORPHAN_ITEM_KEY;232	key.offset = 0;233 234	while (1) {235		u64 root_objectid;236 237		ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);238		if (ret < 0) {239			err = ret;240			break;241		}242 243		leaf = path->nodes[0];244		if (path->slots[0] >= btrfs_header_nritems(leaf)) {245			ret = btrfs_next_leaf(tree_root, path);246			if (ret < 0)247				err = ret;248			if (ret != 0)249				break;250			leaf = path->nodes[0];251		}252 253		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);254		btrfs_release_path(path);255 256		if (key.objectid != BTRFS_ORPHAN_OBJECTID ||257		    key.type != BTRFS_ORPHAN_ITEM_KEY)258			break;259 260		root_objectid = key.offset;261		key.offset++;262 263		root = btrfs_get_fs_root(fs_info, root_objectid, false);264		err = PTR_ERR_OR_ZERO(root);265		if (err && err != -ENOENT) {266			break;267		} else if (err == -ENOENT) {268			struct btrfs_trans_handle *trans;269 270			btrfs_release_path(path);271 272			trans = btrfs_join_transaction(tree_root);273			if (IS_ERR(trans)) {274				err = PTR_ERR(trans);275				btrfs_handle_fs_error(fs_info, err,276					    "Failed to start trans to delete orphan item");277				break;278			}279			err = btrfs_del_orphan_item(trans, tree_root,280						    root_objectid);281			btrfs_end_transaction(trans);282			if (err) {283				btrfs_handle_fs_error(fs_info, err,284					    "Failed to delete root orphan item");285				break;286			}287			continue;288		}289 290		WARN_ON(!test_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state));291		if (btrfs_root_refs(&root->root_item) == 0) {292			struct btrfs_key drop_key;293 294			btrfs_disk_key_to_cpu(&drop_key, &root->root_item.drop_progress);295			/*296			 * If we have a non-zero drop_progress then we know we297			 * made it partly through deleting this snapshot, and298			 * thus we need to make sure we block any balance from299			 * happening until this snapshot is completely dropped.300			 */301			if (drop_key.objectid != 0 || drop_key.type != 0 ||302			    drop_key.offset != 0) {303				set_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags);304				set_bit(BTRFS_ROOT_UNFINISHED_DROP, &root->state);305			}306 307			set_bit(BTRFS_ROOT_DEAD_TREE, &root->state);308			btrfs_add_dead_root(root);309		}310		btrfs_put_root(root);311	}312 313	btrfs_free_path(path);314	return err;315}316 317/* drop the root item for 'key' from the tree root */318int btrfs_del_root(struct btrfs_trans_handle *trans,319		   const struct btrfs_key *key)320{321	struct btrfs_root *root = trans->fs_info->tree_root;322	struct btrfs_path *path;323	int ret;324 325	path = btrfs_alloc_path();326	if (!path)327		return -ENOMEM;328	ret = btrfs_search_slot(trans, root, key, path, -1, 1);329	if (ret < 0)330		goto out;331	if (ret != 0) {332		/* The root must exist but we did not find it by the key. */333		ret = -EUCLEAN;334		goto out;335	}336 337	ret = btrfs_del_item(trans, root, path);338out:339	btrfs_free_path(path);340	return ret;341}342 343int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id,344		       u64 ref_id, u64 dirid, u64 *sequence,345		       const struct fscrypt_str *name)346{347	struct btrfs_root *tree_root = trans->fs_info->tree_root;348	struct btrfs_path *path;349	struct btrfs_root_ref *ref;350	struct extent_buffer *leaf;351	struct btrfs_key key;352	unsigned long ptr;353	int ret;354 355	path = btrfs_alloc_path();356	if (!path)357		return -ENOMEM;358 359	key.objectid = root_id;360	key.type = BTRFS_ROOT_BACKREF_KEY;361	key.offset = ref_id;362again:363	ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);364	if (ret < 0) {365		goto out;366	} else if (ret == 0) {367		leaf = path->nodes[0];368		ref = btrfs_item_ptr(leaf, path->slots[0],369				     struct btrfs_root_ref);370		ptr = (unsigned long)(ref + 1);371		if ((btrfs_root_ref_dirid(leaf, ref) != dirid) ||372		    (btrfs_root_ref_name_len(leaf, ref) != name->len) ||373		    memcmp_extent_buffer(leaf, name->name, ptr, name->len)) {374			ret = -ENOENT;375			goto out;376		}377		*sequence = btrfs_root_ref_sequence(leaf, ref);378 379		ret = btrfs_del_item(trans, tree_root, path);380		if (ret)381			goto out;382	} else {383		ret = -ENOENT;384		goto out;385	}386 387	if (key.type == BTRFS_ROOT_BACKREF_KEY) {388		btrfs_release_path(path);389		key.objectid = ref_id;390		key.type = BTRFS_ROOT_REF_KEY;391		key.offset = root_id;392		goto again;393	}394 395out:396	btrfs_free_path(path);397	return ret;398}399 400/*401 * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY402 * or BTRFS_ROOT_BACKREF_KEY.403 *404 * The dirid, sequence, name and name_len refer to the directory entry405 * that is referencing the root.406 *407 * For a forward ref, the root_id is the id of the tree referencing408 * the root and ref_id is the id of the subvol  or snapshot.409 *410 * For a back ref the root_id is the id of the subvol or snapshot and411 * ref_id is the id of the tree referencing it.412 *413 * Will return 0, -ENOMEM, or anything from the CoW path414 */415int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,416		       u64 ref_id, u64 dirid, u64 sequence,417		       const struct fscrypt_str *name)418{419	struct btrfs_root *tree_root = trans->fs_info->tree_root;420	struct btrfs_key key;421	int ret;422	struct btrfs_path *path;423	struct btrfs_root_ref *ref;424	struct extent_buffer *leaf;425	unsigned long ptr;426 427	path = btrfs_alloc_path();428	if (!path)429		return -ENOMEM;430 431	key.objectid = root_id;432	key.type = BTRFS_ROOT_BACKREF_KEY;433	key.offset = ref_id;434again:435	ret = btrfs_insert_empty_item(trans, tree_root, path, &key,436				      sizeof(*ref) + name->len);437	if (ret) {438		btrfs_abort_transaction(trans, ret);439		btrfs_free_path(path);440		return ret;441	}442 443	leaf = path->nodes[0];444	ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);445	btrfs_set_root_ref_dirid(leaf, ref, dirid);446	btrfs_set_root_ref_sequence(leaf, ref, sequence);447	btrfs_set_root_ref_name_len(leaf, ref, name->len);448	ptr = (unsigned long)(ref + 1);449	write_extent_buffer(leaf, name->name, ptr, name->len);450	btrfs_mark_buffer_dirty(trans, leaf);451 452	if (key.type == BTRFS_ROOT_BACKREF_KEY) {453		btrfs_release_path(path);454		key.objectid = ref_id;455		key.type = BTRFS_ROOT_REF_KEY;456		key.offset = root_id;457		goto again;458	}459 460	btrfs_free_path(path);461	return 0;462}463 464/*465 * Old btrfs forgets to init root_item->flags and root_item->byte_limit466 * for subvolumes. To work around this problem, we steal a bit from467 * root_item->inode_item->flags, and use it to indicate if those fields468 * have been properly initialized.469 */470void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)471{472	u64 inode_flags = btrfs_stack_inode_flags(&root_item->inode);473 474	if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {475		inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;476		btrfs_set_stack_inode_flags(&root_item->inode, inode_flags);477		btrfs_set_root_flags(root_item, 0);478		btrfs_set_root_limit(root_item, 0);479	}480}481 482void btrfs_update_root_times(struct btrfs_trans_handle *trans,483			     struct btrfs_root *root)484{485	struct btrfs_root_item *item = &root->root_item;486	struct timespec64 ct;487 488	ktime_get_real_ts64(&ct);489	spin_lock(&root->root_item_lock);490	btrfs_set_root_ctransid(item, trans->transid);491	btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);492	btrfs_set_stack_timespec_nsec(&item->ctime, ct.tv_nsec);493	spin_unlock(&root->root_item_lock);494}495 496/*497 * Reserve space for subvolume operation.498 *499 * root: the root of the parent directory500 * rsv: block reservation501 * items: the number of items that we need do reservation502 * use_global_rsv: allow fallback to the global block reservation503 *504 * This function is used to reserve the space for snapshot/subvolume505 * creation and deletion. Those operations are different with the506 * common file/directory operations, they change two fs/file trees507 * and root tree, the number of items that the qgroup reserves is508 * different with the free space reservation. So we can not use509 * the space reservation mechanism in start_transaction().510 */511int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,512				     struct btrfs_block_rsv *rsv, int items,513				     bool use_global_rsv)514{515	u64 qgroup_num_bytes = 0;516	u64 num_bytes;517	int ret;518	struct btrfs_fs_info *fs_info = root->fs_info;519	struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;520 521	if (btrfs_qgroup_enabled(fs_info)) {522		/* One for parent inode, two for dir entries */523		qgroup_num_bytes = 3 * fs_info->nodesize;524		ret = btrfs_qgroup_reserve_meta_prealloc(root,525							 qgroup_num_bytes, true,526							 false);527		if (ret)528			return ret;529	}530 531	num_bytes = btrfs_calc_insert_metadata_size(fs_info, items);532	rsv->space_info = btrfs_find_space_info(fs_info,533					    BTRFS_BLOCK_GROUP_METADATA);534	ret = btrfs_block_rsv_add(fs_info, rsv, num_bytes,535				  BTRFS_RESERVE_FLUSH_ALL);536 537	if (ret == -ENOSPC && use_global_rsv)538		ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, true);539 540	if (ret && qgroup_num_bytes)541		btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);542 543	if (!ret) {544		spin_lock(&rsv->lock);545		rsv->qgroup_rsv_reserved += qgroup_num_bytes;546		spin_unlock(&rsv->lock);547	}548	return ret;549}550