| pos:  0
| flags:        02004002
| clockid:      0
| ticks:        6

Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Alexander Viro <v...@zeniv.linux.org.uk>
Signed-off-by: Shawn Landden <sh...@churchofgit.com>
---
 fs/timerfd.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/fs/timerfd.c b/fs/timerfd.c
index 9293121..2e81bdb 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -25,6 +25,7 @@
 #include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/rcupdate.h>
+#include <linux/seq_file.h>
 
 struct timerfd_ctx {
        union {
@@ -284,10 +285,73 @@ static ssize_t timerfd_read(struct file *file, char 
__user *buf, size_t count,
        return res;
 }
 
+#ifdef CONFIG_PROC_FS
+static int timerfd_show_fdinfo(struct seq_file *m, struct file *f)
+{
+       struct timerfd_ctx *ctx = f->private_data;
+
+       seq_printf(m, "clockid:\t%d\n"
+                     "ticks:\t%llu\n", ctx->clockid, ctx->ticks);
+
+       return 0;
+}
+#endif
+
+static ssize_t timerfd_write(struct file *file, const char __user *buf, size_t 
count,
+                        loff_t *ppos)
+{
+       struct timerfd_ctx *ctx = file->private_data;
+       ssize_t res;
+       __u64 ucnt;
+       DECLARE_WAITQUEUE(wait, current);
+
+       if (count < sizeof(ucnt))
+               return -EINVAL;
+       if (copy_from_user(&ucnt, buf, sizeof(ucnt)))
+               return -EFAULT;
+       if (ucnt == ULLONG_MAX)
+               return -EINVAL;
+       spin_lock_irq(&ctx->wqh.lock);
+       res = -EAGAIN;
+       if (ULLONG_MAX - ctx->ticks > ucnt)
+               res = sizeof(ucnt);
+       else if (!(file->f_flags & O_NONBLOCK)) {
+               __add_wait_queue(&ctx->wqh, &wait);
+               for (res = 0;;) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (ULLONG_MAX - ctx->ticks > ucnt) {
+                               res = sizeof(ucnt);
+                               break;
+                       }
+                       if (signal_pending(current)) {
+                               res = -ERESTARTSYS;
+                               break;
+                       }
+                       spin_unlock_irq(&ctx->wqh.lock);
+                       schedule();
+                       spin_lock_irq(&ctx->wqh.lock);
+               }
+               __remove_wait_queue(&ctx->wqh, &wait);
+               __set_current_state(TASK_RUNNING);
+       }
+       if (likely(res > 0)) {
+               ctx->ticks += ucnt;
+               if (waitqueue_active(&ctx->wqh))
+                       wake_up_locked_poll(&ctx->wqh, POLLIN);
+       }
+       spin_unlock_irq(&ctx->wqh.lock);
+
+       return res;
+}
+
 static const struct file_operations timerfd_fops = {
+#ifdef CONFIG_PROC_FS
+       .show_fdinfo    = timerfd_show_fdinfo,
+#endif
        .release        = timerfd_release,
        .poll           = timerfd_poll,
        .read           = timerfd_read,
+       .write          = timerfd_write,
        .llseek         = noop_llseek,
 };
 
-- 
1.8.5.2.297.g3e57c29

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

Reply via email to