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. With this patch I can see that the performance has improved on my ARM box Before the patch: |# time cryptsetup luksOpen /dev/sda2 crypt -d key |key slot 0 unlocked. |Command successful. | |real 0m3.089s |user 0m0.550s |sys 0m0.120s |# time cryptsetup luksOpen /dev/sda2 crypt -d key |key slot 0 unlocked. |Command successful. | |real 0m3.059s |user 0m0.550s |sys 0m0.110s With the patch: |# time src/cryptsetup luksOpen /dev/sda2 crypt -d key |key slot 0 unlocked. |Command successful. | |real 0m2.061s |user 0m0.560s |sys 0m0.290s |# time src/cryptsetup luksOpen /dev/sda2 crypt -d key |key slot 0 unlocked. |Command successful. | |real 0m1.977s |user 0m0.580s |sys 0m0.200s I also see this improvement on my x86_64 box Signed-off-by: Sebastian Andrzej Siewior <sebastian@xxxxxxxxxxxxx> --- lib/utils.c | 134 ++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 78 insertions(+), 56 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index 8bffc50..a676d31 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -113,22 +113,6 @@ char *safe_strdup(const char *s) return strcpy(s2, s); } -/* Credits go to Michal's padlock patches for this alignment code */ - -static void *aligned_malloc(char **base, int size, int alignment) -{ - char *ptr; - - ptr = malloc(size + alignment); - if(ptr == NULL) return NULL; - - *base = ptr; - if(alignment > 1 && ((long)ptr & (alignment - 1))) { - ptr += alignment - ((long)(ptr) & (alignment - 1)); - } - return ptr; -} - static int sector_size(int fd) { int bsize; @@ -149,12 +133,14 @@ 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; + void *hangover_buf; + void *buf; + int r; int hangover; int solid; int bsize; + int alignment; + ssize_t ret = -1; if ((bsize = sector_size(fd)) < 0) return bsize; @@ -162,61 +148,97 @@ ssize_t write_blockwise(int fd, const void *orig_buf, size_t count) hangover = count % bsize; solid = count - hangover; - padbuf = aligned_malloc(&padbuf_base, bsize, bsize); - if(padbuf == NULL) return -ENOMEM; + alignment = fpathconf(fd, _PC_REC_XFER_ALIGN); + if (alignment < 0) + return alignment; - while(solid) { - memcpy(padbuf, buf, bsize); - r = write(fd, padbuf, bsize); - if(r < 0 || r != bsize) goto out; - - solid -= bsize; - buf += bsize; + if ((long)orig_buf & (alignment - 1)) { + r = posix_memalign(&buf, alignment, count); + if (r) + return r; + memcpy(buf, orig_buf, count); + } else { + buf = (void *)orig_buf; } - if(hangover) { - r = read(fd,padbuf,bsize); + + r = write(fd, buf, solid); + if (r < 0 || r != solid) + goto out; + + if (hangover) { + r = posix_memalign(&hangover_buf, alignment, bsize); + if (r) + goto out; + + 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) + 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); } + ret = count; out: - free(padbuf_base); - return (buf-(char *)orig_buf)?(buf-(char *)orig_buf):r; - + if (buf != orig_buf) + free(buf); + 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 *buf; + int r; + int alignment; + int hangover; int solid; int bsize; + 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 = fpathconf(fd, _PC_REC_XFER_ALIGN); + if (alignment < 0) + return alignment; + + if ((long)orig_buf & (alignment - 1)) { + r = posix_memalign(&buf, alignment, count); + if (r) + return r; + } 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) { + void *hangover_buf; - while(count) { - r = read(fd,padbuf,bsize); - if(r < 0 || r != bsize) { - set_error("read failed in read_blockwise.\n"); + r = posix_memalign(&hangover_buf, alignment, bsize); + if (r) goto out; - } - step = count<bsize?count:bsize; - memcpy(buf,padbuf,step); - buf += step; - count -= step; + r = read(fd, hangover_buf, bsize); + if (r < 0 || r != bsize) + goto out; + + memcpy(buf + solid, hangover_buf, hangover); + free(hangover_buf); } + ret = count; out: - free(padbuf_base); - return (buf-(char *)orig_buf)?(buf-(char *)orig_buf):r; + if (buf != orig_buf) { + memcpy(orig_buf, buf, solid); + free(buf); + } + return ret; } /* -- 1.6.3.1 --------------------------------------------------------------------- dm-crypt mailing list - http://www.saout.de/misc/dm-crypt/ To unsubscribe, e-mail: dm-crypt-unsubscribe@xxxxxxxx For additional commands, e-mail: dm-crypt-help@xxxxxxxx