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.037 / U:0.360 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site