lkml.org 
[lkml]   [2002]   [Oct]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] tmpfs 5/9 shmem_file_sendfile
Added shmem_file_sendfile to allow sendfile from tmpfs.  Checked
do_shmem_file_read and shmem_file_read against filemap equivalents
to add in any recent fixes (-EINVAL when count < 0 was missing).

--- tmpfs4/include/linux/fs.h Wed Oct 16 06:31:04 2002
+++ tmpfs5/include/linux/fs.h Thu Oct 17 22:01:29 2002
@@ -1242,6 +1242,7 @@

extern int generic_file_mmap(struct file *, struct vm_area_struct *);
extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
+extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
extern ssize_t generic_file_aio_read(struct kiocb *, char *, size_t, loff_t);
--- tmpfs4/mm/filemap.c Wed Oct 16 06:31:04 2002
+++ tmpfs5/mm/filemap.c Thu Oct 17 22:01:29 2002
@@ -906,7 +906,7 @@
return ret;
}

-static int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
+int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
{
ssize_t written;
unsigned long count = desc->count;
--- tmpfs4/mm/shmem.c Thu Oct 17 22:01:19 2002
+++ tmpfs5/mm/shmem.c Thu Oct 17 22:01:29 2002
@@ -1136,19 +1136,18 @@
goto release;
}

-static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc)
+static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
{
struct inode *inode = filp->f_dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
unsigned long index, offset;
- int nr = 1;

index = *ppos >> PAGE_CACHE_SHIFT;
offset = *ppos & ~PAGE_CACHE_MASK;

- while (nr && desc->count) {
+ for (;;) {
struct page *page;
- unsigned long end_index, nr;
+ unsigned long end_index, nr, ret;

end_index = inode->i_size >> PAGE_CACHE_SHIFT;
if (index > end_index)
@@ -1181,6 +1180,10 @@
}
nr -= offset;

+ /* If users can be writing to this page using arbitrary
+ * virtual addresses, take care about potential aliasing
+ * before reading the page on the kernel side.
+ */
if (!list_empty(&mapping->i_mmap_shared) &&
page != ZERO_PAGE(0))
flush_dcache_page(page);
@@ -1195,12 +1198,14 @@
* "pos" here (the actor routine has to update the user buffer
* pointers and the remaining count).
*/
- nr = file_read_actor(desc, page, offset, nr);
- offset += nr;
+ ret = actor(desc, page, offset, nr);
+ offset += ret;
index += offset >> PAGE_CACHE_SHIFT;
offset &= ~PAGE_CACHE_MASK;

page_cache_release(page);
+ if (ret != nr || !desc->count)
+ break;
}

*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
@@ -1209,27 +1214,43 @@

static ssize_t shmem_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
{
- ssize_t retval;
+ read_descriptor_t desc;

- retval = -EFAULT;
- if (access_ok(VERIFY_WRITE, buf, count)) {
- retval = 0;
-
- if (count) {
- read_descriptor_t desc;
-
- desc.written = 0;
- desc.count = count;
- desc.buf = buf;
- desc.error = 0;
- do_shmem_file_read(filp, ppos, &desc);
-
- retval = desc.written;
- if (!retval)
- retval = desc.error;
- }
- }
- return retval;
+ if ((ssize_t) count < 0)
+ return -EINVAL;
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
+ if (!count)
+ return 0;
+
+ desc.written = 0;
+ desc.count = count;
+ desc.buf = buf;
+ desc.error = 0;
+
+ do_shmem_file_read(filp, ppos, &desc, file_read_actor);
+ if (desc.written)
+ return desc.written;
+ return desc.error;
+}
+
+static ssize_t shmem_file_sendfile(struct file *out_file,
+ struct file *in_file, loff_t *ppos, size_t count)
+{
+ read_descriptor_t desc;
+
+ if (!count)
+ return 0;
+
+ desc.written = 0;
+ desc.count = count;
+ desc.buf = (char *)out_file;
+ desc.error = 0;
+
+ do_shmem_file_read(in_file, ppos, &desc, file_send_actor);
+ if (desc.written)
+ return desc.written;
+ return desc.error;
}

static int shmem_statfs(struct super_block *sb, struct statfs *buf)
@@ -1649,6 +1670,7 @@
.read = shmem_file_read,
.write = shmem_file_write,
.fsync = simple_sync_file,
+ .sendfile = shmem_file_sendfile,
#endif
};

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:30    [W:0.044 / U:0.448 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site