]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/notify/fanotify/fanotify_user.c
make fanotify_read() restartable across signals
[net-next-2.6.git] / fs / notify / fanotify / fanotify_user.c
index a7d9369482d59a0ec38825c98f21ed9b80358e86..063224812b7e607879bffeedd5b90f9c4967346f 100644 (file)
@@ -330,7 +330,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
                ret = -EAGAIN;
                if (file->f_flags & O_NONBLOCK)
                        break;
-               ret = -EINTR;
+               ret = -ERESTARTSYS;
                if (signal_pending(current))
                        break;
 
@@ -376,11 +376,10 @@ static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t
 static int fanotify_release(struct inode *ignored, struct file *file)
 {
        struct fsnotify_group *group = file->private_data;
-       struct fanotify_response_event *re, *lre;
-
-       pr_debug("%s: file=%p group=%p\n", __func__, file, group);
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       struct fanotify_response_event *re, *lre;
+
        mutex_lock(&group->fanotify_data.access_mutex);
 
        group->fanotify_data.bypass_perm = true;
@@ -558,18 +557,24 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
                                       __u32 mask,
                                       unsigned int flags)
 {
-       __u32 oldmask;
+       __u32 oldmask = -1;
 
        spin_lock(&fsn_mark->lock);
        if (!(flags & FAN_MARK_IGNORED_MASK)) {
                oldmask = fsn_mark->mask;
                fsnotify_set_mark_mask_locked(fsn_mark, (oldmask | mask));
        } else {
-               oldmask = fsn_mark->ignored_mask;
-               fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask | mask));
+               __u32 tmask = fsn_mark->ignored_mask | mask;
+               fsnotify_set_mark_ignored_mask_locked(fsn_mark, tmask);
                if (flags & FAN_MARK_IGNORED_SURV_MODIFY)
                        fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY;
        }
+
+       if (!(flags & FAN_MARK_ONDIR)) {
+               __u32 tmask = fsn_mark->ignored_mask | FAN_ONDIR;
+               fsnotify_set_mark_ignored_mask_locked(fsn_mark, tmask);
+       }
+
        spin_unlock(&fsn_mark->lock);
 
        return mask & ~oldmask;
@@ -766,6 +771,12 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
        default:
                return -EINVAL;
        }
+
+       if (mask & FAN_ONDIR) {
+               flags |= FAN_MARK_ONDIR;
+               mask &= ~FAN_ONDIR;
+       }
+
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
        if (mask & ~(FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_EVENT_ON_CHILD))
 #else