b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 2) /*
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 3) * fs/ext4/extents_status.c
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 4) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 5) * Written by Yongqiang Yang <xiaoqiangnk@gmail.com>
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 6) * Modified by
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 7) * Allison Henderson <achender@linux.vnet.ibm.com>
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 8) * Hugh Dickins <hughd@google.com>
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 9) * Zheng Liu <wenqing.lz@taobao.com>
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 10) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 11) * Ext4 extents status tree core functions.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 12) */
d3922a777f9b4 (Zheng Liu 2013-07-01 08:12:37 -0400 13) #include <linux/list_sort.h>
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 14) #include <linux/proc_fs.h>
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 15) #include <linux/seq_file.h>
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 16) #include "ext4.h"
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 17)
992e9fdd7b3f6 (Zheng Liu 2012-11-08 21:57:33 -0500 18) #include <trace/events/ext4.h>
992e9fdd7b3f6 (Zheng Liu 2012-11-08 21:57:33 -0500 19)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 20) /*
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 21) * According to previous discussion in Ext4 Developer Workshop, we
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 22) * will introduce a new structure called io tree to track all extent
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 23) * status in order to solve some problems that we have met
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 24) * (e.g. Reservation space warning), and provide extent-level locking.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 25) * Delay extent tree is the first step to achieve this goal. It is
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 26) * original built by Yongqiang Yang. At that time it is called delay
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 27) * extent tree, whose goal is only track delayed extents in memory to
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 28) * simplify the implementation of fiemap and bigalloc, and introduce
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 29) * lseek SEEK_DATA/SEEK_HOLE support. That is why it is still called
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 30) * delay extent tree at the first commit. But for better understand
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 31) * what it does, it has been rename to extent status tree.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 32) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 33) * Step1:
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 34) * Currently the first step has been done. All delayed extents are
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 35) * tracked in the tree. It maintains the delayed extent when a delayed
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 36) * allocation is issued, and the delayed extent is written out or
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 37) * invalidated. Therefore the implementation of fiemap and bigalloc
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 38) * are simplified, and SEEK_DATA/SEEK_HOLE are introduced.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 39) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 40) * The following comment describes the implemenmtation of extent
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 41) * status tree and future works.
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 42) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 43) * Step2:
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 44) * In this step all extent status are tracked by extent status tree.
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 45) * Thus, we can first try to lookup a block mapping in this tree before
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 46) * finding it in extent tree. Hence, single extent cache can be removed
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 47) * because extent status tree can do a better job. Extents in status
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 48) * tree are loaded on-demand. Therefore, the extent status tree may not
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 49) * contain all of the extents in a file. Meanwhile we define a shrinker
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 50) * to reclaim memory from extent status tree because fragmented extent
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 51) * tree will make status tree cost too much memory. written/unwritten/-
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 52) * hole extents in the tree will be reclaimed by this shrinker when we
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 53) * are under high memory pressure. Delayed extents will not be
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 54) * reclimed because fiemap, bigalloc, and seek_data/hole need it.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 55) */
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 56)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 57) /*
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 58) * Extent status tree implementation for ext4.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 59) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 60) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 61) * ==========================================================================
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 62) * Extent status tree tracks all extent status.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 63) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 64) * 1. Why we need to implement extent status tree?
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 65) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 66) * Without extent status tree, ext4 identifies a delayed extent by looking
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 67) * up page cache, this has several deficiencies - complicated, buggy,
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 68) * and inefficient code.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 69) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 70) * FIEMAP, SEEK_HOLE/DATA, bigalloc, and writeout all need to know if a
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 71) * block or a range of blocks are belonged to a delayed extent.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 72) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 73) * Let us have a look at how they do without extent status tree.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 74) * -- FIEMAP
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 75) * FIEMAP looks up page cache to identify delayed allocations from holes.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 76) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 77) * -- SEEK_HOLE/DATA
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 78) * SEEK_HOLE/DATA has the same problem as FIEMAP.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 79) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 80) * -- bigalloc
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 81) * bigalloc looks up page cache to figure out if a block is
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 82) * already under delayed allocation or not to determine whether
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 83) * quota reserving is needed for the cluster.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 84) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 85) * -- writeout
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 86) * Writeout looks up whole page cache to see if a buffer is
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 87) * mapped, If there are not very many delayed buffers, then it is
3f8b6fb7f279c (Masahiro Yamada 2017-02-27 14:29:25 -0800 88) * time consuming.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 89) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 90) * With extent status tree implementation, FIEMAP, SEEK_HOLE/DATA,
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 91) * bigalloc and writeout can figure out if a block or a range of
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 92) * blocks is under delayed allocation(belonged to a delayed extent) or
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 93) * not by searching the extent tree.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 94) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 95) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 96) * ==========================================================================
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 97) * 2. Ext4 extent status tree impelmentation
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 98) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 99) * -- extent
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 100) * A extent is a range of blocks which are contiguous logically and
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 101) * physically. Unlike extent in extent tree, this extent in ext4 is
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 102) * a in-memory struct, there is no corresponding on-disk data. There
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 103) * is no limit on length of extent, so an extent can contain as many
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 104) * blocks as they are contiguous logically and physically.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 105) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 106) * -- extent status tree
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 107) * Every inode has an extent status tree and all allocation blocks
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 108) * are added to the tree with different status. The extent in the
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 109) * tree are ordered by logical block no.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 110) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 111) * -- operations on a extent status tree
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 112) * There are three important operations on a delayed extent tree: find
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 113) * next extent, adding a extent(a range of blocks) and removing a extent.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 114) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 115) * -- race on a extent status tree
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 116) * Extent status tree is protected by inode->i_es_lock.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 117) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 118) * -- memory consumption
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 119) * Fragmented extent tree will make extent status tree cost too much
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 120) * memory. Hence, we will reclaim written/unwritten/hole extents from
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 121) * the tree under a heavy memory pressure.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 122) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 123) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 124) * ==========================================================================
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 125) * 3. Performance analysis
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 126) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 127) * -- overhead
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 128) * 1. There is a cache extent for write access, so if writes are
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 129) * not very random, adding space operaions are in O(1) time.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 130) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 131) * -- gain
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 132) * 2. Code is much simpler, more readable, more maintainable and
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 133) * more efficient.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 134) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 135) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 136) * ==========================================================================
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 137) * 4. TODO list
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 138) *
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 139) * -- Refactor delayed space reservation
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 140) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 141) * -- Extent-level locking
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 142) */
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 143)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 144) static struct kmem_cache *ext4_es_cachep;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 145) static struct kmem_cache *ext4_pending_cachep;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 146)
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 147) static int __es_insert_extent(struct inode *inode, struct extent_status *newes);
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 148) static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 149) ext4_lblk_t end, int *reserved);
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 150) static int es_reclaim_extents(struct ext4_inode_info *ei, int *nr_to_scan);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 151) static int __es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 152) struct ext4_inode_info *locked_ei);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 153) static void __revise_pending(struct inode *inode, ext4_lblk_t lblk,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 154) ext4_lblk_t len);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 155)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 156) int __init ext4_init_es(void)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 157) {
246307745c406 (Theodore Ts'o 2013-02-28 23:58:56 -0500 158) ext4_es_cachep = kmem_cache_create("ext4_extent_status",
246307745c406 (Theodore Ts'o 2013-02-28 23:58:56 -0500 159) sizeof(struct extent_status),
246307745c406 (Theodore Ts'o 2013-02-28 23:58:56 -0500 160) 0, (SLAB_RECLAIM_ACCOUNT), NULL);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 161) if (ext4_es_cachep == NULL)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 162) return -ENOMEM;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 163) return 0;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 164) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 165)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 166) void ext4_exit_es(void)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 167) {
21c580d88e2ab (Sean Fu 2018-05-20 22:44:13 -0400 168) kmem_cache_destroy(ext4_es_cachep);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 169) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 170)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 171) void ext4_es_init_tree(struct ext4_es_tree *tree)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 172) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 173) tree->root = RB_ROOT;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 174) tree->cache_es = NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 175) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 176)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 177) #ifdef ES_DEBUG__
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 178) static void ext4_es_print_tree(struct inode *inode)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 179) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 180) struct ext4_es_tree *tree;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 181) struct rb_node *node;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 182)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 183) printk(KERN_DEBUG "status extents for inode %lu:", inode->i_ino);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 184) tree = &EXT4_I(inode)->i_es_tree;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 185) node = rb_first(&tree->root);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 186) while (node) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 187) struct extent_status *es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 188) es = rb_entry(node, struct extent_status, rb_node);
ce140cdd9c171 (Eric Whitney 2014-02-20 16:09:12 -0500 189) printk(KERN_DEBUG " [%u/%u) %llu %x",
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 190) es->es_lblk, es->es_len,
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 191) ext4_es_pblock(es), ext4_es_status(es));
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 192) node = rb_next(node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 193) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 194) printk(KERN_DEBUG "\n");
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 195) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 196) #else
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 197) #define ext4_es_print_tree(inode)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 198) #endif
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 199)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 200) static inline ext4_lblk_t ext4_es_end(struct extent_status *es)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 201) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 202) BUG_ON(es->es_lblk + es->es_len < es->es_lblk);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 203) return es->es_lblk + es->es_len - 1;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 204) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 205)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 206) /*
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 207) * search through the tree for an delayed extent with a given offset. If
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 208) * it can't be found, try to find next extent.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 209) */
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 210) static struct extent_status *__es_tree_search(struct rb_root *root,
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 211) ext4_lblk_t lblk)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 212) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 213) struct rb_node *node = root->rb_node;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 214) struct extent_status *es = NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 215)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 216) while (node) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 217) es = rb_entry(node, struct extent_status, rb_node);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 218) if (lblk < es->es_lblk)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 219) node = node->rb_left;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 220) else if (lblk > ext4_es_end(es))
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 221) node = node->rb_right;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 222) else
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 223) return es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 224) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 225)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 226) if (es && lblk < es->es_lblk)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 227) return es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 228)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 229) if (es && lblk > ext4_es_end(es)) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 230) node = rb_next(&es->rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 231) return node ? rb_entry(node, struct extent_status, rb_node) :
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 232) NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 233) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 234)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 235) return NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 236) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 237)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 238) /*
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 239) * ext4_es_find_extent_range - find extent with specified status within block
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 240) * range or next extent following block range in
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 241) * extents status tree
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 242) *
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 243) * @inode - file containing the range
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 244) * @matching_fn - pointer to function that matches extents with desired status
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 245) * @lblk - logical block defining start of range
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 246) * @end - logical block defining end of range
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 247) * @es - extent found, if any
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 248) *
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 249) * Find the first extent within the block range specified by @lblk and @end
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 250) * in the extents status tree that satisfies @matching_fn. If a match
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 251) * is found, it's returned in @es. If not, and a matching extent is found
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 252) * beyond the block range, it's returned in @es. If no match is found, an
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 253) * extent is returned in @es whose es_lblk, es_len, and es_pblk components
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 254) * are 0.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 255) */
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 256) static void __es_find_extent_range(struct inode *inode,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 257) int (*matching_fn)(struct extent_status *es),
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 258) ext4_lblk_t lblk, ext4_lblk_t end,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 259) struct extent_status *es)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 260) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 261) struct ext4_es_tree *tree = NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 262) struct extent_status *es1 = NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 263) struct rb_node *node;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 264)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 265) WARN_ON(es == NULL);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 266) WARN_ON(end < lblk);
992e9fdd7b3f6 (Zheng Liu 2012-11-08 21:57:33 -0500 267)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 268) tree = &EXT4_I(inode)->i_es_tree;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 269)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 270) /* see if the extent has been cached */
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 271) es->es_lblk = es->es_len = es->es_pblk = 0;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 272) if (tree->cache_es) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 273) es1 = tree->cache_es;
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 274) if (in_range(lblk, es1->es_lblk, es1->es_len)) {
3be78c73179c9 (Theodore Ts'o 2013-08-16 21:22:41 -0400 275) es_debug("%u cached by [%u/%u) %llu %x\n",
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 276) lblk, es1->es_lblk, es1->es_len,
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 277) ext4_es_pblock(es1), ext4_es_status(es1));
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 278) goto out;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 279) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 280) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 281)
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 282) es1 = __es_tree_search(&tree->root, lblk);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 283)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 284) out:
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 285) if (es1 && !matching_fn(es1)) {
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 286) while ((node = rb_next(&es1->rb_node)) != NULL) {
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 287) es1 = rb_entry(node, struct extent_status, rb_node);
e30b5dca15dea (Yan, Zheng 2013-05-03 02:15:52 -0400 288) if (es1->es_lblk > end) {
e30b5dca15dea (Yan, Zheng 2013-05-03 02:15:52 -0400 289) es1 = NULL;
e30b5dca15dea (Yan, Zheng 2013-05-03 02:15:52 -0400 290) break;
e30b5dca15dea (Yan, Zheng 2013-05-03 02:15:52 -0400 291) }
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 292) if (matching_fn(es1))
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 293) break;
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 294) }
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 295) }
be401363ac5ec (Zheng Liu 2013-02-18 00:27:26 -0500 296)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 297) if (es1 && matching_fn(es1)) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 298) tree->cache_es = es1;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 299) es->es_lblk = es1->es_lblk;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 300) es->es_len = es1->es_len;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 301) es->es_pblk = es1->es_pblk;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 302) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 303)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 304) }
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 305)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 306) /*
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 307) * Locking for __es_find_extent_range() for external use
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 308) */
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 309) void ext4_es_find_extent_range(struct inode *inode,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 310) int (*matching_fn)(struct extent_status *es),
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 311) ext4_lblk_t lblk, ext4_lblk_t end,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 312) struct extent_status *es)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 313) {
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 314) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 315) return;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 316)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 317) trace_ext4_es_find_extent_range_enter(inode, lblk);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 318)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 319) read_lock(&EXT4_I(inode)->i_es_lock);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 320) __es_find_extent_range(inode, matching_fn, lblk, end, es);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 321) read_unlock(&EXT4_I(inode)->i_es_lock);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 322)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 323) trace_ext4_es_find_extent_range_exit(inode, es);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 324) }
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 325)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 326) /*
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 327) * __es_scan_range - search block range for block with specified status
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 328) * in extents status tree
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 329) *
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 330) * @inode - file containing the range
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 331) * @matching_fn - pointer to function that matches extents with desired status
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 332) * @lblk - logical block defining start of range
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 333) * @end - logical block defining end of range
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 334) *
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 335) * Returns true if at least one block in the specified block range satisfies
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 336) * the criterion specified by @matching_fn, and false if not. If at least
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 337) * one extent has the specified status, then there is at least one block
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 338) * in the cluster with that status. Should only be called by code that has
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 339) * taken i_es_lock.
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 340) */
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 341) static bool __es_scan_range(struct inode *inode,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 342) int (*matching_fn)(struct extent_status *es),
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 343) ext4_lblk_t start, ext4_lblk_t end)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 344) {
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 345) struct extent_status es;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 346)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 347) __es_find_extent_range(inode, matching_fn, start, end, &es);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 348) if (es.es_len == 0)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 349) return false; /* no matching extent in the tree */
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 350) else if (es.es_lblk <= start &&
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 351) start < es.es_lblk + es.es_len)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 352) return true;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 353) else if (start <= es.es_lblk && es.es_lblk <= end)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 354) return true;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 355) else
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 356) return false;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 357) }
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 358) /*
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 359) * Locking for __es_scan_range() for external use
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 360) */
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 361) bool ext4_es_scan_range(struct inode *inode,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 362) int (*matching_fn)(struct extent_status *es),
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 363) ext4_lblk_t lblk, ext4_lblk_t end)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 364) {
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 365) bool ret;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 366)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 367) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 368) return false;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 369)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 370) read_lock(&EXT4_I(inode)->i_es_lock);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 371) ret = __es_scan_range(inode, matching_fn, lblk, end);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 372) read_unlock(&EXT4_I(inode)->i_es_lock);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 373)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 374) return ret;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 375) }
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 376)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 377) /*
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 378) * __es_scan_clu - search cluster for block with specified status in
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 379) * extents status tree
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 380) *
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 381) * @inode - file containing the cluster
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 382) * @matching_fn - pointer to function that matches extents with desired status
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 383) * @lblk - logical block in cluster to be searched
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 384) *
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 385) * Returns true if at least one extent in the cluster containing @lblk
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 386) * satisfies the criterion specified by @matching_fn, and false if not. If at
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 387) * least one extent has the specified status, then there is at least one block
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 388) * in the cluster with that status. Should only be called by code that has
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 389) * taken i_es_lock.
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 390) */
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 391) static bool __es_scan_clu(struct inode *inode,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 392) int (*matching_fn)(struct extent_status *es),
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 393) ext4_lblk_t lblk)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 394) {
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 395) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 396) ext4_lblk_t lblk_start, lblk_end;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 397)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 398) lblk_start = EXT4_LBLK_CMASK(sbi, lblk);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 399) lblk_end = lblk_start + sbi->s_cluster_ratio - 1;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 400)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 401) return __es_scan_range(inode, matching_fn, lblk_start, lblk_end);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 402) }
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 403)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 404) /*
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 405) * Locking for __es_scan_clu() for external use
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 406) */
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 407) bool ext4_es_scan_clu(struct inode *inode,
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 408) int (*matching_fn)(struct extent_status *es),
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 409) ext4_lblk_t lblk)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 410) {
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 411) bool ret;
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 412)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 413) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 414) return false;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 415)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 416) read_lock(&EXT4_I(inode)->i_es_lock);
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 417) ret = __es_scan_clu(inode, matching_fn, lblk);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 418) read_unlock(&EXT4_I(inode)->i_es_lock);
992e9fdd7b3f6 (Zheng Liu 2012-11-08 21:57:33 -0500 419)
ad431025aecda (Eric Whitney 2018-10-01 14:10:39 -0400 420) return ret;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 421) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 422)
b0dea4c1651f3 (Jan Kara 2014-11-25 11:49:25 -0500 423) static void ext4_es_list_add(struct inode *inode)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 424) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 425) struct ext4_inode_info *ei = EXT4_I(inode);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 426) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 427)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 428) if (!list_empty(&ei->i_es_list))
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 429) return;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 430)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 431) spin_lock(&sbi->s_es_lock);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 432) if (list_empty(&ei->i_es_list)) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 433) list_add_tail(&ei->i_es_list, &sbi->s_es_list);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 434) sbi->s_es_nr_inode++;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 435) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 436) spin_unlock(&sbi->s_es_lock);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 437) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 438)
b0dea4c1651f3 (Jan Kara 2014-11-25 11:49:25 -0500 439) static void ext4_es_list_del(struct inode *inode)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 440) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 441) struct ext4_inode_info *ei = EXT4_I(inode);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 442) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 443)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 444) spin_lock(&sbi->s_es_lock);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 445) if (!list_empty(&ei->i_es_list)) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 446) list_del_init(&ei->i_es_list);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 447) sbi->s_es_nr_inode--;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 448) WARN_ON_ONCE(sbi->s_es_nr_inode < 0);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 449) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 450) spin_unlock(&sbi->s_es_lock);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 451) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 452)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 453) static struct extent_status *
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 454) ext4_es_alloc_extent(struct inode *inode, ext4_lblk_t lblk, ext4_lblk_t len,
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 455) ext4_fsblk_t pblk)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 456) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 457) struct extent_status *es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 458) es = kmem_cache_alloc(ext4_es_cachep, GFP_ATOMIC);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 459) if (es == NULL)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 460) return NULL;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 461) es->es_lblk = lblk;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 462) es->es_len = len;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 463) es->es_pblk = pblk;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 464)
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 465) /*
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 466) * We don't count delayed extent because we never try to reclaim them
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 467) */
246307745c406 (Theodore Ts'o 2013-02-28 23:58:56 -0500 468) if (!ext4_es_is_delayed(es)) {
b0dea4c1651f3 (Jan Kara 2014-11-25 11:49:25 -0500 469) if (!EXT4_I(inode)->i_es_shk_nr++)
b0dea4c1651f3 (Jan Kara 2014-11-25 11:49:25 -0500 470) ext4_es_list_add(inode);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 471) percpu_counter_inc(&EXT4_SB(inode->i_sb)->
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 472) s_es_stats.es_stats_shk_cnt);
246307745c406 (Theodore Ts'o 2013-02-28 23:58:56 -0500 473) }
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 474)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 475) EXT4_I(inode)->i_es_all_nr++;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 476) percpu_counter_inc(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 477)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 478) return es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 479) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 480)
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 481) static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 482) {
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 483) EXT4_I(inode)->i_es_all_nr--;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 484) percpu_counter_dec(&EXT4_SB(inode->i_sb)->s_es_stats.es_stats_all_cnt);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 485)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 486) /* Decrease the shrink counter when this es is not delayed */
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 487) if (!ext4_es_is_delayed(es)) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 488) BUG_ON(EXT4_I(inode)->i_es_shk_nr == 0);
b0dea4c1651f3 (Jan Kara 2014-11-25 11:49:25 -0500 489) if (!--EXT4_I(inode)->i_es_shk_nr)
b0dea4c1651f3 (Jan Kara 2014-11-25 11:49:25 -0500 490) ext4_es_list_del(inode);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 491) percpu_counter_dec(&EXT4_SB(inode->i_sb)->
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 492) s_es_stats.es_stats_shk_cnt);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 493) }
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 494)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 495) kmem_cache_free(ext4_es_cachep, es);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 496) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 497)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 498) /*
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 499) * Check whether or not two extents can be merged
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 500) * Condition:
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 501) * - logical block number is contiguous
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 502) * - physical block number is contiguous
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 503) * - status is equal
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 504) */
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 505) static int ext4_es_can_be_merged(struct extent_status *es1,
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 506) struct extent_status *es2)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 507) {
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 508) if (ext4_es_type(es1) != ext4_es_type(es2))
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 509) return 0;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 510)
0baaea64009d5 (Lukas Czerner 2014-05-12 22:21:43 -0400 511) if (((__u64) es1->es_len) + es2->es_len > EXT_MAX_BLOCKS) {
0baaea64009d5 (Lukas Czerner 2014-05-12 22:21:43 -0400 512) pr_warn("ES assertion failed when merging extents. "
0baaea64009d5 (Lukas Czerner 2014-05-12 22:21:43 -0400 513) "The sum of lengths of es1 (%d) and es2 (%d) "
0baaea64009d5 (Lukas Czerner 2014-05-12 22:21:43 -0400 514) "is bigger than allowed file size (%d)\n",
0baaea64009d5 (Lukas Czerner 2014-05-12 22:21:43 -0400 515) es1->es_len, es2->es_len, EXT_MAX_BLOCKS);
0baaea64009d5 (Lukas Czerner 2014-05-12 22:21:43 -0400 516) WARN_ON(1);
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 517) return 0;
0baaea64009d5 (Lukas Czerner 2014-05-12 22:21:43 -0400 518) }
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 519)
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 520) if (((__u64) es1->es_lblk) + es1->es_len != es2->es_lblk)
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 521) return 0;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 522)
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 523) if ((ext4_es_is_written(es1) || ext4_es_is_unwritten(es1)) &&
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 524) (ext4_es_pblock(es1) + es1->es_len == ext4_es_pblock(es2)))
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 525) return 1;
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 526)
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 527) if (ext4_es_is_hole(es1))
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 528) return 1;
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 529)
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 530) /* we need to check delayed extent is without unwritten status */
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 531) if (ext4_es_is_delayed(es1) && !ext4_es_is_unwritten(es1))
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 532) return 1;
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 533)
bd384364c1185 (Zheng Liu 2013-03-10 20:48:59 -0400 534) return 0;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 535) }
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 536)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 537) static struct extent_status *
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 538) ext4_es_try_to_merge_left(struct inode *inode, struct extent_status *es)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 539) {
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 540) struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 541) struct extent_status *es1;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 542) struct rb_node *node;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 543)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 544) node = rb_prev(&es->rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 545) if (!node)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 546) return es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 547)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 548) es1 = rb_entry(node, struct extent_status, rb_node);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 549) if (ext4_es_can_be_merged(es1, es)) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 550) es1->es_len += es->es_len;
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 551) if (ext4_es_is_referenced(es))
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 552) ext4_es_set_referenced(es1);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 553) rb_erase(&es->rb_node, &tree->root);
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 554) ext4_es_free_extent(inode, es);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 555) es = es1;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 556) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 557)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 558) return es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 559) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 560)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 561) static struct extent_status *
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 562) ext4_es_try_to_merge_right(struct inode *inode, struct extent_status *es)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 563) {
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 564) struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 565) struct extent_status *es1;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 566) struct rb_node *node;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 567)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 568) node = rb_next(&es->rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 569) if (!node)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 570) return es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 571)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 572) es1 = rb_entry(node, struct extent_status, rb_node);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 573) if (ext4_es_can_be_merged(es, es1)) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 574) es->es_len += es1->es_len;
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 575) if (ext4_es_is_referenced(es1))
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 576) ext4_es_set_referenced(es);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 577) rb_erase(node, &tree->root);
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 578) ext4_es_free_extent(inode, es1);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 579) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 580)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 581) return es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 582) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 583)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 584) #ifdef ES_AGGRESSIVE_TEST
d7b2a00c2e2ee (Zheng Liu 2013-08-28 14:47:06 -0400 585) #include "ext4_extents.h" /* Needed when ES_AGGRESSIVE_TEST is defined */
d7b2a00c2e2ee (Zheng Liu 2013-08-28 14:47:06 -0400 586)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 587) static void ext4_es_insert_extent_ext_check(struct inode *inode,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 588) struct extent_status *es)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 589) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 590) struct ext4_ext_path *path = NULL;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 591) struct ext4_extent *ex;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 592) ext4_lblk_t ee_block;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 593) ext4_fsblk_t ee_start;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 594) unsigned short ee_len;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 595) int depth, ee_status, es_status;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 596)
ed8a1a766af73 (Theodore Ts'o 2014-09-01 14:43:09 -0400 597) path = ext4_find_extent(inode, es->es_lblk, NULL, EXT4_EX_NOCACHE);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 598) if (IS_ERR(path))
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 599) return;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 600)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 601) depth = ext_depth(inode);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 602) ex = path[depth].p_ext;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 603)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 604) if (ex) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 605)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 606) ee_block = le32_to_cpu(ex->ee_block);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 607) ee_start = ext4_ext_pblock(ex);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 608) ee_len = ext4_ext_get_actual_len(ex);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 609)
556615dcbf38b (Lukas Czerner 2014-04-20 23:45:47 -0400 610) ee_status = ext4_ext_is_unwritten(ex) ? 1 : 0;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 611) es_status = ext4_es_is_unwritten(es) ? 1 : 0;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 612)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 613) /*
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 614) * Make sure ex and es are not overlap when we try to insert
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 615) * a delayed/hole extent.
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 616) */
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 617) if (!ext4_es_is_written(es) && !ext4_es_is_unwritten(es)) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 618) if (in_range(es->es_lblk, ee_block, ee_len)) {
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 619) pr_warn("ES insert assertion failed for "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 620) "inode: %lu we can find an extent "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 621) "at block [%d/%d/%llu/%c], but we "
ce140cdd9c171 (Eric Whitney 2014-02-20 16:09:12 -0500 622) "want to add a delayed/hole extent "
ce140cdd9c171 (Eric Whitney 2014-02-20 16:09:12 -0500 623) "[%d/%d/%llu/%x]\n",
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 624) inode->i_ino, ee_block, ee_len,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 625) ee_start, ee_status ? 'u' : 'w',
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 626) es->es_lblk, es->es_len,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 627) ext4_es_pblock(es), ext4_es_status(es));
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 628) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 629) goto out;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 630) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 631)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 632) /*
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 633) * We don't check ee_block == es->es_lblk, etc. because es
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 634) * might be a part of whole extent, vice versa.
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 635) */
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 636) if (es->es_lblk < ee_block ||
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 637) ext4_es_pblock(es) != ee_start + es->es_lblk - ee_block) {
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 638) pr_warn("ES insert assertion failed for inode: %lu "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 639) "ex_status [%d/%d/%llu/%c] != "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 640) "es_status [%d/%d/%llu/%c]\n", inode->i_ino,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 641) ee_block, ee_len, ee_start,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 642) ee_status ? 'u' : 'w', es->es_lblk, es->es_len,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 643) ext4_es_pblock(es), es_status ? 'u' : 'w');
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 644) goto out;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 645) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 646)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 647) if (ee_status ^ es_status) {
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 648) pr_warn("ES insert assertion failed for inode: %lu "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 649) "ex_status [%d/%d/%llu/%c] != "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 650) "es_status [%d/%d/%llu/%c]\n", inode->i_ino,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 651) ee_block, ee_len, ee_start,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 652) ee_status ? 'u' : 'w', es->es_lblk, es->es_len,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 653) ext4_es_pblock(es), es_status ? 'u' : 'w');
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 654) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 655) } else {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 656) /*
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 657) * We can't find an extent on disk. So we need to make sure
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 658) * that we don't want to add an written/unwritten extent.
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 659) */
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 660) if (!ext4_es_is_delayed(es) && !ext4_es_is_hole(es)) {
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 661) pr_warn("ES insert assertion failed for inode: %lu "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 662) "can't find an extent at block %d but we want "
ce140cdd9c171 (Eric Whitney 2014-02-20 16:09:12 -0500 663) "to add a written/unwritten extent "
ce140cdd9c171 (Eric Whitney 2014-02-20 16:09:12 -0500 664) "[%d/%d/%llu/%x]\n", inode->i_ino,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 665) es->es_lblk, es->es_lblk, es->es_len,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 666) ext4_es_pblock(es), ext4_es_status(es));
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 667) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 668) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 669) out:
b7ea89ad0a6b8 (Theodore Ts'o 2014-09-01 14:39:09 -0400 670) ext4_ext_drop_refs(path);
b7ea89ad0a6b8 (Theodore Ts'o 2014-09-01 14:39:09 -0400 671) kfree(path);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 672) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 673)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 674) static void ext4_es_insert_extent_ind_check(struct inode *inode,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 675) struct extent_status *es)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 676) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 677) struct ext4_map_blocks map;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 678) int retval;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 679)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 680) /*
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 681) * Here we call ext4_ind_map_blocks to lookup a block mapping because
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 682) * 'Indirect' structure is defined in indirect.c. So we couldn't
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 683) * access direct/indirect tree from outside. It is too dirty to define
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 684) * this function in indirect.c file.
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 685) */
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 686)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 687) map.m_lblk = es->es_lblk;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 688) map.m_len = es->es_len;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 689)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 690) retval = ext4_ind_map_blocks(NULL, inode, &map, 0);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 691) if (retval > 0) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 692) if (ext4_es_is_delayed(es) || ext4_es_is_hole(es)) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 693) /*
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 694) * We want to add a delayed/hole extent but this
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 695) * block has been allocated.
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 696) */
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 697) pr_warn("ES insert assertion failed for inode: %lu "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 698) "We can find blocks but we want to add a "
ce140cdd9c171 (Eric Whitney 2014-02-20 16:09:12 -0500 699) "delayed/hole extent [%d/%d/%llu/%x]\n",
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 700) inode->i_ino, es->es_lblk, es->es_len,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 701) ext4_es_pblock(es), ext4_es_status(es));
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 702) return;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 703) } else if (ext4_es_is_written(es)) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 704) if (retval != es->es_len) {
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 705) pr_warn("ES insert assertion failed for "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 706) "inode: %lu retval %d != es_len %d\n",
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 707) inode->i_ino, retval, es->es_len);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 708) return;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 709) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 710) if (map.m_pblk != ext4_es_pblock(es)) {
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 711) pr_warn("ES insert assertion failed for "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 712) "inode: %lu m_pblk %llu != "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 713) "es_pblk %llu\n",
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 714) inode->i_ino, map.m_pblk,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 715) ext4_es_pblock(es));
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 716) return;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 717) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 718) } else {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 719) /*
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 720) * We don't need to check unwritten extent because
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 721) * indirect-based file doesn't have it.
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 722) */
1e83bc8156028 (Arnd Bergmann 2019-04-07 12:24:43 -0400 723) BUG();
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 724) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 725) } else if (retval == 0) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 726) if (ext4_es_is_written(es)) {
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 727) pr_warn("ES insert assertion failed for inode: %lu "
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 728) "We can't find the block but we want to add "
ce140cdd9c171 (Eric Whitney 2014-02-20 16:09:12 -0500 729) "a written extent [%d/%d/%llu/%x]\n",
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 730) inode->i_ino, es->es_lblk, es->es_len,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 731) ext4_es_pblock(es), ext4_es_status(es));
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 732) return;
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 733) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 734) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 735) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 736)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 737) static inline void ext4_es_insert_extent_check(struct inode *inode,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 738) struct extent_status *es)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 739) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 740) /*
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 741) * We don't need to worry about the race condition because
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 742) * caller takes i_data_sem locking.
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 743) */
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 744) BUG_ON(!rwsem_is_locked(&EXT4_I(inode)->i_data_sem));
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 745) if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 746) ext4_es_insert_extent_ext_check(inode, es);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 747) else
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 748) ext4_es_insert_extent_ind_check(inode, es);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 749) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 750) #else
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 751) static inline void ext4_es_insert_extent_check(struct inode *inode,
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 752) struct extent_status *es)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 753) {
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 754) }
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 755) #endif
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 756)
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 757) static int __es_insert_extent(struct inode *inode, struct extent_status *newes)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 758) {
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 759) struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 760) struct rb_node **p = &tree->root.rb_node;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 761) struct rb_node *parent = NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 762) struct extent_status *es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 763)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 764) while (*p) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 765) parent = *p;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 766) es = rb_entry(parent, struct extent_status, rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 767)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 768) if (newes->es_lblk < es->es_lblk) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 769) if (ext4_es_can_be_merged(newes, es)) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 770) /*
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 771) * Here we can modify es_lblk directly
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 772) * because it isn't overlapped.
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 773) */
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 774) es->es_lblk = newes->es_lblk;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 775) es->es_len += newes->es_len;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 776) if (ext4_es_is_written(es) ||
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 777) ext4_es_is_unwritten(es))
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 778) ext4_es_store_pblock(es,
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 779) newes->es_pblk);
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 780) es = ext4_es_try_to_merge_left(inode, es);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 781) goto out;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 782) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 783) p = &(*p)->rb_left;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 784) } else if (newes->es_lblk > ext4_es_end(es)) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 785) if (ext4_es_can_be_merged(es, newes)) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 786) es->es_len += newes->es_len;
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 787) es = ext4_es_try_to_merge_right(inode, es);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 788) goto out;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 789) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 790) p = &(*p)->rb_right;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 791) } else {
1e83bc8156028 (Arnd Bergmann 2019-04-07 12:24:43 -0400 792) BUG();
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 793) return -EINVAL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 794) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 795) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 796)
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 797) es = ext4_es_alloc_extent(inode, newes->es_lblk, newes->es_len,
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 798) newes->es_pblk);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 799) if (!es)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 800) return -ENOMEM;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 801) rb_link_node(&es->rb_node, parent, p);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 802) rb_insert_color(&es->rb_node, &tree->root);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 803)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 804) out:
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 805) tree->cache_es = es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 806) return 0;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 807) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 808)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 809) /*
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 810) * ext4_es_insert_extent() adds information to an inode's extent
bdafe42aaf728 (Theodore Ts'o 2013-07-13 00:40:31 -0400 811) * status tree.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 812) *
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 813) * Return 0 on success, error code on failure.
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 814) */
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 815) int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 816) ext4_lblk_t len, ext4_fsblk_t pblk,
3be78c73179c9 (Theodore Ts'o 2013-08-16 21:22:41 -0400 817) unsigned int status)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 818) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 819) struct extent_status newes;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 820) ext4_lblk_t end = lblk + len - 1;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 821) int err = 0;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 822) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 823)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 824) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 825) return 0;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 826)
3be78c73179c9 (Theodore Ts'o 2013-08-16 21:22:41 -0400 827) es_debug("add [%u/%u) %llu %x to extent status tree of inode %lu\n",
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 828) lblk, len, pblk, status, inode->i_ino);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 829)
d438147211110 (Eryu Guan 2013-02-22 15:27:47 -0500 830) if (!len)
d438147211110 (Eryu Guan 2013-02-22 15:27:47 -0500 831) return 0;
d438147211110 (Eryu Guan 2013-02-22 15:27:47 -0500 832)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 833) BUG_ON(end < lblk);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 834)
d2dc317d564a4 (Lukas Czerner 2015-05-02 21:36:55 -0400 835) if ((status & EXTENT_STATUS_DELAYED) &&
d2dc317d564a4 (Lukas Czerner 2015-05-02 21:36:55 -0400 836) (status & EXTENT_STATUS_WRITTEN)) {
d2dc317d564a4 (Lukas Czerner 2015-05-02 21:36:55 -0400 837) ext4_warning(inode->i_sb, "Inserting extent [%u/%u] as "
d2dc317d564a4 (Lukas Czerner 2015-05-02 21:36:55 -0400 838) " delayed and written which can potentially "
8d2ae1cbe8a98 (Jakub Wilk 2016-04-27 01:11:21 -0400 839) " cause data loss.", lblk, len);
d2dc317d564a4 (Lukas Czerner 2015-05-02 21:36:55 -0400 840) WARN_ON(1);
d2dc317d564a4 (Lukas Czerner 2015-05-02 21:36:55 -0400 841) }
d2dc317d564a4 (Lukas Czerner 2015-05-02 21:36:55 -0400 842)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 843) newes.es_lblk = lblk;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 844) newes.es_len = len;
9a6633b1a3603 (Theodore Ts'o 2014-02-19 20:15:15 -0500 845) ext4_es_store_pblock_status(&newes, pblk, status);
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 846) trace_ext4_es_insert_extent(inode, &newes);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 847)
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 848) ext4_es_insert_extent_check(inode, &newes);
921f266bc6bfe (Dmitry Monakhov 2013-03-10 21:01:03 -0400 849)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 850) write_lock(&EXT4_I(inode)->i_es_lock);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 851) err = __es_remove_extent(inode, lblk, end, NULL);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 852) if (err != 0)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 853) goto error;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 854) retry:
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 855) err = __es_insert_extent(inode, &newes);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 856) if (err == -ENOMEM && __es_shrink(EXT4_SB(inode->i_sb),
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 857) 128, EXT4_I(inode)))
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 858) goto retry;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 859) if (err == -ENOMEM && !ext4_es_is_delayed(&newes))
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 860) err = 0;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 861)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 862) if (sbi->s_cluster_ratio > 1 && test_opt(inode->i_sb, DELALLOC) &&
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 863) (status & EXTENT_STATUS_WRITTEN ||
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 864) status & EXTENT_STATUS_UNWRITTEN))
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 865) __revise_pending(inode, lblk, len);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 866)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 867) error:
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 868) write_unlock(&EXT4_I(inode)->i_es_lock);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 869)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 870) ext4_es_print_tree(inode);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 871)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 872) return err;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 873) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 874)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 875) /*
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 876) * ext4_es_cache_extent() inserts information into the extent status
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 877) * tree if and only if there isn't information about the range in
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 878) * question already.
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 879) */
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 880) void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 881) ext4_lblk_t len, ext4_fsblk_t pblk,
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 882) unsigned int status)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 883) {
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 884) struct extent_status *es;
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 885) struct extent_status newes;
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 886) ext4_lblk_t end = lblk + len - 1;
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 887)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 888) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 889) return;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 890)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 891) newes.es_lblk = lblk;
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 892) newes.es_len = len;
9a6633b1a3603 (Theodore Ts'o 2014-02-19 20:15:15 -0500 893) ext4_es_store_pblock_status(&newes, pblk, status);
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 894) trace_ext4_es_cache_extent(inode, &newes);
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 895)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 896) if (!len)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 897) return;
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 898)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 899) BUG_ON(end < lblk);
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 900)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 901) write_lock(&EXT4_I(inode)->i_es_lock);
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 902)
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 903) es = __es_tree_search(&EXT4_I(inode)->i_es_tree.root, lblk);
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 904) if (!es || es->es_lblk > end)
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 905) __es_insert_extent(inode, &newes);
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 906) write_unlock(&EXT4_I(inode)->i_es_lock);
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 907) }
107a7bd31ac00 (Theodore Ts'o 2013-08-16 21:23:41 -0400 908)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 909) /*
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 910) * ext4_es_lookup_extent() looks up an extent in extent status tree.
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 911) *
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 912) * ext4_es_lookup_extent is called by ext4_map_blocks/ext4_da_map_blocks.
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 913) *
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 914) * Return: 1 on found, 0 on not
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 915) */
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 916) int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 917) ext4_lblk_t *next_lblk,
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 918) struct extent_status *es)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 919) {
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 920) struct ext4_es_tree *tree;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 921) struct ext4_es_stats *stats;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 922) struct extent_status *es1 = NULL;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 923) struct rb_node *node;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 924) int found = 0;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 925)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 926) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 927) return 0;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 928)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 929) trace_ext4_es_lookup_extent_enter(inode, lblk);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 930) es_debug("lookup extent in block %u\n", lblk);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 931)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 932) tree = &EXT4_I(inode)->i_es_tree;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 933) read_lock(&EXT4_I(inode)->i_es_lock);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 934)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 935) /* find extent in cache firstly */
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 936) es->es_lblk = es->es_len = es->es_pblk = 0;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 937) if (tree->cache_es) {
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 938) es1 = tree->cache_es;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 939) if (in_range(lblk, es1->es_lblk, es1->es_len)) {
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 940) es_debug("%u cached by [%u/%u)\n",
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 941) lblk, es1->es_lblk, es1->es_len);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 942) found = 1;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 943) goto out;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 944) }
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 945) }
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 946)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 947) node = tree->root.rb_node;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 948) while (node) {
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 949) es1 = rb_entry(node, struct extent_status, rb_node);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 950) if (lblk < es1->es_lblk)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 951) node = node->rb_left;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 952) else if (lblk > ext4_es_end(es1))
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 953) node = node->rb_right;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 954) else {
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 955) found = 1;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 956) break;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 957) }
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 958) }
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 959)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 960) out:
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 961) stats = &EXT4_SB(inode->i_sb)->s_es_stats;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 962) if (found) {
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 963) BUG_ON(!es1);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 964) es->es_lblk = es1->es_lblk;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 965) es->es_len = es1->es_len;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 966) es->es_pblk = es1->es_pblk;
87d8a74b56746 (Jan Kara 2016-03-09 22:26:55 -0500 967) if (!ext4_es_is_referenced(es1))
87d8a74b56746 (Jan Kara 2016-03-09 22:26:55 -0500 968) ext4_es_set_referenced(es1);
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 969) percpu_counter_inc(&stats->es_stats_cache_hits);
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 970) if (next_lblk) {
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 971) node = rb_next(&es1->rb_node);
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 972) if (node) {
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 973) es1 = rb_entry(node, struct extent_status,
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 974) rb_node);
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 975) *next_lblk = es1->es_lblk;
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 976) } else
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 977) *next_lblk = 0;
bb5835edcdf8b (Theodore Ts'o 2019-08-11 16:32:41 -0400 978) }
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 979) } else {
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 980) percpu_counter_inc(&stats->es_stats_cache_misses);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 981) }
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 982)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 983) read_unlock(&EXT4_I(inode)->i_es_lock);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 984)
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 985) trace_ext4_es_lookup_extent_exit(inode, es, found);
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 986) return found;
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 987) }
d100eef2440fe (Zheng Liu 2013-02-18 00:29:59 -0500 988)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 989) struct rsvd_count {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 990) int ndelonly;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 991) bool first_do_lblk_found;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 992) ext4_lblk_t first_do_lblk;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 993) ext4_lblk_t last_do_lblk;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 994) struct extent_status *left_es;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 995) bool partial;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 996) ext4_lblk_t lclu;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 997) };
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 998)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 999) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1000) * init_rsvd - initialize reserved count data before removing block range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1001) * in file from extent status tree
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1002) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1003) * @inode - file containing range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1004) * @lblk - first block in range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1005) * @es - pointer to first extent in range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1006) * @rc - pointer to reserved count data
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1007) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1008) * Assumes es is not NULL
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1009) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1010) static void init_rsvd(struct inode *inode, ext4_lblk_t lblk,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1011) struct extent_status *es, struct rsvd_count *rc)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1012) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1013) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1014) struct rb_node *node;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1015)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1016) rc->ndelonly = 0;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1017)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1018) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1019) * for bigalloc, note the first delonly block in the range has not
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1020) * been found, record the extent containing the block to the left of
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1021) * the region to be removed, if any, and note that there's no partial
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1022) * cluster to track
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1023) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1024) if (sbi->s_cluster_ratio > 1) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1025) rc->first_do_lblk_found = false;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1026) if (lblk > es->es_lblk) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1027) rc->left_es = es;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1028) } else {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1029) node = rb_prev(&es->rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1030) rc->left_es = node ? rb_entry(node,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1031) struct extent_status,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1032) rb_node) : NULL;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1033) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1034) rc->partial = false;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1035) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1036) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1037)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1038) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1039) * count_rsvd - count the clusters containing delayed and not unwritten
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1040) * (delonly) blocks in a range within an extent and add to
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1041) * the running tally in rsvd_count
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1042) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1043) * @inode - file containing extent
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1044) * @lblk - first block in range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1045) * @len - length of range in blocks
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1046) * @es - pointer to extent containing clusters to be counted
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1047) * @rc - pointer to reserved count data
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1048) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1049) * Tracks partial clusters found at the beginning and end of extents so
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1050) * they aren't overcounted when they span adjacent extents
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1051) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1052) static void count_rsvd(struct inode *inode, ext4_lblk_t lblk, long len,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1053) struct extent_status *es, struct rsvd_count *rc)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1054) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1055) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1056) ext4_lblk_t i, end, nclu;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1057)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1058) if (!ext4_es_is_delonly(es))
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1059) return;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1060)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1061) WARN_ON(len <= 0);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1062)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1063) if (sbi->s_cluster_ratio == 1) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1064) rc->ndelonly += (int) len;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1065) return;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1066) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1067)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1068) /* bigalloc */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1069)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1070) i = (lblk < es->es_lblk) ? es->es_lblk : lblk;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1071) end = lblk + (ext4_lblk_t) len - 1;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1072) end = (end > ext4_es_end(es)) ? ext4_es_end(es) : end;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1073)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1074) /* record the first block of the first delonly extent seen */
39c0ae163f3b3 (Jason Yan 2020-04-20 12:29:18 +0800 1075) if (!rc->first_do_lblk_found) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1076) rc->first_do_lblk = i;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1077) rc->first_do_lblk_found = true;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1078) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1079)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1080) /* update the last lblk in the region seen so far */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1081) rc->last_do_lblk = end;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1082)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1083) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1084) * if we're tracking a partial cluster and the current extent
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1085) * doesn't start with it, count it and stop tracking
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1086) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1087) if (rc->partial && (rc->lclu != EXT4_B2C(sbi, i))) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1088) rc->ndelonly++;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1089) rc->partial = false;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1090) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1091)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1092) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1093) * if the first cluster doesn't start on a cluster boundary but
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1094) * ends on one, count it
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1095) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1096) if (EXT4_LBLK_COFF(sbi, i) != 0) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1097) if (end >= EXT4_LBLK_CFILL(sbi, i)) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1098) rc->ndelonly++;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1099) rc->partial = false;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1100) i = EXT4_LBLK_CFILL(sbi, i) + 1;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1101) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1102) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1103)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1104) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1105) * if the current cluster starts on a cluster boundary, count the
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1106) * number of whole delonly clusters in the extent
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1107) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1108) if ((i + sbi->s_cluster_ratio - 1) <= end) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1109) nclu = (end - i + 1) >> sbi->s_cluster_bits;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1110) rc->ndelonly += nclu;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1111) i += nclu << sbi->s_cluster_bits;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1112) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1113)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1114) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1115) * start tracking a partial cluster if there's a partial at the end
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1116) * of the current extent and we're not already tracking one
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1117) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1118) if (!rc->partial && i <= end) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1119) rc->partial = true;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1120) rc->lclu = EXT4_B2C(sbi, i);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1121) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1122) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1123)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1124) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1125) * __pr_tree_search - search for a pending cluster reservation
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1126) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1127) * @root - root of pending reservation tree
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1128) * @lclu - logical cluster to search for
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1129) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1130) * Returns the pending reservation for the cluster identified by @lclu
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1131) * if found. If not, returns a reservation for the next cluster if any,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1132) * and if not, returns NULL.
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1133) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1134) static struct pending_reservation *__pr_tree_search(struct rb_root *root,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1135) ext4_lblk_t lclu)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1136) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1137) struct rb_node *node = root->rb_node;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1138) struct pending_reservation *pr = NULL;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1139)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1140) while (node) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1141) pr = rb_entry(node, struct pending_reservation, rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1142) if (lclu < pr->lclu)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1143) node = node->rb_left;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1144) else if (lclu > pr->lclu)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1145) node = node->rb_right;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1146) else
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1147) return pr;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1148) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1149) if (pr && lclu < pr->lclu)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1150) return pr;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1151) if (pr && lclu > pr->lclu) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1152) node = rb_next(&pr->rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1153) return node ? rb_entry(node, struct pending_reservation,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1154) rb_node) : NULL;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1155) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1156) return NULL;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1157) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1158)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1159) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1160) * get_rsvd - calculates and returns the number of cluster reservations to be
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1161) * released when removing a block range from the extent status tree
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1162) * and releases any pending reservations within the range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1163) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1164) * @inode - file containing block range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1165) * @end - last block in range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1166) * @right_es - pointer to extent containing next block beyond end or NULL
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1167) * @rc - pointer to reserved count data
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1168) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1169) * The number of reservations to be released is equal to the number of
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1170) * clusters containing delayed and not unwritten (delonly) blocks within
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1171) * the range, minus the number of clusters still containing delonly blocks
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1172) * at the ends of the range, and minus the number of pending reservations
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1173) * within the range.
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1174) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1175) static unsigned int get_rsvd(struct inode *inode, ext4_lblk_t end,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1176) struct extent_status *right_es,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1177) struct rsvd_count *rc)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1178) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1179) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1180) struct pending_reservation *pr;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1181) struct ext4_pending_tree *tree = &EXT4_I(inode)->i_pending_tree;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1182) struct rb_node *node;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1183) ext4_lblk_t first_lclu, last_lclu;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1184) bool left_delonly, right_delonly, count_pending;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1185) struct extent_status *es;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1186)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1187) if (sbi->s_cluster_ratio > 1) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1188) /* count any remaining partial cluster */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1189) if (rc->partial)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1190) rc->ndelonly++;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1191)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1192) if (rc->ndelonly == 0)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1193) return 0;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1194)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1195) first_lclu = EXT4_B2C(sbi, rc->first_do_lblk);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1196) last_lclu = EXT4_B2C(sbi, rc->last_do_lblk);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1197)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1198) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1199) * decrease the delonly count by the number of clusters at the
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1200) * ends of the range that still contain delonly blocks -
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1201) * these clusters still need to be reserved
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1202) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1203) left_delonly = right_delonly = false;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1204)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1205) es = rc->left_es;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1206) while (es && ext4_es_end(es) >=
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1207) EXT4_LBLK_CMASK(sbi, rc->first_do_lblk)) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1208) if (ext4_es_is_delonly(es)) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1209) rc->ndelonly--;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1210) left_delonly = true;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1211) break;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1212) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1213) node = rb_prev(&es->rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1214) if (!node)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1215) break;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1216) es = rb_entry(node, struct extent_status, rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1217) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1218) if (right_es && (!left_delonly || first_lclu != last_lclu)) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1219) if (end < ext4_es_end(right_es)) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1220) es = right_es;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1221) } else {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1222) node = rb_next(&right_es->rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1223) es = node ? rb_entry(node, struct extent_status,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1224) rb_node) : NULL;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1225) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1226) while (es && es->es_lblk <=
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1227) EXT4_LBLK_CFILL(sbi, rc->last_do_lblk)) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1228) if (ext4_es_is_delonly(es)) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1229) rc->ndelonly--;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1230) right_delonly = true;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1231) break;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1232) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1233) node = rb_next(&es->rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1234) if (!node)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1235) break;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1236) es = rb_entry(node, struct extent_status,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1237) rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1238) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1239) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1240)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1241) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1242) * Determine the block range that should be searched for
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1243) * pending reservations, if any. Clusters on the ends of the
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1244) * original removed range containing delonly blocks are
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1245) * excluded. They've already been accounted for and it's not
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1246) * possible to determine if an associated pending reservation
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1247) * should be released with the information available in the
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1248) * extents status tree.
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1249) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1250) if (first_lclu == last_lclu) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1251) if (left_delonly | right_delonly)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1252) count_pending = false;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1253) else
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1254) count_pending = true;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1255) } else {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1256) if (left_delonly)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1257) first_lclu++;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1258) if (right_delonly)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1259) last_lclu--;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1260) if (first_lclu <= last_lclu)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1261) count_pending = true;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1262) else
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1263) count_pending = false;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1264) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1265)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1266) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1267) * a pending reservation found between first_lclu and last_lclu
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1268) * represents an allocated cluster that contained at least one
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1269) * delonly block, so the delonly total must be reduced by one
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1270) * for each pending reservation found and released
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1271) */
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1272) if (count_pending) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1273) pr = __pr_tree_search(&tree->root, first_lclu);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1274) while (pr && pr->lclu <= last_lclu) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1275) rc->ndelonly--;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1276) node = rb_next(&pr->rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1277) rb_erase(&pr->rb_node, &tree->root);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1278) kmem_cache_free(ext4_pending_cachep, pr);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1279) if (!node)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1280) break;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1281) pr = rb_entry(node, struct pending_reservation,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1282) rb_node);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1283) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1284) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1285) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1286) return rc->ndelonly;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1287) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1288)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1289)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1290) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1291) * __es_remove_extent - removes block range from extent status tree
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1292) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1293) * @inode - file containing range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1294) * @lblk - first block in range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1295) * @end - last block in range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1296) * @reserved - number of cluster reservations released
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1297) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1298) * If @reserved is not NULL and delayed allocation is enabled, counts
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1299) * block/cluster reservations freed by removing range and if bigalloc
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1300) * enabled cancels pending reservations as needed. Returns 0 on success,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1301) * error code on failure.
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1302) */
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 1303) static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1304) ext4_lblk_t end, int *reserved)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1305) {
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 1306) struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1307) struct rb_node *node;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1308) struct extent_status *es;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1309) struct extent_status orig_es;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1310) ext4_lblk_t len1, len2;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1311) ext4_fsblk_t block;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1312) int err;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1313) bool count_reserved = true;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1314) struct rsvd_count rc;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1315)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1316) if (reserved == NULL || !test_opt(inode->i_sb, DELALLOC))
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1317) count_reserved = false;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1318) retry:
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1319) err = 0;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1320)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1321) es = __es_tree_search(&tree->root, lblk);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1322) if (!es)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1323) goto out;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1324) if (es->es_lblk > end)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1325) goto out;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1326)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1327) /* Simply invalidate cache_es. */
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1328) tree->cache_es = NULL;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1329) if (count_reserved)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1330) init_rsvd(inode, lblk, es, &rc);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1331)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1332) orig_es.es_lblk = es->es_lblk;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1333) orig_es.es_len = es->es_len;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1334) orig_es.es_pblk = es->es_pblk;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1335)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1336) len1 = lblk > es->es_lblk ? lblk - es->es_lblk : 0;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1337) len2 = ext4_es_end(es) > end ? ext4_es_end(es) - end : 0;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1338) if (len1 > 0)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1339) es->es_len = len1;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1340) if (len2 > 0) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1341) if (len1 > 0) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1342) struct extent_status newes;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1343)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1344) newes.es_lblk = end + 1;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1345) newes.es_len = len2;
666525dfbdca0 (Chen Gang 2014-04-07 10:18:56 -0400 1346) block = 0x7FDEADBEEFULL;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1347) if (ext4_es_is_written(&orig_es) ||
9a6633b1a3603 (Theodore Ts'o 2014-02-19 20:15:15 -0500 1348) ext4_es_is_unwritten(&orig_es))
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1349) block = ext4_es_pblock(&orig_es) +
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1350) orig_es.es_len - len2;
9a6633b1a3603 (Theodore Ts'o 2014-02-19 20:15:15 -0500 1351) ext4_es_store_pblock_status(&newes, block,
9a6633b1a3603 (Theodore Ts'o 2014-02-19 20:15:15 -0500 1352) ext4_es_status(&orig_es));
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 1353) err = __es_insert_extent(inode, &newes);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1354) if (err) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1355) es->es_lblk = orig_es.es_lblk;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1356) es->es_len = orig_es.es_len;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1357) if ((err == -ENOMEM) &&
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1358) __es_shrink(EXT4_SB(inode->i_sb),
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1359) 128, EXT4_I(inode)))
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1360) goto retry;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1361) goto out;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1362) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1363) } else {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1364) es->es_lblk = end + 1;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1365) es->es_len = len2;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1366) if (ext4_es_is_written(es) ||
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1367) ext4_es_is_unwritten(es)) {
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1368) block = orig_es.es_pblk + orig_es.es_len - len2;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1369) ext4_es_store_pblock(es, block);
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1370) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1371) }
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1372) if (count_reserved)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1373) count_rsvd(inode, lblk, orig_es.es_len - len1 - len2,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1374) &orig_es, &rc);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1375) goto out;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1376) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1377)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1378) if (len1 > 0) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1379) if (count_reserved)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1380) count_rsvd(inode, lblk, orig_es.es_len - len1,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1381) &orig_es, &rc);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1382) node = rb_next(&es->rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1383) if (node)
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1384) es = rb_entry(node, struct extent_status, rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1385) else
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1386) es = NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1387) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1388)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1389) while (es && ext4_es_end(es) <= end) {
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1390) if (count_reserved)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1391) count_rsvd(inode, es->es_lblk, es->es_len, es, &rc);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1392) node = rb_next(&es->rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1393) rb_erase(&es->rb_node, &tree->root);
bdedbb7b8d5b9 (Zheng Liu 2013-02-18 00:32:02 -0500 1394) ext4_es_free_extent(inode, es);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1395) if (!node) {
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1396) es = NULL;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1397) break;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1398) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1399) es = rb_entry(node, struct extent_status, rb_node);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1400) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1401)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1402) if (es && es->es_lblk < end + 1) {
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1403) ext4_lblk_t orig_len = es->es_len;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1404)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1405) len1 = ext4_es_end(es) - end;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1406) if (count_reserved)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1407) count_rsvd(inode, es->es_lblk, orig_len - len1,
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1408) es, &rc);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1409) es->es_lblk = end + 1;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1410) es->es_len = len1;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1411) if (ext4_es_is_written(es) || ext4_es_is_unwritten(es)) {
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1412) block = es->es_pblk + orig_len - len1;
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1413) ext4_es_store_pblock(es, block);
fdc0212e86ca1 (Zheng Liu 2013-02-18 00:26:51 -0500 1414) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1415) }
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1416)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1417) if (count_reserved)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1418) *reserved = get_rsvd(inode, end, es, &rc);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1419) out:
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1420) return err;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1421) }
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1422)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1423) /*
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1424) * ext4_es_remove_extent - removes block range from extent status tree
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1425) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1426) * @inode - file containing range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1427) * @lblk - first block in range
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1428) * @len - number of blocks to remove
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1429) *
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1430) * Reduces block/cluster reservation count and for bigalloc cancels pending
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1431) * reservations as needed. Returns 0 on success, error code on failure.
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1432) */
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1433) int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1434) ext4_lblk_t len)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1435) {
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1436) ext4_lblk_t end;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1437) int err = 0;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1438) int reserved = 0;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1439)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 1440) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 1441) return 0;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 1442)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1443) trace_ext4_es_remove_extent(inode, lblk, len);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1444) es_debug("remove [%u/%u) from extent status tree of inode %lu\n",
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1445) lblk, len, inode->i_ino);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1446)
d438147211110 (Eryu Guan 2013-02-22 15:27:47 -0500 1447) if (!len)
d438147211110 (Eryu Guan 2013-02-22 15:27:47 -0500 1448) return err;
d438147211110 (Eryu Guan 2013-02-22 15:27:47 -0500 1449)
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1450) end = lblk + len - 1;
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1451) BUG_ON(end < lblk);
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1452)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1453) /*
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1454) * ext4_clear_inode() depends on us taking i_es_lock unconditionally
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1455) * so that we are sure __es_shrink() is done with the inode before it
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1456) * is reclaimed.
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1457) */
06b0c886214a2 (Zheng Liu 2013-02-18 00:26:51 -0500 1458) write_lock(&EXT4_I(inode)->i_es_lock);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1459) err = __es_remove_extent(inode, lblk, end, &reserved);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1460) write_unlock(&EXT4_I(inode)->i_es_lock);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1461) ext4_es_print_tree(inode);
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1462) ext4_da_release_space(inode, reserved);
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1463) return err;
654598bef3731 (Zheng Liu 2012-11-08 21:57:20 -0500 1464) }
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1465)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1466) static int __es_shrink(struct ext4_sb_info *sbi, int nr_to_scan,
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1467) struct ext4_inode_info *locked_ei)
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1468) {
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1469) struct ext4_inode_info *ei;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1470) struct ext4_es_stats *es_stats;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1471) ktime_t start_time;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1472) u64 scan_time;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1473) int nr_to_walk;
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1474) int nr_shrunk = 0;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1475) int retried = 0, nr_skipped = 0;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1476)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1477) es_stats = &sbi->s_es_stats;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1478) start_time = ktime_get();
d3922a777f9b4 (Zheng Liu 2013-07-01 08:12:37 -0400 1479)
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1480) retry:
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1481) spin_lock(&sbi->s_es_lock);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1482) nr_to_walk = sbi->s_es_nr_inode;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1483) while (nr_to_walk-- > 0) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1484) if (list_empty(&sbi->s_es_list)) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1485) spin_unlock(&sbi->s_es_lock);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1486) goto out;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1487) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1488) ei = list_first_entry(&sbi->s_es_list, struct ext4_inode_info,
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1489) i_es_list);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1490) /* Move the inode to the tail */
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1491) list_move_tail(&ei->i_es_list, &sbi->s_es_list);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1492)
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1493) /*
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1494) * Normally we try hard to avoid shrinking precached inodes,
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1495) * but we will as a last resort.
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1496) */
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1497) if (!retried && ext4_test_inode_state(&ei->vfs_inode,
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1498) EXT4_STATE_EXT_PRECACHED)) {
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1499) nr_skipped++;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1500) continue;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1501) }
d3922a777f9b4 (Zheng Liu 2013-07-01 08:12:37 -0400 1502)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1503) if (ei == locked_ei || !write_trylock(&ei->i_es_lock)) {
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1504) nr_skipped++;
d3922a777f9b4 (Zheng Liu 2013-07-01 08:12:37 -0400 1505) continue;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1506) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1507) /*
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1508) * Now we hold i_es_lock which protects us from inode reclaim
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1509) * freeing inode under us
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1510) */
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1511) spin_unlock(&sbi->s_es_lock);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1512)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1513) nr_shrunk += es_reclaim_extents(ei, &nr_to_scan);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1514) write_unlock(&ei->i_es_lock);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1515)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1516) if (nr_to_scan <= 0)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1517) goto out;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1518) spin_lock(&sbi->s_es_lock);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1519) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1520) spin_unlock(&sbi->s_es_lock);
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1521)
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1522) /*
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1523) * If we skipped any inodes, and we weren't able to make any
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1524) * forward progress, try again to scan precached inodes.
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1525) */
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1526) if ((nr_shrunk == 0) && nr_skipped && !retried) {
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1527) retried++;
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1528) goto retry;
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1529) }
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1530)
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1531) if (locked_ei && nr_shrunk == 0)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1532) nr_shrunk = es_reclaim_extents(locked_ei, &nr_to_scan);
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1533)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1534) out:
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1535) scan_time = ktime_to_ns(ktime_sub(ktime_get(), start_time));
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1536) if (likely(es_stats->es_stats_scan_time))
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1537) es_stats->es_stats_scan_time = (scan_time +
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1538) es_stats->es_stats_scan_time*3) / 4;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1539) else
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1540) es_stats->es_stats_scan_time = scan_time;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1541) if (scan_time > es_stats->es_stats_max_scan_time)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1542) es_stats->es_stats_max_scan_time = scan_time;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1543) if (likely(es_stats->es_stats_shrunk))
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1544) es_stats->es_stats_shrunk = (nr_shrunk +
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1545) es_stats->es_stats_shrunk*3) / 4;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1546) else
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1547) es_stats->es_stats_shrunk = nr_shrunk;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1548)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1549) trace_ext4_es_shrink(sbi->s_sb, nr_shrunk, scan_time,
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1550) nr_skipped, retried);
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1551) return nr_shrunk;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1552) }
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1553)
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1554) static unsigned long ext4_es_count(struct shrinker *shrink,
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1555) struct shrink_control *sc)
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1556) {
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1557) unsigned long nr;
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1558) struct ext4_sb_info *sbi;
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1559)
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1560) sbi = container_of(shrink, struct ext4_sb_info, s_es_shrinker);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1561) nr = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt);
e963bb1de415a (Zheng Liu 2014-09-01 22:22:13 -0400 1562) trace_ext4_es_shrink_count(sbi->s_sb, sc->nr_to_scan, nr);
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1563) return nr;
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1564) }
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1565)
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1566) static unsigned long ext4_es_scan(struct shrinker *shrink,
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1567) struct shrink_control *sc)
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1568) {
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1569) struct ext4_sb_info *sbi = container_of(shrink,
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1570) struct ext4_sb_info, s_es_shrinker);
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1571) int nr_to_scan = sc->nr_to_scan;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1572) int ret, nr_shrunk;
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1573)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1574) ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt);
e963bb1de415a (Zheng Liu 2014-09-01 22:22:13 -0400 1575) trace_ext4_es_shrink_scan_enter(sbi->s_sb, nr_to_scan, ret);
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1576)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1577) nr_shrunk = __es_shrink(sbi, nr_to_scan, NULL);
e15f742ce8160 (Theodore Ts'o 2013-07-15 00:12:14 -0400 1578)
74983f8c0d03f (Zhang Yi 2021-05-22 18:30:45 +0800 1579) ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt);
e963bb1de415a (Zheng Liu 2014-09-01 22:22:13 -0400 1580) trace_ext4_es_shrink_scan_exit(sbi->s_sb, nr_shrunk, ret);
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1581) return nr_shrunk;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1582) }
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1583)
ebd173beb8db5 (Theodore Ts'o 2015-09-23 12:46:17 -0400 1584) int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v)
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1585) {
ebd173beb8db5 (Theodore Ts'o 2015-09-23 12:46:17 -0400 1586) struct ext4_sb_info *sbi = EXT4_SB((struct super_block *) seq->private);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1587) struct ext4_es_stats *es_stats = &sbi->s_es_stats;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1588) struct ext4_inode_info *ei, *max = NULL;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1589) unsigned int inode_cnt = 0;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1590)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1591) if (v != SEQ_START_TOKEN)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1592) return 0;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1593)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1594) /* here we just find an inode that has the max nr. of objects */
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1595) spin_lock(&sbi->s_es_lock);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1596) list_for_each_entry(ei, &sbi->s_es_list, i_es_list) {
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1597) inode_cnt++;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1598) if (max && max->i_es_all_nr < ei->i_es_all_nr)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1599) max = ei;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1600) else if (!max)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1601) max = ei;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1602) }
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1603) spin_unlock(&sbi->s_es_lock);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1604)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1605) seq_printf(seq, "stats:\n %lld objects\n %lld reclaimable objects\n",
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1606) percpu_counter_sum_positive(&es_stats->es_stats_all_cnt),
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1607) percpu_counter_sum_positive(&es_stats->es_stats_shk_cnt));
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1608) seq_printf(seq, " %lld/%lld cache hits/misses\n",
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1609) percpu_counter_sum_positive(&es_stats->es_stats_cache_hits),
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1610) percpu_counter_sum_positive(&es_stats->es_stats_cache_misses));
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1611) if (inode_cnt)
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1612) seq_printf(seq, " %d inodes on list\n", inode_cnt);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1613)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1614) seq_printf(seq, "average:\n %llu us scan time\n",
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1615) div_u64(es_stats->es_stats_scan_time, 1000));
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1616) seq_printf(seq, " %lu shrunk objects\n", es_stats->es_stats_shrunk);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1617) if (inode_cnt)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1618) seq_printf(seq,
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1619) "maximum:\n %lu inode (%u objects, %u reclaimable)\n"
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1620) " %llu us max scan time\n",
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1621) max->vfs_inode.i_ino, max->i_es_all_nr, max->i_es_shk_nr,
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1622) div_u64(es_stats->es_stats_max_scan_time, 1000));
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1623)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1624) return 0;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1625) }
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1626)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1627) int ext4_es_register_shrinker(struct ext4_sb_info *sbi)
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1628) {
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1629) int err;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1630)
624d0f1dd7c80 (Jan Kara 2014-11-25 11:53:47 -0500 1631) /* Make sure we have enough bits for physical block number */
624d0f1dd7c80 (Jan Kara 2014-11-25 11:53:47 -0500 1632) BUILD_BUG_ON(ES_SHIFT < 48);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1633) INIT_LIST_HEAD(&sbi->s_es_list);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1634) sbi->s_es_nr_inode = 0;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1635) spin_lock_init(&sbi->s_es_lock);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1636) sbi->s_es_stats.es_stats_shrunk = 0;
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1637) err = percpu_counter_init(&sbi->s_es_stats.es_stats_cache_hits, 0,
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1638) GFP_KERNEL);
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1639) if (err)
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1640) return err;
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1641) err = percpu_counter_init(&sbi->s_es_stats.es_stats_cache_misses, 0,
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1642) GFP_KERNEL);
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1643) if (err)
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1644) goto err1;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1645) sbi->s_es_stats.es_stats_scan_time = 0;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1646) sbi->s_es_stats.es_stats_max_scan_time = 0;
c2661b806092d (Linus Torvalds 2014-10-20 09:50:11 -0700 1647) err = percpu_counter_init(&sbi->s_es_stats.es_stats_all_cnt, 0, GFP_KERNEL);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1648) if (err)
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1649) goto err2;
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1650) err = percpu_counter_init(&sbi->s_es_stats.es_stats_shk_cnt, 0, GFP_KERNEL);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1651) if (err)
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1652) goto err3;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1653)
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1654) sbi->s_es_shrinker.scan_objects = ext4_es_scan;
1ab6c4997e04a (Dave Chinner 2013-08-28 10:18:09 +1000 1655) sbi->s_es_shrinker.count_objects = ext4_es_count;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1656) sbi->s_es_shrinker.seeks = DEFAULT_SEEKS;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1657) err = register_shrinker(&sbi->s_es_shrinker);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1658) if (err)
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1659) goto err4;
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1660)
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1661) return 0;
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1662) err4:
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1663) percpu_counter_destroy(&sbi->s_es_stats.es_stats_shk_cnt);
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1664) err3:
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1665) percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1666) err2:
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1667) percpu_counter_destroy(&sbi->s_es_stats.es_stats_cache_misses);
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1668) err1:
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1669) percpu_counter_destroy(&sbi->s_es_stats.es_stats_cache_hits);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1670) return err;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1671) }
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1672)
d3922a777f9b4 (Zheng Liu 2013-07-01 08:12:37 -0400 1673) void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi)
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1674) {
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1675) percpu_counter_destroy(&sbi->s_es_stats.es_stats_cache_hits);
520f897a3554b (Yang Guo 2019-08-28 11:19:23 -0400 1676) percpu_counter_destroy(&sbi->s_es_stats.es_stats_cache_misses);
eb68d0e2fc5a4 (Zheng Liu 2014-09-01 22:26:49 -0400 1677) percpu_counter_destroy(&sbi->s_es_stats.es_stats_all_cnt);
edaa53cac8fd4 (Zheng Liu 2014-11-25 11:45:37 -0500 1678) percpu_counter_destroy(&sbi->s_es_stats.es_stats_shk_cnt);
d3922a777f9b4 (Zheng Liu 2013-07-01 08:12:37 -0400 1679) unregister_shrinker(&sbi->s_es_shrinker);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1680) }
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1681)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1682) /*
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1683) * Shrink extents in given inode from ei->i_es_shrink_lblk till end. Scan at
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1684) * most *nr_to_scan extents, update *nr_to_scan accordingly.
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1685) *
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1686) * Return 0 if we hit end of tree / interval, 1 if we exhausted nr_to_scan.
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1687) * Increment *nr_shrunk by the number of reclaimed extents. Also update
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1688) * ei->i_es_shrink_lblk to where we should continue scanning.
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1689) */
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1690) static int es_do_reclaim_extents(struct ext4_inode_info *ei, ext4_lblk_t end,
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1691) int *nr_to_scan, int *nr_shrunk)
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1692) {
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1693) struct inode *inode = &ei->vfs_inode;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1694) struct ext4_es_tree *tree = &ei->i_es_tree;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1695) struct extent_status *es;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1696) struct rb_node *node;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1697)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1698) es = __es_tree_search(&tree->root, ei->i_es_shrink_lblk);
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1699) if (!es)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1700) goto out_wrap;
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 1701)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1702) while (*nr_to_scan > 0) {
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1703) if (es->es_lblk > end) {
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1704) ei->i_es_shrink_lblk = end + 1;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1705) return 0;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1706) }
7869a4a6c5caa (Theodore Ts'o 2013-08-16 22:05:14 -0400 1707)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1708) (*nr_to_scan)--;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1709) node = rb_next(&es->rb_node);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1710) /*
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1711) * We can't reclaim delayed extent from status tree because
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1712) * fiemap, bigallic, and seek_data/hole need to use it.
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1713) */
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1714) if (ext4_es_is_delayed(es))
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1715) goto next;
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1716) if (ext4_es_is_referenced(es)) {
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1717) ext4_es_clear_referenced(es);
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1718) goto next;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1719) }
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1720)
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1721) rb_erase(&es->rb_node, &tree->root);
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1722) ext4_es_free_extent(inode, es);
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1723) (*nr_shrunk)++;
2be12de98a1cc (Jan Kara 2014-11-25 11:55:24 -0500 1724) next:
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1725) if (!node)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1726) goto out_wrap;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1727) es = rb_entry(node, struct extent_status, rb_node);
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1728) }
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1729) ei->i_es_shrink_lblk = es->es_lblk;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1730) return 1;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1731) out_wrap:
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1732) ei->i_es_shrink_lblk = 0;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1733) return 0;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1734) }
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1735)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1736) static int es_reclaim_extents(struct ext4_inode_info *ei, int *nr_to_scan)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1737) {
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1738) struct inode *inode = &ei->vfs_inode;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1739) int nr_shrunk = 0;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1740) ext4_lblk_t start = ei->i_es_shrink_lblk;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1741) static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1742) DEFAULT_RATELIMIT_BURST);
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1743)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1744) if (ei->i_es_shk_nr == 0)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1745) return 0;
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1746)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1747) if (ext4_test_inode_state(inode, EXT4_STATE_EXT_PRECACHED) &&
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1748) __ratelimit(&_rs))
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1749) ext4_warning(inode->i_sb, "forced shrink of precached extents");
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1750)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1751) if (!es_do_reclaim_extents(ei, EXT_MAX_BLOCKS, nr_to_scan, &nr_shrunk) &&
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1752) start != 0)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1753) es_do_reclaim_extents(ei, start - 1, nr_to_scan, &nr_shrunk);
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1754)
dd47592551887 (Jan Kara 2014-11-25 11:51:23 -0500 1755) ei->i_es_tree.cache_es = NULL;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1756) return nr_shrunk;
74cd15cd02708 (Zheng Liu 2013-02-18 00:32:55 -0500 1757) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1758)
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1759) /*
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1760) * Called to support EXT4_IOC_CLEAR_ES_CACHE. We can only remove
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1761) * discretionary entries from the extent status cache. (Some entries
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1762) * must be present for proper operations.)
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1763) */
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1764) void ext4_clear_inode_es(struct inode *inode)
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1765) {
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1766) struct ext4_inode_info *ei = EXT4_I(inode);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1767) struct extent_status *es;
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1768) struct ext4_es_tree *tree;
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1769) struct rb_node *node;
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1770)
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1771) write_lock(&ei->i_es_lock);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1772) tree = &EXT4_I(inode)->i_es_tree;
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1773) tree->cache_es = NULL;
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1774) node = rb_first(&tree->root);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1775) while (node) {
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1776) es = rb_entry(node, struct extent_status, rb_node);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1777) node = rb_next(node);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1778) if (!ext4_es_is_delayed(es)) {
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1779) rb_erase(&es->rb_node, &tree->root);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1780) ext4_es_free_extent(inode, es);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1781) }
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1782) }
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1783) ext4_clear_inode_state(inode, EXT4_STATE_EXT_PRECACHED);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1784) write_unlock(&ei->i_es_lock);
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1785) }
b0c013e2928d3 (Theodore Ts'o 2019-08-11 16:30:41 -0400 1786)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1787) #ifdef ES_DEBUG__
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1788) static void ext4_print_pending_tree(struct inode *inode)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1789) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1790) struct ext4_pending_tree *tree;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1791) struct rb_node *node;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1792) struct pending_reservation *pr;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1793)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1794) printk(KERN_DEBUG "pending reservations for inode %lu:", inode->i_ino);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1795) tree = &EXT4_I(inode)->i_pending_tree;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1796) node = rb_first(&tree->root);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1797) while (node) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1798) pr = rb_entry(node, struct pending_reservation, rb_node);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1799) printk(KERN_DEBUG " %u", pr->lclu);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1800) node = rb_next(node);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1801) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1802) printk(KERN_DEBUG "\n");
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1803) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1804) #else
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1805) #define ext4_print_pending_tree(inode)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1806) #endif
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1807)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1808) int __init ext4_init_pending(void)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1809) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1810) ext4_pending_cachep = kmem_cache_create("ext4_pending_reservation",
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1811) sizeof(struct pending_reservation),
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1812) 0, (SLAB_RECLAIM_ACCOUNT), NULL);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1813) if (ext4_pending_cachep == NULL)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1814) return -ENOMEM;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1815) return 0;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1816) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1817)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1818) void ext4_exit_pending(void)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1819) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1820) kmem_cache_destroy(ext4_pending_cachep);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1821) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1822)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1823) void ext4_init_pending_tree(struct ext4_pending_tree *tree)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1824) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1825) tree->root = RB_ROOT;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1826) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1827)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1828) /*
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1829) * __get_pending - retrieve a pointer to a pending reservation
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1830) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1831) * @inode - file containing the pending cluster reservation
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1832) * @lclu - logical cluster of interest
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1833) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1834) * Returns a pointer to a pending reservation if it's a member of
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1835) * the set, and NULL if not. Must be called holding i_es_lock.
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1836) */
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1837) static struct pending_reservation *__get_pending(struct inode *inode,
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1838) ext4_lblk_t lclu)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1839) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1840) struct ext4_pending_tree *tree;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1841) struct rb_node *node;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1842) struct pending_reservation *pr = NULL;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1843)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1844) tree = &EXT4_I(inode)->i_pending_tree;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1845) node = (&tree->root)->rb_node;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1846)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1847) while (node) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1848) pr = rb_entry(node, struct pending_reservation, rb_node);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1849) if (lclu < pr->lclu)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1850) node = node->rb_left;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1851) else if (lclu > pr->lclu)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1852) node = node->rb_right;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1853) else if (lclu == pr->lclu)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1854) return pr;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1855) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1856) return NULL;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1857) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1858)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1859) /*
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1860) * __insert_pending - adds a pending cluster reservation to the set of
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1861) * pending reservations
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1862) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1863) * @inode - file containing the cluster
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1864) * @lblk - logical block in the cluster to be added
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1865) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1866) * Returns 0 on successful insertion and -ENOMEM on failure. If the
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1867) * pending reservation is already in the set, returns successfully.
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1868) */
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1869) static int __insert_pending(struct inode *inode, ext4_lblk_t lblk)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1870) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1871) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1872) struct ext4_pending_tree *tree = &EXT4_I(inode)->i_pending_tree;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1873) struct rb_node **p = &tree->root.rb_node;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1874) struct rb_node *parent = NULL;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1875) struct pending_reservation *pr;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1876) ext4_lblk_t lclu;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1877) int ret = 0;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1878)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1879) lclu = EXT4_B2C(sbi, lblk);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1880) /* search to find parent for insertion */
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1881) while (*p) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1882) parent = *p;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1883) pr = rb_entry(parent, struct pending_reservation, rb_node);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1884)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1885) if (lclu < pr->lclu) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1886) p = &(*p)->rb_left;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1887) } else if (lclu > pr->lclu) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1888) p = &(*p)->rb_right;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1889) } else {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1890) /* pending reservation already inserted */
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1891) goto out;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1892) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1893) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1894)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1895) pr = kmem_cache_alloc(ext4_pending_cachep, GFP_ATOMIC);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1896) if (pr == NULL) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1897) ret = -ENOMEM;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1898) goto out;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1899) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1900) pr->lclu = lclu;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1901)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1902) rb_link_node(&pr->rb_node, parent, p);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1903) rb_insert_color(&pr->rb_node, &tree->root);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1904)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1905) out:
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1906) return ret;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1907) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1908)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1909) /*
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1910) * __remove_pending - removes a pending cluster reservation from the set
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1911) * of pending reservations
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1912) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1913) * @inode - file containing the cluster
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1914) * @lblk - logical block in the pending cluster reservation to be removed
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1915) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1916) * Returns successfully if pending reservation is not a member of the set.
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1917) */
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1918) static void __remove_pending(struct inode *inode, ext4_lblk_t lblk)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1919) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1920) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1921) struct pending_reservation *pr;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1922) struct ext4_pending_tree *tree;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1923)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1924) pr = __get_pending(inode, EXT4_B2C(sbi, lblk));
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1925) if (pr != NULL) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1926) tree = &EXT4_I(inode)->i_pending_tree;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1927) rb_erase(&pr->rb_node, &tree->root);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1928) kmem_cache_free(ext4_pending_cachep, pr);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1929) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1930) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1931)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1932) /*
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1933) * ext4_remove_pending - removes a pending cluster reservation from the set
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1934) * of pending reservations
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1935) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1936) * @inode - file containing the cluster
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1937) * @lblk - logical block in the pending cluster reservation to be removed
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1938) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1939) * Locking for external use of __remove_pending.
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1940) */
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1941) void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1942) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1943) struct ext4_inode_info *ei = EXT4_I(inode);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1944)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1945) write_lock(&ei->i_es_lock);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1946) __remove_pending(inode, lblk);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1947) write_unlock(&ei->i_es_lock);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1948) }
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1949)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1950) /*
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1951) * ext4_is_pending - determine whether a cluster has a pending reservation
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1952) * on it
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1953) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1954) * @inode - file containing the cluster
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1955) * @lblk - logical block in the cluster
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1956) *
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1957) * Returns true if there's a pending reservation for the cluster in the
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1958) * set of pending reservations, and false if not.
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1959) */
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1960) bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1961) {
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1962) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1963) struct ext4_inode_info *ei = EXT4_I(inode);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1964) bool ret;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1965)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1966) read_lock(&ei->i_es_lock);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1967) ret = (bool)(__get_pending(inode, EXT4_B2C(sbi, lblk)) != NULL);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1968) read_unlock(&ei->i_es_lock);
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1969)
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1970) return ret;
1dc0aa46e74a3 (Eric Whitney 2018-10-01 14:17:41 -0400 1971) }
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1972)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1973) /*
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1974) * ext4_es_insert_delayed_block - adds a delayed block to the extents status
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1975) * tree, adding a pending reservation where
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1976) * needed
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1977) *
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1978) * @inode - file containing the newly added block
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1979) * @lblk - logical block to be added
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1980) * @allocated - indicates whether a physical cluster has been allocated for
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1981) * the logical cluster that contains the block
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1982) *
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1983) * Returns 0 on success, negative error code on failure.
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1984) */
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1985) int ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk,
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1986) bool allocated)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1987) {
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1988) struct extent_status newes;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1989) int err = 0;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1990)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 1991) if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 1992) return 0;
8016e29f4362e (Harshad Shirwadkar 2020-10-15 13:37:59 -0700 1993)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1994) es_debug("add [%u/1) delayed to extent status tree of inode %lu\n",
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1995) lblk, inode->i_ino);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1996)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1997) newes.es_lblk = lblk;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1998) newes.es_len = 1;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 1999) ext4_es_store_pblock_status(&newes, ~0, EXTENT_STATUS_DELAYED);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2000) trace_ext4_es_insert_delayed_block(inode, &newes, allocated);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2001)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2002) ext4_es_insert_extent_check(inode, &newes);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2003)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2004) write_lock(&EXT4_I(inode)->i_es_lock);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2005)
8fcc3a580651c (Eric Whitney 2019-08-22 23:22:14 -0400 2006) err = __es_remove_extent(inode, lblk, lblk, NULL);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2007) if (err != 0)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2008) goto error;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2009) retry:
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2010) err = __es_insert_extent(inode, &newes);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2011) if (err == -ENOMEM && __es_shrink(EXT4_SB(inode->i_sb),
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2012) 128, EXT4_I(inode)))
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2013) goto retry;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2014) if (err != 0)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2015) goto error;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2016)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2017) if (allocated)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2018) __insert_pending(inode, lblk);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2019)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2020) error:
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2021) write_unlock(&EXT4_I(inode)->i_es_lock);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2022)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2023) ext4_es_print_tree(inode);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2024) ext4_print_pending_tree(inode);
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2025)
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2026) return err;
0b02f4c0d6d9e (Eric Whitney 2018-10-01 14:19:37 -0400 2027) }
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2028)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2029) /*
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2030) * __es_delayed_clu - count number of clusters containing blocks that
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2031) * are delayed only
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2032) *
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2033) * @inode - file containing block range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2034) * @start - logical block defining start of range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2035) * @end - logical block defining end of range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2036) *
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2037) * Returns the number of clusters containing only delayed (not delayed
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2038) * and unwritten) blocks in the range specified by @start and @end. Any
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2039) * cluster or part of a cluster within the range and containing a delayed
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2040) * and not unwritten block within the range is counted as a whole cluster.
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2041) */
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2042) static unsigned int __es_delayed_clu(struct inode *inode, ext4_lblk_t start,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2043) ext4_lblk_t end)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2044) {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2045) struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2046) struct extent_status *es;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2047) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2048) struct rb_node *node;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2049) ext4_lblk_t first_lclu, last_lclu;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2050) unsigned long long last_counted_lclu;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2051) unsigned int n = 0;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2052)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2053) /* guaranteed to be unequal to any ext4_lblk_t value */
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2054) last_counted_lclu = ~0ULL;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2055)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2056) es = __es_tree_search(&tree->root, start);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2057)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2058) while (es && (es->es_lblk <= end)) {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2059) if (ext4_es_is_delonly(es)) {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2060) if (es->es_lblk <= start)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2061) first_lclu = EXT4_B2C(sbi, start);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2062) else
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2063) first_lclu = EXT4_B2C(sbi, es->es_lblk);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2064)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2065) if (ext4_es_end(es) >= end)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2066) last_lclu = EXT4_B2C(sbi, end);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2067) else
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2068) last_lclu = EXT4_B2C(sbi, ext4_es_end(es));
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2069)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2070) if (first_lclu == last_counted_lclu)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2071) n += last_lclu - first_lclu;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2072) else
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2073) n += last_lclu - first_lclu + 1;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2074) last_counted_lclu = last_lclu;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2075) }
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2076) node = rb_next(&es->rb_node);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2077) if (!node)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2078) break;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2079) es = rb_entry(node, struct extent_status, rb_node);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2080) }
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2081)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2082) return n;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2083) }
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2084)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2085) /*
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2086) * ext4_es_delayed_clu - count number of clusters containing blocks that
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2087) * are both delayed and unwritten
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2088) *
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2089) * @inode - file containing block range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2090) * @lblk - logical block defining start of range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2091) * @len - number of blocks in range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2092) *
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2093) * Locking for external use of __es_delayed_clu().
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2094) */
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2095) unsigned int ext4_es_delayed_clu(struct inode *inode, ext4_lblk_t lblk,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2096) ext4_lblk_t len)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2097) {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2098) struct ext4_inode_info *ei = EXT4_I(inode);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2099) ext4_lblk_t end;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2100) unsigned int n;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2101)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2102) if (len == 0)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2103) return 0;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2104)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2105) end = lblk + len - 1;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2106) WARN_ON(end < lblk);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2107)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2108) read_lock(&ei->i_es_lock);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2109)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2110) n = __es_delayed_clu(inode, lblk, end);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2111)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2112) read_unlock(&ei->i_es_lock);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2113)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2114) return n;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2115) }
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2116)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2117) /*
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2118) * __revise_pending - makes, cancels, or leaves unchanged pending cluster
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2119) * reservations for a specified block range depending
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2120) * upon the presence or absence of delayed blocks
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2121) * outside the range within clusters at the ends of the
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2122) * range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2123) *
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2124) * @inode - file containing the range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2125) * @lblk - logical block defining the start of range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2126) * @len - length of range in blocks
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2127) *
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2128) * Used after a newly allocated extent is added to the extents status tree.
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2129) * Requires that the extents in the range have either written or unwritten
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2130) * status. Must be called while holding i_es_lock.
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2131) */
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2132) static void __revise_pending(struct inode *inode, ext4_lblk_t lblk,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2133) ext4_lblk_t len)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2134) {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2135) struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2136) ext4_lblk_t end = lblk + len - 1;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2137) ext4_lblk_t first, last;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2138) bool f_del = false, l_del = false;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2139)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2140) if (len == 0)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2141) return;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2142)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2143) /*
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2144) * Two cases - block range within single cluster and block range
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2145) * spanning two or more clusters. Note that a cluster belonging
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2146) * to a range starting and/or ending on a cluster boundary is treated
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2147) * as if it does not contain a delayed extent. The new range may
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2148) * have allocated space for previously delayed blocks out to the
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2149) * cluster boundary, requiring that any pre-existing pending
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2150) * reservation be canceled. Because this code only looks at blocks
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2151) * outside the range, it should revise pending reservations
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2152) * correctly even if the extent represented by the range can't be
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2153) * inserted in the extents status tree due to ENOSPC.
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2154) */
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2155)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2156) if (EXT4_B2C(sbi, lblk) == EXT4_B2C(sbi, end)) {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2157) first = EXT4_LBLK_CMASK(sbi, lblk);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2158) if (first != lblk)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2159) f_del = __es_scan_range(inode, &ext4_es_is_delonly,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2160) first, lblk - 1);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2161) if (f_del) {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2162) __insert_pending(inode, first);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2163) } else {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2164) last = EXT4_LBLK_CMASK(sbi, end) +
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2165) sbi->s_cluster_ratio - 1;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2166) if (last != end)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2167) l_del = __es_scan_range(inode,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2168) &ext4_es_is_delonly,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2169) end + 1, last);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2170) if (l_del)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2171) __insert_pending(inode, last);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2172) else
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2173) __remove_pending(inode, last);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2174) }
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2175) } else {
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2176) first = EXT4_LBLK_CMASK(sbi, lblk);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2177) if (first != lblk)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2178) f_del = __es_scan_range(inode, &ext4_es_is_delonly,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2179) first, lblk - 1);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2180) if (f_del)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2181) __insert_pending(inode, first);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2182) else
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2183) __remove_pending(inode, first);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2184)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2185) last = EXT4_LBLK_CMASK(sbi, end) + sbi->s_cluster_ratio - 1;
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2186) if (last != end)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2187) l_del = __es_scan_range(inode, &ext4_es_is_delonly,
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2188) end + 1, last);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2189) if (l_del)
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2190) __insert_pending(inode, last);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2191) else
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2192) __remove_pending(inode, last);
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2193) }
b6bf9171ef5c3 (Eric Whitney 2018-10-01 14:24:08 -0400 2194) }