Commit e3e3027e authored by Milan Broz's avatar Milan Broz

Optimize o_direct read/writes.

* 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
parent a3c8571d
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.
......
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)
......
......@@ -11,6 +11,7 @@
#define SECTOR_SHIFT 9
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define DEFAULT_ALIGNMENT 4096
/* private struct crypt_options flags */
......
......@@ -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;
}
/*
......
......@@ -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);
......
......@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment