Blame view

fs/btrfs/root-tree.c 10.7 KB
6cbd55707   Chris Mason   Btrfs: add GPLv2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * 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.
   */
3768f3689   Chris Mason   Btrfs: Change the...
18
  #include "ctree.h"
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
19
  #include "transaction.h"
3768f3689   Chris Mason   Btrfs: Change the...
20
21
  #include "disk-io.h"
  #include "print-tree.h"
bf4ef6792   Chris Mason   Btrfs: Properly f...
22
  /*
d352ac681   Chris Mason   Btrfs: add and im...
23
24
25
26
   * lookup the root with the highest offset for a given objectid.  The key we do
   * find is copied into 'key'.  If we find something return 0, otherwise 1, < 0
   * on error.
   */
3768f3689   Chris Mason   Btrfs: Change the...
27
28
29
  int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
  			struct btrfs_root_item *item, struct btrfs_key *key)
  {
5caf2a002   Chris Mason   Btrfs: dynamic al...
30
  	struct btrfs_path *path;
3768f3689   Chris Mason   Btrfs: Change the...
31
  	struct btrfs_key search_key;
5f39d397d   Chris Mason   Btrfs: Create ext...
32
33
  	struct btrfs_key found_key;
  	struct extent_buffer *l;
3768f3689   Chris Mason   Btrfs: Change the...
34
35
36
37
  	int ret;
  	int slot;
  
  	search_key.objectid = objectid;
0660b5af3   Chris Mason   Btrfs: Add backre...
38
  	search_key.type = BTRFS_ROOT_ITEM_KEY;
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
39
  	search_key.offset = (u64)-1;
3768f3689   Chris Mason   Btrfs: Change the...
40

5caf2a002   Chris Mason   Btrfs: dynamic al...
41
  	path = btrfs_alloc_path();
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
42
43
  	if (!path)
  		return -ENOMEM;
5caf2a002   Chris Mason   Btrfs: dynamic al...
44
  	ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
3768f3689   Chris Mason   Btrfs: Change the...
45
46
  	if (ret < 0)
  		goto out;
5f39d397d   Chris Mason   Btrfs: Create ext...
47

3768f3689   Chris Mason   Btrfs: Change the...
48
  	BUG_ON(ret == 0);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
49
50
51
52
  	if (path->slots[0] == 0) {
  		ret = 1;
  		goto out;
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
53
  	l = path->nodes[0];
5caf2a002   Chris Mason   Btrfs: dynamic al...
54
  	slot = path->slots[0] - 1;
5f39d397d   Chris Mason   Btrfs: Create ext...
55
  	btrfs_item_key_to_cpu(l, &found_key, slot);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
56
57
  	if (found_key.objectid != objectid ||
  	    found_key.type != BTRFS_ROOT_ITEM_KEY) {
3768f3689   Chris Mason   Btrfs: Change the...
58
59
60
  		ret = 1;
  		goto out;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
61
62
63
64
65
  	if (item)
  		read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot),
  				   sizeof(*item));
  	if (key)
  		memcpy(key, &found_key, sizeof(found_key));
3768f3689   Chris Mason   Btrfs: Change the...
66
67
  	ret = 0;
  out:
5caf2a002   Chris Mason   Btrfs: dynamic al...
68
  	btrfs_free_path(path);
3768f3689   Chris Mason   Btrfs: Change the...
69
70
  	return ret;
  }
bf5f32ecb   Mark Fasheh   btrfs: make btrfs...
71
72
  void btrfs_set_root_node(struct btrfs_root_item *item,
  			 struct extent_buffer *node)
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
73
74
75
76
  {
  	btrfs_set_root_bytenr(item, node->start);
  	btrfs_set_root_level(item, btrfs_header_level(node));
  	btrfs_set_root_generation(item, btrfs_header_generation(node));
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
77
  }
d352ac681   Chris Mason   Btrfs: add and im...
78
79
80
  /*
   * copy the data in 'item' into the btree
   */
e089f05c1   Chris Mason   Btrfs: transactio...
81
82
83
  int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
  		      *root, struct btrfs_key *key, struct btrfs_root_item
  		      *item)
