Blame view
fs/btrfs/free-space-cache.c
107 KB
c1d7c514f btrfs: replace GP... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
0f9dd46cd Btrfs: free space... |
2 3 |
/* * Copyright (C) 2008 Red Hat. All rights reserved. |
0f9dd46cd Btrfs: free space... |
4 |
*/ |
963030817 Btrfs: use hybrid... |
5 |
#include <linux/pagemap.h> |
0f9dd46cd Btrfs: free space... |
6 |
#include <linux/sched.h> |
f361bf4a6 sched/headers: Pr... |
7 |
#include <linux/sched/signal.h> |
5a0e3ad6a include cleanup: ... |
8 |
#include <linux/slab.h> |
963030817 Btrfs: use hybrid... |
9 |
#include <linux/math64.h> |
6ab60601d Btrfs: ratelimit ... |
10 |
#include <linux/ratelimit.h> |
540adea38 error-injection: ... |
11 |
#include <linux/error-injection.h> |
84de76a2f btrfs: protect sp... |
12 |
#include <linux/sched/mm.h> |
0f9dd46cd Btrfs: free space... |
13 |
#include "ctree.h" |
fa9c0d795 Btrfs: rework all... |
14 15 |
#include "free-space-cache.h" #include "transaction.h" |
0af3d00ba Btrfs: create spe... |
16 |
#include "disk-io.h" |
43be21462 Btrfs: fix free s... |
17 |
#include "extent_io.h" |
581bb0509 Btrfs: Cache free... |
18 |
#include "inode-map.h" |
04216820f Btrfs: fix race b... |
19 |
#include "volumes.h" |
8719aaae8 btrfs: move space... |
20 |
#include "space-info.h" |
867363429 btrfs: migrate th... |
21 |
#include "delalloc-space.h" |
aac0023c2 btrfs: move basic... |
22 |
#include "block-group.h" |
b0643e59c btrfs: add the be... |
23 |
#include "discard.h" |
fa9c0d795 Btrfs: rework all... |
24 |
|
0ef6447a3 Btrfs: Fix intege... |
25 |
#define BITS_PER_BITMAP (PAGE_SIZE * 8UL) |
5d90c5c75 btrfs: increase t... |
26 27 |
#define MAX_CACHE_BYTES_PER_GIG SZ_64K #define FORCE_EXTENT_THRESHOLD SZ_1M |
0f9dd46cd Btrfs: free space... |
28 |
|
55507ce36 Btrfs: fix race b... |
29 30 31 32 33 |
struct btrfs_trim_range { u64 start; u64 bytes; struct list_head list; }; |
dfb79ddb1 btrfs: track disc... |
34 35 |
static int count_bitmap_extents(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *bitmap_info); |
34d52cb6c Btrfs: Make free ... |
36 |
static int link_free_space(struct btrfs_free_space_ctl *ctl, |
0cb59c995 Btrfs: write out ... |
37 |
struct btrfs_free_space *info); |
cd023e7b1 Btrfs: merge cont... |
38 39 |
static void unlink_free_space(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info); |
afdb57189 btrfs: simplify b... |
40 41 42 43 |
static int btrfs_wait_cache_io_root(struct btrfs_root *root, struct btrfs_trans_handle *trans, struct btrfs_io_ctl *io_ctl, struct btrfs_path *path); |
0cb59c995 Btrfs: write out ... |
44 |
|
0414efae7 Btrfs: Make the c... |
45 46 47 |
static struct inode *__lookup_free_space_inode(struct btrfs_root *root, struct btrfs_path *path, u64 offset) |
0af3d00ba Btrfs: create spe... |
48 |
{ |
0b246afa6 btrfs: root->fs_i... |
49 |
struct btrfs_fs_info *fs_info = root->fs_info; |
0af3d00ba Btrfs: create spe... |
50 51 52 53 54 55 |
struct btrfs_key key; struct btrfs_key location; struct btrfs_disk_key disk_key; struct btrfs_free_space_header *header; struct extent_buffer *leaf; struct inode *inode = NULL; |
84de76a2f btrfs: protect sp... |
56 |
unsigned nofs_flag; |
0af3d00ba Btrfs: create spe... |
57 |
int ret; |
0af3d00ba Btrfs: create spe... |
58 |
key.objectid = BTRFS_FREE_SPACE_OBJECTID; |
0414efae7 Btrfs: Make the c... |
59 |
key.offset = offset; |
0af3d00ba Btrfs: create spe... |
60 61 62 63 64 65 |
key.type = 0; ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) return ERR_PTR(ret); if (ret > 0) { |
b3b4aa74b btrfs: drop unuse... |
66 |
btrfs_release_path(path); |
0af3d00ba Btrfs: create spe... |
67 68 69 70 71 72 73 74 |
return ERR_PTR(-ENOENT); } leaf = path->nodes[0]; header = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_free_space_header); btrfs_free_space_key(leaf, header, &disk_key); btrfs_disk_key_to_cpu(&location, &disk_key); |
b3b4aa74b btrfs: drop unuse... |
75 |
btrfs_release_path(path); |
0af3d00ba Btrfs: create spe... |
76 |
|
84de76a2f btrfs: protect sp... |
77 78 79 80 81 |
/* * We are often under a trans handle at this point, so we need to make * sure NOFS is set to keep us from deadlocking. */ nofs_flag = memalloc_nofs_save(); |
0202e83fd btrfs: simplify i... |
82 |
inode = btrfs_iget_path(fs_info->sb, location.objectid, root, path); |
4222ea710 Btrfs: fix deadlo... |
83 |
btrfs_release_path(path); |
84de76a2f btrfs: protect sp... |
84 |
memalloc_nofs_restore(nofs_flag); |
0af3d00ba Btrfs: create spe... |
85 86 |
if (IS_ERR(inode)) return inode; |
0af3d00ba Btrfs: create spe... |
87 |
|
528c03276 btrfs: trivial en... |
88 |
mapping_set_gfp_mask(inode->i_mapping, |
c62d25556 mm, fs: introduce... |
89 90 |
mapping_gfp_constraint(inode->i_mapping, ~(__GFP_FS | __GFP_HIGHMEM))); |
adae52b94 btrfs: clear __GF... |
91 |
|
0414efae7 Btrfs: Make the c... |
92 93 |
return inode; } |
32da5386d btrfs: rename btr... |
94 |
struct inode *lookup_free_space_inode(struct btrfs_block_group *block_group, |
7949f3392 btrfs: get fs_inf... |
95 |
struct btrfs_path *path) |
0414efae7 Btrfs: Make the c... |
96 |
{ |
7949f3392 btrfs: get fs_inf... |
97 |
struct btrfs_fs_info *fs_info = block_group->fs_info; |
0414efae7 Btrfs: Make the c... |
98 |
struct inode *inode = NULL; |
5b0e95bf6 Btrfs: inline che... |
99 |
u32 flags = BTRFS_INODE_NODATASUM | BTRFS_INODE_NODATACOW; |
0414efae7 Btrfs: Make the c... |
100 101 102 103 104 105 106 |
spin_lock(&block_group->lock); if (block_group->inode) inode = igrab(block_group->inode); spin_unlock(&block_group->lock); if (inode) return inode; |
77ab86bf1 btrfs: free-space... |
107 |
inode = __lookup_free_space_inode(fs_info->tree_root, path, |
b3470b5db btrfs: add dedica... |
108 |
block_group->start); |
0414efae7 Btrfs: Make the c... |
109 110 |
if (IS_ERR(inode)) return inode; |
0af3d00ba Btrfs: create spe... |
111 |
spin_lock(&block_group->lock); |
5b0e95bf6 Btrfs: inline che... |
112 |
if (!((BTRFS_I(inode)->flags & flags) == flags)) { |
0b246afa6 btrfs: root->fs_i... |
113 |
btrfs_info(fs_info, "Old style space inode found, converting."); |
5b0e95bf6 Btrfs: inline che... |
114 115 |
BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM | BTRFS_INODE_NODATACOW; |
2f356126c Btrfs: use the no... |
116 117 |
block_group->disk_cache_state = BTRFS_DC_CLEAR; } |
300e4f8a5 Btrfs: put the bl... |
118 |
if (!block_group->iref) { |
0af3d00ba Btrfs: create spe... |
119 120 121 122 123 124 125 |
block_group->inode = igrab(inode); block_group->iref = 1; } spin_unlock(&block_group->lock); return inode; } |
48a3b6366 btrfs: make stati... |
126 127 128 129 |
static int __create_free_space_inode(struct btrfs_root *root, struct btrfs_trans_handle *trans, struct btrfs_path *path, u64 ino, u64 offset) |
0af3d00ba Btrfs: create spe... |
130 131 132 133 134 135 |
{ struct btrfs_key key; struct btrfs_disk_key disk_key; struct btrfs_free_space_header *header; struct btrfs_inode_item *inode_item; struct extent_buffer *leaf; |
5b0e95bf6 Btrfs: inline che... |
136 |
u64 flags = BTRFS_INODE_NOCOMPRESS | BTRFS_INODE_PREALLOC; |
0af3d00ba Btrfs: create spe... |
137 |
int ret; |
0414efae7 Btrfs: Make the c... |
138 |
ret = btrfs_insert_empty_inode(trans, root, path, ino); |
0af3d00ba Btrfs: create spe... |
139 140 |
if (ret) return ret; |
5b0e95bf6 Btrfs: inline che... |
141 142 143 |
/* We inline crc's for the free disk space cache */ if (ino != BTRFS_FREE_INO_OBJECTID) flags |= BTRFS_INODE_NODATASUM | BTRFS_INODE_NODATACOW; |
0af3d00ba Btrfs: create spe... |
144 145 146 147 |
leaf = path->nodes[0]; inode_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_inode_item); btrfs_item_key(leaf, &disk_key, path->slots[0]); |
b159fa280 btrfs: remove con... |
148 |
memzero_extent_buffer(leaf, (unsigned long)inode_item, |
0af3d00ba Btrfs: create spe... |
149 150 151 152 153 154 155 |
sizeof(*inode_item)); btrfs_set_inode_generation(leaf, inode_item, trans->transid); btrfs_set_inode_size(leaf, inode_item, 0); btrfs_set_inode_nbytes(leaf, inode_item, 0); btrfs_set_inode_uid(leaf, inode_item, 0); btrfs_set_inode_gid(leaf, inode_item, 0); btrfs_set_inode_mode(leaf, inode_item, S_IFREG | 0600); |
5b0e95bf6 Btrfs: inline che... |
156 |
btrfs_set_inode_flags(leaf, inode_item, flags); |
0af3d00ba Btrfs: create spe... |
157 158 |
btrfs_set_inode_nlink(leaf, inode_item, 1); btrfs_set_inode_transid(leaf, inode_item, trans->transid); |
0414efae7 Btrfs: Make the c... |
159 |
btrfs_set_inode_block_group(leaf, inode_item, offset); |
0af3d00ba Btrfs: create spe... |
160 |
btrfs_mark_buffer_dirty(leaf); |
b3b4aa74b btrfs: drop unuse... |
161 |
btrfs_release_path(path); |
0af3d00ba Btrfs: create spe... |
162 163 |
key.objectid = BTRFS_FREE_SPACE_OBJECTID; |
0414efae7 Btrfs: Make the c... |
164 |
key.offset = offset; |
0af3d00ba Btrfs: create spe... |
165 |
key.type = 0; |
0af3d00ba Btrfs: create spe... |
166 167 168 |
ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(struct btrfs_free_space_header)); if (ret < 0) { |
b3b4aa74b btrfs: drop unuse... |
169 |
btrfs_release_path(path); |
0af3d00ba Btrfs: create spe... |
170 171 |
return ret; } |
c9dc4c657 Btrfs: two stage ... |
172 |
|
0af3d00ba Btrfs: create spe... |
173 174 175 |
leaf = path->nodes[0]; header = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_free_space_header); |
b159fa280 btrfs: remove con... |
176 |
memzero_extent_buffer(leaf, (unsigned long)header, sizeof(*header)); |
0af3d00ba Btrfs: create spe... |
177 178 |
btrfs_set_free_space_key(leaf, header, &disk_key); btrfs_mark_buffer_dirty(leaf); |
b3b4aa74b btrfs: drop unuse... |
179 |
btrfs_release_path(path); |
0af3d00ba Btrfs: create spe... |
180 181 182 |
return 0; } |
4ca75f1bd btrfs: get fs_inf... |
183 |
int create_free_space_inode(struct btrfs_trans_handle *trans, |
32da5386d btrfs: rename btr... |
184 |
struct btrfs_block_group *block_group, |
0414efae7 Btrfs: Make the c... |
185 186 187 188 |
struct btrfs_path *path) { int ret; u64 ino; |
4ca75f1bd btrfs: get fs_inf... |
189 |
ret = btrfs_find_free_objectid(trans->fs_info->tree_root, &ino); |
0414efae7 Btrfs: Make the c... |
190 191 |
if (ret < 0) return ret; |
4ca75f1bd btrfs: get fs_inf... |
192 |
return __create_free_space_inode(trans->fs_info->tree_root, trans, path, |
b3470b5db btrfs: add dedica... |
193 |
ino, block_group->start); |
0414efae7 Btrfs: Make the c... |
194 |
} |
2ff7e61e0 btrfs: take an fs... |
195 |
int btrfs_check_trunc_cache_free_space(struct btrfs_fs_info *fs_info, |
7b61cd922 Btrfs: don't use ... |
196 |
struct btrfs_block_rsv *rsv) |
0af3d00ba Btrfs: create spe... |
197 |
{ |
c8174313a Btrfs: use the gl... |
198 |
u64 needed_bytes; |
7b61cd922 Btrfs: don't use ... |
199 |
int ret; |
c8174313a Btrfs: use the gl... |
200 201 |
/* 1 for slack space, 1 for updating the inode */ |
2bd36e7b4 btrfs: rename the... |
202 203 |
needed_bytes = btrfs_calc_insert_metadata_size(fs_info, 1) + btrfs_calc_metadata_size(fs_info, 1); |
c8174313a Btrfs: use the gl... |
204 |
|
7b61cd922 Btrfs: don't use ... |
205 206 207 208 209 210 |
spin_lock(&rsv->lock); if (rsv->reserved < needed_bytes) ret = -ENOSPC; else ret = 0; spin_unlock(&rsv->lock); |
4b286cd1f Btrfs: return err... |
211 |
return ret; |
7b61cd922 Btrfs: don't use ... |
212 |
} |
77ab86bf1 btrfs: free-space... |
213 |
int btrfs_truncate_free_space_cache(struct btrfs_trans_handle *trans, |
32da5386d btrfs: rename btr... |
214 |
struct btrfs_block_group *block_group, |
7b61cd922 Btrfs: don't use ... |
215 216 |
struct inode *inode) { |
77ab86bf1 btrfs: free-space... |
217 |
struct btrfs_root *root = BTRFS_I(inode)->root; |
7b61cd922 Btrfs: don't use ... |
218 |
int ret = 0; |
35c766425 Btrfs: fix mutex ... |
219 |
bool locked = false; |
1bbc621ef Btrfs: allow bloc... |
220 |
|
1bbc621ef Btrfs: allow bloc... |
221 |
if (block_group) { |
21e75ffe3 btrfs: btrfs_trun... |
222 223 224 225 226 227 |
struct btrfs_path *path = btrfs_alloc_path(); if (!path) { ret = -ENOMEM; goto fail; } |
35c766425 Btrfs: fix mutex ... |
228 |
locked = true; |
1bbc621ef Btrfs: allow bloc... |
229 230 231 |
mutex_lock(&trans->transaction->cache_write_mutex); if (!list_empty(&block_group->io_list)) { list_del_init(&block_group->io_list); |
afdb57189 btrfs: simplify b... |
232 |
btrfs_wait_cache_io(trans, block_group, path); |
1bbc621ef Btrfs: allow bloc... |
233 234 235 236 237 238 239 240 241 242 |
btrfs_put_block_group(block_group); } /* * now that we've truncated the cache away, its no longer * setup or written */ spin_lock(&block_group->lock); block_group->disk_cache_state = BTRFS_DC_CLEAR; spin_unlock(&block_group->lock); |
21e75ffe3 btrfs: btrfs_trun... |
243 |
btrfs_free_path(path); |
1bbc621ef Btrfs: allow bloc... |
244 |
} |
0af3d00ba Btrfs: create spe... |
245 |
|
6ef06d279 btrfs: Make btrfs... |
246 |
btrfs_i_size_write(BTRFS_I(inode), 0); |
7caef2676 truncate: drop 'o... |
247 |
truncate_pagecache(inode, 0); |
0af3d00ba Btrfs: create spe... |
248 249 |
/* |
f7e9e8fc7 Btrfs: stop creat... |
250 251 |
* We skip the throttling logic for free space cache inodes, so we don't * need to check for -EAGAIN. |
0af3d00ba Btrfs: create spe... |
252 253 254 |
*/ ret = btrfs_truncate_inode_items(trans, root, inode, 0, BTRFS_EXTENT_DATA_KEY); |
35c766425 Btrfs: fix mutex ... |
255 256 |
if (ret) goto fail; |
0af3d00ba Btrfs: create spe... |
257 |
|
82d5902d9 Btrfs: Support re... |
258 |
ret = btrfs_update_inode(trans, root, inode); |
1bbc621ef Btrfs: allow bloc... |
259 |
|
1bbc621ef Btrfs: allow bloc... |
260 |
fail: |
35c766425 Btrfs: fix mutex ... |
261 262 |
if (locked) mutex_unlock(&trans->transaction->cache_write_mutex); |
79787eaab btrfs: replace ma... |
263 |
if (ret) |
66642832f btrfs: btrfs_abor... |
264 |
btrfs_abort_transaction(trans, ret); |
c8174313a Btrfs: use the gl... |
265 |
|
82d5902d9 Btrfs: Support re... |
266 |
return ret; |
0af3d00ba Btrfs: create spe... |
267 |
} |
1d4805386 btrfs: make space... |
268 |
static void readahead_cache(struct inode *inode) |
9d66e233c Btrfs: load free ... |
269 270 271 272 273 274 |
{ struct file_ra_state *ra; unsigned long last_index; ra = kzalloc(sizeof(*ra), GFP_NOFS); if (!ra) |
1d4805386 btrfs: make space... |
275 |
return; |
9d66e233c Btrfs: load free ... |
276 277 |
file_ra_state_init(ra, inode->i_mapping); |
09cbfeaf1 mm, fs: get rid o... |
278 |
last_index = (i_size_read(inode) - 1) >> PAGE_SHIFT; |
9d66e233c Btrfs: load free ... |
279 280 281 282 |
page_cache_sync_readahead(inode->i_mapping, ra, NULL, 0, last_index); kfree(ra); |
9d66e233c Btrfs: load free ... |
283 |
} |
4c6d1d85a btrfs: move struc... |
284 |
static int io_ctl_init(struct btrfs_io_ctl *io_ctl, struct inode *inode, |
f15376df0 btrfs: root->fs_i... |
285 |
int write) |
a67509c30 Btrfs: add a io_c... |
286 |
{ |
5349d6c3f Btrfs: make free ... |
287 288 |
int num_pages; int check_crcs = 0; |
09cbfeaf1 mm, fs: get rid o... |
289 |
num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE); |
5349d6c3f Btrfs: make free ... |
290 |
|
4a0cc7ca6 btrfs: Make btrfs... |
291 |
if (btrfs_ino(BTRFS_I(inode)) != BTRFS_FREE_INO_OBJECTID) |
5349d6c3f Btrfs: make free ... |
292 |
check_crcs = 1; |
8f6c72a9e Btrfs: free space... |
293 |
/* Make sure we can fit our crcs and generation into the first page */ |
5349d6c3f Btrfs: make free ... |
294 |
if (write && check_crcs && |
8f6c72a9e Btrfs: free space... |
295 |
(num_pages * sizeof(u32) + sizeof(u64)) > PAGE_SIZE) |
5349d6c3f Btrfs: make free ... |
296 |
return -ENOSPC; |
4c6d1d85a btrfs: move struc... |
297 |
memset(io_ctl, 0, sizeof(struct btrfs_io_ctl)); |
5349d6c3f Btrfs: make free ... |
298 |
|
31e818fe7 btrfs: cleanup, u... |
299 |
io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS); |
a67509c30 Btrfs: add a io_c... |
300 301 |
if (!io_ctl->pages) return -ENOMEM; |
5349d6c3f Btrfs: make free ... |
302 303 |
io_ctl->num_pages = num_pages; |
f15376df0 btrfs: root->fs_i... |
304 |
io_ctl->fs_info = btrfs_sb(inode->i_sb); |
5349d6c3f Btrfs: make free ... |
305 |
io_ctl->check_crcs = check_crcs; |
c9dc4c657 Btrfs: two stage ... |
306 |
io_ctl->inode = inode; |
5349d6c3f Btrfs: make free ... |
307 |
|
a67509c30 Btrfs: add a io_c... |
308 309 |
return 0; } |
663faf9f7 error-injection: ... |
310 |
ALLOW_ERROR_INJECTION(io_ctl_init, ERRNO); |
a67509c30 Btrfs: add a io_c... |
311 |
|
4c6d1d85a btrfs: move struc... |
312 |
static void io_ctl_free(struct btrfs_io_ctl *io_ctl) |
a67509c30 Btrfs: add a io_c... |
313 314 |
{ kfree(io_ctl->pages); |
c9dc4c657 Btrfs: two stage ... |
315 |
io_ctl->pages = NULL; |
a67509c30 Btrfs: add a io_c... |
316 |
} |
4c6d1d85a btrfs: move struc... |
317 |
static void io_ctl_unmap_page(struct btrfs_io_ctl *io_ctl) |
a67509c30 Btrfs: add a io_c... |
318 319 |
{ if (io_ctl->cur) { |
a67509c30 Btrfs: add a io_c... |
320 321 322 323 |
io_ctl->cur = NULL; io_ctl->orig = NULL; } } |
4c6d1d85a btrfs: move struc... |
324 |
static void io_ctl_map_page(struct btrfs_io_ctl *io_ctl, int clear) |
a67509c30 Btrfs: add a io_c... |
325 |
{ |
b12d6869f Btrfs: convert al... |
326 |
ASSERT(io_ctl->index < io_ctl->num_pages); |
a67509c30 Btrfs: add a io_c... |
327 |
io_ctl->page = io_ctl->pages[io_ctl->index++]; |
2b1082680 Btrfs: don't use ... |
328 |
io_ctl->cur = page_address(io_ctl->page); |
a67509c30 Btrfs: add a io_c... |
329 |
io_ctl->orig = io_ctl->cur; |
09cbfeaf1 mm, fs: get rid o... |
330 |
io_ctl->size = PAGE_SIZE; |
a67509c30 Btrfs: add a io_c... |
331 |
if (clear) |
619a97429 btrfs: use clear_... |
332 |
clear_page(io_ctl->cur); |
a67509c30 Btrfs: add a io_c... |
333 |
} |
4c6d1d85a btrfs: move struc... |
334 |
static void io_ctl_drop_pages(struct btrfs_io_ctl *io_ctl) |
a67509c30 Btrfs: add a io_c... |
335 336 337 338 339 340 |
{ int i; io_ctl_unmap_page(io_ctl); for (i = 0; i < io_ctl->num_pages; i++) { |
a1ee5a458 Btrfs: avoid poss... |
341 342 343 |
if (io_ctl->pages[i]) { ClearPageChecked(io_ctl->pages[i]); unlock_page(io_ctl->pages[i]); |
09cbfeaf1 mm, fs: get rid o... |
344 |
put_page(io_ctl->pages[i]); |
a1ee5a458 Btrfs: avoid poss... |
345 |
} |
a67509c30 Btrfs: add a io_c... |
346 347 |
} } |
7a195f6db btrfs: make the u... |
348 |
static int io_ctl_prepare_pages(struct btrfs_io_ctl *io_ctl, bool uptodate) |
a67509c30 Btrfs: add a io_c... |
349 350 |
{ struct page *page; |
831fa14f1 btrfs: use inode ... |
351 |
struct inode *inode = io_ctl->inode; |
a67509c30 Btrfs: add a io_c... |
352 353 354 355 356 357 358 359 360 361 362 363 364 |
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping); int i; for (i = 0; i < io_ctl->num_pages; i++) { page = find_or_create_page(inode->i_mapping, i, mask); if (!page) { io_ctl_drop_pages(io_ctl); return -ENOMEM; } io_ctl->pages[i] = page; if (uptodate && !PageUptodate(page)) { btrfs_readpage(NULL, page); lock_page(page); |
3797136b6 btrfs: check page... |
365 366 367 368 369 370 |
if (page->mapping != inode->i_mapping) { btrfs_err(BTRFS_I(inode)->root->fs_info, "free space cache page truncated"); io_ctl_drop_pages(io_ctl); return -EIO; } |
a67509c30 Btrfs: add a io_c... |
371 |
if (!PageUptodate(page)) { |
efe120a06 Btrfs: convert pr... |
372 373 |
btrfs_err(BTRFS_I(inode)->root->fs_info, "error reading free space cache"); |
a67509c30 Btrfs: add a io_c... |
374 375 376 377 378 |
io_ctl_drop_pages(io_ctl); return -EIO; } } } |
f7d61dcd6 Btrfs: clear page... |
379 380 381 382 |
for (i = 0; i < io_ctl->num_pages; i++) { clear_page_dirty_for_io(io_ctl->pages[i]); set_page_extent_mapped(io_ctl->pages[i]); } |
a67509c30 Btrfs: add a io_c... |
383 384 |
return 0; } |
4c6d1d85a btrfs: move struc... |
385 |
static void io_ctl_set_generation(struct btrfs_io_ctl *io_ctl, u64 generation) |
a67509c30 Btrfs: add a io_c... |
386 |
{ |
a67509c30 Btrfs: add a io_c... |
387 388 389 |
io_ctl_map_page(io_ctl, 1); /* |
5b0e95bf6 Btrfs: inline che... |
390 391 |
* Skip the csum areas. If we don't check crcs then we just have a * 64bit chunk at the front of the first page. |
a67509c30 Btrfs: add a io_c... |
392 |
*/ |
5b0e95bf6 Btrfs: inline che... |
393 394 395 396 397 398 399 |
if (io_ctl->check_crcs) { io_ctl->cur += (sizeof(u32) * io_ctl->num_pages); io_ctl->size -= sizeof(u64) + (sizeof(u32) * io_ctl->num_pages); } else { io_ctl->cur += sizeof(u64); io_ctl->size -= sizeof(u64) * 2; } |
a67509c30 Btrfs: add a io_c... |
400 |
|
6994ca367 btrfs: free-space... |
401 |
put_unaligned_le64(generation, io_ctl->cur); |
a67509c30 Btrfs: add a io_c... |
402 |
io_ctl->cur += sizeof(u64); |
a67509c30 Btrfs: add a io_c... |
403 |
} |
4c6d1d85a btrfs: move struc... |
404 |
static int io_ctl_check_generation(struct btrfs_io_ctl *io_ctl, u64 generation) |
a67509c30 Btrfs: add a io_c... |
405 |
{ |
6994ca367 btrfs: free-space... |
406 |
u64 cache_gen; |
a67509c30 Btrfs: add a io_c... |
407 |
|
5b0e95bf6 Btrfs: inline che... |
408 409 410 411 412 413 414 415 416 417 418 419 |
/* * Skip the crc area. If we don't check crcs then we just have a 64bit * chunk at the front of the first page. */ if (io_ctl->check_crcs) { io_ctl->cur += sizeof(u32) * io_ctl->num_pages; io_ctl->size -= sizeof(u64) + (sizeof(u32) * io_ctl->num_pages); } else { io_ctl->cur += sizeof(u64); io_ctl->size -= sizeof(u64) * 2; } |
a67509c30 Btrfs: add a io_c... |
420 |
|
6994ca367 btrfs: free-space... |
421 422 |
cache_gen = get_unaligned_le64(io_ctl->cur); if (cache_gen != generation) { |
f15376df0 btrfs: root->fs_i... |
423 |
btrfs_err_rl(io_ctl->fs_info, |
946473226 btrfs: switch mes... |
424 |
"space cache generation (%llu) does not match inode (%llu)", |
6994ca367 btrfs: free-space... |
425 |
cache_gen, generation); |
a67509c30 Btrfs: add a io_c... |
426 427 428 429 |
io_ctl_unmap_page(io_ctl); return -EIO; } io_ctl->cur += sizeof(u64); |
5b0e95bf6 Btrfs: inline che... |
430 431 |
return 0; } |
4c6d1d85a btrfs: move struc... |
432 |
static void io_ctl_set_crc(struct btrfs_io_ctl *io_ctl, int index) |
5b0e95bf6 Btrfs: inline che... |
433 434 435 436 437 438 439 440 441 442 443 |
{ u32 *tmp; u32 crc = ~(u32)0; unsigned offset = 0; if (!io_ctl->check_crcs) { io_ctl_unmap_page(io_ctl); return; } if (index == 0) |
cb54f2571 btrfs: free-space... |
444 |
offset = sizeof(u32) * io_ctl->num_pages; |
5b0e95bf6 Btrfs: inline che... |
445 |
|
4bb3c2e2b btrfs: use btrfs_... |
446 447 |
crc = btrfs_crc32c(crc, io_ctl->orig + offset, PAGE_SIZE - offset); btrfs_crc32c_final(crc, (u8 *)&crc); |
5b0e95bf6 Btrfs: inline che... |
448 |
io_ctl_unmap_page(io_ctl); |
2b1082680 Btrfs: don't use ... |
449 |
tmp = page_address(io_ctl->pages[0]); |
5b0e95bf6 Btrfs: inline che... |
450 451 |
tmp += index; *tmp = crc; |
5b0e95bf6 Btrfs: inline che... |
452 |
} |
4c6d1d85a btrfs: move struc... |
453 |
static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index) |
5b0e95bf6 Btrfs: inline che... |
454 455 456 457 458 459 460 461 462 463 464 465 |
{ u32 *tmp, val; u32 crc = ~(u32)0; unsigned offset = 0; if (!io_ctl->check_crcs) { io_ctl_map_page(io_ctl, 0); return 0; } if (index == 0) offset = sizeof(u32) * io_ctl->num_pages; |
2b1082680 Btrfs: don't use ... |
466 |
tmp = page_address(io_ctl->pages[0]); |
5b0e95bf6 Btrfs: inline che... |
467 468 |
tmp += index; val = *tmp; |
5b0e95bf6 Btrfs: inline che... |
469 470 |
io_ctl_map_page(io_ctl, 0); |
4bb3c2e2b btrfs: use btrfs_... |
471 472 |
crc = btrfs_crc32c(crc, io_ctl->orig + offset, PAGE_SIZE - offset); btrfs_crc32c_final(crc, (u8 *)&crc); |
5b0e95bf6 Btrfs: inline che... |
473 |
if (val != crc) { |
f15376df0 btrfs: root->fs_i... |
474 |
btrfs_err_rl(io_ctl->fs_info, |
946473226 btrfs: switch mes... |
475 |
"csum mismatch on free space cache"); |
5b0e95bf6 Btrfs: inline che... |
476 477 478 |
io_ctl_unmap_page(io_ctl); return -EIO; } |
a67509c30 Btrfs: add a io_c... |
479 480 |
return 0; } |
4c6d1d85a btrfs: move struc... |
481 |
static int io_ctl_add_entry(struct btrfs_io_ctl *io_ctl, u64 offset, u64 bytes, |
a67509c30 Btrfs: add a io_c... |
482 483 484 485 486 487 488 489 |
void *bitmap) { struct btrfs_free_space_entry *entry; if (!io_ctl->cur) return -ENOSPC; entry = io_ctl->cur; |
6994ca367 btrfs: free-space... |
490 491 |
put_unaligned_le64(offset, &entry->offset); put_unaligned_le64(bytes, &entry->bytes); |
a67509c30 Btrfs: add a io_c... |
492 493 494 495 496 497 498 |
entry->type = (bitmap) ? BTRFS_FREE_SPACE_BITMAP : BTRFS_FREE_SPACE_EXTENT; io_ctl->cur += sizeof(struct btrfs_free_space_entry); io_ctl->size -= sizeof(struct btrfs_free_space_entry); if (io_ctl->size >= sizeof(struct btrfs_free_space_entry)) return 0; |
5b0e95bf6 Btrfs: inline che... |
499 |
io_ctl_set_crc(io_ctl, io_ctl->index - 1); |
a67509c30 Btrfs: add a io_c... |
500 501 502 503 504 505 506 507 508 |
/* No more pages to map */ if (io_ctl->index >= io_ctl->num_pages) return 0; /* map the next page */ io_ctl_map_page(io_ctl, 1); return 0; } |
4c6d1d85a btrfs: move struc... |
509 |
static int io_ctl_add_bitmap(struct btrfs_io_ctl *io_ctl, void *bitmap) |
a67509c30 Btrfs: add a io_c... |
510 511 512 513 514 515 516 517 518 |
{ if (!io_ctl->cur) return -ENOSPC; /* * If we aren't at the start of the current page, unmap this one and * map the next one if there is any left. */ if (io_ctl->cur != io_ctl->orig) { |
5b0e95bf6 Btrfs: inline che... |
519 |
io_ctl_set_crc(io_ctl, io_ctl->index - 1); |
a67509c30 Btrfs: add a io_c... |
520 521 522 523 |
if (io_ctl->index >= io_ctl->num_pages) return -ENOSPC; io_ctl_map_page(io_ctl, 0); } |
69d248045 btrfs: use copy_p... |
524 |
copy_page(io_ctl->cur, bitmap); |
5b0e95bf6 Btrfs: inline che... |
525 |
io_ctl_set_crc(io_ctl, io_ctl->index - 1); |
a67509c30 Btrfs: add a io_c... |
526 527 528 529 |
if (io_ctl->index < io_ctl->num_pages) io_ctl_map_page(io_ctl, 0); return 0; } |
4c6d1d85a btrfs: move struc... |
530 |
static void io_ctl_zero_remaining_pages(struct btrfs_io_ctl *io_ctl) |
a67509c30 Btrfs: add a io_c... |
531 |
{ |
5b0e95bf6 Btrfs: inline che... |
532 533 534 535 536 537 538 539 |
/* * If we're not on the boundary we know we've modified the page and we * need to crc the page. */ if (io_ctl->cur != io_ctl->orig) io_ctl_set_crc(io_ctl, io_ctl->index - 1); else io_ctl_unmap_page(io_ctl); |
a67509c30 Btrfs: add a io_c... |
540 541 542 |
while (io_ctl->index < io_ctl->num_pages) { io_ctl_map_page(io_ctl, 1); |
5b0e95bf6 Btrfs: inline che... |
543 |
io_ctl_set_crc(io_ctl, io_ctl->index - 1); |
a67509c30 Btrfs: add a io_c... |
544 545 |
} } |
4c6d1d85a btrfs: move struc... |
546 |
static int io_ctl_read_entry(struct btrfs_io_ctl *io_ctl, |
5b0e95bf6 Btrfs: inline che... |
547 |
struct btrfs_free_space *entry, u8 *type) |
a67509c30 Btrfs: add a io_c... |
548 549 |
{ struct btrfs_free_space_entry *e; |
2f120c05e Btrfs: only map p... |
550 551 552 553 554 555 556 |
int ret; if (!io_ctl->cur) { ret = io_ctl_check_crc(io_ctl, io_ctl->index); if (ret) return ret; } |
a67509c30 Btrfs: add a io_c... |
557 558 |
e = io_ctl->cur; |
6994ca367 btrfs: free-space... |
559 560 |
entry->offset = get_unaligned_le64(&e->offset); entry->bytes = get_unaligned_le64(&e->bytes); |
5b0e95bf6 Btrfs: inline che... |
561 |
*type = e->type; |
a67509c30 Btrfs: add a io_c... |
562 563 564 565 |
io_ctl->cur += sizeof(struct btrfs_free_space_entry); io_ctl->size -= sizeof(struct btrfs_free_space_entry); if (io_ctl->size >= sizeof(struct btrfs_free_space_entry)) |
5b0e95bf6 Btrfs: inline che... |
566 |
return 0; |
a67509c30 Btrfs: add a io_c... |
567 568 |
io_ctl_unmap_page(io_ctl); |
2f120c05e Btrfs: only map p... |
569 |
return 0; |
a67509c30 Btrfs: add a io_c... |
570 |
} |
4c6d1d85a btrfs: move struc... |
571 |
static int io_ctl_read_bitmap(struct btrfs_io_ctl *io_ctl, |
5b0e95bf6 Btrfs: inline che... |
572 |
struct btrfs_free_space *entry) |
a67509c30 Btrfs: add a io_c... |
573 |
{ |
5b0e95bf6 Btrfs: inline che... |
574 |
int ret; |
5b0e95bf6 Btrfs: inline che... |
575 576 577 |
ret = io_ctl_check_crc(io_ctl, io_ctl->index); if (ret) return ret; |
69d248045 btrfs: use copy_p... |
578 |
copy_page(entry->bitmap, io_ctl->cur); |
a67509c30 Btrfs: add a io_c... |
579 |
io_ctl_unmap_page(io_ctl); |
5b0e95bf6 Btrfs: inline che... |
580 581 |
return 0; |
a67509c30 Btrfs: add a io_c... |
582 |
} |
cd023e7b1 Btrfs: merge cont... |
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 |
/* * Since we attach pinned extents after the fact we can have contiguous sections * of free space that are split up in entries. This poses a problem with the * tree logging stuff since it could have allocated across what appears to be 2 * entries since we would have merged the entries when adding the pinned extents * back to the free space cache. So run through the space cache that we just * loaded and merge contiguous entries. This will make the log replay stuff not * blow up and it will make for nicer allocator behavior. */ static void merge_space_tree(struct btrfs_free_space_ctl *ctl) { struct btrfs_free_space *e, *prev = NULL; struct rb_node *n; again: spin_lock(&ctl->tree_lock); for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) { e = rb_entry(n, struct btrfs_free_space, offset_index); if (!prev) goto next; if (e->bitmap || prev->bitmap) goto next; if (prev->offset + prev->bytes == e->offset) { unlink_free_space(ctl, prev); unlink_free_space(ctl, e); prev->bytes += e->bytes; kmem_cache_free(btrfs_free_space_cachep, e); link_free_space(ctl, prev); prev = NULL; spin_unlock(&ctl->tree_lock); goto again; } next: prev = e; } spin_unlock(&ctl->tree_lock); } |
48a3b6366 btrfs: make stati... |
620 621 622 |
static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, struct btrfs_free_space_ctl *ctl, struct btrfs_path *path, u64 offset) |
9d66e233c Btrfs: load free ... |
623 |
{ |
3ffbd68c4 btrfs: simplify p... |
624 |
struct btrfs_fs_info *fs_info = root->fs_info; |
9d66e233c Btrfs: load free ... |
625 626 |
struct btrfs_free_space_header *header; struct extent_buffer *leaf; |
4c6d1d85a btrfs: move struc... |
627 |
struct btrfs_io_ctl io_ctl; |
9d66e233c Btrfs: load free ... |
628 |
struct btrfs_key key; |
a67509c30 Btrfs: add a io_c... |
629 |
struct btrfs_free_space *e, *n; |
b76808fc2 btrfs: cleanup in... |
630 |
LIST_HEAD(bitmaps); |
9d66e233c Btrfs: load free ... |
631 632 633 |
u64 num_entries; u64 num_bitmaps; u64 generation; |
a67509c30 Btrfs: add a io_c... |
634 |
u8 type; |
f6a398298 Btrfs: fix duplic... |
635 |
int ret = 0; |
9d66e233c Btrfs: load free ... |
636 |
|
9d66e233c Btrfs: load free ... |
637 |
/* Nothing in the space cache, goodbye */ |
0414efae7 Btrfs: Make the c... |
638 |
if (!i_size_read(inode)) |
a67509c30 Btrfs: add a io_c... |
639 |
return 0; |
9d66e233c Btrfs: load free ... |
640 641 |
key.objectid = BTRFS_FREE_SPACE_OBJECTID; |
0414efae7 Btrfs: Make the c... |
642 |
key.offset = offset; |
9d66e233c Btrfs: load free ... |
643 644 645 |
key.type = 0; ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
0414efae7 Btrfs: Make the c... |
646 |
if (ret < 0) |
a67509c30 Btrfs: add a io_c... |
647 |
return 0; |
0414efae7 Btrfs: Make the c... |
648 |
else if (ret > 0) { |
945d8962c Merge branch 'cle... |
649 |
btrfs_release_path(path); |
a67509c30 Btrfs: add a io_c... |
650 |
return 0; |
9d66e233c Btrfs: load free ... |
651 |
} |
0414efae7 Btrfs: Make the c... |
652 |
ret = -1; |
9d66e233c Btrfs: load free ... |
653 654 655 656 657 658 |
leaf = path->nodes[0]; header = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_free_space_header); num_entries = btrfs_free_space_entries(leaf, header); num_bitmaps = btrfs_free_space_bitmaps(leaf, header); generation = btrfs_free_space_generation(leaf, header); |
945d8962c Merge branch 'cle... |
659 |
btrfs_release_path(path); |
9d66e233c Btrfs: load free ... |
660 |
|
e570fd27f Btrfs: fix broken... |
661 |
if (!BTRFS_I(inode)->generation) { |
0b246afa6 btrfs: root->fs_i... |
662 |
btrfs_info(fs_info, |
913e15357 btrfs: drop newli... |
663 |
"the free space cache file (%llu) is invalid, skip it", |
e570fd27f Btrfs: fix broken... |
664 665 666 |
offset); return 0; } |
9d66e233c Btrfs: load free ... |
667 |
if (BTRFS_I(inode)->generation != generation) { |
0b246afa6 btrfs: root->fs_i... |
668 669 670 |
btrfs_err(fs_info, "free space inode generation (%llu) did not match free space cache generation (%llu)", BTRFS_I(inode)->generation, generation); |
a67509c30 Btrfs: add a io_c... |
671 |
return 0; |
9d66e233c Btrfs: load free ... |
672 673 674 |
} if (!num_entries) |
a67509c30 Btrfs: add a io_c... |
675 |
return 0; |
9d66e233c Btrfs: load free ... |
676 |
|
f15376df0 btrfs: root->fs_i... |
677 |
ret = io_ctl_init(&io_ctl, inode, 0); |
706efc663 Btrfs: check the ... |
678 679 |
if (ret) return ret; |
1d4805386 btrfs: make space... |
680 |
readahead_cache(inode); |
9d66e233c Btrfs: load free ... |
681 |
|
7a195f6db btrfs: make the u... |
682 |
ret = io_ctl_prepare_pages(&io_ctl, true); |
a67509c30 Btrfs: add a io_c... |
683 684 |
if (ret) goto out; |
9d66e233c Btrfs: load free ... |
685 |
|
5b0e95bf6 Btrfs: inline che... |
686 687 688 |
ret = io_ctl_check_crc(&io_ctl, 0); if (ret) goto free_cache; |
a67509c30 Btrfs: add a io_c... |
689 690 691 |
ret = io_ctl_check_generation(&io_ctl, generation); if (ret) goto free_cache; |
9d66e233c Btrfs: load free ... |
692 |
|
a67509c30 Btrfs: add a io_c... |
693 694 695 696 |
while (num_entries) { e = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); if (!e) |
9d66e233c Btrfs: load free ... |
697 |
goto free_cache; |
9d66e233c Btrfs: load free ... |
698 |
|
5b0e95bf6 Btrfs: inline che... |
699 700 701 702 703 |
ret = io_ctl_read_entry(&io_ctl, e, &type); if (ret) { kmem_cache_free(btrfs_free_space_cachep, e); goto free_cache; } |
a7ccb2558 btrfs: keep track... |
704 705 706 |
/* * Sync discard ensures that the free space cache is always * trimmed. So when reading this in, the state should reflect |
b0643e59c btrfs: add the be... |
707 708 |
* that. We also do this for async as a stop gap for lack of * persistence. |
a7ccb2558 btrfs: keep track... |
709 |
*/ |
b0643e59c btrfs: add the be... |
710 711 |
if (btrfs_test_opt(fs_info, DISCARD_SYNC) || btrfs_test_opt(fs_info, DISCARD_ASYNC)) |
a7ccb2558 btrfs: keep track... |
712 |
e->trim_state = BTRFS_TRIM_STATE_TRIMMED; |
a67509c30 Btrfs: add a io_c... |
713 714 715 |
if (!e->bytes) { kmem_cache_free(btrfs_free_space_cachep, e); goto free_cache; |
9d66e233c Btrfs: load free ... |
716 |
} |
a67509c30 Btrfs: add a io_c... |
717 718 719 720 721 722 |
if (type == BTRFS_FREE_SPACE_EXTENT) { spin_lock(&ctl->tree_lock); ret = link_free_space(ctl, e); spin_unlock(&ctl->tree_lock); if (ret) { |
0b246afa6 btrfs: root->fs_i... |
723 |
btrfs_err(fs_info, |
c2cf52eb7 Btrfs: Include th... |
724 |
"Duplicate entries in free space cache, dumping"); |
a67509c30 Btrfs: add a io_c... |
725 |
kmem_cache_free(btrfs_free_space_cachep, e); |
9d66e233c Btrfs: load free ... |
726 727 |
goto free_cache; } |
a67509c30 Btrfs: add a io_c... |
728 |
} else { |
b12d6869f Btrfs: convert al... |
729 |
ASSERT(num_bitmaps); |
a67509c30 Btrfs: add a io_c... |
730 |
num_bitmaps--; |
3acd48507 btrfs: fix alloca... |
731 732 |
e->bitmap = kmem_cache_zalloc( btrfs_free_space_bitmap_cachep, GFP_NOFS); |
a67509c30 Btrfs: add a io_c... |
733 734 735 |
if (!e->bitmap) { kmem_cache_free( btrfs_free_space_cachep, e); |
9d66e233c Btrfs: load free ... |
736 737 |
goto free_cache; } |
a67509c30 Btrfs: add a io_c... |
738 739 740 741 742 743 |
spin_lock(&ctl->tree_lock); ret = link_free_space(ctl, e); ctl->total_bitmaps++; ctl->op->recalc_thresholds(ctl); spin_unlock(&ctl->tree_lock); if (ret) { |
0b246afa6 btrfs: root->fs_i... |
744 |
btrfs_err(fs_info, |
c2cf52eb7 Btrfs: Include th... |
745 |
"Duplicate entries in free space cache, dumping"); |
dc89e9824 Btrfs: use a slab... |
746 |
kmem_cache_free(btrfs_free_space_cachep, e); |
9d66e233c Btrfs: load free ... |
747 748 |
goto free_cache; } |
a67509c30 Btrfs: add a io_c... |
749 |
list_add_tail(&e->list, &bitmaps); |
9d66e233c Btrfs: load free ... |
750 |
} |
a67509c30 Btrfs: add a io_c... |
751 752 |
num_entries--; } |
9d66e233c Btrfs: load free ... |
753 |
|
2f120c05e Btrfs: only map p... |
754 |
io_ctl_unmap_page(&io_ctl); |
a67509c30 Btrfs: add a io_c... |
755 756 757 758 759 |
/* * We add the bitmaps at the end of the entries in order that * the bitmap entries are added to the cache. */ list_for_each_entry_safe(e, n, &bitmaps, list) { |
9d66e233c Btrfs: load free ... |
760 |
list_del_init(&e->list); |
5b0e95bf6 Btrfs: inline che... |
761 762 763 |
ret = io_ctl_read_bitmap(&io_ctl, e); if (ret) goto free_cache; |
dfb79ddb1 btrfs: track disc... |
764 |
e->bitmap_extents = count_bitmap_extents(ctl, e); |
5dc7c10b8 btrfs: keep track... |
765 |
if (!btrfs_free_space_trimmed(e)) { |
dfb79ddb1 btrfs: track disc... |
766 767 |
ctl->discardable_extents[BTRFS_STAT_CURR] += e->bitmap_extents; |
5dc7c10b8 btrfs: keep track... |
768 769 |
ctl->discardable_bytes[BTRFS_STAT_CURR] += e->bytes; } |
9d66e233c Btrfs: load free ... |
770 |
} |
a67509c30 Btrfs: add a io_c... |
771 |
io_ctl_drop_pages(&io_ctl); |
cd023e7b1 Btrfs: merge cont... |
772 |
merge_space_tree(ctl); |
9d66e233c Btrfs: load free ... |
773 774 |
ret = 1; out: |
dfb79ddb1 btrfs: track disc... |
775 |
btrfs_discard_update_discardable(ctl->private, ctl); |
a67509c30 Btrfs: add a io_c... |
776 |
io_ctl_free(&io_ctl); |
9d66e233c Btrfs: load free ... |
777 |
return ret; |
9d66e233c Btrfs: load free ... |
778 |
free_cache: |
a67509c30 Btrfs: add a io_c... |
779 |
io_ctl_drop_pages(&io_ctl); |
0414efae7 Btrfs: Make the c... |
780 |
__btrfs_remove_free_space_cache(ctl); |
9d66e233c Btrfs: load free ... |
781 782 |
goto out; } |
32da5386d btrfs: rename btr... |
783 |
int load_free_space_cache(struct btrfs_block_group *block_group) |
0cb59c995 Btrfs: write out ... |
784 |
{ |
bb6cb1c5b btrfs: get fs_inf... |
785 |
struct btrfs_fs_info *fs_info = block_group->fs_info; |
34d52cb6c Btrfs: Make free ... |
786 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
0414efae7 Btrfs: Make the c... |
787 788 |
struct inode *inode; struct btrfs_path *path; |
5b0e95bf6 Btrfs: inline che... |
789 |
int ret = 0; |
0414efae7 Btrfs: Make the c... |
790 |
bool matched; |
bf38be65f btrfs: move block... |
791 |
u64 used = block_group->used; |
0414efae7 Btrfs: Make the c... |
792 793 |
/* |
0414efae7 Btrfs: Make the c... |
794 795 796 |
* If this block group has been marked to be cleared for one reason or * another then we can't trust the on disk cache, so just return. */ |
9d66e233c Btrfs: load free ... |
797 |
spin_lock(&block_group->lock); |
0414efae7 Btrfs: Make the c... |
798 799 800 801 |
if (block_group->disk_cache_state != BTRFS_DC_WRITTEN) { spin_unlock(&block_group->lock); return 0; } |
9d66e233c Btrfs: load free ... |
802 |
spin_unlock(&block_group->lock); |
0414efae7 Btrfs: Make the c... |
803 804 805 806 |
path = btrfs_alloc_path(); if (!path) return 0; |
d53ba4748 Btrfs: use commit... |
807 808 |
path->search_commit_root = 1; path->skip_locking = 1; |
0414efae7 Btrfs: Make the c... |
809 |
|
4222ea710 Btrfs: fix deadlo... |
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 |
/* * We must pass a path with search_commit_root set to btrfs_iget in * order to avoid a deadlock when allocating extents for the tree root. * * When we are COWing an extent buffer from the tree root, when looking * for a free extent, at extent-tree.c:find_free_extent(), we can find * block group without its free space cache loaded. When we find one * we must load its space cache which requires reading its free space * cache's inode item from the root tree. If this inode item is located * in the same leaf that we started COWing before, then we end up in * deadlock on the extent buffer (trying to read lock it when we * previously write locked it). * * It's safe to read the inode item using the commit root because * block groups, once loaded, stay in memory forever (until they are * removed) as well as their space caches once loaded. New block groups * once created get their ->cached field set to BTRFS_CACHE_FINISHED so * we will never try to read their inode item while the fs is mounted. */ |
7949f3392 btrfs: get fs_inf... |
829 |
inode = lookup_free_space_inode(block_group, path); |
0414efae7 Btrfs: Make the c... |
830 831 832 833 |
if (IS_ERR(inode)) { btrfs_free_path(path); return 0; } |
5b0e95bf6 Btrfs: inline che... |
834 835 836 837 |
/* We may have converted the inode and made the cache invalid. */ spin_lock(&block_group->lock); if (block_group->disk_cache_state != BTRFS_DC_WRITTEN) { spin_unlock(&block_group->lock); |
a7e221e90 Btrfs: fix memory... |
838 |
btrfs_free_path(path); |
5b0e95bf6 Btrfs: inline che... |
839 840 841 |
goto out; } spin_unlock(&block_group->lock); |
0414efae7 Btrfs: Make the c... |
842 |
ret = __load_free_space_cache(fs_info->tree_root, inode, ctl, |
b3470b5db btrfs: add dedica... |
843 |
path, block_group->start); |
0414efae7 Btrfs: Make the c... |
844 845 846 847 848 |
btrfs_free_path(path); if (ret <= 0) goto out; spin_lock(&ctl->tree_lock); |
b3470b5db btrfs: add dedica... |
849 |
matched = (ctl->free_space == (block_group->length - used - |
0414efae7 Btrfs: Make the c... |
850 851 852 853 854 |
block_group->bytes_super)); spin_unlock(&ctl->tree_lock); if (!matched) { __btrfs_remove_free_space_cache(ctl); |
5d163e0e6 btrfs: unsplit pr... |
855 856 |
btrfs_warn(fs_info, "block group %llu has wrong amount of free space", |
b3470b5db btrfs: add dedica... |
857 |
block_group->start); |
0414efae7 Btrfs: Make the c... |
858 859 860 861 862 863 864 865 |
ret = -1; } out: if (ret < 0) { /* This cache is bogus, make sure it gets cleared */ spin_lock(&block_group->lock); block_group->disk_cache_state = BTRFS_DC_CLEAR; spin_unlock(&block_group->lock); |
82d5902d9 Btrfs: Support re... |
866 |
ret = 0; |
0414efae7 Btrfs: Make the c... |
867 |
|
5d163e0e6 btrfs: unsplit pr... |
868 869 |
btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuilding it now", |
b3470b5db btrfs: add dedica... |
870 |
block_group->start); |
0414efae7 Btrfs: Make the c... |
871 872 873 874 |
} iput(inode); return ret; |
9d66e233c Btrfs: load free ... |
875 |
} |
d4452bc52 Btrfs: break up _... |
876 |
static noinline_for_stack |
4c6d1d85a btrfs: move struc... |
877 |
int write_cache_extent_entries(struct btrfs_io_ctl *io_ctl, |
d4452bc52 Btrfs: break up _... |
878 |
struct btrfs_free_space_ctl *ctl, |
32da5386d btrfs: rename btr... |
879 |
struct btrfs_block_group *block_group, |
d4452bc52 Btrfs: break up _... |
880 881 |
int *entries, int *bitmaps, struct list_head *bitmap_list) |
0cb59c995 Btrfs: write out ... |
882 |
{ |
c09544e07 Btrfs: handle eno... |
883 |
int ret; |
d4452bc52 Btrfs: break up _... |
884 |
struct btrfs_free_cluster *cluster = NULL; |
1bbc621ef Btrfs: allow bloc... |
885 |
struct btrfs_free_cluster *cluster_locked = NULL; |
d4452bc52 Btrfs: break up _... |
886 |
struct rb_node *node = rb_first(&ctl->free_space_offset); |
55507ce36 Btrfs: fix race b... |
887 |
struct btrfs_trim_range *trim_entry; |
be1a12a0d Btrfs: deal with ... |
888 |
|
43be21462 Btrfs: fix free s... |
889 |
/* Get the cluster for this block_group if it exists */ |
d4452bc52 Btrfs: break up _... |
890 |
if (block_group && !list_empty(&block_group->cluster_list)) { |
43be21462 Btrfs: fix free s... |
891 892 893 |
cluster = list_entry(block_group->cluster_list.next, struct btrfs_free_cluster, block_group_list); |
d4452bc52 Btrfs: break up _... |
894 |
} |
43be21462 Btrfs: fix free s... |
895 |
|
f75b130e9 Btrfs: don't skip... |
896 |
if (!node && cluster) { |
1bbc621ef Btrfs: allow bloc... |
897 898 |
cluster_locked = cluster; spin_lock(&cluster_locked->lock); |
f75b130e9 Btrfs: don't skip... |
899 900 901 |
node = rb_first(&cluster->root); cluster = NULL; } |
a67509c30 Btrfs: add a io_c... |
902 903 904 |
/* Write out the extent entries */ while (node) { struct btrfs_free_space *e; |
0cb59c995 Btrfs: write out ... |
905 |
|
a67509c30 Btrfs: add a io_c... |
906 |
e = rb_entry(node, struct btrfs_free_space, offset_index); |
d4452bc52 Btrfs: break up _... |
907 |
*entries += 1; |
0cb59c995 Btrfs: write out ... |
908 |
|
d4452bc52 Btrfs: break up _... |
909 |
ret = io_ctl_add_entry(io_ctl, e->offset, e->bytes, |
a67509c30 Btrfs: add a io_c... |
910 911 |
e->bitmap); if (ret) |
d4452bc52 Btrfs: break up _... |
912 |
goto fail; |
2f356126c Btrfs: use the no... |
913 |
|
a67509c30 Btrfs: add a io_c... |
914 |
if (e->bitmap) { |
d4452bc52 Btrfs: break up _... |
915 916 |
list_add_tail(&e->list, bitmap_list); *bitmaps += 1; |
2f356126c Btrfs: use the no... |
917 |
} |
a67509c30 Btrfs: add a io_c... |
918 919 920 |
node = rb_next(node); if (!node && cluster) { node = rb_first(&cluster->root); |
1bbc621ef Btrfs: allow bloc... |
921 922 |
cluster_locked = cluster; spin_lock(&cluster_locked->lock); |
a67509c30 Btrfs: add a io_c... |
923 |
cluster = NULL; |
43be21462 Btrfs: fix free s... |
924 |
} |
a67509c30 Btrfs: add a io_c... |
925 |
} |
1bbc621ef Btrfs: allow bloc... |
926 927 928 929 |
if (cluster_locked) { spin_unlock(&cluster_locked->lock); cluster_locked = NULL; } |
55507ce36 Btrfs: fix race b... |
930 931 932 933 934 935 936 937 938 939 940 941 942 943 |
/* * Make sure we don't miss any range that was removed from our rbtree * because trimming is running. Otherwise after a umount+mount (or crash * after committing the transaction) we would leak free space and get * an inconsistent free space cache report from fsck. */ list_for_each_entry(trim_entry, &ctl->trimming_ranges, list) { ret = io_ctl_add_entry(io_ctl, trim_entry->start, trim_entry->bytes, NULL); if (ret) goto fail; *entries += 1; } |
d4452bc52 Btrfs: break up _... |
944 945 |
return 0; fail: |
1bbc621ef Btrfs: allow bloc... |
946 947 |
if (cluster_locked) spin_unlock(&cluster_locked->lock); |
d4452bc52 Btrfs: break up _... |
948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
return -ENOSPC; } static noinline_for_stack int update_cache_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode, struct btrfs_path *path, u64 offset, int entries, int bitmaps) { struct btrfs_key key; struct btrfs_free_space_header *header; struct extent_buffer *leaf; int ret; key.objectid = BTRFS_FREE_SPACE_OBJECTID; key.offset = offset; key.type = 0; ret = btrfs_search_slot(trans, root, &key, path, 0, 1); if (ret < 0) { clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, inode->i_size - 1, |
e182163d9 btrfs: stop clear... |
970 |
EXTENT_DELALLOC, 0, 0, NULL); |
d4452bc52 Btrfs: break up _... |
971 972 973 974 975 976 977 978 979 980 981 |
goto fail; } leaf = path->nodes[0]; if (ret > 0) { struct btrfs_key found_key; ASSERT(path->slots[0]); path->slots[0]--; btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID || found_key.offset != offset) { clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, |
e182163d9 btrfs: stop clear... |
982 983 |
inode->i_size - 1, EXTENT_DELALLOC, 0, 0, NULL); |
d4452bc52 Btrfs: break up _... |
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 |
btrfs_release_path(path); goto fail; } } BTRFS_I(inode)->generation = trans->transid; header = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_free_space_header); btrfs_set_free_space_entries(leaf, header, entries); btrfs_set_free_space_bitmaps(leaf, header, bitmaps); btrfs_set_free_space_generation(leaf, header, trans->transid); btrfs_mark_buffer_dirty(leaf); btrfs_release_path(path); return 0; fail: return -1; } |
6701bdb39 btrfs: get fs_inf... |
1003 |
static noinline_for_stack int write_pinned_extent_entries( |
6b45f6417 btrfs: Pass trans... |
1004 |
struct btrfs_trans_handle *trans, |
32da5386d btrfs: rename btr... |
1005 |
struct btrfs_block_group *block_group, |
4c6d1d85a btrfs: move struc... |
1006 |
struct btrfs_io_ctl *io_ctl, |
5349d6c3f Btrfs: make free ... |
1007 |
int *entries) |
d4452bc52 Btrfs: break up _... |
1008 1009 |
{ u64 start, extent_start, extent_end, len; |
d4452bc52 Btrfs: break up _... |
1010 1011 |
struct extent_io_tree *unpin = NULL; int ret; |
43be21462 Btrfs: fix free s... |
1012 |
|
5349d6c3f Btrfs: make free ... |
1013 1014 |
if (!block_group) return 0; |
a67509c30 Btrfs: add a io_c... |
1015 1016 1017 |
/* * We want to add any pinned extents to our free space cache * so we don't leak the space |
d4452bc52 Btrfs: break up _... |
1018 |
* |
db804f23a Btrfs: add pinned... |
1019 1020 1021 |
* We shouldn't have switched the pinned extents yet so this is the * right one */ |
fe119a6ee btrfs: switch to ... |
1022 |
unpin = &trans->transaction->pinned_extents; |
db804f23a Btrfs: add pinned... |
1023 |
|
b3470b5db btrfs: add dedica... |
1024 |
start = block_group->start; |
db804f23a Btrfs: add pinned... |
1025 |
|
b3470b5db btrfs: add dedica... |
1026 |
while (start < block_group->start + block_group->length) { |
db804f23a Btrfs: add pinned... |
1027 1028 |
ret = find_first_extent_bit(unpin, start, &extent_start, &extent_end, |
e6138876a Btrfs: cache exte... |
1029 |
EXTENT_DIRTY, NULL); |
5349d6c3f Btrfs: make free ... |
1030 1031 |
if (ret) return 0; |
0cb59c995 Btrfs: write out ... |
1032 |
|
a67509c30 Btrfs: add a io_c... |
1033 |
/* This pinned extent is out of our range */ |
b3470b5db btrfs: add dedica... |
1034 |
if (extent_start >= block_group->start + block_group->length) |
5349d6c3f Btrfs: make free ... |
1035 |
return 0; |
2f356126c Btrfs: use the no... |
1036 |
|
db804f23a Btrfs: add pinned... |
1037 |
extent_start = max(extent_start, start); |
b3470b5db btrfs: add dedica... |
1038 1039 |
extent_end = min(block_group->start + block_group->length, extent_end + 1); |
db804f23a Btrfs: add pinned... |
1040 |
len = extent_end - extent_start; |
0cb59c995 Btrfs: write out ... |
1041 |
|
d4452bc52 Btrfs: break up _... |
1042 1043 |
*entries += 1; ret = io_ctl_add_entry(io_ctl, extent_start, len, NULL); |
a67509c30 Btrfs: add a io_c... |
1044 |
if (ret) |
5349d6c3f Btrfs: make free ... |
1045 |
return -ENOSPC; |
0cb59c995 Btrfs: write out ... |
1046 |
|
db804f23a Btrfs: add pinned... |
1047 |
start = extent_end; |
a67509c30 Btrfs: add a io_c... |
1048 |
} |
0cb59c995 Btrfs: write out ... |
1049 |
|
5349d6c3f Btrfs: make free ... |
1050 1051 1052 1053 |
return 0; } static noinline_for_stack int |
4c6d1d85a btrfs: move struc... |
1054 |
write_bitmap_entries(struct btrfs_io_ctl *io_ctl, struct list_head *bitmap_list) |
5349d6c3f Btrfs: make free ... |
1055 |
{ |
7ae1681e1 btrfs: use list_f... |
1056 |
struct btrfs_free_space *entry, *next; |
5349d6c3f Btrfs: make free ... |
1057 |
int ret; |
0cb59c995 Btrfs: write out ... |
1058 |
/* Write out the bitmaps */ |
7ae1681e1 btrfs: use list_f... |
1059 |
list_for_each_entry_safe(entry, next, bitmap_list, list) { |
d4452bc52 Btrfs: break up _... |
1060 |
ret = io_ctl_add_bitmap(io_ctl, entry->bitmap); |
a67509c30 Btrfs: add a io_c... |
1061 |
if (ret) |
5349d6c3f Btrfs: make free ... |
1062 |
return -ENOSPC; |
0cb59c995 Btrfs: write out ... |
1063 |
list_del_init(&entry->list); |
be1a12a0d Btrfs: deal with ... |
1064 |
} |
5349d6c3f Btrfs: make free ... |
1065 1066 |
return 0; } |
0cb59c995 Btrfs: write out ... |
1067 |
|
5349d6c3f Btrfs: make free ... |
1068 1069 1070 |
static int flush_dirty_cache(struct inode *inode) { int ret; |
be1a12a0d Btrfs: deal with ... |
1071 |
|
0ef8b7260 Btrfs: return an ... |
1072 |
ret = btrfs_wait_ordered_range(inode, 0, (u64)-1); |
5349d6c3f Btrfs: make free ... |
1073 |
if (ret) |
0ef8b7260 Btrfs: return an ... |
1074 |
clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, inode->i_size - 1, |
e182163d9 btrfs: stop clear... |
1075 |
EXTENT_DELALLOC, 0, 0, NULL); |
0cb59c995 Btrfs: write out ... |
1076 |
|
5349d6c3f Btrfs: make free ... |
1077 |
return ret; |
d4452bc52 Btrfs: break up _... |
1078 1079 1080 |
} static void noinline_for_stack |
a3bdccc4e Btrfs: prevent li... |
1081 |
cleanup_bitmap_list(struct list_head *bitmap_list) |
d4452bc52 Btrfs: break up _... |
1082 |
{ |
7ae1681e1 btrfs: use list_f... |
1083 |
struct btrfs_free_space *entry, *next; |
5349d6c3f Btrfs: make free ... |
1084 |
|
7ae1681e1 btrfs: use list_f... |
1085 |
list_for_each_entry_safe(entry, next, bitmap_list, list) |
d4452bc52 Btrfs: break up _... |
1086 |
list_del_init(&entry->list); |
a3bdccc4e Btrfs: prevent li... |
1087 1088 1089 1090 1091 |
} static void noinline_for_stack cleanup_write_cache_enospc(struct inode *inode, struct btrfs_io_ctl *io_ctl, |
7bf1a1591 btrfs: remove unu... |
1092 |
struct extent_state **cached_state) |
a3bdccc4e Btrfs: prevent li... |
1093 |
{ |
d4452bc52 Btrfs: break up _... |
1094 1095 |
io_ctl_drop_pages(io_ctl); unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, |
e43bbe5e1 btrfs: sink unloc... |
1096 |
i_size_read(inode) - 1, cached_state); |
d4452bc52 Btrfs: break up _... |
1097 |
} |
549b4fdb8 Btrfs: check the ... |
1098 |
|
afdb57189 btrfs: simplify b... |
1099 1100 |
static int __btrfs_wait_cache_io(struct btrfs_root *root, struct btrfs_trans_handle *trans, |
32da5386d btrfs: rename btr... |
1101 |
struct btrfs_block_group *block_group, |
afdb57189 btrfs: simplify b... |
1102 1103 |
struct btrfs_io_ctl *io_ctl, struct btrfs_path *path, u64 offset) |
c9dc4c657 Btrfs: two stage ... |
1104 1105 1106 |
{ int ret; struct inode *inode = io_ctl->inode; |
1bbc621ef Btrfs: allow bloc... |
1107 1108 |
if (!inode) return 0; |
c9dc4c657 Btrfs: two stage ... |
1109 1110 1111 1112 1113 1114 1115 1116 1117 |
/* Flush the dirty pages in the cache file. */ ret = flush_dirty_cache(inode); if (ret) goto out; /* Update the cache item to tell everyone this cache file is valid. */ ret = update_cache_item(trans, root, inode, path, offset, io_ctl->entries, io_ctl->bitmaps); out: |
c9dc4c657 Btrfs: two stage ... |
1118 1119 1120 |
if (ret) { invalidate_inode_pages2(inode->i_mapping); BTRFS_I(inode)->generation = 0; |
bbcd1f4d5 btrfs: turn space... |
1121 1122 |
if (block_group) btrfs_debug(root->fs_info, |
2e69a7a60 btrfs: include er... |
1123 1124 |
"failed to write free space cache for block group %llu error %d", block_group->start, ret); |
c9dc4c657 Btrfs: two stage ... |
1125 1126 1127 1128 |
} btrfs_update_inode(trans, root, inode); if (block_group) { |
1bbc621ef Btrfs: allow bloc... |
1129 1130 1131 1132 |
/* the dirty list is protected by the dirty_bgs_lock */ spin_lock(&trans->transaction->dirty_bgs_lock); /* the disk_cache_state is protected by the block group lock */ |
c9dc4c657 Btrfs: two stage ... |
1133 1134 1135 1136 |
spin_lock(&block_group->lock); /* * only mark this as written if we didn't get put back on |
1bbc621ef Btrfs: allow bloc... |
1137 1138 |
* the dirty list while waiting for IO. Otherwise our * cache state won't be right, and we won't get written again |
c9dc4c657 Btrfs: two stage ... |
1139 1140 1141 1142 1143 1144 1145 |
*/ if (!ret && list_empty(&block_group->dirty_list)) block_group->disk_cache_state = BTRFS_DC_WRITTEN; else if (ret) block_group->disk_cache_state = BTRFS_DC_ERROR; spin_unlock(&block_group->lock); |
1bbc621ef Btrfs: allow bloc... |
1146 |
spin_unlock(&trans->transaction->dirty_bgs_lock); |
c9dc4c657 Btrfs: two stage ... |
1147 1148 1149 1150 1151 1152 1153 |
io_ctl->inode = NULL; iput(inode); } return ret; } |
afdb57189 btrfs: simplify b... |
1154 1155 1156 1157 1158 1159 1160 1161 1162 |
static int btrfs_wait_cache_io_root(struct btrfs_root *root, struct btrfs_trans_handle *trans, struct btrfs_io_ctl *io_ctl, struct btrfs_path *path) { return __btrfs_wait_cache_io(root, trans, NULL, io_ctl, path, 0); } int btrfs_wait_cache_io(struct btrfs_trans_handle *trans, |
32da5386d btrfs: rename btr... |
1163 |
struct btrfs_block_group *block_group, |
afdb57189 btrfs: simplify b... |
1164 1165 1166 1167 |
struct btrfs_path *path) { return __btrfs_wait_cache_io(block_group->fs_info->tree_root, trans, block_group, &block_group->io_ctl, |
b3470b5db btrfs: add dedica... |
1168 |
path, block_group->start); |
afdb57189 btrfs: simplify b... |
1169 |
} |
d4452bc52 Btrfs: break up _... |
1170 1171 1172 1173 1174 1175 |
/** * __btrfs_write_out_cache - write out cached info to an inode * @root - the root the inode belongs to * @ctl - the free space cache we are going to write out * @block_group - the block_group for this cache if it belongs to a block_group * @trans - the trans handle |
d4452bc52 Btrfs: break up _... |
1176 1177 |
* * This function writes out a free space cache struct to disk for quick recovery |
8cd1e7311 btrfs: fix a comm... |
1178 |
* on mount. This will return 0 if it was successful in writing the cache out, |
b86054540 btrfs: check io_c... |
1179 |
* or an errno if it was not. |
d4452bc52 Btrfs: break up _... |
1180 1181 1182 |
*/ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, struct btrfs_free_space_ctl *ctl, |
32da5386d btrfs: rename btr... |
1183 |
struct btrfs_block_group *block_group, |
c9dc4c657 Btrfs: two stage ... |
1184 |
struct btrfs_io_ctl *io_ctl, |
0e8d931a8 btrfs: remove unu... |
1185 |
struct btrfs_trans_handle *trans) |
d4452bc52 Btrfs: break up _... |
1186 1187 |
{ struct extent_state *cached_state = NULL; |
5349d6c3f Btrfs: make free ... |
1188 |
LIST_HEAD(bitmap_list); |
d4452bc52 Btrfs: break up _... |
1189 1190 1191 |
int entries = 0; int bitmaps = 0; int ret; |
c9dc4c657 Btrfs: two stage ... |
1192 |
int must_iput = 0; |
d4452bc52 Btrfs: break up _... |
1193 1194 |
if (!i_size_read(inode)) |
b86054540 btrfs: check io_c... |
1195 |
return -EIO; |
d4452bc52 Btrfs: break up _... |
1196 |
|
c9dc4c657 Btrfs: two stage ... |
1197 |
WARN_ON(io_ctl->pages); |
f15376df0 btrfs: root->fs_i... |
1198 |
ret = io_ctl_init(io_ctl, inode, 1); |
d4452bc52 Btrfs: break up _... |
1199 |
if (ret) |
b86054540 btrfs: check io_c... |
1200 |
return ret; |
d4452bc52 Btrfs: break up _... |
1201 |
|
e570fd27f Btrfs: fix broken... |
1202 1203 1204 1205 1206 1207 1208 1209 1210 |
if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA)) { down_write(&block_group->data_rwsem); spin_lock(&block_group->lock); if (block_group->delalloc_bytes) { block_group->disk_cache_state = BTRFS_DC_WRITTEN; spin_unlock(&block_group->lock); up_write(&block_group->data_rwsem); BTRFS_I(inode)->generation = 0; ret = 0; |
c9dc4c657 Btrfs: two stage ... |
1211 |
must_iput = 1; |
e570fd27f Btrfs: fix broken... |
1212 1213 1214 1215 |
goto out; } spin_unlock(&block_group->lock); } |
d4452bc52 Btrfs: break up _... |
1216 |
/* Lock all pages first so we can lock the extent safely. */ |
7a195f6db btrfs: make the u... |
1217 |
ret = io_ctl_prepare_pages(io_ctl, false); |
b86054540 btrfs: check io_c... |
1218 |
if (ret) |
b77000ed5 btrfs: fix deadlo... |
1219 |
goto out_unlock; |
d4452bc52 Btrfs: break up _... |
1220 1221 |
lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1, |
ff13db41f btrfs: drop unuse... |
1222 |
&cached_state); |
d4452bc52 Btrfs: break up _... |
1223 |
|
c9dc4c657 Btrfs: two stage ... |
1224 |
io_ctl_set_generation(io_ctl, trans->transid); |
d4452bc52 Btrfs: break up _... |
1225 |
|
55507ce36 Btrfs: fix race b... |
1226 |
mutex_lock(&ctl->cache_writeout_mutex); |
5349d6c3f Btrfs: make free ... |
1227 |
/* Write out the extent entries in the free space cache */ |
1bbc621ef Btrfs: allow bloc... |
1228 |
spin_lock(&ctl->tree_lock); |
c9dc4c657 Btrfs: two stage ... |
1229 |
ret = write_cache_extent_entries(io_ctl, ctl, |
d4452bc52 Btrfs: break up _... |
1230 1231 |
block_group, &entries, &bitmaps, &bitmap_list); |
a3bdccc4e Btrfs: prevent li... |
1232 1233 |
if (ret) goto out_nospc_locked; |
d4452bc52 Btrfs: break up _... |
1234 |
|
5349d6c3f Btrfs: make free ... |
1235 1236 1237 1238 |
/* * Some spaces that are freed in the current transaction are pinned, * they will be added into free space cache after the transaction is * committed, we shouldn't lose them. |
1bbc621ef Btrfs: allow bloc... |
1239 1240 1241 |
* * If this changes while we are working we'll get added back to * the dirty list and redo it. No locking needed |
5349d6c3f Btrfs: make free ... |
1242 |
*/ |
6b45f6417 btrfs: Pass trans... |
1243 |
ret = write_pinned_extent_entries(trans, block_group, io_ctl, &entries); |
a3bdccc4e Btrfs: prevent li... |
1244 1245 |
if (ret) goto out_nospc_locked; |
5349d6c3f Btrfs: make free ... |
1246 |
|
55507ce36 Btrfs: fix race b... |
1247 1248 1249 1250 1251 |
/* * At last, we write out all the bitmaps and keep cache_writeout_mutex * locked while doing it because a concurrent trim can be manipulating * or freeing the bitmap. */ |
c9dc4c657 Btrfs: two stage ... |
1252 |
ret = write_bitmap_entries(io_ctl, &bitmap_list); |
1bbc621ef Btrfs: allow bloc... |
1253 |
spin_unlock(&ctl->tree_lock); |
55507ce36 Btrfs: fix race b... |
1254 |
mutex_unlock(&ctl->cache_writeout_mutex); |
5349d6c3f Btrfs: make free ... |
1255 1256 1257 1258 |
if (ret) goto out_nospc; /* Zero out the rest of the pages just to make sure */ |
c9dc4c657 Btrfs: two stage ... |
1259 |
io_ctl_zero_remaining_pages(io_ctl); |
d4452bc52 Btrfs: break up _... |
1260 |
|
5349d6c3f Btrfs: make free ... |
1261 |
/* Everything is written out, now we dirty the pages in the file. */ |
088545f6e btrfs: make btrfs... |
1262 1263 1264 |
ret = btrfs_dirty_pages(BTRFS_I(inode), io_ctl->pages, io_ctl->num_pages, 0, i_size_read(inode), &cached_state); |
5349d6c3f Btrfs: make free ... |
1265 |
if (ret) |
d4452bc52 Btrfs: break up _... |
1266 |
goto out_nospc; |
5349d6c3f Btrfs: make free ... |
1267 |
|
e570fd27f Btrfs: fix broken... |
1268 1269 |
if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA)) up_write(&block_group->data_rwsem); |
5349d6c3f Btrfs: make free ... |
1270 1271 1272 1273 |
/* * Release the pages and unlock the extent, we will flush * them out later */ |
c9dc4c657 Btrfs: two stage ... |
1274 |
io_ctl_drop_pages(io_ctl); |
bbc37d6e4 btrfs: fix space ... |
1275 |
io_ctl_free(io_ctl); |
5349d6c3f Btrfs: make free ... |
1276 1277 |
unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0, |
e43bbe5e1 btrfs: sink unloc... |
1278 |
i_size_read(inode) - 1, &cached_state); |
5349d6c3f Btrfs: make free ... |
1279 |
|
c9dc4c657 Btrfs: two stage ... |
1280 1281 |
/* * at this point the pages are under IO and we're happy, |
260db43cd btrfs: delete dup... |
1282 |
* The caller is responsible for waiting on them and updating |
c9dc4c657 Btrfs: two stage ... |
1283 1284 1285 1286 1287 1288 |
* the cache and the inode */ io_ctl->entries = entries; io_ctl->bitmaps = bitmaps; ret = btrfs_fdatawrite_range(inode, 0, (u64)-1); |
5349d6c3f Btrfs: make free ... |
1289 |
if (ret) |
d4452bc52 Btrfs: break up _... |
1290 |
goto out; |
c9dc4c657 Btrfs: two stage ... |
1291 |
return 0; |
a3bdccc4e Btrfs: prevent li... |
1292 1293 1294 1295 |
out_nospc_locked: cleanup_bitmap_list(&bitmap_list); spin_unlock(&ctl->tree_lock); mutex_unlock(&ctl->cache_writeout_mutex); |
a67509c30 Btrfs: add a io_c... |
1296 |
out_nospc: |
7bf1a1591 btrfs: remove unu... |
1297 |
cleanup_write_cache_enospc(inode, io_ctl, &cached_state); |
e570fd27f Btrfs: fix broken... |
1298 |
|
b77000ed5 btrfs: fix deadlo... |
1299 |
out_unlock: |
e570fd27f Btrfs: fix broken... |
1300 1301 |
if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA)) up_write(&block_group->data_rwsem); |
fd8efa818 btrfs: simplify e... |
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 |
out: io_ctl->inode = NULL; io_ctl_free(io_ctl); if (ret) { invalidate_inode_pages2(inode->i_mapping); BTRFS_I(inode)->generation = 0; } btrfs_update_inode(trans, root, inode); if (must_iput) iput(inode); return ret; |
0414efae7 Btrfs: Make the c... |
1313 |
} |
fe0415345 btrfs: get fs_inf... |
1314 |
int btrfs_write_out_cache(struct btrfs_trans_handle *trans, |
32da5386d btrfs: rename btr... |
1315 |
struct btrfs_block_group *block_group, |
0414efae7 Btrfs: Make the c... |
1316 1317 |
struct btrfs_path *path) { |
fe0415345 btrfs: get fs_inf... |
1318 |
struct btrfs_fs_info *fs_info = trans->fs_info; |
0414efae7 Btrfs: Make the c... |
1319 1320 1321 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct inode *inode; int ret = 0; |
0414efae7 Btrfs: Make the c... |
1322 1323 1324 |
spin_lock(&block_group->lock); if (block_group->disk_cache_state < BTRFS_DC_SETUP) { spin_unlock(&block_group->lock); |
e570fd27f Btrfs: fix broken... |
1325 1326 |
return 0; } |
0414efae7 Btrfs: Make the c... |
1327 |
spin_unlock(&block_group->lock); |
7949f3392 btrfs: get fs_inf... |
1328 |
inode = lookup_free_space_inode(block_group, path); |
0414efae7 Btrfs: Make the c... |
1329 1330 |
if (IS_ERR(inode)) return 0; |
77ab86bf1 btrfs: free-space... |
1331 1332 |
ret = __btrfs_write_out_cache(fs_info->tree_root, inode, ctl, block_group, &block_group->io_ctl, trans); |
c09544e07 Btrfs: handle eno... |
1333 |
if (ret) { |
bbcd1f4d5 btrfs: turn space... |
1334 |
btrfs_debug(fs_info, |
2e69a7a60 btrfs: include er... |
1335 1336 |
"failed to write free space cache for block group %llu error %d", block_group->start, ret); |
c9dc4c657 Btrfs: two stage ... |
1337 1338 1339 1340 1341 1342 |
spin_lock(&block_group->lock); block_group->disk_cache_state = BTRFS_DC_ERROR; spin_unlock(&block_group->lock); block_group->io_ctl.inode = NULL; iput(inode); |
0414efae7 Btrfs: Make the c... |
1343 |
} |
c9dc4c657 Btrfs: two stage ... |
1344 1345 1346 1347 |
/* * if ret == 0 the caller is expected to call btrfs_wait_cache_io * to wait for IO and put the inode */ |
0cb59c995 Btrfs: write out ... |
1348 1349 |
return ret; } |
34d52cb6c Btrfs: Make free ... |
1350 |
static inline unsigned long offset_to_bit(u64 bitmap_start, u32 unit, |
963030817 Btrfs: use hybrid... |
1351 |
u64 offset) |
0f9dd46cd Btrfs: free space... |
1352 |
{ |
b12d6869f Btrfs: convert al... |
1353 |
ASSERT(offset >= bitmap_start); |
963030817 Btrfs: use hybrid... |
1354 |
offset -= bitmap_start; |
34d52cb6c Btrfs: Make free ... |
1355 |
return (unsigned long)(div_u64(offset, unit)); |
963030817 Btrfs: use hybrid... |
1356 |
} |
0f9dd46cd Btrfs: free space... |
1357 |
|
34d52cb6c Btrfs: Make free ... |
1358 |
static inline unsigned long bytes_to_bits(u64 bytes, u32 unit) |
963030817 Btrfs: use hybrid... |
1359 |
{ |
34d52cb6c Btrfs: Make free ... |
1360 |
return (unsigned long)(div_u64(bytes, unit)); |
963030817 Btrfs: use hybrid... |
1361 |
} |
0f9dd46cd Btrfs: free space... |
1362 |
|
34d52cb6c Btrfs: Make free ... |
1363 |
static inline u64 offset_to_bitmap(struct btrfs_free_space_ctl *ctl, |
963030817 Btrfs: use hybrid... |
1364 1365 1366 |
u64 offset) { u64 bitmap_start; |
0ef6447a3 Btrfs: Fix intege... |
1367 |
u64 bytes_per_bitmap; |
0f9dd46cd Btrfs: free space... |
1368 |
|
34d52cb6c Btrfs: Make free ... |
1369 1370 |
bytes_per_bitmap = BITS_PER_BITMAP * ctl->unit; bitmap_start = offset - ctl->start; |
0ef6447a3 Btrfs: Fix intege... |
1371 |
bitmap_start = div64_u64(bitmap_start, bytes_per_bitmap); |
963030817 Btrfs: use hybrid... |
1372 |
bitmap_start *= bytes_per_bitmap; |
34d52cb6c Btrfs: Make free ... |
1373 |
bitmap_start += ctl->start; |
0f9dd46cd Btrfs: free space... |
1374 |
|
963030817 Btrfs: use hybrid... |
1375 |
return bitmap_start; |
0f9dd46cd Btrfs: free space... |
1376 |
} |
963030817 Btrfs: use hybrid... |
1377 1378 |
static int tree_insert_offset(struct rb_root *root, u64 offset, struct rb_node *node, int bitmap) |
0f9dd46cd Btrfs: free space... |
1379 1380 1381 1382 1383 1384 1385 |
{ struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct btrfs_free_space *info; while (*p) { parent = *p; |
963030817 Btrfs: use hybrid... |
1386 |
info = rb_entry(parent, struct btrfs_free_space, offset_index); |
0f9dd46cd Btrfs: free space... |
1387 |
|
963030817 Btrfs: use hybrid... |
1388 |
if (offset < info->offset) { |
0f9dd46cd Btrfs: free space... |
1389 |
p = &(*p)->rb_left; |
963030817 Btrfs: use hybrid... |
1390 |
} else if (offset > info->offset) { |
0f9dd46cd Btrfs: free space... |
1391 |
p = &(*p)->rb_right; |
963030817 Btrfs: use hybrid... |
1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 |
} else { /* * we could have a bitmap entry and an extent entry * share the same offset. If this is the case, we want * the extent entry to always be found first if we do a * linear search through the tree, since we want to have * the quickest allocation time, and allocating from an * extent is faster than allocating from a bitmap. So * if we're inserting a bitmap and we find an entry at * this offset, we want to go right, or after this entry * logically. If we are inserting an extent and we've * found a bitmap, we want to go left, or before * logically. */ if (bitmap) { |
207dde828 Btrfs: check for ... |
1407 1408 1409 1410 |
if (info->bitmap) { WARN_ON_ONCE(1); return -EEXIST; } |
963030817 Btrfs: use hybrid... |
1411 1412 |
p = &(*p)->rb_right; } else { |
207dde828 Btrfs: check for ... |
1413 1414 1415 1416 |
if (!info->bitmap) { WARN_ON_ONCE(1); return -EEXIST; } |
963030817 Btrfs: use hybrid... |
1417 1418 1419 |
p = &(*p)->rb_left; } } |
0f9dd46cd Btrfs: free space... |
1420 1421 1422 1423 1424 1425 1426 1427 1428 |
} rb_link_node(node, parent, p); rb_insert_color(node, root); return 0; } /* |
70cb07434 Btrfs: free space... |
1429 1430 |
* searches the tree for the given offset. * |
963030817 Btrfs: use hybrid... |
1431 1432 1433 |
* fuzzy - If this is set, then we are trying to make an allocation, and we just * want a section that has at least bytes size and comes at or after the given * offset. |
0f9dd46cd Btrfs: free space... |
1434 |
*/ |
963030817 Btrfs: use hybrid... |
1435 |
static struct btrfs_free_space * |
34d52cb6c Btrfs: Make free ... |
1436 |
tree_search_offset(struct btrfs_free_space_ctl *ctl, |
963030817 Btrfs: use hybrid... |
1437 |
u64 offset, int bitmap_only, int fuzzy) |
0f9dd46cd Btrfs: free space... |
1438 |
{ |
34d52cb6c Btrfs: Make free ... |
1439 |
struct rb_node *n = ctl->free_space_offset.rb_node; |
963030817 Btrfs: use hybrid... |
1440 1441 1442 1443 1444 1445 1446 1447 |
struct btrfs_free_space *entry, *prev = NULL; /* find entry that is closest to the 'offset' */ while (1) { if (!n) { entry = NULL; break; } |
0f9dd46cd Btrfs: free space... |
1448 |
|
0f9dd46cd Btrfs: free space... |
1449 |
entry = rb_entry(n, struct btrfs_free_space, offset_index); |
963030817 Btrfs: use hybrid... |
1450 |
prev = entry; |
0f9dd46cd Btrfs: free space... |
1451 |
|
963030817 Btrfs: use hybrid... |
1452 |
if (offset < entry->offset) |
0f9dd46cd Btrfs: free space... |
1453 |
n = n->rb_left; |
963030817 Btrfs: use hybrid... |
1454 |
else if (offset > entry->offset) |
0f9dd46cd Btrfs: free space... |
1455 |
n = n->rb_right; |
963030817 Btrfs: use hybrid... |
1456 |
else |
0f9dd46cd Btrfs: free space... |
1457 |
break; |
0f9dd46cd Btrfs: free space... |
1458 |
} |
963030817 Btrfs: use hybrid... |
1459 1460 1461 1462 1463 |
if (bitmap_only) { if (!entry) return NULL; if (entry->bitmap) return entry; |
0f9dd46cd Btrfs: free space... |
1464 |
|
963030817 Btrfs: use hybrid... |
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 |
/* * bitmap entry and extent entry may share same offset, * in that case, bitmap entry comes after extent entry. */ n = rb_next(n); if (!n) return NULL; entry = rb_entry(n, struct btrfs_free_space, offset_index); if (entry->offset != offset) return NULL; |
0f9dd46cd Btrfs: free space... |
1475 |
|
963030817 Btrfs: use hybrid... |
1476 1477 1478 1479 |
WARN_ON(!entry->bitmap); return entry; } else if (entry) { if (entry->bitmap) { |
0f9dd46cd Btrfs: free space... |
1480 |
/* |
963030817 Btrfs: use hybrid... |
1481 1482 |
* if previous extent entry covers the offset, * we should return it instead of the bitmap entry |
0f9dd46cd Btrfs: free space... |
1483 |
*/ |
de6c4115a Btrfs: fix unnece... |
1484 1485 |
n = rb_prev(&entry->offset_index); if (n) { |
963030817 Btrfs: use hybrid... |
1486 1487 |
prev = rb_entry(n, struct btrfs_free_space, offset_index); |
de6c4115a Btrfs: fix unnece... |
1488 1489 1490 |
if (!prev->bitmap && prev->offset + prev->bytes > offset) entry = prev; |
0f9dd46cd Btrfs: free space... |
1491 |
} |
963030817 Btrfs: use hybrid... |
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 |
} return entry; } if (!prev) return NULL; /* find last entry before the 'offset' */ entry = prev; if (entry->offset > offset) { n = rb_prev(&entry->offset_index); if (n) { entry = rb_entry(n, struct btrfs_free_space, offset_index); |
b12d6869f Btrfs: convert al... |
1506 |
ASSERT(entry->offset <= offset); |
0f9dd46cd Btrfs: free space... |
1507 |
} else { |
963030817 Btrfs: use hybrid... |
1508 1509 1510 1511 |
if (fuzzy) return entry; else return NULL; |
0f9dd46cd Btrfs: free space... |
1512 1513 |
} } |
963030817 Btrfs: use hybrid... |
1514 |
if (entry->bitmap) { |
de6c4115a Btrfs: fix unnece... |
1515 1516 |
n = rb_prev(&entry->offset_index); if (n) { |
963030817 Btrfs: use hybrid... |
1517 1518 |
prev = rb_entry(n, struct btrfs_free_space, offset_index); |
de6c4115a Btrfs: fix unnece... |
1519 1520 1521 |
if (!prev->bitmap && prev->offset + prev->bytes > offset) return prev; |
963030817 Btrfs: use hybrid... |
1522 |
} |
34d52cb6c Btrfs: Make free ... |
1523 |
if (entry->offset + BITS_PER_BITMAP * ctl->unit > offset) |
963030817 Btrfs: use hybrid... |
1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 |
return entry; } else if (entry->offset + entry->bytes > offset) return entry; if (!fuzzy) return NULL; while (1) { if (entry->bitmap) { if (entry->offset + BITS_PER_BITMAP * |
34d52cb6c Btrfs: Make free ... |
1534 |
ctl->unit > offset) |
963030817 Btrfs: use hybrid... |
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 |
break; } else { if (entry->offset + entry->bytes > offset) break; } n = rb_next(&entry->offset_index); if (!n) return NULL; entry = rb_entry(n, struct btrfs_free_space, offset_index); } return entry; |
0f9dd46cd Btrfs: free space... |
1547 |
} |
f333adb5d btrfs: Check merg... |
1548 |
static inline void |
34d52cb6c Btrfs: Make free ... |
1549 |
__unlink_free_space(struct btrfs_free_space_ctl *ctl, |
f333adb5d btrfs: Check merg... |
1550 |
struct btrfs_free_space *info) |
0f9dd46cd Btrfs: free space... |
1551 |
{ |
34d52cb6c Btrfs: Make free ... |
1552 1553 |
rb_erase(&info->offset_index, &ctl->free_space_offset); ctl->free_extents--; |
dfb79ddb1 btrfs: track disc... |
1554 |
|
5dc7c10b8 btrfs: keep track... |
1555 |
if (!info->bitmap && !btrfs_free_space_trimmed(info)) { |
dfb79ddb1 btrfs: track disc... |
1556 |
ctl->discardable_extents[BTRFS_STAT_CURR]--; |
5dc7c10b8 btrfs: keep track... |
1557 1558 |
ctl->discardable_bytes[BTRFS_STAT_CURR] -= info->bytes; } |
f333adb5d btrfs: Check merg... |
1559 |
} |
34d52cb6c Btrfs: Make free ... |
1560 |
static void unlink_free_space(struct btrfs_free_space_ctl *ctl, |
f333adb5d btrfs: Check merg... |
1561 1562 |
struct btrfs_free_space *info) { |
34d52cb6c Btrfs: Make free ... |
1563 1564 |
__unlink_free_space(ctl, info); ctl->free_space -= info->bytes; |
0f9dd46cd Btrfs: free space... |
1565 |
} |
34d52cb6c Btrfs: Make free ... |
1566 |
static int link_free_space(struct btrfs_free_space_ctl *ctl, |
0f9dd46cd Btrfs: free space... |
1567 1568 1569 |
struct btrfs_free_space *info) { int ret = 0; |
b12d6869f Btrfs: convert al... |
1570 |
ASSERT(info->bytes || info->bitmap); |
34d52cb6c Btrfs: Make free ... |
1571 |
ret = tree_insert_offset(&ctl->free_space_offset, info->offset, |
963030817 Btrfs: use hybrid... |
1572 |
&info->offset_index, (info->bitmap != NULL)); |
0f9dd46cd Btrfs: free space... |
1573 1574 |
if (ret) return ret; |
5dc7c10b8 btrfs: keep track... |
1575 |
if (!info->bitmap && !btrfs_free_space_trimmed(info)) { |
dfb79ddb1 btrfs: track disc... |
1576 |
ctl->discardable_extents[BTRFS_STAT_CURR]++; |
5dc7c10b8 btrfs: keep track... |
1577 1578 |
ctl->discardable_bytes[BTRFS_STAT_CURR] += info->bytes; } |
dfb79ddb1 btrfs: track disc... |
1579 |
|
34d52cb6c Btrfs: Make free ... |
1580 1581 |
ctl->free_space += info->bytes; ctl->free_extents++; |
963030817 Btrfs: use hybrid... |
1582 1583 |
return ret; } |
34d52cb6c Btrfs: Make free ... |
1584 |
static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl) |
963030817 Btrfs: use hybrid... |
1585 |
{ |
32da5386d btrfs: rename btr... |
1586 |
struct btrfs_block_group *block_group = ctl->private; |
25891f796 Btrfs: fix extent... |
1587 1588 1589 |
u64 max_bytes; u64 bitmap_bytes; u64 extent_bytes; |
b3470b5db btrfs: add dedica... |
1590 |
u64 size = block_group->length; |
0ef6447a3 Btrfs: Fix intege... |
1591 1592 |
u64 bytes_per_bg = BITS_PER_BITMAP * ctl->unit; u64 max_bitmaps = div64_u64(size + bytes_per_bg - 1, bytes_per_bg); |
34d52cb6c Btrfs: Make free ... |
1593 |
|
0ef6447a3 Btrfs: Fix intege... |
1594 |
max_bitmaps = max_t(u64, max_bitmaps, 1); |
dde5740fd Btrfs: relax the ... |
1595 |
|
b12d6869f Btrfs: convert al... |
1596 |
ASSERT(ctl->total_bitmaps <= max_bitmaps); |
963030817 Btrfs: use hybrid... |
1597 1598 |
/* |
5d90c5c75 btrfs: increase t... |
1599 1600 1601 1602 |
* We are trying to keep the total amount of memory used per 1GiB of * space to be MAX_CACHE_BYTES_PER_GIG. However, with a reclamation * mechanism of pulling extents >= FORCE_EXTENT_THRESHOLD out of * bitmaps, we may end up using more memory than this. |
963030817 Btrfs: use hybrid... |
1603 |
*/ |
ee22184b5 Btrfs: use linux/... |
1604 |
if (size < SZ_1G) |
8eb2d829f btrfs: Fix thresh... |
1605 1606 |
max_bytes = MAX_CACHE_BYTES_PER_GIG; else |
ee22184b5 Btrfs: use linux/... |
1607 |
max_bytes = MAX_CACHE_BYTES_PER_GIG * div_u64(size, SZ_1G); |
963030817 Btrfs: use hybrid... |
1608 |
|
5d90c5c75 btrfs: increase t... |
1609 |
bitmap_bytes = ctl->total_bitmaps * ctl->unit; |
963030817 Btrfs: use hybrid... |
1610 |
|
25891f796 Btrfs: fix extent... |
1611 |
/* |
f8c269d72 btrfs: cleanup 64... |
1612 |
* we want the extent entry threshold to always be at most 1/2 the max |
25891f796 Btrfs: fix extent... |
1613 1614 1615 |
* bytes we can have, or whatever is less than that. */ extent_bytes = max_bytes - bitmap_bytes; |
f8c269d72 btrfs: cleanup 64... |
1616 |
extent_bytes = min_t(u64, extent_bytes, max_bytes >> 1); |
963030817 Btrfs: use hybrid... |
1617 |
|
34d52cb6c Btrfs: Make free ... |
1618 |
ctl->extents_thresh = |
f8c269d72 btrfs: cleanup 64... |
1619 |
div_u64(extent_bytes, sizeof(struct btrfs_free_space)); |
963030817 Btrfs: use hybrid... |
1620 |
} |
bb3ac5a4d Btrfs: fix wrong ... |
1621 1622 1623 |
static inline void __bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info, u64 offset, u64 bytes) |
963030817 Btrfs: use hybrid... |
1624 |
{ |
dfb79ddb1 btrfs: track disc... |
1625 1626 |
unsigned long start, count, end; int extent_delta = -1; |
963030817 Btrfs: use hybrid... |
1627 |
|
34d52cb6c Btrfs: Make free ... |
1628 1629 |
start = offset_to_bit(info->offset, ctl->unit, offset); count = bytes_to_bits(bytes, ctl->unit); |
dfb79ddb1 btrfs: track disc... |
1630 1631 |
end = start + count; ASSERT(end <= BITS_PER_BITMAP); |
963030817 Btrfs: use hybrid... |
1632 |
|
f38b6e754 Btrfs: Use bitmap... |
1633 |
bitmap_clear(info->bitmap, start, count); |
963030817 Btrfs: use hybrid... |
1634 1635 |
info->bytes -= bytes; |
553cceb49 btrfs: reset max_... |
1636 1637 |
if (info->max_extent_size > ctl->unit) info->max_extent_size = 0; |
dfb79ddb1 btrfs: track disc... |
1638 1639 1640 1641 1642 1643 1644 1645 |
if (start && test_bit(start - 1, info->bitmap)) extent_delta++; if (end < BITS_PER_BITMAP && test_bit(end, info->bitmap)) extent_delta++; info->bitmap_extents += extent_delta; |
5dc7c10b8 btrfs: keep track... |
1646 |
if (!btrfs_free_space_trimmed(info)) { |
dfb79ddb1 btrfs: track disc... |
1647 |
ctl->discardable_extents[BTRFS_STAT_CURR] += extent_delta; |
5dc7c10b8 btrfs: keep track... |
1648 1649 |
ctl->discardable_bytes[BTRFS_STAT_CURR] -= bytes; } |
bb3ac5a4d Btrfs: fix wrong ... |
1650 1651 1652 1653 1654 1655 1656 |
} static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info, u64 offset, u64 bytes) { __bitmap_clear_bits(ctl, info, offset, bytes); |
34d52cb6c Btrfs: Make free ... |
1657 |
ctl->free_space -= bytes; |
963030817 Btrfs: use hybrid... |
1658 |
} |
34d52cb6c Btrfs: Make free ... |
1659 |
static void bitmap_set_bits(struct btrfs_free_space_ctl *ctl, |
817d52f8d Btrfs: async bloc... |
1660 1661 |
struct btrfs_free_space *info, u64 offset, u64 bytes) |
963030817 Btrfs: use hybrid... |
1662 |
{ |
dfb79ddb1 btrfs: track disc... |
1663 1664 |
unsigned long start, count, end; int extent_delta = 1; |
963030817 Btrfs: use hybrid... |
1665 |
|
34d52cb6c Btrfs: Make free ... |
1666 1667 |
start = offset_to_bit(info->offset, ctl->unit, offset); count = bytes_to_bits(bytes, ctl->unit); |
dfb79ddb1 btrfs: track disc... |
1668 1669 |
end = start + count; ASSERT(end <= BITS_PER_BITMAP); |
963030817 Btrfs: use hybrid... |
1670 |
|
f38b6e754 Btrfs: Use bitmap... |
1671 |
bitmap_set(info->bitmap, start, count); |
963030817 Btrfs: use hybrid... |
1672 1673 |
info->bytes += bytes; |
34d52cb6c Btrfs: Make free ... |
1674 |
ctl->free_space += bytes; |
dfb79ddb1 btrfs: track disc... |
1675 1676 1677 1678 1679 1680 1681 1682 |
if (start && test_bit(start - 1, info->bitmap)) extent_delta--; if (end < BITS_PER_BITMAP && test_bit(end, info->bitmap)) extent_delta--; info->bitmap_extents += extent_delta; |
5dc7c10b8 btrfs: keep track... |
1683 |
if (!btrfs_free_space_trimmed(info)) { |
dfb79ddb1 btrfs: track disc... |
1684 |
ctl->discardable_extents[BTRFS_STAT_CURR] += extent_delta; |
5dc7c10b8 btrfs: keep track... |
1685 1686 |
ctl->discardable_bytes[BTRFS_STAT_CURR] += bytes; } |
963030817 Btrfs: use hybrid... |
1687 |
} |
a48203988 Btrfs: allocate t... |
1688 1689 1690 1691 |
/* * If we can not find suitable extent, we will use bytes to record * the size of the max extent. */ |
34d52cb6c Btrfs: Make free ... |
1692 |
static int search_bitmap(struct btrfs_free_space_ctl *ctl, |
963030817 Btrfs: use hybrid... |
1693 |
struct btrfs_free_space *bitmap_info, u64 *offset, |
0584f718e Btrfs: don't do e... |
1694 |
u64 *bytes, bool for_alloc) |
963030817 Btrfs: use hybrid... |
1695 1696 |
{ unsigned long found_bits = 0; |
a48203988 Btrfs: allocate t... |
1697 |
unsigned long max_bits = 0; |
963030817 Btrfs: use hybrid... |
1698 1699 |
unsigned long bits, i; unsigned long next_zero; |
a48203988 Btrfs: allocate t... |
1700 |
unsigned long extent_bits; |
963030817 Btrfs: use hybrid... |
1701 |
|
cef404837 Btrfs: keep track... |
1702 1703 1704 1705 |
/* * Skip searching the bitmap if we don't have a contiguous section that * is large enough for this allocation. */ |
0584f718e Btrfs: don't do e... |
1706 1707 |
if (for_alloc && bitmap_info->max_extent_size && |
cef404837 Btrfs: keep track... |
1708 1709 1710 1711 |
bitmap_info->max_extent_size < *bytes) { *bytes = bitmap_info->max_extent_size; return -1; } |
34d52cb6c Btrfs: Make free ... |
1712 |
i = offset_to_bit(bitmap_info->offset, ctl->unit, |
963030817 Btrfs: use hybrid... |
1713 |
max_t(u64, *offset, bitmap_info->offset)); |
34d52cb6c Btrfs: Make free ... |
1714 |
bits = bytes_to_bits(*bytes, ctl->unit); |
963030817 Btrfs: use hybrid... |
1715 |
|
ebb3dad43 Btrfs: using for_... |
1716 |
for_each_set_bit_from(i, bitmap_info->bitmap, BITS_PER_BITMAP) { |
0584f718e Btrfs: don't do e... |
1717 1718 1719 1720 |
if (for_alloc && bits == 1) { found_bits = 1; break; } |
963030817 Btrfs: use hybrid... |
1721 1722 |
next_zero = find_next_zero_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i); |
a48203988 Btrfs: allocate t... |
1723 1724 1725 |
extent_bits = next_zero - i; if (extent_bits >= bits) { found_bits = extent_bits; |
963030817 Btrfs: use hybrid... |
1726 |
break; |
a48203988 Btrfs: allocate t... |
1727 1728 |
} else if (extent_bits > max_bits) { max_bits = extent_bits; |
963030817 Btrfs: use hybrid... |
1729 1730 1731 1732 1733 |
} i = next_zero; } if (found_bits) { |
34d52cb6c Btrfs: Make free ... |
1734 1735 |
*offset = (u64)(i * ctl->unit) + bitmap_info->offset; *bytes = (u64)(found_bits) * ctl->unit; |
963030817 Btrfs: use hybrid... |
1736 1737 |
return 0; } |
a48203988 Btrfs: allocate t... |
1738 |
*bytes = (u64)(max_bits) * ctl->unit; |
cef404837 Btrfs: keep track... |
1739 |
bitmap_info->max_extent_size = *bytes; |
963030817 Btrfs: use hybrid... |
1740 1741 |
return -1; } |
ad22cf6ea btrfs: set max_ex... |
1742 1743 1744 1745 1746 1747 |
static inline u64 get_max_extent_size(struct btrfs_free_space *entry) { if (entry->bitmap) return entry->max_extent_size; return entry->bytes; } |
a48203988 Btrfs: allocate t... |
1748 |
/* Cache the size of the max extent in bytes */ |
34d52cb6c Btrfs: Make free ... |
1749 |
static struct btrfs_free_space * |
53b381b3a Btrfs: RAID5 and ... |
1750 |
find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, |
a48203988 Btrfs: allocate t... |
1751 |
unsigned long align, u64 *max_extent_size) |
963030817 Btrfs: use hybrid... |
1752 1753 1754 |
{ struct btrfs_free_space *entry; struct rb_node *node; |
53b381b3a Btrfs: RAID5 and ... |
1755 1756 |
u64 tmp; u64 align_off; |
963030817 Btrfs: use hybrid... |
1757 |
int ret; |
34d52cb6c Btrfs: Make free ... |
1758 |
if (!ctl->free_space_offset.rb_node) |
a48203988 Btrfs: allocate t... |
1759 |
goto out; |
963030817 Btrfs: use hybrid... |
1760 |
|
34d52cb6c Btrfs: Make free ... |
1761 |
entry = tree_search_offset(ctl, offset_to_bitmap(ctl, *offset), 0, 1); |
963030817 Btrfs: use hybrid... |
1762 |
if (!entry) |
a48203988 Btrfs: allocate t... |
1763 |
goto out; |
963030817 Btrfs: use hybrid... |
1764 1765 1766 |
for (node = &entry->offset_index; node; node = rb_next(node)) { entry = rb_entry(node, struct btrfs_free_space, offset_index); |
a48203988 Btrfs: allocate t... |
1767 |
if (entry->bytes < *bytes) { |
ad22cf6ea btrfs: set max_ex... |
1768 1769 |
*max_extent_size = max(get_max_extent_size(entry), *max_extent_size); |
963030817 Btrfs: use hybrid... |
1770 |
continue; |
a48203988 Btrfs: allocate t... |
1771 |
} |
963030817 Btrfs: use hybrid... |
1772 |
|
53b381b3a Btrfs: RAID5 and ... |
1773 1774 1775 1776 |
/* make sure the space returned is big enough * to match our requested alignment */ if (*bytes >= align) { |
a48203988 Btrfs: allocate t... |
1777 |
tmp = entry->offset - ctl->start + align - 1; |
47c5713f4 btrfs: replace re... |
1778 |
tmp = div64_u64(tmp, align); |
53b381b3a Btrfs: RAID5 and ... |
1779 1780 1781 1782 1783 1784 |
tmp = tmp * align + ctl->start; align_off = tmp - entry->offset; } else { align_off = 0; tmp = entry->offset; } |
a48203988 Btrfs: allocate t... |
1785 |
if (entry->bytes < *bytes + align_off) { |
ad22cf6ea btrfs: set max_ex... |
1786 1787 |
*max_extent_size = max(get_max_extent_size(entry), *max_extent_size); |
53b381b3a Btrfs: RAID5 and ... |
1788 |
continue; |
a48203988 Btrfs: allocate t... |
1789 |
} |
53b381b3a Btrfs: RAID5 and ... |
1790 |
|
963030817 Btrfs: use hybrid... |
1791 |
if (entry->bitmap) { |
a48203988 Btrfs: allocate t... |
1792 |
u64 size = *bytes; |
0584f718e Btrfs: don't do e... |
1793 |
ret = search_bitmap(ctl, entry, &tmp, &size, true); |
53b381b3a Btrfs: RAID5 and ... |
1794 1795 |
if (!ret) { *offset = tmp; |
a48203988 Btrfs: allocate t... |
1796 |
*bytes = size; |
963030817 Btrfs: use hybrid... |
1797 |
return entry; |
ad22cf6ea btrfs: set max_ex... |
1798 1799 1800 1801 |
} else { *max_extent_size = max(get_max_extent_size(entry), *max_extent_size); |
53b381b3a Btrfs: RAID5 and ... |
1802 |
} |
963030817 Btrfs: use hybrid... |
1803 1804 |
continue; } |
53b381b3a Btrfs: RAID5 and ... |
1805 1806 |
*offset = tmp; *bytes = entry->bytes - align_off; |
963030817 Btrfs: use hybrid... |
1807 1808 |
return entry; } |
a48203988 Btrfs: allocate t... |
1809 |
out: |
963030817 Btrfs: use hybrid... |
1810 1811 |
return NULL; } |
dfb79ddb1 btrfs: track disc... |
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 |
static int count_bitmap_extents(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *bitmap_info) { struct btrfs_block_group *block_group = ctl->private; u64 bytes = bitmap_info->bytes; unsigned int rs, re; int count = 0; if (!block_group || !bytes) return count; bitmap_for_each_set_region(bitmap_info->bitmap, rs, re, 0, BITS_PER_BITMAP) { bytes -= (rs - re) * ctl->unit; count++; if (!bytes) break; } return count; } |
34d52cb6c Btrfs: Make free ... |
1834 |
static void add_new_bitmap(struct btrfs_free_space_ctl *ctl, |
963030817 Btrfs: use hybrid... |
1835 1836 |
struct btrfs_free_space *info, u64 offset) { |
34d52cb6c Btrfs: Make free ... |
1837 |
info->offset = offset_to_bitmap(ctl, offset); |
f019f4264 Btrfs: fix bitmap... |
1838 |
info->bytes = 0; |
dfb79ddb1 btrfs: track disc... |
1839 |
info->bitmap_extents = 0; |
f2d0f6765 Btrfs: initialize... |
1840 |
INIT_LIST_HEAD(&info->list); |
34d52cb6c Btrfs: Make free ... |
1841 1842 |
link_free_space(ctl, info); ctl->total_bitmaps++; |
963030817 Btrfs: use hybrid... |
1843 |
|
34d52cb6c Btrfs: Make free ... |
1844 |
ctl->op->recalc_thresholds(ctl); |
963030817 Btrfs: use hybrid... |
1845 |
} |
34d52cb6c Btrfs: Make free ... |
1846 |
static void free_bitmap(struct btrfs_free_space_ctl *ctl, |
edf6e2d1d btrfs: Add helper... |
1847 1848 |
struct btrfs_free_space *bitmap_info) { |
27f0afc73 btrfs: ensure rem... |
1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 |
/* * Normally when this is called, the bitmap is completely empty. However, * if we are blowing up the free space cache for one reason or another * via __btrfs_remove_free_space_cache(), then it may not be freed and * we may leave stats on the table. */ if (bitmap_info->bytes && !btrfs_free_space_trimmed(bitmap_info)) { ctl->discardable_extents[BTRFS_STAT_CURR] -= bitmap_info->bitmap_extents; ctl->discardable_bytes[BTRFS_STAT_CURR] -= bitmap_info->bytes; } |
34d52cb6c Btrfs: Make free ... |
1861 |
unlink_free_space(ctl, bitmap_info); |
3acd48507 btrfs: fix alloca... |
1862 |
kmem_cache_free(btrfs_free_space_bitmap_cachep, bitmap_info->bitmap); |
dc89e9824 Btrfs: use a slab... |
1863 |
kmem_cache_free(btrfs_free_space_cachep, bitmap_info); |
34d52cb6c Btrfs: Make free ... |
1864 1865 |
ctl->total_bitmaps--; ctl->op->recalc_thresholds(ctl); |
edf6e2d1d btrfs: Add helper... |
1866 |
} |
34d52cb6c Btrfs: Make free ... |
1867 |
static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl, |
963030817 Btrfs: use hybrid... |
1868 1869 1870 1871 |
struct btrfs_free_space *bitmap_info, u64 *offset, u64 *bytes) { u64 end; |
6606bb97e Btrfs: fix btrfs_... |
1872 1873 |
u64 search_start, search_bytes; int ret; |
963030817 Btrfs: use hybrid... |
1874 1875 |
again: |
34d52cb6c Btrfs: Make free ... |
1876 |
end = bitmap_info->offset + (u64)(BITS_PER_BITMAP * ctl->unit) - 1; |
963030817 Btrfs: use hybrid... |
1877 |
|
6606bb97e Btrfs: fix btrfs_... |
1878 |
/* |
bdb7d303b Btrfs: fix tree l... |
1879 1880 1881 1882 |
* We need to search for bits in this bitmap. We could only cover some * of the extent in this bitmap thanks to how we add space, so we need * to search for as much as it as we can and clear that amount, and then * go searching for the next bit. |
6606bb97e Btrfs: fix btrfs_... |
1883 1884 |
*/ search_start = *offset; |
bdb7d303b Btrfs: fix tree l... |
1885 |
search_bytes = ctl->unit; |
13dbc0898 Btrfs: make sure ... |
1886 |
search_bytes = min(search_bytes, end - search_start + 1); |
0584f718e Btrfs: don't do e... |
1887 1888 |
ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes, false); |
b50c6e250 Btrfs: deal with ... |
1889 1890 |
if (ret < 0 || search_start != *offset) return -EINVAL; |
6606bb97e Btrfs: fix btrfs_... |
1891 |
|
bdb7d303b Btrfs: fix tree l... |
1892 1893 1894 1895 1896 1897 1898 1899 1900 |
/* We may have found more bits than what we need */ search_bytes = min(search_bytes, *bytes); /* Cannot clear past the end of the bitmap */ search_bytes = min(search_bytes, end - search_start + 1); bitmap_clear_bits(ctl, bitmap_info, search_start, search_bytes); *offset += search_bytes; *bytes -= search_bytes; |
963030817 Btrfs: use hybrid... |
1901 1902 |
if (*bytes) { |
6606bb97e Btrfs: fix btrfs_... |
1903 |
struct rb_node *next = rb_next(&bitmap_info->offset_index); |
edf6e2d1d btrfs: Add helper... |
1904 |
if (!bitmap_info->bytes) |
34d52cb6c Btrfs: Make free ... |
1905 |
free_bitmap(ctl, bitmap_info); |
963030817 Btrfs: use hybrid... |
1906 |
|
6606bb97e Btrfs: fix btrfs_... |
1907 1908 1909 1910 1911 |
/* * no entry after this bitmap, but we still have bytes to * remove, so something has gone wrong. */ if (!next) |
963030817 Btrfs: use hybrid... |
1912 |
return -EINVAL; |
6606bb97e Btrfs: fix btrfs_... |
1913 1914 1915 1916 1917 1918 1919 |
bitmap_info = rb_entry(next, struct btrfs_free_space, offset_index); /* * if the next entry isn't a bitmap we need to return to let the * extent stuff do its work. */ |
963030817 Btrfs: use hybrid... |
1920 1921 |
if (!bitmap_info->bitmap) return -EAGAIN; |
6606bb97e Btrfs: fix btrfs_... |
1922 1923 1924 1925 1926 1927 1928 |
/* * Ok the next item is a bitmap, but it may not actually hold * the information for the rest of this free space stuff, so * look for it, and if we don't find it return so we can try * everything over again. */ search_start = *offset; |
bdb7d303b Btrfs: fix tree l... |
1929 |
search_bytes = ctl->unit; |
34d52cb6c Btrfs: Make free ... |
1930 |
ret = search_bitmap(ctl, bitmap_info, &search_start, |
0584f718e Btrfs: don't do e... |
1931 |
&search_bytes, false); |
6606bb97e Btrfs: fix btrfs_... |
1932 1933 |
if (ret < 0 || search_start != *offset) return -EAGAIN; |
963030817 Btrfs: use hybrid... |
1934 |
goto again; |
edf6e2d1d btrfs: Add helper... |
1935 |
} else if (!bitmap_info->bytes) |
34d52cb6c Btrfs: Make free ... |
1936 |
free_bitmap(ctl, bitmap_info); |
963030817 Btrfs: use hybrid... |
1937 1938 1939 |
return 0; } |
2cdc342c2 Btrfs: fix bitmap... |
1940 1941 |
static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info, u64 offset, |
da080fe1b btrfs: keep track... |
1942 |
u64 bytes, enum btrfs_trim_state trim_state) |
2cdc342c2 Btrfs: fix bitmap... |
1943 1944 1945 |
{ u64 bytes_to_set = 0; u64 end; |
da080fe1b btrfs: keep track... |
1946 1947 1948 1949 |
/* * This is a tradeoff to make bitmap trim state minimal. We mark the * whole bitmap untrimmed if at any point we add untrimmed regions. */ |
dfb79ddb1 btrfs: track disc... |
1950 |
if (trim_state == BTRFS_TRIM_STATE_UNTRIMMED) { |
5dc7c10b8 btrfs: keep track... |
1951 |
if (btrfs_free_space_trimmed(info)) { |
dfb79ddb1 btrfs: track disc... |
1952 1953 |
ctl->discardable_extents[BTRFS_STAT_CURR] += info->bitmap_extents; |
5dc7c10b8 btrfs: keep track... |
1954 1955 |
ctl->discardable_bytes[BTRFS_STAT_CURR] += info->bytes; } |
da080fe1b btrfs: keep track... |
1956 |
info->trim_state = BTRFS_TRIM_STATE_UNTRIMMED; |
dfb79ddb1 btrfs: track disc... |
1957 |
} |
da080fe1b btrfs: keep track... |
1958 |
|
2cdc342c2 Btrfs: fix bitmap... |
1959 1960 1961 1962 1963 |
end = info->offset + (u64)(BITS_PER_BITMAP * ctl->unit); bytes_to_set = min(end - offset, bytes); bitmap_set_bits(ctl, info, offset, bytes_to_set); |
cef404837 Btrfs: keep track... |
1964 1965 1966 1967 1968 |
/* * We set some bytes, we have no idea what the max extent size is * anymore. */ info->max_extent_size = 0; |
2cdc342c2 Btrfs: fix bitmap... |
1969 1970 1971 |
return bytes_to_set; } |
34d52cb6c Btrfs: Make free ... |
1972 1973 |
static bool use_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) |
963030817 Btrfs: use hybrid... |
1974 |
{ |
32da5386d btrfs: rename btr... |
1975 |
struct btrfs_block_group *block_group = ctl->private; |
0b246afa6 btrfs: root->fs_i... |
1976 |
struct btrfs_fs_info *fs_info = block_group->fs_info; |
d0bd45607 Btrfs: add fragme... |
1977 1978 1979 |
bool forced = false; #ifdef CONFIG_BTRFS_DEBUG |
2ff7e61e0 btrfs: take an fs... |
1980 |
if (btrfs_should_fragment_free_space(block_group)) |
d0bd45607 Btrfs: add fragme... |
1981 1982 |
forced = true; #endif |
963030817 Btrfs: use hybrid... |
1983 |
|
5d90c5c75 btrfs: increase t... |
1984 1985 1986 |
/* This is a way to reclaim large regions from the bitmaps. */ if (!forced && info->bytes >= FORCE_EXTENT_THRESHOLD) return false; |
963030817 Btrfs: use hybrid... |
1987 1988 1989 1990 |
/* * If we are below the extents threshold then we can add this as an * extent, and don't have to deal with the bitmap */ |
d0bd45607 Btrfs: add fragme... |
1991 |
if (!forced && ctl->free_extents < ctl->extents_thresh) { |
32cb0840c Btrfs: don't be a... |
1992 1993 1994 |
/* * If this block group has some small extents we don't want to * use up all of our free slots in the cache with them, we want |
013276101 btrfs: fix string... |
1995 |
* to reserve them to larger extents, however if we have plenty |
32cb0840c Btrfs: don't be a... |
1996 1997 1998 |
* of cache left then go ahead an dadd them, no sense in adding * the overhead of a bitmap if we don't have to. */ |
f9bb615af btrfs: make small... |
1999 2000 |
if (info->bytes <= fs_info->sectorsize * 8) { if (ctl->free_extents * 3 <= ctl->extents_thresh) |
34d52cb6c Btrfs: Make free ... |
2001 |
return false; |
32cb0840c Btrfs: don't be a... |
2002 |
} else { |
34d52cb6c Btrfs: Make free ... |
2003 |
return false; |
32cb0840c Btrfs: don't be a... |
2004 2005 |
} } |
963030817 Btrfs: use hybrid... |
2006 2007 |
/* |
dde5740fd Btrfs: relax the ... |
2008 2009 2010 2011 2012 2013 |
* The original block groups from mkfs can be really small, like 8 * megabytes, so don't bother with a bitmap for those entries. However * some block groups can be smaller than what a bitmap would cover but * are still large enough that they could overflow the 32k memory limit, * so allow those block groups to still be allowed to have a bitmap * entry. |
963030817 Btrfs: use hybrid... |
2014 |
*/ |
b3470b5db btrfs: add dedica... |
2015 |
if (((BITS_PER_BITMAP * ctl->unit) >> 1) > block_group->length) |
34d52cb6c Btrfs: Make free ... |
2016 2017 2018 2019 |
return false; return true; } |
20e5506ba btrfs: constify r... |
2020 |
static const struct btrfs_free_space_op free_space_op = { |
2cdc342c2 Btrfs: fix bitmap... |
2021 2022 2023 |
.recalc_thresholds = recalculate_thresholds, .use_bitmap = use_bitmap, }; |
34d52cb6c Btrfs: Make free ... |
2024 2025 2026 2027 |
static int insert_into_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) { struct btrfs_free_space *bitmap_info; |
32da5386d btrfs: rename btr... |
2028 |
struct btrfs_block_group *block_group = NULL; |
34d52cb6c Btrfs: Make free ... |
2029 |
int added = 0; |
2cdc342c2 Btrfs: fix bitmap... |
2030 |
u64 bytes, offset, bytes_added; |
da080fe1b btrfs: keep track... |
2031 |
enum btrfs_trim_state trim_state; |
34d52cb6c Btrfs: Make free ... |
2032 |
int ret; |
963030817 Btrfs: use hybrid... |
2033 2034 2035 |
bytes = info->bytes; offset = info->offset; |
da080fe1b btrfs: keep track... |
2036 |
trim_state = info->trim_state; |
963030817 Btrfs: use hybrid... |
2037 |
|
34d52cb6c Btrfs: Make free ... |
2038 2039 |
if (!ctl->op->use_bitmap(ctl, info)) return 0; |
2cdc342c2 Btrfs: fix bitmap... |
2040 2041 |
if (ctl->op == &free_space_op) block_group = ctl->private; |
38e878806 Btrfs: make sure ... |
2042 |
again: |
2cdc342c2 Btrfs: fix bitmap... |
2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 |
/* * Since we link bitmaps right into the cluster we need to see if we * have a cluster here, and if so and it has our bitmap we need to add * the free space to that bitmap. */ if (block_group && !list_empty(&block_group->cluster_list)) { struct btrfs_free_cluster *cluster; struct rb_node *node; struct btrfs_free_space *entry; cluster = list_entry(block_group->cluster_list.next, struct btrfs_free_cluster, block_group_list); spin_lock(&cluster->lock); node = rb_first(&cluster->root); if (!node) { spin_unlock(&cluster->lock); |
38e878806 Btrfs: make sure ... |
2060 |
goto no_cluster_bitmap; |
2cdc342c2 Btrfs: fix bitmap... |
2061 2062 2063 2064 2065 |
} entry = rb_entry(node, struct btrfs_free_space, offset_index); if (!entry->bitmap) { spin_unlock(&cluster->lock); |
38e878806 Btrfs: make sure ... |
2066 |
goto no_cluster_bitmap; |
2cdc342c2 Btrfs: fix bitmap... |
2067 2068 2069 |
} if (entry->offset == offset_to_bitmap(ctl, offset)) { |
da080fe1b btrfs: keep track... |
2070 2071 |
bytes_added = add_bytes_to_bitmap(ctl, entry, offset, bytes, trim_state); |
2cdc342c2 Btrfs: fix bitmap... |
2072 2073 2074 2075 2076 2077 2078 2079 2080 |
bytes -= bytes_added; offset += bytes_added; } spin_unlock(&cluster->lock); if (!bytes) { ret = 1; goto out; } } |
38e878806 Btrfs: make sure ... |
2081 2082 |
no_cluster_bitmap: |
34d52cb6c Btrfs: Make free ... |
2083 |
bitmap_info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), |
963030817 Btrfs: use hybrid... |
2084 2085 |
1, 0); if (!bitmap_info) { |
b12d6869f Btrfs: convert al... |
2086 |
ASSERT(added == 0); |
963030817 Btrfs: use hybrid... |
2087 2088 |
goto new_bitmap; } |
da080fe1b btrfs: keep track... |
2089 2090 |
bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes, trim_state); |
2cdc342c2 Btrfs: fix bitmap... |
2091 2092 2093 |
bytes -= bytes_added; offset += bytes_added; added = 0; |
963030817 Btrfs: use hybrid... |
2094 2095 2096 2097 2098 2099 2100 2101 2102 |
if (!bytes) { ret = 1; goto out; } else goto again; new_bitmap: if (info && info->bitmap) { |
34d52cb6c Btrfs: Make free ... |
2103 |
add_new_bitmap(ctl, info, offset); |
963030817 Btrfs: use hybrid... |
2104 2105 2106 2107 |
added = 1; info = NULL; goto again; } else { |
34d52cb6c Btrfs: Make free ... |
2108 |
spin_unlock(&ctl->tree_lock); |
963030817 Btrfs: use hybrid... |
2109 2110 2111 |
/* no pre-allocated info, allocate a new one */ if (!info) { |
dc89e9824 Btrfs: use a slab... |
2112 2113 |
info = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); |
963030817 Btrfs: use hybrid... |
2114 |
if (!info) { |
34d52cb6c Btrfs: Make free ... |
2115 |
spin_lock(&ctl->tree_lock); |
963030817 Btrfs: use hybrid... |
2116 2117 2118 2119 2120 2121 |
ret = -ENOMEM; goto out; } } /* allocate the bitmap */ |
3acd48507 btrfs: fix alloca... |
2122 2123 |
info->bitmap = kmem_cache_zalloc(btrfs_free_space_bitmap_cachep, GFP_NOFS); |
da080fe1b btrfs: keep track... |
2124 |
info->trim_state = BTRFS_TRIM_STATE_TRIMMED; |
34d52cb6c Btrfs: Make free ... |
2125 |
spin_lock(&ctl->tree_lock); |
963030817 Btrfs: use hybrid... |
2126 2127 2128 2129 2130 2131 2132 2133 2134 |
if (!info->bitmap) { ret = -ENOMEM; goto out; } goto again; } out: if (info) { |
3acd48507 btrfs: fix alloca... |
2135 2136 2137 |
if (info->bitmap) kmem_cache_free(btrfs_free_space_bitmap_cachep, info->bitmap); |
dc89e9824 Btrfs: use a slab... |
2138 |
kmem_cache_free(btrfs_free_space_cachep, info); |
963030817 Btrfs: use hybrid... |
2139 |
} |
0f9dd46cd Btrfs: free space... |
2140 2141 2142 |
return ret; } |
a7ccb2558 btrfs: keep track... |
2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 |
/* * Free space merging rules: * 1) Merge trimmed areas together * 2) Let untrimmed areas coalesce with trimmed areas * 3) Always pull neighboring regions from bitmaps * * The above rules are for when we merge free space based on btrfs_trim_state. * Rules 2 and 3 are subtle because they are suboptimal, but are done for the * same reason: to promote larger extent regions which makes life easier for * find_free_extent(). Rule 2 enables coalescing based on the common path * being returning free space from btrfs_finish_extent_commit(). So when free * space is trimmed, it will prevent aggregating trimmed new region and * untrimmed regions in the rb_tree. Rule 3 is purely to obtain larger extents * and provide find_free_extent() with the largest extents possible hoping for * the reuse path. */ |
945d8962c Merge branch 'cle... |
2159 |
static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl, |
f333adb5d btrfs: Check merg... |
2160 |
struct btrfs_free_space *info, bool update_stat) |
0f9dd46cd Btrfs: free space... |
2161 |
{ |
bf53d4687 btrfs: only searc... |
2162 |
struct btrfs_free_space *left_info = NULL; |
120d66eec btrfs: Add a help... |
2163 2164 2165 2166 |
struct btrfs_free_space *right_info; bool merged = false; u64 offset = info->offset; u64 bytes = info->bytes; |
a7ccb2558 btrfs: keep track... |
2167 |
const bool is_trimmed = btrfs_free_space_trimmed(info); |
6226cb0a5 Btrfs: kill the b... |
2168 |
|
0f9dd46cd Btrfs: free space... |
2169 2170 2171 2172 2173 |
/* * first we want to see if there is free space adjacent to the range we * are adding, if there is remove that struct and add a new one to * cover the entire range */ |
34d52cb6c Btrfs: Make free ... |
2174 |
right_info = tree_search_offset(ctl, offset + bytes, 0, 0); |
963030817 Btrfs: use hybrid... |
2175 2176 2177 |
if (right_info && rb_prev(&right_info->offset_index)) left_info = rb_entry(rb_prev(&right_info->offset_index), struct btrfs_free_space, offset_index); |
bf53d4687 btrfs: only searc... |
2178 |
else if (!right_info) |
34d52cb6c Btrfs: Make free ... |
2179 |
left_info = tree_search_offset(ctl, offset - 1, 0, 0); |
0f9dd46cd Btrfs: free space... |
2180 |
|
a7ccb2558 btrfs: keep track... |
2181 2182 2183 |
/* See try_merge_free_space() comment. */ if (right_info && !right_info->bitmap && (!is_trimmed || btrfs_free_space_trimmed(right_info))) { |
f333adb5d btrfs: Check merg... |
2184 |
if (update_stat) |
34d52cb6c Btrfs: Make free ... |
2185 |
unlink_free_space(ctl, right_info); |
f333adb5d btrfs: Check merg... |
2186 |
else |
34d52cb6c Btrfs: Make free ... |
2187 |
__unlink_free_space(ctl, right_info); |
6226cb0a5 Btrfs: kill the b... |
2188 |
info->bytes += right_info->bytes; |
dc89e9824 Btrfs: use a slab... |
2189 |
kmem_cache_free(btrfs_free_space_cachep, right_info); |
120d66eec btrfs: Add a help... |
2190 |
merged = true; |
0f9dd46cd Btrfs: free space... |
2191 |
} |
a7ccb2558 btrfs: keep track... |
2192 |
/* See try_merge_free_space() comment. */ |
963030817 Btrfs: use hybrid... |
2193 |
if (left_info && !left_info->bitmap && |
a7ccb2558 btrfs: keep track... |
2194 2195 |
left_info->offset + left_info->bytes == offset && (!is_trimmed || btrfs_free_space_trimmed(left_info))) { |
f333adb5d btrfs: Check merg... |
2196 |
if (update_stat) |
34d52cb6c Btrfs: Make free ... |
2197 |
unlink_free_space(ctl, left_info); |
f333adb5d btrfs: Check merg... |
2198 |
else |
34d52cb6c Btrfs: Make free ... |
2199 |
__unlink_free_space(ctl, left_info); |
6226cb0a5 Btrfs: kill the b... |
2200 2201 |
info->offset = left_info->offset; info->bytes += left_info->bytes; |
dc89e9824 Btrfs: use a slab... |
2202 |
kmem_cache_free(btrfs_free_space_cachep, left_info); |
120d66eec btrfs: Add a help... |
2203 |
merged = true; |
0f9dd46cd Btrfs: free space... |
2204 |
} |
120d66eec btrfs: Add a help... |
2205 2206 |
return merged; } |
200055239 Btrfs: improve fr... |
2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 |
static bool steal_from_bitmap_to_end(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info, bool update_stat) { struct btrfs_free_space *bitmap; unsigned long i; unsigned long j; const u64 end = info->offset + info->bytes; const u64 bitmap_offset = offset_to_bitmap(ctl, end); u64 bytes; bitmap = tree_search_offset(ctl, bitmap_offset, 1, 0); if (!bitmap) return false; i = offset_to_bit(bitmap->offset, ctl->unit, end); j = find_next_zero_bit(bitmap->bitmap, BITS_PER_BITMAP, i); if (j == i) return false; bytes = (j - i) * ctl->unit; info->bytes += bytes; |
a7ccb2558 btrfs: keep track... |
2228 2229 2230 |
/* See try_merge_free_space() comment. */ if (!btrfs_free_space_trimmed(bitmap)) info->trim_state = BTRFS_TRIM_STATE_UNTRIMMED; |
200055239 Btrfs: improve fr... |
2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 |
if (update_stat) bitmap_clear_bits(ctl, bitmap, end, bytes); else __bitmap_clear_bits(ctl, bitmap, end, bytes); if (!bitmap->bytes) free_bitmap(ctl, bitmap); return true; } static bool steal_from_bitmap_to_front(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info, bool update_stat) { struct btrfs_free_space *bitmap; u64 bitmap_offset; unsigned long i; unsigned long j; unsigned long prev_j; u64 bytes; bitmap_offset = offset_to_bitmap(ctl, info->offset); /* If we're on a boundary, try the previous logical bitmap. */ if (bitmap_offset == info->offset) { if (info->offset == 0) return false; bitmap_offset = offset_to_bitmap(ctl, info->offset - 1); } bitmap = tree_search_offset(ctl, bitmap_offset, 1, 0); if (!bitmap) return false; i = offset_to_bit(bitmap->offset, ctl->unit, info->offset) - 1; j = 0; prev_j = (unsigned long)-1; for_each_clear_bit_from(j, bitmap->bitmap, BITS_PER_BITMAP) { if (j > i) break; prev_j = j; } if (prev_j == i) return false; if (prev_j == (unsigned long)-1) bytes = (i + 1) * ctl->unit; else bytes = (i - prev_j) * ctl->unit; info->offset -= bytes; info->bytes += bytes; |
a7ccb2558 btrfs: keep track... |
2283 2284 2285 |
/* See try_merge_free_space() comment. */ if (!btrfs_free_space_trimmed(bitmap)) info->trim_state = BTRFS_TRIM_STATE_UNTRIMMED; |
200055239 Btrfs: improve fr... |
2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 |
if (update_stat) bitmap_clear_bits(ctl, bitmap, info->offset, bytes); else __bitmap_clear_bits(ctl, bitmap, info->offset, bytes); if (!bitmap->bytes) free_bitmap(ctl, bitmap); return true; } /* * We prefer always to allocate from extent entries, both for clustered and * non-clustered allocation requests. So when attempting to add a new extent * entry, try to see if there's adjacent free space in bitmap entries, and if * there is, migrate that space from the bitmaps to the extent. * Like this we get better chances of satisfying space allocation requests * because we attempt to satisfy them based on a single cache entry, and never * on 2 or more entries - even if the entries represent a contiguous free space * region (e.g. 1 extent entry + 1 bitmap entry starting where the extent entry * ends). */ static void steal_from_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info, bool update_stat) { /* * Only work with disconnected entries, as we can change their offset, * and must be extent entries. */ ASSERT(!info->bitmap); ASSERT(RB_EMPTY_NODE(&info->offset_index)); if (ctl->total_bitmaps > 0) { bool stole_end; bool stole_front = false; stole_end = steal_from_bitmap_to_end(ctl, info, update_stat); if (ctl->total_bitmaps > 0) stole_front = steal_from_bitmap_to_front(ctl, info, update_stat); if (stole_end || stole_front) try_merge_free_space(ctl, info, update_stat); } } |
ab8d0fc48 btrfs: convert pr... |
2332 2333 |
int __btrfs_add_free_space(struct btrfs_fs_info *fs_info, struct btrfs_free_space_ctl *ctl, |
a7ccb2558 btrfs: keep track... |
2334 2335 |
u64 offset, u64 bytes, enum btrfs_trim_state trim_state) |
120d66eec btrfs: Add a help... |
2336 |
{ |
b0643e59c btrfs: add the be... |
2337 |
struct btrfs_block_group *block_group = ctl->private; |
120d66eec btrfs: Add a help... |
2338 2339 |
struct btrfs_free_space *info; int ret = 0; |
7fe6d45e4 btrfs: have multi... |
2340 |
u64 filter_bytes = bytes; |
120d66eec btrfs: Add a help... |
2341 |
|
dc89e9824 Btrfs: use a slab... |
2342 |
info = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); |
120d66eec btrfs: Add a help... |
2343 2344 2345 2346 2347 |
if (!info) return -ENOMEM; info->offset = offset; info->bytes = bytes; |
a7ccb2558 btrfs: keep track... |
2348 |
info->trim_state = trim_state; |
200055239 Btrfs: improve fr... |
2349 |
RB_CLEAR_NODE(&info->offset_index); |
120d66eec btrfs: Add a help... |
2350 |
|
34d52cb6c Btrfs: Make free ... |
2351 |
spin_lock(&ctl->tree_lock); |
120d66eec btrfs: Add a help... |
2352 |
|
34d52cb6c Btrfs: Make free ... |
2353 |
if (try_merge_free_space(ctl, info, true)) |
120d66eec btrfs: Add a help... |
2354 2355 2356 2357 2358 2359 2360 |
goto link; /* * There was no extent directly to the left or right of this new * extent then we know we're going to have to allocate a new extent, so * before we do that see if we need to drop this into a bitmap */ |
34d52cb6c Btrfs: Make free ... |
2361 |
ret = insert_into_bitmap(ctl, info); |
120d66eec btrfs: Add a help... |
2362 2363 2364 2365 2366 2367 2368 |
if (ret < 0) { goto out; } else if (ret) { ret = 0; goto out; } link: |
200055239 Btrfs: improve fr... |
2369 2370 2371 2372 2373 2374 2375 |
/* * Only steal free space from adjacent bitmaps if we're sure we're not * going to add the new free space to existing bitmap entries - because * that would mean unnecessary work that would be reverted. Therefore * attempt to steal space from bitmaps if we're adding an extent entry. */ steal_from_bitmap(ctl, info, true); |
7fe6d45e4 btrfs: have multi... |
2376 |
filter_bytes = max(filter_bytes, info->bytes); |
34d52cb6c Btrfs: Make free ... |
2377 |
ret = link_free_space(ctl, info); |
0f9dd46cd Btrfs: free space... |
2378 |
if (ret) |
dc89e9824 Btrfs: use a slab... |
2379 |
kmem_cache_free(btrfs_free_space_cachep, info); |
963030817 Btrfs: use hybrid... |
2380 |
out: |
dfb79ddb1 btrfs: track disc... |
2381 |
btrfs_discard_update_discardable(block_group, ctl); |
34d52cb6c Btrfs: Make free ... |
2382 |
spin_unlock(&ctl->tree_lock); |
6226cb0a5 Btrfs: kill the b... |
2383 |
|
0f9dd46cd Btrfs: free space... |
2384 |
if (ret) { |
ab8d0fc48 btrfs: convert pr... |
2385 |
btrfs_crit(fs_info, "unable to add free space :%d", ret); |
b12d6869f Btrfs: convert al... |
2386 |
ASSERT(ret != -EEXIST); |
0f9dd46cd Btrfs: free space... |
2387 |
} |
7fe6d45e4 btrfs: have multi... |
2388 2389 |
if (trim_state != BTRFS_TRIM_STATE_TRIMMED) { btrfs_discard_check_filter(block_group, filter_bytes); |
b0643e59c btrfs: add the be... |
2390 |
btrfs_discard_queue_work(&fs_info->discard_ctl, block_group); |
7fe6d45e4 btrfs: have multi... |
2391 |
} |
b0643e59c btrfs: add the be... |
2392 |
|
0f9dd46cd Btrfs: free space... |
2393 2394 |
return ret; } |
32da5386d btrfs: rename btr... |
2395 |
int btrfs_add_free_space(struct btrfs_block_group *block_group, |
478b4d9f0 btrfs: move btrfs... |
2396 2397 |
u64 bytenr, u64 size) { |
a7ccb2558 btrfs: keep track... |
2398 2399 2400 2401 |
enum btrfs_trim_state trim_state = BTRFS_TRIM_STATE_UNTRIMMED; if (btrfs_test_opt(block_group->fs_info, DISCARD_SYNC)) trim_state = BTRFS_TRIM_STATE_TRIMMED; |
478b4d9f0 btrfs: move btrfs... |
2402 2403 |
return __btrfs_add_free_space(block_group->fs_info, block_group->free_space_ctl, |
a7ccb2558 btrfs: keep track... |
2404 |
bytenr, size, trim_state); |
478b4d9f0 btrfs: move btrfs... |
2405 |
} |
b0643e59c btrfs: add the be... |
2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 |
/* * This is a subtle distinction because when adding free space back in general, * we want it to be added as untrimmed for async. But in the case where we add * it on loading of a block group, we want to consider it trimmed. */ int btrfs_add_free_space_async_trimmed(struct btrfs_block_group *block_group, u64 bytenr, u64 size) { enum btrfs_trim_state trim_state = BTRFS_TRIM_STATE_UNTRIMMED; if (btrfs_test_opt(block_group->fs_info, DISCARD_SYNC) || btrfs_test_opt(block_group->fs_info, DISCARD_ASYNC)) trim_state = BTRFS_TRIM_STATE_TRIMMED; return __btrfs_add_free_space(block_group->fs_info, block_group->free_space_ctl, bytenr, size, trim_state); } |
32da5386d btrfs: rename btr... |
2424 |
int btrfs_remove_free_space(struct btrfs_block_group *block_group, |
6226cb0a5 Btrfs: kill the b... |
2425 |
u64 offset, u64 bytes) |
0f9dd46cd Btrfs: free space... |
2426 |
{ |
34d52cb6c Btrfs: Make free ... |
2427 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
0f9dd46cd Btrfs: free space... |
2428 |
struct btrfs_free_space *info; |
b0175117b Btrfs: fix panic ... |
2429 2430 |
int ret; bool re_search = false; |
0f9dd46cd Btrfs: free space... |
2431 |
|
34d52cb6c Btrfs: Make free ... |
2432 |
spin_lock(&ctl->tree_lock); |
6226cb0a5 Btrfs: kill the b... |
2433 |
|
963030817 Btrfs: use hybrid... |
2434 |
again: |
b0175117b Btrfs: fix panic ... |
2435 |
ret = 0; |
bdb7d303b Btrfs: fix tree l... |
2436 2437 |
if (!bytes) goto out_lock; |
34d52cb6c Btrfs: Make free ... |
2438 |
info = tree_search_offset(ctl, offset, 0, 0); |
963030817 Btrfs: use hybrid... |
2439 |
if (!info) { |
6606bb97e Btrfs: fix btrfs_... |
2440 2441 2442 2443 |
/* * oops didn't find an extent that matched the space we wanted * to remove, look for a bitmap instead */ |
34d52cb6c Btrfs: Make free ... |
2444 |
info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), |
6606bb97e Btrfs: fix btrfs_... |
2445 2446 |
1, 0); if (!info) { |
b0175117b Btrfs: fix panic ... |
2447 2448 2449 2450 |
/* * If we found a partial bit of our free space in a * bitmap but then couldn't find the other part this may * be a problem, so WARN about it. |
24a703139 Btrfs: remove fre... |
2451 |
*/ |
b0175117b Btrfs: fix panic ... |
2452 |
WARN_ON(re_search); |
6606bb97e Btrfs: fix btrfs_... |
2453 2454 |
goto out_lock; } |
963030817 Btrfs: use hybrid... |
2455 |
} |
b0175117b Btrfs: fix panic ... |
2456 |
re_search = false; |
bdb7d303b Btrfs: fix tree l... |
2457 |
if (!info->bitmap) { |
34d52cb6c Btrfs: Make free ... |
2458 |
unlink_free_space(ctl, info); |
bdb7d303b Btrfs: fix tree l... |
2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 |
if (offset == info->offset) { u64 to_free = min(bytes, info->bytes); info->bytes -= to_free; info->offset += to_free; if (info->bytes) { ret = link_free_space(ctl, info); WARN_ON(ret); } else { kmem_cache_free(btrfs_free_space_cachep, info); } |
0f9dd46cd Btrfs: free space... |
2470 |
|
bdb7d303b Btrfs: fix tree l... |
2471 2472 2473 2474 2475 |
offset += to_free; bytes -= to_free; goto again; } else { u64 old_end = info->bytes + info->offset; |
9b49c9b9f Btrfs: Fix alloca... |
2476 |
|
bdb7d303b Btrfs: fix tree l... |
2477 |
info->bytes = offset - info->offset; |
34d52cb6c Btrfs: Make free ... |
2478 |
ret = link_free_space(ctl, info); |
963030817 Btrfs: use hybrid... |
2479 2480 2481 |
WARN_ON(ret); if (ret) goto out_lock; |
963030817 Btrfs: use hybrid... |
2482 |
|
bdb7d303b Btrfs: fix tree l... |
2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 |
/* Not enough bytes in this entry to satisfy us */ if (old_end < offset + bytes) { bytes -= old_end - offset; offset = old_end; goto again; } else if (old_end == offset + bytes) { /* all done */ goto out_lock; } spin_unlock(&ctl->tree_lock); |
a7ccb2558 btrfs: keep track... |
2493 2494 2495 2496 |
ret = __btrfs_add_free_space(block_group->fs_info, ctl, offset + bytes, old_end - (offset + bytes), info->trim_state); |
bdb7d303b Btrfs: fix tree l... |
2497 2498 2499 |
WARN_ON(ret); goto out; } |
0f9dd46cd Btrfs: free space... |
2500 |
} |
963030817 Btrfs: use hybrid... |
2501 |
|
34d52cb6c Btrfs: Make free ... |
2502 |
ret = remove_from_bitmap(ctl, info, &offset, &bytes); |
b0175117b Btrfs: fix panic ... |
2503 2504 |
if (ret == -EAGAIN) { re_search = true; |
963030817 Btrfs: use hybrid... |
2505 |
goto again; |
b0175117b Btrfs: fix panic ... |
2506 |
} |
963030817 Btrfs: use hybrid... |
2507 |
out_lock: |
dfb79ddb1 btrfs: track disc... |
2508 |
btrfs_discard_update_discardable(block_group, ctl); |
34d52cb6c Btrfs: Make free ... |
2509 |
spin_unlock(&ctl->tree_lock); |
0f9dd46cd Btrfs: free space... |
2510 |
out: |
251792013 Btrfs: nuke fs wi... |
2511 2512 |
return ret; } |
32da5386d btrfs: rename btr... |
2513 |
void btrfs_dump_free_space(struct btrfs_block_group *block_group, |
0f9dd46cd Btrfs: free space... |
2514 2515 |
u64 bytes) { |
0b246afa6 btrfs: root->fs_i... |
2516 |
struct btrfs_fs_info *fs_info = block_group->fs_info; |
34d52cb6c Btrfs: Make free ... |
2517 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
0f9dd46cd Btrfs: free space... |
2518 2519 2520 |
struct btrfs_free_space *info; struct rb_node *n; int count = 0; |
9084cb6a2 Btrfs: fix use-af... |
2521 |
spin_lock(&ctl->tree_lock); |
34d52cb6c Btrfs: Make free ... |
2522 |
for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) { |
0f9dd46cd Btrfs: free space... |
2523 |
info = rb_entry(n, struct btrfs_free_space, offset_index); |
f6175efab Btrfs: do not cou... |
2524 |
if (info->bytes >= bytes && !block_group->ro) |
0f9dd46cd Btrfs: free space... |
2525 |
count++; |
0b246afa6 btrfs: root->fs_i... |
2526 |
btrfs_crit(fs_info, "entry offset %llu, bytes %llu, bitmap %s", |
efe120a06 Btrfs: convert pr... |
2527 |
info->offset, info->bytes, |
963030817 Btrfs: use hybrid... |
2528 |
(info->bitmap) ? "yes" : "no"); |
0f9dd46cd Btrfs: free space... |
2529 |
} |
9084cb6a2 Btrfs: fix use-af... |
2530 |
spin_unlock(&ctl->tree_lock); |
0b246afa6 btrfs: root->fs_i... |
2531 |
btrfs_info(fs_info, "block group has cluster?: %s", |
963030817 Btrfs: use hybrid... |
2532 |
list_empty(&block_group->cluster_list) ? "no" : "yes"); |
0b246afa6 btrfs: root->fs_i... |
2533 |
btrfs_info(fs_info, |
efe120a06 Btrfs: convert pr... |
2534 |
"%d blocks of free space at or bigger than bytes is", count); |
0f9dd46cd Btrfs: free space... |
2535 |
} |
32da5386d btrfs: rename btr... |
2536 |
void btrfs_init_free_space_ctl(struct btrfs_block_group *block_group) |
0f9dd46cd Btrfs: free space... |
2537 |
{ |
0b246afa6 btrfs: root->fs_i... |
2538 |
struct btrfs_fs_info *fs_info = block_group->fs_info; |
34d52cb6c Btrfs: Make free ... |
2539 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
0f9dd46cd Btrfs: free space... |
2540 |
|
34d52cb6c Btrfs: Make free ... |
2541 |
spin_lock_init(&ctl->tree_lock); |
0b246afa6 btrfs: root->fs_i... |
2542 |
ctl->unit = fs_info->sectorsize; |
b3470b5db btrfs: add dedica... |
2543 |
ctl->start = block_group->start; |
34d52cb6c Btrfs: Make free ... |
2544 2545 |
ctl->private = block_group; ctl->op = &free_space_op; |
55507ce36 Btrfs: fix race b... |
2546 2547 |
INIT_LIST_HEAD(&ctl->trimming_ranges); mutex_init(&ctl->cache_writeout_mutex); |
0f9dd46cd Btrfs: free space... |
2548 |
|
34d52cb6c Btrfs: Make free ... |
2549 2550 2551 2552 2553 |
/* * we only want to have 32k of ram per block group for keeping * track of free space, and if we pass 1/2 of that we want to * start converting things over to using bitmaps */ |
ee22184b5 Btrfs: use linux/... |
2554 |
ctl->extents_thresh = (SZ_32K / 2) / sizeof(struct btrfs_free_space); |
0f9dd46cd Btrfs: free space... |
2555 |
} |
fa9c0d795 Btrfs: rework all... |
2556 2557 2558 2559 2560 2561 |
/* * for a given cluster, put all of its extents back into the free * space cache. If the block group passed doesn't match the block group * pointed to by the cluster, someone else raced in and freed the * cluster already. In that case, we just return without changing anything */ |
69b0e093c btrfs: let btrfs_... |
2562 |
static void __btrfs_return_cluster_to_free_space( |
32da5386d btrfs: rename btr... |
2563 |
struct btrfs_block_group *block_group, |
fa9c0d795 Btrfs: rework all... |
2564 2565 |
struct btrfs_free_cluster *cluster) { |
34d52cb6c Btrfs: Make free ... |
2566 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
fa9c0d795 Btrfs: rework all... |
2567 2568 2569 2570 2571 2572 |
struct btrfs_free_space *entry; struct rb_node *node; spin_lock(&cluster->lock); if (cluster->block_group != block_group) goto out; |
963030817 Btrfs: use hybrid... |
2573 |
cluster->block_group = NULL; |
fa9c0d795 Btrfs: rework all... |
2574 |
cluster->window_start = 0; |
963030817 Btrfs: use hybrid... |
2575 |
list_del_init(&cluster->block_group_list); |
963030817 Btrfs: use hybrid... |
2576 |
|
fa9c0d795 Btrfs: rework all... |
2577 |
node = rb_first(&cluster->root); |
963030817 Btrfs: use hybrid... |
2578 |
while (node) { |
4e69b598f Btrfs: cleanup ho... |
2579 |
bool bitmap; |
fa9c0d795 Btrfs: rework all... |
2580 2581 2582 |
entry = rb_entry(node, struct btrfs_free_space, offset_index); node = rb_next(&entry->offset_index); rb_erase(&entry->offset_index, &cluster->root); |
200055239 Btrfs: improve fr... |
2583 |
RB_CLEAR_NODE(&entry->offset_index); |
4e69b598f Btrfs: cleanup ho... |
2584 2585 |
bitmap = (entry->bitmap != NULL); |
200055239 Btrfs: improve fr... |
2586 |
if (!bitmap) { |
dfb79ddb1 btrfs: track disc... |
2587 |
/* Merging treats extents as if they were new */ |
5dc7c10b8 btrfs: keep track... |
2588 |
if (!btrfs_free_space_trimmed(entry)) { |
dfb79ddb1 btrfs: track disc... |
2589 |
ctl->discardable_extents[BTRFS_STAT_CURR]--; |
5dc7c10b8 btrfs: keep track... |
2590 2591 2592 |
ctl->discardable_bytes[BTRFS_STAT_CURR] -= entry->bytes; } |
dfb79ddb1 btrfs: track disc... |
2593 |
|
34d52cb6c Btrfs: Make free ... |
2594 |
try_merge_free_space(ctl, entry, false); |
200055239 Btrfs: improve fr... |
2595 |
steal_from_bitmap(ctl, entry, false); |
dfb79ddb1 btrfs: track disc... |
2596 2597 |
/* As we insert directly, update these statistics */ |
5dc7c10b8 btrfs: keep track... |
2598 |
if (!btrfs_free_space_trimmed(entry)) { |
dfb79ddb1 btrfs: track disc... |
2599 |
ctl->discardable_extents[BTRFS_STAT_CURR]++; |
5dc7c10b8 btrfs: keep track... |
2600 2601 2602 |
ctl->discardable_bytes[BTRFS_STAT_CURR] += entry->bytes; } |
200055239 Btrfs: improve fr... |
2603 |
} |
34d52cb6c Btrfs: Make free ... |
2604 |
tree_insert_offset(&ctl->free_space_offset, |
4e69b598f Btrfs: cleanup ho... |
2605 |
entry->offset, &entry->offset_index, bitmap); |
fa9c0d795 Btrfs: rework all... |
2606 |
} |
6bef4d317 Btrfs: use RB_ROO... |
2607 |
cluster->root = RB_ROOT; |
963030817 Btrfs: use hybrid... |
2608 |
|
fa9c0d795 Btrfs: rework all... |
2609 2610 |
out: spin_unlock(&cluster->lock); |
963030817 Btrfs: use hybrid... |
2611 |
btrfs_put_block_group(block_group); |
fa9c0d795 Btrfs: rework all... |
2612 |
} |
48a3b6366 btrfs: make stati... |
2613 2614 |
static void __btrfs_remove_free_space_cache_locked( struct btrfs_free_space_ctl *ctl) |
0f9dd46cd Btrfs: free space... |
2615 2616 2617 |
{ struct btrfs_free_space *info; struct rb_node *node; |
581bb0509 Btrfs: Cache free... |
2618 |
|
581bb0509 Btrfs: Cache free... |
2619 2620 |
while ((node = rb_last(&ctl->free_space_offset)) != NULL) { info = rb_entry(node, struct btrfs_free_space, offset_index); |
9b90f5135 Btrfs: make sure ... |
2621 2622 2623 2624 2625 2626 |
if (!info->bitmap) { unlink_free_space(ctl, info); kmem_cache_free(btrfs_free_space_cachep, info); } else { free_bitmap(ctl, info); } |
351810c1d btrfs: use cond_r... |
2627 2628 |
cond_resched_lock(&ctl->tree_lock); |
581bb0509 Btrfs: Cache free... |
2629 |
} |
096553730 Merge branch 'ino... |
2630 2631 2632 2633 2634 2635 |
} void __btrfs_remove_free_space_cache(struct btrfs_free_space_ctl *ctl) { spin_lock(&ctl->tree_lock); __btrfs_remove_free_space_cache_locked(ctl); |
27f0afc73 btrfs: ensure rem... |
2636 2637 |
if (ctl->private) btrfs_discard_update_discardable(ctl->private, ctl); |
581bb0509 Btrfs: Cache free... |
2638 2639 |
spin_unlock(&ctl->tree_lock); } |
32da5386d btrfs: rename btr... |
2640 |
void btrfs_remove_free_space_cache(struct btrfs_block_group *block_group) |
581bb0509 Btrfs: Cache free... |
2641 2642 |
{ struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
fa9c0d795 Btrfs: rework all... |
2643 |
struct btrfs_free_cluster *cluster; |
963030817 Btrfs: use hybrid... |
2644 |
struct list_head *head; |
0f9dd46cd Btrfs: free space... |
2645 |
|
34d52cb6c Btrfs: Make free ... |
2646 |
spin_lock(&ctl->tree_lock); |
963030817 Btrfs: use hybrid... |
2647 2648 2649 2650 |
while ((head = block_group->cluster_list.next) != &block_group->cluster_list) { cluster = list_entry(head, struct btrfs_free_cluster, block_group_list); |
fa9c0d795 Btrfs: rework all... |
2651 2652 2653 |
WARN_ON(cluster->block_group != block_group); __btrfs_return_cluster_to_free_space(block_group, cluster); |
351810c1d btrfs: use cond_r... |
2654 2655 |
cond_resched_lock(&ctl->tree_lock); |
fa9c0d795 Btrfs: rework all... |
2656 |
} |
096553730 Merge branch 'ino... |
2657 |
__btrfs_remove_free_space_cache_locked(ctl); |
dfb79ddb1 btrfs: track disc... |
2658 |
btrfs_discard_update_discardable(block_group, ctl); |
34d52cb6c Btrfs: Make free ... |
2659 |
spin_unlock(&ctl->tree_lock); |
fa9c0d795 Btrfs: rework all... |
2660 |
|
0f9dd46cd Btrfs: free space... |
2661 |
} |
6e80d4f8c btrfs: handle emp... |
2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 |
/** * btrfs_is_free_space_trimmed - see if everything is trimmed * @block_group: block_group of interest * * Walk @block_group's free space rb_tree to determine if everything is trimmed. */ bool btrfs_is_free_space_trimmed(struct btrfs_block_group *block_group) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *info; struct rb_node *node; bool ret = true; spin_lock(&ctl->tree_lock); node = rb_first(&ctl->free_space_offset); while (node) { info = rb_entry(node, struct btrfs_free_space, offset_index); if (!btrfs_free_space_trimmed(info)) { ret = false; break; } node = rb_next(node); } spin_unlock(&ctl->tree_lock); return ret; } |
32da5386d btrfs: rename btr... |
2692 |
u64 btrfs_find_space_for_alloc(struct btrfs_block_group *block_group, |
a48203988 Btrfs: allocate t... |
2693 2694 |
u64 offset, u64 bytes, u64 empty_size, u64 *max_extent_size) |
0f9dd46cd Btrfs: free space... |
2695 |
{ |
34d52cb6c Btrfs: Make free ... |
2696 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
9ddf648f9 btrfs: keep track... |
2697 2698 |
struct btrfs_discard_ctl *discard_ctl = &block_group->fs_info->discard_ctl; |
6226cb0a5 Btrfs: kill the b... |
2699 |
struct btrfs_free_space *entry = NULL; |
963030817 Btrfs: use hybrid... |
2700 |
u64 bytes_search = bytes + empty_size; |
6226cb0a5 Btrfs: kill the b... |
2701 |
u64 ret = 0; |
53b381b3a Btrfs: RAID5 and ... |
2702 2703 |
u64 align_gap = 0; u64 align_gap_len = 0; |
a7ccb2558 btrfs: keep track... |
2704 |
enum btrfs_trim_state align_gap_trim_state = BTRFS_TRIM_STATE_UNTRIMMED; |
0f9dd46cd Btrfs: free space... |
2705 |
|
34d52cb6c Btrfs: Make free ... |
2706 |
spin_lock(&ctl->tree_lock); |
53b381b3a Btrfs: RAID5 and ... |
2707 |
entry = find_free_space(ctl, &offset, &bytes_search, |
a48203988 Btrfs: allocate t... |
2708 |
block_group->full_stripe_len, max_extent_size); |
6226cb0a5 Btrfs: kill the b... |
2709 |
if (!entry) |
963030817 Btrfs: use hybrid... |
2710 2711 2712 2713 |
goto out; ret = offset; if (entry->bitmap) { |
34d52cb6c Btrfs: Make free ... |
2714 |
bitmap_clear_bits(ctl, entry, offset, bytes); |
9ddf648f9 btrfs: keep track... |
2715 2716 2717 |
if (!btrfs_free_space_trimmed(entry)) atomic64_add(bytes, &discard_ctl->discard_bytes_saved); |
edf6e2d1d btrfs: Add helper... |
2718 |
if (!entry->bytes) |
34d52cb6c Btrfs: Make free ... |
2719 |
free_bitmap(ctl, entry); |
963030817 Btrfs: use hybrid... |
2720 |
} else { |
34d52cb6c Btrfs: Make free ... |
2721 |
unlink_free_space(ctl, entry); |
53b381b3a Btrfs: RAID5 and ... |
2722 2723 |
align_gap_len = offset - entry->offset; align_gap = entry->offset; |
a7ccb2558 btrfs: keep track... |
2724 |
align_gap_trim_state = entry->trim_state; |
53b381b3a Btrfs: RAID5 and ... |
2725 |
|
9ddf648f9 btrfs: keep track... |
2726 2727 |
if (!btrfs_free_space_trimmed(entry)) atomic64_add(bytes, &discard_ctl->discard_bytes_saved); |
53b381b3a Btrfs: RAID5 and ... |
2728 2729 2730 2731 |
entry->offset = offset + bytes; WARN_ON(entry->bytes < bytes + align_gap_len); entry->bytes -= bytes + align_gap_len; |
6226cb0a5 Btrfs: kill the b... |
2732 |
if (!entry->bytes) |
dc89e9824 Btrfs: use a slab... |
2733 |
kmem_cache_free(btrfs_free_space_cachep, entry); |
6226cb0a5 Btrfs: kill the b... |
2734 |
else |
34d52cb6c Btrfs: Make free ... |
2735 |
link_free_space(ctl, entry); |
6226cb0a5 Btrfs: kill the b... |
2736 |
} |
963030817 Btrfs: use hybrid... |
2737 |
out: |
dfb79ddb1 btrfs: track disc... |
2738 |
btrfs_discard_update_discardable(block_group, ctl); |
34d52cb6c Btrfs: Make free ... |
2739 |
spin_unlock(&ctl->tree_lock); |
817d52f8d Btrfs: async bloc... |
2740 |
|
53b381b3a Btrfs: RAID5 and ... |
2741 |
if (align_gap_len) |
ab8d0fc48 btrfs: convert pr... |
2742 |
__btrfs_add_free_space(block_group->fs_info, ctl, |
a7ccb2558 btrfs: keep track... |
2743 2744 |
align_gap, align_gap_len, align_gap_trim_state); |
0f9dd46cd Btrfs: free space... |
2745 2746 |
return ret; } |
fa9c0d795 Btrfs: rework all... |
2747 2748 2749 2750 2751 2752 2753 2754 2755 |
/* * given a cluster, put all of its extents back into the free space * cache. If a block group is passed, this function will only free * a cluster that belongs to the passed block group. * * Otherwise, it'll get a reference on the block group pointed to by the * cluster and remove the cluster from it. */ |
69b0e093c btrfs: let btrfs_... |
2756 |
void btrfs_return_cluster_to_free_space( |
32da5386d btrfs: rename btr... |
2757 |
struct btrfs_block_group *block_group, |
fa9c0d795 Btrfs: rework all... |
2758 2759 |
struct btrfs_free_cluster *cluster) { |
34d52cb6c Btrfs: Make free ... |
2760 |
struct btrfs_free_space_ctl *ctl; |
fa9c0d795 Btrfs: rework all... |
2761 2762 2763 2764 2765 2766 2767 |
/* first, get a safe pointer to the block group */ spin_lock(&cluster->lock); if (!block_group) { block_group = cluster->block_group; if (!block_group) { spin_unlock(&cluster->lock); |
69b0e093c btrfs: let btrfs_... |
2768 |
return; |
fa9c0d795 Btrfs: rework all... |
2769 2770 2771 2772 |
} } else if (cluster->block_group != block_group) { /* someone else has already freed it don't redo their work */ spin_unlock(&cluster->lock); |
69b0e093c btrfs: let btrfs_... |
2773 |
return; |
fa9c0d795 Btrfs: rework all... |
2774 |
} |
b5790d518 btrfs: use helper... |
2775 |
btrfs_get_block_group(block_group); |
fa9c0d795 Btrfs: rework all... |
2776 |
spin_unlock(&cluster->lock); |
34d52cb6c Btrfs: Make free ... |
2777 |
ctl = block_group->free_space_ctl; |
fa9c0d795 Btrfs: rework all... |
2778 |
/* now return any extents the cluster had on it */ |
34d52cb6c Btrfs: Make free ... |
2779 |
spin_lock(&ctl->tree_lock); |
69b0e093c btrfs: let btrfs_... |
2780 |
__btrfs_return_cluster_to_free_space(block_group, cluster); |
34d52cb6c Btrfs: Make free ... |
2781 |
spin_unlock(&ctl->tree_lock); |
fa9c0d795 Btrfs: rework all... |
2782 |
|
6e80d4f8c btrfs: handle emp... |
2783 |
btrfs_discard_queue_work(&block_group->fs_info->discard_ctl, block_group); |
fa9c0d795 Btrfs: rework all... |
2784 2785 |
/* finally drop our ref */ btrfs_put_block_group(block_group); |
fa9c0d795 Btrfs: rework all... |
2786 |
} |
32da5386d btrfs: rename btr... |
2787 |
static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group *block_group, |
963030817 Btrfs: use hybrid... |
2788 |
struct btrfs_free_cluster *cluster, |
4e69b598f Btrfs: cleanup ho... |
2789 |
struct btrfs_free_space *entry, |
a48203988 Btrfs: allocate t... |
2790 2791 |
u64 bytes, u64 min_start, u64 *max_extent_size) |
963030817 Btrfs: use hybrid... |
2792 |
{ |
34d52cb6c Btrfs: Make free ... |
2793 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
963030817 Btrfs: use hybrid... |
2794 2795 2796 2797 |
int err; u64 search_start = cluster->window_start; u64 search_bytes = bytes; u64 ret = 0; |
963030817 Btrfs: use hybrid... |
2798 2799 |
search_start = min_start; search_bytes = bytes; |
0584f718e Btrfs: don't do e... |
2800 |
err = search_bitmap(ctl, entry, &search_start, &search_bytes, true); |
a48203988 Btrfs: allocate t... |
2801 |
if (err) { |
ad22cf6ea btrfs: set max_ex... |
2802 2803 |
*max_extent_size = max(get_max_extent_size(entry), *max_extent_size); |
4e69b598f Btrfs: cleanup ho... |
2804 |
return 0; |
a48203988 Btrfs: allocate t... |
2805 |
} |
963030817 Btrfs: use hybrid... |
2806 2807 |
ret = search_start; |
bb3ac5a4d Btrfs: fix wrong ... |
2808 |
__bitmap_clear_bits(ctl, entry, ret, bytes); |
963030817 Btrfs: use hybrid... |
2809 2810 2811 |
return ret; } |
fa9c0d795 Btrfs: rework all... |
2812 2813 2814 2815 2816 |
/* * given a cluster, try to allocate 'bytes' from it, returns 0 * if it couldn't find anything suitably large, or a logical disk offset * if things worked out */ |
32da5386d btrfs: rename btr... |
2817 |
u64 btrfs_alloc_from_cluster(struct btrfs_block_group *block_group, |
fa9c0d795 Btrfs: rework all... |
2818 |
struct btrfs_free_cluster *cluster, u64 bytes, |
a48203988 Btrfs: allocate t... |
2819 |
u64 min_start, u64 *max_extent_size) |
fa9c0d795 Btrfs: rework all... |
2820 |
{ |
34d52cb6c Btrfs: Make free ... |
2821 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
9ddf648f9 btrfs: keep track... |
2822 2823 |
struct btrfs_discard_ctl *discard_ctl = &block_group->fs_info->discard_ctl; |
fa9c0d795 Btrfs: rework all... |
2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 |
struct btrfs_free_space *entry = NULL; struct rb_node *node; u64 ret = 0; spin_lock(&cluster->lock); if (bytes > cluster->max_size) goto out; if (cluster->block_group != block_group) goto out; node = rb_first(&cluster->root); if (!node) goto out; entry = rb_entry(node, struct btrfs_free_space, offset_index); |
678712545 btrfs: Fix checkp... |
2840 |
while (1) { |
ad22cf6ea btrfs: set max_ex... |
2841 2842 2843 |
if (entry->bytes < bytes) *max_extent_size = max(get_max_extent_size(entry), *max_extent_size); |
a48203988 Btrfs: allocate t... |
2844 |
|
4e69b598f Btrfs: cleanup ho... |
2845 2846 |
if (entry->bytes < bytes || (!entry->bitmap && entry->offset < min_start)) { |
fa9c0d795 Btrfs: rework all... |
2847 2848 2849 2850 2851 2852 2853 |
node = rb_next(&entry->offset_index); if (!node) break; entry = rb_entry(node, struct btrfs_free_space, offset_index); continue; } |
fa9c0d795 Btrfs: rework all... |
2854 |
|
4e69b598f Btrfs: cleanup ho... |
2855 2856 2857 |
if (entry->bitmap) { ret = btrfs_alloc_from_bitmap(block_group, cluster, entry, bytes, |
a48203988 Btrfs: allocate t... |
2858 2859 |
cluster->window_start, max_extent_size); |
4e69b598f Btrfs: cleanup ho... |
2860 |
if (ret == 0) { |
4e69b598f Btrfs: cleanup ho... |
2861 2862 2863 2864 2865 2866 2867 |
node = rb_next(&entry->offset_index); if (!node) break; entry = rb_entry(node, struct btrfs_free_space, offset_index); continue; } |
9b2306284 Btrfs: advance wi... |
2868 |
cluster->window_start += bytes; |
4e69b598f Btrfs: cleanup ho... |
2869 |
} else { |
4e69b598f Btrfs: cleanup ho... |
2870 2871 2872 2873 2874 |
ret = entry->offset; entry->offset += bytes; entry->bytes -= bytes; } |
fa9c0d795 Btrfs: rework all... |
2875 |
|
5e71b5d5e btrfs: Update sta... |
2876 |
if (entry->bytes == 0) |
fa9c0d795 Btrfs: rework all... |
2877 |
rb_erase(&entry->offset_index, &cluster->root); |
fa9c0d795 Btrfs: rework all... |
2878 2879 2880 2881 |
break; } out: spin_unlock(&cluster->lock); |
963030817 Btrfs: use hybrid... |
2882 |
|
5e71b5d5e btrfs: Update sta... |
2883 2884 |
if (!ret) return 0; |
34d52cb6c Btrfs: Make free ... |
2885 |
spin_lock(&ctl->tree_lock); |
5e71b5d5e btrfs: Update sta... |
2886 |
|
9ddf648f9 btrfs: keep track... |
2887 2888 |
if (!btrfs_free_space_trimmed(entry)) atomic64_add(bytes, &discard_ctl->discard_bytes_saved); |
34d52cb6c Btrfs: Make free ... |
2889 |
ctl->free_space -= bytes; |
5dc7c10b8 btrfs: keep track... |
2890 2891 |
if (!entry->bitmap && !btrfs_free_space_trimmed(entry)) ctl->discardable_bytes[BTRFS_STAT_CURR] -= bytes; |
5e71b5d5e btrfs: Update sta... |
2892 |
if (entry->bytes == 0) { |
34d52cb6c Btrfs: Make free ... |
2893 |
ctl->free_extents--; |
4e69b598f Btrfs: cleanup ho... |
2894 |
if (entry->bitmap) { |
3acd48507 btrfs: fix alloca... |
2895 2896 |
kmem_cache_free(btrfs_free_space_bitmap_cachep, entry->bitmap); |
34d52cb6c Btrfs: Make free ... |
2897 2898 |
ctl->total_bitmaps--; ctl->op->recalc_thresholds(ctl); |
dfb79ddb1 btrfs: track disc... |
2899 2900 |
} else if (!btrfs_free_space_trimmed(entry)) { ctl->discardable_extents[BTRFS_STAT_CURR]--; |
4e69b598f Btrfs: cleanup ho... |
2901 |
} |
dc89e9824 Btrfs: use a slab... |
2902 |
kmem_cache_free(btrfs_free_space_cachep, entry); |
5e71b5d5e btrfs: Update sta... |
2903 |
} |
34d52cb6c Btrfs: Make free ... |
2904 |
spin_unlock(&ctl->tree_lock); |
5e71b5d5e btrfs: Update sta... |
2905 |
|
fa9c0d795 Btrfs: rework all... |
2906 2907 |
return ret; } |
32da5386d btrfs: rename btr... |
2908 |
static int btrfs_bitmap_cluster(struct btrfs_block_group *block_group, |
963030817 Btrfs: use hybrid... |
2909 2910 |
struct btrfs_free_space *entry, struct btrfs_free_cluster *cluster, |
1bb91902d Btrfs: revamp clu... |
2911 2912 |
u64 offset, u64 bytes, u64 cont1_bytes, u64 min_bytes) |
963030817 Btrfs: use hybrid... |
2913 |
{ |
34d52cb6c Btrfs: Make free ... |
2914 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
963030817 Btrfs: use hybrid... |
2915 2916 |
unsigned long next_zero; unsigned long i; |
1bb91902d Btrfs: revamp clu... |
2917 2918 |
unsigned long want_bits; unsigned long min_bits; |
963030817 Btrfs: use hybrid... |
2919 |
unsigned long found_bits; |
cef404837 Btrfs: keep track... |
2920 |
unsigned long max_bits = 0; |
963030817 Btrfs: use hybrid... |
2921 2922 |
unsigned long start = 0; unsigned long total_found = 0; |
4e69b598f Btrfs: cleanup ho... |
2923 |
int ret; |
963030817 Btrfs: use hybrid... |
2924 |
|
960097622 Btrfs: use ctl->u... |
2925 |
i = offset_to_bit(entry->offset, ctl->unit, |
963030817 Btrfs: use hybrid... |
2926 |
max_t(u64, offset, entry->offset)); |
960097622 Btrfs: use ctl->u... |
2927 2928 |
want_bits = bytes_to_bits(bytes, ctl->unit); min_bits = bytes_to_bits(min_bytes, ctl->unit); |
963030817 Btrfs: use hybrid... |
2929 |
|
cef404837 Btrfs: keep track... |
2930 2931 2932 2933 2934 2935 2936 |
/* * Don't bother looking for a cluster in this bitmap if it's heavily * fragmented. */ if (entry->max_extent_size && entry->max_extent_size < cont1_bytes) return -ENOSPC; |
963030817 Btrfs: use hybrid... |
2937 2938 |
again: found_bits = 0; |
ebb3dad43 Btrfs: using for_... |
2939 |
for_each_set_bit_from(i, entry->bitmap, BITS_PER_BITMAP) { |
963030817 Btrfs: use hybrid... |
2940 2941 |
next_zero = find_next_zero_bit(entry->bitmap, BITS_PER_BITMAP, i); |
1bb91902d Btrfs: revamp clu... |
2942 |
if (next_zero - i >= min_bits) { |
963030817 Btrfs: use hybrid... |
2943 |
found_bits = next_zero - i; |
cef404837 Btrfs: keep track... |
2944 2945 |
if (found_bits > max_bits) max_bits = found_bits; |
963030817 Btrfs: use hybrid... |
2946 2947 |
break; } |
cef404837 Btrfs: keep track... |
2948 2949 |
if (next_zero - i > max_bits) max_bits = next_zero - i; |
963030817 Btrfs: use hybrid... |
2950 2951 |
i = next_zero; } |
cef404837 Btrfs: keep track... |
2952 2953 |
if (!found_bits) { entry->max_extent_size = (u64)max_bits * ctl->unit; |
4e69b598f Btrfs: cleanup ho... |
2954 |
return -ENOSPC; |
cef404837 Btrfs: keep track... |
2955 |
} |
963030817 Btrfs: use hybrid... |
2956 |
|
1bb91902d Btrfs: revamp clu... |
2957 |
if (!total_found) { |
963030817 Btrfs: use hybrid... |
2958 |
start = i; |
b78d09bce Btrfs: reset clus... |
2959 |
cluster->max_size = 0; |
963030817 Btrfs: use hybrid... |
2960 2961 2962 |
} total_found += found_bits; |
960097622 Btrfs: use ctl->u... |
2963 2964 |
if (cluster->max_size < found_bits * ctl->unit) cluster->max_size = found_bits * ctl->unit; |
963030817 Btrfs: use hybrid... |
2965 |
|
1bb91902d Btrfs: revamp clu... |
2966 2967 |
if (total_found < want_bits || cluster->max_size < cont1_bytes) { i = next_zero + 1; |
963030817 Btrfs: use hybrid... |
2968 2969 |
goto again; } |
960097622 Btrfs: use ctl->u... |
2970 |
cluster->window_start = start * ctl->unit + entry->offset; |
34d52cb6c Btrfs: Make free ... |
2971 |
rb_erase(&entry->offset_index, &ctl->free_space_offset); |
4e69b598f Btrfs: cleanup ho... |
2972 2973 |
ret = tree_insert_offset(&cluster->root, entry->offset, &entry->offset_index, 1); |
b12d6869f Btrfs: convert al... |
2974 |
ASSERT(!ret); /* -EEXIST; Logic error */ |
963030817 Btrfs: use hybrid... |
2975 |
|
3f7de037f Btrfs: add alloca... |
2976 |
trace_btrfs_setup_cluster(block_group, cluster, |
960097622 Btrfs: use ctl->u... |
2977 |
total_found * ctl->unit, 1); |
963030817 Btrfs: use hybrid... |
2978 2979 |
return 0; } |
fa9c0d795 Btrfs: rework all... |
2980 |
/* |
4e69b598f Btrfs: cleanup ho... |
2981 |
* This searches the block group for just extents to fill the cluster with. |
1bb91902d Btrfs: revamp clu... |
2982 2983 |
* Try to find a cluster with at least bytes total bytes, at least one * extent of cont1_bytes, and other clusters of at least min_bytes. |
4e69b598f Btrfs: cleanup ho... |
2984 |
*/ |
3de85bb95 Btrfs: noinline t... |
2985 |
static noinline int |
32da5386d btrfs: rename btr... |
2986 |
setup_cluster_no_bitmap(struct btrfs_block_group *block_group, |
3de85bb95 Btrfs: noinline t... |
2987 2988 |
struct btrfs_free_cluster *cluster, struct list_head *bitmaps, u64 offset, u64 bytes, |
1bb91902d Btrfs: revamp clu... |
2989 |
u64 cont1_bytes, u64 min_bytes) |
4e69b598f Btrfs: cleanup ho... |
2990 |
{ |
34d52cb6c Btrfs: Make free ... |
2991 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
4e69b598f Btrfs: cleanup ho... |
2992 2993 |
struct btrfs_free_space *first = NULL; struct btrfs_free_space *entry = NULL; |
4e69b598f Btrfs: cleanup ho... |
2994 2995 |
struct btrfs_free_space *last; struct rb_node *node; |
4e69b598f Btrfs: cleanup ho... |
2996 2997 |
u64 window_free; u64 max_extent; |
3f7de037f Btrfs: add alloca... |
2998 |
u64 total_size = 0; |
4e69b598f Btrfs: cleanup ho... |
2999 |
|
34d52cb6c Btrfs: Make free ... |
3000 |
entry = tree_search_offset(ctl, offset, 0, 1); |
4e69b598f Btrfs: cleanup ho... |
3001 3002 3003 3004 3005 3006 3007 |
if (!entry) return -ENOSPC; /* * We don't want bitmaps, so just move along until we find a normal * extent entry. */ |
1bb91902d Btrfs: revamp clu... |
3008 3009 |
while (entry->bitmap || entry->bytes < min_bytes) { if (entry->bitmap && list_empty(&entry->list)) |
86d4a77ba Btrfs: cache bitm... |
3010 |
list_add_tail(&entry->list, bitmaps); |
4e69b598f Btrfs: cleanup ho... |
3011 3012 3013 3014 3015 |
node = rb_next(&entry->offset_index); if (!node) return -ENOSPC; entry = rb_entry(node, struct btrfs_free_space, offset_index); } |
4e69b598f Btrfs: cleanup ho... |
3016 3017 3018 3019 |
window_free = entry->bytes; max_extent = entry->bytes; first = entry; last = entry; |
4e69b598f Btrfs: cleanup ho... |
3020 |
|
1bb91902d Btrfs: revamp clu... |
3021 3022 |
for (node = rb_next(&entry->offset_index); node; node = rb_next(&entry->offset_index)) { |
4e69b598f Btrfs: cleanup ho... |
3023 |
entry = rb_entry(node, struct btrfs_free_space, offset_index); |
86d4a77ba Btrfs: cache bitm... |
3024 3025 3026 |
if (entry->bitmap) { if (list_empty(&entry->list)) list_add_tail(&entry->list, bitmaps); |
4e69b598f Btrfs: cleanup ho... |
3027 |
continue; |
86d4a77ba Btrfs: cache bitm... |
3028 |
} |
1bb91902d Btrfs: revamp clu... |
3029 3030 3031 3032 3033 3034 |
if (entry->bytes < min_bytes) continue; last = entry; window_free += entry->bytes; if (entry->bytes > max_extent) |
4e69b598f Btrfs: cleanup ho... |
3035 |
max_extent = entry->bytes; |
4e69b598f Btrfs: cleanup ho... |
3036 |
} |
1bb91902d Btrfs: revamp clu... |
3037 3038 |
if (window_free < bytes || max_extent < cont1_bytes) return -ENOSPC; |
4e69b598f Btrfs: cleanup ho... |
3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 |
cluster->window_start = first->offset; node = &first->offset_index; /* * now we've found our entries, pull them out of the free space * cache and put them into the cluster rbtree */ do { int ret; entry = rb_entry(node, struct btrfs_free_space, offset_index); node = rb_next(&entry->offset_index); |
1bb91902d Btrfs: revamp clu... |
3052 |
if (entry->bitmap || entry->bytes < min_bytes) |
4e69b598f Btrfs: cleanup ho... |
3053 |
continue; |
34d52cb6c Btrfs: Make free ... |
3054 |
rb_erase(&entry->offset_index, &ctl->free_space_offset); |
4e69b598f Btrfs: cleanup ho... |
3055 3056 |
ret = tree_insert_offset(&cluster->root, entry->offset, &entry->offset_index, 0); |
3f7de037f Btrfs: add alloca... |
3057 |
total_size += entry->bytes; |
b12d6869f Btrfs: convert al... |
3058 |
ASSERT(!ret); /* -EEXIST; Logic error */ |
4e69b598f Btrfs: cleanup ho... |
3059 3060 3061 |
} while (node && entry != last); cluster->max_size = max_extent; |
3f7de037f Btrfs: add alloca... |
3062 |
trace_btrfs_setup_cluster(block_group, cluster, total_size, 0); |
4e69b598f Btrfs: cleanup ho... |
3063 3064 3065 3066 3067 3068 3069 |
return 0; } /* * This specifically looks for bitmaps that may work in the cluster, we assume * that we have already failed to find extents that will work. */ |
3de85bb95 Btrfs: noinline t... |
3070 |
static noinline int |
32da5386d btrfs: rename btr... |
3071 |
setup_cluster_bitmap(struct btrfs_block_group *block_group, |
3de85bb95 Btrfs: noinline t... |
3072 3073 |
struct btrfs_free_cluster *cluster, struct list_head *bitmaps, u64 offset, u64 bytes, |
1bb91902d Btrfs: revamp clu... |
3074 |
u64 cont1_bytes, u64 min_bytes) |
4e69b598f Btrfs: cleanup ho... |
3075 |
{ |
34d52cb6c Btrfs: Make free ... |
3076 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
1b9b922a3 Btrfs: check for ... |
3077 |
struct btrfs_free_space *entry = NULL; |
4e69b598f Btrfs: cleanup ho... |
3078 |
int ret = -ENOSPC; |
0f0fbf1d0 Btrfs: fix to sea... |
3079 |
u64 bitmap_offset = offset_to_bitmap(ctl, offset); |
4e69b598f Btrfs: cleanup ho... |
3080 |
|
34d52cb6c Btrfs: Make free ... |
3081 |
if (ctl->total_bitmaps == 0) |
4e69b598f Btrfs: cleanup ho... |
3082 |
return -ENOSPC; |
86d4a77ba Btrfs: cache bitm... |
3083 |
/* |
0f0fbf1d0 Btrfs: fix to sea... |
3084 3085 3086 |
* The bitmap that covers offset won't be in the list unless offset * is just its start offset. */ |
1b9b922a3 Btrfs: check for ... |
3087 3088 3089 3090 |
if (!list_empty(bitmaps)) entry = list_first_entry(bitmaps, struct btrfs_free_space, list); if (!entry || entry->offset != bitmap_offset) { |
0f0fbf1d0 Btrfs: fix to sea... |
3091 3092 3093 3094 |
entry = tree_search_offset(ctl, bitmap_offset, 1, 0); if (entry && list_empty(&entry->list)) list_add(&entry->list, bitmaps); } |
86d4a77ba Btrfs: cache bitm... |
3095 |
list_for_each_entry(entry, bitmaps, list) { |
357b9784b Btrfs: make sure ... |
3096 |
if (entry->bytes < bytes) |
86d4a77ba Btrfs: cache bitm... |
3097 3098 |
continue; ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, |
1bb91902d Btrfs: revamp clu... |
3099 |
bytes, cont1_bytes, min_bytes); |
86d4a77ba Btrfs: cache bitm... |
3100 3101 3102 3103 3104 |
if (!ret) return 0; } /* |
52621cb6e Btrfs: avoid unne... |
3105 3106 |
* The bitmaps list has all the bitmaps that record free space * starting after offset, so no more search is required. |
86d4a77ba Btrfs: cache bitm... |
3107 |
*/ |
52621cb6e Btrfs: avoid unne... |
3108 |
return -ENOSPC; |
4e69b598f Btrfs: cleanup ho... |
3109 3110 3111 |
} /* |
fa9c0d795 Btrfs: rework all... |
3112 |
* here we try to find a cluster of blocks in a block group. The goal |
1bb91902d Btrfs: revamp clu... |
3113 |
* is to find at least bytes+empty_size. |
fa9c0d795 Btrfs: rework all... |
3114 3115 3116 3117 3118 |
* We might not find them all in one contiguous area. * * returns zero and sets up cluster if things worked out, otherwise * it returns -enospc */ |
32da5386d btrfs: rename btr... |
3119 |
int btrfs_find_space_cluster(struct btrfs_block_group *block_group, |
fa9c0d795 Btrfs: rework all... |
3120 3121 3122 |
struct btrfs_free_cluster *cluster, u64 offset, u64 bytes, u64 empty_size) { |
2ceeae2e4 btrfs: get fs_inf... |
3123 |
struct btrfs_fs_info *fs_info = block_group->fs_info; |
34d52cb6c Btrfs: Make free ... |
3124 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
86d4a77ba Btrfs: cache bitm... |
3125 |
struct btrfs_free_space *entry, *tmp; |
52621cb6e Btrfs: avoid unne... |
3126 |
LIST_HEAD(bitmaps); |
fa9c0d795 Btrfs: rework all... |
3127 |
u64 min_bytes; |
1bb91902d Btrfs: revamp clu... |
3128 |
u64 cont1_bytes; |
fa9c0d795 Btrfs: rework all... |
3129 |
int ret; |
1bb91902d Btrfs: revamp clu... |
3130 3131 3132 3133 3134 3135 |
/* * Choose the minimum extent size we'll require for this * cluster. For SSD_SPREAD, don't allow any fragmentation. * For metadata, allow allocates with smaller extents. For * data, keep it dense. */ |
0b246afa6 btrfs: root->fs_i... |
3136 |
if (btrfs_test_opt(fs_info, SSD_SPREAD)) { |
1bb91902d Btrfs: revamp clu... |
3137 |
cont1_bytes = min_bytes = bytes + empty_size; |
451d7585a Btrfs: add mount ... |
3138 |
} else if (block_group->flags & BTRFS_BLOCK_GROUP_METADATA) { |
1bb91902d Btrfs: revamp clu... |
3139 |
cont1_bytes = bytes; |
0b246afa6 btrfs: root->fs_i... |
3140 |
min_bytes = fs_info->sectorsize; |
1bb91902d Btrfs: revamp clu... |
3141 3142 |
} else { cont1_bytes = max(bytes, (bytes + empty_size) >> 2); |
0b246afa6 btrfs: root->fs_i... |
3143 |
min_bytes = fs_info->sectorsize; |
1bb91902d Btrfs: revamp clu... |
3144 |
} |
fa9c0d795 Btrfs: rework all... |
3145 |
|
34d52cb6c Btrfs: Make free ... |
3146 |
spin_lock(&ctl->tree_lock); |
7d0d2e8e6 Btrfs: check free... |
3147 3148 3149 3150 3151 |
/* * If we know we don't have enough space to make a cluster don't even * bother doing all the work to try and find one. */ |
1bb91902d Btrfs: revamp clu... |
3152 |
if (ctl->free_space < bytes) { |
34d52cb6c Btrfs: Make free ... |
3153 |
spin_unlock(&ctl->tree_lock); |
7d0d2e8e6 Btrfs: check free... |
3154 3155 |
return -ENOSPC; } |
fa9c0d795 Btrfs: rework all... |
3156 3157 3158 3159 3160 3161 3162 |
spin_lock(&cluster->lock); /* someone already found a cluster, hooray */ if (cluster->block_group) { ret = 0; goto out; } |
fa9c0d795 Btrfs: rework all... |
3163 |
|
3f7de037f Btrfs: add alloca... |
3164 3165 |
trace_btrfs_find_cluster(block_group, offset, bytes, empty_size, min_bytes); |
86d4a77ba Btrfs: cache bitm... |
3166 |
ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset, |
1bb91902d Btrfs: revamp clu... |
3167 3168 |
bytes + empty_size, cont1_bytes, min_bytes); |
4e69b598f Btrfs: cleanup ho... |
3169 |
if (ret) |
86d4a77ba Btrfs: cache bitm... |
3170 |
ret = setup_cluster_bitmap(block_group, cluster, &bitmaps, |
1bb91902d Btrfs: revamp clu... |
3171 3172 |
offset, bytes + empty_size, cont1_bytes, min_bytes); |
86d4a77ba Btrfs: cache bitm... |
3173 3174 3175 3176 |
/* Clear our temporary list */ list_for_each_entry_safe(entry, tmp, &bitmaps, list) list_del_init(&entry->list); |
fa9c0d795 Btrfs: rework all... |
3177 |
|
4e69b598f Btrfs: cleanup ho... |
3178 |
if (!ret) { |
b5790d518 btrfs: use helper... |
3179 |
btrfs_get_block_group(block_group); |
4e69b598f Btrfs: cleanup ho... |
3180 3181 3182 |
list_add_tail(&cluster->block_group_list, &block_group->cluster_list); cluster->block_group = block_group; |
3f7de037f Btrfs: add alloca... |
3183 3184 |
} else { trace_btrfs_failed_cluster_setup(block_group); |
fa9c0d795 Btrfs: rework all... |
3185 |
} |
fa9c0d795 Btrfs: rework all... |
3186 3187 |
out: spin_unlock(&cluster->lock); |
34d52cb6c Btrfs: Make free ... |
3188 |
spin_unlock(&ctl->tree_lock); |
fa9c0d795 Btrfs: rework all... |
3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 |
return ret; } /* * simple code to zero out a cluster */ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster) { spin_lock_init(&cluster->lock); spin_lock_init(&cluster->refill_lock); |
6bef4d317 Btrfs: use RB_ROO... |
3200 |
cluster->root = RB_ROOT; |
fa9c0d795 Btrfs: rework all... |
3201 |
cluster->max_size = 0; |
c759c4e16 Btrfs: don't keep... |
3202 |
cluster->fragmented = false; |
fa9c0d795 Btrfs: rework all... |
3203 3204 3205 |
INIT_LIST_HEAD(&cluster->block_group_list); cluster->block_group = NULL; } |
32da5386d btrfs: rename btr... |
3206 |
static int do_trimming(struct btrfs_block_group *block_group, |
7fe1e6415 Btrfs: rewrite bt... |
3207 |
u64 *total_trimmed, u64 start, u64 bytes, |
55507ce36 Btrfs: fix race b... |
3208 |
u64 reserved_start, u64 reserved_bytes, |
b0643e59c btrfs: add the be... |
3209 |
enum btrfs_trim_state reserved_trim_state, |
55507ce36 Btrfs: fix race b... |
3210 |
struct btrfs_trim_range *trim_entry) |
f7039b1d5 Btrfs: add btrfs_... |
3211 |
{ |
7fe1e6415 Btrfs: rewrite bt... |
3212 |
struct btrfs_space_info *space_info = block_group->space_info; |
f7039b1d5 Btrfs: add btrfs_... |
3213 |
struct btrfs_fs_info *fs_info = block_group->fs_info; |
55507ce36 Btrfs: fix race b... |
3214 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
7fe1e6415 Btrfs: rewrite bt... |
3215 3216 |
int ret; int update = 0; |
b0643e59c btrfs: add the be... |
3217 3218 3219 |
const u64 end = start + bytes; const u64 reserved_end = reserved_start + reserved_bytes; enum btrfs_trim_state trim_state = BTRFS_TRIM_STATE_UNTRIMMED; |
7fe1e6415 Btrfs: rewrite bt... |
3220 |
u64 trimmed = 0; |
f7039b1d5 Btrfs: add btrfs_... |
3221 |
|
7fe1e6415 Btrfs: rewrite bt... |
3222 3223 3224 3225 3226 3227 3228 3229 3230 |
spin_lock(&space_info->lock); spin_lock(&block_group->lock); if (!block_group->ro) { block_group->reserved += reserved_bytes; space_info->bytes_reserved += reserved_bytes; update = 1; } spin_unlock(&block_group->lock); spin_unlock(&space_info->lock); |
2ff7e61e0 btrfs: take an fs... |
3231 |
ret = btrfs_discard_extent(fs_info, start, bytes, &trimmed); |
b0643e59c btrfs: add the be... |
3232 |
if (!ret) { |
7fe1e6415 Btrfs: rewrite bt... |
3233 |
*total_trimmed += trimmed; |
b0643e59c btrfs: add the be... |
3234 3235 |
trim_state = BTRFS_TRIM_STATE_TRIMMED; } |
7fe1e6415 Btrfs: rewrite bt... |
3236 |
|
55507ce36 Btrfs: fix race b... |
3237 |
mutex_lock(&ctl->cache_writeout_mutex); |
b0643e59c btrfs: add the be... |
3238 3239 3240 3241 3242 3243 3244 3245 |
if (reserved_start < start) __btrfs_add_free_space(fs_info, ctl, reserved_start, start - reserved_start, reserved_trim_state); if (start + bytes < reserved_start + reserved_bytes) __btrfs_add_free_space(fs_info, ctl, end, reserved_end - end, reserved_trim_state); __btrfs_add_free_space(fs_info, ctl, start, bytes, trim_state); |
55507ce36 Btrfs: fix race b... |
3246 3247 |
list_del(&trim_entry->list); mutex_unlock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3248 3249 3250 3251 3252 3253 3254 3255 |
if (update) { spin_lock(&space_info->lock); spin_lock(&block_group->lock); if (block_group->ro) space_info->bytes_readonly += reserved_bytes; block_group->reserved -= reserved_bytes; space_info->bytes_reserved -= reserved_bytes; |
7fe1e6415 Btrfs: rewrite bt... |
3256 |
spin_unlock(&block_group->lock); |
8f63a8405 btrfs: switch ord... |
3257 |
spin_unlock(&space_info->lock); |
7fe1e6415 Btrfs: rewrite bt... |
3258 3259 3260 3261 |
} return ret; } |
2bee7eb8b btrfs: discard on... |
3262 3263 3264 |
/* * If @async is set, then we will trim 1 region and return. */ |
32da5386d btrfs: rename btr... |
3265 |
static int trim_no_bitmap(struct btrfs_block_group *block_group, |
2bee7eb8b btrfs: discard on... |
3266 3267 |
u64 *total_trimmed, u64 start, u64 end, u64 minlen, bool async) |
7fe1e6415 Btrfs: rewrite bt... |
3268 |
{ |
19b2a2c71 btrfs: make max a... |
3269 3270 |
struct btrfs_discard_ctl *discard_ctl = &block_group->fs_info->discard_ctl; |
7fe1e6415 Btrfs: rewrite bt... |
3271 3272 3273 3274 3275 3276 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *entry; struct rb_node *node; int ret = 0; u64 extent_start; u64 extent_bytes; |
b0643e59c btrfs: add the be... |
3277 |
enum btrfs_trim_state extent_trim_state; |
7fe1e6415 Btrfs: rewrite bt... |
3278 |
u64 bytes; |
19b2a2c71 btrfs: make max a... |
3279 |
const u64 max_discard_size = READ_ONCE(discard_ctl->max_discard_size); |
f7039b1d5 Btrfs: add btrfs_... |
3280 3281 |
while (start < end) { |
55507ce36 Btrfs: fix race b... |
3282 3283 3284 |
struct btrfs_trim_range trim_entry; mutex_lock(&ctl->cache_writeout_mutex); |
34d52cb6c Btrfs: Make free ... |
3285 |
spin_lock(&ctl->tree_lock); |
f7039b1d5 Btrfs: add btrfs_... |
3286 |
|
2bee7eb8b btrfs: discard on... |
3287 3288 |
if (ctl->free_space < minlen) goto out_unlock; |
f7039b1d5 Btrfs: add btrfs_... |
3289 |
|
34d52cb6c Btrfs: Make free ... |
3290 |
entry = tree_search_offset(ctl, start, 0, 1); |
2bee7eb8b btrfs: discard on... |
3291 3292 |
if (!entry) goto out_unlock; |
f7039b1d5 Btrfs: add btrfs_... |
3293 |
|
2bee7eb8b btrfs: discard on... |
3294 3295 3296 |
/* Skip bitmaps and if async, already trimmed entries */ while (entry->bitmap || (async && btrfs_free_space_trimmed(entry))) { |
7fe1e6415 Btrfs: rewrite bt... |
3297 |
node = rb_next(&entry->offset_index); |
2bee7eb8b btrfs: discard on... |
3298 3299 |
if (!node) goto out_unlock; |
7fe1e6415 Btrfs: rewrite bt... |
3300 3301 |
entry = rb_entry(node, struct btrfs_free_space, offset_index); |
f7039b1d5 Btrfs: add btrfs_... |
3302 |
} |
2bee7eb8b btrfs: discard on... |
3303 3304 |
if (entry->offset >= end) goto out_unlock; |
f7039b1d5 Btrfs: add btrfs_... |
3305 |
|
7fe1e6415 Btrfs: rewrite bt... |
3306 3307 |
extent_start = entry->offset; extent_bytes = entry->bytes; |
b0643e59c btrfs: add the be... |
3308 |
extent_trim_state = entry->trim_state; |
4aa9ad520 btrfs: limit max ... |
3309 3310 3311 3312 3313 3314 3315 3316 3317 |
if (async) { start = entry->offset; bytes = entry->bytes; if (bytes < minlen) { spin_unlock(&ctl->tree_lock); mutex_unlock(&ctl->cache_writeout_mutex); goto next; } unlink_free_space(ctl, entry); |
7fe6d45e4 btrfs: have multi... |
3318 3319 3320 3321 3322 3323 3324 3325 |
/* * Let bytes = BTRFS_MAX_DISCARD_SIZE + X. * If X < BTRFS_ASYNC_DISCARD_MIN_FILTER, we won't trim * X when we come back around. So trim it now. */ if (max_discard_size && bytes >= (max_discard_size + BTRFS_ASYNC_DISCARD_MIN_FILTER)) { |
19b2a2c71 btrfs: make max a... |
3326 3327 3328 3329 |
bytes = max_discard_size; extent_bytes = max_discard_size; entry->offset += max_discard_size; entry->bytes -= max_discard_size; |
4aa9ad520 btrfs: limit max ... |
3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 |
link_free_space(ctl, entry); } else { kmem_cache_free(btrfs_free_space_cachep, entry); } } else { start = max(start, extent_start); bytes = min(extent_start + extent_bytes, end) - start; if (bytes < minlen) { spin_unlock(&ctl->tree_lock); mutex_unlock(&ctl->cache_writeout_mutex); goto next; } |
f7039b1d5 Btrfs: add btrfs_... |
3342 |
|
4aa9ad520 btrfs: limit max ... |
3343 3344 3345 |
unlink_free_space(ctl, entry); kmem_cache_free(btrfs_free_space_cachep, entry); } |
7fe1e6415 Btrfs: rewrite bt... |
3346 |
|
34d52cb6c Btrfs: Make free ... |
3347 |
spin_unlock(&ctl->tree_lock); |
55507ce36 Btrfs: fix race b... |
3348 3349 3350 3351 |
trim_entry.start = extent_start; trim_entry.bytes = extent_bytes; list_add_tail(&trim_entry.list, &ctl->trimming_ranges); mutex_unlock(&ctl->cache_writeout_mutex); |
f7039b1d5 Btrfs: add btrfs_... |
3352 |
|
7fe1e6415 Btrfs: rewrite bt... |
3353 |
ret = do_trimming(block_group, total_trimmed, start, bytes, |
b0643e59c btrfs: add the be... |
3354 3355 |
extent_start, extent_bytes, extent_trim_state, &trim_entry); |
2bee7eb8b btrfs: discard on... |
3356 3357 |
if (ret) { block_group->discard_cursor = start + bytes; |
7fe1e6415 Btrfs: rewrite bt... |
3358 |
break; |
2bee7eb8b btrfs: discard on... |
3359 |
} |
7fe1e6415 Btrfs: rewrite bt... |
3360 3361 |
next: start += bytes; |
2bee7eb8b btrfs: discard on... |
3362 3363 3364 |
block_group->discard_cursor = start; if (async && *total_trimmed) break; |
f7039b1d5 Btrfs: add btrfs_... |
3365 |
|
7fe1e6415 Btrfs: rewrite bt... |
3366 3367 3368 3369 3370 3371 3372 |
if (fatal_signal_pending(current)) { ret = -ERESTARTSYS; break; } cond_resched(); } |
2bee7eb8b btrfs: discard on... |
3373 3374 3375 3376 3377 3378 3379 |
return ret; out_unlock: block_group->discard_cursor = btrfs_block_group_end(block_group); spin_unlock(&ctl->tree_lock); mutex_unlock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3380 3381 |
return ret; } |
da080fe1b btrfs: keep track... |
3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 |
/* * If we break out of trimming a bitmap prematurely, we should reset the * trimming bit. In a rather contrieved case, it's possible to race here so * reset the state to BTRFS_TRIM_STATE_UNTRIMMED. * * start = start of bitmap * end = near end of bitmap * * Thread 1: Thread 2: * trim_bitmaps(start) * trim_bitmaps(end) * end_trimming_bitmap() * reset_trimming_bitmap() */ static void reset_trimming_bitmap(struct btrfs_free_space_ctl *ctl, u64 offset) { struct btrfs_free_space *entry; spin_lock(&ctl->tree_lock); entry = tree_search_offset(ctl, offset, 1, 0); |
dfb79ddb1 btrfs: track disc... |
3402 |
if (entry) { |
5dc7c10b8 btrfs: keep track... |
3403 |
if (btrfs_free_space_trimmed(entry)) { |
dfb79ddb1 btrfs: track disc... |
3404 3405 |
ctl->discardable_extents[BTRFS_STAT_CURR] += entry->bitmap_extents; |
5dc7c10b8 btrfs: keep track... |
3406 3407 |
ctl->discardable_bytes[BTRFS_STAT_CURR] += entry->bytes; } |
da080fe1b btrfs: keep track... |
3408 |
entry->trim_state = BTRFS_TRIM_STATE_UNTRIMMED; |
dfb79ddb1 btrfs: track disc... |
3409 |
} |
da080fe1b btrfs: keep track... |
3410 3411 |
spin_unlock(&ctl->tree_lock); } |
dfb79ddb1 btrfs: track disc... |
3412 3413 |
static void end_trimming_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *entry) |
da080fe1b btrfs: keep track... |
3414 |
{ |
dfb79ddb1 btrfs: track disc... |
3415 |
if (btrfs_free_space_trimming_bitmap(entry)) { |
da080fe1b btrfs: keep track... |
3416 |
entry->trim_state = BTRFS_TRIM_STATE_TRIMMED; |
dfb79ddb1 btrfs: track disc... |
3417 3418 |
ctl->discardable_extents[BTRFS_STAT_CURR] -= entry->bitmap_extents; |
5dc7c10b8 btrfs: keep track... |
3419 |
ctl->discardable_bytes[BTRFS_STAT_CURR] -= entry->bytes; |
dfb79ddb1 btrfs: track disc... |
3420 |
} |
da080fe1b btrfs: keep track... |
3421 |
} |
2bee7eb8b btrfs: discard on... |
3422 3423 3424 |
/* * If @async is set, then we will trim 1 region and return. */ |
32da5386d btrfs: rename btr... |
3425 |
static int trim_bitmaps(struct btrfs_block_group *block_group, |
2bee7eb8b btrfs: discard on... |
3426 |
u64 *total_trimmed, u64 start, u64 end, u64 minlen, |
7fe6d45e4 btrfs: have multi... |
3427 |
u64 maxlen, bool async) |
7fe1e6415 Btrfs: rewrite bt... |
3428 |
{ |
19b2a2c71 btrfs: make max a... |
3429 3430 |
struct btrfs_discard_ctl *discard_ctl = &block_group->fs_info->discard_ctl; |
7fe1e6415 Btrfs: rewrite bt... |
3431 3432 3433 3434 3435 3436 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space *entry; int ret = 0; int ret2; u64 bytes; u64 offset = offset_to_bitmap(ctl, start); |
19b2a2c71 btrfs: make max a... |
3437 |
const u64 max_discard_size = READ_ONCE(discard_ctl->max_discard_size); |
7fe1e6415 Btrfs: rewrite bt... |
3438 3439 3440 |
while (offset < end) { bool next_bitmap = false; |
55507ce36 Btrfs: fix race b... |
3441 |
struct btrfs_trim_range trim_entry; |
7fe1e6415 Btrfs: rewrite bt... |
3442 |
|
55507ce36 Btrfs: fix race b... |
3443 |
mutex_lock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3444 3445 3446 |
spin_lock(&ctl->tree_lock); if (ctl->free_space < minlen) { |
2bee7eb8b btrfs: discard on... |
3447 3448 |
block_group->discard_cursor = btrfs_block_group_end(block_group); |
7fe1e6415 Btrfs: rewrite bt... |
3449 |
spin_unlock(&ctl->tree_lock); |
55507ce36 Btrfs: fix race b... |
3450 |
mutex_unlock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3451 3452 3453 3454 |
break; } entry = tree_search_offset(ctl, offset, 1, 0); |
7fe6d45e4 btrfs: have multi... |
3455 3456 3457 3458 3459 3460 3461 3462 3463 |
/* * Bitmaps are marked trimmed lossily now to prevent constant * discarding of the same bitmap (the reason why we are bound * by the filters). So, retrim the block group bitmaps when we * are preparing to punt to the unused_bgs list. This uses * @minlen to determine if we are in BTRFS_DISCARD_INDEX_UNUSED * which is the only discard index which sets minlen to 0. */ if (!entry || (async && minlen && start == offset && |
2bee7eb8b btrfs: discard on... |
3464 |
btrfs_free_space_trimmed(entry))) { |
7fe1e6415 Btrfs: rewrite bt... |
3465 |
spin_unlock(&ctl->tree_lock); |
55507ce36 Btrfs: fix race b... |
3466 |
mutex_unlock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3467 3468 3469 |
next_bitmap = true; goto next; } |
da080fe1b btrfs: keep track... |
3470 3471 3472 3473 3474 3475 3476 3477 |
/* * Async discard bitmap trimming begins at by setting the start * to be key.objectid and the offset_to_bitmap() aligns to the * start of the bitmap. This lets us know we are fully * scanning the bitmap rather than only some portion of it. */ if (start == offset) entry->trim_state = BTRFS_TRIM_STATE_TRIMMING; |
7fe1e6415 Btrfs: rewrite bt... |
3478 |
bytes = minlen; |
0584f718e Btrfs: don't do e... |
3479 |
ret2 = search_bitmap(ctl, entry, &start, &bytes, false); |
7fe1e6415 Btrfs: rewrite bt... |
3480 |
if (ret2 || start >= end) { |
da080fe1b btrfs: keep track... |
3481 |
/* |
7fe6d45e4 btrfs: have multi... |
3482 3483 |
* We lossily consider a bitmap trimmed if we only skip * over regions <= BTRFS_ASYNC_DISCARD_MIN_FILTER. |
da080fe1b btrfs: keep track... |
3484 |
*/ |
7fe6d45e4 btrfs: have multi... |
3485 |
if (ret2 && minlen <= BTRFS_ASYNC_DISCARD_MIN_FILTER) |
dfb79ddb1 btrfs: track disc... |
3486 |
end_trimming_bitmap(ctl, entry); |
da080fe1b btrfs: keep track... |
3487 3488 |
else entry->trim_state = BTRFS_TRIM_STATE_UNTRIMMED; |
7fe1e6415 Btrfs: rewrite bt... |
3489 |
spin_unlock(&ctl->tree_lock); |
55507ce36 Btrfs: fix race b... |
3490 |
mutex_unlock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3491 3492 3493 |
next_bitmap = true; goto next; } |
2bee7eb8b btrfs: discard on... |
3494 3495 3496 3497 3498 3499 3500 3501 3502 |
/* * We already trimmed a region, but are using the locking above * to reset the trim_state. */ if (async && *total_trimmed) { spin_unlock(&ctl->tree_lock); mutex_unlock(&ctl->cache_writeout_mutex); goto out; } |
7fe1e6415 Btrfs: rewrite bt... |
3503 |
bytes = min(bytes, end - start); |
7fe6d45e4 btrfs: have multi... |
3504 |
if (bytes < minlen || (async && maxlen && bytes > maxlen)) { |
7fe1e6415 Btrfs: rewrite bt... |
3505 |
spin_unlock(&ctl->tree_lock); |
55507ce36 Btrfs: fix race b... |
3506 |
mutex_unlock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3507 3508 |
goto next; } |
7fe6d45e4 btrfs: have multi... |
3509 3510 3511 3512 3513 3514 3515 3516 3517 |
/* * Let bytes = BTRFS_MAX_DISCARD_SIZE + X. * If X < @minlen, we won't trim X when we come back around. * So trim it now. We differ here from trimming extents as we * don't keep individual state per bit. */ if (async && max_discard_size && bytes > (max_discard_size + minlen)) |
19b2a2c71 btrfs: make max a... |
3518 |
bytes = max_discard_size; |
4aa9ad520 btrfs: limit max ... |
3519 |
|
7fe1e6415 Btrfs: rewrite bt... |
3520 3521 3522 3523 3524 |
bitmap_clear_bits(ctl, entry, start, bytes); if (entry->bytes == 0) free_bitmap(ctl, entry); spin_unlock(&ctl->tree_lock); |
55507ce36 Btrfs: fix race b... |
3525 3526 3527 3528 |
trim_entry.start = start; trim_entry.bytes = bytes; list_add_tail(&trim_entry.list, &ctl->trimming_ranges); mutex_unlock(&ctl->cache_writeout_mutex); |
7fe1e6415 Btrfs: rewrite bt... |
3529 3530 |
ret = do_trimming(block_group, total_trimmed, start, bytes, |
b0643e59c btrfs: add the be... |
3531 |
start, bytes, 0, &trim_entry); |
da080fe1b btrfs: keep track... |
3532 3533 |
if (ret) { reset_trimming_bitmap(ctl, offset); |
2bee7eb8b btrfs: discard on... |
3534 3535 |
block_group->discard_cursor = btrfs_block_group_end(block_group); |
7fe1e6415 Btrfs: rewrite bt... |
3536 |
break; |
da080fe1b btrfs: keep track... |
3537 |
} |
7fe1e6415 Btrfs: rewrite bt... |
3538 3539 3540 |
next: if (next_bitmap) { offset += BITS_PER_BITMAP * ctl->unit; |
da080fe1b btrfs: keep track... |
3541 |
start = offset; |
7fe1e6415 Btrfs: rewrite bt... |
3542 3543 |
} else { start += bytes; |
f7039b1d5 Btrfs: add btrfs_... |
3544 |
} |
2bee7eb8b btrfs: discard on... |
3545 |
block_group->discard_cursor = start; |
f7039b1d5 Btrfs: add btrfs_... |
3546 3547 |
if (fatal_signal_pending(current)) { |
da080fe1b btrfs: keep track... |
3548 3549 |
if (start != offset) reset_trimming_bitmap(ctl, offset); |
f7039b1d5 Btrfs: add btrfs_... |
3550 3551 3552 3553 3554 3555 |
ret = -ERESTARTSYS; break; } cond_resched(); } |
2bee7eb8b btrfs: discard on... |
3556 3557 3558 3559 |
if (offset >= end) block_group->discard_cursor = end; out: |
f7039b1d5 Btrfs: add btrfs_... |
3560 3561 |
return ret; } |
581bb0509 Btrfs: Cache free... |
3562 |
|
32da5386d btrfs: rename btr... |
3563 |
int btrfs_trim_block_group(struct btrfs_block_group *block_group, |
e33e17ee1 btrfs: add missin... |
3564 3565 |
u64 *trimmed, u64 start, u64 end, u64 minlen) { |
da080fe1b btrfs: keep track... |
3566 |
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
e33e17ee1 btrfs: add missin... |
3567 |
int ret; |
da080fe1b btrfs: keep track... |
3568 |
u64 rem = 0; |
e33e17ee1 btrfs: add missin... |
3569 3570 3571 3572 3573 |
*trimmed = 0; spin_lock(&block_group->lock); if (block_group->removed) { |
04216820f Btrfs: fix race b... |
3574 |
spin_unlock(&block_group->lock); |
e33e17ee1 btrfs: add missin... |
3575 |
return 0; |
04216820f Btrfs: fix race b... |
3576 |
} |
6b7304af6 btrfs: rename mem... |
3577 |
btrfs_freeze_block_group(block_group); |
e33e17ee1 btrfs: add missin... |
3578 |
spin_unlock(&block_group->lock); |
2bee7eb8b btrfs: discard on... |
3579 |
ret = trim_no_bitmap(block_group, trimmed, start, end, minlen, false); |
e33e17ee1 btrfs: add missin... |
3580 3581 |
if (ret) goto out; |
7fe1e6415 Btrfs: rewrite bt... |
3582 |
|
7fe6d45e4 btrfs: have multi... |
3583 |
ret = trim_bitmaps(block_group, trimmed, start, end, minlen, 0, false); |
da080fe1b btrfs: keep track... |
3584 3585 3586 3587 |
div64_u64_rem(end, BITS_PER_BITMAP * ctl->unit, &rem); /* If we ended in the middle of a bitmap, reset the trimming flag */ if (rem) reset_trimming_bitmap(ctl, offset_to_bitmap(ctl, end)); |
e33e17ee1 btrfs: add missin... |
3588 |
out: |
6b7304af6 btrfs: rename mem... |
3589 |
btrfs_unfreeze_block_group(block_group); |
7fe1e6415 Btrfs: rewrite bt... |
3590 3591 |
return ret; } |
2bee7eb8b btrfs: discard on... |
3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 |
int btrfs_trim_block_group_extents(struct btrfs_block_group *block_group, u64 *trimmed, u64 start, u64 end, u64 minlen, bool async) { int ret; *trimmed = 0; spin_lock(&block_group->lock); if (block_group->removed) { spin_unlock(&block_group->lock); return 0; } |
6b7304af6 btrfs: rename mem... |
3605 |
btrfs_freeze_block_group(block_group); |
2bee7eb8b btrfs: discard on... |
3606 3607 3608 |
spin_unlock(&block_group->lock); ret = trim_no_bitmap(block_group, trimmed, start, end, minlen, async); |
6b7304af6 btrfs: rename mem... |
3609 |
btrfs_unfreeze_block_group(block_group); |
2bee7eb8b btrfs: discard on... |
3610 3611 3612 3613 3614 3615 |
return ret; } int btrfs_trim_block_group_bitmaps(struct btrfs_block_group *block_group, u64 *trimmed, u64 start, u64 end, u64 minlen, |
7fe6d45e4 btrfs: have multi... |
3616 |
u64 maxlen, bool async) |
2bee7eb8b btrfs: discard on... |
3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 |
{ int ret; *trimmed = 0; spin_lock(&block_group->lock); if (block_group->removed) { spin_unlock(&block_group->lock); return 0; } |
6b7304af6 btrfs: rename mem... |
3627 |
btrfs_freeze_block_group(block_group); |
2bee7eb8b btrfs: discard on... |
3628 |
spin_unlock(&block_group->lock); |
7fe6d45e4 btrfs: have multi... |
3629 3630 |
ret = trim_bitmaps(block_group, trimmed, start, end, minlen, maxlen, async); |
6b7304af6 btrfs: rename mem... |
3631 |
btrfs_unfreeze_block_group(block_group); |
2bee7eb8b btrfs: discard on... |
3632 3633 3634 |
return ret; } |
581bb0509 Btrfs: Cache free... |
3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 |
/* * Find the left-most item in the cache tree, and then return the * smallest inode number in the item. * * Note: the returned inode number may not be the smallest one in * the tree, if the left-most item is a bitmap. */ u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root) { struct btrfs_free_space_ctl *ctl = fs_root->free_ino_ctl; struct btrfs_free_space *entry = NULL; u64 ino = 0; spin_lock(&ctl->tree_lock); if (RB_EMPTY_ROOT(&ctl->free_space_offset)) goto out; entry = rb_entry(rb_first(&ctl->free_space_offset), struct btrfs_free_space, offset_index); if (!entry->bitmap) { ino = entry->offset; unlink_free_space(ctl, entry); entry->offset++; entry->bytes--; if (!entry->bytes) kmem_cache_free(btrfs_free_space_cachep, entry); else link_free_space(ctl, entry); } else { u64 offset = 0; u64 count = 1; int ret; |
0584f718e Btrfs: don't do e... |
3670 |
ret = search_bitmap(ctl, entry, &offset, &count, true); |
79787eaab btrfs: replace ma... |
3671 |
/* Logic error; Should be empty if it can't find anything */ |
b12d6869f Btrfs: convert al... |
3672 |
ASSERT(!ret); |
581bb0509 Btrfs: Cache free... |
3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 |
ino = offset; bitmap_clear_bits(ctl, entry, offset, 1); if (entry->bytes == 0) free_bitmap(ctl, entry); } out: spin_unlock(&ctl->tree_lock); return ino; } |
82d5902d9 Btrfs: Support re... |
3684 3685 3686 3687 3688 |
struct inode *lookup_free_ino_inode(struct btrfs_root *root, struct btrfs_path *path) { struct inode *inode = NULL; |
57cdc8db2 btrfs: cleanup in... |
3689 3690 3691 3692 |
spin_lock(&root->ino_cache_lock); if (root->ino_cache_inode) inode = igrab(root->ino_cache_inode); spin_unlock(&root->ino_cache_lock); |
82d5902d9 Btrfs: Support re... |
3693 3694 3695 3696 3697 3698 |
if (inode) return inode; inode = __lookup_free_space_inode(root, path, 0); if (IS_ERR(inode)) return inode; |
57cdc8db2 btrfs: cleanup in... |
3699 |
spin_lock(&root->ino_cache_lock); |
7841cb289 btrfs: add helper... |
3700 |
if (!btrfs_fs_closing(root->fs_info)) |
57cdc8db2 btrfs: cleanup in... |
3701 3702 |
root->ino_cache_inode = igrab(inode); spin_unlock(&root->ino_cache_lock); |
82d5902d9 Btrfs: Support re... |
3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 |
return inode; } int create_free_ino_inode(struct btrfs_root *root, struct btrfs_trans_handle *trans, struct btrfs_path *path) { return __create_free_space_inode(root, trans, path, BTRFS_FREE_INO_OBJECTID, 0); } int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root) { struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; struct btrfs_path *path; struct inode *inode; int ret = 0; u64 root_gen = btrfs_root_generation(&root->root_item); |
0b246afa6 btrfs: root->fs_i... |
3722 |
if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE)) |
4b9465cb9 Btrfs: add mount ... |
3723 |
return 0; |
82d5902d9 Btrfs: Support re... |
3724 3725 3726 3727 |
/* * If we're unmounting then just return, since this does a search on the * normal root and not the commit root and we could deadlock. */ |
7841cb289 btrfs: add helper... |
3728 |
if (btrfs_fs_closing(fs_info)) |
82d5902d9 Btrfs: Support re... |
3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 |
return 0; path = btrfs_alloc_path(); if (!path) return 0; inode = lookup_free_ino_inode(root, path); if (IS_ERR(inode)) goto out; if (root_gen != BTRFS_I(inode)->generation) goto out_put; ret = __load_free_space_cache(root, inode, ctl, path, 0); if (ret < 0) |
c2cf52eb7 Btrfs: Include th... |
3745 3746 3747 |
btrfs_err(fs_info, "failed to load free ino cache for root %llu", root->root_key.objectid); |
82d5902d9 Btrfs: Support re... |
3748 3749 3750 3751 3752 3753 3754 3755 3756 |
out_put: iput(inode); out: btrfs_free_path(path); return ret; } int btrfs_write_out_ino_cache(struct btrfs_root *root, struct btrfs_trans_handle *trans, |
53645a91f Btrfs: remove dup... |
3757 3758 |
struct btrfs_path *path, struct inode *inode) |
82d5902d9 Btrfs: Support re... |
3759 |
{ |
0b246afa6 btrfs: root->fs_i... |
3760 |
struct btrfs_fs_info *fs_info = root->fs_info; |
82d5902d9 Btrfs: Support re... |
3761 |
struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; |
82d5902d9 Btrfs: Support re... |
3762 |
int ret; |
c9dc4c657 Btrfs: two stage ... |
3763 |
struct btrfs_io_ctl io_ctl; |
e43699d4b Btrfs: fix crash ... |
3764 |
bool release_metadata = true; |
82d5902d9 Btrfs: Support re... |
3765 |
|
0b246afa6 btrfs: root->fs_i... |
3766 |
if (!btrfs_test_opt(fs_info, INODE_MAP_CACHE)) |
4b9465cb9 Btrfs: add mount ... |
3767 |
return 0; |
85db36cfb Btrfs: fix inode ... |
3768 |
memset(&io_ctl, 0, sizeof(io_ctl)); |
0e8d931a8 btrfs: remove unu... |
3769 |
ret = __btrfs_write_out_cache(root, inode, ctl, NULL, &io_ctl, trans); |
e43699d4b Btrfs: fix crash ... |
3770 3771 3772 3773 3774 3775 3776 3777 |
if (!ret) { /* * At this point writepages() didn't error out, so our metadata * reservation is released when the writeback finishes, at * inode.c:btrfs_finish_ordered_io(), regardless of it finishing * with or without an error. */ release_metadata = false; |
afdb57189 btrfs: simplify b... |
3778 |
ret = btrfs_wait_cache_io_root(root, trans, &io_ctl, path); |
e43699d4b Btrfs: fix crash ... |
3779 |
} |
85db36cfb Btrfs: fix inode ... |
3780 |
|
c09544e07 Btrfs: handle eno... |
3781 |
if (ret) { |
e43699d4b Btrfs: fix crash ... |
3782 |
if (release_metadata) |
691fa0596 btrfs: all btrfs_... |
3783 |
btrfs_delalloc_release_metadata(BTRFS_I(inode), |
43b18595d btrfs: qgroup: Us... |
3784 |
inode->i_size, true); |
bbcd1f4d5 btrfs: turn space... |
3785 |
btrfs_debug(fs_info, |
2e69a7a60 btrfs: include er... |
3786 3787 |
"failed to write free ino cache for root %llu error %d", root->root_key.objectid, ret); |
c09544e07 Btrfs: handle eno... |
3788 |
} |
82d5902d9 Btrfs: Support re... |
3789 |
|
82d5902d9 Btrfs: Support re... |
3790 3791 |
return ret; } |
74255aa07 Btrfs: add some f... |
3792 3793 |
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS |
dc11dd5d7 Btrfs: separate o... |
3794 3795 3796 3797 3798 3799 |
/* * Use this if you need to make a bitmap or extent entry specifically, it * doesn't do any of the merging that add_free_space does, this acts a lot like * how the free space cache loading stuff works, so you can get really weird * configurations. */ |
32da5386d btrfs: rename btr... |
3800 |
int test_add_free_space_entry(struct btrfs_block_group *cache, |
dc11dd5d7 Btrfs: separate o... |
3801 |
u64 offset, u64 bytes, bool bitmap) |
74255aa07 Btrfs: add some f... |
3802 |
{ |
dc11dd5d7 Btrfs: separate o... |
3803 3804 3805 |
struct btrfs_free_space_ctl *ctl = cache->free_space_ctl; struct btrfs_free_space *info = NULL, *bitmap_info; void *map = NULL; |
da080fe1b btrfs: keep track... |
3806 |
enum btrfs_trim_state trim_state = BTRFS_TRIM_STATE_TRIMMED; |
dc11dd5d7 Btrfs: separate o... |
3807 3808 |
u64 bytes_added; int ret; |
74255aa07 Btrfs: add some f... |
3809 |
|
dc11dd5d7 Btrfs: separate o... |
3810 3811 3812 3813 3814 |
again: if (!info) { info = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); if (!info) return -ENOMEM; |
74255aa07 Btrfs: add some f... |
3815 |
} |
dc11dd5d7 Btrfs: separate o... |
3816 3817 3818 3819 |
if (!bitmap) { spin_lock(&ctl->tree_lock); info->offset = offset; info->bytes = bytes; |
cef404837 Btrfs: keep track... |
3820 |
info->max_extent_size = 0; |
dc11dd5d7 Btrfs: separate o... |
3821 3822 3823 3824 3825 3826 3827 3828 |
ret = link_free_space(ctl, info); spin_unlock(&ctl->tree_lock); if (ret) kmem_cache_free(btrfs_free_space_cachep, info); return ret; } if (!map) { |
3acd48507 btrfs: fix alloca... |
3829 |
map = kmem_cache_zalloc(btrfs_free_space_bitmap_cachep, GFP_NOFS); |
dc11dd5d7 Btrfs: separate o... |
3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 |
if (!map) { kmem_cache_free(btrfs_free_space_cachep, info); return -ENOMEM; } } spin_lock(&ctl->tree_lock); bitmap_info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); if (!bitmap_info) { info->bitmap = map; map = NULL; add_new_bitmap(ctl, info, offset); bitmap_info = info; |
200055239 Btrfs: improve fr... |
3844 |
info = NULL; |
dc11dd5d7 Btrfs: separate o... |
3845 |
} |
74255aa07 Btrfs: add some f... |
3846 |
|
da080fe1b btrfs: keep track... |
3847 3848 |
bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes, trim_state); |
cef404837 Btrfs: keep track... |
3849 |
|
dc11dd5d7 Btrfs: separate o... |
3850 3851 3852 |
bytes -= bytes_added; offset += bytes_added; spin_unlock(&ctl->tree_lock); |
74255aa07 Btrfs: add some f... |
3853 |
|
dc11dd5d7 Btrfs: separate o... |
3854 3855 |
if (bytes) goto again; |
74255aa07 Btrfs: add some f... |
3856 |
|
200055239 Btrfs: improve fr... |
3857 3858 |
if (info) kmem_cache_free(btrfs_free_space_cachep, info); |
3acd48507 btrfs: fix alloca... |
3859 3860 |
if (map) kmem_cache_free(btrfs_free_space_bitmap_cachep, map); |
dc11dd5d7 Btrfs: separate o... |
3861 |
return 0; |
74255aa07 Btrfs: add some f... |
3862 3863 3864 3865 3866 3867 3868 |
} /* * Checks to see if the given range is in the free space cache. This is really * just used to check the absence of space, so if there is free space in the * range at all we will return 1. */ |
32da5386d btrfs: rename btr... |
3869 |
int test_check_exists(struct btrfs_block_group *cache, |
dc11dd5d7 Btrfs: separate o... |
3870 |
u64 offset, u64 bytes) |
74255aa07 Btrfs: add some f... |
3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 |
{ struct btrfs_free_space_ctl *ctl = cache->free_space_ctl; struct btrfs_free_space *info; int ret = 0; spin_lock(&ctl->tree_lock); info = tree_search_offset(ctl, offset, 0, 0); if (!info) { info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 1, 0); if (!info) goto out; } have_info: if (info->bitmap) { u64 bit_off, bit_bytes; struct rb_node *n; struct btrfs_free_space *tmp; bit_off = offset; bit_bytes = ctl->unit; |
0584f718e Btrfs: don't do e... |
3893 |
ret = search_bitmap(ctl, info, &bit_off, &bit_bytes, false); |
74255aa07 Btrfs: add some f... |
3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 |
if (!ret) { if (bit_off == offset) { ret = 1; goto out; } else if (bit_off > offset && offset + bytes > bit_off) { ret = 1; goto out; } } n = rb_prev(&info->offset_index); while (n) { tmp = rb_entry(n, struct btrfs_free_space, offset_index); if (tmp->offset + tmp->bytes < offset) break; if (offset + bytes < tmp->offset) { |
5473e0c42 Btrfs: test_check... |
3912 |
n = rb_prev(&tmp->offset_index); |
74255aa07 Btrfs: add some f... |
3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 |
continue; } info = tmp; goto have_info; } n = rb_next(&info->offset_index); while (n) { tmp = rb_entry(n, struct btrfs_free_space, offset_index); if (offset + bytes < tmp->offset) break; if (tmp->offset + tmp->bytes < offset) { |
5473e0c42 Btrfs: test_check... |
3926 |
n = rb_next(&tmp->offset_index); |
74255aa07 Btrfs: add some f... |
3927 3928 3929 3930 3931 |
continue; } info = tmp; goto have_info; } |
200055239 Btrfs: improve fr... |
3932 |
ret = 0; |
74255aa07 Btrfs: add some f... |
3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 |
goto out; } if (info->offset == offset) { ret = 1; goto out; } if (offset > info->offset && offset < info->offset + info->bytes) ret = 1; out: spin_unlock(&ctl->tree_lock); return ret; } |
dc11dd5d7 Btrfs: separate o... |
3947 |
#endif /* CONFIG_BTRFS_FS_RUN_SANITY_TESTS */ |