@@ -219,6 +219,17 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
long res = (long) dreq->error;
if (!res)
res = (long) dreq->count;
+ /*
+ * vfs doesn't want us drop kiocb->ki_users in error case.
+ * we get an extra ref on it then later drop it in aio_complete
+ */
+ if (dreq->error) {
+ struct kioctx *ctx = dreq->iocb->ki_ctx;
+
+ spin_lock_irq(&ctx->ctx_lock);
+ dreq->iocb->ki_users ++;
+ spin_unlock_irq(&ctx->ctx_lock);
+ }
aio_complete(dreq->iocb, res, 0);
}
complete_all(&dreq->completion);
@@ -319,6 +330,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
data->npages, 1, 0, data->pagevec, NULL);
up_read(¤t->mm->mmap_sem);
if (result < 0) {
+ dreq->error = result;
nfs_readdata_free(data);
break;
}
@@ -357,8 +369,10 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
NFS_PROTO(inode)->read_setup(data, &msg);
task = rpc_run_task(&task_setup_data);
- if (IS_ERR(task))
+ if (IS_ERR(task)) {
+ dreq->error = PTR_ERR(task);
break;
+ }
rpc_put_task(task);
dprintk("NFS: %5u initiated direct read call "
@@ -748,6 +762,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
data->npages, 0, 0, data->pagevec, NULL);
up_read(¤t->mm->mmap_sem);
if (result < 0) {
+ dreq->error = result;
nfs_writedata_free(data);
break;
}
@@ -789,8 +804,10 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
NFS_PROTO(inode)->write_setup(data, &msg);
task = rpc_run_task(&task_setup_data);
- if (IS_ERR(task))
+ if (IS_ERR(task)) {
+ dreq->error = PTR_ERR(task);
break;
+ }
rpc_put_task(task);
dprintk("NFS: %5u initiated direct write call "