Commit 05335cff9f01555b769ac97b7bacc472b7ed047a

Authored by Kent Overstreet
1 parent 4fe6a81670

bcache: Fix a race when freeing btree nodes

This isn't a bulletproof fix; btree_node_free() -> bch_bucket_free() puts the
bucket on the unused freelist, where it can be reused right away without any
ordering requirements. It would be better to wait on at least a journal write to
go down before reusing the bucket. bch_btree_set_root() does this, and inserting
into non leaf nodes is completely synchronous so we should be ok, but future
patches are just going to get rid of the unused freelist - it was needed in the
past for various reasons but shouldn't be anymore.

Signed-off-by: Kent Overstreet <kmo@daterainc.com>

Showing 1 changed file with 20 additions and 33 deletions Side-by-side Diff

drivers/md/bcache/btree.c
... ... @@ -1006,8 +1006,6 @@
1006 1006  
1007 1007 static void btree_node_free(struct btree *b)
1008 1008 {
1009   - unsigned i;
1010   -
1011 1009 trace_bcache_btree_node_free(b);
1012 1010  
1013 1011 BUG_ON(b == b->c->root);
... ... @@ -1019,14 +1017,6 @@
1019 1017 cancel_delayed_work(&b->work);
1020 1018  
1021 1019 mutex_lock(&b->c->bucket_lock);
1022   -
1023   - for (i = 0; i < KEY_PTRS(&b->key); i++) {
1024   - BUG_ON(atomic_read(&PTR_BUCKET(b->c, &b->key, i)->pin));
1025   -
1026   - bch_inc_gen(PTR_CACHE(b->c, &b->key, i),
1027   - PTR_BUCKET(b->c, &b->key, i));
1028   - }
1029   -
1030 1020 bch_bucket_free(b->c, &b->key);
1031 1021 mca_bucket_free(b);
1032 1022 mutex_unlock(&b->c->bucket_lock);
1033 1023  
1034 1024  
... ... @@ -1086,16 +1076,19 @@
1086 1076 {
1087 1077 unsigned i;
1088 1078  
  1079 + mutex_lock(&b->c->bucket_lock);
  1080 +
  1081 + atomic_inc(&b->c->prio_blocked);
  1082 +
1089 1083 bkey_copy(k, &b->key);
1090 1084 bkey_copy_key(k, &ZERO_KEY);
1091 1085  
1092   - for (i = 0; i < KEY_PTRS(k); i++) {
1093   - uint8_t g = PTR_BUCKET(b->c, k, i)->gen + 1;
  1086 + for (i = 0; i < KEY_PTRS(k); i++)
  1087 + SET_PTR_GEN(k, i,
  1088 + bch_inc_gen(PTR_CACHE(b->c, &b->key, i),
  1089 + PTR_BUCKET(b->c, &b->key, i)));
1094 1090  
1095   - SET_PTR_GEN(k, i, g);
1096   - }
1097   -
1098   - atomic_inc(&b->c->prio_blocked);
  1091 + mutex_unlock(&b->c->bucket_lock);
1099 1092 }
1100 1093  
1101 1094 static int btree_check_reserve(struct btree *b, struct btree_op *op)
... ... @@ -1342,6 +1335,13 @@
1342 1335 bch_keylist_add(keylist, &new_nodes[i]->key);
1343 1336 }
1344 1337  
  1338 + closure_sync(&cl);
  1339 +
  1340 + /* We emptied out this node */
  1341 + BUG_ON(btree_bset_first(new_nodes[0])->keys);
  1342 + btree_node_free(new_nodes[0]);
  1343 + rw_unlock(true, new_nodes[0]);
  1344 +
1345 1345 for (i = 0; i < nodes; i++) {
1346 1346 if (__bch_keylist_realloc(keylist, bkey_u64s(&r[i].b->key)))
1347 1347 goto out_nocoalesce;
1348 1348  
... ... @@ -1350,13 +1350,9 @@
1350 1350 bch_keylist_push(keylist);
1351 1351 }
1352 1352  
1353   - /* We emptied out this node */
1354   - BUG_ON(btree_bset_first(new_nodes[0])->keys);
1355   - btree_node_free(new_nodes[0]);
1356   - rw_unlock(true, new_nodes[0]);
  1353 + bch_btree_insert_node(b, op, keylist, NULL, NULL);
  1354 + BUG_ON(!bch_keylist_empty(keylist));
1357 1355  
1358   - closure_sync(&cl);
1359   -
1360 1356 for (i = 0; i < nodes; i++) {
1361 1357 btree_node_free(r[i].b);
1362 1358 rw_unlock(true, r[i].b);
... ... @@ -1364,9 +1360,6 @@
1364 1360 r[i].b = new_nodes[i];
1365 1361 }
1366 1362  
1367   - bch_btree_insert_node(b, op, keylist, NULL, NULL);
1368   - BUG_ON(!bch_keylist_empty(keylist));
1369   -
1370 1363 memmove(r, r + 1, sizeof(r[0]) * (nodes - 1));
1371 1364 r[nodes - 1].b = ERR_PTR(-EINTR);
1372 1365  
1373 1366  
... ... @@ -1456,12 +1449,11 @@
1456 1449 keys.top);
1457 1450 bch_keylist_push(&keys);
1458 1451  
1459   - btree_node_free(last->b);
1460   -
1461 1452 bch_btree_insert_node(b, op, &keys,
1462 1453 NULL, NULL);
1463 1454 BUG_ON(!bch_keylist_empty(&keys));
1464 1455  
  1456 + btree_node_free(last->b);
1465 1457 rw_unlock(true, last->b);
1466 1458 last->b = n;
1467 1459  
1468 1460  
1469 1461  
1470 1462  
... ... @@ -1924,26 +1916,21 @@
1924 1916 closure_sync(&cl);
1925 1917 bch_btree_set_root(n3);
1926 1918 rw_unlock(true, n3);
1927   -
1928   - btree_node_free(b);
1929 1919 } else if (!b->parent) {
1930 1920 /* Root filled up but didn't need to be split */
1931 1921 closure_sync(&cl);
1932 1922 bch_btree_set_root(n1);
1933   -
1934   - btree_node_free(b);
1935 1923 } else {
1936 1924 /* Split a non root node */
1937 1925 closure_sync(&cl);
1938 1926 make_btree_freeing_key(b, parent_keys.top);
1939 1927 bch_keylist_push(&parent_keys);
1940 1928  
1941   - btree_node_free(b);
1942   -
1943 1929 bch_btree_insert_node(b->parent, op, &parent_keys, NULL, NULL);
1944 1930 BUG_ON(!bch_keylist_empty(&parent_keys));
1945 1931 }
1946 1932  
  1933 + btree_node_free(b);
1947 1934 rw_unlock(true, n1);
1948 1935  
1949 1936 bch_time_stats_update(&b->c->btree_split_time, start_time);