diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-02-18 18:53:41 -0500 |
---|---|---|
committer | Mike Marshall <hubcap@omnibond.com> | 2016-02-19 13:45:55 -0500 |
commit | 5964c1b83912dd5052f66ceb50634df958129981 (patch) | |
tree | 09ff39527536bc1b0cfbba5a2f60536005304fa7 /fs/orangefs | |
parent | ddb84da38d0f050ff3582d5bb5e70cc7f2c6ef18 (diff) |
orangefs: set correct ->downcall.status on failing to copy reply from daemon
... and clean the end of control device ->write_iter() while we are at it
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
Diffstat (limited to 'fs/orangefs')
-rw-r--r-- | fs/orangefs/devorangefs-req.c | 61 |
1 files changed, 22 insertions, 39 deletions
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c index b27ed1cb9a36..89c282afeb29 100644 --- a/fs/orangefs/devorangefs-req.c +++ b/fs/orangefs/devorangefs-req.c @@ -333,8 +333,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, n = copy_from_iter(&op->downcall, downcall_size, iter); if (n != downcall_size) { gossip_err("%s: failed to copy downcall.\n", __func__); - ret = -EFAULT; - goto Broken; + goto Efault; } if (op->downcall.status) @@ -354,8 +353,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, downcall_size, op->downcall.trailer_size, total); - ret = -EFAULT; - goto Broken; + goto Efault; } /* Only READDIR operations should have trailers. */ @@ -364,8 +362,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, gossip_err("%s: %x operation with trailer.", __func__, op->downcall.type); - ret = -EFAULT; - goto Broken; + goto Efault; } /* READDIR operations should always have trailers. */ @@ -374,8 +371,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, gossip_err("%s: %x operation with no trailer.", __func__, op->downcall.type); - ret = -EFAULT; - goto Broken; + goto Efault; } if (op->downcall.type != ORANGEFS_VFS_OP_READDIR) @@ -386,8 +382,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, if (op->downcall.trailer_buf == NULL) { gossip_err("%s: failed trailer vmalloc.\n", __func__); - ret = -ENOMEM; - goto Broken; + goto Enomem; } memset(op->downcall.trailer_buf, 0, op->downcall.trailer_size); n = copy_from_iter(op->downcall.trailer_buf, @@ -396,8 +391,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, if (n != op->downcall.trailer_size) { gossip_err("%s: failed to copy trailer.\n", __func__); vfree(op->downcall.trailer_buf); - ret = -EFAULT; - goto Broken; + goto Efault; } wakeup: @@ -406,38 +400,27 @@ wakeup: * that this op is done */ spin_lock(&op->lock); - if (unlikely(op_state_given_up(op))) { + if (unlikely(op_is_cancel(op))) { spin_unlock(&op->lock); - goto out; - } - set_op_state_serviced(op); - spin_unlock(&op->lock); - - /* - * If this operation is an I/O operation we need to wait - * for all data to be copied before we can return to avoid - * buffer corruption and races that can pull the buffers - * out from under us. - * - * Essentially we're synchronizing with other parts of the - * vfs implicitly by not allowing the user space - * application reading/writing this device to return until - * the buffers are done being used. - */ -out: - if (unlikely(op_is_cancel(op))) put_cancel(op); + } else if (unlikely(op_state_given_up(op))) { + spin_unlock(&op->lock); + } else { + set_op_state_serviced(op); + spin_unlock(&op->lock); + } op_release(op); return ret; -Broken: - spin_lock(&op->lock); - if (!op_state_given_up(op)) { - op->downcall.status = ret; - set_op_state_serviced(op); - } - spin_unlock(&op->lock); - goto out; +Efault: + op->downcall.status = -(ORANGEFS_ERROR_BIT | 9); + ret = -EFAULT; + goto wakeup; + +Enomem: + op->downcall.status = -(ORANGEFS_ERROR_BIT | 8); + ret = -ENOMEM; + goto wakeup; } /* Returns whether any FS are still pending remounted */ |