18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2007 Oracle. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/kthread.h> 78c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "ctree.h" 108c2ecf20Sopenharmony_ci#include "disk-io.h" 118c2ecf20Sopenharmony_ci#include "free-space-cache.h" 128c2ecf20Sopenharmony_ci#include "inode-map.h" 138c2ecf20Sopenharmony_ci#include "transaction.h" 148c2ecf20Sopenharmony_ci#include "delalloc-space.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic void fail_caching_thread(struct btrfs_root *root) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci btrfs_warn(fs_info, "failed to start inode caching task"); 218c2ecf20Sopenharmony_ci btrfs_clear_pending_and_info(fs_info, INODE_MAP_CACHE, 228c2ecf20Sopenharmony_ci "disabling inode map caching"); 238c2ecf20Sopenharmony_ci spin_lock(&root->ino_cache_lock); 248c2ecf20Sopenharmony_ci root->ino_cache_state = BTRFS_CACHE_ERROR; 258c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 268c2ecf20Sopenharmony_ci wake_up(&root->ino_cache_wait); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic int caching_kthread(void *data) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci struct btrfs_root *root = data; 328c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 338c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; 348c2ecf20Sopenharmony_ci struct btrfs_key key; 358c2ecf20Sopenharmony_ci struct btrfs_path *path; 368c2ecf20Sopenharmony_ci struct extent_buffer *leaf; 378c2ecf20Sopenharmony_ci u64 last = (u64)-1; 388c2ecf20Sopenharmony_ci int slot; 398c2ecf20Sopenharmony_ci int ret; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE)) 428c2ecf20Sopenharmony_ci return 0; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 458c2ecf20Sopenharmony_ci if (!path) { 468c2ecf20Sopenharmony_ci fail_caching_thread(root); 478c2ecf20Sopenharmony_ci return -ENOMEM; 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci /* Since the commit root is read-only, we can safely skip locking. */ 518c2ecf20Sopenharmony_ci path->skip_locking = 1; 528c2ecf20Sopenharmony_ci path->search_commit_root = 1; 538c2ecf20Sopenharmony_ci path->reada = READA_FORWARD; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci key.objectid = BTRFS_FIRST_FREE_OBJECTID; 568c2ecf20Sopenharmony_ci key.offset = 0; 578c2ecf20Sopenharmony_ci key.type = BTRFS_INODE_ITEM_KEY; 588c2ecf20Sopenharmony_ciagain: 598c2ecf20Sopenharmony_ci /* need to make sure the commit_root doesn't disappear */ 608c2ecf20Sopenharmony_ci down_read(&fs_info->commit_root_sem); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 638c2ecf20Sopenharmony_ci if (ret < 0) 648c2ecf20Sopenharmony_ci goto out; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci while (1) { 678c2ecf20Sopenharmony_ci if (btrfs_fs_closing(fs_info)) 688c2ecf20Sopenharmony_ci goto out; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 718c2ecf20Sopenharmony_ci slot = path->slots[0]; 728c2ecf20Sopenharmony_ci if (slot >= btrfs_header_nritems(leaf)) { 738c2ecf20Sopenharmony_ci ret = btrfs_next_leaf(root, path); 748c2ecf20Sopenharmony_ci if (ret < 0) 758c2ecf20Sopenharmony_ci goto out; 768c2ecf20Sopenharmony_ci else if (ret > 0) 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (need_resched() || 808c2ecf20Sopenharmony_ci btrfs_transaction_in_commit(fs_info)) { 818c2ecf20Sopenharmony_ci leaf = path->nodes[0]; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (WARN_ON(btrfs_header_nritems(leaf) == 0)) 848c2ecf20Sopenharmony_ci break; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* 878c2ecf20Sopenharmony_ci * Save the key so we can advances forward 888c2ecf20Sopenharmony_ci * in the next search. 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, 0); 918c2ecf20Sopenharmony_ci btrfs_release_path(path); 928c2ecf20Sopenharmony_ci root->ino_cache_progress = last; 938c2ecf20Sopenharmony_ci up_read(&fs_info->commit_root_sem); 948c2ecf20Sopenharmony_ci schedule_timeout(1); 958c2ecf20Sopenharmony_ci goto again; 968c2ecf20Sopenharmony_ci } else 978c2ecf20Sopenharmony_ci continue; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci btrfs_item_key_to_cpu(leaf, &key, slot); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (key.type != BTRFS_INODE_ITEM_KEY) 1038c2ecf20Sopenharmony_ci goto next; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (key.objectid >= root->highest_objectid) 1068c2ecf20Sopenharmony_ci break; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (last != (u64)-1 && last + 1 != key.objectid) { 1098c2ecf20Sopenharmony_ci __btrfs_add_free_space(fs_info, ctl, last + 1, 1108c2ecf20Sopenharmony_ci key.objectid - last - 1, 0); 1118c2ecf20Sopenharmony_ci wake_up(&root->ino_cache_wait); 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci last = key.objectid; 1158c2ecf20Sopenharmony_cinext: 1168c2ecf20Sopenharmony_ci path->slots[0]++; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (last < root->highest_objectid - 1) { 1208c2ecf20Sopenharmony_ci __btrfs_add_free_space(fs_info, ctl, last + 1, 1218c2ecf20Sopenharmony_ci root->highest_objectid - last - 1, 0); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci spin_lock(&root->ino_cache_lock); 1258c2ecf20Sopenharmony_ci root->ino_cache_state = BTRFS_CACHE_FINISHED; 1268c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci root->ino_cache_progress = (u64)-1; 1298c2ecf20Sopenharmony_ci btrfs_unpin_free_ino(root); 1308c2ecf20Sopenharmony_ciout: 1318c2ecf20Sopenharmony_ci wake_up(&root->ino_cache_wait); 1328c2ecf20Sopenharmony_ci up_read(&fs_info->commit_root_sem); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci btrfs_free_path(path); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci return ret; 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic void start_caching(struct btrfs_root *root) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 1428c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; 1438c2ecf20Sopenharmony_ci struct task_struct *tsk; 1448c2ecf20Sopenharmony_ci int ret; 1458c2ecf20Sopenharmony_ci u64 objectid; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE)) 1488c2ecf20Sopenharmony_ci return; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci spin_lock(&root->ino_cache_lock); 1518c2ecf20Sopenharmony_ci if (root->ino_cache_state != BTRFS_CACHE_NO) { 1528c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 1538c2ecf20Sopenharmony_ci return; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci root->ino_cache_state = BTRFS_CACHE_STARTED; 1578c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci ret = load_free_ino_cache(fs_info, root); 1608c2ecf20Sopenharmony_ci if (ret == 1) { 1618c2ecf20Sopenharmony_ci spin_lock(&root->ino_cache_lock); 1628c2ecf20Sopenharmony_ci root->ino_cache_state = BTRFS_CACHE_FINISHED; 1638c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 1648c2ecf20Sopenharmony_ci wake_up(&root->ino_cache_wait); 1658c2ecf20Sopenharmony_ci return; 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci /* 1698c2ecf20Sopenharmony_ci * It can be quite time-consuming to fill the cache by searching 1708c2ecf20Sopenharmony_ci * through the extent tree, and this can keep ino allocation path 1718c2ecf20Sopenharmony_ci * waiting. Therefore at start we quickly find out the highest 1728c2ecf20Sopenharmony_ci * inode number and we know we can use inode numbers which fall in 1738c2ecf20Sopenharmony_ci * [highest_ino + 1, BTRFS_LAST_FREE_OBJECTID]. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ci ret = btrfs_find_free_objectid(root, &objectid); 1768c2ecf20Sopenharmony_ci if (!ret && objectid <= BTRFS_LAST_FREE_OBJECTID) { 1778c2ecf20Sopenharmony_ci __btrfs_add_free_space(fs_info, ctl, objectid, 1788c2ecf20Sopenharmony_ci BTRFS_LAST_FREE_OBJECTID - objectid + 1, 1798c2ecf20Sopenharmony_ci 0); 1808c2ecf20Sopenharmony_ci wake_up(&root->ino_cache_wait); 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu", 1848c2ecf20Sopenharmony_ci root->root_key.objectid); 1858c2ecf20Sopenharmony_ci if (IS_ERR(tsk)) 1868c2ecf20Sopenharmony_ci fail_caching_thread(root); 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ciint btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE)) 1928c2ecf20Sopenharmony_ci return btrfs_find_free_objectid(root, objectid); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ciagain: 1958c2ecf20Sopenharmony_ci *objectid = btrfs_find_ino_for_alloc(root); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (*objectid != 0) 1988c2ecf20Sopenharmony_ci return 0; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci start_caching(root); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci wait_event(root->ino_cache_wait, 2038c2ecf20Sopenharmony_ci root->ino_cache_state == BTRFS_CACHE_FINISHED || 2048c2ecf20Sopenharmony_ci root->ino_cache_state == BTRFS_CACHE_ERROR || 2058c2ecf20Sopenharmony_ci root->free_ino_ctl->free_space > 0); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci if (root->ino_cache_state == BTRFS_CACHE_FINISHED && 2088c2ecf20Sopenharmony_ci root->free_ino_ctl->free_space == 0) 2098c2ecf20Sopenharmony_ci return -ENOSPC; 2108c2ecf20Sopenharmony_ci else if (root->ino_cache_state == BTRFS_CACHE_ERROR) 2118c2ecf20Sopenharmony_ci return btrfs_find_free_objectid(root, objectid); 2128c2ecf20Sopenharmony_ci else 2138c2ecf20Sopenharmony_ci goto again; 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_civoid btrfs_return_ino(struct btrfs_root *root, u64 objectid) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 2198c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *pinned = root->free_ino_pinned; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE)) 2228c2ecf20Sopenharmony_ci return; 2238c2ecf20Sopenharmony_ciagain: 2248c2ecf20Sopenharmony_ci if (root->ino_cache_state == BTRFS_CACHE_FINISHED) { 2258c2ecf20Sopenharmony_ci __btrfs_add_free_space(fs_info, pinned, objectid, 1, 0); 2268c2ecf20Sopenharmony_ci } else { 2278c2ecf20Sopenharmony_ci down_write(&fs_info->commit_root_sem); 2288c2ecf20Sopenharmony_ci spin_lock(&root->ino_cache_lock); 2298c2ecf20Sopenharmony_ci if (root->ino_cache_state == BTRFS_CACHE_FINISHED) { 2308c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 2318c2ecf20Sopenharmony_ci up_write(&fs_info->commit_root_sem); 2328c2ecf20Sopenharmony_ci goto again; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci start_caching(root); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci __btrfs_add_free_space(fs_info, pinned, objectid, 1, 0); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci up_write(&fs_info->commit_root_sem); 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci/* 2458c2ecf20Sopenharmony_ci * When a transaction is committed, we'll move those inode numbers which are 2468c2ecf20Sopenharmony_ci * smaller than root->ino_cache_progress from pinned tree to free_ino tree, and 2478c2ecf20Sopenharmony_ci * others will just be dropped, because the commit root we were searching has 2488c2ecf20Sopenharmony_ci * changed. 2498c2ecf20Sopenharmony_ci * 2508c2ecf20Sopenharmony_ci * Must be called with root->fs_info->commit_root_sem held 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_civoid btrfs_unpin_free_ino(struct btrfs_root *root) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; 2558c2ecf20Sopenharmony_ci struct rb_root *rbroot = &root->free_ino_pinned->free_space_offset; 2568c2ecf20Sopenharmony_ci spinlock_t *rbroot_lock = &root->free_ino_pinned->tree_lock; 2578c2ecf20Sopenharmony_ci struct btrfs_free_space *info; 2588c2ecf20Sopenharmony_ci struct rb_node *n; 2598c2ecf20Sopenharmony_ci u64 count; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE)) 2628c2ecf20Sopenharmony_ci return; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci while (1) { 2658c2ecf20Sopenharmony_ci spin_lock(rbroot_lock); 2668c2ecf20Sopenharmony_ci n = rb_first(rbroot); 2678c2ecf20Sopenharmony_ci if (!n) { 2688c2ecf20Sopenharmony_ci spin_unlock(rbroot_lock); 2698c2ecf20Sopenharmony_ci break; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci info = rb_entry(n, struct btrfs_free_space, offset_index); 2738c2ecf20Sopenharmony_ci BUG_ON(info->bitmap); /* Logic error */ 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (info->offset > root->ino_cache_progress) 2768c2ecf20Sopenharmony_ci count = 0; 2778c2ecf20Sopenharmony_ci else 2788c2ecf20Sopenharmony_ci count = min(root->ino_cache_progress - info->offset + 1, 2798c2ecf20Sopenharmony_ci info->bytes); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci rb_erase(&info->offset_index, rbroot); 2828c2ecf20Sopenharmony_ci spin_unlock(rbroot_lock); 2838c2ecf20Sopenharmony_ci if (count) 2848c2ecf20Sopenharmony_ci __btrfs_add_free_space(root->fs_info, ctl, 2858c2ecf20Sopenharmony_ci info->offset, count, 0); 2868c2ecf20Sopenharmony_ci kmem_cache_free(btrfs_free_space_cachep, info); 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci#define INIT_THRESHOLD ((SZ_32K / 2) / sizeof(struct btrfs_free_space)) 2918c2ecf20Sopenharmony_ci#define INODES_PER_BITMAP (PAGE_SIZE * 8) 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/* 2948c2ecf20Sopenharmony_ci * The goal is to keep the memory used by the free_ino tree won't 2958c2ecf20Sopenharmony_ci * exceed the memory if we use bitmaps only. 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_cistatic void recalculate_thresholds(struct btrfs_free_space_ctl *ctl) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci struct btrfs_free_space *info; 3008c2ecf20Sopenharmony_ci struct rb_node *n; 3018c2ecf20Sopenharmony_ci int max_ino; 3028c2ecf20Sopenharmony_ci int max_bitmaps; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci n = rb_last(&ctl->free_space_offset); 3058c2ecf20Sopenharmony_ci if (!n) { 3068c2ecf20Sopenharmony_ci ctl->extents_thresh = INIT_THRESHOLD; 3078c2ecf20Sopenharmony_ci return; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci info = rb_entry(n, struct btrfs_free_space, offset_index); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* 3128c2ecf20Sopenharmony_ci * Find the maximum inode number in the filesystem. Note we 3138c2ecf20Sopenharmony_ci * ignore the fact that this can be a bitmap, because we are 3148c2ecf20Sopenharmony_ci * not doing precise calculation. 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_ci max_ino = info->bytes - 1; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci max_bitmaps = ALIGN(max_ino, INODES_PER_BITMAP) / INODES_PER_BITMAP; 3198c2ecf20Sopenharmony_ci if (max_bitmaps <= ctl->total_bitmaps) { 3208c2ecf20Sopenharmony_ci ctl->extents_thresh = 0; 3218c2ecf20Sopenharmony_ci return; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci ctl->extents_thresh = (max_bitmaps - ctl->total_bitmaps) * 3258c2ecf20Sopenharmony_ci PAGE_SIZE / sizeof(*info); 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci/* 3298c2ecf20Sopenharmony_ci * We don't fall back to bitmap, if we are below the extents threshold 3308c2ecf20Sopenharmony_ci * or this chunk of inode numbers is a big one. 3318c2ecf20Sopenharmony_ci */ 3328c2ecf20Sopenharmony_cistatic bool use_bitmap(struct btrfs_free_space_ctl *ctl, 3338c2ecf20Sopenharmony_ci struct btrfs_free_space *info) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci if (ctl->free_extents < ctl->extents_thresh || 3368c2ecf20Sopenharmony_ci info->bytes > INODES_PER_BITMAP / 10) 3378c2ecf20Sopenharmony_ci return false; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return true; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic const struct btrfs_free_space_op free_ino_op = { 3438c2ecf20Sopenharmony_ci .recalc_thresholds = recalculate_thresholds, 3448c2ecf20Sopenharmony_ci .use_bitmap = use_bitmap, 3458c2ecf20Sopenharmony_ci}; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic void pinned_recalc_thresholds(struct btrfs_free_space_ctl *ctl) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cistatic bool pinned_use_bitmap(struct btrfs_free_space_ctl *ctl, 3528c2ecf20Sopenharmony_ci struct btrfs_free_space *info) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci /* 3558c2ecf20Sopenharmony_ci * We always use extents for two reasons: 3568c2ecf20Sopenharmony_ci * 3578c2ecf20Sopenharmony_ci * - The pinned tree is only used during the process of caching 3588c2ecf20Sopenharmony_ci * work. 3598c2ecf20Sopenharmony_ci * - Make code simpler. See btrfs_unpin_free_ino(). 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_ci return false; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic const struct btrfs_free_space_op pinned_free_ino_op = { 3658c2ecf20Sopenharmony_ci .recalc_thresholds = pinned_recalc_thresholds, 3668c2ecf20Sopenharmony_ci .use_bitmap = pinned_use_bitmap, 3678c2ecf20Sopenharmony_ci}; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_civoid btrfs_init_free_ino_ctl(struct btrfs_root *root) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; 3728c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *pinned = root->free_ino_pinned; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci spin_lock_init(&ctl->tree_lock); 3758c2ecf20Sopenharmony_ci ctl->unit = 1; 3768c2ecf20Sopenharmony_ci ctl->start = 0; 3778c2ecf20Sopenharmony_ci ctl->private = NULL; 3788c2ecf20Sopenharmony_ci ctl->op = &free_ino_op; 3798c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctl->trimming_ranges); 3808c2ecf20Sopenharmony_ci mutex_init(&ctl->cache_writeout_mutex); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* 3838c2ecf20Sopenharmony_ci * Initially we allow to use 16K of ram to cache chunks of 3848c2ecf20Sopenharmony_ci * inode numbers before we resort to bitmaps. This is somewhat 3858c2ecf20Sopenharmony_ci * arbitrary, but it will be adjusted in runtime. 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_ci ctl->extents_thresh = INIT_THRESHOLD; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci spin_lock_init(&pinned->tree_lock); 3908c2ecf20Sopenharmony_ci pinned->unit = 1; 3918c2ecf20Sopenharmony_ci pinned->start = 0; 3928c2ecf20Sopenharmony_ci pinned->private = NULL; 3938c2ecf20Sopenharmony_ci pinned->extents_thresh = 0; 3948c2ecf20Sopenharmony_ci pinned->op = &pinned_free_ino_op; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ciint btrfs_save_ino_cache(struct btrfs_root *root, 3988c2ecf20Sopenharmony_ci struct btrfs_trans_handle *trans) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci struct btrfs_fs_info *fs_info = root->fs_info; 4018c2ecf20Sopenharmony_ci struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; 4028c2ecf20Sopenharmony_ci struct btrfs_path *path; 4038c2ecf20Sopenharmony_ci struct inode *inode; 4048c2ecf20Sopenharmony_ci struct btrfs_block_rsv *rsv; 4058c2ecf20Sopenharmony_ci struct extent_changeset *data_reserved = NULL; 4068c2ecf20Sopenharmony_ci u64 num_bytes; 4078c2ecf20Sopenharmony_ci u64 alloc_hint = 0; 4088c2ecf20Sopenharmony_ci int ret; 4098c2ecf20Sopenharmony_ci int prealloc; 4108c2ecf20Sopenharmony_ci bool retry = false; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* only fs tree and subvol/snap needs ino cache */ 4138c2ecf20Sopenharmony_ci if (root->root_key.objectid != BTRFS_FS_TREE_OBJECTID && 4148c2ecf20Sopenharmony_ci (root->root_key.objectid < BTRFS_FIRST_FREE_OBJECTID || 4158c2ecf20Sopenharmony_ci root->root_key.objectid > BTRFS_LAST_FREE_OBJECTID)) 4168c2ecf20Sopenharmony_ci return 0; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci /* Don't save inode cache if we are deleting this root */ 4198c2ecf20Sopenharmony_ci if (btrfs_root_refs(&root->root_item) == 0) 4208c2ecf20Sopenharmony_ci return 0; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE)) 4238c2ecf20Sopenharmony_ci return 0; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci path = btrfs_alloc_path(); 4268c2ecf20Sopenharmony_ci if (!path) 4278c2ecf20Sopenharmony_ci return -ENOMEM; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci rsv = trans->block_rsv; 4308c2ecf20Sopenharmony_ci trans->block_rsv = &fs_info->trans_block_rsv; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci num_bytes = trans->bytes_reserved; 4338c2ecf20Sopenharmony_ci /* 4348c2ecf20Sopenharmony_ci * 1 item for inode item insertion if need 4358c2ecf20Sopenharmony_ci * 4 items for inode item update (in the worst case) 4368c2ecf20Sopenharmony_ci * 1 items for slack space if we need do truncation 4378c2ecf20Sopenharmony_ci * 1 item for free space object 4388c2ecf20Sopenharmony_ci * 3 items for pre-allocation 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_ci trans->bytes_reserved = btrfs_calc_insert_metadata_size(fs_info, 10); 4418c2ecf20Sopenharmony_ci ret = btrfs_block_rsv_add(root, trans->block_rsv, 4428c2ecf20Sopenharmony_ci trans->bytes_reserved, 4438c2ecf20Sopenharmony_ci BTRFS_RESERVE_NO_FLUSH); 4448c2ecf20Sopenharmony_ci if (ret) 4458c2ecf20Sopenharmony_ci goto out; 4468c2ecf20Sopenharmony_ci trace_btrfs_space_reservation(fs_info, "ino_cache", trans->transid, 4478c2ecf20Sopenharmony_ci trans->bytes_reserved, 1); 4488c2ecf20Sopenharmony_ciagain: 4498c2ecf20Sopenharmony_ci inode = lookup_free_ino_inode(root, path); 4508c2ecf20Sopenharmony_ci if (IS_ERR(inode) && (PTR_ERR(inode) != -ENOENT || retry)) { 4518c2ecf20Sopenharmony_ci ret = PTR_ERR(inode); 4528c2ecf20Sopenharmony_ci goto out_release; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 4568c2ecf20Sopenharmony_ci BUG_ON(retry); /* Logic error */ 4578c2ecf20Sopenharmony_ci retry = true; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci ret = create_free_ino_inode(root, trans, path); 4608c2ecf20Sopenharmony_ci if (ret) 4618c2ecf20Sopenharmony_ci goto out_release; 4628c2ecf20Sopenharmony_ci goto again; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci BTRFS_I(inode)->generation = 0; 4668c2ecf20Sopenharmony_ci ret = btrfs_update_inode(trans, root, inode); 4678c2ecf20Sopenharmony_ci if (ret) { 4688c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 4698c2ecf20Sopenharmony_ci goto out_put; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (i_size_read(inode) > 0) { 4738c2ecf20Sopenharmony_ci ret = btrfs_truncate_free_space_cache(trans, NULL, inode); 4748c2ecf20Sopenharmony_ci if (ret) { 4758c2ecf20Sopenharmony_ci if (ret != -ENOSPC) 4768c2ecf20Sopenharmony_ci btrfs_abort_transaction(trans, ret); 4778c2ecf20Sopenharmony_ci goto out_put; 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci spin_lock(&root->ino_cache_lock); 4828c2ecf20Sopenharmony_ci if (root->ino_cache_state != BTRFS_CACHE_FINISHED) { 4838c2ecf20Sopenharmony_ci ret = -1; 4848c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 4858c2ecf20Sopenharmony_ci goto out_put; 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci spin_unlock(&root->ino_cache_lock); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci spin_lock(&ctl->tree_lock); 4908c2ecf20Sopenharmony_ci prealloc = sizeof(struct btrfs_free_space) * ctl->free_extents; 4918c2ecf20Sopenharmony_ci prealloc = ALIGN(prealloc, PAGE_SIZE); 4928c2ecf20Sopenharmony_ci prealloc += ctl->total_bitmaps * PAGE_SIZE; 4938c2ecf20Sopenharmony_ci spin_unlock(&ctl->tree_lock); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci /* Just to make sure we have enough space */ 4968c2ecf20Sopenharmony_ci prealloc += 8 * PAGE_SIZE; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci ret = btrfs_delalloc_reserve_space(BTRFS_I(inode), &data_reserved, 0, 4998c2ecf20Sopenharmony_ci prealloc); 5008c2ecf20Sopenharmony_ci if (ret) 5018c2ecf20Sopenharmony_ci goto out_put; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, prealloc, 5048c2ecf20Sopenharmony_ci prealloc, prealloc, &alloc_hint); 5058c2ecf20Sopenharmony_ci if (ret) { 5068c2ecf20Sopenharmony_ci btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc); 5078c2ecf20Sopenharmony_ci btrfs_delalloc_release_metadata(BTRFS_I(inode), prealloc, true); 5088c2ecf20Sopenharmony_ci goto out_put; 5098c2ecf20Sopenharmony_ci } 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci ret = btrfs_write_out_ino_cache(root, trans, path, inode); 5128c2ecf20Sopenharmony_ci btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc); 5138c2ecf20Sopenharmony_ciout_put: 5148c2ecf20Sopenharmony_ci iput(inode); 5158c2ecf20Sopenharmony_ciout_release: 5168c2ecf20Sopenharmony_ci trace_btrfs_space_reservation(fs_info, "ino_cache", trans->transid, 5178c2ecf20Sopenharmony_ci trans->bytes_reserved, 0); 5188c2ecf20Sopenharmony_ci btrfs_block_rsv_release(fs_info, trans->block_rsv, 5198c2ecf20Sopenharmony_ci trans->bytes_reserved, NULL); 5208c2ecf20Sopenharmony_ciout: 5218c2ecf20Sopenharmony_ci trans->block_rsv = rsv; 5228c2ecf20Sopenharmony_ci trans->bytes_reserved = num_bytes; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci btrfs_free_path(path); 5258c2ecf20Sopenharmony_ci extent_changeset_free(data_reserved); 5268c2ecf20Sopenharmony_ci return ret; 5278c2ecf20Sopenharmony_ci} 528