diff options
Diffstat (limited to 'fs/eventfd.c')
-rw-r--r-- | fs/eventfd.c | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/fs/eventfd.c b/fs/eventfd.c index 31d12de83a2a..8b47e4200e65 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c | |||
@@ -68,11 +68,16 @@ int eventfd_signal(struct eventfd_ctx *ctx, int n) | |||
68 | } | 68 | } |
69 | EXPORT_SYMBOL_GPL(eventfd_signal); | 69 | EXPORT_SYMBOL_GPL(eventfd_signal); |
70 | 70 | ||
71 | static void eventfd_free_ctx(struct eventfd_ctx *ctx) | ||
72 | { | ||
73 | kfree(ctx); | ||
74 | } | ||
75 | |||
71 | static void eventfd_free(struct kref *kref) | 76 | static void eventfd_free(struct kref *kref) |
72 | { | 77 | { |
73 | struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref); | 78 | struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref); |
74 | 79 | ||
75 | kfree(ctx); | 80 | eventfd_free_ctx(ctx); |
76 | } | 81 | } |
77 | 82 | ||
78 | /** | 83 | /** |
@@ -298,9 +303,23 @@ struct eventfd_ctx *eventfd_ctx_fileget(struct file *file) | |||
298 | } | 303 | } |
299 | EXPORT_SYMBOL_GPL(eventfd_ctx_fileget); | 304 | EXPORT_SYMBOL_GPL(eventfd_ctx_fileget); |
300 | 305 | ||
301 | SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) | 306 | /** |
307 | * eventfd_file_create - Creates an eventfd file pointer. | ||
308 | * @count: Initial eventfd counter value. | ||
309 | * @flags: Flags for the eventfd file. | ||
310 | * | ||
311 | * This function creates an eventfd file pointer, w/out installing it into | ||
312 | * the fd table. This is useful when the eventfd file is used during the | ||
313 | * initialization of data structures that require extra setup after the eventfd | ||
314 | * creation. So the eventfd creation is split into the file pointer creation | ||
315 | * phase, and the file descriptor installation phase. | ||
316 | * In this way races with userspace closing the newly installed file descriptor | ||
317 | * can be avoided. | ||
318 | * Returns an eventfd file pointer, or a proper error pointer. | ||
319 | */ | ||
320 | struct file *eventfd_file_create(unsigned int count, int flags) | ||
302 | { | 321 | { |
303 | int fd; | 322 | struct file *file; |
304 | struct eventfd_ctx *ctx; | 323 | struct eventfd_ctx *ctx; |
305 | 324 | ||
306 | /* Check the EFD_* constants for consistency. */ | 325 | /* Check the EFD_* constants for consistency. */ |
@@ -308,26 +327,48 @@ SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) | |||
308 | BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); | 327 | BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); |
309 | 328 | ||
310 | if (flags & ~EFD_FLAGS_SET) | 329 | if (flags & ~EFD_FLAGS_SET) |
311 | return -EINVAL; | 330 | return ERR_PTR(-EINVAL); |
312 | 331 | ||
313 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); | 332 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); |
314 | if (!ctx) | 333 | if (!ctx) |
315 | return -ENOMEM; | 334 | return ERR_PTR(-ENOMEM); |
316 | 335 | ||
317 | kref_init(&ctx->kref); | 336 | kref_init(&ctx->kref); |
318 | init_waitqueue_head(&ctx->wqh); | 337 | init_waitqueue_head(&ctx->wqh); |
319 | ctx->count = count; | 338 | ctx->count = count; |
320 | ctx->flags = flags; | 339 | ctx->flags = flags; |
321 | 340 | ||
322 | /* | 341 | file = anon_inode_getfile("[eventfd]", &eventfd_fops, ctx, |
323 | * When we call this, the initialization must be complete, since | 342 | flags & EFD_SHARED_FCNTL_FLAGS); |
324 | * anon_inode_getfd() will install the fd. | 343 | if (IS_ERR(file)) |
325 | */ | 344 | eventfd_free_ctx(ctx); |
326 | fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx, | 345 | |
327 | flags & EFD_SHARED_FCNTL_FLAGS); | 346 | return file; |
328 | if (fd < 0) | 347 | } |
329 | kfree(ctx); | 348 | |
349 | SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) | ||
350 | { | ||
351 | int fd, error; | ||
352 | struct file *file; | ||
353 | |||
354 | error = get_unused_fd_flags(flags & EFD_SHARED_FCNTL_FLAGS); | ||
355 | if (error < 0) | ||
356 | return error; | ||
357 | fd = error; | ||
358 | |||
359 | file = eventfd_file_create(count, flags); | ||
360 | if (IS_ERR(file)) { | ||
361 | error = PTR_ERR(file); | ||
362 | goto err_put_unused_fd; | ||
363 | } | ||
364 | fd_install(fd, file); | ||
365 | |||
330 | return fd; | 366 | return fd; |
367 | |||
368 | err_put_unused_fd: | ||
369 | put_unused_fd(fd); | ||
370 | |||
371 | return error; | ||
331 | } | 372 | } |
332 | 373 | ||
333 | SYSCALL_DEFINE1(eventfd, unsigned int, count) | 374 | SYSCALL_DEFINE1(eventfd, unsigned int, count) |