Optimize o_direct read/writes.
authorMilan Broz <gmazyland@gmail.com>
Tue, 28 Jul 2009 09:29:13 +0000 (09:29 +0000)
committerMilan Broz <gmazyland@gmail.com>
Tue, 28 Jul 2009 09:29:13 +0000 (09:29 +0000)
* Pad luks header to 512 sector size. We need read/write in whole
sector anyway and space is unused (wiped in luksFormat) so there is
no need for read/seek/write exercise.

* Rework read/write blockwise to not split operation to many pieces.
thanks to Sebastian Andrzej Siewior:

  The buffer has to be aligned due to the O_DIRECT in open(). Currently a small
  blocksize buffer is allocated and everything is read in multiple reads and
  copied back to the original buffer. In my case AFEKSize gets computed to 64000
  which results in 125 reads with 512 bytes each.
  This patch changes this behavior to a single operation where the majority is
  read()/write() plus an optional fixup in case the request is not modulo block
  size.

* Use posix_memalign and check for alignment if available.
Othewise use old align functions. Add autoconf to detect posix_memalign.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@74 36d66b0a-2a48-0410-832c-cd162a569da5

ChangeLog
configure.in
lib/internal.h
lib/utils.c
luks/keymanage.c
luks/luks.h

index 03f87b0..a6c5f50 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-07-28  Milan Broz  <mbroz@redhat.com>
+       * Pad luks header to 512 sector size.
+       * Rework read/write blockwise to not split operation to many pieces.
+       * Use posix_memalign if available.
+
 2009-07-22  Milan Broz  <mbroz@redhat.com>
        * Fix segfault if provided slot in luksKillslot is invalid.
        * Remove unneeded timeout when remove of temporary device succeeded.
index 44a232a..c208ebc 100644 (file)
@@ -1,6 +1,7 @@
 AC_PREREQ(2.57)
 AC_INIT(cryptsetup,1.0.7)
 AC_CONFIG_SRCDIR(src/cryptsetup.c)
+AC_CONFIG_MACRO_DIR([m4])
 
 AM_CONFIG_HEADER([config.h:config.h.in])
 AM_INIT_AUTOMAKE(dist-bzip2)
@@ -117,6 +118,7 @@ MODULE_HELPER(libdevmapper,
 AM_CONDITIONAL(BUILD_LIBDEVMAPPER, test x$build_static = xyes)
 AM_CONDITIONAL(SHARED_LIBDEVMAPPER, test x$build_shared = xyes)
 
+AC_CHECK_FUNCS([posix_memalign])
 dnl ==========================================================================
 
 AM_CONDITIONAL(STATIC_CRYPTSETUP, test x$enable_static = xyes)
index 2a9559d..38a03a8 100644 (file)
@@ -11,6 +11,7 @@
 
 #define SECTOR_SHIFT           9
 #define SECTOR_SIZE            (1 << SECTOR_SHIFT)
+#define DEFAULT_ALIGNMENT      4096
 
 /* private struct crypt_options flags */
 
index f4c639e..4f1518d 100644 (file)
@@ -116,10 +116,24 @@ char *safe_strdup(const char *s)
        return strcpy(s2, s);
 }
 
-/* Credits go to Michal's padlock patches for this alignment code */
+static int get_alignment(int fd)
+{
+       int alignment = DEFAULT_ALIGNMENT;
+
+#ifdef _PC_REC_XFER_ALIGN
+       alignment = fpathconf(fd, _PC_REC_XFER_ALIGN);
+       if (alignment < 0)
+               alignment = DEFAULT_ALIGNMENT;
+#endif
+       return alignment;
+}
 
-static void *aligned_malloc(char **base, int size, int alignment) 
+static void *aligned_malloc(void **base, int size, int alignment)
 {
+#ifdef HAVE_POSIX_MEMALIGN
+       return posix_memalign(base, alignment, size) ? NULL : *base;
+#else
+/* Credits go to Michal's padlock patches for this alignment code */
        char *ptr;
 
        ptr  = malloc(size + alignment);
@@ -130,8 +144,8 @@ static void *aligned_malloc(char **base, int size, int alignment)
                ptr += alignment - ((long)(ptr) & (alignment - 1));
        }
        return ptr;
+#endif
 }
-
 static int sector_size(int fd) 
 {
        int bsize;
@@ -152,74 +166,100 @@ int sector_size_for_device(const char *device)
        return r;
 }
 
