enum {
ACTIVE = 0,
DIRTY = 1,
- VISIBLE = 2
+ VISIBLE = 2,
+ READWRITE = 3
};
typedef enum {
/*
* Low level device-layer operations.
*/
-static struct dm_task *_setup_task(const char *name, int task)
+static struct dm_task *_setup_task(const char *name, const char *uuid, int task)
{
struct dm_task *dmt;
return NULL;
}
- dm_task_set_name(dmt, name);
+ if (name)
+ dm_task_set_name(dmt, name);
+
+ if (uuid && *uuid)
+ dm_task_set_uuid(dmt, uuid);
+
return dmt;
}
-static int _info(const char *name, const char *uuid, struct dm_info *info,
+static int _info_run(const char *name, const char *uuid, struct dm_info *info,
struct pool *mem, char **uuid_out)
{
int r = 0;
struct dm_task *dmt;
const char *u;
- log_debug("Getting device info for %s", name);
- if (!(dmt = _setup_task(name, DM_DEVICE_INFO))) {
+ if (!(dmt = _setup_task(name, uuid, DM_DEVICE_INFO))) {
stack;
return 0;
}
- if (uuid)
- dm_task_set_uuid(dmt, uuid);
-
if (!dm_task_run(dmt)) {
stack;
goto out;
return r;
}
+static int _info(const char *name, const char *uuid, struct dm_info *info,
+ struct pool *mem, char **uuid_out)
+{
+ if (uuid && *uuid && _info_run(NULL, uuid, info, mem, uuid_out)
+ && info->exists)
+ return 1;
+
+ if (name)
+ return _info_run(name, NULL, info, mem, uuid_out);
+
+ return 0;
+}
+
static int _rename(struct dev_manager *dm, struct dev_layer *dl, char *newname)
{
int r = 1;
log_verbose("Renaming %s to %s", dl->name, newname);
- if (!(dmt = _setup_task(dl->name, DM_DEVICE_RENAME))) {
+ if (!(dmt = _setup_task(dl->name, NULL, DM_DEVICE_RENAME))) {
stack;
return 0;
}
struct dm_task *dmt;
log_verbose("Loading %s", dl->name);
- if (!(dmt = _setup_task(dl->name, task))) {
+ if (!(dmt = _setup_task(task == DM_DEVICE_CREATE ? dl->name : NULL,
+ dl->dlid, task))) {
stack;
return 0;
}
goto out;
}
- dm_task_set_uuid(dmt, dl->dlid);
+ if (!_get_flag(dl, READWRITE)) {
+ if (!dm_task_set_ro(dmt)) {
+ log_error("Failed to set %s read-only during "
+ "activation.", dl->name);
+ goto out;
+ } else
+ log_very_verbose("Activating %s read-only", dl->name);
+ }
if (!(r = dm_task_run(dmt)))
log_error("Couldn't load device '%s'.", dl->name);
else
log_very_verbose("Removing %s", dl->name);
- if (!(dmt = _setup_task(dl->name, DM_DEVICE_REMOVE))) {
+ if (!(dmt = _setup_task(dl->name, NULL, DM_DEVICE_REMOVE))) {
stack;
return 0;
}
int task = sus ? DM_DEVICE_SUSPEND : DM_DEVICE_RESUME;
log_very_verbose("%s %s", sus ? "Suspending" : "Resuming", name);
- if (!(dmt = _setup_task(name, task))) {
+ if (!(dmt = _setup_task(name, NULL, task))) {
stack;
return 0;
}
char *name;
/*
- * Build a name for the top layer.
- */
+ * Build a name for the top layer.
+ */
if (!(name = _build_name(dm->mem, lv->vg->name, lv->name, NULL))) {
stack;
return 0;
/*
* Try and get some info on this device.
*/
+ log_debug("Getting device info for %s", name);
if (!_info(name, lv->lvid.s, info, NULL, NULL)) {
stack;
return 0;
dl->name = name;
+ log_debug("Getting device info for %s", dl->name);
if (!_info(dl->name, dlid, &dl->info, dm->mem, &uuid)) {
stack;
return NULL;
return dl;
}
+static inline int _read_only_lv(struct logical_volume *lv)
+{
+ return (!(lv->vg->status & LVM_WRITE) ||
+ !(lv->status & LVM_WRITE));
+}
+
static struct dev_layer *_create_layer(struct dev_manager *dm,
const char *layer,
struct logical_volume *lv)
dl->lv = lv;
+ if (!_read_only_lv(lv))
+ _set_flag(dl, READWRITE);
+
return dl;
}
struct list *sh;
struct dev_layer *dep;
char *dlid, *newname, *suffix;
- int suspended = 0;
list_iterate(sh, &dl->pre_create) {
dlid = list_item(sh, struct str_list)->str;
return 0;
}
- if (dl->info.exists && !suspended && !_suspend(dl)) {
+ if (dl->info.exists && !_suspend(dl)) {
stack;
return 0;
}
- suspended = 1;
if (!strcmp(dep->dlid, dl->dlid)) {
log_error("BUG: pre-create loop detected (%s)", dlid);
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;