summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorCyril Plisko <[email protected]>2012-09-13 23:25:15 +0300
committerBrian Behlendorf <[email protected]>2012-09-17 11:06:58 -0700
commit49d39798f286cce2497a87fc06d78c051ca87570 (patch)
tree8eebad026e5f70e9ea45c017b9cc12cab66db701 /module/zfs
parent8312c6df55c1fb2ad3536fc3bc7ae93c429b85aa (diff)
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 <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #933
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/zfs_replay.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c
index 782d5582b..aa6366e11 100644
--- a/module/zfs/zfs_replay.c
+++ b/module/zfs/zfs_replay.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 Cyril Plisko. All rights reserved.
*/
#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 */
znode_t *zp;
- int error;
+ int error, written;
uint64_t eod, offset, length;
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;
}
- error = zpl_write_common(ZTOI(zp), data, length, offset,
+ written = zpl_write_common(ZTOI(zp), data, length, offset,
UIO_SYSSPACE, 0, kcred);
- if (error) {
- if (error < 0)
- error = -error;
- else
- error = EIO; /* Short write */
- }
+ if (written < 0)
+ error = -written;
+ else if (written < length)
+ error = EIO; /* short write */
iput(ZTOI(zp));
zsb->z_replay_eof = 0; /* safety */