aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Marshall <hubcap@omnibond.com>2016-03-09 13:12:37 -0500
committerMike Marshall <hubcap@omnibond.com>2016-03-09 13:12:37 -0500
commit162ada7764162eb2eb0a02546f820ca8b099cdea (patch)
tree6fc674756ae2646012bef5539ea6fdf7a088faa4
parentcf07c0bf88b7e8765361e808b61fef287caedfe3 (diff)
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>
-rw-r--r--fs/orangefs/file.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 6f2e0f745c5d..9b561b7894b3 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -180,21 +180,57 @@ populate_shared_memory:
180 } 180 }
181 181
182 if (ret < 0) { 182 if (ret < 0) {
183 /* 183 if (ret == -EINTR) {
184 * don't write an error to syslog on signaled operation 184 /*
185 * termination unless we've got debugging turned on, as 185 * We can't return EINTR if any data was written,
186 * this can happen regularly (i.e. ctrl-c) 186 * it's not POSIX. It is minimally acceptable
187 */ 187 * to give a partial write, the way NFS does.
188 if (ret == -EINTR) 188 *
189 * It would be optimal to return all or nothing,
190 * but if a userspace write is bigger than
191 * an IO buffer, and the interrupt occurs
192 * between buffer writes, that would not be
193 * possible.
194 */
195 switch (new_op->op_state - OP_VFS_STATE_GIVEN_UP) {
196 /*
197 * If the op was waiting when the interrupt
198 * occurred, then the client-core did not
199 * trigger the write.
200 */
201 case OP_VFS_STATE_WAITING:
202 if (*offset == 0)
203 ret = -EINTR;
204 else
205 ret = 0;
206 break;
207 /*
208 * If the op was in progress when the interrupt
209 * occurred, then the client-core was able to
210 * trigger the write.
211 */
212 case OP_VFS_STATE_INPROGR:
213 ret = total_size;
214 break;
215 default:
216 gossip_err("%s: unexpected op state :%d:.\n",
217 __func__,
218 new_op->op_state);
219 ret = 0;
220 break;
221 }
189 gossip_debug(GOSSIP_FILE_DEBUG, 222 gossip_debug(GOSSIP_FILE_DEBUG,
190 "%s: returning error %ld\n", __func__, 223 "%s: got EINTR, state:%d: %p\n",
191 (long)ret); 224 __func__,
192 else 225 new_op->op_state,
226 new_op);
227 } else {
193 gossip_err("%s: error in %s handle %pU, returning %zd\n", 228 gossip_err("%s: error in %s handle %pU, returning %zd\n",
194 __func__, 229 __func__,
195 type == ORANGEFS_IO_READ ? 230 type == ORANGEFS_IO_READ ?
196 "read from" : "write to", 231 "read from" : "write to",
197 handle, ret); 232 handle, ret);
233 }
198 if (orangefs_cancel_op_in_progress(new_op)) 234 if (orangefs_cancel_op_in_progress(new_op))
199 return ret; 235 return ret;
200 236