00001
00016 #include <linux/aquosa/rres_config.h>
00017 #include "qres_config.h"
00018 #define QOS_DEBUG_LEVEL QRES_MOD_DEBUG_LEVEL
00019 #include <linux/aquosa/qos_debug.h>
00020 #include <linux/posix-timers.h>
00021 #include <linux/time.h>
00022
00023 #ifdef QRES_MOD_PROFILE
00024 # define QOS_PROFILE
00025 #endif
00026 #include <linux/aquosa/qos_prof.h>
00027
00028 #include "qres_gw_ks.h"
00029 #include "qsup_gw_ks.h"
00030 #include "qres_kpi_protected.h"
00031
00032 #include <linux/aquosa/qos_types.h>
00033 #include <linux/aquosa/qos_memory.h>
00034 #include <linux/aquosa/qos_func.h>
00035 #include <linux/aquosa/rres.h>
00036 #include <linux/aquosa/kal_sched.h>
00037
00039 qos_rv qres_init(void) {
00040
00041 if (offsetof(qres_server_t, rres) != 0) {
00042 qos_log_crit("Please, ensure qres_server_t.rres field has a null offset");
00043 return QOS_E_INTERNAL_ERROR;
00044 }
00045 return QOS_OK;
00046 }
00047
00049 qos_rv qres_cleanup(void) {
00050 server_t *srv;
00051 struct list_head *tmp, *tmpdel;
00052
00053 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00054
00055
00056 for_each_server_safe(srv, tmp, tmpdel) {
00057 qos_log_debug("Destroying sever %d ", srv->id);
00058
00059 qos_chk_ok_ret(qres_destroy_server(qres_find_by_rres(srv)));
00060 srv = NULL;
00061 }
00062 return QOS_OK;
00063 }
00064
00077 static qos_bool_t authorize_for_task(struct task_struct *tsk) {
00078 return (kal_task_get_uid(kal_task_current()) == 0) ||
00079 (kal_task_get_uid(kal_task_current()) == kal_task_get_uid(tsk));
00080 }
00081
00086 static qos_bool_t authorize_for_server(qres_server_t *qres) {
00087 return (kal_task_get_uid(kal_task_current()) == 0) ||
00088 (kal_task_get_uid(kal_task_current()) == qres_get_owner_uid(qres));
00089 }
00090
00092 qos_func_define(qos_rv, qres_create_server, qres_params_t *param, qres_sid_t *p_sid) {
00093 qres_server_t *qres;
00094 qos_rv rv;
00095
00096 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00097 qos_log_debug("q=" QRES_TIME_FMT ", q_min=" QRES_TIME_FMT ", p=" QRES_TIME_FMT ", flags=%d",
00098 param->Q, param->Q_min, param->P, param->flags);
00099 qres = qos_create(qres_server_t);
00100 qos_chk_rv(qres != NULL, QOS_E_NO_MEMORY);
00101 rv = qres_init_server(qres, param);
00102 if (rv != QOS_OK) {
00103 qos_free(qres);
00104 qos_log_info("qres_init_server failed: %s", qos_strerror(rv));
00105 return rv;
00106 }
00107 *p_sid = rres_get_sid(&qres->rres);
00108 return QOS_OK;
00109 }
00110
00111
00112 void qres_update_bandwidths(void) {
00113 struct list_head *tmp;
00114 server_t *srv;
00115 for_each_server(srv, tmp) {
00116 qres_time_t q = bw2Q(rres_get_bandwidth(srv), rres_get_period(srv));
00117 rres_set_budget(srv, q);
00118 }
00119 }
00120
00122 qos_func_define(qos_rv, qres_init_server, qres_server_t *qres, qres_params_t *param) {
00123 qos_rv rv;
00124 qres_time_t approved_Q;
00125 qos_bw_t bw_min;
00126 qos_bw_t bw_req;
00127 kal_uid_t uid;
00128 kal_gid_t gid;
00129
00130 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00131 qos_log_debug("(Q, P): (" QRES_TIME_FMT ", " QRES_TIME_FMT ")", param->Q, param->P);
00132 if (param->P < MIN_SRV_PERIOD || param->Q > param->P)
00133 return QOS_E_INVALID_PARAM;
00134
00135 if (param->Q < MIN_SRV_MAX_BUDGET) {
00136
00137 return QOS_E_INVALID_PARAM;
00138 }
00139
00140
00141
00142
00143 bw_min = r2bw_ceil(param->Q_min, param->P);
00144
00145
00146 param->Q_min = bw2Q(bw_min, param->P);
00147 param->Q = bw2Q(r2bw_ceil(param->Q, param->P), param->P);
00148 qos_log_debug("Rounded (Q, Q_min, P): (" QRES_TIME_FMT ", " QRES_TIME_FMT ", " QRES_TIME_FMT ")", param->Q, param->Q_min, param->P);
00149
00150 uid = kal_task_get_uid(kal_task_current());
00151 gid = kal_task_get_gid(kal_task_current());
00152
00153 #ifdef QRES_ENABLE_QSUP
00154
00155
00156
00157
00158
00159 if (param->flags & QOS_F_DEFAULT) {
00160 if (uid != 0 && uid != QSUP_DEFAULT_SRV_UID && gid != QSUP_DEFAULT_SRV_GID)
00161 return QOS_E_UNAUTHORIZED;
00162 }
00163 qos_chk_ok_ret(qsup_init_server(&qres->qsup, kal_task_get_uid(kal_task_current()),
00164 kal_task_get_gid(kal_task_current()), param));
00165
00166
00167 bw_req = r2bw(param->Q, param->P);
00168 qos_log_debug("Setting required bw to " QOS_BW_FMT, bw_req);
00169 rv = qsup_set_required_bw(&qres->qsup, bw_req);
00170 if (rv != QOS_OK) {
00171 qos_log_info("qsup_set_required_bw() failed: %s", qos_strerror(rv));
00172 qsup_cleanup_server(&qres->qsup);
00173 return rv;
00174 }
00175
00177 approved_Q = bw2Q(qsup_get_approved_bw(&qres->qsup), param->P);
00178
00179 #else
00180 if ((param->flags & QOS_F_DEFAULT) && (uid != 0))
00181 return QOS_E_UNAUTHORIZED;
00182 approved_Q = param->Q;
00183 #endif
00184
00185 qos_log_debug("Required=" QRES_TIME_FMT ", Approved=" QRES_TIME_FMT, param->Q, approved_Q);
00186
00187
00188
00189 qres_update_bandwidths();
00190
00192 rv = rres_init_server(&qres->rres, approved_Q,
00193 param->P, param->flags);
00194 if (rv != QOS_OK) {
00195 qos_log_info("rres_init_server() failed: %s", qos_strerror(rv));
00196 #ifdef QRES_ENABLE_QSUP
00197 qsup_cleanup_server(&qres->qsup);
00198 #endif
00199
00200
00201 qres_update_bandwidths();
00202 return rv;
00203 }
00204
00205 qres->owner_uid = uid;
00206 qres->owner_gid = gid;
00207
00208 qres->params = *param;
00209
00210
00211 qres->rres.cleanup = &_qres_cleanup_server;
00212 qres->rres.get_bandwidth = &_qres_get_bandwidth;
00213
00214 return QOS_OK;
00215 }
00216
00217 qos_func_define(qos_rv, qres_destroy_server, qres_server_t *qres) {
00218 struct task_struct *task;
00219 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00220 while ((task = rres_any_ready_task(&qres->rres)) != NULL) {
00221 qos_chk_ok_ret(rres_detach_task(&qres->rres, task));
00222 }
00223 while ((task = rres_any_blocked_task(&qres->rres)) != NULL) {
00224 qos_chk_ok_ret(rres_detach_task(&qres->rres, task));
00225 }
00226 qos_chk_ok_ret(rres_destroy_server(&qres->rres));
00227 qres = NULL;
00228
00229 return QOS_OK;
00230 }
00231
00233 qos_func_define(qos_rv, _qres_cleanup_server, server_t *rres) {
00234 qres_server_t *qres = qres_find_by_rres(rres);
00235
00236 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00237 if (! authorize_for_server(qres))
00238 return QOS_E_UNAUTHORIZED;
00239
00240
00241
00242 #ifdef QRES_ENABLE_QSUP
00243 qos_chk_ok_ret(qsup_cleanup_server(&qres->qsup));
00244 #endif
00245
00246
00247
00248 qres->rres.cleanup = &_rres_cleanup_server;
00249 qres->rres.get_bandwidth = &_rres_get_bandwidth;
00250
00251
00252 qos_chk_ok_ret(_rres_cleanup_server(&qres->rres));
00253 return QOS_OK;
00254 }
00255
00257 qos_bw_t _qres_get_bandwidth(server_t *srv) {
00258 qres_server_t *qres = qres_find_by_rres(srv);
00259
00260 #ifdef QRES_ENABLE_QSUP
00261 return qsup_get_approved_bw(&qres->qsup);
00262 #else
00263 return _rres_get_bandwidth(&qres->rres);
00264 #endif
00265 }
00266
00268 qos_func_define(qos_rv, qres_attach_task, qres_server_t *qres, struct task_struct *tsk) {
00269 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00270 if ((! authorize_for_task(tsk)) || (! authorize_for_server(qres)))
00271 return QOS_E_UNAUTHORIZED;
00272 qos_chk_ok_ret(rres_attach_task(&qres->rres, tsk));
00273
00274
00275
00276 if (rres_has_ready_tasks(&qres->rres)) {
00277 qsup_set_required_bw(&qres->qsup, r2bw(qres->params.Q, qres->params.P));
00278 }
00279
00280 return QOS_OK;
00281 }
00282
00293 qos_func_define(qos_rv, qres_detach_task, qres_server_t *qres, struct task_struct *tsk) {
00294 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00295 if (qres == NULL)
00296 return QOS_E_NOT_FOUND;
00297 if ((! authorize_for_task(tsk)) || (! authorize_for_server(qres)))
00298 return QOS_E_UNAUTHORIZED;
00299 qos_chk_ok_ret(rres_detach_task(&qres->rres, tsk));
00300
00301
00302
00303 if (! rres_has_ready_tasks(&qres->rres)) {
00304 qsup_set_required_bw(&qres->qsup, 0);
00305 }
00306
00307 qos_chk_ok_ret(rres_check_destroy(&qres->rres));
00308 qres = NULL;
00309 return QOS_OK;
00310 }
00311
00313 qos_func_define(qos_rv, qres_set_params, qres_server_t *qres, qres_params_t *param) {
00314 qres_time_t approved_Q;
00315
00316 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00317 qos_log_debug("Q=" QRES_TIME_FMT " Q_min=" QRES_TIME_FMT " P=" QRES_TIME_FMT,
00318 param->Q, param->Q_min, param->P);
00319
00320 if (! authorize_for_server(qres))
00321 return(QOS_E_UNAUTHORIZED);
00322
00323 if (param->P < MIN_SRV_PERIOD || param->Q > param->P)
00324 return QOS_E_INVALID_PARAM;
00325
00326 if (param->Q < MIN_SRV_MAX_BUDGET)
00327 return QOS_E_INVALID_PARAM;
00328
00329 if (param->flags != qres->params.flags)
00330 return QOS_E_UNIMPLEMENTED;
00331
00332
00333 param->Q_min = bw2Q(r2bw_ceil(param->Q_min, param->P), param->P);
00334 param->Q = bw2Q(r2bw_ceil(param->Q, param->P), param->P);
00335 qos_log_debug("Rounded (Q, Q_min, P): (" QRES_TIME_FMT ", " QRES_TIME_FMT ", " QRES_TIME_FMT ")", param->Q, param->Q_min, param->P);
00336
00337 #ifdef QRES_ENABLE_QSUP
00338 if (param->Q_min != qres->params.Q_min
00339 || param->P != qres->params.P) {
00340 qos_chk_ok_ret(qsup_cleanup_server(&qres->qsup));
00341 if (qsup_init_server(&qres->qsup, qres->owner_uid, qres->owner_gid, param) != QOS_OK)
00342 qos_chk_ok_ret(qsup_init_server(&qres->qsup, qres->owner_uid, qres->owner_gid, &qres->params));
00343 }
00344 qos_chk_ok_ret(qsup_set_required_bw(&qres->qsup, r2bw(param->Q, param->P)));
00345 approved_Q = bw2Q(qsup_get_approved_bw(&qres->qsup), param->P);
00346 #else
00347 approved_Q = param->Q;
00348 #endif
00349 qos_log_debug("Required=" QRES_TIME_FMT ", Approved=" QRES_TIME_FMT, param->Q, approved_Q);
00350 qos_chk_ok_ret(rres_set_params(&qres->rres, approved_Q, param->P));
00351 qres->params = *param;
00352
00353 return QOS_OK;
00354 }
00355
00356 qos_func_define(qos_rv, qres_get_params, qres_server_t *qres, qres_params_t *params) {
00357 qos_chk_do(kal_atomic(), return QOS_E_INTERNAL_ERROR);
00358 *params = qres->params;
00359 return QOS_OK;
00360 }
00361
00362 qos_func_define(qres_time_t, qres_get_curr_budget, qres_server_t *qres) {
00363 return rres_get_curr_budget(&qres->rres);
00364 }
00365
00366 qos_func_define(qres_time_t, qres_get_next_budget, qres_server_t *qres) {
00367 return bw2Q(rres_get_current_bandwidth(&qres->rres), qres->params.P);
00368 }
00369
00370 qos_func_define(qres_time_t, qres_get_appr_budget, qres_server_t *qres) {
00371 return bw2Q(rres_get_bandwidth(&qres->rres), qres->params.P);
00372 }
00373
00374 qos_func_define(qos_rv, qres_get_deadline, qres_server_t *qres, struct timespec *p_deadline) {
00375 return rres_get_deadline(&qres->rres, p_deadline);
00376 }
00377
00378 qos_func_define(qos_rv, qres_get_exec_abs_time, qres_server_t *qres,
00379 qres_time_t *exec_time, qres_atime_t *abs_time) {
00380 *exec_time = rres_get_exec_time(&qres->rres);
00381 *abs_time = kal_time2usec(kal_time_now());
00382 return QOS_OK;
00383 }
00384
00386 kal_uid_t qres_get_owner_uid(qres_server_t* qres) {
00387 return qres->owner_uid;
00388 }
00389 EXPORT_SYMBOL_GPL(qres_get_owner_uid);
00390
00392 kal_gid_t qres_get_owner_gid(qres_server_t* qres) {
00393 return qres->owner_gid;
00394 }
00395 EXPORT_SYMBOL_GPL(qres_get_owner_gid);
00396
00397 EXPORT_SYMBOL_GPL(qres_create_server);
00398 EXPORT_SYMBOL_GPL(qres_destroy_server);
00399 EXPORT_SYMBOL_GPL(qres_attach_task);
00400 EXPORT_SYMBOL_GPL(qres_detach_task);
00401 EXPORT_SYMBOL_GPL(qres_set_params);
00402 EXPORT_SYMBOL_GPL(qres_get_params);
00403
00404 EXPORT_SYMBOL_GPL(qres_get_exec_abs_time);
00405 EXPORT_SYMBOL_GPL(qres_get_deadline);
00406
00407
00408 EXPORT_SYMBOL_GPL(_qres_get_bandwidth);
00409 EXPORT_SYMBOL_GPL(_qres_cleanup_server);