| pos: 0 | flags: 02004002 | clockid: 0 | ticks: 6 Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> Signed-off-by: Shawn Landden <shawn@xxxxxxxxxxxxxxx> --- 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-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html