orangefs: move handle_io_error() to file.c

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 7af0adb..c585063 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -14,11 +14,6 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 
-#define wake_up_daemon_for_return(op)			\
-do {							\
-	complete(&op->done);				\
-} while (0)
-
 /*
  * Copy to client-core's address space from the buffers specified
  * by the iovec upto total_size bytes.
@@ -88,6 +83,46 @@
 }
 
 /*
+ * handles two possible error cases, depending on context.
+ *
+ * by design, our vfs i/o errors need to be handled in one of two ways,
+ * depending on where the error occured.
+ *
+ * if the error happens in the waitqueue code because we either timed
+ * out or a signal was raised while waiting, we need to cancel the
+ * userspace i/o operation and free the op manually.  this is done to
+ * avoid having the device start writing application data to our shared
+ * bufmap pages without us expecting it.
+ *
+ * FIXME: POSSIBLE OPTIMIZATION:
+ * However, if we timed out or if we got a signal AND our upcall was never
+ * picked off the queue (i.e. we were in OP_VFS_STATE_WAITING), then we don't
+ * need to send a cancellation upcall. The way we can handle this is
+ * set error_exit to 2 in such cases and 1 whenever cancellation has to be
+ * sent and have handle_error
+ * take care of this situation as well..
+ *
+ * if a orangefs sysint level error occured and i/o has been completed,
+ * there is no need to cancel the operation, as the user has finished
+ * using the bufmap page and so there is no danger in this case.  in
+ * this case, we wake up the device normally so that it may free the
+ * op, as normal.
+ *
+ * note the only reason this is a macro is because both read and write
+ * cases need the exact same handling code.
+ */
+#define handle_io_error()					\
+do {								\
+	if (!op_state_serviced(new_op)) {			\
+		orangefs_cancel_op_in_progress(new_op->tag);	\
+	} else {						\
+		complete(&new_op->done);			\
+	}							\
+	orangefs_bufmap_put(bufmap, buffer_index);		\
+	buffer_index = -1;					\
+} while (0)
+
+/*
  * Post and wait for the I/O upcall to finish
  */
 static ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inode,
@@ -232,7 +267,7 @@
 	 * tell the device file owner waiting on I/O that this read has
 	 * completed and it can return now.
 	 */
-	wake_up_daemon_for_return(new_op);
+	complete(&new_op->done);
 
 out:
 	if (buffer_index >= 0) {