]> sourceware.org Git - dm.git/commitdiff
On 'buffer full' condition, double buffer size and repeat ioctl. [Untested]
authorAlasdair Kergon <agk@redhat.com>
Mon, 19 Sep 2005 14:29:16 +0000 (14:29 +0000)
committerAlasdair Kergon <agk@redhat.com>
Mon, 19 Sep 2005 14:29:16 +0000 (14:29 +0000)
WHATS_NEW
lib/ioctl/libdm-iface.c

index 579f21e30204f1e105a5d18109cb557c85b79f5b..22dd8d48ce4089a9bf08d891f48a2266e425338f 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 1.01.05 -
 =============================
+  On 'buffer full' condition, double buffer size and repeat ioctl.
   Fix termination of getopt_long() option array.
   Report 'buffer full' condition with v4 ioctl as well as with v1.
 
index 25f0aa25e051dd0179bd49860f90ca13d4459522..54b34867e4d74545734e05b6e1fc64b369736c57 100644 (file)
@@ -1026,7 +1026,7 @@ static void *_add_target(struct target *t, void *out, void *end)
        return out;
 }
 
-static struct dm_ioctl *_flatten(struct dm_task *dmt)
+static struct dm_ioctl *_flatten(struct dm_task *dmt, unsigned repeat_count)
 {
        const size_t min_size = 16 * 1024;
        const int (*version)[3];
@@ -1077,6 +1077,10 @@ static struct dm_ioctl *_flatten(struct dm_task *dmt)
        if (len < min_size)
                len = min_size;
 
+       /* Increase buffer size if repeating because buffer was too small */
+       while (repeat_count--)
+               len *= 2;
+
        if (!(dmi = malloc(len)))
                return NULL;
 
@@ -1276,40 +1280,14 @@ static int _create_and_load_v4(struct dm_task *dmt)
        return r;
 }
 
-int dm_task_run(struct dm_task *dmt)
+static struct dm_ioctl *_do_dm_ioctl(struct dm_task *dmt, unsigned repeat_count)
 {
-       struct dm_ioctl *dmi = NULL;
-       unsigned int command;
-
-#ifdef DM_COMPAT
-       if (_dm_version == 1)
-               return _dm_task_run_v1(dmt);
-#endif
-
-       if ((unsigned) dmt->type >=
-           (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
-               log_error("Internal error: unknown device-mapper task %d",
-                         dmt->type);
-               goto bad;
-       }
-
-       command = _cmd_data_v4[dmt->type].cmd;
-
-       /* Old-style creation had a table supplied */
-       if (dmt->type == DM_DEVICE_CREATE && dmt->head)
-               return _create_and_load_v4(dmt);
-
-       if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
-           !dmt->uuid && dmt->major <= 0)
-               return _mknodes_v4(dmt);
-
-       if (!_open_control())
-               return 0;
+       struct dm_ioctl *dmi;
 
-       dmi = _flatten(dmt);
+       dmi = _flatten(dmt, repeat_count);
        if (!dmi) {
                log_error("Couldn't create ioctl argument");
-               return 0;
+               return NULL;
        }
 
        if (dmt->type == DM_DEVICE_TABLE)
@@ -1338,15 +1316,65 @@ int dm_task_run(struct dm_task *dmt)
                                log_error("device-mapper ioctl "
                                          "cmd %d failed: %s",
                                          _IOC_NR(command), strerror(errno));
-                       goto bad;
+                       free(dmi);
+                       return NULL;
                }
        }
 #else /* Userspace alternative for testing */
 #endif
+       return dmi;
+}
 
-       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");
+int dm_task_run(struct dm_task *dmt)
+{
+       struct dm_ioctl *dmi;
+       unsigned command;
+       unsigned repeat_count = 0;
+
+#ifdef DM_COMPAT
+       if (_dm_version == 1)
+               return _dm_task_run_v1(dmt);
+#endif
+
+       if ((unsigned) dmt->type >=
+           (sizeof(_cmd_data_v4) / sizeof(*_cmd_data_v4))) {
+               log_error("Internal error: unknown device-mapper task %d",
+                         dmt->type);
+               return 0;
+       }
+
+       command = _cmd_data_v4[dmt->type].cmd;
+
+       /* Old-style creation had a table supplied */
+       if (dmt->type == DM_DEVICE_CREATE && dmt->head)
+               return _create_and_load_v4(dmt);
+
+       if (dmt->type == DM_DEVICE_MKNODES && !dmt->dev_name &&
+           !dmt->uuid && dmt->major <= 0)
+               return _mknodes_v4(dmt);
+
+       if (!_open_control())
+               return 0;
+
+repeat_ioctl:
+       if (!(dmi = _do_dm_ioctl(dmt, repeat_count)))
+               return 0;
+
+       if (dmi->flags & DM_BUFFER_FULL_FLAG) {
+               switch (dmt->type) {
+               case DM_DEVICE_LIST_VERSIONS:
+               case DM_DEVICE_LIST:
+               case DM_DEVICE_DEPS:
+               case DM_DEVICE_STATUS:
+               case DM_DEVICE_TABLE:
+               case DM_DEVICE_WAITEVENT:
+                       repeat_count++;
+                       free(dmi);
+                       goto repeat_ioctl;
+               default:
+                       log_error("Warning: libdevmapper buffer too small for data");
+               }
+       }
 
        switch (dmt->type) {
        case DM_DEVICE_CREATE:
This page took 0.032716 seconds and 5 git commands to generate.