Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 162ada77 authored by Mike Marshall's avatar Mike Marshall
Browse files

Orangefs: improve the POSIXness of interrupted writes...



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

Signed-off-by: default avatarMike Marshall <hubcap@omnibond.com>
parent cf07c0bf
Loading
Loading
Loading
Loading
+45 −9
Original line number Diff line number Diff line
@@ -180,21 +180,57 @@ static ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inod
	}

	if (ret < 0) {
		if (ret == -EINTR) {
			/*
		 * don't write an error to syslog on signaled operation
		 * termination unless we've got debugging turned on, as
		 * this can happen regularly (i.e. ctrl-c)
			 * We can't return EINTR if any data was written,
			 * it's not POSIX. It is minimally acceptable
			 * 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)
			gossip_debug(GOSSIP_FILE_DEBUG,
				     "%s: returning error %ld\n", __func__,
				     (long)ret);
			switch (new_op->op_state - OP_VFS_STATE_GIVEN_UP) {
			/*
			 * If the op was waiting when the interrupt
			 * occurred, then the client-core did not
			 * trigger the write.
			 */
			case OP_VFS_STATE_WAITING:
				if (*offset == 0)
					ret = -EINTR;
				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",
				__func__,
				type == ORANGEFS_IO_READ ?
					"read from" : "write to",
				handle, ret);
		}
		if (orangefs_cancel_op_in_progress(new_op))
			return ret;