+ should_have_subvol = BCH_SNAPSHOT_SUBVOL(s.v) &&
+ !BCH_SNAPSHOT_DELETED(s.v);
+
+ if (should_have_subvol) {
+ id = le32_to_cpu(s.v->subvol);
+ ret = bch2_subvolume_get(trans, id, 0, false, &subvol);
+ if (ret == -ENOENT)
+ bch_err(c, "snapshot points to nonexistent subvolume:\n %s",
+ (bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf));
+ if (ret)
+ goto err;
+
+ if (BCH_SNAPSHOT_SUBVOL(s.v) != (le32_to_cpu(subvol.snapshot) == s.k->p.offset)) {
+ bch_err(c, "snapshot node %llu has wrong BCH_SNAPSHOT_SUBVOL",
+ s.k->p.offset);
+ ret = -EINVAL;
+ goto err;
+ }
+ } else {
+ if (fsck_err_on(s.v->subvol, c, "snapshot should not point to subvol:\n %s",
+ (bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf))) {
+ struct bkey_i_snapshot *u = bch2_trans_kmalloc(trans, sizeof(*u));
+
+ ret = PTR_ERR_OR_ZERO(u);
+ if (ret)
+ goto err;
+
+ bkey_reassemble(&u->k_i, s.s_c);
+ u->v.subvol = 0;
+ ret = bch2_trans_update(trans, iter, &u->k_i, 0);
+ if (ret)
+ goto err;
+ }
+ }
+
+ if (BCH_SNAPSHOT_DELETED(s.v))
+ set_bit(BCH_FS_HAVE_DELETED_SNAPSHOTS, &c->flags);
+err:
+fsck_err:
+ printbuf_exit(&buf);
+ return ret;