dovecot-1.2: ostream: Make sure writing to files always fully su...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Aug 30 13:21:22 EEST 2008
details: http://hg.dovecot.org/dovecot-1.2/rev/744f9dbff89c
changeset: 8124:744f9dbff89c
user: Timo Sirainen <tss at iki.fi>
date: Sat Aug 30 13:21:18 2008 +0300
description:
ostream: Make sure writing to files always fully succeeds or fails.
Don't allow partial writes (to NFS).
diffstat:
1 file changed, 47 insertions(+), 4 deletions(-)
src/lib/ostream-file.c | 51 ++++++++++++++++++++++++++++++++++++++++++++----
diffs (98 lines):
diff -r 26b67708b365 -r 744f9dbff89c src/lib/ostream-file.c
--- a/src/lib/ostream-file.c Sat Aug 30 12:34:34 2008 +0300
+++ b/src/lib/ostream-file.c Sat Aug 30 13:21:18 2008 +0300
@@ -161,8 +161,9 @@ static ssize_t o_stream_writev(struct fi
static ssize_t o_stream_writev(struct file_ostream *fstream,
const struct const_iovec *iov, int iov_size)
{
- ssize_t ret;
+ ssize_t ret, ret2;
size_t size, sent;
+ bool partial;
int i;
o_stream_socket_cork(fstream);
@@ -176,11 +177,12 @@ static ssize_t o_stream_writev(struct fi
ret = pwrite(fstream->fd, iov->iov_base, iov->iov_len,
fstream->buffer_offset);
}
+ partial = ret != (ssize_t)iov->iov_len;
} else {
if (o_stream_lseek(fstream) < 0)
return -1;
- sent = 0;
+ sent = 0; partial = FALSE;
while (iov_size > IOV_MAX) {
size = 0;
for (i = 0; i < IOV_MAX; i++)
@@ -188,8 +190,10 @@ static ssize_t o_stream_writev(struct fi
ret = writev(fstream->fd, (const struct iovec *)iov,
IOV_MAX);
- if (ret != (ssize_t)size)
+ if (ret != (ssize_t)size) {
+ partial = TRUE;
break;
+ }
fstream->real_offset += ret;
fstream->buffer_offset += ret;
@@ -199,8 +203,13 @@ static ssize_t o_stream_writev(struct fi
}
if (iov_size <= IOV_MAX) {
+ size = 0;
+ for (i = 0; i < iov_size; i++)
+ size += iov[i].iov_len;
+
ret = writev(fstream->fd, (const struct iovec *)iov,
iov_size);
+ partial = ret != (ssize_t)size;
}
if (ret > 0) {
fstream->real_offset += ret;
@@ -224,8 +233,42 @@ static ssize_t o_stream_writev(struct fi
stream_closed(fstream);
return -1;
}
-
fstream->buffer_offset += ret;
+ if (partial && fstream->file) {
+ /* we failed to write everything to a file. either we ran out
+ of disk space or we're writing to NFS. try to write the
+ rest to resolve this. */
+ size = ret;
+ while (iov_size > 0 && size >= iov->iov_len) {
+ size -= iov->iov_len;
+ iov++;
+ iov_size--;
+ }
+ i_assert(iov_size > 0);
+ if (size == 0)
+ ret2 = o_stream_writev(fstream, iov, iov_size);
+ else {
+ /* write the first iov separately */
+ struct const_iovec new_iov;
+
+ new_iov.iov_base =
+ CONST_PTR_OFFSET(iov->iov_base, size);
+ new_iov.iov_len = iov->iov_len - size;
+ ret2 = o_stream_writev(fstream, &new_iov, 1);
+ if (ret2 > 0) {
+ i_assert((size_t)ret2 == new_iov.iov_len);
+ /* write the rest */
+ if (iov_size > 1) {
+ ret += ret2;
+ ret2 = o_stream_writev(fstream, iov + 1,
+ iov_size - 1);
+ }
+ }
+ }
+ if (ret2 <= 0)
+ return ret2;
+ ret += ret2;
+ }
return ret;
}
More information about the dovecot-cvs
mailing list