return dreq;
}
-static void nfs_direct_req_release(struct kref *kref)
+static void nfs_direct_req_free(struct kref *kref)
{
struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref);
kmem_cache_free(nfs_direct_cachep, dreq);
}
+static void nfs_direct_req_release(struct nfs_direct_req *dreq)
+{
+ kref_put(&dreq->kref, nfs_direct_req_free);
+}
+
/*
* Collects and returns the final error value/byte-count.
*/
result = dreq->count;
out:
- kref_put(&dreq->kref, nfs_direct_req_release);
return (ssize_t) result;
}
}
complete_all(&dreq->completion);
- kref_put(&dreq->kref, nfs_direct_req_release);
+ nfs_direct_req_release(dreq);
}
/*
static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos)
{
struct nfs_open_context *ctx = dreq->ctx;
- struct inode *inode = ctx->dentry->d_inode;
+ struct inode *inode = ctx->path.dentry->d_inode;
size_t rsize = NFS_SERVER(inode)->rsize;
unsigned int pgbase;
int result;
break;
}
if ((unsigned)result < data->npages) {
- nfs_direct_release_pages(data->pagevec, result);
- nfs_readdata_release(data);
- break;
+ bytes = result * PAGE_SIZE;
+ if (bytes <= pgbase) {
+ nfs_direct_release_pages(data->pagevec, result);
+ nfs_readdata_release(data);
+ break;
+ }
+ bytes -= pgbase;
+ data->npages = result;
}
get_dreq(dreq);
if (!result)
result = nfs_direct_wait(dreq);
rpc_clnt_sigunmask(clnt, &oldset);
+ nfs_direct_req_release(dreq);
return result;
}
static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync)
{
struct nfs_open_context *ctx = dreq->ctx;
- struct inode *inode = ctx->dentry->d_inode;
+ struct inode *inode = ctx->path.dentry->d_inode;
size_t wsize = NFS_SERVER(inode)->wsize;
unsigned int pgbase;
int result;
break;
}
if ((unsigned)result < data->npages) {
- nfs_direct_release_pages(data->pagevec, result);
- nfs_writedata_release(data);
- break;
+ bytes = result * PAGE_SIZE;
+ if (bytes <= pgbase) {
+ nfs_direct_release_pages(data->pagevec, result);
+ nfs_writedata_release(data);
+ break;
+ }
+ bytes -= pgbase;
+ data->npages = result;
}
get_dreq(dreq);
if (!result)
result = nfs_direct_wait(dreq);
rpc_clnt_sigunmask(clnt, &oldset);
+ nfs_direct_req_release(dreq);
return result;
}
(unsigned long) count, (long long) pos);
if (nr_segs != 1)
- return -EINVAL;
-
- if (count < 0)
goto out;
+
retval = -EFAULT;
if (!access_ok(VERIFY_WRITE, buf, count))
goto out;
ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
- ssize_t retval;
+ ssize_t retval = -EINVAL;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
/* XXX: temporary */
(unsigned long) count, (long long) pos);
if (nr_segs != 1)
- return -EINVAL;
+ goto out;
retval = generic_write_checks(file, &pos, &count, 0);
if (retval)
sizeof(struct nfs_direct_req),
0, (SLAB_RECLAIM_ACCOUNT|
SLAB_MEM_SPREAD),
- NULL, NULL);
+ NULL);
if (nfs_direct_cachep == NULL)
return -ENOMEM;