VirtualBox

Ignore:
Timestamp:
Jan 4, 2018 4:56:53 PM (7 years ago)
Author:
vboxsync
Message:

Fix Guest Additions vboxsf sendfile() caching problems (see #2548), for older linux kernels (e.g. 2.6.23 <= linux kernel < 2.6.31)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/sharedfolders/regops.c

    r69500 r70460  
    9292}
    9393
     94#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && \
     95    LINUX_VERSION_CODE <  KERNEL_VERSION(2, 6, 31)
     96
     97void free_pipebuf(struct page *kpage)
     98{
     99    kunmap(kpage);
     100    __free_pages(kpage, 0);
     101}
     102
     103void *sf_pipe_buf_map(struct pipe_inode_info *pipe,
     104                           struct pipe_buffer *pipe_buf, int atomic)
     105{
     106    return 0;
     107}
     108
     109void sf_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *pipe_buf)
     110{
     111}
     112
     113void sf_pipe_buf_unmap(struct pipe_inode_info *pipe,  struct pipe_buffer *pipe_buf, void *map_data)
     114{
     115}
     116
     117int sf_pipe_buf_steal(struct pipe_inode_info *pipe,
     118                           struct pipe_buffer *pipe_buf) {
     119        return 0;
     120}
     121
     122static void sf_pipe_buf_release(struct pipe_inode_info *pipe,
     123                                  struct pipe_buffer *pipe_buf)
     124{
     125    free_pipebuf(pipe_buf->page);
     126}
     127
     128int sf_pipe_buf_confirm(struct pipe_inode_info *info,
     129                             struct pipe_buffer *pipe_buf)
     130{
     131        return 0;
     132}
     133
     134static struct pipe_buf_operations sf_pipe_buf_ops = {
     135    .can_merge = 0,
     136    .map = sf_pipe_buf_map,
     137    .unmap = sf_pipe_buf_unmap,
     138    .confirm = sf_pipe_buf_confirm,
     139    .release = sf_pipe_buf_release,
     140    .steal = sf_pipe_buf_steal,
     141    .get = sf_pipe_buf_get,
     142};
     143
     144#define LOCK_PIPE(pipe) \
     145    if (pipe->inode) \
     146        mutex_lock(&pipe->inode->i_mutex);
     147
     148#define UNLOCK_PIPE(pipe) \
     149    if (pipe->inode) \
     150        mutex_unlock(&pipe->inode->i_mutex);
     151
     152ssize_t
     153sf_splice_read(struct file *in, loff_t *poffset,
     154                                 struct pipe_inode_info *pipe, size_t len,
     155                                 unsigned int flags)
     156{
     157    size_t bytes_remaining = len;
     158    loff_t orig_offset = *poffset;
     159    loff_t offset = orig_offset;
     160    struct inode *inode = GET_F_DENTRY(in)->d_inode;
     161    struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
     162    struct sf_reg_info *sf_r = in->private_data;
     163    ssize_t retval;
     164    struct page *kpage = 0;
     165    size_t nsent = 0;
     166
     167    TRACE();
     168    if (!S_ISREG(inode->i_mode))
     169    {
     170        LogFunc(("read from non regular file %d\n", inode->i_mode));
     171        return -EINVAL;
     172    }
     173    if (!len) {
     174        return 0;
     175    }
     176
     177    LOCK_PIPE(pipe);
     178
     179    uint32_t req_size = 0;
     180    while (bytes_remaining > 0)
     181    {
     182        kpage = alloc_page(GFP_KERNEL);
     183        if (unlikely(kpage == NULL))
     184        {
     185            UNLOCK_PIPE(pipe);
     186            return -ENOMEM;
     187        }
     188        req_size = 0;
     189        uint32_t nread = req_size = (uint32_t)min(bytes_remaining, (size_t)PAGE_SIZE);
     190        uint32_t chunk = 0;
     191        void *kbuf = kmap(kpage);
     192        while (chunk < req_size)
     193        {
     194            retval = sf_reg_read_aux(__func__, sf_g, sf_r, kbuf + chunk, &nread, offset);
     195            if (retval < 0)
     196                goto err;
     197            if (nread == 0)
     198                break;
     199            chunk += nread;
     200            offset += nread;
     201            nread = req_size - chunk;
     202        }
     203        if (!pipe->readers)
     204        {
     205            send_sig(SIGPIPE, current, 0);
     206            retval = -EPIPE;
     207            goto err;
     208        }
     209        if (pipe->nrbufs < PIPE_BUFFERS)
     210        {
     211            struct pipe_buffer *pipebuf =
     212                pipe->bufs + ((pipe->curbuf + pipe->nrbufs) & (PIPE_BUFFERS - 1));
     213            pipebuf->page = kpage;
     214            pipebuf->ops = &sf_pipe_buf_ops;
     215            pipebuf->len = req_size;
     216            pipebuf->offset = 0;
     217            pipebuf->private = 0;
     218            pipebuf->flags = 0;
     219            pipe->nrbufs++;
     220            nsent += req_size;
     221            bytes_remaining -= req_size;
     222            if (signal_pending(current))
     223                break;
     224        }
     225        else /* pipe full */
     226        {
     227            if (flags & SPLICE_F_NONBLOCK) {
     228                retval = -EAGAIN;
     229                goto err;
     230            }
     231            free_pipebuf(kpage);
     232            break;
     233        }
     234    }
     235    UNLOCK_PIPE(pipe);
     236    if (!nsent && signal_pending(current))
     237        return -ERESTARTSYS;
     238    *poffset += nsent;
     239    return offset - orig_offset;
     240
     241err:
     242    UNLOCK_PIPE(pipe);
     243    free_pipebuf(kpage);
     244    return retval;
     245}
     246
     247#endif
     248
    94249/**
    95250 * Read from a regular file.
     
    567722 * cached.  Investigate. */
    568723#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
    569     .splice_read = generic_file_splice_read,
     724    .splice_read = sf_splice_read,
    570725#  else
    571726    .sendfile    = generic_file_sendfile,
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette