Commit 0f5254aa authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: bch2_fs_quota_transfer

improve quota transfer locking & make ei_qid usage more consistent
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent d42dd4ad
...@@ -108,21 +108,12 @@ static int bch2_set_projid(struct bch_fs *c, ...@@ -108,21 +108,12 @@ static int bch2_set_projid(struct bch_fs *c,
u32 projid) u32 projid)
{ {
struct bch_qid qid = inode->ei_qid; struct bch_qid qid = inode->ei_qid;
int ret;
if (projid == inode->ei_qid.q[QTYP_PRJ])
return 0;
qid.q[QTYP_PRJ] = projid; qid.q[QTYP_PRJ] = projid;
return bch2_quota_transfer(c, 1 << QTYP_PRJ, qid, inode->ei_qid, return bch2_fs_quota_transfer(c, inode, qid,
inode->v.i_blocks + 1 << QTYP_PRJ,
inode->ei_quota_reserved); KEY_TYPE_QUOTA_PREALLOC);
if (ret)
return ret;
inode->ei_qid.q[QTYP_PRJ] = projid;
return 0;
} }
static int fssetxattr_inode_update_fn(struct bch_inode_info *inode, static int fssetxattr_inode_update_fn(struct bch_inode_info *inode,
......
...@@ -170,7 +170,6 @@ void bch2_inode_update_after_write(struct bch_fs *c, ...@@ -170,7 +170,6 @@ void bch2_inode_update_after_write(struct bch_fs *c,
inode_set_ctime_to_ts(&inode->v, bch2_time_to_timespec(c, bi->bi_ctime)); inode_set_ctime_to_ts(&inode->v, bch2_time_to_timespec(c, bi->bi_ctime));
inode->ei_inode = *bi; inode->ei_inode = *bi;
inode->ei_qid = bch_qid(bi);
bch2_inode_flags_to_vfs(inode); bch2_inode_flags_to_vfs(inode);
} }
...@@ -248,6 +247,41 @@ int __must_check bch2_write_inode(struct bch_fs *c, ...@@ -248,6 +247,41 @@ int __must_check bch2_write_inode(struct bch_fs *c,
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
int bch2_fs_quota_transfer(struct bch_fs *c,
struct bch_inode_info *inode,
struct bch_qid new_qid,
unsigned qtypes,
enum quota_acct_mode mode)
{
unsigned i;
int ret;
qtypes &= enabled_qtypes(c);
for (i = 0; i < QTYP_NR; i++)
if (new_qid.q[i] == inode->ei_qid.q[i])
qtypes &= ~(1U << i);
if (!qtypes)
return 0;
mutex_lock(&inode->ei_quota_lock);
ret = bch2_quota_transfer(c, qtypes, new_qid,
inode->ei_qid,
inode->v.i_blocks +
inode->ei_quota_reserved,
mode);
if (!ret)
for (i = 0; i < QTYP_NR; i++)
if (qtypes & (1 << i))
inode->ei_qid.q[i] = new_qid.q[i];
mutex_unlock(&inode->ei_quota_lock);
return ret;
}
static struct inode *bch2_vfs_inode_get(struct bch_fs *c, u64 inum) static struct inode *bch2_vfs_inode_get(struct bch_fs *c, u64 inum)
{ {
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
...@@ -913,37 +947,27 @@ static int bch2_setattr_nonsize(struct mnt_idmap *idmap, ...@@ -913,37 +947,27 @@ static int bch2_setattr_nonsize(struct mnt_idmap *idmap,
struct iattr *iattr) struct iattr *iattr)
{ {
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_qid qid = inode->ei_qid; struct bch_qid qid;
struct btree_trans trans; struct btree_trans trans;
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
struct posix_acl *acl = NULL; struct posix_acl *acl = NULL;
struct inode_write_setattr s = { iattr, idmap }; struct inode_write_setattr s = { iattr, idmap };
unsigned qtypes = 0;
int ret; int ret;
mutex_lock(&inode->ei_update_lock); mutex_lock(&inode->ei_update_lock);
if (c->opts.usrquota && qid = inode->ei_qid;
(iattr->ia_valid & ATTR_UID) &&
!uid_eq(iattr->ia_uid, inode->v.i_uid)) { if (iattr->ia_valid & ATTR_UID)
qid.q[QTYP_USR] = from_kuid(i_user_ns(&inode->v), iattr->ia_uid), qid.q[QTYP_USR] = from_kuid(i_user_ns(&inode->v), iattr->ia_uid);
qtypes |= 1 << QTYP_USR;
}
if (c->opts.grpquota && if (iattr->ia_valid & ATTR_GID)
(iattr->ia_valid & ATTR_GID) &&
!gid_eq(iattr->ia_gid, inode->v.i_gid)) {
qid.q[QTYP_GRP] = from_kgid(i_user_ns(&inode->v), iattr->ia_gid); qid.q[QTYP_GRP] = from_kgid(i_user_ns(&inode->v), iattr->ia_gid);
qtypes |= 1 << QTYP_GRP;
}
if (qtypes) { ret = bch2_fs_quota_transfer(c, inode, qid, ~0,
ret = bch2_quota_transfer(c, qtypes, qid, inode->ei_qid, KEY_TYPE_QUOTA_PREALLOC);
inode->v.i_blocks + if (ret)
inode->ei_quota_reserved); goto err;
if (ret)
goto err;
}
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
retry: retry:
...@@ -1312,6 +1336,7 @@ static void bch2_vfs_inode_init(struct bch_fs *c, ...@@ -1312,6 +1336,7 @@ static void bch2_vfs_inode_init(struct bch_fs *c,
inode->ei_journal_seq = 0; inode->ei_journal_seq = 0;
inode->ei_quota_reserved = 0; inode->ei_quota_reserved = 0;
inode->ei_str_hash = bch2_hash_info_init(c, bi); inode->ei_str_hash = bch2_hash_info_init(c, bi);
inode->ei_qid = bch_qid(bi);
inode->v.i_mapping->a_ops = &bch_address_space_operations; inode->v.i_mapping->a_ops = &bch_address_space_operations;
......
...@@ -70,6 +70,12 @@ struct bch_inode_unpacked; ...@@ -70,6 +70,12 @@ struct bch_inode_unpacked;
#ifndef NO_BCACHEFS_FS #ifndef NO_BCACHEFS_FS
int bch2_fs_quota_transfer(struct bch_fs *,
struct bch_inode_info *,
struct bch_qid,
unsigned,
enum quota_acct_mode);
/* returns 0 if we want to do the update, or error is passed up */ /* returns 0 if we want to do the update, or error is passed up */
typedef int (*inode_set_fn)(struct bch_inode_info *, typedef int (*inode_set_fn)(struct bch_inode_info *,
struct bch_inode_unpacked *, void *); struct bch_inode_unpacked *, void *);
......
...@@ -270,7 +270,8 @@ static void __bch2_quota_transfer(struct bch_memquota *src_q, ...@@ -270,7 +270,8 @@ static void __bch2_quota_transfer(struct bch_memquota *src_q,
int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes, int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes,
struct bch_qid dst, struct bch_qid dst,
struct bch_qid src, u64 space) struct bch_qid src, u64 space,
enum quota_acct_mode mode)
{ {
struct bch_memquota_type *q; struct bch_memquota_type *q;
struct bch_memquota *src_q[3], *dst_q[3]; struct bch_memquota *src_q[3], *dst_q[3];
...@@ -296,13 +297,13 @@ int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes, ...@@ -296,13 +297,13 @@ int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes,
ret = bch2_quota_check_limit(c, i, dst_q[i], &msgs, Q_SPC, ret = bch2_quota_check_limit(c, i, dst_q[i], &msgs, Q_SPC,
dst_q[i]->c[Q_SPC].v + space, dst_q[i]->c[Q_SPC].v + space,
KEY_TYPE_QUOTA_PREALLOC); mode);
if (ret) if (ret)
goto err; goto err;
ret = bch2_quota_check_limit(c, i, dst_q[i], &msgs, Q_INO, ret = bch2_quota_check_limit(c, i, dst_q[i], &msgs, Q_INO,
dst_q[i]->c[Q_INO].v + 1, dst_q[i]->c[Q_INO].v + 1,
KEY_TYPE_QUOTA_PREALLOC); mode);
if (ret) if (ret)
goto err; goto err;
} }
......
...@@ -15,12 +15,6 @@ void bch2_quota_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c); ...@@ -15,12 +15,6 @@ void bch2_quota_to_text(struct printbuf *, struct bch_fs *, struct bkey_s_c);
.val_to_text = bch2_quota_to_text, \ .val_to_text = bch2_quota_to_text, \
} }
enum quota_acct_mode {
KEY_TYPE_QUOTA_PREALLOC,
KEY_TYPE_QUOTA_WARN,
KEY_TYPE_QUOTA_NOCHECK,
};
static inline struct bch_qid bch_qid(struct bch_inode_unpacked *u) static inline struct bch_qid bch_qid(struct bch_inode_unpacked *u)
{ {
return (struct bch_qid) { return (struct bch_qid) {
...@@ -43,7 +37,7 @@ int bch2_quota_acct(struct bch_fs *, struct bch_qid, enum quota_counters, ...@@ -43,7 +37,7 @@ int bch2_quota_acct(struct bch_fs *, struct bch_qid, enum quota_counters,
s64, enum quota_acct_mode); s64, enum quota_acct_mode);
int bch2_quota_transfer(struct bch_fs *, unsigned, struct bch_qid, int bch2_quota_transfer(struct bch_fs *, unsigned, struct bch_qid,
struct bch_qid, u64); struct bch_qid, u64, enum quota_acct_mode);
void bch2_fs_quota_exit(struct bch_fs *); void bch2_fs_quota_exit(struct bch_fs *);
void bch2_fs_quota_init(struct bch_fs *); void bch2_fs_quota_init(struct bch_fs *);
...@@ -62,7 +56,8 @@ static inline int bch2_quota_acct(struct bch_fs *c, struct bch_qid qid, ...@@ -62,7 +56,8 @@ static inline int bch2_quota_acct(struct bch_fs *c, struct bch_qid qid,
static inline int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes, static inline int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes,
struct bch_qid dst, struct bch_qid dst,
struct bch_qid src, u64 space) struct bch_qid src, u64 space,
enum quota_acct_mode mode)
{ {
return 0; return 0;
} }
......
...@@ -8,6 +8,12 @@ struct bch_qid { ...@@ -8,6 +8,12 @@ struct bch_qid {
u32 q[QTYP_NR]; u32 q[QTYP_NR];
}; };
enum quota_acct_mode {
KEY_TYPE_QUOTA_PREALLOC,
KEY_TYPE_QUOTA_WARN,
KEY_TYPE_QUOTA_NOCHECK,
};
struct memquota_counter { struct memquota_counter {
u64 v; u64 v;
u64 hardlimit; u64 hardlimit;
......
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