Commit cb1b479d authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Fix quotas + snapshots

Now that we can reliably designate and find the master subvolume out of
a tree of snapshots, we can finally make quotas work with snapshots:

That is - quotas will now _ignore_ snapshot subvolumes, and only be in
effect for the master (non snapshot) subvolume.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 653693be
...@@ -333,6 +333,9 @@ static int bch2_quota_reservation_add(struct bch_fs *c, ...@@ -333,6 +333,9 @@ static int bch2_quota_reservation_add(struct bch_fs *c,
{ {
int ret; int ret;
if (test_bit(EI_INODE_SNAPSHOT, &inode->ei_flags))
return 0;
mutex_lock(&inode->ei_quota_lock); mutex_lock(&inode->ei_quota_lock);
ret = bch2_quota_acct(c, inode->ei_qid, Q_SPC, sectors, ret = bch2_quota_acct(c, inode->ei_qid, Q_SPC, sectors,
check_enospc ? KEY_TYPE_QUOTA_PREALLOC : KEY_TYPE_QUOTA_NOCHECK); check_enospc ? KEY_TYPE_QUOTA_PREALLOC : KEY_TYPE_QUOTA_NOCHECK);
...@@ -414,7 +417,9 @@ static void __i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode, ...@@ -414,7 +417,9 @@ static void __i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode,
inode->v.i_blocks += sectors; inode->v.i_blocks += sectors;
#ifdef CONFIG_BCACHEFS_QUOTA #ifdef CONFIG_BCACHEFS_QUOTA
if (quota_res && sectors > 0) { if (quota_res &&
!test_bit(EI_INODE_SNAPSHOT, &inode->ei_flags) &&
sectors > 0) {
BUG_ON(sectors > quota_res->sectors); BUG_ON(sectors > quota_res->sectors);
BUG_ON(sectors > inode->ei_quota_reserved); BUG_ON(sectors > inode->ei_quota_reserved);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "bcachefs.h" #include "bcachefs.h"
#include "btree_update.h" #include "btree_update.h"
#include "errcode.h" #include "errcode.h"
#include "error.h"
#include "inode.h" #include "inode.h"
#include "quota.h" #include "quota.h"
#include "subvolume.h" #include "subvolume.h"
...@@ -556,23 +557,25 @@ static int bch2_fs_quota_read_inode(struct btree_trans *trans, ...@@ -556,23 +557,25 @@ static int bch2_fs_quota_read_inode(struct btree_trans *trans,
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct bch_inode_unpacked u; struct bch_inode_unpacked u;
struct bch_subvolume subvolume; struct bch_snapshot_tree s_t;
int ret; int ret;
ret = bch2_snapshot_get_subvol(trans, k.k->p.snapshot, &subvolume); ret = bch2_snapshot_tree_lookup(trans,
snapshot_t(c, k.k->p.snapshot)->tree, &s_t);
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
"%s: snapshot tree %u not found", __func__,
snapshot_t(c, k.k->p.snapshot)->tree);
if (ret) if (ret)
return ret; return ret;
/* if (!s_t.master_subvol)
* We don't do quota accounting in snapshots:
*/
if (BCH_SUBVOLUME_SNAP(&subvolume))
goto advance;
if (!bkey_is_inode(k.k))
goto advance; goto advance;
ret = bch2_inode_unpack(k, &u); ret = bch2_inode_find_by_inum_trans(trans,
(subvol_inum) {
le32_to_cpu(s_t.master_subvol),
k.k->p.offset,
}, &u);
if (ret) if (ret)
return ret; return ret;
...@@ -581,7 +584,7 @@ static int bch2_fs_quota_read_inode(struct btree_trans *trans, ...@@ -581,7 +584,7 @@ static int bch2_fs_quota_read_inode(struct btree_trans *trans,
bch2_quota_acct(c, bch_qid(&u), Q_INO, 1, bch2_quota_acct(c, bch_qid(&u), Q_INO, 1,
KEY_TYPE_QUOTA_NOCHECK); KEY_TYPE_QUOTA_NOCHECK);
advance: advance:
bch2_btree_iter_set_pos(iter, POS(iter->pos.inode, iter->pos.offset + 1)); bch2_btree_iter_set_pos(iter, bpos_nosnap_successor(iter->pos));
return 0; return 0;
} }
......
...@@ -34,7 +34,7 @@ int bch2_snapshot_tree_invalid(const struct bch_fs *c, struct bkey_s_c k, ...@@ -34,7 +34,7 @@ int bch2_snapshot_tree_invalid(const struct bch_fs *c, struct bkey_s_c k,
return 0; return 0;
} }
static int snapshot_tree_lookup(struct btree_trans *trans, u32 id, int bch2_snapshot_tree_lookup(struct btree_trans *trans, u32 id,
struct bch_snapshot_tree *s) struct bch_snapshot_tree *s)
{ {
return bch2_bkey_get_val_typed(trans, BTREE_ID_snapshot_trees, POS(0, id), return bch2_bkey_get_val_typed(trans, BTREE_ID_snapshot_trees, POS(0, id),
...@@ -426,7 +426,7 @@ static int snapshot_tree_ptr_good(struct btree_trans *trans, ...@@ -426,7 +426,7 @@ static int snapshot_tree_ptr_good(struct btree_trans *trans,
u32 snap_id, u32 tree_id) u32 snap_id, u32 tree_id)
{ {
struct bch_snapshot_tree s_t; struct bch_snapshot_tree s_t;
int ret = snapshot_tree_lookup(trans, tree_id, &s_t); int ret = bch2_snapshot_tree_lookup(trans, tree_id, &s_t);
if (bch2_err_matches(ret, ENOENT)) if (bch2_err_matches(ret, ENOENT))
return 0; return 0;
...@@ -462,7 +462,7 @@ static int snapshot_tree_ptr_repair(struct btree_trans *trans, ...@@ -462,7 +462,7 @@ static int snapshot_tree_ptr_repair(struct btree_trans *trans,
tree_id = le32_to_cpu(root.v->tree); tree_id = le32_to_cpu(root.v->tree);
ret = snapshot_tree_lookup(trans, tree_id, &s_t); ret = bch2_snapshot_tree_lookup(trans, tree_id, &s_t);
if (ret && !bch2_err_matches(ret, ENOENT)) if (ret && !bch2_err_matches(ret, ENOENT))
return ret; return ret;
...@@ -659,7 +659,7 @@ static int check_subvol(struct btree_trans *trans, ...@@ -659,7 +659,7 @@ static int check_subvol(struct btree_trans *trans,
u32 snapshot_tree = snapshot_t(c, snapshot_root)->tree; u32 snapshot_tree = snapshot_t(c, snapshot_root)->tree;
struct bch_snapshot_tree st; struct bch_snapshot_tree st;
ret = snapshot_tree_lookup(trans, snapshot_tree, &st); ret = bch2_snapshot_tree_lookup(trans, snapshot_tree, &st);
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c, bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), c,
"%s: snapshot tree %u not found", __func__, snapshot_tree); "%s: snapshot tree %u not found", __func__, snapshot_tree);
......
...@@ -15,6 +15,8 @@ int bch2_snapshot_tree_invalid(const struct bch_fs *, struct bkey_s_c, ...@@ -15,6 +15,8 @@ int bch2_snapshot_tree_invalid(const struct bch_fs *, struct bkey_s_c,
.min_val_size = 8, \ .min_val_size = 8, \
}) })
int bch2_snapshot_tree_lookup(struct btree_trans *, u32, struct bch_snapshot_tree *);
void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); void bch2_snapshot_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
int bch2_snapshot_invalid(const struct bch_fs *, struct bkey_s_c, int bch2_snapshot_invalid(const struct bch_fs *, struct bkey_s_c,
unsigned, struct printbuf *); unsigned, struct printbuf *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment