int get_alua_info(int fd) { int rc; int tpg; rc = get_target_port_group_support(fd); if (rc < 0) return -ALUA_PRIO_TPGS_FAILED; if (rc == TPGS_NONE) return -ALUA_PRIO_NOT_SUPPORTED; tpg = get_target_port_group(fd); if (tpg < 0) return -ALUA_PRIO_RTPG_FAILED; condlog(3, "reported target port group is %i", tpg); rc = get_asymmetric_access_state(fd, tpg); if (rc < 0) return -ALUA_PRIO_GETAAS_FAILED; condlog(3, "aas = %02x [%s]%s", rc, aas_print_string(rc), (rc & 0x80) ? " [preferred]" : ""); return rc; }
int select_no_path_retry(struct config *conf, struct multipath *mp) { char *origin = NULL; char buff[12]; if (mp->flush_on_last_del == FLUSH_IN_PROGRESS) { condlog(0, "flush_on_last_del in progress"); mp->no_path_retry = NO_PATH_RETRY_FAIL; return 0; } mp_set_mpe(no_path_retry); mp_set_ovr(no_path_retry); mp_set_hwe(no_path_retry); mp_set_conf(no_path_retry); out: print_no_path_retry(buff, 12, &mp->no_path_retry); if (origin) condlog(3, "%s: no_path_retry = %s %s", mp->alias, buff, origin); else if (mp->no_path_retry != NO_PATH_RETRY_UNDEF) condlog(3, "%s: no_path_retry = %s (inherited setting)", mp->alias, buff); else condlog(3, "%s: no_path_retry = undef (setting: multipath internal)", mp->alias); return 0; }
/* Data initialization */ int process_file(struct config *conf, char *file) { int r; FILE *stream; if (!conf->keywords) { condlog(0, "No keywords alocated"); return 1; } stream = fopen(file, "r"); if (!stream) { condlog(0, "couldn't open configuration file '%s': %s", file, strerror(errno)); return 1; } /* Stream handling */ line_nr = 0; r = process_stream(conf, stream, conf->keywords, file); fclose(stream); //free_keywords(keywords); return r; }
int select_checker(struct config *conf, struct path *pp) { char *origin, *checker_name; struct checker * c = &pp->checker; do_set(checker_name, conf->overrides, checker_name, "(setting: multipath.conf overrides section)"); do_set(checker_name, pp->hwe, checker_name, "(setting: array configuration)"); do_set(checker_name, conf, checker_name, "(setting: multipath.conf defaults/devices section)"); do_default(checker_name, DEFAULT_CHECKER); out: checker_get(conf->multipath_dir, c, checker_name); condlog(3, "%s: path_checker = %s %s", pp->dev, c->name, origin); if (conf->checker_timeout) { c->timeout = conf->checker_timeout; condlog(3, "%s: checker timeout = %u s (setting: multipath.conf defaults/devices section)", pp->dev, c->timeout); } else if (sysfs_get_timeout(pp, &c->timeout) > 0) condlog(3, "%s: checker timeout = %u ms (setting: kernel sysfs)", pp->dev, c->timeout); else { c->timeout = DEF_TIMEOUT; condlog(3, "%s: checker timeout = %u ms (setting: multipath internal)", pp->dev, c->timeout); } return 0; }
int start_waiter_thread (struct multipath *mpp, struct vectors *vecs) { struct event_thread *wp; if (!mpp) return 0; wp = alloc_waiter(); if (!wp) goto out; mpp->waiter = (void *)wp; strncpy(wp->mapname, mpp->alias, WWID_SIZE); wp->vecs = vecs; wp->mpp = mpp; if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) { condlog(0, "%s: cannot create event checker", wp->mapname); goto out1; } condlog(2, "%s: event checker started", wp->mapname); return 0; out1: free_waiter(wp); mpp->waiter = NULL; out: condlog(0, "failed to start waiter thread"); return 1; }
int select_minio_bio (struct multipath * mp) { if (mp->mpe && mp->mpe->minio) { mp->minio = mp->mpe->minio; condlog(3, "%s: minio = %i (LUN setting)", mp->alias, mp->minio); return 0; } if (mp->hwe && mp->hwe->minio) { mp->minio = mp->hwe->minio; condlog(3, "%s: minio = %i (controller setting)", mp->alias, mp->minio); return 0; } if (conf->minio) { mp->minio = conf->minio; condlog(3, "%s: minio = %i (config file default)", mp->alias, mp->minio); return 0; } mp->minio = DEFAULT_MINIO; condlog(3, "%s: minio = %i (internal default)", mp->alias, mp->minio); return 0; }
extern int select_flush_on_last_del(struct multipath *mp) { if (mp->flush_on_last_del == FLUSH_IN_PROGRESS) return 0; if (mp->mpe && mp->mpe->flush_on_last_del != FLUSH_UNDEF) { mp->flush_on_last_del = mp->mpe->flush_on_last_del; condlog(3, "%s: flush_on_last_del = %i (multipath setting)", mp->alias, mp->flush_on_last_del); return 0; } if (mp->hwe && mp->hwe->flush_on_last_del != FLUSH_UNDEF) { mp->flush_on_last_del = mp->hwe->flush_on_last_del; condlog(3, "%s: flush_on_last_del = %i (controler setting)", mp->alias, mp->flush_on_last_del); return 0; } if (conf->flush_on_last_del != FLUSH_UNDEF) { mp->flush_on_last_del = conf->flush_on_last_del; condlog(3, "%s: flush_on_last_del = %i (config file default)", mp->alias, mp->flush_on_last_del); return 0; } mp->flush_on_last_del = FLUSH_UNDEF; condlog(3, "%s: flush_on_last_del = DISABLED (internal default)", mp->alias); return 0; }
extern int select_selector (struct multipath * mp) { if (mp->mpe && mp->mpe->selector) { mp->selector = mp->mpe->selector; condlog(3, "%s: selector = %s (LUN setting)", mp->alias, mp->selector); return 0; } if (mp->hwe && mp->hwe->selector) { mp->selector = mp->hwe->selector; condlog(3, "%s: selector = %s (controller setting)", mp->alias, mp->selector); return 0; } if (conf->selector) { mp->selector = conf->selector; condlog(3, "%s: selector = %s (config file default)", mp->alias, mp->selector); return 0; } mp->selector = set_default(DEFAULT_SELECTOR); condlog(3, "%s: selector = %s (internal default)", mp->alias, mp->selector); return 0; }
void *tur_thread(void *ctx) { struct checker *c = ctx; struct tur_checker_context *ct = c->context; int state; condlog(3, "%d:%d: tur checker starting up", TUR_DEVT(ct)); /* This thread can be canceled, so setup clean up */ tur_thread_cleanup_push(ct) /* TUR checker start up */ pthread_mutex_lock(&ct->lock); ct->state = PATH_PENDING; pthread_mutex_unlock(&ct->lock); state = tur_check(c); /* TUR checker done */ pthread_mutex_lock(&ct->lock); ct->state = state; pthread_mutex_unlock(&ct->lock); pthread_cond_signal(&ct->active); condlog(3, "%d:%d: tur checker finished, state %s", TUR_DEVT(ct), checker_state_name(state)); tur_thread_cleanup_pop(ct); return ((void *)0); }
extern int select_pgfailback (struct multipath * mp) { if (mp->mpe && mp->mpe->pgfailback != FAILBACK_UNDEF) { mp->pgfailback = mp->mpe->pgfailback; condlog(3, "%s: pgfailback = %i (LUN setting)", mp->alias, mp->pgfailback); return 0; } if (mp->hwe && mp->hwe->pgfailback != FAILBACK_UNDEF) { mp->pgfailback = mp->hwe->pgfailback; condlog(3, "%s: pgfailback = %i (controller setting)", mp->alias, mp->pgfailback); return 0; } if (conf->pgfailback != FAILBACK_UNDEF) { mp->pgfailback = conf->pgfailback; condlog(3, "%s: pgfailback = %i (config file default)", mp->alias, mp->pgfailback); return 0; } mp->pgfailback = DEFAULT_FAILBACK; condlog(3, "%s: pgfailover = %i (internal default)", mp->alias, mp->pgfailback); return 0; }
int should_multipath(struct path *pp1, vector pathvec) { int i; struct path *pp2; condlog(4, "checking if %s should be multipathed", pp1->dev); vector_foreach_slot(pathvec, pp2, i) { if (pp1->dev == pp2->dev) continue; if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) { condlog(3, "found multiple paths with wwid %s, " "multipathing %s", pp1->wwid, pp1->dev); return 1; } } if (check_wwids_file(pp1->wwid, 0) < 0) { condlog(3, "wwid %s not in wwids file, skipping %s", pp1->wwid, pp1->dev); return 0; } condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid, pp1->dev); return 1; }
static int write_out_wwid(int fd, char *wwid) { int ret; off_t offset; char buf[WWID_SIZE + 3]; ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid); if (ret >= (WWID_SIZE + 3) || ret < 0){ condlog(0, "can't format wwid for writing (%d) : %s", ret, strerror(errno)); return -1; } offset = lseek(fd, 0, SEEK_END); if (offset < 0) { condlog(0, "can't seek to the end of wwids file : %s", strerror(errno)); return -1; } if (write_all(fd, buf, strlen(buf)) != strlen(buf)) { condlog(0, "cannot write wwid to wwids file : %s", strerror(errno)); if (ftruncate(fd, offset)) condlog(0, "cannot truncate failed wwid write : %s", strerror(errno)); return -1; } return 1; }
extern int select_retain_hwhandler (struct multipath * mp) { unsigned int minv_dm_retain[3] = {1, 5, 0}; if (!VERSION_GE(conf->version, minv_dm_retain)) { mp->retain_hwhandler = RETAIN_HWHANDLER_OFF; condlog(3, "%s: retain_attached_hw_hander disabled (requires kernel version >= 1.5.0)", mp->alias); return 0; } if (mp->hwe && mp->hwe->retain_hwhandler) { mp->retain_hwhandler = mp->hwe->retain_hwhandler; condlog(3, "%s: retain_attached_hw_handler = %d (controller default)", mp->alias, mp->retain_hwhandler); return 0; } if (conf->retain_hwhandler) { mp->retain_hwhandler = conf->retain_hwhandler; condlog(3, "%s: retain_attached_hw_handler = %d (config file default)", mp->alias, mp->retain_hwhandler); return 0; } mp->retain_hwhandler = 0; condlog(3, "%s: retain_attached_hw_handler = %d (compiled in default)", mp->alias, mp->retain_hwhandler); return 0; }
static int dm_lib_prereq (void) { char version[64]; int v[3]; #if defined(LIBDM_API_DEFERRED) int minv[3] = {1, 2, 89}; #elif defined(DM_SUBSYSTEM_UDEV_FLAG0) int minv[3] = {1, 2, 82}; #elif defined(LIBDM_API_COOKIE) int minv[3] = {1, 2, 38}; #else int minv[3] = {1, 2, 8}; #endif dm_get_library_version(version, sizeof(version)); condlog(3, "libdevmapper version %s", version); if (sscanf(version, "%d.%d.%d ", &v[0], &v[1], &v[2]) != 3) { condlog(0, "invalid libdevmapper version %s", version); return 1; } if VERSION_GE(v, minv) return 0; condlog(0, "libdevmapper version must be >= %d.%.2d.%.2d", minv[0], minv[1], minv[2]); return 1; }
/* * selectors : * traverse the configuration layers from most specific to most generic * stop at first explicit setting found */ extern int select_rr_weight (struct multipath * mp) { if (mp->mpe && mp->mpe->rr_weight) { mp->rr_weight = mp->mpe->rr_weight; condlog(3, "%s: rr_weight = %i (LUN setting)", mp->alias, mp->rr_weight); return 0; } if (mp->hwe && mp->hwe->rr_weight) { mp->rr_weight = mp->hwe->rr_weight; condlog(3, "%s: rr_weight = %i (controller setting)", mp->alias, mp->rr_weight); return 0; } if (conf->rr_weight) { mp->rr_weight = conf->rr_weight; condlog(3, "%s: rr_weight = %i (config file default)", mp->alias, mp->rr_weight); return 0; } mp->rr_weight = RR_WEIGHT_NONE; condlog(3, "%s: rr_weight = %i (internal default)", mp->alias, mp->rr_weight); return 0; }
extern int select_fast_io_fail(struct multipath *mp) { if (mp->hwe && mp->hwe->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { mp->fast_io_fail = mp->hwe->fast_io_fail; if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF) condlog(3, "%s: fast_io_fail_tmo = off " "(controller setting)", mp->alias); else condlog(3, "%s: fast_io_fail_tmo = %d " "(controller setting)", mp->alias, mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail); return 0; } if (conf->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { mp->fast_io_fail = conf->fast_io_fail; if (mp->fast_io_fail == MP_FAST_IO_FAIL_OFF) condlog(3, "%s: fast_io_fail_tmo = off " "(config file default)", mp->alias); else condlog(3, "%s: fast_io_fail_tmo = %d " "(config file default)", mp->alias, mp->fast_io_fail == MP_FAST_IO_FAIL_ZERO ? 0 : mp->fast_io_fail); return 0; } mp->fast_io_fail = MP_FAST_IO_FAIL_UNSET; return 0; }
extern int dm_suspend_and_flush_map (const char * mapname) { int s = 0, queue_if_no_path = 0; unsigned long long mapsize; char params[PARAMS_SIZE] = {0}; if (!dm_is_mpath(mapname)) return 0; /* nothing to do */ if (!dm_get_map(mapname, &mapsize, params)) { if (strstr(params, "queue_if_no_path")) queue_if_no_path = 1; } if (queue_if_no_path) s = dm_queue_if_no_path((char *)mapname, 0); /* Leave queue_if_no_path alone if unset failed */ if (s) queue_if_no_path = 0; else s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0); if (!dm_flush_map(mapname)) { condlog(4, "multipath map %s removed", mapname); return 0; } condlog(2, "failed to remove multipath map %s", mapname); dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0); if (queue_if_no_path) s = dm_queue_if_no_path((char *)mapname, 1); return 1; }
extern int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove) { int r; if (!dm_is_mpath(mapname)) return 0; /* nothing to do */ /* If you aren't doing a deferred remove, make sure that no * devices are in use */ if (!do_deferred(deferred_remove) && partmap_in_use(mapname, NULL)) return 1; if (dm_remove_partmaps(mapname, need_sync, deferred_remove)) return 1; if (!do_deferred(deferred_remove) && dm_get_opencount(mapname)) { condlog(2, "%s: map in use", mapname); return 1; } r = dm_device_remove(mapname, need_sync, deferred_remove); if (r) { if (do_deferred(deferred_remove) && dm_map_present(mapname)) { condlog(4, "multipath map %s remove deferred", mapname); return 2; } condlog(4, "multipath map %s removed", mapname); return 0; } return 1; }
extern int dm_addmap_create (struct multipath *mpp, char * params) { int ro; for (ro = 0; ro <= 1; ro++) { int err; if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, ro)) return 1; /* * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD. * Failing the second part leaves an empty map. Clean it up. */ err = errno; if (dm_map_present(mpp->alias)) { condlog(3, "%s: failed to load map (a path might be in use)", mpp->alias); dm_flush_map_nosync(mpp->alias); } if (err != EROFS) { condlog(3, "%s: failed to load map, error %d", mpp->alias, err); break; } } return 0; }
extern int select_features (struct multipath * mp) { struct mpentry * mpe; char *origin; if ((mpe = find_mpe(mp->wwid)) && mpe->features) { mp->features = STRDUP(mpe->features); origin = "LUN setting"; } else if (mp->hwe && mp->hwe->features) { mp->features = STRDUP(mp->hwe->features); origin = "controller setting"; } else if (conf->features) { mp->features = STRDUP(conf->features); origin = "config file default"; } else { mp->features = set_default(DEFAULT_FEATURES); origin = "internal default"; } condlog(3, "%s: features = %s (%s)", mp->alias, mp->features, origin); if (strstr(mp->features, "queue_if_no_path")) { if (mp->no_path_retry == NO_PATH_RETRY_UNDEF) mp->no_path_retry = NO_PATH_RETRY_QUEUE; else if (mp->no_path_retry == NO_PATH_RETRY_FAIL) { condlog(1, "%s: config error, overriding 'no_path_retry' value", mp->alias); mp->no_path_retry = NO_PATH_RETRY_QUEUE; } } return 0; }
int remove_wwid(char *wwid) { int fd, len, can_write; char *str; int ret = -1; len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */ str = malloc(len); if (str == NULL) { condlog(0, "can't allocate memory to remove wwid : %s", strerror(errno)); return -1; } if (snprintf(str, len, "/%s/\n", wwid) >= len) { condlog(0, "string overflow trying to remove wwid"); goto out; } condlog(3, "removing line '%s' from wwids file", str); fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); if (fd < 0) goto out; if (!can_write) { condlog(0, "cannot remove wwid. wwids file is read-only"); goto out_file; } ret = do_remove_wwid(fd, str); out_file: close(fd); out: free(str); return ret; }
void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs) { if (mpp->waiter == (pthread_t)0) { condlog(3, "%s: event checker thread already stopped", mpp->alias); return; } condlog(2, "%s: stop event checker thread (%lu)", mpp->alias, mpp->waiter); pthread_kill(mpp->waiter, SIGUSR1); mpp->waiter = (pthread_t)0; }
void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs) { struct event_thread *wp = (struct event_thread *)mpp->waiter; pthread_t thread; if (!wp) { condlog(3, "%s: no waiter thread", mpp->alias); return; } thread = wp->thread; condlog(2, "%s: stop event checker thread (%lu)", wp->mapname, thread); pthread_kill(thread, SIGUSR1); }
int remember_wwid(char *wwid) { int ret = check_wwids_file(wwid, 1); if (ret < 0){ condlog(3, "failed writing wwid %s to wwids file", wwid); return -1; } if (ret == 1) condlog(3, "wrote wwid %s to wwids file", wwid); else condlog(4, "wwid %s already in wwids file", wwid); return 0; }
int getprio (struct path * pp, char * args) { int rc; int aas; int priopath; if (pp->fd < 0) return -ALUA_PRIO_NO_INFORMATION; rc = get_alua_info(pp->fd); if (rc >= 0) { aas = (rc & 0x0f); priopath = (rc & 0x80); switch(aas) { case AAS_OPTIMIZED: rc = 50; break; case AAS_NON_OPTIMIZED: rc = 10; break; case AAS_LBA_DEPENDENT: rc = 5; break; case AAS_STANDBY: rc = 1; break; default: rc = 0; } if (priopath && aas != AAS_OPTIMIZED) rc += 80; } else { switch(-rc) { case ALUA_PRIO_NOT_SUPPORTED: condlog(0, "%s: alua not supported", pp->dev); break; case ALUA_PRIO_RTPG_FAILED: condlog(0, "%s: couldn't get target port group", pp->dev); break; case ALUA_PRIO_GETAAS_FAILED: condlog(0, "%s: couldn't get asymmetric access state", pp->dev); break; case ALUA_PRIO_TPGS_FAILED: condlog(3, "%s: couldn't get supported alua states", pp->dev); break; } } return rc; }
int replace_wwids(vector mp) { int i, fd, can_write; struct multipath * mpp; size_t len; int ret = -1; fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); if (fd < 0) goto out; if (!can_write) { condlog(0, "cannot replace wwids. wwids file is read-only"); goto out_file; } if (ftruncate(fd, 0) < 0) { condlog(0, "cannot truncate wwids file : %s", strerror(errno)); goto out_file; } if (lseek(fd, 0, SEEK_SET) < 0) { condlog(0, "cannot seek to the start of the file : %s", strerror(errno)); goto out_file; } len = strlen(WWIDS_FILE_HEADER); if (write_all(fd, WWIDS_FILE_HEADER, len) != len) { condlog(0, "Can't write wwid file header : %s", strerror(errno)); /* cleanup partially written header */ if (ftruncate(fd, 0) < 0) condlog(0, "Cannot truncate header : %s", strerror(errno)); goto out_file; } if (!mp || !mp->allocated) { ret = 0; goto out_file; } vector_foreach_slot(mp, mpp, i) { if (write_out_wwid(fd, mpp->wwid) < 0) goto out_file; } ret = 0; out_file: close(fd); out: return ret; }
extern int select_pgpolicy (struct multipath * mp) { char pgpolicy_name[POLICY_NAME_SIZE]; if (conf->pgpolicy_flag > 0) { mp->pgpolicy = conf->pgpolicy_flag; mp->pgpolicyfn = pgpolicies[mp->pgpolicy]; get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE, mp->pgpolicy); condlog(3, "%s: pgpolicy = %s (cmd line flag)", mp->alias, pgpolicy_name); return 0; } if (mp->mpe && mp->mpe->pgpolicy > 0) { mp->pgpolicy = mp->mpe->pgpolicy; mp->pgpolicyfn = pgpolicies[mp->pgpolicy]; get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE, mp->pgpolicy); condlog(3, "%s: pgpolicy = %s (LUN setting)", mp->alias, pgpolicy_name); return 0; } if (mp->hwe && mp->hwe->pgpolicy > 0) { mp->pgpolicy = mp->hwe->pgpolicy; mp->pgpolicyfn = pgpolicies[mp->pgpolicy]; get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE, mp->pgpolicy); condlog(3, "%s: pgpolicy = %s (controller setting)", mp->alias, pgpolicy_name); return 0; } if (conf->pgpolicy > 0) { mp->pgpolicy = conf->pgpolicy; mp->pgpolicyfn = pgpolicies[mp->pgpolicy]; get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE, mp->pgpolicy); condlog(3, "%s: pgpolicy = %s (config file default)", mp->alias, pgpolicy_name); return 0; } mp->pgpolicy = DEFAULT_PGPOLICY; mp->pgpolicyfn = pgpolicies[mp->pgpolicy]; get_pgpolicy_name(pgpolicy_name, POLICY_NAME_SIZE, mp->pgpolicy); condlog(3, "%s: pgpolicy = %s (internal default)", mp->alias, pgpolicy_name); return 0; }
static void dm_write_log (int level, const char *file, int line, const char *f, ...) { va_list ap; int thres; if (level > 6) level = 6; thres = (conf) ? conf->verbosity : 0; if (thres <= 3 || level > thres) return; va_start(ap, f); if (!logsink) { time_t t = time(NULL); struct tm *tb = localtime(&t); char buff[16]; strftime(buff, sizeof(buff), "%b %d %H:%M:%S", tb); buff[sizeof(buff)-1] = '\0'; fprintf(stdout, "%s | ", buff); fprintf(stdout, "libdevmapper: %s(%i): ", file, line); vfprintf(stdout, f, ap); fprintf(stdout, "\n"); } else { condlog(level, "libdevmapper: %s(%i): ", file, line); log_safe(level + 3, f, ap); } va_end(ap); return; }
int dm_message(const char * mapname, char * message) { int r = 1; struct dm_task *dmt; if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG))) return 1; if (!dm_task_set_name(dmt, mapname)) goto out; if (!dm_task_set_sector(dmt, 0)) goto out; if (!dm_task_set_message(dmt, message)) goto out; dm_task_no_open_count(dmt); if (!dm_task_run(dmt)) goto out; r = 0; out: if (r) condlog(0, "DM message failed [%s]", message); dm_task_destroy(dmt); return r; }
void free_waiter (void *data) { sigset_t old; struct event_thread *wp = (struct event_thread *)data; /* * indicate in mpp that the wp is already freed storage */ block_signal(SIGHUP, &old); lock(wp->vecs->lock); if (wp->mpp) /* * be careful, mpp may already be freed -- null if so */ wp->mpp->waiter = NULL; else /* * This is OK condition during shutdown. */ condlog(3, "free_waiter, mpp freed before wp=%p (%s).", wp, wp->mapname); unlock(wp->vecs->lock); pthread_sigmask(SIG_SETMASK, &old, NULL); if (wp->dmt) dm_task_destroy(wp->dmt); FREE(wp); }