#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
/*
* libcheckers
#include <switchgroup.h>
#include <print.h>
#include <configure.h>
+#include <prio.h>
#include "main.h"
#include "pidfile.h"
pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
+int logsink;
+
/*
* global copy of vecs for use in sig handlers
*/
* remove all current maps not allowed by the
* current configuration
*/
- if (dm_flush_map(ompp->alias, DEFAULT_TARGET)) {
+ if (dm_flush_map(ompp->alias)) {
condlog(0, "%s: unable to flush devmap",
ompp->alias);
/*
}
else {
dm_lib_release();
- condlog(3, "%s devmap removed", ompp->alias);
+ condlog(2, "%s devmap removed", ompp->alias);
}
}
}
struct path *pp;
unsigned int i, j;
+ if (!mpp->pg)
+ return;
+
vector_foreach_slot (mpp->pg, pgp, i){
vector_foreach_slot (pgp->paths, pp, j){
- if (pp->state <= PATH_UNCHECKED)
+ if (pp->state == PATH_UNCHECKED ||
+ pp->state == PATH_WILD)
continue;
if ((pp->dmstate == PSTATE_FAILED ||
pp->dmstate == PSTATE_UNDEF) &&
* clear references to this map before flushing so we can ignore
* the spurious uevent we may generate with the dm_flush_map call below
*/
- if (dm_flush_map(mpp->alias, DEFAULT_TARGET)) {
+ if (dm_flush_map(mpp->alias)) {
/*
* May not really be an error -- if the map was already flushed
* from the device mapper by dmsetup(8) for instance.
}
else {
dm_lib_release();
- condlog(3, "%s: devmap removed", mpp->alias);
+ condlog(2, "%s: devmap removed", mpp->alias);
}
orphan_paths(vecs->pathvec, mpp);
- remove_map(mpp, vecs, stop_waiter_thread, 1);
+ remove_map_and_stop_waiter(mpp, vecs, 1);
return 0;
}
map_present = dm_map_present(alias);
- if (map_present && dm_type(alias, DEFAULT_TARGET) <= 0) {
+ if (map_present && dm_type(alias, TGT_MPATH) <= 0) {
condlog(4, "%s: not a multipath map", alias);
return 0;
}
/*
* now we can register the map
*/
- if (map_present && (mpp = add_map_without_path(vecs, minor, alias,
- start_waiter_thread))) {
+ if (map_present && (mpp = add_map_without_path(vecs, minor, alias))) {
sync_map_state(mpp);
- condlog(3, "%s: devmap %s added", alias, dev->kernel);
+ condlog(2, "%s: devmap %s added", alias, dev->kernel);
return 0;
}
refwwid = get_refwwid(dev->kernel, DEV_DEVMAP, vecs->pathvec);
if (refwwid) {
- r = coalesce_paths(vecs, NULL, refwwid);
+ r = coalesce_paths(vecs, NULL, refwwid, 0);
dm_lib_release();
}
if (!r)
- condlog(3, "%s: devmap %s added", alias, dev->kernel);
+ condlog(2, "%s: devmap %s added", alias, dev->kernel);
else
condlog(0, "%s: uev_add_map %s failed", alias, dev->kernel);
mpp = find_mp_by_str(vecs->mpvec, devname);
if (!mpp) {
- condlog(3, "%s: devmap not registered, can't remove",
+ condlog(2, "%s: devmap not registered, can't remove",
devname);
return 0;
}
condlog(0, "%s: failed to get path uid", devname);
return 1; /* leave path added to pathvec */
}
- if (filter_path(conf, pp)){
+ if (filter_path(conf, pp) > 0){
int i = find_slot(vecs->pathvec, (void *)pp);
if (i != -1)
vector_del_slot(vecs->pathvec, i);
start_waiter_thread(mpp, vecs))
goto out;
- condlog(3, "%s path added to devmap %s", devname, mpp->alias);
+ condlog(2, "%s path added to devmap %s", devname, mpp->alias);
return 0;
out:
- remove_map(mpp, vecs, NULL, 1);
+ remove_map(mpp, vecs, 1);
return 1;
}
{
struct multipath * mpp;
struct path * pp;
- int i;
- int rm_path = 1;
+ int i, retval = 0;
pp = find_path_by_dev(vecs->pathvec, devname);
}
/*
- * avoid referring to the map of an orphanned path
+ * avoid referring to the map of an orphaned path
*/
if ((mpp = pp->mpp)) {
+ /*
+ * transform the mp->pg vector of vectors of paths
+ * into a mp->params string to feed the device-mapper
+ */
+ if (update_mpp_paths(mpp, vecs->pathvec)) {
+ condlog(0, "%s: failed to update paths",
+ mpp->alias);
+ goto out;
+ }
+ if ((i = find_slot(mpp->paths, (void *)pp)) != -1)
+ vector_del_slot(mpp->paths, i);
/*
* remove the map IFF removing the last path
*/
- if (pathcount(mpp, PATH_WILD) > 1) {
- vector rpvec = vector_alloc();
+ if (VECTOR_SIZE(mpp->paths) == 0) {
+ char alias[WWID_SIZE];
/*
- * transform the mp->pg vector of vectors of paths
- * into a mp->params string to feed the device-mapper
+ * flush_map will fail if the device is open
*/
- update_mpp_paths(mpp, vecs->pathvec);
- if ((i = find_slot(mpp->paths, (void *)pp)) != -1)
- vector_del_slot(mpp->paths, i);
-
- if (VECTOR_SIZE(mpp->paths) == 0) {
- char alias[WWID_SIZE];
-
- /*
- * flush_map will fail if the device is open
- */
- strncpy(alias, mpp->alias, WWID_SIZE);
- if (flush_map(mpp, vecs))
- rm_path = 0;
- else
- condlog(3, "%s: removed map after removing"
- " multiple paths", alias);
- }
- else {
- if (setup_map(mpp)) {
- condlog(0, "%s: failed to setup map for"
- " removal of path %s", mpp->alias, devname);
- free_pathvec(rpvec, KEEP_PATHS);
- goto out;
- }
- /*
- * reload the map
- */
- mpp->action = ACT_RELOAD;
- if (domap(mpp) <= 0) {
- condlog(0, "%s: failed in domap for "
- "removal of path %s",
- mpp->alias, devname);
- /*
- * Delete path from pathvec so that
- * update_mpp_paths wont find it later
- * when/if another path is removed.
- */
- if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
- vector_del_slot(vecs->pathvec, i);
- free_path(pp);
- return 1;
- }
- /*
- * update our state from kernel
- */
- if (setup_multipath(vecs, mpp)) {
- free_pathvec(rpvec, KEEP_PATHS);
- goto out;
- }
- sync_map_state(mpp);
-
- condlog(3, "%s: path removed from map %s",
- devname, mpp->alias);
+ strncpy(alias, mpp->alias, WWID_SIZE);
+ if (!flush_map(mpp, vecs)) {
+ condlog(2, "%s: removed map after"
+ " removing all paths",
+ alias);
+ free_path(pp);
+ return 0;
}
- free_pathvec(rpvec, KEEP_PATHS);
+ /*
+ * Not an error, continue
+ */
}
- else {
- char alias[WWID_SIZE];
+ if (setup_map(mpp)) {
+ condlog(0, "%s: failed to setup map for"
+ " removal of path %s", mpp->alias,
+ devname);
+ goto out;
+ }
+ /*
+ * reload the map
+ */
+ mpp->action = ACT_RELOAD;
+ if (domap(mpp) <= 0) {
+ condlog(0, "%s: failed in domap for "
+ "removal of path %s",
+ mpp->alias, devname);
+ retval = 1;
+ } else {
/*
- * flush_map will fail if the device is open
+ * update our state from kernel
*/
- strncpy(alias, mpp->alias, WWID_SIZE);
- if (flush_map(mpp, vecs))
- rm_path = 0;
- else
- condlog(3, "%s: removed map", alias);
+ if (setup_multipath(vecs, mpp)) {
+ goto out;
+ }
+ sync_map_state(mpp);
+
+ condlog(2, "%s: path removed from map %s",
+ devname, mpp->alias);
}
}
- if (rm_path) {
- if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
- vector_del_slot(vecs->pathvec, i);
- free_path(pp);
- }
+ if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
+ vector_del_slot(vecs->pathvec, i);
- return 0;
+ free_path(pp);
+
+ return retval;
out:
- remove_map(mpp, vecs, stop_waiter_thread, 1);
+ remove_map_and_stop_waiter(mpp, vecs, 1);
return 1;
}
struct multipath * mpp;
unsigned int i;
- if (dm_get_maps(vecs->mpvec, "multipath"))
+ if (dm_get_maps(vecs->mpvec))
return 1;
vector_foreach_slot (vecs->mpvec, mpp, i)
return NULL;
set_handler_callback(LIST+PATHS, cli_list_paths);
+ set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt);
set_handler_callback(LIST+MAPS, cli_list_maps);
+ set_handler_callback(LIST+STATUS, cli_list_status);
set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status);
set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats);
set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
set_handler_callback(LIST+CONFIG, cli_list_config);
set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
set_handler_callback(LIST+DEVICES, cli_list_devices);
+ set_handler_callback(LIST+WILDCARDS, cli_list_wildcards);
set_handler_callback(ADD+PATH, cli_add_path);
set_handler_callback(DEL+PATH, cli_del_path);
set_handler_callback(ADD+MAP, cli_add_map);
vector_foreach_slot (vecs->mpvec, mpp, i) {
if (mpp && mpp->alias && !dm_map_present(mpp->alias)) {
condlog(2, "%s: remove dead map", mpp->alias);
- remove_map(mpp, vecs, stop_waiter_thread, 1);
+ remove_map_and_stop_waiter(mpp, vecs, 1);
i--;
}
}
lock(vecs->lock);
condlog(4, "tick");
- vector_foreach_slot (vecs->pathvec, pp, i) {
- check_path(vecs, pp);
+ if (vecs->pathvec) {
+ vector_foreach_slot (vecs->pathvec, pp, i) {
+ check_path(vecs, pp);
+ }
+ }
+ if (vecs->mpvec) {
+ defered_failback_tick(vecs->mpvec);
+ retry_count_tick(vecs->mpvec);
}
- defered_failback_tick(vecs->mpvec);
- retry_count_tick(vecs->mpvec);
-
if (count)
count--;
else {
path_discovery(vecs->pathvec, conf, DI_ALL);
vector_foreach_slot (vecs->pathvec, pp, i){
- if (filter_path(conf, pp)){
+ if (filter_path(conf, pp) > 0){
vector_del_slot(vecs->pathvec, i);
free_path(pp);
i--;
/*
* create new set of maps & push changed ones into dm
*/
- if (coalesce_paths(vecs, mpvec, NULL))
+ if (coalesce_paths(vecs, mpvec, NULL, 0))
return 1;
/*
/*
* purge dm of old maps
*/
- remove_maps(vecs, NULL);
+ remove_maps(vecs);
/*
* save new set of maps formed by considering current path state
* free old map and path vectors ... they use old conf state
*/
if (VECTOR_SIZE(vecs->mpvec))
- remove_maps(vecs, stop_waiter_thread);
+ remove_maps_and_stop_waiters(vecs);
if (VECTOR_SIZE(vecs->pathvec))
free_pathvec(vecs->pathvec, FREE_PATHS);
if (load_config(DEFAULT_CONFIGFILE))
exit(1);
+ if (init_checkers()) {
+ condlog(0, "failed to initialize checkers");
+ exit(1);
+ }
+ if (init_prio()) {
+ condlog(0, "failed to initialize prioritizers");
+ exit(1);
+ }
+
setlogmask(LOG_UPTO(conf->verbosity + 3));
/*
conf->max_checkint = MAX_CHECKINT(conf->checkint);
}
+ if (conf->max_fds) {
+ struct rlimit fd_limit;
+ if (conf->max_fds > 0) {
+ fd_limit.rlim_cur = conf->max_fds;
+ fd_limit.rlim_max = conf->max_fds;
+ }
+ else {
+ fd_limit.rlim_cur = RLIM_INFINITY;
+ fd_limit.rlim_max = RLIM_INFINITY;
+ }
+ if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0)
+ condlog(0, "can't set open fds limit to %d : %s\n",
+ conf->max_fds, strerror(errno));
+ }
+
if (pidfile_create(DEFAULT_PIDFILE, getpid())) {
if (logsink)
log_thread_stop();
* exit path
*/
lock(vecs->lock);
- remove_maps(vecs, stop_waiter_thread);
+ remove_maps_and_stop_waiters(vecs);
free_pathvec(vecs->pathvec, FREE_PATHS);
pthread_cancel(check_thr);
vecs->lock = NULL;
FREE(vecs);
vecs = NULL;
- free_config(conf);
- conf = NULL;
condlog(2, "--------shut down-------");
dm_lib_release();
dm_lib_exit();
+ /*
+ * Freeing config must be done after condlog() and dm_lib_exit(),
+ * because logging functions like dlog() and dm_write_log()
+ * reference the config.
+ */
+ free_config(conf);
+ conf = NULL;
+
#ifdef _DEBUG_
dbg_free_final(NULL);
#endif