aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/timerfd.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/timerfd.c b/fs/timerfd.c
index 9ae4abb4110b..ab8dd1538381 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -40,6 +40,7 @@ struct timerfd_ctx {
40 short unsigned settime_flags; /* to show in fdinfo */ 40 short unsigned settime_flags; /* to show in fdinfo */
41 struct rcu_head rcu; 41 struct rcu_head rcu;
42 struct list_head clist; 42 struct list_head clist;
43 spinlock_t cancel_lock;
43 bool might_cancel; 44 bool might_cancel;
44}; 45};
45 46
@@ -112,7 +113,7 @@ void timerfd_clock_was_set(void)
112 rcu_read_unlock(); 113 rcu_read_unlock();
113} 114}
114 115
115static void timerfd_remove_cancel(struct timerfd_ctx *ctx) 116static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
116{ 117{
117 if (ctx->might_cancel) { 118 if (ctx->might_cancel) {
118 ctx->might_cancel = false; 119 ctx->might_cancel = false;
@@ -122,6 +123,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
122 } 123 }
123} 124}
124 125
126static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
127{
128 spin_lock(&ctx->cancel_lock);
129 __timerfd_remove_cancel(ctx);
130 spin_unlock(&ctx->cancel_lock);
131}
132
125static bool timerfd_canceled(struct timerfd_ctx *ctx) 133static bool timerfd_canceled(struct timerfd_ctx *ctx)
126{ 134{
127 if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX) 135 if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
@@ -132,6 +140,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)
132 140
133static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) 141static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
134{ 142{
143 spin_lock(&ctx->cancel_lock);
135 if ((ctx->clockid == CLOCK_REALTIME || 144 if ((ctx->clockid == CLOCK_REALTIME ||
136 ctx->clockid == CLOCK_REALTIME_ALARM) && 145 ctx->clockid == CLOCK_REALTIME_ALARM) &&
137 (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) { 146 (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
@@ -141,9 +150,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
141 list_add_rcu(&ctx->clist, &cancel_list); 150 list_add_rcu(&ctx->clist, &cancel_list);
142 spin_unlock(&cancel_lock); 151 spin_unlock(&cancel_lock);
143 } 152 }
144 } else if (ctx->might_cancel) { 153 } else {
145 timerfd_remove_cancel(ctx); 154 __timerfd_remove_cancel(ctx);
146 } 155 }
156 spin_unlock(&ctx->cancel_lock);
147} 157}
148 158
149static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) 159static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
@@ -400,6 +410,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
400 return -ENOMEM; 410 return -ENOMEM;
401 411
402 init_waitqueue_head(&ctx->wqh); 412 init_waitqueue_head(&ctx->wqh);
413 spin_lock_init(&ctx->cancel_lock);
403 ctx->clockid = clockid; 414 ctx->clockid = clockid;
404 415
405 if (isalarm(ctx)) 416 if (isalarm(ctx))