KVM: MMU: invalidate and flush on spte small->large page size change
[safe/jmp/linux-2.6] / kernel / relay.c
index 32b0bef..c7cf397 100644 (file)
@@ -60,7 +60,7 @@ static int relay_buf_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 /*
  * vm_ops for relay file mappings.
  */
-static struct vm_operations_struct relay_file_mmap_ops = {
+static const struct vm_operations_struct relay_file_mmap_ops = {
        .fault = relay_buf_fault,
        .close = relay_file_mmap_close,
 };
@@ -539,7 +539,7 @@ static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb,
                                        "relay_hotcpu_callback: cpu %d buffer "
                                        "creation failed\n", hotcpu);
                                mutex_unlock(&relay_channels_mutex);
-                               return NOTIFY_BAD;
+                               return notifier_from_errno(-ENOMEM);
                        }
                }
                mutex_unlock(&relay_channels_mutex);
@@ -663,8 +663,10 @@ int relay_late_setup_files(struct rchan *chan,
 
        mutex_lock(&relay_channels_mutex);
        /* Is chan already set up? */
-       if (unlikely(chan->has_base_filename))
+       if (unlikely(chan->has_base_filename)) {
+               mutex_unlock(&relay_channels_mutex);
                return -EEXIST;
+       }
        chan->has_base_filename = 1;
        chan->parent = parent;
        curr_cpu = get_cpu();
@@ -675,9 +677,7 @@ int relay_late_setup_files(struct rchan *chan,
         */
        for_each_online_cpu(i) {
                if (unlikely(!chan->buf[i])) {
-                       printk(KERN_ERR "relay_late_setup_files: CPU %u "
-                                       "has no buffer, it must have!\n", i);
-                       BUG();
+                       WARN_ONCE(1, KERN_ERR "CPU has no buffer!\n");
                        err = -EINVAL;
                        break;
                }
@@ -748,7 +748,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
                         * from the scheduler (trying to re-grab
                         * rq->lock), so defer it.
                         */
-                       __mod_timer(&buf->timer, jiffies + 1);
+                       mod_timer(&buf->timer, jiffies + 1);
        }
 
        old = buf->data;
@@ -795,13 +795,15 @@ void relay_subbufs_consumed(struct rchan *chan,
        if (!chan)
                return;
 
-       if (cpu >= NR_CPUS || !chan->buf[cpu])
+       if (cpu >= NR_CPUS || !chan->buf[cpu] ||
+                                       subbufs_consumed > chan->n_subbufs)
                return;
 
        buf = chan->buf[cpu];
-       buf->subbufs_consumed += subbufs_consumed;
-       if (buf->subbufs_consumed > buf->subbufs_produced)
+       if (subbufs_consumed > buf->subbufs_produced - buf->subbufs_consumed)
                buf->subbufs_consumed = buf->subbufs_produced;
+       else
+               buf->subbufs_consumed += subbufs_consumed;
 }
 EXPORT_SYMBOL_GPL(relay_subbufs_consumed);
 
@@ -1196,7 +1198,7 @@ static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
        relay_consume_bytes(rbuf, buf->private);
 }
 
-static struct pipe_buf_operations relay_pipe_buf_ops = {
+static const struct pipe_buf_operations relay_pipe_buf_ops = {
        .can_merge = 0,
        .map = generic_pipe_buf_map,
        .unmap = generic_pipe_buf_unmap,
@@ -1213,14 +1215,14 @@ static void relay_page_release(struct splice_pipe_desc *spd, unsigned int i)
 /*
  *     subbuf_splice_actor - splice up to one subbuf's worth of data
  */
-static int subbuf_splice_actor(struct file *in,
+static ssize_t subbuf_splice_actor(struct file *in,
                               loff_t *ppos,
                               struct pipe_inode_info *pipe,
                               size_t len,
                               unsigned int flags,
                               int *nonpad_ret)
 {
-       unsigned int pidx, poff, total_len, subbuf_pages, nr_pages, ret;
+       unsigned int pidx, poff, total_len, subbuf_pages, nr_pages;
        struct rchan_buf *rbuf = in->private_data;
        unsigned int subbuf_size = rbuf->chan->subbuf_size;
        uint64_t pos = (uint64_t) *ppos;
@@ -1229,8 +1231,8 @@ static int subbuf_splice_actor(struct file *in,
        size_t read_subbuf = read_start / subbuf_size;
        size_t padding = rbuf->padding[read_subbuf];
        size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;
-       struct page *pages[PIPE_BUFFERS];
-       struct partial_page partial[PIPE_BUFFERS];
+       struct page *pages[PIPE_DEF_BUFFERS];
+       struct partial_page partial[PIPE_DEF_BUFFERS];
        struct splice_pipe_desc spd = {
                .pages = pages,
                .nr_pages = 0,
@@ -1239,9 +1241,12 @@ static int subbuf_splice_actor(struct file *in,
                .ops = &relay_pipe_buf_ops,
                .spd_release = relay_page_release,
        };
+       ssize_t ret;
 
        if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
                return 0;
+       if (splice_grow_spd(pipe, &spd))
+               return -ENOMEM;
 
        /*
         * Adjust read len, if longer than what is available
@@ -1252,7 +1257,7 @@ static int subbuf_splice_actor(struct file *in,
        subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
        pidx = (read_start / PAGE_SIZE) % subbuf_pages;
        poff = read_start & ~PAGE_MASK;
-       nr_pages = min_t(unsigned int, subbuf_pages, PIPE_BUFFERS);
+       nr_pages = min_t(unsigned int, subbuf_pages, pipe->buffers);
 
        for (total_len = 0; spd.nr_pages < nr_pages; spd.nr_pages++) {
                unsigned int this_len, this_end, private;
@@ -1286,16 +1291,19 @@ static int subbuf_splice_actor(struct file *in,
                }
        }
 
+       ret = 0;
        if (!spd.nr_pages)
-               return 0;
+               goto out;
 
        ret = *nonpad_ret = splice_to_pipe(pipe, &spd);
        if (ret < 0 || ret < total_len)
-               return ret;
+               goto out;
 
         if (read_start + ret == nonpad_end)
                 ret += padding;
 
+out:
+       splice_shrink_spd(pipe, &spd);
         return ret;
 }
 
@@ -1317,12 +1325,9 @@ static ssize_t relay_file_splice_read(struct file *in,
                if (ret < 0)
                        break;
                else if (!ret) {
-                       if (spliced)
-                               break;
-                       if (flags & SPLICE_F_NONBLOCK) {
+                       if (flags & SPLICE_F_NONBLOCK)
                                ret = -EAGAIN;
-                               break;
-                       }
+                       break;
                }
 
                *ppos += ret;