Author: asomers
Date: Thu Oct 12 21:25:11 2017
New Revision: 324568
URL: https://svnweb.freebsd.org/changeset/base/324568

Log:
  Optimize zpool_read_all_labels with AIO
  
  Read all labels in parallel instead of sequentially
  
  MFC after:    3 weeks
  X-MFC-With: 322854
  Sponsored by: Spectra Logic Corp
  Differential Revision:        https://reviews.freebsd.org/D12495

Modified:
  head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c

Modified: head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c     Thu Oct 
12 20:31:10 2017        (r324567)
+++ head/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c     Thu Oct 
12 21:25:11 2017        (r324568)
@@ -42,6 +42,7 @@
  * using our derived config, and record the results.
  */
 
+#include <aio.h>
 #include <ctype.h>
 #include <devid.h>
 #include <dirent.h>
@@ -919,13 +920,17 @@ zpool_read_label(int fd, nvlist_t **config)
  * Given a file descriptor, read the label information and return an nvlist
  * describing the configuration, if there is one.
  * returns the number of valid labels found
+ * If a label is found, returns it via config.  The caller is responsible for
+ * freeing it.
  */
 int
 zpool_read_all_labels(int fd, nvlist_t **config)
 {
        struct stat64 statbuf;
+       struct aiocb aiocbs[VDEV_LABELS];
+       struct aiocb *aiocbps[VDEV_LABELS];
        int l;
-       vdev_label_t *label;
+       vdev_label_t *labels;
        uint64_t state, txg, size;
        int nlabels = 0;
 
@@ -935,19 +940,39 @@ zpool_read_all_labels(int fd, nvlist_t **config)
                return (0);
        size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
 
-       if ((label = malloc(sizeof (vdev_label_t))) == NULL)
+       if ((labels = calloc(VDEV_LABELS, sizeof (vdev_label_t))) == NULL)
                return (0);
 
+       memset(aiocbs, 0, sizeof(aiocbs));
        for (l = 0; l < VDEV_LABELS; l++) {
+               aiocbs[l].aio_fildes = fd;
+               aiocbs[l].aio_offset = label_offset(size, l);
+               aiocbs[l].aio_buf = &labels[l];
+               aiocbs[l].aio_nbytes = sizeof(vdev_label_t);
+               aiocbs[l].aio_lio_opcode = LIO_READ;
+               aiocbps[l] = &aiocbs[l];
+       }
+
+       if (lio_listio(LIO_WAIT, aiocbps, VDEV_LABELS, NULL) != 0) {
+               if (errno == EAGAIN || errno == EINTR || errno == EIO) {
+                       for (l = 0; l < VDEV_LABELS; l++) {
+                               errno = 0;
+                               int r = aio_error(&aiocbs[l]);
+                               if (r != EINVAL)
+                                       (void)aio_return(&aiocbs[l]);
+                       }
+               }
+               return (0);
+       }
+
+       for (l = 0; l < VDEV_LABELS; l++) {
                nvlist_t *temp = NULL;
 
-               /* TODO: use aio_read so we can read al 4 labels in parallel */
-               if (pread64(fd, label, sizeof (vdev_label_t),
-                   label_offset(size, l)) != sizeof (vdev_label_t))
+               if (aio_return(&aiocbs[l]) != sizeof(vdev_label_t))
                        continue;
 
-               if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
-                   sizeof (label->vl_vdev_phys.vp_nvlist), &temp, 0) != 0)
+               if (nvlist_unpack(labels[l].vl_vdev_phys.vp_nvlist,
+                   sizeof (labels[l].vl_vdev_phys.vp_nvlist), &temp, 0) != 0)
                        continue;
 
                if (nvlist_lookup_uint64(temp, ZPOOL_CONFIG_POOL_STATE,
@@ -970,7 +995,7 @@ zpool_read_all_labels(int fd, nvlist_t **config)
                nlabels++;
        }
 
-       free(label);
+       free(labels);
        return (nlabels);
 }
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to