Add Quota support

Adds a function to to insert quota rules as filesystem items.
This will then have an outward facing function that takes a
writer and a mirror of the _squota_rule struct in quota.c
and is called _parallel_restore_quota_rule. Adds testing
to make sure we are restoring a test quota.

Signed-off-by: Hunter Shaffer <hunter.shaffer@versity.com>
This commit is contained in:
Hunter Shaffer
2024-08-22 21:37:40 -04:00
committed by Auke Kok
parent c4147a7e8d
commit 2be15d416d
3 changed files with 101 additions and 1 deletions

View File

@@ -254,6 +254,33 @@ generate_entry(struct opts *opts, char *prefix, u64 nr, u64 dir_ino, u64 pos, u6
return entry;
}
/*
* since the _parallel_restore_quota_rule mimics the squota_rule found in the
* kernel we can also mimic its rule_to_irule function
*/
#define TEST_RULE_STR "7 13,L,- 15,L,- 17,L,- I 33 -"
static struct scoutfs_parallel_restore_quota_rule *
generate_quota(struct opts *opts)
{
struct scoutfs_parallel_restore_quota_rule *prule;
int err;
prule = calloc(1, sizeof(struct scoutfs_parallel_restore_quota_rule));
error_exit(!prule, "Quota rule alloc failed");
err = sscanf(TEST_RULE_STR, " %hhu %llu,%c,%c %llu,%c,%c %llu,%c,%c %c %llu %c",
&prule->prio,
&prule->names[0].val, &prule->names[0].source, &prule->names[0].flags,
&prule->names[1].val, &prule->names[1].source, &prule->names[1].flags,
&prule->names[2].val, &prule->names[2].source, &prule->names[2].flags,
&prule->op, &prule->limit, &prule->rule_flags);
error_exit(err != 13, "invalid quota rule, missing fields. nr fields: %d rule str: %s\n", err, TEST_RULE_STR);
return prule;
}
static u64 random64(void)
{
return ((u64)lrand48() << 32) | lrand48();
@@ -564,6 +591,7 @@ static int do_restore(struct opts *opts)
{
struct scoutfs_parallel_restore_writer *wri = NULL;
struct scoutfs_parallel_restore_slice *slices = NULL;
struct scoutfs_parallel_restore_quota_rule *rule = NULL;
struct scoutfs_super_block *super = NULL;
struct write_result res;
struct writer_args *args;
@@ -604,6 +632,11 @@ static int do_restore(struct opts *opts)
ret = scoutfs_parallel_restore_import_super(wri, super, dev_fd);
error_exit(ret, "import super %d", ret);
rule = generate_quota(opts);
ret = scoutfs_parallel_restore_add_quota_rule(wri, rule);
free(rule);
error_exit(ret, "add quotas %d", ret);
slices = calloc(1 + opts->nr_writers, sizeof(struct scoutfs_parallel_restore_slice));
error_exit(!slices, "alloc slices");

View File

@@ -405,7 +405,8 @@ static spr_err_t map_start_key(struct scoutfs_key *start, struct scoutfs_key *ke
init_key(start, SCOUTFS_INODE_INDEX_ZONE, 0, 0,
le64_to_cpu(key->_sk_second) & ~(u64)SCOUTFS_LOCK_SEQ_GROUP_MASK,
0, 0);
} else if (key->sk_zone == SCOUTFS_QUOTA_ZONE) {
init_key(start, SCOUTFS_QUOTA_ZONE, 0, 0, le64_to_cpu(key->_sk_second), 0, 0);
} else {
return EINVAL;
}
@@ -919,6 +920,46 @@ static spr_err_t insert_srch_item(struct scoutfs_parallel_restore_writer *wri,
return err;
}
static spr_err_t insert_quota_item(struct scoutfs_parallel_restore_writer *wri,
struct scoutfs_parallel_restore_quota_rule *rule)
{
struct scoutfs_quota_rule_val *rv;
struct btree_item *bti;
spr_err_t err;
err = bti_alloc(sizeof(struct scoutfs_quota_rule_val), &bti);
if (err)
goto out;
rv = bti->val;
memset(rv, 0, sizeof(struct scoutfs_quota_rule_val));
rv->limit = cpu_to_le64(rule->limit);
rv->prio = rule->prio;
rv->op = rule->op;
rv->rule_flags = rule->rule_flags;
rv->name_val[0] = cpu_to_le64(rule->names[0].val);
rv->name_source[0] = rule->names[0].source;
rv->name_flags[0] = rule->names[0].flags;
rv->name_val[1] = cpu_to_le64(rule->names[1].val);
rv->name_source[1] = rule->names[1].source;
rv->name_flags[1] = rule->names[1].flags;
rv->name_val[2] = cpu_to_le64(rule->names[2].val);
rv->name_source[2] = rule->names[2].source;
rv->name_flags[2] = rule->names[2].flags;
memset(&rv->_pad, 0, sizeof(rv->_pad));
init_key(&bti->key, SCOUTFS_QUOTA_ZONE, SCOUTFS_QUOTA_RULE_TYPE,
0, scoutfs_hash64(&rv, sizeof(rv)), 0, 0);
err = insert_fs_item(wri, bti);
if (err) {
free(bti);
goto out;
}
out:
return err;
}
#define UNLINKED_AVL_HEIGHT 255
static void link_avl_nodes(struct scoutfs_btree_block *bt, __le16 *parent, __le16 parent_off,
@@ -1765,6 +1806,15 @@ spr_err_t scoutfs_parallel_restore_add_progress(struct scoutfs_parallel_restore_
return err;
}
spr_err_t scoutfs_parallel_restore_add_quota_rule(struct scoutfs_parallel_restore_writer *wri,
struct scoutfs_parallel_restore_quota_rule *rule)
{
if (!wri_has_super(wri))
return EINVAL;
return insert_quota_item(wri, rule);
}
spr_err_t scoutfs_parallel_restore_write_buf(struct scoutfs_parallel_restore_writer *wri,
void *buf, size_t len, off_t *off_ret,
size_t *count_ret)

View File

@@ -68,6 +68,20 @@ struct scoutfs_parallel_restore_inode {
unsigned int target_len; /* not including null terminator */
};
struct scoutfs_parallel_restore_quota_rule {
u64 limit;
u8 prio;
u8 op;
u8 rule_flags;
struct quota_rule_name {
u64 val;
u8 source;
u8 flags;
} names [3];
char *value;
unsigned int value_len;
};
typedef __typeof__(EINVAL) spr_err_t;
struct scoutfs_parallel_restore_writer;
@@ -95,6 +109,9 @@ spr_err_t scoutfs_parallel_restore_get_progress(struct scoutfs_parallel_restore_
spr_err_t scoutfs_parallel_restore_add_progress(struct scoutfs_parallel_restore_writer *wri,
struct scoutfs_parallel_restore_progress *prog);
spr_err_t scoutfs_parallel_restore_add_quota_rule(struct scoutfs_parallel_restore_writer *wri,
struct scoutfs_parallel_restore_quota_rule *rule);
spr_err_t scoutfs_parallel_restore_write_buf(struct scoutfs_parallel_restore_writer *wri,
void *buf, size_t len, off_t *off_ret,
size_t *count_ret);