ZFS replay transaction error 5

When zfs_replay_write() replays TX_WRITE records from ZIL
it calls zpl_write_common() to perform the actual write.
zpl_write_common() returns the number of bytes written
(similar to write() system call) or an (negative) error.
However, the code expects the positive return value to be
a residual counter. Thus when zpl_write_common() successfully
completes it is mistakenly considered to be a partial write and
the error code delivered further. At this point the ZIL processing
is aborted with famous "ZFS replay transaction error 5" error
message given to the message buffer.

The fix is to compare the zpl_write_commmon() return value with
the buffer size and flag error only when they disagree.

Signed-off-by: Cyril Plisko <cyril.plisko@mountall.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #933
This commit is contained in:
Cyril Plisko 2012-09-13 23:25:15 +03:00 committed by Brian Behlendorf
parent 8312c6df55
commit 49d39798f2

View File

@ -20,6 +20,7 @@
*/ */
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 Cyril Plisko. All rights reserved.
*/ */
#include <sys/types.h> #include <sys/types.h>
@ -626,7 +627,7 @@ zfs_replay_write(zfs_sb_t *zsb, lr_write_t *lr, boolean_t byteswap)
{ {
char *data = (char *)(lr + 1); /* data follows lr_write_t */ char *data = (char *)(lr + 1); /* data follows lr_write_t */
znode_t *zp; znode_t *zp;
int error; int error, written;
uint64_t eod, offset, length; uint64_t eod, offset, length;
if (byteswap) if (byteswap)
@ -671,14 +672,12 @@ zfs_replay_write(zfs_sb_t *zsb, lr_write_t *lr, boolean_t byteswap)
zsb->z_replay_eof = eod; zsb->z_replay_eof = eod;
} }
error = zpl_write_common(ZTOI(zp), data, length, offset, written = zpl_write_common(ZTOI(zp), data, length, offset,
UIO_SYSSPACE, 0, kcred); UIO_SYSSPACE, 0, kcred);
if (error) { if (written < 0)
if (error < 0) error = -written;
error = -error; else if (written < length)
else error = EIO; /* short write */
error = EIO; /* Short write */
}
iput(ZTOI(zp)); iput(ZTOI(zp));
zsb->z_replay_eof = 0; /* safety */ zsb->z_replay_eof = 0; /* safety */