[PATCH] rework write_blockwise() and read_blockwise()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Device Mapper Devel]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]     [Fedora Docs]

  Powered by Linux