Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / kernel / relay.c
index fc9b4a4..da79a10 100644 (file)
@@ -328,13 +328,15 @@ static struct rchan_callbacks default_channel_callbacks = {
 
 /**
  *     wakeup_readers - wake up readers waiting on a channel
- *     @data: contains the channel buffer
+ *     @work: contains the channel buffer
  *
- *     This is the timer function used to defer reader waking.
+ *     This is the function used to defer reader waking
  */
-static void wakeup_readers(unsigned long data)
+static void wakeup_readers(struct irq_work *work)
 {
-       struct rchan_buf *buf = (struct rchan_buf *)data;
+       struct rchan_buf *buf;
+
+       buf = container_of(work, struct rchan_buf, wakeup_work);
        wake_up_interruptible(&buf->read_wait);
 }
 
@@ -352,9 +354,10 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)
        if (init) {
                init_waitqueue_head(&buf->read_wait);
                kref_init(&buf->kref);
-               setup_timer(&buf->timer, wakeup_readers, (unsigned long)buf);
-       } else
-               del_timer_sync(&buf->timer);
+               init_irq_work(&buf->wakeup_work, wakeup_readers);
+       } else {
+               irq_work_sync(&buf->wakeup_work);
+       }
 
        buf->subbufs_produced = 0;
        buf->subbufs_consumed = 0;
@@ -487,7 +490,7 @@ free_buf:
 static void relay_close_buf(struct rchan_buf *buf)
 {
        buf->finalized = 1;
-       del_timer_sync(&buf->timer);
+       irq_work_sync(&buf->wakeup_work);
        buf->chan->cb->remove_buf_file(buf->dentry);
        kref_put(&buf->kref, relay_remove_buf);
 }
@@ -754,14 +757,15 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
                        buf->early_bytes += buf->chan->subbuf_size -
                                            buf->padding[old_subbuf];
                smp_mb();
-               if (waitqueue_active(&buf->read_wait))
+               if (waitqueue_active(&buf->read_wait)) {
                        /*
                         * Calling wake_up_interruptible() from here
                         * will deadlock if we happen to be logging
                         * from the scheduler (trying to re-grab
                         * rq->lock), so defer it.
                         */
-                       mod_timer(&buf->timer, jiffies + 1);
+                       irq_work_queue(&buf->wakeup_work);
+               }
        }
 
        old = buf->data;
@@ -1108,51 +1112,23 @@ static size_t relay_file_read_end_pos(struct rchan_buf *buf,
        return end_pos;
 }
 
-/*
- *     subbuf_read_actor - read up to one subbuf's worth of data
- */
-static int subbuf_read_actor(size_t read_start,
-                            struct rchan_buf *buf,
-                            size_t avail,
-                            read_descriptor_t *desc)
-{
-       void *from;
-       int ret = 0;
-
-       from = buf->start + read_start;
-       ret = avail;
-       if (copy_to_user(desc->arg.buf, from, avail)) {
-               desc->error = -EFAULT;
-               ret = 0;
-       }
-       desc->arg.data += ret;
-       desc->written += ret;
-       desc->count -= ret;
-
-       return ret;
-}
-
-typedef int (*subbuf_actor_t) (size_t read_start,
-                              struct rchan_buf *buf,
-                              size_t avail,
-                              read_descriptor_t *desc);
-
-/*
- *     relay_file_read_subbufs - read count bytes, bridging subbuf boundaries
- */
-static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos,
-                                       subbuf_actor_t subbuf_actor,
-                                       read_descriptor_t *desc)
+static ssize_t relay_file_read(struct file *filp,
+                              char __user *buffer,
+                              size_t count,
+                              loff_t *ppos)
 {
        struct rchan_buf *buf = filp->private_data;
        size_t read_start, avail;
+       size_t written = 0;
        int ret;
 
-       if (!desc->count)
+       if (!count)
                return 0;
 
        inode_lock(file_inode(filp));
        do {
+               void *from;
+
                if (!relay_file_read_avail(buf, *ppos))
                        break;
 
@@ -1161,32 +1137,22 @@ static ssize_t relay_file_read_subbufs(struct file *filp, loff_t *ppos,
                if (!avail)
                        break;
 
-               avail = min(desc->count, avail);
-               ret = subbuf_actor(read_start, buf, avail, desc);
-               if (desc->error < 0)
+               avail = min(count, avail);
+               from = buf->start + read_start;
+               ret = avail;
+               if (copy_to_user(buffer, from, avail))
                        break;
 
-               if (ret) {
-                       relay_file_read_consume(buf, read_start, ret);
-                       *ppos = relay_file_read_end_pos(buf, read_start, ret);
-               }
-       } while (desc->count && ret);
-       inode_unlock(file_inode(filp));
+               buffer += ret;
+               written += ret;
+               count -= ret;
 
-       return desc->written;
-}
+               relay_file_read_consume(buf, read_start, ret);
+               *ppos = relay_file_read_end_pos(buf, read_start, ret);
+       } while (count);
+       inode_unlock(file_inode(filp));
 
-static ssize_t relay_file_read(struct file *filp,
-                              char __user *buffer,
-                              size_t count,
-                              loff_t *ppos)
-{
-       read_descriptor_t desc;
-       desc.written = 0;
-       desc.count = count;
-       desc.arg.buf = buffer;
-       desc.error = 0;
-       return relay_file_read_subbufs(filp, ppos, subbuf_read_actor, &desc);
+       return written;
 }
 
 static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed)