Commit bd954215 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Quota fixes

 - We now correctly allow soft limits to be exceeded, instead of always
   returning -EDQUOT
 - Disk quota grate times/warnings can now be set, not just the
   systemwide defaults
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent d7e4e513
...@@ -605,7 +605,7 @@ static void bch2_page_reservation_put(struct bch_fs *c, ...@@ -605,7 +605,7 @@ static void bch2_page_reservation_put(struct bch_fs *c,
static int bch2_page_reservation_get(struct bch_fs *c, static int bch2_page_reservation_get(struct bch_fs *c,
struct bch_inode_info *inode, struct page *page, struct bch_inode_info *inode, struct page *page,
struct bch2_page_reservation *res, struct bch2_page_reservation *res,
unsigned offset, unsigned len, bool check_enospc) unsigned offset, unsigned len)
{ {
struct bch_page_state *s = bch2_page_state_create(page, 0); struct bch_page_state *s = bch2_page_state_create(page, 0);
unsigned i, disk_sectors = 0, quota_sectors = 0; unsigned i, disk_sectors = 0, quota_sectors = 0;
...@@ -625,19 +625,14 @@ static int bch2_page_reservation_get(struct bch_fs *c, ...@@ -625,19 +625,14 @@ static int bch2_page_reservation_get(struct bch_fs *c,
} }
if (disk_sectors) { if (disk_sectors) {
ret = bch2_disk_reservation_add(c, &res->disk, ret = bch2_disk_reservation_add(c, &res->disk, disk_sectors, 0);
disk_sectors,
!check_enospc
? BCH_DISK_RESERVATION_NOFAIL
: 0);
if (unlikely(ret)) if (unlikely(ret))
return ret; return ret;
} }
if (quota_sectors) { if (quota_sectors) {
ret = bch2_quota_reservation_add(c, inode, &res->quota, ret = bch2_quota_reservation_add(c, inode, &res->quota,
quota_sectors, quota_sectors, true);
check_enospc);
if (unlikely(ret)) { if (unlikely(ret)) {
struct disk_reservation tmp = { struct disk_reservation tmp = {
.sectors = disk_sectors .sectors = disk_sectors
...@@ -821,7 +816,7 @@ vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf) ...@@ -821,7 +816,7 @@ vm_fault_t bch2_page_mkwrite(struct vm_fault *vmf)
} }
} }
if (bch2_page_reservation_get(c, inode, page, &res, 0, len, true)) { if (bch2_page_reservation_get(c, inode, page, &res, 0, len)) {
unlock_page(page); unlock_page(page);
ret = VM_FAULT_SIGBUS; ret = VM_FAULT_SIGBUS;
goto out; goto out;
...@@ -1520,8 +1515,7 @@ int bch2_write_begin(struct file *file, struct address_space *mapping, ...@@ -1520,8 +1515,7 @@ int bch2_write_begin(struct file *file, struct address_space *mapping,
goto err; goto err;
} }
ret = bch2_page_reservation_get(c, inode, page, res, ret = bch2_page_reservation_get(c, inode, page, res, offset, len);
offset, len, true);
if (ret) { if (ret) {
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
/* /*
...@@ -1663,7 +1657,7 @@ static int __bch2_buffered_write(struct bch_inode_info *inode, ...@@ -1663,7 +1657,7 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
} }
ret = bch2_page_reservation_get(c, inode, page, &res, ret = bch2_page_reservation_get(c, inode, page, &res,
pg_offset, pg_len, true); pg_offset, pg_len);
if (ret) if (ret)
goto out; goto out;
......
...@@ -332,34 +332,20 @@ static int bch2_quota_check_limit(struct bch_fs *c, ...@@ -332,34 +332,20 @@ static int bch2_quota_check_limit(struct bch_fs *c,
if (qc->hardlimit && if (qc->hardlimit &&
qc->hardlimit < n && qc->hardlimit < n &&
!ignore_hardlimit(q)) { !ignore_hardlimit(q)) {
if (mode == KEY_TYPE_QUOTA_PREALLOC)
return -EDQUOT;
prepare_warning(qc, qtype, counter, msgs, HARDWARN); prepare_warning(qc, qtype, counter, msgs, HARDWARN);
return -EDQUOT;
} }
if (qc->softlimit && if (qc->softlimit &&
qc->softlimit < n && qc->softlimit < n) {
qc->timer && if (qc->timer == 0) {
ktime_get_real_seconds() >= qc->timer && qc->timer = ktime_get_real_seconds() + q->limits[counter].timelimit;
!ignore_hardlimit(q)) { prepare_warning(qc, qtype, counter, msgs, SOFTWARN);
if (mode == KEY_TYPE_QUOTA_PREALLOC) } else if (ktime_get_real_seconds() >= qc->timer &&
return -EDQUOT; !ignore_hardlimit(q)) {
prepare_warning(qc, qtype, counter, msgs, SOFTLONGWARN);
prepare_warning(qc, qtype, counter, msgs, SOFTLONGWARN);
}
if (qc->softlimit &&
qc->softlimit < n &&
qc->timer == 0) {
if (mode == KEY_TYPE_QUOTA_PREALLOC)
return -EDQUOT; return -EDQUOT;
}
prepare_warning(qc, qtype, counter, msgs, SOFTWARN);
/* XXX is this the right one? */
qc->timer = ktime_get_real_seconds() +
q->limits[counter].warnlimit;
} }
return 0; return 0;
...@@ -469,7 +455,8 @@ int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes, ...@@ -469,7 +455,8 @@ int bch2_quota_transfer(struct bch_fs *c, unsigned qtypes,
return ret; return ret;
} }
static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k) static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k,
struct qc_dqblk *qdq)
{ {
struct bkey_s_c_quota dq; struct bkey_s_c_quota dq;
struct bch_memquota_type *q; struct bch_memquota_type *q;
...@@ -498,6 +485,15 @@ static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k) ...@@ -498,6 +485,15 @@ static int __bch2_quota_set(struct bch_fs *c, struct bkey_s_c k)
mq->c[i].softlimit = le64_to_cpu(dq.v->c[i].softlimit); mq->c[i].softlimit = le64_to_cpu(dq.v->c[i].softlimit);
} }
if (qdq && qdq->d_fieldmask & QC_SPC_TIMER)
mq->c[Q_SPC].timer = cpu_to_le64(qdq->d_spc_timer);
if (qdq && qdq->d_fieldmask & QC_SPC_WARNS)
mq->c[Q_SPC].warns = cpu_to_le64(qdq->d_spc_warns);
if (qdq && qdq->d_fieldmask & QC_INO_TIMER)
mq->c[Q_INO].timer = cpu_to_le64(qdq->d_ino_timer);
if (qdq && qdq->d_fieldmask & QC_INO_WARNS)
mq->c[Q_INO].warns = cpu_to_le64(qdq->d_ino_warns);
mutex_unlock(&q->lock); mutex_unlock(&q->lock);
} }
...@@ -618,7 +614,7 @@ int bch2_fs_quota_read(struct bch_fs *c) ...@@ -618,7 +614,7 @@ int bch2_fs_quota_read(struct bch_fs *c)
ret = for_each_btree_key2(&trans, iter, BTREE_ID_quotas, ret = for_each_btree_key2(&trans, iter, BTREE_ID_quotas,
POS_MIN, BTREE_ITER_PREFETCH, k, POS_MIN, BTREE_ITER_PREFETCH, k,
__bch2_quota_set(c, k)) ?: __bch2_quota_set(c, k, NULL)) ?:
for_each_btree_key2(&trans, iter, BTREE_ID_inodes, for_each_btree_key2(&trans, iter, BTREE_ID_inodes,
POS_MIN, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, POS_MIN, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
bch2_fs_quota_read_inode(&trans, &iter, k)); bch2_fs_quota_read_inode(&trans, &iter, k));
...@@ -961,7 +957,7 @@ static int bch2_set_quota(struct super_block *sb, struct kqid qid, ...@@ -961,7 +957,7 @@ static int bch2_set_quota(struct super_block *sb, struct kqid qid,
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_set_quota_trans(&trans, &new_quota, qdq)) ?: bch2_set_quota_trans(&trans, &new_quota, qdq)) ?:
__bch2_quota_set(c, bkey_i_to_s_c(&new_quota.k_i)); __bch2_quota_set(c, bkey_i_to_s_c(&new_quota.k_i), qdq);
return ret; return ret;
} }
......
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