-ssize_t write_blockwise(int fd, const void *orig_buf, size_t count) 
+ssize_t write_blockwise(int fd, const void *orig_buf, size_t count)
 {
-       char *padbuf; char *padbuf_base;
-       char *buf = (char *)orig_buf;
-       int r = 0;
-       int hangover; int solid; int bsize;
+       void *hangover_buf, *hangover_buf_base = NULL;
+       void *buf, *buf_base = NULL;
+       int r, hangover, solid, bsize, alignment;
+       ssize_t ret = -1;
 
        if ((bsize = sector_size(fd)) < 0)
                return bsize;
 
        hangover = count % bsize;
        solid = count - hangover;
+       alignment = get_alignment(fd);
+
+       if ((long)orig_buf & (alignment - 1)) {
+               buf = aligned_malloc(&buf_base, count, alignment);
+               if (!buf)
+                       goto out;
+               memcpy(buf, orig_buf, count);
+       } else
+               buf = (void *)orig_buf;
 
-       padbuf = aligned_malloc(&padbuf_base, bsize, bsize);
-       if(padbuf == NULL) return -ENOMEM;
+       r = write(fd, buf, solid);
+       if (r < 0 || r != solid)
+               goto out;
 
-       while(solid) {
-               memcpy(padbuf, buf, bsize);
-               r = write(fd, padbuf, bsize);
-               if(r < 0 || r != bsize) goto out;
+       if (hangover) {
+               hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
+               if (!hangover_buf)
+                       goto out;
 
-               solid -= bsize;
-               buf += bsize;
-       }
-       if(hangover) {
-               r = read(fd,padbuf,bsize);
+               r = read(fd, hangover_buf, bsize);
                if(r < 0 || r != bsize) goto out;
 
-               lseek(fd,-bsize,SEEK_CUR);
-               memcpy(padbuf,buf,hangover);
+               r = lseek(fd, -bsize, SEEK_CUR);
+               if (r < 0)
+                       goto out;
+               memcpy(hangover_buf, buf + solid, hangover);
 
-               r = write(fd,padbuf, bsize);
+               r = write(fd, hangover_buf, bsize);
                if(r < 0 || r != bsize) goto out;
-               buf += hangover;
+               free(hangover_buf_base);
        }
+       ret = count;
  out:
-       free(padbuf_base);
-       return (buf-(char *)orig_buf)?(buf-(char *)orig_buf):r;
-
+       if (buf != orig_buf)
+               free(buf_base);
+       return ret;
 }
 
 ssize_t read_blockwise(int fd, void *orig_buf, size_t count) {
-       char *padbuf; char *padbuf_base;
-       char *buf = (char *)orig_buf;
-       int r = 0;
-       int step;
-       int bsize;
+       void *hangover_buf, *hangover_buf_base;
+       void *buf, *buf_base = NULL;
+       int r, hangover, solid, bsize, alignment;
+       ssize_t ret = -1;
 
        if ((bsize = sector_size(fd)) < 0)
                return bsize;
 
-       padbuf = aligned_malloc(&padbuf_base, bsize, bsize);
-       if(padbuf == NULL) return -ENOMEM;
+       hangover = count % bsize;
+       solid = count - hangover;
+       alignment = get_alignment(fd);
 
-       while(count) {
-               r = read(fd,padbuf,bsize);
-               if(r < 0 || r != bsize) {
-                       set_error("read failed in read_blockwise.\n");
+       if ((long)orig_buf & (alignment - 1)) {
+               buf = aligned_malloc(&buf_base, count, alignment);
+               if (!buf)
                        goto out;
-               }
-               step = count<bsize?count:bsize;
-               memcpy(buf,padbuf,step);
-               buf += step;
-               count -= step;
+       } else
+               buf = orig_buf;
+
+       r = read(fd, buf, solid);
+       if(r < 0 || r != solid) {
+               set_error("read failed in read_blockwise.\n");
+               goto out;
        }
+
+       if (hangover) {
+               hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
+               if (!hangover_buf)
+                       goto out;
+               r = read(fd, hangover_buf, bsize);
+               if (r <  0 || r != bsize)
+                       goto out;
+
+               memcpy(buf + solid, hangover_buf, hangover);
+               free(hangover_buf_base);
+       }
+       ret = count;
  out:
-       free(padbuf_base); 
-       return (buf-(char *)orig_buf)?(buf-(char *)orig_buf):r;
+       if (buf != orig_buf) {
+               memcpy(orig_buf, buf, count);
+               free(buf_base);
+       }
+       return ret;
 }
 
 /* 
index 2a09874..bcec13b 100644 (file)
@@ -142,6 +142,7 @@ int LUKS_write_phdr(const char *device, struct luks_phdr *hdr)
        }
 
        memcpy(&convHdr, hdr, sizeof(struct luks_phdr));
+       memset(&convHdr._padding, 0, sizeof(convHdr._padding));
 
        /* Convert every uint16/32_t item to network byte order */
        convHdr.version            = htons(hdr->version);
index 9a6a6ec..caa4a99 100644 (file)
@@ -63,15 +63,18 @@ struct luks_phdr {
 
        struct {
                uint32_t active;
-       
+
                /* parameters used for password processing */
                uint32_t passwordIterations;
                char     passwordSalt[LUKS_SALTSIZE];
-               
-               /* parameters used for AF store/load */         
+
+               /* parameters used for AF store/load */
                uint32_t keyMaterialOffset;
-               uint32_t stripes;               
+               uint32_t stripes;
        } keyblock[LUKS_NUMKEYS];
+
+       /* Align it to 512 sector size */
+       char            _padding[432];
 };
 
 struct luks_masterkey {