#include <fres_sa_scenario.h>
#include <stdbool.h>
#include <ul_log.h>
+#include <ul_logreg.h>
#include <stdio.h>
#include <math.h>
+
#include "res_disk.h"
+#include "diskbfq_th.h"
UL_LOG_CUST(ulogd_frm_diskbfq);
-ul_log_domain_t ulogd_fra_fwp = {UL_LOGL_DEB, "frm_diskbfq"};
+ul_log_domain_t ulogd_frm_diskbfq = {UL_LOGL_DEB, "frm_diskbfq"};
struct disk_data {
- long throughput;
+ double throughput;
int budget;
};
long int sum_weight = 0;
struct disk_data *data = priv;
- fres_sa_scenario_for_each_contract(scenario, c) {
+ fres_sa_scenario_for_each_no_cancel_contract(scenario, c) {
fres_block_basic *basic;
fres_block_resource *resource;
fres_block_disk_sched *disk_sched;
period = fosa_rel_time_to_nsec(basic->period);
budget = fosa_rel_time_to_nsec(basic->budget);
- printf("processing: id=%s, period=%ld ms, budget=%ld ms\n",
- id, period, budget);
+ ul_logmsg("processing: id=%s, period=%ld us, budget=%ld us\n",
+ id, period/1000, budget/1000);
if (c->contract == c->new) {
int ret;
ret = fres_contract_add_disk_sched(c->contract,
disk_sched);
if (ret) {
- fprintf(stderr,
- "Cannot add disk_sched block\n");
+ ul_logerr("Cannot add disk_sched block\n");
free(disk_sched);
return -1;
}
} else {
disk_sched = fres_contract_get_disk_sched(c->contract);
if (!disk_sched) {
- fprintf(stderr,
- "disk_sched is not present\n");
+ ul_logerr("disk_sched is not present\n");
return -1;
}
}
sum_weight += disk_sched->weight;
}
- printf("sum_weight=%ld, max_weight=%d\n",
- sum_weight,
- DISKBFQ_WEIGHT_MAX);
+ ul_logmsg("sum_weight=%ld, max_weight=%d\n",
+ sum_weight,
+ DISKBFQ_WEIGHT_MAX);
*schedulable = sum_weight < DISKBFQ_WEIGHT_MAX;
- printf("=>%s\n", (*schedulable) ? "schedulable" : "not schedulable");
+ ul_logmsg("=> %s\n", (*schedulable) ? "schedulable" : "not schedulable");
return 0;
}
static struct fres_res_manager frm = {
.res_type = FRSH_RT_DISK,
.res_id = 0,
+ .name = "Disk BFQ",
.admission_test = diskbfq_admtest,
.priv = &disk
};
int main(int argc, char *argv[])
{
+ forb_init_attr_t attr = { .orb_id = "org.frescor.frm.diskbfq" };
forb_orb orb;
FILE* fd;
- char disk_name[40];
+ int readers = 4;
+ char disk_dev[40] = {0}, *disk_name = disk_dev;
char path[128], scheduler[128];
- int opt, ret;
+ int i, opt, ret;
+
+ ul_logreg_domain(&ulogd_frm_diskbfq);
if (argc < 3) {
err_usage:
- fprintf(stderr, "Usage:\n %s -i disk_id -d disk_dev_name\n",
+ fprintf(stderr, "Usage:\n %s "
+ "-i disk_id -d disk_device [-n readers]\n",
argv[0]);
error(1, EINVAL, "frm_diskbfq");
}
- while ((opt = getopt(argc, argv, "i:d:")) != -1) {
+ while ((opt = getopt(argc, argv, "i:d:n:")) != -1) {
switch (opt) {
case 'i':
frm.res_id = atoi(optarg);
break;
case 'd':
- strncpy(disk_name,
- optarg, sizeof(disk_name));
+ strncpy(disk_dev,
+ optarg, sizeof(disk_dev));
+
+ for (i = strlen(disk_dev) - 1; i >= 0; i--) {
+ if (disk_dev[i] == '/') {
+ disk_name = disk_dev + i + 1;
+ break;
+ }
+ }
+ break;
+ case 'n':
+ readers = atoi(optarg);
break;
default:
goto err_usage;
}
}
- orb = forb_init(&argc, &argv, "frm_diskbfq");
+ if (!*disk_name)
+ error(1, 0, "Disk device not specified");
+
+ orb = forb_init(&argc, &argv, &attr);
if (!orb) error(1, errno, "forb_init");
/*
snprintf(path, 128,
SYSFS_BFQ_SCHED_PATH,
disk_name);
- if (!(fd = fopen(path, "rw")))
- error(1, errno, "frm_generic_run");
+ if (!(fd = fopen(path, "r+")))
+ error(1, errno, "fopen(%s)", path);
ret = fscanf(fd, "%128[^\n]", scheduler);
if (ret == 0 || ret == EOF)
- error(1, errno, "frm_generic_run");
+ error(1, errno, "fscanf: %s", path);
if (!strstr(scheduler, SYSFS_BFQ_NAME))
- error(1, errno, "frm_generic_run");
+ error(1, errno, "bfq not available in kernel");
- /*
+ /**
* Now check if BFQ is the default I/O scheduler
* for the specific disk and set it to so if not.
- */
+ **/
else if (!strstr(scheduler, "[" SYSFS_BFQ_NAME "]")) {
rewind(fd);
ret = fprintf(fd, SYSFS_BFQ_NAME);
if (ret && ret != EOF)
ret = fflush(fd);
if (ret == 0 || ret == EOF)
- error(1, errno, "frm_generic_run");
+ error(1, errno, "cannot activate bfq scheduler");
}
fclose(fd);
snprintf(path, sizeof(path),
SYSFS_BFQ_BUDGET_PATH,
disk_name);
- if (!(fd = fopen(path, "r")))
- error(1, errno, "frm_generic_run");
+ if (!(fd = fopen(path, "r+")))
+ error(1, errno, "fopen(%s)", path);
+
+ ret = fprintf(fd, "256");
+ if (ret == 0)
+ error(1, errno, "fprintf: %s", path);
+ rewind(fd);
ret = fscanf(fd, "%d", &disk.budget);
if (ret == 0 || ret == EOF)
- error(1, errno, "frm_generic_run");
+ error(1, errno, "fscanf: %s", path);
fclose(fd);
- /*
- * TODO:
- * run the benchmark to get the throughput.
- */
- disk.throughput = 100000;
+ /**
+ * Estimate the disk throughput in order to achieve
+ * effective weight assignement during runtime.
+ **/
+ printf("Throughput estimation...\n");
+ disk.throughput = estimate_throughput(disk_dev, readers);
+ if (disk.throughput < 0.0)
+ error(1, errno, "throughput estimation error");
fprintf(stdout, "disk name: %s\n"
"scheduler: %s\n"
- "disk aggregate throughput: %ld\n"
+ "disk aggregate throughput: %f KiB/s\n"
"scheduling budget: %d\n",
disk_name, SYSFS_BFQ_NAME, disk.throughput, disk.budget);
fres_block_register_disk_sched();
ret = frm_register_and_run(orb, &frm);
- if (ret) error(1, errno, "frm_generic_run");
+ if (ret) error(1, errno, "frm_register_and_run");
return 0;
}