VISIBLE = 2
};
+typedef enum {
+ ACTIVATE,
+ DEACTIVATE
+} activate_t;
+
+typedef enum {
+ SUSPEND,
+ RESUME
+} suspend_t;
+
struct dev_layer {
char *name;
if (_get_flag(dl, VISIBLE))
fs_add_lv(dl->lv, dl->name);
+ _clear_flag(dl, DIRTY);
+
return r;
}
int r;
struct dm_task *dmt;
- log_verbose("Removing %s", dl->name);
+ if (_get_flag(dl, VISIBLE))
+ log_verbose("Removing %s", dl->name);
+ else
+ log_very_verbose("Removing %s", dl->name);
+
if (!(dmt = _setup_task(dl->name, DM_DEVICE_REMOVE))) {
stack;
return 0;
}
- if (!(r = dm_task_run(dmt)))
- log_error("Couldn't remove device '%s'", dl->name);
- else
+ /* Suppress error message if it's still in use - we'll log it later */
+ log_suppress(1);
+
+ if ((r = dm_task_run(dmt)))
dl->info.exists = 0;
+ log_suppress(0);
+
dm_task_destroy(dmt);
if (_get_flag(dl, VISIBLE))
fs_del_lv(dl->lv);
+ _clear_flag(dl, ACTIVE);
+
return r;
}
-static int _suspend_or_resume(const char *name, int sus)
+static int _suspend_or_resume(const char *name, suspend_t suspend)
{
int r;
struct dm_task *dmt;
+ int sus = (suspend == SUSPEND) ? 1 : 0;
int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
if (dl->info.suspended)
return 1;
- if (!_suspend_or_resume(dl->name, 1)) {
+ if (!_suspend_or_resume(dl->name, SUSPEND)) {
stack;
return 0;
}
if (!dl->info.suspended)
return 1;
- if (!_suspend_or_resume(dl->name, 0)) {
+ if (!_suspend_or_resume(dl->name, RESUME)) {
stack;
return 0;
}
return 0;
}
- if (!_suspend_or_resume(name, 1)) {
+ if (!_suspend_or_resume(name, SUSPEND)) {
stack;
return 0;
}
struct list *sh;
struct dev_layer *dep;
char *name;
-
- if (dl->info.exists && !_suspend(dl)) {
- stack;
- return 0;
- }
+ int suspended = 0;
list_iterate(sh, &dl->pre_create) {
name = list_item(sh, struct str_list)->str;
return 0;
}
- if (!_create_rec(dm, dep)) {
+ if (dl->info.exists && !suspended && !_suspend(dl)) {
stack;
return 0;
}
- }
+ suspended = 1;
- if (dl->info.exists) {
- /* reload */
- if (!_load(dm, dl, DM_DEVICE_RELOAD)) {
- stack;
- return 0;
- }
-
- if (!_resume(dl)) {
+ if (!_create_rec(dm, dep)) {
stack;
return 0;
}
+ }
- } else {
- /* create */
+ /* Create? */
+ if (!dl->info.exists) {
if (!_load(dm, dl, DM_DEVICE_CREATE)) {
stack;
return 0;
}
+ return 1;
+ }
+
+ /* We didn't suspend it - nothing to do */
+ if (!suspended)
+ return 1;
+
+ /* Reload */
+ if (_get_flag(dl, DIRTY) && !_load(dm, dl, DM_DEVICE_RELOAD)) {
+ stack;
+ return 0;
+ }
+
+ if (!_resume(dl)) {
+ stack;
+ return 0;
}
return 1;
int _remove_old_layers(struct dev_manager *dm)
{
int change;
+ struct list *rh, *n;
+ struct dev_layer *dl;
- /*
- * FIXME: quick hack. We just loop round removing
- * unopened devices, until we run out of things to close.
- */
do {
- struct list *rh, *n;
- struct dev_layer *dl;
-
change = 0;
list_iterate_safe(rh, n, &dm->remove_list) {
dl = list_item(rh, struct dl_list)->dl;
- if (!_info(dl->name, &dl->info)) {
- stack;
- return 0;
- }
-
if (!dl->info.exists) {
list_del(rh);
continue;
}
- if (!dl->info.open_count) {
- if (!_remove(dl)) {
- stack;
- continue;
- }
-
+ if (_remove(dl)) {
change = 1;
list_del(rh);
}
} while (change);
if (!list_empty(&dm->remove_list)) {
- log_error("Couldn't remove all redundant layers.");
+ list_iterate(rh, &dm->remove_list) {
+ dl = list_item(rh, struct dl_list)->dl;
+ log_error("Couldn't deactivate device %s", dl->name);
+ }
return 0;
}
{
const char *dev_dir = dm_dir();
- int i, count, r = 1;
- struct dirent **dirent;
+ int r = 1;
const char *name;
+ struct dirent *dirent;
+ DIR *d;
- count = scandir(dev_dir, &dirent, NULL, alphasort);
- if (!count)
- return 1;
-
- if (count < 0) {
- log_error("Couldn't scan device-mapper directory '%s'.",
- dev_dir);
+ if (!(d = opendir(dev_dir))) {
+ log_sys_error("opendir", dev_dir);
return 0;
}
- /*
- * Scan the devices.
- */
- for (i = 0; i < count; i++) {
- name = dirent[i]->d_name;
+ while ((dirent = readdir(d))) {
+ name = dirent->d_name;
- /*
- * Ignore dot files.
- */
if (name[0] == '.')
continue;
}
}
- /*
- * Free the directory entries.
- */
- for (i = 0; i < count; i++)
- free(dirent[i]);
- free(dirent);
+ if (closedir(d))
+ log_sys_error("closedir", dev_dir);
return r;
}
pool_free(dm->mem, name);
if (found) {
- log_debug("Active lv '%s' found.", lv->name);
+ log_debug("Found active lv %s", lv->name);
if (!_add_lv(dm->mem, &dm->active_list, lv)) {
stack;
return 1;
}
-/*
- * FIXME: There's a lot of common code between activate and
- * deactivate.
- */
-int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
+static int _activate(struct dev_manager *dm, struct logical_volume *lv,
+ activate_t activate)
{
if (!_scan_existing_devices(dm)) {
stack;
return 0;
}
- /*
- * Remove it so we don't add it twice.
- */
+ /* Remove from active list if present */
_remove_lv(&dm->active_list, lv);
- if (!_add_lv(dm->mem, &dm->dirty_list, lv) ||
- !_add_lv(dm->mem, &dm->active_list, lv)) {
- stack;
- return 0;
+
+ if (activate == ACTIVATE) {
+ /* Add to active and dirty lists */
+ if (!_add_lv(dm->mem, &dm->dirty_list, lv) ||
+ !_add_lv(dm->mem, &dm->active_list, lv)) {
+ stack;
+ return 0;
+ }
}
if (!_execute(dm, lv->vg)) {
return 1;
}
-int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
+int dev_manager_activate(struct dev_manager *dm, struct logical_volume *lv)
{
- if (!_scan_existing_devices(dm)) {
- stack;
- return 0;
- }
-
- if (!_fill_in_active_list(dm, lv->vg)) {
- stack;
- return 0;
- }
-
- _remove_lv(&dm->active_list, lv);
-
- if (!_execute(dm, lv->vg)) {
- stack;
- return 0;
- }
+ return _activate(dm, lv, ACTIVATE);
+}
- return 0;
+int dev_manager_deactivate(struct dev_manager *dm, struct logical_volume *lv)
+{
+ return _activate(dm, lv, DEACTIVATE);
}
+