+
+ /*
+ * Set the operation to be in progress and move it between lists since
+ * it has been sent to the client.
+ */
+ set_op_state_inprogress(cur_op);
+
+ list_del(&cur_op->list);
+ spin_unlock(&pvfs2_request_list_lock);
+ pvfs2_devreq_add_op(cur_op);
+ spin_unlock(&cur_op->lock);
+
+ /* Push the upcall out. */
+ ret = copy_to_user(buf, &proto_ver, sizeof(__s32));
+ if (ret != 0)
+ goto error;
+ ret = copy_to_user(buf+sizeof(__s32), &magic, sizeof(__s32));
+ if (ret != 0)
+ goto error;
+ ret = copy_to_user(buf+2 * sizeof(__s32), &cur_op->tag, sizeof(__u64));
+ if (ret != 0)
+ goto error;
+ ret = copy_to_user(buf+2*sizeof(__s32)+sizeof(__u64), &cur_op->upcall,
+ sizeof(struct pvfs2_upcall_s));
+ if (ret != 0)
+ goto error;
+
+ /* The client only asks to read one size buffer. */
+ return MAX_ALIGNED_DEV_REQ_UPSIZE;
+error:
+ /*
+ * We were unable to copy the op data to the client. Put the op back in
+ * list. If client has crashed, the op will be purged later when the
+ * device is released.
+ */
+ gossip_err("orangefs: Failed to copy data to user space\n");
+ spin_lock(&pvfs2_request_list_lock);
+ spin_lock(&cur_op->lock);
+ set_op_state_waiting(cur_op);
+ pvfs2_devreq_remove_op(cur_op->tag);
+ list_add(&cur_op->list, &pvfs2_request_list);
+ spin_unlock(&cur_op->lock);
+ spin_unlock(&pvfs2_request_list_lock);
+ return -EFAULT;