diff --git a/tests/src/parallel_restore.c b/tests/src/parallel_restore.c index b6c82657..49cf84ea 100644 --- a/tests/src/parallel_restore.c +++ b/tests/src/parallel_restore.c @@ -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"); diff --git a/utils/src/parallel_restore.c b/utils/src/parallel_restore.c index f1ce66ae..d322776f 100644 --- a/utils/src/parallel_restore.c +++ b/utils/src/parallel_restore.c @@ -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) diff --git a/utils/src/parallel_restore.h b/utils/src/parallel_restore.h index c49f3868..51fcf4b2 100644 --- a/utils/src/parallel_restore.h +++ b/utils/src/parallel_restore.h @@ -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);