* @goals: Head of quota tuning goals (&damos_quota_goal) list.
* @goal_tuner: Goal-based @esz tuning algorithm to use.
* @esz: Effective size quota in bytes.
+ * @fail_charge_num: Failed regions charge rate numerator.
+ * @fail_charge_denom: Failed regions charge rate denominator.
*
* @weight_sz: Weight of the region's size for prioritization.
* @weight_nr_accesses: Weight of the region's nr_accesses for prioritization.
*
* The resulting effective size quota in bytes is set to @esz.
*
+ * For DAMOS action applying failed amount of regions, charging those same to
+ * those that the action has successfully applied may be unfair. For the
+ * reason, 'the size * @fail_charge_num / @fail_charge_denom' is charged.
+ *
* For selecting regions within the quota, DAMON prioritizes current scheme's
* target memory regions using the &struct damon_operations->get_scheme_score.
* You could customize the prioritization logic by setting &weight_sz,
enum damos_quota_goal_tuner goal_tuner;
unsigned long esz;
+ unsigned int fail_charge_num;
+ unsigned int fail_charge_denom;
+
unsigned int weight_sz;
unsigned int weight_nr_accesses;
unsigned int weight_age;
if (err)
return err;
dst->goal_tuner = src->goal_tuner;
+ dst->fail_charge_num = src->fail_charge_num;
+ dst->fail_charge_denom = src->fail_charge_denom;
dst->weight_sz = src->weight_sz;
dst->weight_nr_accesses = src->weight_nr_accesses;
dst->weight_age = src->weight_age;
mutex_unlock(&ctx->walk_control_lock);
}
+static void damos_charge_quota(struct damos_quota *quota,
+ unsigned long sz_region, unsigned long sz_applied)
+{
+ /*
+ * sz_applied could be bigger than sz_region, depending on ops
+ * implementation of the action, e.g., damos_pa_pageout(). Charge only
+ * the region size in the case.
+ */
+ if (!quota->fail_charge_denom || sz_applied > sz_region)
+ quota->charged_sz += sz_region;
+ else
+ quota->charged_sz += sz_applied + mult_frac(
+ (sz_region - sz_applied),
+ quota->fail_charge_num,
+ quota->fail_charge_denom);
+}
+
static bool damos_quota_is_full(struct damos_quota *quota,
unsigned long min_region_sz)
{
ktime_get_coarse_ts64(&end);
quota->total_charged_ns += timespec64_to_ns(&end) -
timespec64_to_ns(&begin);
- quota->charged_sz += sz;
+ damos_charge_quota(quota, sz, sz_applied);
if (damos_quota_is_full(quota, c->min_region_sz)) {
quota->charge_target_from = t;
quota->charge_addr_from = r->ar.end;