133 lines
3.4 KiB
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)
|