Changeset ed5367b in mainline


Ignore:
Timestamp:
2019-08-07T10:01:13Z (5 years ago)
Author:
Matthieu Riolo <matthieu.riolo@…>
Children:
a097c50
Parents:
68ae40a
git-author:
Michal Koutný <xm.koutny+hos@…> (2015-11-05 01:52:07)
git-committer:
Matthieu Riolo <matthieu.riolo@…> (2019-08-07 10:01:13)
Message:

sysman: Implement stopping units

Currently fails service monitoring because of taskman flawed event flags.
However, job closure works well.

Location:
uspace
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/sysctl/main.c

    r68ae40a red5367b  
    3737#include <stdlib.h>
    3838#include <str.h>
     39#include <str_error.h>
    3940#include <sysman/ctl.h>
    4041
     
    9192                continue;
    9293fail:
    93                 printf(" -- unit skipped due to IPC error (%i) --\n", rc);
     94                printf(" -- unit skipped due to IPC error (%s) --\n",
     95                    str_error(rc));
     96        }
     97
     98        return 0;
     99}
     100
     101static int stop(int argc, char *argv[])
     102{
     103        unit_handle_t handle;
     104        char *unit_name = argv[1];
     105
     106        int rc = sysman_unit_handle(unit_name, &handle);
     107        if (rc != EOK) {
     108                printf("Cannot obtain handle for unit '%s' (%s).\n",
     109                    unit_name, str_error(rc));
     110                return rc;
     111        }
     112
     113        rc = sysman_unit_stop(handle, IPC_FLAG_BLOCKING);
     114        if (rc != EOK) {
     115                printf("Error when stopping unit '%s' handle (%s).\n",
     116                    unit_name, str_error(rc));
     117                return rc;
    94118        }
    95119
     
    99123command_t commands[] = {
    100124        { "list-units", 0, &list_units },
     125        { "stop",       1, &stop },
    101126        { 0 }
    102127};
  • uspace/lib/c/include/ipc/sysman.h

    r68ae40a red5367b  
    4444        SYSMAN_BROKER_EXP_ADDED,
    4545        SYSMAN_BROKER_EXP_REMOVED,
     46        SYSMAN_CTL_UNIT_HANDLE,
    4647        SYSMAN_CTL_UNIT_START,
     48        SYSMAN_CTL_UNIT_STOP,
    4749        SYSMAN_CTL_GET_UNITS,
    4850        SYSMAN_CTL_UNIT_GET_NAME,
     
    7173        STATE_STARTED,
    7274        STATE_STOPPED,
     75        STATE_STOPPING,
    7376        STATE_FAILED
    7477} unit_state_t;
  • uspace/lib/sysman/include/sysman/ctl.h

    r68ae40a red5367b  
    3333#include <sysman/unit.h>
    3434
     35int sysman_unit_handle(const char *, unit_handle_t *);
     36
    3537int sysman_unit_start(const char *, int);
     38int sysman_unit_stop(unit_handle_t, int);
    3639
    3740int sysman_get_units(unit_handle_t **, size_t *);
  • uspace/lib/sysman/src/ctl.c

    r68ae40a red5367b  
    3434#include <sysman/sysman.h>
    3535
     36int sysman_unit_handle(const char *unit_name, unit_handle_t *handle_ptr)
     37{
     38        async_exch_t *exch = sysman_exchange_begin(SYSMAN_PORT_CTL);
     39
     40        ipc_call_t call;
     41        aid_t req = async_send_0(exch, SYSMAN_CTL_UNIT_HANDLE, &call);
     42        sysarg_t rc = async_data_write_start(exch, unit_name, str_size(unit_name));
     43        sysman_exchange_end(exch);
     44
     45        if (rc != EOK) {
     46                async_forget(req);
     47                return rc;
     48        }
     49
     50        async_wait_for(req, &rc);
     51        if (rc == EOK) {
     52                *handle_ptr = IPC_GET_ARG1(call);
     53        }
     54        return rc;
     55}
     56
    3657/*
    3758 * TODO
     
    4162 * broker knows when appropriate exposee is created and the request succeeded.
    4263 * Still though, it's necessary to centralize timeout into sysman.
     64 * TODO convert to name->handle API
    4365 */
    4466int sysman_unit_start(const char *unit_name, int flags)
     
    5678
    5779        async_wait_for(req, &rc);
     80        return rc;
     81}
     82
     83int sysman_unit_stop(unit_handle_t handle, int flags)
     84{
     85        async_exch_t *exch = sysman_exchange_begin(SYSMAN_PORT_CTL);
     86
     87        int rc = async_req_2_0(exch, SYSMAN_CTL_UNIT_STOP, handle, flags);
     88        sysman_exchange_end(exch);
     89       
    5890        return rc;
    5991}
  • uspace/srv/sysman/connection_ctl.c

    r68ae40a red5367b  
    6363        job_del_ref(&job);
    6464}
     65
     66static void sysman_unit_handle(ipc_callid_t iid, ipc_call_t *icall)
     67{
     68        char *unit_name = NULL;
     69        sysarg_t retval;
     70
     71        int rc = async_data_write_accept((void **) &unit_name, true,
     72            0, 0, 0, NULL);
     73        if (rc != EOK) {
     74                retval = rc;
     75                goto fail;
     76        }
     77
     78        // TODO this is connection fibril, UNSYNCHRONIZED access to units!
     79        unit_t *unit = repo_find_unit_by_name(unit_name);
     80        if (unit == NULL) {
     81                retval = ENOENT;
     82                goto fail;
     83        }
     84
     85        async_answer_1(iid, EOK, unit->handle);
     86        goto finish;
     87
     88fail:
     89        async_answer_0(iid, retval);
     90finish:
     91        free(unit_name);
     92}
     93
    6594static void sysman_unit_start(ipc_callid_t iid, ipc_call_t *icall)
    6695{
     
    109138finish:
    110139        free(unit_name);
     140}
     141
     142static void sysman_unit_stop(ipc_callid_t iid, ipc_call_t *icall)
     143{
     144        sysarg_t retval;
     145
     146        unit_handle_t handle = IPC_GET_ARG1(*icall);
     147        int flags = IPC_GET_ARG2(*icall);
     148        sysman_log(LVL_DEBUG2, "%s(%i, %x)", __func__, handle, flags);
     149
     150        // TODO this is connection fibril, UNSYNCHRONIZED access to units!
     151        unit_t *unit = repo_find_unit_by_handle(handle);
     152        if (unit == NULL) {
     153                retval = ENOENT;
     154                goto answer;
     155        }
     156
     157        if (!(flags & IPC_FLAG_BLOCKING)) {
     158                retval = sysman_run_job(unit, STATE_STOPPED, NULL, NULL);
     159                goto answer;
     160        }
     161
     162        ipc_callid_t *iid_ptr = box_callid(iid);
     163        if (iid_ptr == NULL) {
     164                retval = ENOMEM;
     165                goto answer;
     166        }
     167        retval = sysman_run_job(unit, STATE_STOPPED, &answer_callback,
     168            iid_ptr);
     169        if (retval != EOK) {
     170                goto answer;
     171        }
     172
     173        /* Answer asynchronously from callback */
     174        return;
     175
     176answer:
     177        async_answer_0(iid, retval);
    111178}
    112179
     
    220287
    221288                switch (IPC_GET_IMETHOD(call)) {
     289                case SYSMAN_CTL_UNIT_HANDLE:
     290                        sysman_unit_handle(callid, &call);
     291                        break;
    222292                case SYSMAN_CTL_UNIT_START:
    223293                        sysman_unit_start(callid, &call);
     294                        break;
     295                case SYSMAN_CTL_UNIT_STOP:
     296                        sysman_unit_stop(callid, &call);
    224297                        break;
    225298                case SYSMAN_CTL_GET_UNITS:
  • uspace/srv/sysman/job.c

    r68ae40a red5367b  
    199199
    200200        int rc;
     201        // TODO put here similar evaluation as in job_check
     202        //      goal is to have job_run "idempotent"
    201203        switch (job->target_state) {
    202204        case STATE_STARTED:
    203                 // TODO put here same evaluation as in job_check
    204                 //      goal is to have job_run "idempotent"
    205205                if (u->state == job->target_state) {
    206206                        rc = EOK;
     
    209209                }
    210210                break;
     211        case STATE_STOPPED:
     212                if (u->state == job->target_state) {
     213                        rc = EOK;
     214                } else {
     215                        rc = unit_stop(u);
     216                }
     217                break;
    211218        default:
    212                 // TODO implement other states
     219                // TODO implement other states?
    213220                assert(false);
    214221        }
  • uspace/srv/sysman/job_closure.c

    r68ae40a red5367b  
    3939
    4040/** Struct describes how to traverse units graph */
    41 typedef struct {
     41struct bfs_ops;
     42typedef struct bfs_ops bfs_ops_t;
     43
     44struct bfs_ops {
    4245        enum {
    4346                BFS_FORWARD,  /**< Follow oriented edges */
     
    4649
    4750        /** Visit a unit via edge
    48          * unit, incoming edge, user data
     51         * unit, incoming edge, traversing ops, user data
    4952         * return result of visit (error stops further traversal)
    5053         */
    51         int (* visit)(unit_t *, unit_edge_t *, void *);
     54        int (* visit)(unit_t *, unit_edge_t *, bfs_ops_t *, void *);
    5255
    5356        /** Clean units remaining in BFS queue after error */
    54         void (* clean)(unit_t *, void *);
    55 } bfs_ops_t;
     57        void (* clean)(unit_t *, bfs_ops_t *, void *);
     58};
    5659
    5760/*
     
    8386 * @return EOK on success
    8487 */
    85 static int start_visit(unit_t *u, unit_edge_t *e, void *arg)
     88static int visit_propagate_job(unit_t *u, unit_edge_t *e, bfs_ops_t *ops,
     89    void *arg)
    8690{
    8791        int rc = EOK;
     
    99103        }
    100104
    101         job_t *job = e->input->bfs_data;
     105        job_t *job = (ops->direction == BFS_FORWARD) ?
     106            e->input->bfs_data :
     107            e->output->bfs_data;
     108
    102109        assert(job != NULL);
    103110
     
    129136}
    130137
    131 static void traverse_clean(unit_t *u, void *arg)
     138static void traverse_clean(unit_t *u, bfs_ops_t *ops, void *arg)
    132139{
    133140        job_t *job = u->bfs_data;
     
    144151        unit_t *unit = origin;
    145152
    146         rc = ops->visit(unit, NULL, arg);
     153        rc = ops->visit(unit, NULL, ops, arg);
    147154        if (rc != EOK) {
    148155                goto finish;
     
    164171                                list_append(&u->bfs_link, &units_fifo);
    165172                        }
    166                         rc = ops->visit(u, e, arg);
     173                        rc = ops->visit(u, e, ops, arg);
    167174                        if (rc != EOK) {
    168175                                goto finish;
     
    175182                                list_append(&u->bfs_link, &units_fifo);
    176183                        }
    177                         rc = ops->visit(u, e, arg);
     184                        rc = ops->visit(u, e, ops, arg);
    178185                        if (rc != EOK) {
    179186                                goto finish;
     
    187194        list_foreach_safe(units_fifo, cur_link, next_link) {
    188195                unit_t *u = list_get_instance(cur_link, unit_t, bfs_link);
    189                 ops->clean(u, arg);
     196                ops->clean(u, ops, arg);
    190197                list_remove(cur_link);
    191198        }
     
    227234
    228235        static bfs_ops_t ops = {
    229                 .direction = BFS_FORWARD,
    230                 .visit = start_visit,
    231236                .clean = traverse_clean,
     237                .visit = visit_propagate_job
    232238        };
     239
     240        switch (main_job->target_state) {
     241        case STATE_STARTED:
     242                ops.direction = BFS_FORWARD;
     243                break;
     244        case STATE_STOPPED:
     245                ops.direction = BFS_BACKWARD;
     246                break;
     247        default:
     248                assert(false);
     249        }
     250
    233251        int rc = dyn_array_append(job_closure, job_t *, main_job);
    234252        if (rc != EOK) {
  • uspace/srv/sysman/sm_task.c

    r68ae40a red5367b  
    101101        sysman_log(LVL_DEBUG2, "%s, %s(%i)@%" PRIu64 " %i",
    102102            __func__, unit_name(u), u->state, tev->task_id, tev->flags);
    103         assert(u->state == STATE_STARTING);
    104103
    105104        if (tev->flags & TASK_WAIT_EXIT) {
    106105                // TODO maybe call unit_fail (would be nice to contain reason)
    107                 u->state = STATE_FAILED;
    108         } else {
     106                //      or move this whole logic to unit_svc.c
     107                if (u->state == STATE_STOPPING) {
     108                        u->state = STATE_STOPPED;
     109                } else {
     110                        // if it has also retval == 0 then it's not fail
     111                        u->state = STATE_FAILED;
     112                }
     113        }
     114        if (tev->flags & TASK_WAIT_RETVAL) {
     115                assert(u->state == STATE_STARTING);
    109116                u->state = STATE_STARTED;
    110117        }
  • uspace/srv/sysman/unit.c

    r68ae40a red5367b  
    142142}
    143143
     144/** Issue request to restarter to stop a unit
     145 *
     146 * Same semantics like for unit_start applies.
     147 */
     148int unit_stop(unit_t *unit)
     149{
     150        sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit));
     151        return UNIT_VMT(unit)->stop(unit);
     152}
     153
    144154void unit_exposee_created(unit_t *unit)
    145155{
  • uspace/srv/sysman/unit.h

    r68ae40a red5367b  
    7070        job_t *job;
    7171
     72        /** Handle for IPC (immutable) */
    7273        unit_handle_t handle;
     74
     75        /** Unit type (immutable) */
    7376        unit_type_t type;
     77
     78        /** Unit name (immutable) */
    7479        char *name;
    7580
     
    110115        int (*start)(unit_t *);
    111116
     117        int (*stop)(unit_t *);
     118
    112119        void (*exposee_created)(unit_t *);
    113120
     
    124131                .destroy         = &PREFIX##_destroy,                          \
    125132                .start           = &PREFIX##_start,                            \
     133                .stop            = &PREFIX##_stop,                             \
    126134                .exposee_created = &PREFIX##_exposee_created,                  \
    127135                .fail            = &PREFIX##_fail                              \
     
    135143extern int unit_load(unit_t *, ini_configuration_t *, text_parse_t *);
    136144extern int unit_start(unit_t *);
     145extern int unit_stop(unit_t *);
    137146extern void unit_exposee_created(unit_t *);
    138147extern void unit_fail(unit_t *);
  • uspace/srv/sysman/units/unit_cfg.c

    r68ae40a red5367b  
    240240}
    241241
     242static int unit_cfg_stop(unit_t *unit)
     243{
     244        unit_cfg_t *u_cfg = CAST_CFG(unit);
     245        assert(u_cfg);
     246
     247        /*
     248         * It makes no sense to stop configuration (i.e. unload it), however,
     249         * lets virtually stop it not to make obstructions for potential
     250         * restart = reload of configuration.
     251         */
     252        unit->state = STATE_STOPPED;
     253        return EOK;
     254}
     255
    242256static void unit_cfg_exposee_created(unit_t *unit)
    243257{
  • uspace/srv/sysman/units/unit_mnt.c

    r68ae40a red5367b  
    229229}
    230230
     231static int unit_mnt_stop(unit_t *unit)
     232{
     233        unit_mnt_t *u_mnt = CAST_MNT(unit);
     234        assert(u_mnt);
     235        /* autostart implies blocking */
     236        assert(!u_mnt->autostart || u_mnt->blocking);
     237
     238       
     239        // TODO think about unit's lifecycle (is STOPPED only acceptable?)
     240        // note: we should never hit STATE_STARTING, since it'd mean there are
     241        //       two jobs running at once (unless job cancellation is implemented)
     242        assert(unit->state == STATE_STARTED);
     243
     244        /*
     245         * We don't expect unmount to be blocking, since if some files are
     246         * being used, it'd return EBUSY immediately. That's why we call
     247         * unmount synchronously in the event loop fibril.
     248         */
     249        int rc = unmount(u_mnt->mountpoint);
     250
     251        if (rc == EOK) {
     252                unit->state = STATE_STOPPED;
     253                return EOK;
     254        } else if (rc == EBUSY) {
     255                assert(unit->state == STATE_STARTED);
     256                return EBUSY;
     257        } else {
     258                /*
     259                 * Mount may be still usable, but be conservative and mark unit
     260                 * as failed.
     261                 */
     262                unit->state = STATE_FAILED;
     263                return rc;
     264        }
     265}
     266
    231267static void unit_mnt_exposee_created(unit_t *unit)
    232268{
  • uspace/srv/sysman/units/unit_svc.c

    r68ae40a red5367b  
    112112}
    113113
     114static int unit_svc_stop(unit_t *unit)
     115{
     116        unit_svc_t *u_svc = CAST_SVC(unit);
     117        assert(u_svc);
     118
     119       
     120        // TODO think about unit's lifecycle (is STOPPED only acceptable?)
     121        // note: May change when job cancellation is possible.
     122        assert(unit->state == STATE_STARTED);
     123
     124        int rc = task_kill(u_svc->main_task_id);
     125
     126        if (rc != EOK) {
     127                /* Task may still be running, but be conservative about unit's
     128                 * state. */
     129                unit->state = STATE_FAILED;
     130                return rc;
     131        }
     132
     133        unit->state = STATE_STOPPING;
     134
     135        return EOK;
     136}
     137
     138
    114139static void unit_svc_exposee_created(unit_t *unit)
    115140{
  • uspace/srv/sysman/units/unit_tgt.c

    r68ae40a red5367b  
    6363}
    6464
     65static int unit_tgt_stop(unit_t *unit)
     66{
     67        unit_tgt_t *u_tgt = CAST_TGT(unit);
     68        assert(u_tgt);
     69
     70        unit->state = STATE_STOPPED;
     71        return EOK;
     72}
     73
    6574static void unit_tgt_exposee_created(unit_t *unit)
    6675{
Note: See TracChangeset for help on using the changeset viewer.