3768f3689   Chris Mason   Btrfs: Change the...
84
  {
5caf2a002   Chris Mason   Btrfs: dynamic al...
85
  	struct btrfs_path *path;
5f39d397d   Chris Mason   Btrfs: Create ext...
86
  	struct extent_buffer *l;
3768f3689   Chris Mason   Btrfs: Change the...
87
88
  	int ret;
  	int slot;
5f39d397d   Chris Mason   Btrfs: Create ext...
89
  	unsigned long ptr;
3768f3689   Chris Mason   Btrfs: Change the...
90

5caf2a002   Chris Mason   Btrfs: dynamic al...
91
92
  	path = btrfs_alloc_path();
  	BUG_ON(!path);
5caf2a002   Chris Mason   Btrfs: dynamic al...
93
  	ret = btrfs_search_slot(trans, root, key, path, 0, 1);
3768f3689   Chris Mason   Btrfs: Change the...
94
95
  	if (ret < 0)
  		goto out;
d66674620   Chris Mason   Btrfs: Change st_...
96
97
98
  
  	if (ret != 0) {
  		btrfs_print_leaf(root, path->nodes[0]);
d397712bc   Chris Mason   Btrfs: Fix checkp...
99
100
101
102
  		printk(KERN_CRIT "unable to update root key %llu %u %llu
  ",
  		       (unsigned long long)key->objectid, key->type,
  		       (unsigned long long)key->offset);
d66674620   Chris Mason   Btrfs: Change st_...
103
104
  		BUG_ON(1);
  	}
5f39d397d   Chris Mason   Btrfs: Create ext...
105
  	l = path->nodes[0];
5caf2a002   Chris Mason   Btrfs: dynamic al...
106
  	slot = path->slots[0];
5f39d397d   Chris Mason   Btrfs: Create ext...
107
108
  	ptr = btrfs_item_ptr_offset(l, slot);
  	write_extent_buffer(l, item, ptr, sizeof(*item));
5caf2a002   Chris Mason   Btrfs: dynamic al...
109
  	btrfs_mark_buffer_dirty(path->nodes[0]);
3768f3689   Chris Mason   Btrfs: Change the...
110
  out:
5caf2a002   Chris Mason   Btrfs: dynamic al...
111
  	btrfs_free_path(path);
3768f3689   Chris Mason   Btrfs: Change the...
112
113
  	return ret;
  }
e089f05c1   Chris Mason   Btrfs: transactio...
114
115
116
  int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
  		      *root, struct btrfs_key *key, struct btrfs_root_item
  		      *item)
3768f3689   Chris Mason   Btrfs: Change the...
117
118
  {
  	int ret;
e089f05c1   Chris Mason   Btrfs: transactio...
119
  	ret = btrfs_insert_item(trans, root, key, item, sizeof(*item));
3768f3689   Chris Mason   Btrfs: Change the...
120
121
  	return ret;
  }
