18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2008 Oracle. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef BTRFS_LOCKING_H 78c2ecf20Sopenharmony_ci#define BTRFS_LOCKING_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/atomic.h> 108c2ecf20Sopenharmony_ci#include <linux/wait.h> 118c2ecf20Sopenharmony_ci#include <linux/percpu_counter.h> 128c2ecf20Sopenharmony_ci#include "extent_io.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define BTRFS_WRITE_LOCK 1 158c2ecf20Sopenharmony_ci#define BTRFS_READ_LOCK 2 168c2ecf20Sopenharmony_ci#define BTRFS_WRITE_LOCK_BLOCKING 3 178c2ecf20Sopenharmony_ci#define BTRFS_READ_LOCK_BLOCKING 4 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * We are limited in number of subclasses by MAX_LOCKDEP_SUBCLASSES, which at 218c2ecf20Sopenharmony_ci * the time of this patch is 8, which is how many we use. Keep this in mind if 228c2ecf20Sopenharmony_ci * you decide you want to add another subclass. 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_cienum btrfs_lock_nesting { 258c2ecf20Sopenharmony_ci BTRFS_NESTING_NORMAL, 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci /* 288c2ecf20Sopenharmony_ci * When we COW a block we are holding the lock on the original block, 298c2ecf20Sopenharmony_ci * and since our lockdep maps are rootid+level, this confuses lockdep 308c2ecf20Sopenharmony_ci * when we lock the newly allocated COW'd block. Handle this by having 318c2ecf20Sopenharmony_ci * a subclass for COW'ed blocks so that lockdep doesn't complain. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci BTRFS_NESTING_COW, 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* 368c2ecf20Sopenharmony_ci * Oftentimes we need to lock adjacent nodes on the same level while 378c2ecf20Sopenharmony_ci * still holding the lock on the original node we searched to, such as 388c2ecf20Sopenharmony_ci * for searching forward or for split/balance. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * Because of this we need to indicate to lockdep that this is 418c2ecf20Sopenharmony_ci * acceptable by having a different subclass for each of these 428c2ecf20Sopenharmony_ci * operations. 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci BTRFS_NESTING_LEFT, 458c2ecf20Sopenharmony_ci BTRFS_NESTING_RIGHT, 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci /* 488c2ecf20Sopenharmony_ci * When splitting we will be holding a lock on the left/right node when 498c2ecf20Sopenharmony_ci * we need to cow that node, thus we need a new set of subclasses for 508c2ecf20Sopenharmony_ci * these two operations. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci BTRFS_NESTING_LEFT_COW, 538c2ecf20Sopenharmony_ci BTRFS_NESTING_RIGHT_COW, 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci /* 568c2ecf20Sopenharmony_ci * When splitting we may push nodes to the left or right, but still use 578c2ecf20Sopenharmony_ci * the subsequent nodes in our path, keeping our locks on those adjacent 588c2ecf20Sopenharmony_ci * blocks. Thus when we go to allocate a new split block we've already 598c2ecf20Sopenharmony_ci * used up all of our available subclasses, so this subclass exists to 608c2ecf20Sopenharmony_ci * handle this case where we need to allocate a new split block. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci BTRFS_NESTING_SPLIT, 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* 658c2ecf20Sopenharmony_ci * When promoting a new block to a root we need to have a special 668c2ecf20Sopenharmony_ci * subclass so we don't confuse lockdep, as it will appear that we are 678c2ecf20Sopenharmony_ci * locking a higher level node before a lower level one. Copying also 688c2ecf20Sopenharmony_ci * has this problem as it appears we're locking the same block again 698c2ecf20Sopenharmony_ci * when we make a snapshot of an existing root. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci BTRFS_NESTING_NEW_ROOT, 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* 748c2ecf20Sopenharmony_ci * We are limited to MAX_LOCKDEP_SUBLCLASSES number of subclasses, so 758c2ecf20Sopenharmony_ci * add this in here and add a static_assert to keep us from going over 768c2ecf20Sopenharmony_ci * the limit. As of this writing we're limited to 8, and we're 778c2ecf20Sopenharmony_ci * definitely using 8, hence this check to keep us from messing up in 788c2ecf20Sopenharmony_ci * the future. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_ci BTRFS_NESTING_MAX, 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic_assert(BTRFS_NESTING_MAX <= MAX_LOCKDEP_SUBCLASSES, 848c2ecf20Sopenharmony_ci "too many lock subclasses defined"); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistruct btrfs_path; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_civoid __btrfs_tree_lock(struct extent_buffer *eb, enum btrfs_lock_nesting nest); 898c2ecf20Sopenharmony_civoid btrfs_tree_lock(struct extent_buffer *eb); 908c2ecf20Sopenharmony_civoid btrfs_tree_unlock(struct extent_buffer *eb); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_civoid __btrfs_tree_read_lock(struct extent_buffer *eb, enum btrfs_lock_nesting nest, 938c2ecf20Sopenharmony_ci bool recurse); 948c2ecf20Sopenharmony_civoid btrfs_tree_read_lock(struct extent_buffer *eb); 958c2ecf20Sopenharmony_civoid btrfs_tree_read_unlock(struct extent_buffer *eb); 968c2ecf20Sopenharmony_civoid btrfs_tree_read_unlock_blocking(struct extent_buffer *eb); 978c2ecf20Sopenharmony_civoid btrfs_set_lock_blocking_read(struct extent_buffer *eb); 988c2ecf20Sopenharmony_civoid btrfs_set_lock_blocking_write(struct extent_buffer *eb); 998c2ecf20Sopenharmony_ciint btrfs_try_tree_read_lock(struct extent_buffer *eb); 1008c2ecf20Sopenharmony_ciint btrfs_try_tree_write_lock(struct extent_buffer *eb); 1018c2ecf20Sopenharmony_ciint btrfs_tree_read_lock_atomic(struct extent_buffer *eb); 1028c2ecf20Sopenharmony_cistruct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root); 1038c2ecf20Sopenharmony_cistruct extent_buffer *__btrfs_read_lock_root_node(struct btrfs_root *root, 1048c2ecf20Sopenharmony_ci bool recurse); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic inline struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci return __btrfs_read_lock_root_node(root, false); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#ifdef CONFIG_BTRFS_DEBUG 1128c2ecf20Sopenharmony_cistatic inline void btrfs_assert_tree_locked(struct extent_buffer *eb) { 1138c2ecf20Sopenharmony_ci BUG_ON(!eb->write_locks); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci#else 1168c2ecf20Sopenharmony_cistatic inline void btrfs_assert_tree_locked(struct extent_buffer *eb) { } 1178c2ecf20Sopenharmony_ci#endif 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_civoid btrfs_set_path_blocking(struct btrfs_path *p); 1208c2ecf20Sopenharmony_civoid btrfs_unlock_up_safe(struct btrfs_path *path, int level); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic inline void btrfs_tree_unlock_rw(struct extent_buffer *eb, int rw) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci if (rw == BTRFS_WRITE_LOCK || rw == BTRFS_WRITE_LOCK_BLOCKING) 1258c2ecf20Sopenharmony_ci btrfs_tree_unlock(eb); 1268c2ecf20Sopenharmony_ci else if (rw == BTRFS_READ_LOCK_BLOCKING) 1278c2ecf20Sopenharmony_ci btrfs_tree_read_unlock_blocking(eb); 1288c2ecf20Sopenharmony_ci else if (rw == BTRFS_READ_LOCK) 1298c2ecf20Sopenharmony_ci btrfs_tree_read_unlock(eb); 1308c2ecf20Sopenharmony_ci else 1318c2ecf20Sopenharmony_ci BUG(); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistruct btrfs_drew_lock { 1358c2ecf20Sopenharmony_ci atomic_t readers; 1368c2ecf20Sopenharmony_ci struct percpu_counter writers; 1378c2ecf20Sopenharmony_ci wait_queue_head_t pending_writers; 1388c2ecf20Sopenharmony_ci wait_queue_head_t pending_readers; 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ciint btrfs_drew_lock_init(struct btrfs_drew_lock *lock); 1428c2ecf20Sopenharmony_civoid btrfs_drew_lock_destroy(struct btrfs_drew_lock *lock); 1438c2ecf20Sopenharmony_civoid btrfs_drew_write_lock(struct btrfs_drew_lock *lock); 1448c2ecf20Sopenharmony_cibool btrfs_drew_try_write_lock(struct btrfs_drew_lock *lock); 1458c2ecf20Sopenharmony_civoid btrfs_drew_write_unlock(struct btrfs_drew_lock *lock); 1468c2ecf20Sopenharmony_civoid btrfs_drew_read_lock(struct btrfs_drew_lock *lock); 1478c2ecf20Sopenharmony_civoid btrfs_drew_read_unlock(struct btrfs_drew_lock *lock); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#endif 150