diff options
author | Mike Marshall <hubcap@omnibond.com> | 2016-03-09 13:12:37 -0500 |
---|---|---|
committer | Mike Marshall <hubcap@omnibond.com> | 2016-03-09 13:12:37 -0500 |
commit | 162ada7764162eb2eb0a02546f820ca8b099cdea (patch) | |
tree | 6fc674756ae2646012bef5539ea6fdf7a088faa4 | |
parent | cf07c0bf88b7e8765361e808b61fef287caedfe3 (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.c | 54 |
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 | ||