From patchwork Tue Dec 27 19:32:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 9489831 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F2BDF62AAF for ; Tue, 27 Dec 2016 19:33:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D90D7201BC for ; Tue, 27 Dec 2016 19:33:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CDF922094F; Tue, 27 Dec 2016 19:33:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 002A1201BC for ; Tue, 27 Dec 2016 19:33:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752522AbcL0TdA (ORCPT ); Tue, 27 Dec 2016 14:33:00 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:32811 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932355AbcL0Tc5 (ORCPT ); Tue, 27 Dec 2016 14:32:57 -0500 Received: by mail-wm0-f68.google.com with SMTP id u144so58538555wmu.0 for ; Tue, 27 Dec 2016 11:32:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Xy1BqP1TcBa+iJGuf/kZNe3qW6PCKs7HaPhfR4W6qWk=; b=m7Qc1/jHiXm8XBifU0vhYhQDpLWglYniXj31jGSznocHMN+F4ppMUrYRSUdwUAjCW0 o/XhYPVK/O/D4MJOio15UY0UH8doenI4XQk7ifawePjMYmgoy2Gm85q5YE0AhdEt5bUc UiJDaAiUbNQ49fm9nW3t4j90aefFX9qyomKPrGLItBP/0FbR3Df0DhWtKPOPc9tyHYdr /culEKiRDPPCBmzR/S/aRHe+0C6VPiVx5iL572CSCuS+D1nGUkbO+ZiAJp1hZaCV5EiS Wyz8hQA+GzKi9wCBLQouKzTUSLI8Cr2SRPZRqV/sXLc4si50wZgDwriHck0NyZyPcpJG SvDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Xy1BqP1TcBa+iJGuf/kZNe3qW6PCKs7HaPhfR4W6qWk=; b=gWY48wScuU9jFSY4+dYOkH8Oa4L4gJjbYLw/+o1OK4AY0HwWBnkHFOoAW2eRWa850w j8ugC78tS3WUqWOL715gxms3k82jd8+qs78gvK/ldMwxeEwDCo86HwQKSJwpYxXcapsG 38q0FTeaXlG7v1Qs6aOf9sLCZHS1NbjVs9TFzUoKIEJiTh2t4aDOfrodsYjpTZbKUqKy tpY25b/oBafPwHsTid66BdE7Vr0ES9yWxAtXtbSiRpKA235PeWHXP34rLJl0PT0mSfsx aUzjEyXFGuyJUHCgNrss7KYwTj0I02yHY8nUbKoz+KYlgaSatavTwbVahwX5HecqB/eg J5Kw== X-Gm-Message-State: AIkVDXJXjaM5pwM5kVTLCR9VB7QDOXdqhRSSQ8Vep0EgLLyoAbYv+6zffhEDtUoKrtPWbg== X-Received: by 10.28.95.193 with SMTP id t184mr23653928wmb.93.1482867175431; Tue, 27 Dec 2016 11:32:55 -0800 (PST) Received: from amir-VirtualBox.Home (bzq-79-176-86-32.red.bezeqint.net. [79.176.86.32]) by smtp.gmail.com with ESMTPSA id i10sm60928003wjd.15.2016.12.27.11.32.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 27 Dec 2016 11:32:54 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: Eric Paris , linux-fsdevel@vger.kernel.org Subject: [RFC][PATCH 4/4] fsnotify: pass single mark to handle_event() Date: Tue, 27 Dec 2016 21:32:28 +0200 Message-Id: <1482867148-31497-5-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1482867148-31497-1-git-send-email-amir73il@gmail.com> References: <1482867148-31497-1-git-send-email-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The only reason to pass both inode mark and vfsmount mark to handle_event() is for masking the inode mark ignored_mask from the vfsmount mark mask. In case an event is destined for both inode and vfsmount marks on the same group, instead of passing both inode and vfsmount mark to handle_event(), start by passing the event with the inode mark and check return value from handle_event(). If event was handled by group with inode mark (FSNOTIFY_DONE) then we don't need to send it again to the same group with the vfsmount mark. If event was dropped by group with inode mark (FSNOTIFY_DROPPED), call handle_event() of the same group again with vfsmount mark. This change gets rid of some excessive code that was needed to deal with passing the two marks to handle_event(). Signed-off-by: Amir Goldstein --- fs/notify/dnotify/dnotify.c | 4 +- fs/notify/fanotify/fanotify.c | 34 ++++++--------- fs/notify/fsnotify.c | 85 +++++++++++++++++++----------------- fs/notify/inotify/inotify.h | 2 +- fs/notify/inotify/inotify_fsnotify.c | 4 +- fs/notify/inotify/inotify_user.c | 2 +- include/linux/fsnotify_backend.h | 4 +- kernel/audit_fsnotify.c | 2 +- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 2 +- 10 files changed, 68 insertions(+), 73 deletions(-) diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 5a4ec30..4ad969b 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -84,7 +84,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) static int dnotify_handle_event(struct fsnotify_group *group, struct inode *inode, struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, + u32 unused, u32 mask, const void *data, int data_type, const unsigned char *file_name, u32 cookie) { @@ -98,8 +98,6 @@ static int dnotify_handle_event(struct fsnotify_group *group, if (!S_ISDIR(inode->i_mode)) return 0; - BUG_ON(vfsmount_mark); - dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark); spin_lock(&inode_mark->lock); diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 9b26e2f..6a2db65 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -87,17 +87,17 @@ static int fanotify_get_response(struct fsnotify_group *group, } #endif -static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmnt_mark, +static bool fanotify_should_send_event(struct fsnotify_mark *mark, + u32 ignored_mask, u32 event_mask, const void *data, int data_type) { - __u32 marks_mask = 0, marks_ignored_mask = 0; + __u32 mark_mask = mark->mask; const struct path *path = data; - pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p" - " data_type=%d\n", __func__, inode_mark, vfsmnt_mark, - event_mask, data, data_type); + pr_debug("%s: mark=%p mark_mask=%x ignored_mask=%x event_mask=%x" + " data=%p data_type=%d\n", __func__, mark, mark_mask, + ignored_mask, event_mask, data, data_type); /* if we don't have enough info to send an event to userspace say no */ if (data_type != FSNOTIFY_EVENT_PATH) @@ -108,28 +108,22 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, !d_can_lookup(path->dentry)) return false; - if (inode_mark) { + if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) { /* * if the event is for a child and this inode doesn't care about * events on the child, don't send it! */ if ((event_mask & FS_EVENT_ON_CHILD) && - !(inode_mark->mask & FS_EVENT_ON_CHILD)) + !(mark_mask & FS_EVENT_ON_CHILD)) return false; - marks_mask |= inode_mark->mask; - marks_ignored_mask |= inode_mark->ignored_mask; - } - if (vfsmnt_mark) { - marks_mask |= vfsmnt_mark->mask; - marks_ignored_mask |= vfsmnt_mark->ignored_mask; } if (d_is_dir(path->dentry) && - !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) + !(mark_mask & FS_ISDIR & ~ignored_mask)) return false; - if (event_mask & FAN_ALL_OUTGOING_EVENTS & marks_mask & - ~marks_ignored_mask) + if (event_mask & FAN_ALL_OUTGOING_EVENTS & mark_mask & + ~ignored_mask) return true; return false; @@ -171,8 +165,8 @@ init: __maybe_unused static int fanotify_handle_event(struct fsnotify_group *group, struct inode *inode, - struct fsnotify_mark *inode_mark, - struct fsnotify_mark *fanotify_mark, + struct fsnotify_mark *mark, + u32 ignored_mask, u32 mask, const void *data, int data_type, const unsigned char *file_name, u32 cookie) { @@ -191,7 +185,7 @@ static int fanotify_handle_event(struct fsnotify_group *group, BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR); - if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data, + if (!fanotify_should_send_event(mark, ignored_mask, mask, data, data_type)) return FSNOTIFY_DROPPED; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index caed3c4..6af8f81 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -146,56 +146,61 @@ static __u32 update_ignored_mask(struct fsnotify_mark *inode_mark, return ignored_mask; } -static int send_to_group(struct inode *to_tell, - struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, - __u32 mask, const void *data, - int data_is, u32 cookie, - const unsigned char *file_name) +static int send_to_group_mark(struct inode *to_tell, + struct fsnotify_mark *mark, + __u32 ignored_mask, + __u32 mask, const void *data, + int data_is, u32 cookie, + const unsigned char *file_name) { - struct fsnotify_group *group = NULL; - __u32 inode_test_mask = 0; - __u32 vfsmount_test_mask = 0; - __u32 ignored_mask; - - if (unlikely(!inode_mark && !vfsmount_mark)) { - BUG(); - return 0; - } + struct fsnotify_group *group = mark->group; + __u32 test_mask; - ignored_mask = update_ignored_mask(inode_mark, vfsmount_mark, mask); - - /* does the inode mark tell us to do something? */ - if (inode_mark) { - group = inode_mark->group; - inode_test_mask = (mask & ~FS_EVENT_ON_CHILD); - inode_test_mask &= inode_mark->mask; - inode_test_mask &= ~ignored_mask; - } + /* does the mark tell us to do something? */ + test_mask = (mask & mark->mask & ~FS_EVENT_ON_CHILD); - /* does the vfsmount_mark tell us to do something? */ - if (vfsmount_mark) { - vfsmount_test_mask = (mask & ~FS_EVENT_ON_CHILD); - group = vfsmount_mark->group; - vfsmount_test_mask &= vfsmount_mark->mask; - vfsmount_test_mask &= ~ignored_mask; - } - - pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p" - " inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x" - " ignored_mask=%x data=%p data_is=%d cookie=%d\n", - __func__, group, to_tell, mask, inode_mark, - inode_test_mask, vfsmount_mark, vfsmount_test_mask, + pr_debug("%s: group=%p to_tell=%p mask=%x mark=%p test_mask=%x" + " ignored_mask=%x"" data=%p data_is=%d cookie=%d\n", + __func__, group, to_tell, mask, mark, test_mask, ignored_mask, data, data_is, cookie); - if (!inode_test_mask && !vfsmount_test_mask) + if (!(test_mask & ~ignored_mask)) return FSNOTIFY_DROPPED; - return group->ops->handle_event(group, to_tell, inode_mark, - vfsmount_mark, mask, data, data_is, + return group->ops->handle_event(group, to_tell, mark, + ignored_mask, mask, data, data_is, file_name, cookie); } +static int send_to_group(struct inode *to_tell, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, + __u32 mask, const void *data, + int data_is, u32 cookie, + const unsigned char *file_name) +{ + int ret = FSNOTIFY_DROPPED; + __u32 ignored_mask = update_ignored_mask(inode_mark, vfsmount_mark, + mask); + + if (inode_mark) + ret = send_to_group_mark(to_tell, inode_mark, + ignored_mask, mask, + data, data_is, cookie, file_name); + /* + * If event was dropped by group when handling with inode mark + * (FSNOTIFY_DROPPED), resend to the group with vfsmount mark. + * If event was handled by group with inode mark (FSNOTIFY_DONE) + * or error was returned, then we don't need to send the event + * to the same group again with vfsmount mark. + */ + if (vfsmount_mark && ret == FSNOTIFY_DROPPED) + ret = send_to_group_mark(to_tell, vfsmount_mark, + ignored_mask, mask, + data, data_is, cookie, file_name); + + return ret; +} /* * This is the main call to fsnotify. The VFS calls into hook specific functions * in linux/fsnotify.h. Those functions then in turn call here. Here will call diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index a6f5907..f25ad80 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h @@ -25,7 +25,7 @@ extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, extern int inotify_handle_event(struct fsnotify_group *group, struct inode *inode, struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, + u32 unused, u32 mask, const void *data, int data_type, const unsigned char *file_name, u32 cookie); diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 19e7ec1..bef7e0d 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -65,7 +65,7 @@ static int inotify_merge(struct list_head *list, int inotify_handle_event(struct fsnotify_group *group, struct inode *inode, struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, + u32 unused, u32 mask, const void *data, int data_type, const unsigned char *file_name, u32 cookie) { @@ -76,8 +76,6 @@ int inotify_handle_event(struct fsnotify_group *group, int len = 0; int alloc_len = sizeof(struct inotify_event_info); - BUG_ON(vfsmount_mark); - if ((inode_mark->mask & FS_EXCL_UNLINK) && (data_type == FSNOTIFY_EVENT_PATH)) { const struct path *path = data; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 69d1ea3..eba9ed3 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -493,7 +493,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, struct inotify_inode_mark *i_mark; /* Queue ignore event for the watch */ - inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED, + inotify_handle_event(group, NULL, fsn_mark, 0, FS_IN_IGNORED, NULL, FSNOTIFY_EVENT_NONE, NULL, 0); i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index cbf9e92..594d6db 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -110,8 +110,8 @@ struct fsnotify_fname; struct fsnotify_ops { int (*handle_event)(struct fsnotify_group *group, struct inode *inode, - struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, + struct fsnotify_mark *mark, + u32 ignored_mask, u32 mask, const void *data, int data_type, const unsigned char *file_name, u32 cookie); void (*free_group_priv)(struct fsnotify_group *group); diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index 7ea57e5..6db88ad 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c @@ -166,7 +166,7 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark) static int audit_mark_handle_event(struct fsnotify_group *group, struct inode *to_tell, struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, + u32 unused, u32 mask, const void *data, int data_type, const unsigned char *dname, u32 cookie) { diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 8b1dde9..4393553 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -946,7 +946,7 @@ static void evict_chunk(struct audit_chunk *chunk) static int audit_tree_handle_event(struct fsnotify_group *group, struct inode *to_tell, struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, + u32 unused, u32 mask, const void *data, int data_type, const unsigned char *file_name, u32 cookie) { diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index f79e465..6c3f811 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -470,7 +470,7 @@ void audit_remove_watch_rule(struct audit_krule *krule) static int audit_watch_handle_event(struct fsnotify_group *group, struct inode *to_tell, struct fsnotify_mark *inode_mark, - struct fsnotify_mark *vfsmount_mark, + u32 unused, u32 mask, const void *data, int data_type, const unsigned char *dname, u32 cookie) {