Blame view

fs/btrfs/tree-defrag.c 3.52 KB
6702ed490   Chris Mason   Btrfs: Add run ti...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   * Copyright (C) 2007 Oracle.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License v2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
  
  #include <linux/sched.h>
  #include "ctree.h"
  #include "disk-io.h"
  #include "print-tree.h"
  #include "transaction.h"
e7a84565b   Chris Mason   Btrfs: Add btree ...
24
  #include "locking.h"
6702ed490   Chris Mason   Btrfs: Add run ti...
25

d397712bc   Chris Mason   Btrfs: Fix checkp...
26
27
  /* defrag all the leaves in a given btree.  If cache_only == 1, don't read
   * things from disk, otherwise read all the leaves and try to get key order to
d352ac681   Chris Mason   Btrfs: add and im...
28
29
   * better reflect disk order
   */
d397712bc   Chris Mason   Btrfs: Fix checkp...
30

6702ed490   Chris Mason   Btrfs: Add run ti...
31
32
33
34
  int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
  			struct btrfs_root *root, int cache_only)
  {
  	struct btrfs_path *path = NULL;
e7a84565b   Chris Mason   Btrfs: Add btree ...
35
  	struct btrfs_key key;
6702ed490   Chris Mason   Btrfs: Add run ti...
36
37
38
  	int ret = 0;
  	int wret;
  	int level;
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
39
  	int is_extent = 0;
e7a84565b   Chris Mason   Btrfs: Add btree ...
40
  	int next_key_ret = 0;
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
41
  	u64 last_ret = 0;
3f157a2fd   Chris Mason   Btrfs: Online btr...
42
43
44
45
  	u64 min_trans = 0;
  
  	if (cache_only)
  		goto out;
e9d0b13b5   Chris Mason   Btrfs: Btree defr...
46

e7a84565b   Chris Mason   Btrfs: Add btree ...
47
  	if (root->fs_info->extent_root == root) {
1b1e2135d   Chris Mason   Btrfs: Add a per-...
48
49
50
51
52
  		/*
  		 * there's recursion here right now in the tree locking,
  		 * we can't defrag the extent root without deadlock
  		 */
  		goto out;
e7a84565b   Chris Mason   Btrfs: Add btree ...
53
  	}
925baeddc   Chris Mason   Btrfs: Start btre...
54

e9d0b13b5   Chris Mason   Btrfs: Btree defr...
55
  	if (root->ref_cows == 0 && !is_extent)
6702ed490   Chris Mason   Btrfs: Add run ti...
56
  		goto out;
5f39d397d   Chris Mason   Btrfs: Create ext...
57

9afbb0b75   Chris Mason   Btrfs: Disable tr...
58
59
  	if (btrfs_test_opt(root, SSD))
  		goto out;
6702ed490   Chris Mason   Btrfs: Add run ti...
60
61
62
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
5f39d397d   Chris Mason   Btrfs: Create ext...
63
  	level = btrfs_header_level(root->node);
0f1ebbd15   Chris Mason   Btrfs: Large bloc...
64

d397712bc   Chris Mason   Btrfs: Fix checkp...
65
  	if (level == 0)
6702ed490   Chris Mason   Btrfs: Add run ti...
66
  		goto out;
d397712bc   Chris Mason   Btrfs: Fix checkp...
67

6702ed490   Chris Mason   Btrfs: Add run ti...
68
  	if (root->defrag_progress.objectid == 0) {
e7a84565b   Chris Mason   Btrfs: Add btree ...
69
  		struct extent_buffer *root_node;
0ef3e66b6   Chris Mason   Btrfs: Allocator ...
70
  		u32 nritems;
e7a84565b   Chris Mason   Btrfs: Add btree ...
71
  		root_node = btrfs_lock_root_node(root);
b4ce94de9   Chris Mason   Btrfs: Change btr...
72
  		btrfs_set_lock_blocking(root_node);
e7a84565b   Chris Mason   Btrfs: Add btree ...
73
  		nritems = btrfs_header_nritems(root_node);
0ef3e66b6   Chris Mason   Btrfs: Allocator ...
74
75
  		root->defrag_max.objectid = 0;
  		/* from above we know this is not a leaf */
e7a84565b   Chris Mason   Btrfs: Add btree ...
76
  		btrfs_node_key_to_cpu(root_node, &root->defrag_max,
0ef3e66b6   Chris Mason   Btrfs: Allocator ...
77
  				      nritems - 1);
e7a84565b   Chris Mason   Btrfs: Add btree ...
78
79
80
  		btrfs_tree_unlock(root_node);
  		free_extent_buffer(root_node);
  		memset(&key, 0, sizeof(key));
6702ed490   Chris Mason   Btrfs: Add run ti...
81
  	} else {
e7a84565b   Chris Mason   Btrfs: Add btree ...
82
  		memcpy(&key, &root->defrag_progress, sizeof(key));
6702ed490   Chris Mason   Btrfs: Add run ti...
83
  	}
e7a84565b   Chris Mason   Btrfs: Add btree ...
84
  	path->keep_locks = 1;
3f157a2fd   Chris Mason   Btrfs: Online btr...
85
86
  	if (cache_only)
  		min_trans = root->defrag_trans_start;
e02119d5a   Chris Mason   Btrfs: Add a writ...
87
88
  	ret = btrfs_search_forward(root, &key, NULL, path,
  				   cache_only, min_trans);
3f157a2fd   Chris Mason   Btrfs: Online btr...
89
90
91
92
93
94
  	if (ret < 0)
  		goto out;
  	if (ret > 0) {
  		ret = 0;
  		goto out;
  	}
b3b4aa74b   David Sterba   btrfs: drop unuse...
95
  	btrfs_release_path(path);
e7a84565b   Chris Mason   Btrfs: Add btree ...
96
  	wret = btrfs_search_slot(trans, root, &key, path, 0, 1);
6702ed490   Chris Mason   Btrfs: Add run ti...
97

e7a84565b   Chris Mason   Btrfs: Add btree ...
98
99
100
101
102
103
104
105
106
  	if (wret < 0) {
  		ret = wret;
  		goto out;
  	}
  	if (!path->nodes[1]) {
  		ret = 0;
  		goto out;
  	}
  	path->slots[1] = btrfs_header_nritems(path->nodes[1]);
3f157a2fd   Chris Mason   Btrfs: Online btr...
107
108
  	next_key_ret = btrfs_find_next_key(root, path, &key, 1, cache_only,
  					   min_trans);
e7a84565b   Chris Mason   Btrfs: Add btree ...
109
110
111
112
  	ret = btrfs_realloc_node(trans, root,
  				 path->nodes[1], 0,
  				 cache_only, &last_ret,
  				 &root->defrag_progress);
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
113
114
115
116
  	if (ret) {
  		WARN_ON(ret == -EAGAIN);
  		goto out;
  	}
e7a84565b   Chris Mason   Btrfs: Add btree ...
117
118
119
  	if (next_key_ret == 0) {
  		memcpy(&root->defrag_progress, &key, sizeof(key));
  		ret = -EAGAIN;
6702ed490   Chris Mason   Btrfs: Add run ti...
120
  	}
6702ed490   Chris Mason   Btrfs: Add run ti...
121
122
123
  out:
  	if (path)
  		btrfs_free_path(path);
0ef3e66b6   Chris Mason   Btrfs: Allocator ...
124
125
126
127
128
129
130
131
132
133
  	if (ret == -EAGAIN) {
  		if (root->defrag_max.objectid > root->defrag_progress.objectid)
  			goto done;
  		if (root->defrag_max.type > root->defrag_progress.type)
  			goto done;
  		if (root->defrag_max.offset > root->defrag_progress.offset)
  			goto done;
  		ret = 0;
  	}
  done:
6702ed490   Chris Mason   Btrfs: Add run ti...
134
135
136
  	if (ret != -EAGAIN) {
  		memset(&root->defrag_progress, 0,
  		       sizeof(root->defrag_progress));
3f157a2fd   Chris Mason   Btrfs: Online btr...
137
  		root->defrag_trans_start = trans->transid;
6702ed490   Chris Mason   Btrfs: Add run ti...
138
139
140
  	}
  	return ret;
  }