On Fri, Oct 12, 2018 at 12:27:07AM +0200, Martin Wilck wrote: > The checkers code implicitly uses a sort-of OOP class/instance model, > but very clumsily. Separate the checker "class" and "instance" cleanly, > and do a few further cleanups (constifications etc) on the way. > Reviewed-by: Benjamin Marzinski <bmarzins@xxxxxxxxxx> > Signed-off-by: Martin Wilck <mwilck@xxxxxxxx> > --- > libmultipath/checkers.c | 137 ++++++++++++++++--------------- > libmultipath/checkers.h | 23 ++---- > libmultipath/checkers/directio.c | 2 +- > libmultipath/checkers/tur.c | 2 +- > libmultipath/print.c | 2 +- > libmultipath/propsel.c | 19 +++-- > 6 files changed, 92 insertions(+), 93 deletions(-) > > diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c > index 19c8ad58..7733471c 100644 > --- a/libmultipath/checkers.c > +++ b/libmultipath/checkers.c > @@ -8,6 +8,19 @@ > #include "checkers.h" > #include "vector.h" > > +struct checker_class { > + struct list_head node; > + void *handle; > + int refcount; > + int sync; > + char name[CHECKER_NAME_LEN]; > + int (*check)(struct checker *); > + int (*init)(struct checker *); /* to allocate the context */ > + void (*free)(struct checker *); /* to free the context */ > + const char **msgtable; > + short msgtable_size; > +}; > + > char *checker_state_names[] = { > "wild", > "unchecked", > @@ -23,38 +36,30 @@ char *checker_state_names[] = { > > static LIST_HEAD(checkers); > > -char * checker_state_name (int i) > +const char *checker_state_name(int i) > { > return checker_state_names[i]; > } > > -int init_checkers (char *multipath_dir) > -{ > - if (!add_checker(multipath_dir, DEFAULT_CHECKER)) > - return 1; > - return 0; > -} > - > -struct checker * alloc_checker (void) > +static struct checker_class *alloc_checker_class(void) > { > - struct checker *c; > + struct checker_class *c; > > - c = MALLOC(sizeof(struct checker)); > + c = MALLOC(sizeof(struct checker_class)); > if (c) { > INIT_LIST_HEAD(&c->node); > c->refcount = 1; > - c->fd = -1; > } > return c; > } > > -void free_checker (struct checker * c) > +void free_checker_class(struct checker_class *c) > { > if (!c) > return; > c->refcount--; > if (c->refcount) { > - condlog(3, "%s checker refcount %d", > + condlog(4, "%s checker refcount %d", > c->name, c->refcount); > return; > } > @@ -71,17 +76,17 @@ void free_checker (struct checker * c) > > void cleanup_checkers (void) > { > - struct checker * checker_loop; > - struct checker * checker_temp; > + struct checker_class *checker_loop; > + struct checker_class *checker_temp; > > list_for_each_entry_safe(checker_loop, checker_temp, &checkers, node) { > - free_checker(checker_loop); > + free_checker_class(checker_loop); > } > } > > -struct checker * checker_lookup (char * name) > +static struct checker_class *checker_class_lookup(const char *name) > { > - struct checker * c; > + struct checker_class *c; > > if (!name || !strlen(name)) > return NULL; > @@ -92,14 +97,15 @@ struct checker * checker_lookup (char * name) > return NULL; > } > > -struct checker * add_checker (char *multipath_dir, char * name) > +static struct checker_class *add_checker_class(const char *multipath_dir, > + const char *name) > { > char libname[LIB_CHECKER_NAMELEN]; > struct stat stbuf; > - struct checker * c; > + struct checker_class *c; > char *errstr; > > - c = alloc_checker(); > + c = alloc_checker_class(); > if (!c) > return NULL; > snprintf(c->name, CHECKER_NAME_LEN, "%s", name); > @@ -158,12 +164,11 @@ struct checker * add_checker (char *multipath_dir, char * name) > c->name, c->msgtable_size); > > done: > - c->fd = -1; > c->sync = 1; > list_add(&c->node, &checkers); > return c; > out: > - free_checker(c); > + free_checker_class(c); > return NULL; > } > > @@ -176,16 +181,16 @@ void checker_set_fd (struct checker * c, int fd) > > void checker_set_sync (struct checker * c) > { > - if (!c) > + if (!c || !c->cls) > return; > - c->sync = 1; > + c->cls->sync = 1; > } > > void checker_set_async (struct checker * c) > { > - if (!c) > + if (!c || !c->cls) > return; > - c->sync = 0; > + c->cls->sync = 0; > } > > void checker_enable (struct checker * c) > @@ -204,11 +209,11 @@ void checker_disable (struct checker * c) > > int checker_init (struct checker * c, void ** mpctxt_addr) > { > - if (!c) > + if (!c || !c->cls) > return 1; > c->mpcontext = mpctxt_addr; > - if (c->init) > - return c->init(c); > + if (c->cls->init) > + return c->cls->init(c); > return 0; > } > > @@ -220,15 +225,16 @@ void checker_clear (struct checker *c) > > void checker_put (struct checker * dst) > { > - struct checker * src; > + struct checker_class *src; > > - if (!dst || !strlen(dst->name)) > + if (!dst) > return; > - src = checker_lookup(dst->name); > - if (dst->free) > - dst->free(dst); > + src = dst->cls; > + > + if (src && src->free) > + src->free(dst); > checker_clear(dst); > - free_checker(src); > + free_checker_class(src); > } > > int checker_check (struct checker * c, int path_state) > @@ -243,32 +249,35 @@ int checker_check (struct checker * c, int path_state) > c->msgid = CHECKER_MSGID_DISABLED; > return PATH_UNCHECKED; > } > - if (!strncmp(c->name, NONE, 4)) > + if (!strncmp(c->cls->name, NONE, 4)) > return path_state; > > if (c->fd < 0) { > c->msgid = CHECKER_MSGID_NO_FD; > return PATH_WILD; > } > - r = c->check(c); > + r = c->cls->check(c); > > return r; > } > > -int checker_selected (struct checker * c) > +int checker_selected(const struct checker *c) > { > if (!c) > return 0; > - if (!strncmp(c->name, NONE, 4)) > - return 1; > - return (c->check) ? 1 : 0; > + return c->cls != NULL; > } > > const char *checker_name(const struct checker *c) > { > - if (!c) > + if (!c || !c->cls) > return NULL; > - return c->name; > + return c->cls->name; > +} > + > +int checker_is_sync(const struct checker *c) > +{ > + return c && c->cls && c->cls->sync; > } > > static const char *generic_msg[CHECKER_LAST_GENERIC_MSGID] = { > @@ -295,8 +304,8 @@ static const char *_checker_message(const struct checker *c) > return generic_msg[c->msgid]; > > id = c->msgid - CHECKER_FIRST_MSGID; > - if (id < c->msgtable_size) > - return c->msgtable[id]; > + if (id < c->cls->msgtable_size) > + return c->cls->msgtable[id]; > return NULL; > } > > @@ -309,7 +318,7 @@ const char *checker_message(const struct checker *c) > *buf = '\0'; > else > snprintf(buf, sizeof(buf), "%s checker%s", > - c->name, msg); > + c->cls->name, msg); > return buf; > } > > @@ -320,31 +329,29 @@ void checker_clear_message (struct checker *c) > c->msgid = CHECKER_MSGID_NONE; > } > > -void checker_get (char *multipath_dir, struct checker * dst, char * name) > +void checker_get(const char *multipath_dir, struct checker *dst, > + const char *name) > { > - struct checker * src = NULL; > + struct checker_class *src = NULL; > > if (!dst) > return; > > if (name && strlen(name)) { > - src = checker_lookup(name); > + src = checker_class_lookup(name); > if (!src) > - src = add_checker(multipath_dir, name); > + src = add_checker_class(multipath_dir, name); > } > - if (!src) { > - dst->check = NULL; > + dst->cls = src; > + if (!src) > return; > - } > - dst->fd = src->fd; > - dst->sync = src->sync; > - strncpy(dst->name, src->name, CHECKER_NAME_LEN); > - dst->msgid = src->msgid; > - dst->check = src->check; > - dst->init = src->init; > - dst->free = src->free; > - dst->msgtable = src->msgtable; > - dst->msgtable_size = src->msgtable_size; > - dst->handle = NULL; > + > src->refcount++; > } > + > +int init_checkers(const char *multipath_dir) > +{ > + if (!add_checker_class(multipath_dir, DEFAULT_CHECKER)) > + return 1; > + return 0; > +} > diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h > index 98fec2c4..c46f7ffa 100644 > --- a/libmultipath/checkers.h > +++ b/libmultipath/checkers.h > @@ -116,32 +116,22 @@ enum { > CHECKER_MSGTABLE_SIZE = 100, /* max msg table size for checkers */ > }; > > +struct checker_class; > struct checker { > - struct list_head node; > - void *handle; > - int refcount; > + struct checker_class *cls; > int fd; > - int sync; > unsigned int timeout; > int disable; > - char name[CHECKER_NAME_LEN]; > short msgid; /* checker-internal extra status */ > void * context; /* store for persistent data */ > void ** mpcontext; /* store for persistent data shared > multipath-wide. Use MALLOC if > you want to stuff data in. */ > - int (*check)(struct checker *); > - int (*init)(struct checker *); /* to allocate the context */ > - void (*free)(struct checker *); /* to free the context */ > - const char**msgtable; > - short msgtable_size; > }; > > -char * checker_state_name (int); > -int init_checkers (char *); > +const char *checker_state_name(int); > +int init_checkers(const char *); > void cleanup_checkers (void); > -struct checker * add_checker (char *, char *); > -struct checker * checker_lookup (char *); > int checker_init (struct checker *, void **); > void checker_clear (struct checker *); > void checker_put (struct checker *); > @@ -152,11 +142,12 @@ void checker_set_fd (struct checker *, int); > void checker_enable (struct checker *); > void checker_disable (struct checker *); > int checker_check (struct checker *, int); > -int checker_selected (struct checker *); > +int checker_selected(const struct checker *); > +int checker_is_sync(const struct checker *); > const char *checker_name (const struct checker *); > const char *checker_message (const struct checker *); > void checker_clear_message (struct checker *c); > -void checker_get (char *, struct checker *, char *); > +void checker_get(const char *, struct checker *, const char *); > > /* Prototypes for symbols exported by path checker dynamic libraries (.so) */ > int libcheck_check(struct checker *); > diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c > index c4a0712e..1b00b775 100644 > --- a/libmultipath/checkers/directio.c > +++ b/libmultipath/checkers/directio.c > @@ -202,7 +202,7 @@ int libcheck_check (struct checker * c) > if (!ct) > return PATH_UNCHECKED; > > - ret = check_state(c->fd, ct, c->sync, c->timeout); > + ret = check_state(c->fd, ct, checker_is_sync(c), c->timeout); > > switch (ret) > { > diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c > index 8f4bdc8b..05e7bed6 100644 > --- a/libmultipath/checkers/tur.c > +++ b/libmultipath/checkers/tur.c > @@ -323,7 +323,7 @@ int libcheck_check(struct checker * c) > if (!ct) > return PATH_UNCHECKED; > > - if (c->sync) > + if (checker_is_sync(c)) > return tur_check(c->fd, c->timeout, &c->msgid); > > /* > diff --git a/libmultipath/print.c b/libmultipath/print.c > index 7b610b94..fc40b0f0 100644 > --- a/libmultipath/print.c > +++ b/libmultipath/print.c > @@ -615,7 +615,7 @@ static int > snprint_path_checker (char * buff, size_t len, const struct path * pp) > { > const struct checker * c = &pp->checker; > - return snprint_str(buff, len, c->name); > + return snprint_str(buff, len, checker_name(c)); > } > > static int > diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c > index fdb5953a..970a3b5c 100644 > --- a/libmultipath/propsel.c > +++ b/libmultipath/propsel.c > @@ -479,26 +479,27 @@ check_rdac(struct path * pp) > int select_checker(struct config *conf, struct path *pp) > { > const char *origin; > - char *checker_name; > + char *ckr_name; > struct checker * c = &pp->checker; > > if (pp->detect_checker == DETECT_CHECKER_ON) { > origin = autodetect_origin; > if (check_rdac(pp)) { > - checker_name = RDAC; > + ckr_name = RDAC; > goto out; > } else if (pp->tpgs > 0) { > - checker_name = TUR; > + ckr_name = TUR; > goto out; > } > } > - do_set(checker_name, conf->overrides, checker_name, overrides_origin); > - do_set_from_hwe(checker_name, pp, checker_name, hwe_origin); > - do_set(checker_name, conf, checker_name, conf_origin); > - do_default(checker_name, DEFAULT_CHECKER); > + do_set(checker_name, conf->overrides, ckr_name, overrides_origin); > + do_set_from_hwe(checker_name, pp, ckr_name, hwe_origin); > + do_set(checker_name, conf, ckr_name, conf_origin); > + do_default(ckr_name, DEFAULT_CHECKER); > out: > - checker_get(conf->multipath_dir, c, checker_name); > - condlog(3, "%s: path_checker = %s %s", pp->dev, c->name, origin); > + checker_get(conf->multipath_dir, c, ckr_name); > + condlog(3, "%s: path_checker = %s %s", pp->dev, > + checker_name(c), origin); > if (conf->checker_timeout) { > c->timeout = conf->checker_timeout; > condlog(3, "%s: checker timeout = %u s %s", > -- > 2.19.0 -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel