Version 2.02.104
===================================
+ Add internal flag for temporary LVs to properly direct udev to not interfere.
Fix endless loop in blkdeactivate <device>... if unable to umount/deactivate.
Add dev-block-<major>:<minor>.device systemd alias for complete PV tracking.
Use major:minor as short form of --major and --minor arg for pvscan --cache.
}
/* Now activate it */
- if (!lv_activate(cmd, resource, exclusive, 0, NULL))
+ if (!lv_activate(cmd, resource, exclusive, 0, 0, NULL))
goto error;
return 0;
return 1;
}
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, int noscan,
- struct logical_volume *lv)
+ int temporary, struct logical_volume *lv)
{
return 1;
}
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive,
- int noscan, struct logical_volume *lv)
+ int noscan, int temporary, struct logical_volume *lv)
{
return 1;
}
if (filter)
laopts->read_only = _passes_readonly_filter(cmd, lv);
- log_debug_activation("Activating %s/%s%s%s%s.", lv->vg->name, lv->name,
+ log_debug_activation("Activating %s/%s%s%s%s%s.", lv->vg->name, lv->name,
laopts->exclusive ? " exclusively" : "",
laopts->read_only ? " read-only" : "",
- laopts->noscan ? " noscan" : "");
+ laopts->noscan ? " noscan" : "",
+ laopts->temporary ? " temporary" : "");
if (!lv_info(cmd, lv, 0, &info, 0, 0))
goto_out;
/* Activate LV */
int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive,
- int noscan, struct logical_volume *lv)
+ int noscan, int temporary, struct logical_volume *lv)
{
- struct lv_activate_opts laopts = { .exclusive = exclusive, .noscan = noscan };
+ struct lv_activate_opts laopts = { .exclusive = exclusive,
+ .noscan = noscan,
+ .temporary = temporary };
if (!_lv_activate(cmd, lvid_s, &laopts, 0, lv))
return_0;
/* Activate LV only if it passes filter */
int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive,
- int noscan, struct logical_volume *lv)
+ int noscan, int temporary, struct logical_volume *lv)
{
- struct lv_activate_opts laopts = { .exclusive = exclusive, .noscan = noscan };
+ struct lv_activate_opts laopts = { .exclusive = exclusive,
+ .noscan = noscan,
+ .temporary = temporary };
if (!_lv_activate(cmd, lvid_s, &laopts, 1, lv))
return_0;
int skip_in_use;
unsigned revert;
unsigned read_only;
- unsigned noscan;
+ unsigned noscan; /* Mark this LV to avoid its scanning. This also
+ directs udev to use proper udev flag to avoid
+ any scanning in udev. This udev flag is automatically
+ dropped in udev db on any spurious event that follows. */
+ unsigned temporary; /* Mark this LV as temporary. It means, the LV
+ * is created, used and deactivated within single
+ * LVM command execution. Such LVs are mostly helper
+ * LVs to do some action or cleanup before the proper
+ * LV is created. This also directs udev to use proper
+ * set of flags to avoid any scanning in udev. These udev
+ * flags are persistent in udev db for any spurious event
+ * that follows. */
};
/* target attribute flags */
int lv_resume(struct cmd_context *cmd, const char *lvid_s, unsigned origin_only, struct logical_volume *lv);
int lv_resume_if_active(struct cmd_context *cmd, const char *lvid_s,
unsigned origin_only, unsigned exclusive, unsigned revert, struct logical_volume *lv);
-int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive, int noscan, struct logical_volume *lv);
-int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s,
- int exclusive, int noscan, struct logical_volume *lv);
+int lv_activate(struct cmd_context *cmd, const char *lvid_s, int exclusive,
+ int noscan, int temporary, struct logical_volume *lv);
+int lv_activate_with_filter(struct cmd_context *cmd, const char *lvid_s, int exclusive,
+ int noscan, int temporary, struct logical_volume *lv);
int lv_deactivate(struct cmd_context *cmd, const char *lvid_s, struct logical_volume *lv);
int lv_mknodes(struct cmd_context *cmd, const struct logical_volume *lv);
#endif /* UDEV_SYNC_SUPPORT */
static uint16_t _get_udev_flags(struct dev_manager *dm, struct logical_volume *lv,
- const char *layer, uint16_t flags)
+ const char *layer, int noscan, int temporary)
{
uint16_t udev_flags = 0;
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
/*
- * Firmly set requested flags.
+ * LVM subsystem specific flags.
*/
- udev_flags |= flags;
+ if (noscan)
+ udev_flags |= DM_SUBSYSTEM_UDEV_FLAG0;
+
+ if (temporary)
+ udev_flags |= DM_UDEV_DISABLE_DISK_RULES_FLAG |
+ DM_UDEV_DISABLE_OTHER_RULES_FLAG;
return udev_flags;
}
}
if (info.exists && !dm_tree_add_dev_with_udev_flags(dtree, info.major, info.minor,
- _get_udev_flags(dm, lv, layer, 0))) {
+ _get_udev_flags(dm, lv, layer, 0, 0))) {
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
info.major, info.minor);
return 0;
}
dm_tree_node_set_udev_flags(child,
- _get_udev_flags(dm, lvl->lv, NULL, 0));
+ _get_udev_flags(dm, lvl->lv, NULL, 0, 0));
}
return 1;
read_only_lv(lv, laopts),
((lv->vg->status & PRECOMMITTED) | laopts->revert) ? 1 : 0,
lvlayer,
- _get_udev_flags(dm, lv, layer,
- laopts->noscan ? LVM_UDEV_NOSCAN_FLAG : 0))))
+ _get_udev_flags(dm, lv, layer, laopts->noscan, laopts->temporary))))
return_0;
/* Store existing name so we can do rename later */
{LV_WRITEMOSTLY, "WRITEMOSTLY", STATUS_FLAG},
{LV_ACTIVATION_SKIP, "ACTIVATION_SKIP", COMPATIBLE_FLAG},
{LV_NOSCAN, NULL, 0},
+ {LV_TEMPORARY, NULL, 0},
{POOL_METADATA_SPARE, NULL, 0},
{RAID, NULL, 0},
{RAID_META, NULL, 0},
break;
case LCK_READ:
log_very_verbose("Locking LV %s (R)", resource);
- if (!lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv)))
+ if (!lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0,
+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv)))
return 0;
break;
case LCK_PREAD:
break;
case LCK_EXCL:
log_very_verbose("Locking LV %s (EX)", resource);
- if (!lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv)))
+ if (!lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0,
+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv)))
return 0;
break;
default:
case LCK_UNLOCK:
return lv_resume_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1: 0, 0, (flags & LCK_REVERT) ? 1 : 0, lv_ondisk(lv));
case LCK_READ:
- return lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv));
+ return lv_activate_with_filter(cmd, resource, 0, lv->status & LV_NOSCAN ? 1 : 0,
+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv));
case LCK_WRITE:
return lv_suspend_if_active(cmd, resource, (flags & LCK_ORIGIN_ONLY) ? 1 : 0, 0, lv_ondisk(lv), lv);
case LCK_EXCL:
- return lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0, lv_ondisk(lv));
+ return lv_activate_with_filter(cmd, resource, 1, lv->status & LV_NOSCAN ? 1 : 0,
+ lv->status & LV_TEMPORARY ? 1 : 0, lv_ondisk(lv));
default:
break;
}
if (lp->zero)
lv->status |= LV_NOSCAN;
+ if (lp->temporary)
+ lv->status |= LV_TEMPORARY;
+
if (lv_is_thin_pool(lv)) {
if (is_change_activating(lp->activate)) {
if (vg_is_clustered(lv->vg)) {
#define LV_WRITEMOSTLY UINT64_C(0x0000020000000000) /* LV (RAID1) */
#define LV_ACTIVATION_SKIP UINT64_C(0x0000040000000000) /* LV */
-#define LV_NOSCAN UINT64_C(0x0000080000000000) /* LV */
+#define LV_NOSCAN UINT64_C(0x0000080000000000) /* LV - internal use only - the LV
+ should not be scanned */
+#define LV_TEMPORARY UINT64_C(0x0000100000000000) /* LV - internal use only - the LV
+ is supposed to be created and
+ removed during single LVM
+ command execution. */
/* Format features flags */
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
int log_count; /* mirror */
int nosync; /* mirror */
int poolmetadataspare; /* thin pool */
+ int temporary; /* temporary LV */
#define ACTIVATION_SKIP_SET 0x01 /* request to set LV activation skip flag state */
#define ACTIVATION_SKIP_SET_ENABLED 0x02 /* set the LV activation skip flag state to 'enabled' */
#define ACTIVATION_SKIP_IGNORE 0x04 /* request to ignore LV activation skip flag (if any) */
.stripes = 1,
.vg_name = vg->name,
.zero = 1,
+ .temporary = 1,
};
dm_list_init(&lp.tags);