On Wed, Feb 24, 2021 at 08:03:21PM -0500, Ashton Fagg wrote:
> Ashton Fagg <ash...@fagg.id.au> writes:
> 
> > Attached is my first attempt at a "proper" solution. I haven't tested it
> > beyond building as I can't take my machine down for testing right now...
> >
> > But, I'd appreciate a sanity check that I'm on the right track.
> 
> Sorry for the noise. I think my mail client mangled the attachment, so
> trying again.
> 

> diff --git a/usr.sbin/iscsictl/iscsictl.c b/usr.sbin/iscsictl/iscsictl.c
> index 77f9c74abde..5fc326acca6 100644
> --- a/usr.sbin/iscsictl/iscsictl.c
> +++ b/usr.sbin/iscsictl/iscsictl.c
> @@ -40,6 +40,8 @@ struct pdu  *ctl_getpdu(char *, size_t);
>  int           ctl_sendpdu(int, struct pdu *);
>  void          show_config(struct ctrlmsghdr *, struct pdu *);
>  void          show_vscsi_stats(struct ctrlmsghdr *, struct pdu *);
> +void             poll_and_wait(void);
> +void             register_poll(struct ctrlmsghdr *, struct pdu *);
>  
>  char         cbuf[CONTROL_READ_SIZE];
>  
> @@ -48,6 +50,14 @@ struct control {
>       int             fd;
>  } control;
>  
> +struct poll_result {
> +     u_int8_t   result;
> +     int        attempts;
> +} pr;
> +
> +#define POLL_DELAY     1
> +#define POLL_ATTEMPTS  10
> +
>  __dead void
>  usage(void)
>  {
> @@ -68,7 +78,7 @@ main (int argc, char* argv[])
>       char *sockname = ISCSID_CONTROL;
>       struct session_ctlcfg *s;
>       struct iscsi_config *cf;
> -     int ch, val = 0;
> +     int ch, poll = 0, val = 0;
>  
>       /* check flags */
>       while ((ch = getopt(argc, argv, "f:s:")) != -1) {
> @@ -135,6 +145,9 @@ main (int argc, char* argv[])
>                           &cf->initiator, sizeof(cf->initiator)) == -1)
>                               err(1, "control_compose");
>               }
> +
> +             /* Reloading, so poll afterwards. */
> +             poll = 1;
>               SIMPLEQ_FOREACH(s, &cf->sessions, entry) {
>                       struct ctrldata cdv[3];
>                       bzero(cdv, sizeof(cdv));
> @@ -174,6 +187,12 @@ main (int argc, char* argv[])
>  
>       run();
>  
> +     /* If we've reloaded, we probably should wait in case any new 
> connections
> +        need to come up (or fail). */
> +     if (poll) {
> +             poll_and_wait();
> +     }
> +
>       close(control.fd);
>  
>       return (0);
> @@ -229,6 +248,10 @@ run_command(struct pdu *pdu)
>               case CTRL_INPROGRESS:
>                       printf("command in progress...\n");
>                       break;
> +             case CTRL_SESS_POLL:
> +                     done = 1;
> +                     register_poll(cmh, pdu);
> +                     break;
>               case CTRL_INITIATOR_CONFIG:
>               case CTRL_SESSION_CONFIG:
>                       show_config(cmh, pdu);
> @@ -383,3 +406,43 @@ show_vscsi_stats(struct ctrlmsghdr *cmh, struct pdu *pdu)
>           vs->cnt_t2i_status[1], 
>           vs->cnt_t2i_status[2]);
>  }
> +
> +void
> +poll_and_wait(void)
> +{
> +     pr.result = (u_int8_t) 0;
> +     printf("polling...");
> +
> +     for (pr.attempts = 1; pr.attempts <= POLL_ATTEMPTS; ++pr.attempts) {
> +             if (control_compose(NULL, CTRL_SESS_POLL, NULL, 0) == -1)
> +                     err(1, "control_compose");
> +
> +             struct pdu *pdu;
> +             while ((pdu = TAILQ_FIRST(&control.channel)) != NULL) {
> +                     run_command(pdu);
> +             }
> +
> +             /* Poll says we are good to go. */
> +             if (pr.result != 0) {
> +                     printf("ok!\n");
> +                     return;
> +             }
> +
> +             /* Poll says we should wait... */
> +             printf("%d, ", pr.attempts);
> +             sleep(POLL_DELAY);
> +     }
> +
> +     printf("..,timer exceeded.\n");
> +}
> +
> +void
> +register_poll(struct ctrlmsghdr *cmh, struct pdu *pdu)
> +{
> +     u_int8_t *r = &pr.result;
> +
> +     if (cmh->len[0] != sizeof(u_int8_t))
> +             errx(1, "poll: bad size of response");
> +
> +     r = pdu_getbuf(pdu, NULL, 1);
> +}
> diff --git a/usr.sbin/iscsid/Makefile b/usr.sbin/iscsid/Makefile
> index 7a62024e68b..bac59d934f8 100644
> --- a/usr.sbin/iscsid/Makefile
> +++ b/usr.sbin/iscsid/Makefile
> @@ -2,7 +2,7 @@
>  
>  PROG=        iscsid
>  SRCS=        connection.c control.c initiator.c iscsid.c log.c logmsg.c 
> pdu.c \
> -     session.c task.c util.c vscsi.c
> +     poll.c session.c task.c util.c vscsi.c
>  
>  MAN= iscsid.8
>  
> diff --git a/usr.sbin/iscsid/iscsid.c b/usr.sbin/iscsid/iscsid.c
> index d3526e96363..61f831c3b24 100644
> --- a/usr.sbin/iscsid/iscsid.c
> +++ b/usr.sbin/iscsid/iscsid.c
> @@ -211,6 +211,7 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu)
>       struct initiator_config *ic;
>       struct session_config *sc;
>       struct session *s;
> +     struct session_poll *p;
>       int *valp;
>  
>       cmh = pdu_getbuf(pdu, NULL, 0);
> @@ -304,6 +305,20 @@ iscsid_ctrl_dispatch(void *ch, struct pdu *pdu)
>  
>               control_compose(ch, CTRL_SUCCESS, NULL, 0);
>               break;
> +     case CTRL_SESS_POLL:
> +             p = poll_alloc();
> +
> +             TAILQ_FOREACH(s, &initiator->sessions, entry) {
> +                     poll_session(p, s);
> +             }
> +
> +             poll_finalize(p);
> +
> +             control_compose(ch, CTRL_SESS_POLL,
> +                 (void *) &(p->status), sizeof(u_int8_t));

No need to type-cast, no need for the () around &(p->status). I prefer to
use sizeof(p->status) since that will adapt properly.

> +
> +             poll_dealloc(p);

I think you could just use a stack variable for p here instead of using
alloc and dealloc. The struct is small.

> +             break;
>       default:
>               log_warnx("unknown control message type %d", cmh->type);
>               control_compose(ch, CTRL_FAILURE, NULL, 0);
> diff --git a/usr.sbin/iscsid/iscsid.h b/usr.sbin/iscsid/iscsid.h
> index b43fb5dcd99..08d5f251a39 100644
> --- a/usr.sbin/iscsid/iscsid.h
> +++ b/usr.sbin/iscsid/iscsid.h
> @@ -67,7 +67,7 @@ struct ctrldata {
>  #define CTRL_LOG_VERBOSE     6
>  #define CTRL_VSCSI_STATS     7
>  #define CTRL_SHOW_SUM                8
> -
> +#define CTRL_SESS_POLL          9
>  
>  TAILQ_HEAD(session_head, session);
>  TAILQ_HEAD(connection_head, connection);
> @@ -251,6 +251,13 @@ struct session {
>       int                      action;
>  };
>  
> +struct session_poll {
> +     u_int16_t session_count; /* Total number of configured sessions*/
> +     u_int16_t init_count;    /* Number of sessions in init state */
> +     u_int16_t running_count; /* Number of sessions in running state */
> +     u_int8_t  status;        /* Status flag */
> +};
> +

I would just use int for all the variables here. Just keep it simple.

>  struct connection {
>       struct event             ev;
>       struct event             wev;
> @@ -391,6 +398,12 @@ void     vscsi_status(int, int, void *, size_t);
>  void vscsi_event(unsigned long, u_int, u_int);
>  struct vscsi_stats *vscsi_stats(void);
>  
> +/* Session polling */
> +struct session_poll *poll_alloc(void);
> +void    poll_dealloc(struct session_poll *);
> +void    poll_session(struct session_poll *, struct session *);
> +void    poll_finalize(struct session_poll *);
> +
>  /* logmsg.c */
>  void log_hexdump(void *, size_t);
>  void log_pdu(struct pdu *, int);
> diff --git a/usr.sbin/iscsid/poll.c b/usr.sbin/iscsid/poll.c
> new file mode 100644
> index 00000000000..d3c79985d71
> --- /dev/null
> +++ b/usr.sbin/iscsid/poll.c
> @@ -0,0 +1,80 @@
> +/*
> + * Copyright (c) 2021 Dr Ashton Fagg <ash...@fagg.id.au>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +
> +#include <event.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +
> +#include "iscsid.h"
> +#include "log.h"
> +
> +struct session_poll
> +*poll_alloc(void)
> +{
> +     struct session_poll *p;
> +
> +     if (!(p = calloc(1, sizeof(*p))))
> +             fatal("poll_alloc failed.");
> +

Calloc already sets all memory to 0. So the code below is not needed.

> +     p->session_count = (u_int16_t) 0;
> +     p->init_count    = (u_int16_t) 0;
> +     p->running_count = (u_int16_t) 0;

Also there is no need to typecast here. In general try to avoid typecasts
since they can hide hard to find bugs.

> +
> +     return p;
> +}
> +
> +
> +void
> +poll_dealloc(struct session_poll *p)
> +{
> +     free(p);
> +}

As mentioned above I would just use a stack variable
        struct session_poll p = { 0 };
instead of dynamically allocate this.

> +void
> +poll_session(struct session_poll *p, struct session *s)
> +{
> +     if (!s)
> +             fatal("poll_session failed: invalid session");
> +
> +     ++(p->session_count);

No need for the ()

> +
> +     /* If SESS_RUNNING, this determines the session has either
> +           been brought up successfully, or has failed. Either way,
> +        we aren't waiting on it. */
> +     if (s->state & SESS_RUNNING)
> +             ++(p->running_count);
> +     /* Otherwise, it is in SESS_INIT. These need to be waited on. */
> +     else if (s->state & SESS_RUNNING)
> +             ++(p->init_count);

The two if statements are the same. I guess you want SESS_INIT in the
second.

> +     else
> +             fatal("poll_session: unknown state.");
> +}
> +
> +void
> +poll_finalize(struct session_poll *p)
> +{
> +     /* Perform final book keeping to determine status.
> +         *
> +      * status will be non-zero if the number of sessions that are
> +         * in states other than SESS_INIT is equal to the total number
> +      * of configured sessions. This indicates to the poller that
> +      * we are not waiting for something to complete. */

Indents are strange here. Guess tab vs spaces.

> +     p->status = (u_int8_t) (p->session_count == p->running_count);
> +}

I actually wonder if this code should just return the various counts to
iscsictl so it could display the status (if requested).

I think this is moving in the right direction.
-- 
:wq Claudio

Reply via email to