@@ -27,6 +27,7 @@ struct checker_class {
void (*reset)(void); /* to reset the global variables */
void *(*thread)(void *); /* async thread entry point */
int (*pending)(struct checker *); /* to recheck pending paths */
+ bool (*need_wait)(struct checker *); /* checker needs waiting for */
const char **msgtable;
short msgtable_size;
};
@@ -182,7 +183,8 @@ static struct checker_class *add_checker_class(const char *name)
c->reset = (void (*)(void)) dlsym(c->handle, "libcheck_reset");
c->thread = (void *(*)(void*)) dlsym(c->handle, "libcheck_thread");
c->pending = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_pending");
- /* These 4 functions can be NULL. call dlerror() to clear out any
+ c->need_wait = (bool (*)(struct checker *)) dlsym(c->handle, "libcheck_need_wait");
+ /* These 5 functions can be NULL. call dlerror() to clear out any
* error string */
dlerror();
@@ -313,6 +315,14 @@ int checker_get_state(struct checker *c)
return c->path_state;
}
+bool checker_need_wait(struct checker *c)
+{
+ if (!c || !c->cls || c->path_state != PATH_PENDING ||
+ !c->cls->need_wait)
+ return false;
+ return c->cls->need_wait(c);
+}
+
void checker_check (struct checker * c, int path_state)
{
if (!c)
@@ -2,6 +2,7 @@
#define CHECKERS_H_INCLUDED
#include <pthread.h>
+#include <stdbool.h>
#include "list.h"
#include "defaults.h"
@@ -171,6 +172,7 @@ struct checker_context {
int start_checker_thread (pthread_t *thread, const pthread_attr_t *attr,
struct checker_context *ctx);
int checker_get_state(struct checker *c);
+bool checker_need_wait(struct checker *c);
void checker_check (struct checker *, int);
int checker_is_sync(const struct checker *);
const char *checker_name (const struct checker *);
@@ -191,7 +193,7 @@ void *libcheck_thread(struct checker_context *ctx);
void libcheck_reset(void);
int libcheck_mp_init(struct checker *);
int libcheck_pending(struct checker *c);
-
+bool libcheck_need_wait(struct checker *c);
/*
* msgid => message map.
@@ -65,6 +65,7 @@ struct directio_context {
struct aio_group *aio_grp;
struct async_req *req;
struct timespec endtime;
+ bool checked_state;
};
static struct aio_group *
@@ -295,6 +296,7 @@ check_pending(struct directio_context *ct, struct timespec endtime)
int r;
struct timespec currtime, timeout;
+ ct->checked_state = true;
while(1) {
get_monotonic_time(&currtime);
timespecsub(&endtime, &currtime, &timeout);
@@ -327,6 +329,7 @@ check_state(int fd, struct directio_context *ct, int sync, int timeout_secs)
LOG(4, "called in synchronous mode");
if (ct->running) {
+ ct->checked_state = true;
if (ct->req->state != PATH_PENDING) {
ct->running = 0;
return ct->req->state;
@@ -346,6 +349,7 @@ check_state(int fd, struct directio_context *ct, int sync, int timeout_secs)
get_monotonic_time(&ct->endtime);
ct->endtime.tv_nsec += 1000 * 1000;
normalize_timespec(&ct->endtime);
+ ct->checked_state = false;
}
ct->running++;
if (!sync)
@@ -386,6 +390,13 @@ static void set_msgid(struct checker *c, int state)
}
}
+bool libcheck_need_wait(struct checker *c)
+{
+ struct directio_context *ct = (struct directio_context *)c->context;
+ return (ct && ct->running && ct->req->state == PATH_PENDING &&
+ !ct->checked_state);
+}
+
int libcheck_pending(struct checker *c)
{
int rc;
@@ -59,6 +59,7 @@ struct tur_checker_context {
struct checker_context ctx;
unsigned int nr_timeouts;
struct timespec endtime;
+ bool checked_state;
};
int libcheck_init (struct checker * c)
@@ -351,9 +352,17 @@ int check_pending(struct checker *c)
ct->thread = 0;
}
+ ct->checked_state = true;
return tur_status;
}
+bool libcheck_need_wait(struct checker *c)
+{
+ struct tur_checker_context *ct = c->context;
+ return (ct && ct->thread && uatomic_read(&ct->running) != 0 &&
+ !ct->checked_state);
+}
+
int libcheck_pending(struct checker *c)
{
struct tur_checker_context *ct = c->context;
@@ -381,6 +390,7 @@ int libcheck_check(struct checker * c)
* Async mode
*/
if (ct->thread) {
+ ct->checked_state = true;
if (tur_check_async_timeout(c)) {
int running = uatomic_xchg(&ct->running, 0);
if (running) {
@@ -463,6 +473,7 @@ int libcheck_check(struct checker * c)
pthread_mutex_unlock(&ct->lock);
ct->fd = c->fd;
ct->timeout = c->timeout;
+ ct->checked_state = false;
uatomic_add(&ct->holders, 1);
uatomic_set(&ct->running, 1);
tur_set_async_timeout(c);
Add a new optional checker class function, libcheck_need_wait() and a new function to call it, checker_need_wait(). This can be used to see if a path_checker is currently running. This will be used to determine if there are pending checkers that need to be waited for. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> --- libmultipath/checkers.c | 12 +++++++++++- libmultipath/checkers.h | 4 +++- libmultipath/checkers/directio.c | 11 +++++++++++ libmultipath/checkers/tur.c | 11 +++++++++++ 4 files changed, 36 insertions(+), 2 deletions(-)