Orangefs: improve the POSIXness of interrupted writes...

Don't return EINTR on interrupted writes if some data has already
been written.

Signed-off-by: Mike Marshall <hubcap@omnibond.com>
This commit is contained in:
Mike Marshall 2016-03-09 13:12:37 -05:00
parent cf07c0bf88
commit 162ada7764

View file

@ -180,21 +180,57 @@ populate_shared_memory:
} }
if (ret < 0) { if (ret < 0) {
if (ret == -EINTR) {
/* /*
* don't write an error to syslog on signaled operation * We can't return EINTR if any data was written,
* termination unless we've got debugging turned on, as * it's not POSIX. It is minimally acceptable
* this can happen regularly (i.e. ctrl-c) * to give a partial write, the way NFS does.
*
* It would be optimal to return all or nothing,
* but if a userspace write is bigger than
* an IO buffer, and the interrupt occurs
* between buffer writes, that would not be
* possible.
*/ */
if (ret == -EINTR) switch (new_op->op_state - OP_VFS_STATE_GIVEN_UP) {
gossip_debug(GOSSIP_FILE_DEBUG, /*
"%s: returning error %ld\n", __func__, * If the op was waiting when the interrupt
(long)ret); * occurred, then the client-core did not
* trigger the write.
*/
case OP_VFS_STATE_WAITING:
if (*offset == 0)
ret = -EINTR;
else else
ret = 0;
break;
/*
* If the op was in progress when the interrupt
* occurred, then the client-core was able to
* trigger the write.
*/
case OP_VFS_STATE_INPROGR:
ret = total_size;
break;
default:
gossip_err("%s: unexpected op state :%d:.\n",
__func__,
new_op->op_state);
ret = 0;
break;
}
gossip_debug(GOSSIP_FILE_DEBUG,
"%s: got EINTR, state:%d: %p\n",
__func__,
new_op->op_state,
new_op);
} else {
gossip_err("%s: error in %s handle %pU, returning %zd\n", gossip_err("%s: error in %s handle %pU, returning %zd\n",
__func__, __func__,
type == ORANGEFS_IO_READ ? type == ORANGEFS_IO_READ ?
"read from" : "write to", "read from" : "write to",
handle, ret); handle, ret);
}
if (orangefs_cancel_op_in_progress(new_op)) if (orangefs_cancel_op_in_progress(new_op))
return ret; return ret;