Skip to content

Commit

Permalink
NFS: remove support for multi-segment iovs in the direct read path
Browse files Browse the repository at this point in the history
Eliminate the persistent use of automatic storage in all parts of the NFS
client's direct read path to pave the way for introducing support for aio
against files opened with the O_DIRECT flag.

Test plan:
Compile the kernel with CONFIG_NFS and CONFIG_NFS_DIRECTIO enabled.
Millions of fsx-odirect ops.  OraSim.

Signed-off-by: Chuck Lever <cel@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Chuck Lever authored and Trond Myklebust committed Mar 20, 2006
1 parent 5dd602f commit 0cdd80d
Showing 1 changed file with 15 additions and 51 deletions.
66 changes: 15 additions & 51 deletions fs/nfs/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ static ssize_t nfs_direct_read_wait(struct nfs_direct_req *dreq, int intr)
return (ssize_t) result;
}

static ssize_t nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, unsigned int nr_pages)
static ssize_t nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, unsigned int nr_pages)
{
ssize_t result;
sigset_t oldset;
Expand All @@ -346,48 +346,6 @@ static ssize_t nfs_direct_read_seg(struct inode *inode, struct nfs_open_context
return result;
}

/*
* We've already pushed out any non-direct writes so that this read
* will see them when we read from the server.
*/
static ssize_t nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx, const struct iovec *iov, loff_t file_offset, unsigned long nr_segs)
{
ssize_t tot_bytes = 0;
unsigned long seg = 0;

while ((seg < nr_segs) && (tot_bytes >= 0)) {
ssize_t result;
int page_count;
struct page **pages;
const struct iovec *vec = &iov[seg++];
unsigned long user_addr = (unsigned long) vec->iov_base;
size_t size = vec->iov_len;

page_count = nfs_get_user_pages(READ, user_addr, size, &pages);
if (page_count < 0) {
nfs_free_user_pages(pages, 0, 0);
if (tot_bytes > 0)
break;
return page_count;
}

result = nfs_direct_read_seg(inode, ctx, user_addr, size,
file_offset, pages, page_count);

if (result <= 0) {
if (tot_bytes > 0)
break;
return result;
}
tot_bytes += result;
file_offset += result;
if (result < size)
break;
}

return tot_bytes;
}

static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx, unsigned long user_addr, size_t count, loff_t file_offset, struct page **pages, int nr_pages)
{
const unsigned int wsize = NFS_SERVER(inode)->wsize;
Expand Down Expand Up @@ -559,16 +517,13 @@ static ssize_t nfs_direct_write(struct inode *inode, struct nfs_open_context *ct
ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
{
ssize_t retval = -EINVAL;
loff_t *ppos = &iocb->ki_pos;
int page_count;
struct page **pages;
struct file *file = iocb->ki_filp;
struct nfs_open_context *ctx =
(struct nfs_open_context *) file->private_data;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
struct iovec iov = {
.iov_base = buf,
.iov_len = count,
};

dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
Expand All @@ -580,7 +535,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
if (count < 0)
goto out;
retval = -EFAULT;
if (!access_ok(VERIFY_WRITE, iov.iov_base, iov.iov_len))
if (!access_ok(VERIFY_WRITE, buf, count))
goto out;
retval = 0;
if (!count)
Expand All @@ -590,9 +545,18 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
if (retval)
goto out;

retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
page_count = nfs_get_user_pages(READ, (unsigned long) buf,
count, &pages);
if (page_count < 0) {
nfs_free_user_pages(pages, 0, 0);
retval = page_count;
goto out;
}

retval = nfs_direct_read(inode, ctx, (unsigned long) buf, count, pos,
pages, page_count);
if (retval > 0)
*ppos = pos + retval;
iocb->ki_pos = pos + retval;

out:
return retval;
Expand Down

0 comments on commit 0cdd80d

Please sign in to comment.