]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
fanotify: fanotify_init syscall implementation
authorEric Paris <eparis@redhat.com>
Fri, 18 Dec 2009 02:24:26 +0000 (21:24 -0500)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 13:58:55 +0000 (09:58 -0400)
NAME
fanotify_init - initialize an fanotify group

SYNOPSIS
int fanotify_init(unsigned int flags, unsigned int event_f_flags, int priority);

DESCRIPTION
fanotify_init() initializes a new fanotify instance and returns a file
descriptor associated with the new fanotify event queue.

The following values can be OR'd into the flags field:

FAN_NONBLOCK Set the O_NONBLOCK file status flag on the new open file description.
Using this flag saves extra calls to fcntl(2) to achieve the same
result.

FAN_CLOEXEC Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor.
See the description of the O_CLOEXEC flag in open(2) for reasons why
this may be useful.

The event_f_flags argument is unused and must be set to 0

The priority argument is unused and must be set to 0

RETURN VALUE
On success, this system call return a new file descriptor. On error, -1 is
returned, and errno is set to indicate the error.

ERRORS
EINVAL An invalid value was specified in flags.

EINVAL A non-zero valid was passed in event_f_flags or in priority

ENFILE The system limit on the total number of file descriptors has been reached.

ENOMEM Insufficient kernel memory is available.

CONFORMING TO
These system calls are Linux-specific.

Signed-off-by: Eric Paris <eparis@redhat.com>
fs/notify/fanotify/fanotify.h
fs/notify/fanotify/fanotify_user.c
include/linux/fanotify.h

index 50765eb30fe4b64fc483e658429804b33fc9a4cb..dd656cfab1ba2facee0082b0a1f8b61d6a57d4eb 100644 (file)
@@ -4,6 +4,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 
+extern const struct fsnotify_ops fanotify_fsnotify_ops;
+
 static inline bool fanotify_mask_valid(__u32 mask)
 {
        if (mask & ~((__u32)FAN_ALL_INCOMING_EVENTS))
index cf176fc7086b523ab9d6f9cf253f26266b669d33..67c0b5e4a4886b4838a6b026bf955c343bd3e49e 100644 (file)
@@ -1,13 +1,72 @@
 #include <linux/fcntl.h>
 #include <linux/fs.h>
+#include <linux/anon_inodes.h>
 #include <linux/fsnotify_backend.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
 
 #include "fanotify.h"
 
+static int fanotify_release(struct inode *ignored, struct file *file)
+{
+       struct fsnotify_group *group = file->private_data;
+
+       pr_debug("%s: file=%p group=%p\n", __func__, file, group);
+
+       /* matches the fanotify_init->fsnotify_alloc_group */
+       fsnotify_put_group(group);
+
+       return 0;
+}
+
+static const struct file_operations fanotify_fops = {
+       .poll           = NULL,
+       .read           = NULL,
+       .fasync         = NULL,
+       .release        = fanotify_release,
+       .unlocked_ioctl = NULL,
+       .compat_ioctl   = NULL,
+};
+
+/* fanotify syscalls */
 SYSCALL_DEFINE3(fanotify_init, unsigned int, flags, unsigned int, event_f_flags,
                unsigned int, priority)
 {
-       return -ENOSYS;
+       struct fsnotify_group *group;
+       int f_flags, fd;
+
+       pr_debug("%s: flags=%d event_f_flags=%d priority=%d\n",
+               __func__, flags, event_f_flags, priority);
+
+       if (event_f_flags)
+               return -EINVAL;
+       if (priority)
+               return -EINVAL;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (flags & ~FAN_ALL_INIT_FLAGS)
+               return -EINVAL;
+
+       f_flags = (O_RDONLY | FMODE_NONOTIFY);
+       if (flags & FAN_CLOEXEC)
+               f_flags |= O_CLOEXEC;
+       if (flags & FAN_NONBLOCK)
+               f_flags |= O_NONBLOCK;
+
+       /* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */
+       group = fsnotify_alloc_group(&fanotify_fsnotify_ops);
+       if (IS_ERR(group))
+               return PTR_ERR(group);
+
+       fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
+       if (fd < 0)
+               goto out_put_group;
+
+       return fd;
+
+out_put_group:
+       fsnotify_put_group(group);
+       return fd;
 }
index b560f86d1401e6b8c3a407a1315d4f3a730cc339..00bc6d4fbb58b4792c56b3890f6172b8a04ff7ca 100644 (file)
 /* helper events */
 #define FAN_CLOSE              (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
 
+#define FAN_CLOEXEC            0x00000001
+#define FAN_NONBLOCK           0x00000002
+
+#define FAN_ALL_INIT_FLAGS     (FAN_CLOEXEC | FAN_NONBLOCK)
 /*
  * All of the events - we build the list by hand so that we can add flags in
  * the future and not break backward compatibility.  Apps will get only the