From mboxrd@z Thu Jan 1 00:00:00 1970 From: Shawn Landden Subject: [PATCH] timerfd: show procfs fdinfo helper, and now accepts write() Date: Mon, 3 Feb 2014 08:01:13 -0800 Message-ID: <1391443273-2031-1-git-send-email-shawn@churchofgit.com> References: <20140203104430.GA21968@paralelels.com> Cc: criu@openvz.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, avagin@gmail.com, Shawn Landden , Thomas Gleixner , Alexander Viro To: unlisted-recipients:; (no To-header on input) Return-path: In-Reply-To: <20140203104430.GA21968@paralelels.com> Sender: linux-kernel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org | pos: 0 | flags: 02004002 | clockid: 0 | ticks: 6 Cc: Thomas Gleixner Cc: Alexander Viro Signed-off-by: Shawn Landden --- 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 #include #include +#include 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