diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/timerfd.c | 17 |
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 | ||
115 | static void timerfd_remove_cancel(struct timerfd_ctx *ctx) | 116 | static 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 | ||
126 | static 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 | |||
125 | static bool timerfd_canceled(struct timerfd_ctx *ctx) | 133 | static 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 | ||
133 | static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags) | 141 | static 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 | ||
149 | static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) | 159 | static 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)) |