@@ -1368,6 +1368,7 @@ static void __del_reloc_root(struct btrfs_root *root)
1368
1368
struct rb_node * rb_node ;
1369
1369
struct mapping_node * node = NULL ;
1370
1370
struct reloc_control * rc = fs_info -> reloc_ctl ;
1371
+ bool put_ref = false;
1371
1372
1372
1373
if (rc && root -> node ) {
1373
1374
spin_lock (& rc -> reloc_root_tree .lock );
@@ -1383,9 +1384,22 @@ static void __del_reloc_root(struct btrfs_root *root)
1383
1384
BUG_ON ((struct btrfs_root * )node -> data != root );
1384
1385
}
1385
1386
1387
+ /*
1388
+ * We only put the reloc root here if it's on the list. There's a lot
1389
+ * of places where the pattern is to splice the rc->reloc_roots, process
1390
+ * the reloc roots, and then add the reloc root back onto
1391
+ * rc->reloc_roots. If we call __del_reloc_root while it's off of the
1392
+ * list we don't want the reference being dropped, because the guy
1393
+ * messing with the list is in charge of the reference.
1394
+ */
1386
1395
spin_lock (& fs_info -> trans_lock );
1387
- list_del_init (& root -> root_list );
1396
+ if (!list_empty (& root -> root_list )) {
1397
+ put_ref = true;
1398
+ list_del_init (& root -> root_list );
1399
+ }
1388
1400
spin_unlock (& fs_info -> trans_lock );
1401
+ if (put_ref )
1402
+ btrfs_put_root (root );
1389
1403
kfree (node );
1390
1404
}
1391
1405
@@ -1500,6 +1514,9 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
1500
1514
/*
1501
1515
* create reloc tree for a given fs tree. reloc tree is just a
1502
1516
* snapshot of the fs tree with special root objectid.
1517
+ *
1518
+ * The reloc_root comes out of here with two references, one for
1519
+ * root->reloc_root, and another for being on the rc->reloc_roots list.
1503
1520
*/
1504
1521
int btrfs_init_reloc_root (struct btrfs_trans_handle * trans ,
1505
1522
struct btrfs_root * root )
@@ -1539,7 +1556,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
1539
1556
1540
1557
ret = __add_reloc_root (reloc_root );
1541
1558
BUG_ON (ret < 0 );
1542
- root -> reloc_root = reloc_root ;
1559
+ root -> reloc_root = btrfs_grab_root ( reloc_root ) ;
1543
1560
return 0 ;
1544
1561
}
1545
1562
@@ -1560,6 +1577,13 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
1560
1577
reloc_root = root -> reloc_root ;
1561
1578
root_item = & reloc_root -> root_item ;
1562
1579
1580
+ /*
1581
+ * We are probably ok here, but __del_reloc_root() will drop its ref of
1582
+ * the root. We have the ref for root->reloc_root, but just in case
1583
+ * hold it while we update the reloc root.
1584
+ */
1585
+ btrfs_grab_root (reloc_root );
1586
+
1563
1587
/* root->reloc_root will stay until current relocation finished */
1564
1588
if (fs_info -> reloc_ctl -> merge_reloc_tree &&
1565
1589
btrfs_root_refs (root_item ) == 0 ) {
@@ -1581,7 +1605,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
1581
1605
ret = btrfs_update_root (trans , fs_info -> tree_root ,
1582
1606
& reloc_root -> root_key , root_item );
1583
1607
BUG_ON (ret );
1584
-
1608
+ btrfs_put_root ( reloc_root );
1585
1609
out :
1586
1610
return 0 ;
1587
1611
}
@@ -2281,18 +2305,28 @@ static int clean_dirty_subvols(struct reloc_control *rc)
2281
2305
*/
2282
2306
smp_wmb ();
2283
2307
clear_bit (BTRFS_ROOT_DEAD_RELOC_TREE , & root -> state );
2284
-
2285
2308
if (reloc_root ) {
2309
+ /*
2310
+ * btrfs_drop_snapshot drops our ref we hold for
2311
+ * ->reloc_root. If it fails however we must
2312
+ * drop the ref ourselves.
2313
+ */
2286
2314
ret2 = btrfs_drop_snapshot (reloc_root , 0 , 1 );
2287
- if (ret2 < 0 && !ret )
2288
- ret = ret2 ;
2315
+ if (ret2 < 0 ) {
2316
+ btrfs_put_root (reloc_root );
2317
+ if (!ret )
2318
+ ret = ret2 ;
2319
+ }
2289
2320
}
2290
2321
btrfs_put_root (root );
2291
2322
} else {
2292
2323
/* Orphan reloc tree, just clean it up */
2293
2324
ret2 = btrfs_drop_snapshot (root , 0 , 1 );
2294
- if (ret2 < 0 && !ret )
2295
- ret = ret2 ;
2325
+ if (ret2 < 0 ) {
2326
+ btrfs_put_root (root );
2327
+ if (!ret )
2328
+ ret = ret2 ;
2329
+ }
2296
2330
}
2297
2331
}
2298
2332
return ret ;
@@ -4510,7 +4544,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
4510
4544
4511
4545
err = __add_reloc_root (reloc_root );
4512
4546
BUG_ON (err < 0 ); /* -ENOMEM or logic error */
4513
- fs_root -> reloc_root = reloc_root ;
4547
+ fs_root -> reloc_root = btrfs_grab_root ( reloc_root ) ;
4514
4548
btrfs_put_root (fs_root );
4515
4549
}
4516
4550
@@ -4698,6 +4732,10 @@ void btrfs_reloc_pre_snapshot(struct btrfs_pending_snapshot *pending,
4698
4732
/*
4699
4733
* called after snapshot is created. migrate block reservation
4700
4734
* and create reloc root for the newly created snapshot
4735
+ *
4736
+ * This is similar to btrfs_init_reloc_root(), we come out of here with two
4737
+ * references held on the reloc_root, one for root->reloc_root and one for
4738
+ * rc->reloc_roots.
4701
4739
*/
4702
4740
int btrfs_reloc_post_snapshot (struct btrfs_trans_handle * trans ,
4703
4741
struct btrfs_pending_snapshot * pending )
@@ -4730,7 +4768,7 @@ int btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
4730
4768
4731
4769
ret = __add_reloc_root (reloc_root );
4732
4770
BUG_ON (ret < 0 );
4733
- new_root -> reloc_root = reloc_root ;
4771
+ new_root -> reloc_root = btrfs_grab_root ( reloc_root ) ;
4734
4772
4735
4773
if (rc -> create_reloc_tree )
4736
4774
ret = clone_backref_node (trans , rc , root , reloc_root );
0 commit comments