mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-25 13:57:15 +00:00
cpukit/jffs2: Fix unaligned writes
The code in flashio.c had a special case for handling unaligned buffers during writes. That code did roughly the following: If the size or start address of the buffer is not aligned to a word: * align the size up to the next word * create a temp buffer on heap or stack with the new size * copy the data from write buffer to this temp buffer * write the temp buffer with the _new_ size to the flash * tell the code above, that the original size has been written That means, that in certain cases, one to three random bytes have been written to the flash. That is definitively not correct. The special cases that trigger the behaviour seem to happen quite often when using the RTEMS functions to unpack a .tar.gz with files in the range of a few megabytes stored on the JFFS2 file system to the same file system. The RTEMS interface for flash drivers doesn't define any alignment requirements. Therefore that code is not necessary and can just be removed to solve these issues.
This commit is contained in:
@@ -65,74 +65,14 @@ jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
// writes need to be aligned but the data we're passed may not be
|
||||
// Observation suggests most unaligned writes are small, so we
|
||||
// optimize for that case.
|
||||
|
||||
if (((vecs[i].iov_len & (sizeof (int) - 1))) ||
|
||||
(((unsigned long) vecs[i].
|
||||
iov_base & (sizeof (unsigned long) - 1)))) {
|
||||
// are there iov's after this one? Or is it so much we'd need
|
||||
// to do multiple writes anyway?
|
||||
if ((i + 1) < count || vecs[i].iov_len > 256) {
|
||||
// cop out and malloc
|
||||
unsigned long j;
|
||||
ssize_t sizetomalloc = 0, totvecsize = 0;
|
||||
char *cbuf, *cbufptr;
|
||||
|
||||
for (j = i; j < count; j++)
|
||||
totvecsize += vecs[j].iov_len;
|
||||
|
||||
// pad up in case unaligned
|
||||
sizetomalloc = totvecsize + sizeof (int) - 1;
|
||||
sizetomalloc &= ~(sizeof (int) - 1);
|
||||
cbuf = (char *) malloc(sizetomalloc);
|
||||
// malloc returns aligned memory
|
||||
if (!cbuf) {
|
||||
ret = -ENOMEM;
|
||||
goto writev_out;
|
||||
}
|
||||
cbufptr = cbuf;
|
||||
for (j = i; j < count; j++) {
|
||||
memcpy(cbufptr, vecs[j].iov_base,
|
||||
vecs[j].iov_len);
|
||||
cbufptr += vecs[j].iov_len;
|
||||
}
|
||||
ret =
|
||||
jffs2_flash_write(c, to, sizetomalloc,
|
||||
&thislen, cbuf);
|
||||
if (thislen > totvecsize) // in case it was aligned up
|
||||
thislen = totvecsize;
|
||||
totlen += thislen;
|
||||
free(cbuf);
|
||||
goto writev_out;
|
||||
} else {
|
||||
// otherwise optimize for the common case
|
||||
int buf[256 / sizeof (int)]; // int, so int aligned
|
||||
size_t lentowrite;
|
||||
|
||||
lentowrite = vecs[i].iov_len;
|
||||
// pad up in case its unaligned
|
||||
lentowrite += sizeof (int) - 1;
|
||||
lentowrite &= ~(sizeof (int) - 1);
|
||||
memcpy(buf, vecs[i].iov_base, lentowrite);
|
||||
|
||||
ret =
|
||||
jffs2_flash_write(c, to, lentowrite,
|
||||
&thislen, (char *) &buf);
|
||||
if (thislen > vecs[i].iov_len)
|
||||
thislen = vecs[i].iov_len;
|
||||
} // else
|
||||
} else
|
||||
ret =
|
||||
jffs2_flash_write(c, to, vecs[i].iov_len, &thislen,
|
||||
vecs[i].iov_base);
|
||||
ret = jffs2_flash_write(c, to, vecs[i].iov_len, &thislen,
|
||||
vecs[i].iov_base);
|
||||
totlen += thislen;
|
||||
if (ret || thislen != vecs[i].iov_len)
|
||||
break;
|
||||
to += vecs[i].iov_len;
|
||||
}
|
||||
writev_out:
|
||||
|
||||
if (retlen)
|
||||
*retlen = totlen;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user