SHA256
1
0
forked from pool/lvm2
lvm2/device-mapper-wait_udev.diff

133 lines
3.4 KiB
Diff

Index: LVM2.2.02.45/libdm/ioctl/libdm-iface.c
===================================================================
--- LVM2.2.02.45.orig/libdm/ioctl/libdm-iface.c 2009-04-27 17:53:30.000000000 +0800
+++ LVM2.2.02.45/libdm/ioctl/libdm-iface.c 2009-04-27 17:57:54.000000000 +0800
@@ -129,6 +129,67 @@
# define DM_EXISTS_FLAG 0x00000004
#endif
+static unsigned long long get_seq()
+{
+ struct stat s;
+ int r;
+ unsigned long long seq = 0;
+ FILE* fp;
+ r = stat("/sys/kernel/uevent_seqnum", &s);
+ if (r) { return seq; }
+ if (!S_ISREG(s.st_mode)) { return seq; }
+ fp = fopen("/sys/kernel/uevent_seqnum", "r");
+ if (fp == NULL) { return seq; }
+ fscanf(fp, "%llu\n", &seq);
+ fclose(fp);
+ return seq;
+}
+
+static int wait_4_udev(unsigned long long start_seq, unsigned long long end_seq)
+{
+ FILE* fp;
+ struct stat s;
+ int r;
+ int ite=30; /* Iterate 30 times. Otherwise, it's considered timed out */
+ unsigned long long seq;
+ /*
+ * len("/dev/.udev/queue/") + len(str(0xffffffffffffffff)) = 38
+ */
+ #define PATH_SIZE 40
+ char filename[PATH_SIZE];
+ #undef PATH_SIZE
+
+ if (start_seq > end_seq || end_seq == 0) return 1;
+
+ /* Wait until end_seq is enqueued into udev */
+ r = stat("/dev/.udev/uevent_seqnum", &s);
+ if (r) { return 1; }
+ if (!S_ISREG(s.st_mode)) { return 1; }
+ while (ite-- > 0) {
+ fp = fopen("/dev/.udev/uevent_seqnum", "r");
+ if (fp == NULL) { return 1; }
+ fscanf(fp, "%llu\n", &seq);
+ fclose(fp);
+ if (seq >= end_seq) { break; }
+ usleep(200000);
+ }
+ if (ite <=0 ) return 1;
+
+ /* Loop to make sure all $seq are unlinked in /dev/.udev/queue then */
+ for (seq = start_seq; seq <= end_seq; seq++) {
+ ite = 30;
+ while (ite-- > 0) {
+ snprintf(filename, sizeof(filename), "/dev/.udev/queue/%llu", seq);
+ r = open(filename, O_RDONLY);
+ if (r == -1 && errno == ENOENT) break;
+ if (r >= 0) close(r);
+ usleep(200000);
+ }
+ if (ite <=0 ) return 1;
+ }
+ return 0;
+}
+
static void *_align(void *ptr, unsigned int a)
{
register unsigned long agn = --a;
@@ -679,6 +740,7 @@
{
struct dm_ioctl_v1 *dmi;
unsigned int command;
+ unsigned long long before_seq, after_seq;
dmi = _flatten_v1(dmt);
if (!dmi) {
@@ -705,6 +767,8 @@
dmi->name, dmi->uuid, dmt->newname ? " " : "",
dmt->newname ? dmt->newname : "",
dmi->data_size);
+
+ before_seq = get_seq();
if (dmt->type == DM_DEVICE_LIST) {
if (!_dm_names_v1(dmi))
goto bad;
@@ -724,10 +788,13 @@
#else /* Userspace alternative for testing */
#endif
+ after_seq = get_seq();
if (dmi->flags & DM_BUFFER_FULL_FLAG)
/* FIXME Increase buffer size and retry operation (if query) */
log_error("WARNING: libdevmapper buffer too small for data");
+ wait_4_udev(before_seq, after_seq);
+
switch (dmt->type) {
case DM_DEVICE_CREATE:
add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),
@@ -1706,6 +1773,7 @@
{
struct dm_ioctl *dmi;
unsigned command;
+ unsigned long long before_seq, after_seq;
#ifdef DM_COMPAT
if (_dm_version == 1)
@@ -1736,9 +1804,11 @@
return 0;
repeat_ioctl:
+ before_seq = get_seq();
if (!(dmi = _do_dm_ioctl(dmt, command, _ioctl_buffer_double_factor)))
return 0;
+ after_seq = get_seq();
if (dmi->flags & DM_BUFFER_FULL_FLAG) {
switch (dmt->type) {
case DM_DEVICE_LIST_VERSIONS:
@@ -1755,6 +1825,8 @@
}
}
+ wait_4_udev(before_seq, after_seq);
+
switch (dmt->type) {
case DM_DEVICE_CREATE:
if (dmt->dev_name && *dmt->dev_name)