d352ac681   Chris Mason   Btrfs: add and im...
122
123
  /*
   * at mount time we want to find all the old transaction snapshots that were in
d397712bc   Chris Mason   Btrfs: Fix checkp...
124
125
126
   * the process of being deleted if we crashed.  This is any root item with an
   * offset lower than the latest root.  They need to be queued for deletion to
   * finish what was happening when we crashed.
d352ac681   Chris Mason   Btrfs: add and im...
127
   */
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
128
  int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid)
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
129
130
  {
  	struct btrfs_root *dead_root;
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
131
132
  	struct btrfs_root_item *ri;
  	struct btrfs_key key;
a7a16fd77   Chris Mason   Btrfs: Fix deadlo...
133
  	struct btrfs_key found_key;
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
134
135
136
  	struct btrfs_path *path;
  	int ret;
  	u32 nritems;
5f39d397d   Chris Mason   Btrfs: Create ext...
137
  	struct extent_buffer *leaf;
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
138
  	int slot;
5ce14bbcd   Chris Mason   Btrfs: Find and r...
139
  	key.objectid = objectid;
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
140
141
142
143
144
  	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
  	key.offset = 0;
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
a7a16fd77   Chris Mason   Btrfs: Fix deadlo...
145
146
  
  again:
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
147
148
149
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	if (ret < 0)
  		goto err;
d397712bc   Chris Mason   Btrfs: Fix checkp...
150
  	while (1) {
5f39d397d   Chris Mason   Btrfs: Create ext...
151
152
  		leaf = path->nodes[0];
  		nritems = btrfs_header_nritems(leaf);
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
153
154
155
156
157
  		slot = path->slots[0];
  		if (slot >= nritems) {
  			ret = btrfs_next_leaf(root, path);
  			if (ret)
  				break;
5f39d397d   Chris Mason   Btrfs: Create ext...
158
159
  			leaf = path->nodes[0];
  			nritems = btrfs_header_nritems(leaf);
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
160
161
  			slot = path->slots[0];
  		}
5f39d397d   Chris Mason   Btrfs: Create ext...
162
  		btrfs_item_key_to_cpu(leaf, &key, slot);
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
163
164
  		if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
  			goto next;
5ce14bbcd   Chris Mason   Btrfs: Find and r...
165
166
167
168
169
170
  
  		if (key.objectid < objectid)
  			goto next;
  
  		if (key.objectid > objectid)
  			break;
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
171
  		ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
5f39d397d   Chris Mason   Btrfs: Create ext...
172
  		if (btrfs_disk_root_refs(leaf, ri) != 0)
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
173
  			goto next;
5ce14bbcd   Chris Mason   Btrfs: Find and r...
174

a7a16fd77   Chris Mason   Btrfs: Fix deadlo...
175
176
  		memcpy(&found_key, &key, sizeof(key));
  		key.offset++;
b3b4aa74b   David Sterba   btrfs: drop unuse...
177
  		btrfs_release_path(path);
e02119d5a   Chris Mason   Btrfs: Add a writ...
178
179
180
  		dead_root =
  			btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
  						    &found_key);
a1f396304   Aneesh   Btrfs: Some code ...
181
182
  		if (IS_ERR(dead_root)) {
  			ret = PTR_ERR(dead_root);
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
183
184
  			goto err;
  		}
5ce14bbcd   Chris Mason   Btrfs: Find and r...
185

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
186
  		ret = btrfs_add_dead_root(dead_root);
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
187
188
  		if (ret)
  			goto err;
a7a16fd77   Chris Mason   Btrfs: Fix deadlo...
189
  		goto again;
5eda7b5e9   Chris Mason   Btrfs: Add the ab...
190
191
192
193
194
195
196
197
198
  next:
  		slot++;
  		path->slots[0]++;
  	}
  	ret = 0;
  err:
  	btrfs_free_path(path);
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
199
200
201
202
203
  int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
  {
  	struct extent_buffer *leaf;
  	struct btrfs_path *path;
  	struct btrfs_key key;
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
204
205
  	struct btrfs_key root_key;
  	struct btrfs_root *root;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
206
207
208
209
210
211
212
213
214
215
  	int err = 0;
  	int ret;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  
  	key.objectid = BTRFS_ORPHAN_OBJECTID;
  	key.type = BTRFS_ORPHAN_ITEM_KEY;
  	key.offset = 0;
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
216
217
  	root_key.type = BTRFS_ROOT_ITEM_KEY;
  	root_key.offset = (u64)-1;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  	while (1) {
  		ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
  		if (ret < 0) {
  			err = ret;
  			break;
  		}
  
  		leaf = path->nodes[0];
  		if (path->slots[0] >= btrfs_header_nritems(leaf)) {
  			ret = btrfs_next_leaf(tree_root, path);
  			if (ret < 0)
  				err = ret;
  			if (ret != 0)
  				break;
  			leaf = path->nodes[0];
  		}
  
  		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
b3b4aa74b   David Sterba   btrfs: drop unuse...
236
  		btrfs_release_path(path);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
237
238
239
240
  
  		if (key.objectid != BTRFS_ORPHAN_OBJECTID ||
  		    key.type != BTRFS_ORPHAN_ITEM_KEY)
  			break;
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
241
242
243
244
245
246
247
248
249
250
  		root_key.objectid = key.offset;
  		key.offset++;
  
  		root = btrfs_read_fs_root_no_name(tree_root->fs_info,
  						  &root_key);
  		if (!IS_ERR(root))
  			continue;
  
  		ret = PTR_ERR(root);
  		if (ret != -ENOENT) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
251
252
253
  			err = ret;
  			break;
  		}
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
254
255
256
257
258
  		ret = btrfs_find_dead_roots(tree_root, root_key.objectid);
  		if (ret) {
  			err = ret;
  			break;
  		}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
259
260
261
262
263
  	}
  
  	btrfs_free_path(path);
  	return err;
  }
d352ac681   Chris Mason   Btrfs: add and im...
264
  /* drop the root item for 'key' from 'root' */
e089f05c1   Chris Mason   Btrfs: transactio...
265
266
  int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
  		   struct btrfs_key *key)
