Commit 55182280 authored by Hirokazu Takahashi's avatar Hirokazu Takahashi Committed by Linus Torvalds

[PATCH] enhance ->sendfile(), allowing kNFSd to use it

I enhanced the sendfile method so that we could pass a proper actor to
it (which exposes the full power of the internal implementation).

Now knfsd calls the sendfile vector rather than depending on a
readpage() that hasn't been set up fully.
parent c51b4f46
......@@ -572,7 +572,6 @@ nfsd_get_raparms(dev_t dev, ino_t ino)
return ra;
}
#if 0 /* don't poke into fs code directly */
/*
* Grab and keep cached pages assosiated with a file in the svc_rqst
* so that they can be passed to the netowork sendmsg/sendpage routines
......@@ -605,30 +604,6 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
return size;
}
static inline ssize_t
nfsd_getpages(struct file *filp, struct svc_rqst *rqstp, unsigned long count)
{
read_descriptor_t desc;
ssize_t retval;
if (!count)
return 0;
svc_pushback_unused_pages(rqstp);
desc.written = 0;
desc.count = count;
desc.buf = (char *)rqstp;
desc.error = 0;
do_generic_file_read(filp, &filp->f_pos, &desc, nfsd_read_actor);
retval = desc.written;
if (!retval)
retval = desc.error;
return retval;
}
#endif
/*
* Read data from a file. count must contain the requested read count
* on entry. On return, *count contains the number of bytes actually read.
......@@ -660,13 +635,11 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (ra)
file.f_ra = ra->p_ra;
#if 0 /* don't poke into fs code directly */
if (inode->i_mapping->a_ops->readpage) {
file.f_pos = offset;
err = nfsd_getpages(&file, rqstp, *count);
} else
#endif
{
if (file.f_op->sendfile) {
svc_pushback_unused_pages(rqstp);
err = file.f_op->sendfile(&file, &offset, *count,
nfsd_read_actor, rqstp);
} else {
oldfs = get_fs();
set_fs(KERNEL_DS);
err = vfs_readv(&file, vec, vlen, &offset);
......
......@@ -565,7 +565,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
count = max - pos;
}
retval = in_file->f_op->sendfile(out_file, in_file, ppos, count);
retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
if (*ppos > max)
retval = -EOVERFLOW;
......
......@@ -735,6 +735,24 @@ struct block_device_operations {
struct module *owner;
};
/*
* "descriptor" for what we're up to with a read for sendfile().
* This allows us to use the same read code yet
* have multiple different users of the data that
* we read from a file.
*
* The simplest case just copies the data to user
* mode.
*/
typedef struct {
size_t written;
size_t count;
char * buf;
int error;
} read_descriptor_t;
typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long, unsigned long);
/*
* NOTE:
* read, write, poll, fsync, readv, writev can be called
......@@ -761,7 +779,7 @@ struct file_operations {
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
ssize_t (*sendfile) (struct file *, struct file *, loff_t *, size_t);
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
};
......@@ -1176,24 +1194,6 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
#include <linux/err.h>
/*
* "descriptor" for what we're up to with a read for sendfile().
* This allows us to use the same read code yet
* have multiple different users of the data that
* we read from a file.
*
* The simplest case just copies the data to user
* mode.
*/
typedef struct {
size_t written;
size_t count;
char * buf;
int error;
} read_descriptor_t;
typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long, unsigned long);
/* needed for stackable file system support */
extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
......@@ -1256,7 +1256,7 @@ extern ssize_t do_sync_read(struct file *filp, char *buf, size_t len, loff_t *pp
extern ssize_t do_sync_write(struct file *filp, const char *buf, size_t len, loff_t *ppos);
ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
unsigned long nr_segs, loff_t *ppos);
extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t);
extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
extern void do_generic_mapping_read(struct address_space *, struct file_ra_state *, struct file *,
loff_t *, read_descriptor_t *, read_actor_t);
extern void
......
......@@ -888,8 +888,8 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o
return written;
}
ssize_t generic_file_sendfile(struct file *out_file, struct file *in_file,
loff_t *ppos, size_t count)
ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos,
size_t count, read_actor_t actor, void *target)
{
read_descriptor_t desc;
......@@ -898,10 +898,10 @@ ssize_t generic_file_sendfile(struct file *out_file, struct file *in_file,
desc.written = 0;
desc.count = count;
desc.buf = (char *)out_file;
desc.buf = target;
desc.error = 0;
do_generic_file_read(in_file, ppos, &desc, file_send_actor);
do_generic_file_read(in_file, ppos, &desc, actor);
if (desc.written)
return desc.written;
return desc.error;
......
......@@ -1387,8 +1387,8 @@ static ssize_t shmem_file_read(struct file *filp, char *buf, size_t count, loff_
return desc.error;
}
static ssize_t shmem_file_sendfile(struct file *out_file,
struct file *in_file, loff_t *ppos, size_t count)
static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
size_t count, read_actor_t actor, void *target)
{
read_descriptor_t desc;
......@@ -1397,10 +1397,10 @@ static ssize_t shmem_file_sendfile(struct file *out_file,
desc.written = 0;
desc.count = count;
desc.buf = (char *)out_file;
desc.buf = target;
desc.error = 0;
do_shmem_file_read(in_file, ppos, &desc, file_send_actor);
do_shmem_file_read(in_file, ppos, &desc, actor);
if (desc.written)
return desc.written;
return desc.error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment