subvolume.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include "bcachefs.h"
  3. #include "btree_key_cache.h"
  4. #include "btree_update.h"
  5. #include "errcode.h"
  6. #include "error.h"
  7. #include "fs.h"
  8. #include "snapshot.h"
  9. #include "subvolume.h"
  10. #include <linux/random.h>
  11. static int bch2_subvolume_delete(struct btree_trans *, u32);
  12. static struct bpos subvolume_children_pos(struct bkey_s_c k)
  13. {
  14. if (k.k->type != KEY_TYPE_subvolume)
  15. return POS_MIN;
  16. struct bkey_s_c_subvolume s = bkey_s_c_to_subvolume(k);
  17. if (!s.v->fs_path_parent)
  18. return POS_MIN;
  19. return POS(le32_to_cpu(s.v->fs_path_parent), s.k->p.offset);
  20. }
  21. static int check_subvol(struct btree_trans *trans,
  22. struct btree_iter *iter,
  23. struct bkey_s_c k)
  24. {
  25. struct bch_fs *c = trans->c;
  26. struct bkey_s_c_subvolume subvol;
  27. struct btree_iter subvol_children_iter = {};
  28. struct bch_snapshot snapshot;
  29. struct printbuf buf = PRINTBUF;
  30. unsigned snapid;
  31. int ret = 0;
  32. if (k.k->type != KEY_TYPE_subvolume)
  33. return 0;
  34. subvol = bkey_s_c_to_subvolume(k);
  35. snapid = le32_to_cpu(subvol.v->snapshot);
  36. ret = bch2_snapshot_lookup(trans, snapid, &snapshot);
  37. if (bch2_err_matches(ret, ENOENT))
  38. bch_err(c, "subvolume %llu points to nonexistent snapshot %u",
  39. k.k->p.offset, snapid);
  40. if (ret)
  41. return ret;
  42. if (BCH_SUBVOLUME_UNLINKED(subvol.v)) {
  43. ret = bch2_subvolume_delete(trans, iter->pos.offset);
  44. bch_err_msg(c, ret, "deleting subvolume %llu", iter->pos.offset);
  45. return ret ?: -BCH_ERR_transaction_restart_nested;
  46. }
  47. if (fsck_err_on(subvol.k->p.offset == BCACHEFS_ROOT_SUBVOL &&
  48. subvol.v->fs_path_parent,
  49. trans, subvol_root_fs_path_parent_nonzero,
  50. "root subvolume has nonzero fs_path_parent\n%s",
  51. (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
  52. struct bkey_i_subvolume *n =
  53. bch2_bkey_make_mut_typed(trans, iter, &subvol.s_c, 0, subvolume);
  54. ret = PTR_ERR_OR_ZERO(n);
  55. if (ret)
  56. goto err;
  57. n->v.fs_path_parent = 0;
  58. }
  59. if (subvol.v->fs_path_parent) {
  60. struct bpos pos = subvolume_children_pos(k);
  61. struct bkey_s_c subvol_children_k =
  62. bch2_bkey_get_iter(trans, &subvol_children_iter,
  63. BTREE_ID_subvolume_children, pos, 0);
  64. ret = bkey_err(subvol_children_k);
  65. if (ret)
  66. goto err;
  67. if (fsck_err_on(subvol_children_k.k->type != KEY_TYPE_set,
  68. trans, subvol_children_not_set,
  69. "subvolume not set in subvolume_children btree at %llu:%llu\n%s",
  70. pos.inode, pos.offset,
  71. (printbuf_reset(&buf),
  72. bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
  73. ret = bch2_btree_bit_mod(trans, BTREE_ID_subvolume_children, pos, true);
  74. if (ret)
  75. goto err;
  76. }
  77. }
  78. struct bch_inode_unpacked inode;
  79. ret = bch2_inode_find_by_inum_nowarn_trans(trans,
  80. (subvol_inum) { k.k->p.offset, le64_to_cpu(subvol.v->inode) },
  81. &inode);
  82. if (!ret) {
  83. if (fsck_err_on(inode.bi_subvol != subvol.k->p.offset,
  84. trans, subvol_root_wrong_bi_subvol,
  85. "subvol root %llu:%u has wrong bi_subvol field: got %u, should be %llu",
  86. inode.bi_inum, inode.bi_snapshot,
  87. inode.bi_subvol, subvol.k->p.offset)) {
  88. inode.bi_subvol = subvol.k->p.offset;
  89. inode.bi_snapshot = le32_to_cpu(subvol.v->snapshot);
  90. ret = __bch2_fsck_write_inode(trans, &inode);
  91. if (ret)
  92. goto err;
  93. }
  94. } else if (bch2_err_matches(ret, ENOENT)) {
  95. if (fsck_err(trans, subvol_to_missing_root,
  96. "subvolume %llu points to missing subvolume root %llu:%u",
  97. k.k->p.offset, le64_to_cpu(subvol.v->inode),
  98. le32_to_cpu(subvol.v->snapshot))) {
  99. ret = bch2_subvolume_delete(trans, iter->pos.offset);
  100. bch_err_msg(c, ret, "deleting subvolume %llu", iter->pos.offset);
  101. ret = ret ?: -BCH_ERR_transaction_restart_nested;
  102. goto err;
  103. }
  104. } else {
  105. goto err;
  106. }
  107. if (!BCH_SUBVOLUME_SNAP(subvol.v)) {
  108. u32 snapshot_root = bch2_snapshot_root(c, le32_to_cpu(subvol.v->snapshot));
  109. u32 snapshot_tree;
  110. struct bch_snapshot_tree st;
  111. rcu_read_lock();
  112. snapshot_tree = snapshot_t(c, snapshot_root)->tree;
  113. rcu_read_unlock();
  114. ret = bch2_snapshot_tree_lookup(trans, snapshot_tree, &st);
  115. bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
  116. "%s: snapshot tree %u not found", __func__, snapshot_tree);
  117. if (ret)
  118. goto err;
  119. if (fsck_err_on(le32_to_cpu(st.master_subvol) != subvol.k->p.offset,
  120. trans, subvol_not_master_and_not_snapshot,
  121. "subvolume %llu is not set as snapshot but is not master subvolume",
  122. k.k->p.offset)) {
  123. struct bkey_i_subvolume *s =
  124. bch2_bkey_make_mut_typed(trans, iter, &subvol.s_c, 0, subvolume);
  125. ret = PTR_ERR_OR_ZERO(s);
  126. if (ret)
  127. goto err;
  128. SET_BCH_SUBVOLUME_SNAP(&s->v, true);
  129. }
  130. }
  131. err:
  132. fsck_err:
  133. bch2_trans_iter_exit(trans, &subvol_children_iter);
  134. printbuf_exit(&buf);
  135. return ret;
  136. }
  137. int bch2_check_subvols(struct bch_fs *c)
  138. {
  139. int ret = bch2_trans_run(c,
  140. for_each_btree_key_commit(trans, iter,
  141. BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_prefetch, k,
  142. NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
  143. check_subvol(trans, &iter, k)));
  144. bch_err_fn(c, ret);
  145. return ret;
  146. }
  147. static int check_subvol_child(struct btree_trans *trans,
  148. struct btree_iter *child_iter,
  149. struct bkey_s_c child_k)
  150. {
  151. struct bch_subvolume s;
  152. int ret = bch2_bkey_get_val_typed(trans, BTREE_ID_subvolumes, POS(0, child_k.k->p.offset),
  153. 0, subvolume, &s);
  154. if (ret && !bch2_err_matches(ret, ENOENT))
  155. return ret;
  156. if (fsck_err_on(ret ||
  157. le32_to_cpu(s.fs_path_parent) != child_k.k->p.inode,
  158. trans, subvol_children_bad,
  159. "incorrect entry in subvolume_children btree %llu:%llu",
  160. child_k.k->p.inode, child_k.k->p.offset)) {
  161. ret = bch2_btree_delete_at(trans, child_iter, 0);
  162. if (ret)
  163. goto err;
  164. }
  165. err:
  166. fsck_err:
  167. return ret;
  168. }
  169. int bch2_check_subvol_children(struct bch_fs *c)
  170. {
  171. int ret = bch2_trans_run(c,
  172. for_each_btree_key_commit(trans, iter,
  173. BTREE_ID_subvolume_children, POS_MIN, BTREE_ITER_prefetch, k,
  174. NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
  175. check_subvol_child(trans, &iter, k)));
  176. bch_err_fn(c, ret);
  177. return 0;
  178. }
  179. /* Subvolumes: */
  180. int bch2_subvolume_validate(struct bch_fs *c, struct bkey_s_c k,
  181. enum bch_validate_flags flags)
  182. {
  183. struct bkey_s_c_subvolume subvol = bkey_s_c_to_subvolume(k);
  184. int ret = 0;
  185. bkey_fsck_err_on(bkey_lt(k.k->p, SUBVOL_POS_MIN) ||
  186. bkey_gt(k.k->p, SUBVOL_POS_MAX),
  187. c, subvol_pos_bad,
  188. "invalid pos");
  189. bkey_fsck_err_on(!subvol.v->snapshot,
  190. c, subvol_snapshot_bad,
  191. "invalid snapshot");
  192. bkey_fsck_err_on(!subvol.v->inode,
  193. c, subvol_inode_bad,
  194. "invalid inode");
  195. fsck_err:
  196. return ret;
  197. }
  198. void bch2_subvolume_to_text(struct printbuf *out, struct bch_fs *c,
  199. struct bkey_s_c k)
  200. {
  201. struct bkey_s_c_subvolume s = bkey_s_c_to_subvolume(k);
  202. prt_printf(out, "root %llu snapshot id %u",
  203. le64_to_cpu(s.v->inode),
  204. le32_to_cpu(s.v->snapshot));
  205. if (bkey_val_bytes(s.k) > offsetof(struct bch_subvolume, creation_parent)) {
  206. prt_printf(out, " creation_parent %u", le32_to_cpu(s.v->creation_parent));
  207. prt_printf(out, " fs_parent %u", le32_to_cpu(s.v->fs_path_parent));
  208. }
  209. }
  210. static int subvolume_children_mod(struct btree_trans *trans, struct bpos pos, bool set)
  211. {
  212. return !bpos_eq(pos, POS_MIN)
  213. ? bch2_btree_bit_mod(trans, BTREE_ID_subvolume_children, pos, set)
  214. : 0;
  215. }
  216. int bch2_subvolume_trigger(struct btree_trans *trans,
  217. enum btree_id btree_id, unsigned level,
  218. struct bkey_s_c old, struct bkey_s new,
  219. enum btree_iter_update_trigger_flags flags)
  220. {
  221. if (flags & BTREE_TRIGGER_transactional) {
  222. struct bpos children_pos_old = subvolume_children_pos(old);
  223. struct bpos children_pos_new = subvolume_children_pos(new.s_c);
  224. if (!bpos_eq(children_pos_old, children_pos_new)) {
  225. int ret = subvolume_children_mod(trans, children_pos_old, false) ?:
  226. subvolume_children_mod(trans, children_pos_new, true);
  227. if (ret)
  228. return ret;
  229. }
  230. }
  231. return 0;
  232. }
  233. int bch2_subvol_has_children(struct btree_trans *trans, u32 subvol)
  234. {
  235. struct btree_iter iter;
  236. bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolume_children, POS(subvol, 0), 0);
  237. struct bkey_s_c k = bch2_btree_iter_peek(&iter);
  238. bch2_trans_iter_exit(trans, &iter);
  239. return bkey_err(k) ?: k.k && k.k->p.inode == subvol
  240. ? -BCH_ERR_ENOTEMPTY_subvol_not_empty
  241. : 0;
  242. }
  243. static __always_inline int
  244. bch2_subvolume_get_inlined(struct btree_trans *trans, unsigned subvol,
  245. bool inconsistent_if_not_found,
  246. int iter_flags,
  247. struct bch_subvolume *s)
  248. {
  249. int ret = bch2_bkey_get_val_typed(trans, BTREE_ID_subvolumes, POS(0, subvol),
  250. iter_flags, subvolume, s);
  251. bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT) &&
  252. inconsistent_if_not_found,
  253. trans->c, "missing subvolume %u", subvol);
  254. return ret;
  255. }
  256. int bch2_subvolume_get(struct btree_trans *trans, unsigned subvol,
  257. bool inconsistent_if_not_found,
  258. int iter_flags,
  259. struct bch_subvolume *s)
  260. {
  261. return bch2_subvolume_get_inlined(trans, subvol, inconsistent_if_not_found, iter_flags, s);
  262. }
  263. int bch2_subvol_is_ro_trans(struct btree_trans *trans, u32 subvol)
  264. {
  265. struct bch_subvolume s;
  266. int ret = bch2_subvolume_get_inlined(trans, subvol, true, 0, &s);
  267. if (ret)
  268. return ret;
  269. if (BCH_SUBVOLUME_RO(&s))
  270. return -EROFS;
  271. return 0;
  272. }
  273. int bch2_subvol_is_ro(struct bch_fs *c, u32 subvol)
  274. {
  275. return bch2_trans_do(c, bch2_subvol_is_ro_trans(trans, subvol));
  276. }
  277. int bch2_snapshot_get_subvol(struct btree_trans *trans, u32 snapshot,
  278. struct bch_subvolume *subvol)
  279. {
  280. struct bch_snapshot snap;
  281. return bch2_snapshot_lookup(trans, snapshot, &snap) ?:
  282. bch2_subvolume_get(trans, le32_to_cpu(snap.subvol), true, 0, subvol);
  283. }
  284. int __bch2_subvolume_get_snapshot(struct btree_trans *trans, u32 subvolid,
  285. u32 *snapid, bool warn)
  286. {
  287. struct btree_iter iter;
  288. struct bkey_s_c_subvolume subvol;
  289. int ret;
  290. subvol = bch2_bkey_get_iter_typed(trans, &iter,
  291. BTREE_ID_subvolumes, POS(0, subvolid),
  292. BTREE_ITER_cached|BTREE_ITER_with_updates,
  293. subvolume);
  294. ret = bkey_err(subvol);
  295. bch2_fs_inconsistent_on(warn && bch2_err_matches(ret, ENOENT), trans->c,
  296. "missing subvolume %u", subvolid);
  297. if (likely(!ret))
  298. *snapid = le32_to_cpu(subvol.v->snapshot);
  299. bch2_trans_iter_exit(trans, &iter);
  300. return ret;
  301. }
  302. int bch2_subvolume_get_snapshot(struct btree_trans *trans, u32 subvolid,
  303. u32 *snapid)
  304. {
  305. return __bch2_subvolume_get_snapshot(trans, subvolid, snapid, true);
  306. }
  307. static int bch2_subvolume_reparent(struct btree_trans *trans,
  308. struct btree_iter *iter,
  309. struct bkey_s_c k,
  310. u32 old_parent, u32 new_parent)
  311. {
  312. struct bkey_i_subvolume *s;
  313. int ret;
  314. if (k.k->type != KEY_TYPE_subvolume)
  315. return 0;
  316. if (bkey_val_bytes(k.k) > offsetof(struct bch_subvolume, creation_parent) &&
  317. le32_to_cpu(bkey_s_c_to_subvolume(k).v->creation_parent) != old_parent)
  318. return 0;
  319. s = bch2_bkey_make_mut_typed(trans, iter, &k, 0, subvolume);
  320. ret = PTR_ERR_OR_ZERO(s);
  321. if (ret)
  322. return ret;
  323. s->v.creation_parent = cpu_to_le32(new_parent);
  324. return 0;
  325. }
  326. /*
  327. * Separate from the snapshot tree in the snapshots btree, we record the tree
  328. * structure of how snapshot subvolumes were created - the parent subvolume of
  329. * each snapshot subvolume.
  330. *
  331. * When a subvolume is deleted, we scan for child subvolumes and reparant them,
  332. * to avoid dangling references:
  333. */
  334. static int bch2_subvolumes_reparent(struct btree_trans *trans, u32 subvolid_to_delete)
  335. {
  336. struct bch_subvolume s;
  337. return lockrestart_do(trans,
  338. bch2_subvolume_get(trans, subvolid_to_delete, true,
  339. BTREE_ITER_cached, &s)) ?:
  340. for_each_btree_key_commit(trans, iter,
  341. BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_prefetch, k,
  342. NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
  343. bch2_subvolume_reparent(trans, &iter, k,
  344. subvolid_to_delete, le32_to_cpu(s.creation_parent)));
  345. }
  346. /*
  347. * Delete subvolume, mark snapshot ID as deleted, queue up snapshot
  348. * deletion/cleanup:
  349. */
  350. static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
  351. {
  352. struct btree_iter iter;
  353. struct bkey_s_c_subvolume subvol;
  354. u32 snapid;
  355. int ret = 0;
  356. subvol = bch2_bkey_get_iter_typed(trans, &iter,
  357. BTREE_ID_subvolumes, POS(0, subvolid),
  358. BTREE_ITER_cached|BTREE_ITER_intent,
  359. subvolume);
  360. ret = bkey_err(subvol);
  361. bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
  362. "missing subvolume %u", subvolid);
  363. if (ret)
  364. return ret;
  365. snapid = le32_to_cpu(subvol.v->snapshot);
  366. ret = bch2_btree_delete_at(trans, &iter, 0) ?:
  367. bch2_snapshot_node_set_deleted(trans, snapid);
  368. bch2_trans_iter_exit(trans, &iter);
  369. return ret;
  370. }
  371. static int bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid)
  372. {
  373. return bch2_subvolumes_reparent(trans, subvolid) ?:
  374. commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
  375. __bch2_subvolume_delete(trans, subvolid));
  376. }
  377. static void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *work)
  378. {
  379. struct bch_fs *c = container_of(work, struct bch_fs,
  380. snapshot_wait_for_pagecache_and_delete_work);
  381. snapshot_id_list s;
  382. u32 *id;
  383. int ret = 0;
  384. while (!ret) {
  385. mutex_lock(&c->snapshots_unlinked_lock);
  386. s = c->snapshots_unlinked;
  387. darray_init(&c->snapshots_unlinked);
  388. mutex_unlock(&c->snapshots_unlinked_lock);
  389. if (!s.nr)
  390. break;
  391. bch2_evict_subvolume_inodes(c, &s);
  392. for (id = s.data; id < s.data + s.nr; id++) {
  393. ret = bch2_trans_run(c, bch2_subvolume_delete(trans, *id));
  394. bch_err_msg(c, ret, "deleting subvolume %u", *id);
  395. if (ret)
  396. break;
  397. }
  398. darray_exit(&s);
  399. }
  400. bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
  401. }
  402. struct subvolume_unlink_hook {
  403. struct btree_trans_commit_hook h;
  404. u32 subvol;
  405. };
  406. static int bch2_subvolume_wait_for_pagecache_and_delete_hook(struct btree_trans *trans,
  407. struct btree_trans_commit_hook *_h)
  408. {
  409. struct subvolume_unlink_hook *h = container_of(_h, struct subvolume_unlink_hook, h);
  410. struct bch_fs *c = trans->c;
  411. int ret = 0;
  412. mutex_lock(&c->snapshots_unlinked_lock);
  413. if (!snapshot_list_has_id(&c->snapshots_unlinked, h->subvol))
  414. ret = snapshot_list_add(c, &c->snapshots_unlinked, h->subvol);
  415. mutex_unlock(&c->snapshots_unlinked_lock);
  416. if (ret)
  417. return ret;
  418. if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_snapshot_delete_pagecache))
  419. return -EROFS;
  420. if (!queue_work(c->write_ref_wq, &c->snapshot_wait_for_pagecache_and_delete_work))
  421. bch2_write_ref_put(c, BCH_WRITE_REF_snapshot_delete_pagecache);
  422. return 0;
  423. }
  424. int bch2_subvolume_unlink(struct btree_trans *trans, u32 subvolid)
  425. {
  426. struct btree_iter iter;
  427. struct bkey_i_subvolume *n;
  428. struct subvolume_unlink_hook *h;
  429. int ret = 0;
  430. h = bch2_trans_kmalloc(trans, sizeof(*h));
  431. ret = PTR_ERR_OR_ZERO(h);
  432. if (ret)
  433. return ret;
  434. h->h.fn = bch2_subvolume_wait_for_pagecache_and_delete_hook;
  435. h->subvol = subvolid;
  436. bch2_trans_commit_hook(trans, &h->h);
  437. n = bch2_bkey_get_mut_typed(trans, &iter,
  438. BTREE_ID_subvolumes, POS(0, subvolid),
  439. BTREE_ITER_cached, subvolume);
  440. ret = PTR_ERR_OR_ZERO(n);
  441. if (unlikely(ret)) {
  442. bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c,
  443. "missing subvolume %u", subvolid);
  444. return ret;
  445. }
  446. SET_BCH_SUBVOLUME_UNLINKED(&n->v, true);
  447. bch2_trans_iter_exit(trans, &iter);
  448. return ret;
  449. }
  450. int bch2_subvolume_create(struct btree_trans *trans, u64 inode,
  451. u32 parent_subvolid,
  452. u32 src_subvolid,
  453. u32 *new_subvolid,
  454. u32 *new_snapshotid,
  455. bool ro)
  456. {
  457. struct bch_fs *c = trans->c;
  458. struct btree_iter dst_iter, src_iter = (struct btree_iter) { NULL };
  459. struct bkey_i_subvolume *new_subvol = NULL;
  460. struct bkey_i_subvolume *src_subvol = NULL;
  461. u32 parent = 0, new_nodes[2], snapshot_subvols[2];
  462. int ret = 0;
  463. ret = bch2_bkey_get_empty_slot(trans, &dst_iter,
  464. BTREE_ID_subvolumes, POS(0, U32_MAX));
  465. if (ret == -BCH_ERR_ENOSPC_btree_slot)
  466. ret = -BCH_ERR_ENOSPC_subvolume_create;
  467. if (ret)
  468. return ret;
  469. snapshot_subvols[0] = dst_iter.pos.offset;
  470. snapshot_subvols[1] = src_subvolid;
  471. if (src_subvolid) {
  472. /* Creating a snapshot: */
  473. src_subvol = bch2_bkey_get_mut_typed(trans, &src_iter,
  474. BTREE_ID_subvolumes, POS(0, src_subvolid),
  475. BTREE_ITER_cached, subvolume);
  476. ret = PTR_ERR_OR_ZERO(src_subvol);
  477. if (unlikely(ret)) {
  478. bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
  479. "subvolume %u not found", src_subvolid);
  480. goto err;
  481. }
  482. parent = le32_to_cpu(src_subvol->v.snapshot);
  483. }
  484. ret = bch2_snapshot_node_create(trans, parent, new_nodes,
  485. snapshot_subvols,
  486. src_subvolid ? 2 : 1);
  487. if (ret)
  488. goto err;
  489. if (src_subvolid) {
  490. src_subvol->v.snapshot = cpu_to_le32(new_nodes[1]);
  491. ret = bch2_trans_update(trans, &src_iter, &src_subvol->k_i, 0);
  492. if (ret)
  493. goto err;
  494. }
  495. new_subvol = bch2_bkey_alloc(trans, &dst_iter, 0, subvolume);
  496. ret = PTR_ERR_OR_ZERO(new_subvol);
  497. if (ret)
  498. goto err;
  499. new_subvol->v.flags = 0;
  500. new_subvol->v.snapshot = cpu_to_le32(new_nodes[0]);
  501. new_subvol->v.inode = cpu_to_le64(inode);
  502. new_subvol->v.creation_parent = cpu_to_le32(src_subvolid);
  503. new_subvol->v.fs_path_parent = cpu_to_le32(parent_subvolid);
  504. new_subvol->v.otime.lo = cpu_to_le64(bch2_current_time(c));
  505. new_subvol->v.otime.hi = 0;
  506. SET_BCH_SUBVOLUME_RO(&new_subvol->v, ro);
  507. SET_BCH_SUBVOLUME_SNAP(&new_subvol->v, src_subvolid != 0);
  508. *new_subvolid = new_subvol->k.p.offset;
  509. *new_snapshotid = new_nodes[0];
  510. err:
  511. bch2_trans_iter_exit(trans, &src_iter);
  512. bch2_trans_iter_exit(trans, &dst_iter);
  513. return ret;
  514. }
  515. int bch2_initialize_subvolumes(struct bch_fs *c)
  516. {
  517. struct bkey_i_snapshot_tree root_tree;
  518. struct bkey_i_snapshot root_snapshot;
  519. struct bkey_i_subvolume root_volume;
  520. int ret;
  521. bkey_snapshot_tree_init(&root_tree.k_i);
  522. root_tree.k.p.offset = 1;
  523. root_tree.v.master_subvol = cpu_to_le32(1);
  524. root_tree.v.root_snapshot = cpu_to_le32(U32_MAX);
  525. bkey_snapshot_init(&root_snapshot.k_i);
  526. root_snapshot.k.p.offset = U32_MAX;
  527. root_snapshot.v.flags = 0;
  528. root_snapshot.v.parent = 0;
  529. root_snapshot.v.subvol = cpu_to_le32(BCACHEFS_ROOT_SUBVOL);
  530. root_snapshot.v.tree = cpu_to_le32(1);
  531. SET_BCH_SNAPSHOT_SUBVOL(&root_snapshot.v, true);
  532. bkey_subvolume_init(&root_volume.k_i);
  533. root_volume.k.p.offset = BCACHEFS_ROOT_SUBVOL;
  534. root_volume.v.flags = 0;
  535. root_volume.v.snapshot = cpu_to_le32(U32_MAX);
  536. root_volume.v.inode = cpu_to_le64(BCACHEFS_ROOT_INO);
  537. ret = bch2_btree_insert(c, BTREE_ID_snapshot_trees, &root_tree.k_i, NULL, 0, 0) ?:
  538. bch2_btree_insert(c, BTREE_ID_snapshots, &root_snapshot.k_i, NULL, 0, 0) ?:
  539. bch2_btree_insert(c, BTREE_ID_subvolumes, &root_volume.k_i, NULL, 0, 0);
  540. bch_err_fn(c, ret);
  541. return ret;
  542. }
  543. static int __bch2_fs_upgrade_for_subvolumes(struct btree_trans *trans)
  544. {
  545. struct btree_iter iter;
  546. struct bkey_s_c k;
  547. struct bch_inode_unpacked inode;
  548. int ret;
  549. k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
  550. SPOS(0, BCACHEFS_ROOT_INO, U32_MAX), 0);
  551. ret = bkey_err(k);
  552. if (ret)
  553. return ret;
  554. if (!bkey_is_inode(k.k)) {
  555. bch_err(trans->c, "root inode not found");
  556. ret = -BCH_ERR_ENOENT_inode;
  557. goto err;
  558. }
  559. ret = bch2_inode_unpack(k, &inode);
  560. BUG_ON(ret);
  561. inode.bi_subvol = BCACHEFS_ROOT_SUBVOL;
  562. ret = bch2_inode_write(trans, &iter, &inode);
  563. err:
  564. bch2_trans_iter_exit(trans, &iter);
  565. return ret;
  566. }
  567. /* set bi_subvol on root inode */
  568. int bch2_fs_upgrade_for_subvolumes(struct bch_fs *c)
  569. {
  570. int ret = bch2_trans_commit_do(c, NULL, NULL, BCH_TRANS_COMMIT_lazy_rw,
  571. __bch2_fs_upgrade_for_subvolumes(trans));
  572. bch_err_fn(c, ret);
  573. return ret;
  574. }
  575. int bch2_fs_subvolumes_init(struct bch_fs *c)
  576. {
  577. INIT_WORK(&c->snapshot_delete_work, bch2_delete_dead_snapshots_work);
  578. INIT_WORK(&c->snapshot_wait_for_pagecache_and_delete_work,
  579. bch2_subvolume_wait_for_pagecache_and_delete);
  580. mutex_init(&c->snapshots_unlinked_lock);
  581. return 0;
  582. }