3768f3689   Chris Mason   Btrfs: Change the...
267
  {
5caf2a002   Chris Mason   Btrfs: dynamic al...
268
  	struct btrfs_path *path;
3768f3689   Chris Mason   Btrfs: Change the...
269
  	int ret;
c5739bba5   Chris Mason   Btrfs: snapshot p...
270
  	struct btrfs_root_item *ri;
5f39d397d   Chris Mason   Btrfs: Create ext...
271
  	struct extent_buffer *leaf;
3768f3689   Chris Mason   Btrfs: Change the...
272

5caf2a002   Chris Mason   Btrfs: dynamic al...
273
  	path = btrfs_alloc_path();
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
274
275
  	if (!path)
  		return -ENOMEM;
5caf2a002   Chris Mason   Btrfs: dynamic al...
276
  	ret = btrfs_search_slot(trans, root, key, path, -1, 1);
3768f3689   Chris Mason   Btrfs: Change the...
277
278
  	if (ret < 0)
  		goto out;
edbd8d4ef   Chris Mason   Btrfs: Support fo...
279

3768f3689   Chris Mason   Btrfs: Change the...
280
  	BUG_ON(ret != 0);
5f39d397d   Chris Mason   Btrfs: Create ext...
281
282
  	leaf = path->nodes[0];
  	ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item);
c5739bba5   Chris Mason   Btrfs: snapshot p...
283

5eda7b5e9   Chris Mason   Btrfs: Add the ab...
284
  	ret = btrfs_del_item(trans, root, path);
3768f3689   Chris Mason   Btrfs: Change the...
285
  out:
5caf2a002   Chris Mason   Btrfs: dynamic al...
286
  	btrfs_free_path(path);
3768f3689   Chris Mason   Btrfs: Change the...
287
288
  	return ret;
  }
0660b5af3   Chris Mason   Btrfs: Add backre...
289
290
291
  
  int btrfs_del_root_ref(struct btrfs_trans_handle *trans,
  		       struct btrfs_root *tree_root,
4df27c4d5   Yan, Zheng   Btrfs: change how...
292
293
  		       u64 root_id, u64 ref_id, u64 dirid, u64 *sequence,
  		       const char *name, int name_len)
0660b5af3   Chris Mason   Btrfs: Add backre...
294
  {
4df27c4d5   Yan, Zheng   Btrfs: change how...
295
296
297
  	struct btrfs_path *path;
  	struct btrfs_root_ref *ref;
  	struct extent_buffer *leaf;
0660b5af3   Chris Mason   Btrfs: Add backre...
298
  	struct btrfs_key key;
4df27c4d5   Yan, Zheng   Btrfs: change how...
299
300
  	unsigned long ptr;
  	int err = 0;
0660b5af3   Chris Mason   Btrfs: Add backre...
301
  	int ret;
0660b5af3   Chris Mason   Btrfs: Add backre...
302
303
  
  	path = btrfs_alloc_path();
4df27c4d5   Yan, Zheng   Btrfs: change how...
304
305
  	if (!path)
  		return -ENOMEM;
0660b5af3   Chris Mason   Btrfs: Add backre...
306
307
  
  	key.objectid = root_id;
4df27c4d5   Yan, Zheng   Btrfs: change how...
308
  	key.type = BTRFS_ROOT_BACKREF_KEY;
0660b5af3   Chris Mason   Btrfs: Add backre...
309
  	key.offset = ref_id;
4df27c4d5   Yan, Zheng   Btrfs: change how...
310
  again:
0660b5af3   Chris Mason   Btrfs: Add backre...
311
  	ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
4df27c4d5   Yan, Zheng   Btrfs: change how...
312
313
314
315
316
317
318
319
320
321
322
323
324
  	BUG_ON(ret < 0);
  	if (ret == 0) {
  		leaf = path->nodes[0];
  		ref = btrfs_item_ptr(leaf, path->slots[0],
  				     struct btrfs_root_ref);
  
  		WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
  		WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
  		ptr = (unsigned long)(ref + 1);
  		WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
  		*sequence = btrfs_root_ref_sequence(leaf, ref);
  
  		ret = btrfs_del_item(trans, tree_root, path);
65a246c5f   Tsutomu Itoh   Btrfs: return err...
325
326
327
328
  		if (ret) {
  			err = ret;
  			goto out;
  		}
4df27c4d5   Yan, Zheng   Btrfs: change how...
329
330
331
332
  	} else
  		err = -ENOENT;
  
  	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
b3b4aa74b   David Sterba   btrfs: drop unuse...
333
  		btrfs_release_path(path);
4df27c4d5   Yan, Zheng   Btrfs: change how...
334
335
336
337
338
  		key.objectid = ref_id;
  		key.type = BTRFS_ROOT_REF_KEY;
  		key.offset = root_id;
  		goto again;
  	}
0660b5af3   Chris Mason   Btrfs: Add backre...
339

65a246c5f   Tsutomu Itoh   Btrfs: return err...
340
  out:
0660b5af3   Chris Mason   Btrfs: Add backre...
341
  	btrfs_free_path(path);
4df27c4d5   Yan, Zheng   Btrfs: change how...
342
  	return err;
0660b5af3   Chris Mason   Btrfs: Add backre...
343
  }
ea9e8b11b   Chris Mason   Btrfs: prevent lo...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  int btrfs_find_root_ref(struct btrfs_root *tree_root,
  		   struct btrfs_path *path,
  		   u64 root_id, u64 ref_id)
  {
  	struct btrfs_key key;
  	int ret;
  
  	key.objectid = root_id;
  	key.type = BTRFS_ROOT_REF_KEY;
  	key.offset = ref_id;
  
  	ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
  	return ret;
  }
0660b5af3   Chris Mason   Btrfs: Add backre...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
  /*
   * add a btrfs_root_ref item.  type is either BTRFS_ROOT_REF_KEY
   * or BTRFS_ROOT_BACKREF_KEY.
   *
   * The dirid, sequence, name and name_len refer to the directory entry
   * that is referencing the root.
   *
   * For a forward ref, the root_id is the id of the tree referencing
   * the root and ref_id is the id of the subvol  or snapshot.
   *
   * For a back ref the root_id is the id of the subvol or snapshot and
   * ref_id is the id of the tree referencing it.
   */
  int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
  		       struct btrfs_root *tree_root,
4df27c4d5   Yan, Zheng   Btrfs: change how...
373
  		       u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
0660b5af3   Chris Mason   Btrfs: Add backre...
374
375
376
377
378
379
380
381
  		       const char *name, int name_len)
  {
  	struct btrfs_key key;
  	int ret;
  	struct btrfs_path *path;
  	struct btrfs_root_ref *ref;
  	struct extent_buffer *leaf;
  	unsigned long ptr;
0660b5af3   Chris Mason   Btrfs: Add backre...
382
  	path = btrfs_alloc_path();
4df27c4d5   Yan, Zheng   Btrfs: change how...
383
384
  	if (!path)
  		return -ENOMEM;
0660b5af3   Chris Mason   Btrfs: Add backre...
385
386
  
  	key.objectid = root_id;
4df27c4d5   Yan, Zheng   Btrfs: change how...
387
  	key.type = BTRFS_ROOT_BACKREF_KEY;
0660b5af3   Chris Mason   Btrfs: Add backre...
388
  	key.offset = ref_id;
4df27c4d5   Yan, Zheng   Btrfs: change how...
389
  again:
0660b5af3   Chris Mason   Btrfs: Add backre...
390
391
392
393
394
395
396
397
398
399
400
401
  	ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
  				      sizeof(*ref) + name_len);
  	BUG_ON(ret);
  
  	leaf = path->nodes[0];
  	ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref);
  	btrfs_set_root_ref_dirid(leaf, ref, dirid);
  	btrfs_set_root_ref_sequence(leaf, ref, sequence);
  	btrfs_set_root_ref_name_len(leaf, ref, name_len);
  	ptr = (unsigned long)(ref + 1);
  	write_extent_buffer(leaf, name, ptr, name_len);
  	btrfs_mark_buffer_dirty(leaf);
4df27c4d5   Yan, Zheng   Btrfs: change how...
402
  	if (key.type == BTRFS_ROOT_BACKREF_KEY) {
b3b4aa74b   David Sterba   btrfs: drop unuse...
403
  		btrfs_release_path(path);
4df27c4d5   Yan, Zheng   Btrfs: change how...
404
405
406
407
408
  		key.objectid = ref_id;
  		key.type = BTRFS_ROOT_REF_KEY;
  		key.offset = root_id;
  		goto again;
  	}
0660b5af3   Chris Mason   Btrfs: Add backre...
409
  	btrfs_free_path(path);
4df27c4d5   Yan, Zheng   Btrfs: change how...
410
  	return 0;
0660b5af3   Chris Mason   Btrfs: Add backre...
411
  }
08fe4db17   Li Zefan   Btrfs: Fix uninit...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
  
  /*
   * Old btrfs forgets to init root_item->flags and root_item->byte_limit
   * for subvolumes. To work around this problem, we steal a bit from
   * root_item->inode_item->flags, and use it to indicate if those fields
   * have been properly initialized.
   */
  void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
  {
  	u64 inode_flags = le64_to_cpu(root_item->inode.flags);
  
  	if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
  		inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
  		root_item->inode.flags = cpu_to_le64(inode_flags);
  		root_item->flags = 0;
  		root_item->byte_limit = 0;
  	}
  }