From patchwork Wed Dec 2 12:07:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11945845 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 83751C64E7C for ; Wed, 2 Dec 2020 12:08:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 111BD206F9 for ; Wed, 2 Dec 2020 12:08:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728734AbgLBMIj (ORCPT ); Wed, 2 Dec 2020 07:08:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49000 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726589AbgLBMIj (ORCPT ); Wed, 2 Dec 2020 07:08:39 -0500 Received: from mail-ej1-x644.google.com (mail-ej1-x644.google.com [IPv6:2a00:1450:4864:20::644]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11659C061A04 for ; Wed, 2 Dec 2020 04:07:20 -0800 (PST) Received: by mail-ej1-x644.google.com with SMTP id pg6so3822407ejb.6 for ; Wed, 02 Dec 2020 04:07:19 -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 :mime-version:content-transfer-encoding; bh=5xSNu6SmhBDBAHCbKMAFp/TAz51yCqOY0BBeUrJN9P4=; b=qzNp/n6eKVAFXGos8n6tNMEh69rCMvPXu4nQ7Puu2C2U7VP7twKoqf2zAq3Lmt53cy FfJ3g4OdoE5FXxUUaEmsd3KnQApNd7npV+pY11rJAeiVUKvP9YRNt7bbCytKrfHe/5it S465XJb4KjEayYY/8h+69ukV/VC4pAGhZQPgQmDoG5yWq+KYRpeSQ+593d+G1pUc342k WB8s19zWYJQiLbSyfTX2tLaLf6mNuSEAuMHKUXpJdqs3y0B6971iviuY7pAMIib16tBV 8K4ZbsyMdSIzsuu7vWGAriUGO4y2Ka2nj0ovhEUxhjvm3iG3JFY1sLuGrwRVjdrpakV4 M22g== 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:mime-version:content-transfer-encoding; bh=5xSNu6SmhBDBAHCbKMAFp/TAz51yCqOY0BBeUrJN9P4=; b=Gee6SI/mWwNYEWDwLATGfLR8gp85JVh8/mnMjjR/3IV67FXD8xVrj9uuRDlHf2T4QU br+3vsPYbmLrn0GTTwNK2rafqxZ23/S5aTGF6B5n+1GywQjpMtuCLUEE+NxlFj74MSZO NWODy/bRdZudJlh2DLuMy2BsqXzvdYIZCS5QluDlFBP6QvGdzzbwN2gR8RK9X98Cy+8n UyNbgmdYdzIzKsPsiUixnJBPL74LKkID2K+v4j919clQcPTX3yuLR1Z7fn79dlpKHIdT fIqgjeN+QXHnMs6OCPN4+zEuIRzK2UH1u7/LJMsA8t51Ou+dBl+1gzqBCG+QUgmX9O6f hd1g== X-Gm-Message-State: AOAM532pceXVIWIwlp1A3SWAas57ORLNWqbs3Yvjj/tD4WBhjnfozKQs MH6iI8wWR8YephjJM/ndHzA= X-Google-Smtp-Source: ABdhPJxjrlZPpghPp4321mvbkOLV4N3yVyHAdETYje9+TJ+wUtl0YV3VHzT1EZuav541pESWUORRuw== X-Received: by 2002:a17:906:4016:: with SMTP id v22mr2025722ejj.266.1606910838676; Wed, 02 Dec 2020 04:07:18 -0800 (PST) Received: from localhost.localdomain ([31.210.181.203]) by smtp.gmail.com with ESMTPSA id b7sm1058227ejj.85.2020.12.02.04.07.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Dec 2020 04:07:18 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 1/7] fsnotify: generalize handle_inode_event() Date: Wed, 2 Dec 2020 14:07:07 +0200 Message-Id: <20201202120713.702387-2-amir73il@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201202120713.702387-1-amir73il@gmail.com> References: <20201202120713.702387-1-amir73il@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The handle_inode_event() interface was added as (quoting comment): "a simple variant of handle_event() for groups that only have inode marks and don't have ignore mask". In other words, all backends except fanotify. The inotify backend also falls under this category, but because it required extra arguments it was left out of the initial pass of backends conversion to the simple interface. This results in code duplication between the generic helper fsnotify_handle_event() and the inotify_handle_event() callback which also happen to be buggy code. Generalize the handle_inode_event() arguments and add the check for FS_EXCL_UNLINK flag to the generic helper, so inotify backend could be converted to use the simple interface. Signed-off-by: Amir Goldstein --- fs/nfsd/filecache.c | 2 +- fs/notify/dnotify/dnotify.c | 2 +- fs/notify/fsnotify.c | 31 ++++++++++++++++++++++++------- include/linux/fsnotify_backend.h | 3 ++- kernel/audit_fsnotify.c | 2 +- kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 2 +- 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c index 3c6c2f7d1688..5849c1bd88f1 100644 --- a/fs/nfsd/filecache.c +++ b/fs/nfsd/filecache.c @@ -600,7 +600,7 @@ static struct notifier_block nfsd_file_lease_notifier = { static int nfsd_file_fsnotify_handle_event(struct fsnotify_mark *mark, u32 mask, struct inode *inode, struct inode *dir, - const struct qstr *name) + const struct qstr *name, u32 cookie) { trace_nfsd_file_fsnotify_handle_event(inode, mask); diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 5dcda8f20c04..e45ca6ecba95 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -72,7 +72,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) */ static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask, struct inode *inode, struct inode *dir, - const struct qstr *name) + const struct qstr *name, u32 cookie) { struct dnotify_mark *dn_mark; struct dnotify_struct *dn; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 8d3ad5ef2925..c5c68bcbaadf 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -232,6 +232,26 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, } EXPORT_SYMBOL_GPL(__fsnotify_parent); +static int fsnotify_handle_inode_event(struct fsnotify_group *group, + struct fsnotify_mark *inode_mark, + u32 mask, const void *data, int data_type, + struct inode *dir, const struct qstr *name, + u32 cookie) +{ + const struct path *path = fsnotify_data_path(data, data_type); + struct inode *inode = fsnotify_data_inode(data, data_type); + const struct fsnotify_ops *ops = group->ops; + + if (WARN_ON_ONCE(!ops->handle_inode_event)) + return 0; + + if ((inode_mark->mask & FS_EXCL_UNLINK) && + path && d_unlinked(path->dentry)) + return 0; + + return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie); +} + static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, const void *data, int data_type, struct inode *dir, const struct qstr *name, @@ -239,13 +259,8 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, { struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info); - struct inode *inode = fsnotify_data_inode(data, data_type); - const struct fsnotify_ops *ops = group->ops; int ret; - if (WARN_ON_ONCE(!ops->handle_inode_event)) - return 0; - if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) || WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info))) return 0; @@ -262,7 +277,8 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, name = NULL; } - ret = ops->handle_inode_event(inode_mark, mask, inode, dir, name); + ret = fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type, + dir, name, cookie); if (ret || !child_mark) return ret; @@ -272,7 +288,8 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, * report the event once to parent dir with name and once to child * without name. */ - return ops->handle_inode_event(child_mark, mask, inode, NULL, NULL); + return fsnotify_handle_inode_event(group, child_mark, mask, data, data_type, + NULL, NULL, 0); } static int send_to_group(__u32 mask, const void *data, int data_type, diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index f8529a3a2923..4ee3044eedd0 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -137,6 +137,7 @@ struct mem_cgroup; * if @file_name is not NULL, this is the directory that * @file_name is relative to. * @file_name: optional file name associated with event + * @cookie: inotify rename cookie * * free_group_priv - called when a group refcnt hits 0 to clean up the private union * freeing_mark - called when a mark is being destroyed for some reason. The group @@ -151,7 +152,7 @@ struct fsnotify_ops { struct fsnotify_iter_info *iter_info); int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask, struct inode *inode, struct inode *dir, - const struct qstr *file_name); + const struct qstr *file_name, u32 cookie); void (*free_group_priv)(struct fsnotify_group *group); void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); void (*free_event)(struct fsnotify_event *event); diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index bfcfcd61adb6..5b3f01da172b 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c @@ -154,7 +154,7 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark) /* Update mark data in audit rules based on fsnotify events. */ static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask, struct inode *inode, struct inode *dir, - const struct qstr *dname) + const struct qstr *dname, u32 cookie) { struct audit_fsnotify_mark *audit_mark; diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 83e1c07fc99e..6c91902f4f45 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -1037,7 +1037,7 @@ static void evict_chunk(struct audit_chunk *chunk) static int audit_tree_handle_event(struct fsnotify_mark *mark, u32 mask, struct inode *inode, struct inode *dir, - const struct qstr *file_name) + const struct qstr *file_name, u32 cookie) { return 0; } diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 246e5ba704c0..2acf7ca49154 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -466,7 +466,7 @@ void audit_remove_watch_rule(struct audit_krule *krule) /* Update watch data in audit rules based on fsnotify events. */ static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask, struct inode *inode, struct inode *dir, - const struct qstr *dname) + const struct qstr *dname, u32 cookie) { struct audit_parent *parent; From patchwork Wed Dec 2 12:07:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11945843 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CE69CC64E8A for ; Wed, 2 Dec 2020 12:08:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7ABAF22203 for ; Wed, 2 Dec 2020 12:08:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729572AbgLBMIk (ORCPT ); Wed, 2 Dec 2020 07:08:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49004 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726928AbgLBMIj (ORCPT ); Wed, 2 Dec 2020 07:08:39 -0500 Received: from mail-ej1-x643.google.com (mail-ej1-x643.google.com [IPv6:2a00:1450:4864:20::643]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 45879C061A49 for ; Wed, 2 Dec 2020 04:07:21 -0800 (PST) Received: by mail-ej1-x643.google.com with SMTP id x16so3806057ejj.7 for ; Wed, 02 Dec 2020 04:07:21 -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 :mime-version:content-transfer-encoding; bh=HoJCq1RLwaX8TpqBRU2lfWbZSeg4QGA6FWYGWUyqYwU=; b=KEVmrYw/zHKdaIQT/avBPA/xo597cpoJE+ihyyOCuEBmb944CAAyO9wdJPbUVv7XIz emsZD7o56wv5Uotw2XGcn4FGzt3XLloJKNmi09ehfm7O+RoHW3jh7nKFgJUvH+un0zgM 1FXBxlNRyfoTDETjj9hQVRx3CIVapeDR+jOkBHScVYfE/74dqVbw66tSXQhj0w6cYOJH p9za8B1YJgO144q7NoisKgBZ2D+f1ar3vkRYk1mgp6VMtNDubg+gR8U+QpoWBT1rgAeq H74XWsCQKFa257CtxzCPgcwBCFqyidrAm1mSCGWkv/y2XQHy/gascb5StoVutVaydEGS RYrA== 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:mime-version:content-transfer-encoding; bh=HoJCq1RLwaX8TpqBRU2lfWbZSeg4QGA6FWYGWUyqYwU=; b=d9JxORXKenP79HS6hX1/SZ3Su2X7rdd4TwVgX8Wj+vLTKoCAfp8qDr2AD/2mS03l5V z8GUK1zae2Y79++/yVtLfSPEJWJR+BCg1Q4Bfxa8Kg0SxgO2DM4iwNjgFr+DKCL/dbDS StaSN3imgoISzsRmPSpz7Z30qlknNlXA9egnGiwODtKIum6Py+X5kHtWBFlulXkapCSU +ZRvPb4pqAtMBdWhTZR6yDAGLuTNsSR3TwOCi9cPeQCVEGF1swZzrUxSE75WIpJVV/ql AHOWCx76yKw+F2HyHgGTysmukkmcwRcef9cC7ZFSYiAWQ3acNf5Cn5YCRISD1wXhseeI 3cIw== X-Gm-Message-State: AOAM5300jAVPArSEXxodNHZyi+64jNz+6p1RjT0no1fDAmlyYyVbBNDM zwXCTwHt2R1at0L4qBvYQdyjMnRGlrU= X-Google-Smtp-Source: ABdhPJx2lkt/R40XOt0wkDu2u430HUlMx8R5rdM4OUU/cGjs6qMMe4VDftu7xQ3jzqhUTXfvgkik+g== X-Received: by 2002:a17:906:a415:: with SMTP id l21mr1961258ejz.2.1606910839990; Wed, 02 Dec 2020 04:07:19 -0800 (PST) Received: from localhost.localdomain ([31.210.181.203]) by smtp.gmail.com with ESMTPSA id b7sm1058227ejj.85.2020.12.02.04.07.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Dec 2020 04:07:19 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 2/7] inotify: convert to handle_inode_event() interface Date: Wed, 2 Dec 2020 14:07:08 +0200 Message-Id: <20201202120713.702387-3-amir73il@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201202120713.702387-1-amir73il@gmail.com> References: <20201202120713.702387-1-amir73il@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Convert inotify to use the simple handle_inode_event() interface to get rid of the code duplication between the generic helper fsnotify_handle_event() and the inotify_handle_event() callback, which also happen to be buggy code. The bug will be fixed in the generic helper. Signed-off-by: Amir Goldstein --- fs/notify/inotify/inotify.h | 9 +++--- fs/notify/inotify/inotify_fsnotify.c | 47 ++++++---------------------- fs/notify/inotify/inotify_user.c | 7 +---- 3 files changed, 15 insertions(+), 48 deletions(-) diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h index 4327d0e9c364..7fc3782b2fb8 100644 --- a/fs/notify/inotify/inotify.h +++ b/fs/notify/inotify/inotify.h @@ -24,11 +24,10 @@ static inline struct inotify_event_info *INOTIFY_E(struct fsnotify_event *fse) extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group); -extern int inotify_handle_event(struct fsnotify_group *group, u32 mask, - const void *data, int data_type, - struct inode *dir, - const struct qstr *file_name, u32 cookie, - struct fsnotify_iter_info *iter_info); +extern int inotify_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *inode_mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *name, u32 cookie); extern const struct fsnotify_ops inotify_fsnotify_ops; extern struct kmem_cache *inotify_inode_mark_cachep; diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 9ddcbadc98e2..f348c1d3b358 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -55,10 +55,10 @@ static int inotify_merge(struct list_head *list, return event_compare(last_event, event); } -static int inotify_one_event(struct fsnotify_group *group, u32 mask, - struct fsnotify_mark *inode_mark, - const struct path *path, - const struct qstr *file_name, u32 cookie) +int inotify_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *inode_mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *file_name, u32 cookie) { struct inotify_inode_mark *i_mark; struct inotify_event_info *event; @@ -68,10 +68,6 @@ static int inotify_one_event(struct fsnotify_group *group, u32 mask, int alloc_len = sizeof(struct inotify_event_info); struct mem_cgroup *old_memcg; - if ((inode_mark->mask & FS_EXCL_UNLINK) && - path && d_unlinked(path->dentry)) - return 0; - if (file_name) { len = file_name->len; alloc_len += len + 1; @@ -131,35 +127,12 @@ static int inotify_one_event(struct fsnotify_group *group, u32 mask, return 0; } -int inotify_handle_event(struct fsnotify_group *group, u32 mask, - const void *data, int data_type, struct inode *dir, - const struct qstr *file_name, u32 cookie, - struct fsnotify_iter_info *iter_info) +static int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask, + struct inode *inode, struct inode *dir, + const struct qstr *name, u32 cookie) { - const struct path *path = fsnotify_data_path(data, data_type); - struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); - struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info); - int ret = 0; - - if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) - return 0; - - /* - * Some events cannot be sent on both parent and child marks - * (e.g. IN_CREATE). Those events are always sent on inode_mark. - * For events that are possible on both parent and child (e.g. IN_OPEN), - * event is sent on inode_mark with name if the parent is watching and - * is sent on child_mark without name if child is watching. - * If both parent and child are watching, report the event with child's - * name here and report another event without child's name below. - */ - if (inode_mark) - ret = inotify_one_event(group, mask, inode_mark, path, - file_name, cookie); - if (ret || !child_mark) - return ret; - - return inotify_one_event(group, mask, child_mark, path, NULL, 0); + return inotify_handle_event(inode_mark->group, inode_mark, mask, inode, + dir, name, cookie); } static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group) @@ -227,7 +200,7 @@ static void inotify_free_mark(struct fsnotify_mark *fsn_mark) } const struct fsnotify_ops inotify_fsnotify_ops = { - .handle_event = inotify_handle_event, + .handle_inode_event = inotify_handle_inode_event, .free_group_priv = inotify_free_group_priv, .free_event = inotify_free_event, .freeing_mark = inotify_freeing_mark, diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 24d17028375e..b559f296d4cf 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -495,14 +495,9 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group) { struct inotify_inode_mark *i_mark; - struct fsnotify_iter_info iter_info = { }; - - fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE, - fsn_mark); /* Queue ignore event for the watch */ - inotify_handle_event(group, FS_IN_IGNORED, NULL, FSNOTIFY_EVENT_NONE, - NULL, NULL, 0, &iter_info); + inotify_handle_event(group, fsn_mark, FS_IN_IGNORED, NULL, NULL, NULL, 0); i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); /* remove this mark from the idr */ From patchwork Wed Dec 2 12:07:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11945847 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 386D9C83013 for ; Wed, 2 Dec 2020 12:08:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DB4E72222A for ; Wed, 2 Dec 2020 12:08:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387847AbgLBMIn (ORCPT ); Wed, 2 Dec 2020 07:08:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49012 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729690AbgLBMIk (ORCPT ); Wed, 2 Dec 2020 07:08:40 -0500 Received: from mail-ej1-x641.google.com (mail-ej1-x641.google.com [IPv6:2a00:1450:4864:20::641]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B2C2CC061A4C for ; Wed, 2 Dec 2020 04:07:22 -0800 (PST) Received: by mail-ej1-x641.google.com with SMTP id d17so3788652ejy.9 for ; Wed, 02 Dec 2020 04:07:22 -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 :mime-version:content-transfer-encoding; bh=DBohio/dzYx/427lCLMRQSn9ZMdaot71hh7SBHNLl+w=; b=nMmOGjDRiZTq+A/tkZtnhiUecKq569MzeTVZTVME9MvDetLlT/rf9RD8QLtJKHR3wH 4bQMAiUS7iy76fwoBdMAi5DD8VKWIIvkiku/btJ41Z+WQSUFRc02daW1J1vZZHRipKWy SHQfh2HZq5WzuPIMUMSEUhjJaqjil/Xz/jyzTxLMm1eYmi0IKtaialRSqtuAInDVAs/J 2kzAt8TvFnt6VZluFS1khtXucNymJOK6tJVc2FllwJy8/XveCUkXXUcipYCnwdkDuVA0 ws6a3kLEKxuBRN+v9JRHPaeYTnAiFOSy4P+78rQ6e4L7npUFdnahrrGt4HWhvha7ZcOu RFFg== 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:mime-version:content-transfer-encoding; bh=DBohio/dzYx/427lCLMRQSn9ZMdaot71hh7SBHNLl+w=; b=eBxw89htk27KPlxj8yk2YJFTwcb3FYLTt/d/hVOAAuzJMZCI2J973kmP+lVFcXGWhC jlv3MQiWp3fydrkTybmyUH0j7u75/8bz3YQ9rkiQTq/CaKgZV73J1dvF8GID1TlfSwcv X8IVBcLBA1L+kJ9aGzxJyzJYjXWZB+cX5yxpNWv1IYxH7Pm0fcMwGek2dEsvAGFUg/aM /GM4b6g5KUUtMfadAelMckb6CwVUj4OZXiR0SDRpmWNSJCehCN7ZDqAwiNZEMAnWocRc Wd2+LUcKldcSRSnIhllMUGv8rPu+z8GJFDNcp6WhuJQl5Qi0Sjn/7i5WZirJMaAy5ya0 oJBQ== X-Gm-Message-State: AOAM531HAqB5C/Gt2if+o0dXzXPGafY5OPhNhGCUn25/23XFU3D0Os1T 7td32GWPYg5p8UlpB3/VKsTmCEvXak8= X-Google-Smtp-Source: ABdhPJyBHyKeA5eI8IyjcP9RroWhB9ddY/Jd1eOtvSN5JTeDYQBQ8XtuePJw8rIhVrMACTwiMTlELA== X-Received: by 2002:a17:906:1646:: with SMTP id n6mr1934780ejd.89.1606910841369; Wed, 02 Dec 2020 04:07:21 -0800 (PST) Received: from localhost.localdomain ([31.210.181.203]) by smtp.gmail.com with ESMTPSA id b7sm1058227ejj.85.2020.12.02.04.07.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Dec 2020 04:07:20 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 3/7] fsnotify: fix events reported to watching parent and child Date: Wed, 2 Dec 2020 14:07:09 +0200 Message-Id: <20201202120713.702387-4-amir73il@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201202120713.702387-1-amir73il@gmail.com> References: <20201202120713.702387-1-amir73il@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org fsnotify_parent() used to send two separate events to backends when a parent inode is watcing children and the child inode is also watching. In an attempt to avoid duplicate events in fanotify, we unified the two backend callbacks to a single callback and handled the reporting of the two separate events for the relevant backends (inotify and dnotify). The unified event callback with two inode marks (parent and child) is called when both parent and child inode are watched and interested in the event, but they could each be watched by a different group. So before reporting the parent or child event flavor to backend we need to check that the group is really interested in that event flavor. The semantics of INODE and CHILD marks were hard to follow and made the logic more complicated than it should have been. Replace it with INODE and PARENT marks semantics to hopefully make the logic more clear. Fixes: eca4784cbb18 ("fsnotify: send event to parent and child with single callback") Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 7 ++- fs/notify/fsnotify.c | 78 ++++++++++++++++++-------------- include/linux/fsnotify_backend.h | 6 +-- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 9167884a61ec..1192c9953620 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -268,12 +268,11 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, continue; /* - * If the event is for a child and this mark is on a parent not + * If the event is on a child and this mark is on a parent not * watching children, don't send it! */ - if (event_mask & FS_EVENT_ON_CHILD && - type == FSNOTIFY_OBJ_TYPE_INODE && - !(mark->mask & FS_EVENT_ON_CHILD)) + if (type == FSNOTIFY_OBJ_TYPE_PARENT && + !(mark->mask & FS_EVENT_ON_CHILD)) continue; marks_mask |= mark->mask; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index c5c68bcbaadf..0676ce4d3352 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -152,6 +152,13 @@ static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt, if (mask & FS_ISDIR) return false; + /* + * All events that are possible on child can also may be reported with + * parent/name info to inode/sb/mount. Otherwise, a watching parent + * could result in events reported with unexpected name info to sb/mount. + */ + BUILD_BUG_ON(FS_EVENTS_POSS_ON_CHILD & ~FS_EVENTS_POSS_TO_PARENT); + /* Did either inode/sb/mount subscribe for events with parent/name? */ marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask); marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask); @@ -249,6 +256,10 @@ static int fsnotify_handle_inode_event(struct fsnotify_group *group, path && d_unlinked(path->dentry)) return 0; + /* Check interest of this mark in case event was sent with two marks */ + if (!(mask & inode_mark->mask & ALL_FSNOTIFY_EVENTS)) + return 0; + return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie); } @@ -258,38 +269,40 @@ static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, u32 cookie, struct fsnotify_iter_info *iter_info) { struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); - struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info); + struct fsnotify_mark *parent_mark = fsnotify_iter_parent_mark(iter_info); int ret; if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) || WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info))) return 0; - /* - * An event can be sent on child mark iterator instead of inode mark - * iterator because of other groups that have interest of this inode - * and have marks on both parent and child. We can simplify this case. - */ - if (!inode_mark) { - inode_mark = child_mark; - child_mark = NULL; + if (parent_mark) { + /* + * parent_mark indicates that the parent inode is watching children + * and interested in this event, which is an event possible on child. + * But is this mark watching children and interested in this event? + */ + if (parent_mark->mask & FS_EVENT_ON_CHILD) { + ret = fsnotify_handle_inode_event(group, parent_mark, mask, + data, data_type, dir, name, 0); + if (ret) + return ret; + } + if (!inode_mark) + return 0; + + /* + * Some events can be sent on both parent dir and child marks + * (e.g. FS_ATTRIB). If both parent dir and child are watching, + * report the event once to parent dir with name (if interested) + * and once to child without name (if interested). + */ dir = NULL; name = NULL; } - ret = fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type, - dir, name, cookie); - if (ret || !child_mark) - return ret; - - /* - * Some events can be sent on both parent dir and child marks - * (e.g. FS_ATTRIB). If both parent dir and child are watching, - * report the event once to parent dir with name and once to child - * without name. - */ - return fsnotify_handle_inode_event(group, child_mark, mask, data, data_type, - NULL, NULL, 0); + return fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type, + dir, name, cookie); } static int send_to_group(__u32 mask, const void *data, int data_type, @@ -447,7 +460,7 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, struct fsnotify_iter_info iter_info = {}; struct super_block *sb; struct mount *mnt = NULL; - struct inode *child = NULL; + struct inode *parent = NULL; int ret = 0; __u32 test_mask, marks_mask; @@ -459,11 +472,10 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, inode = dir; } else if (mask & FS_EVENT_ON_CHILD) { /* - * Event on child - report on TYPE_INODE to dir if it is - * watching children and on TYPE_CHILD to child. + * Event on child - report on TYPE_PARENT to dir if it is + * watching children and on TYPE_INODE to child. */ - child = inode; - inode = dir; + parent = dir; } sb = inode->i_sb; @@ -477,7 +489,7 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, if (!sb->s_fsnotify_marks && (!mnt || !mnt->mnt_fsnotify_marks) && (!inode || !inode->i_fsnotify_marks) && - (!child || !child->i_fsnotify_marks)) + (!parent || !parent->i_fsnotify_marks)) return 0; marks_mask = sb->s_fsnotify_mask; @@ -485,8 +497,8 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, marks_mask |= mnt->mnt_fsnotify_mask; if (inode) marks_mask |= inode->i_fsnotify_mask; - if (child) - marks_mask |= child->i_fsnotify_mask; + if (parent) + marks_mask |= parent->i_fsnotify_mask; /* @@ -509,9 +521,9 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = fsnotify_first_mark(&inode->i_fsnotify_marks); } - if (child) { - iter_info.marks[FSNOTIFY_OBJ_TYPE_CHILD] = - fsnotify_first_mark(&child->i_fsnotify_marks); + if (parent) { + iter_info.marks[FSNOTIFY_OBJ_TYPE_PARENT] = + fsnotify_first_mark(&parent->i_fsnotify_marks); } /* diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 4ee3044eedd0..a2e42d3cd87c 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -278,7 +278,7 @@ static inline const struct path *fsnotify_data_path(const void *data, enum fsnotify_obj_type { FSNOTIFY_OBJ_TYPE_INODE, - FSNOTIFY_OBJ_TYPE_CHILD, + FSNOTIFY_OBJ_TYPE_PARENT, FSNOTIFY_OBJ_TYPE_VFSMOUNT, FSNOTIFY_OBJ_TYPE_SB, FSNOTIFY_OBJ_TYPE_COUNT, @@ -286,7 +286,7 @@ enum fsnotify_obj_type { }; #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) -#define FSNOTIFY_OBJ_TYPE_CHILD_FL (1U << FSNOTIFY_OBJ_TYPE_CHILD) +#define FSNOTIFY_OBJ_TYPE_PARENT_FL (1U << FSNOTIFY_OBJ_TYPE_PARENT) #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) #define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) @@ -331,7 +331,7 @@ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ } FSNOTIFY_ITER_FUNCS(inode, INODE) -FSNOTIFY_ITER_FUNCS(child, CHILD) +FSNOTIFY_ITER_FUNCS(parent, PARENT) FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) FSNOTIFY_ITER_FUNCS(sb, SB) From patchwork Wed Dec 2 12:07:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11945849 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A52A2C83017 for ; Wed, 2 Dec 2020 12:08:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7530622203 for ; Wed, 2 Dec 2020 12:08:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387520AbgLBMIn (ORCPT ); Wed, 2 Dec 2020 07:08:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729713AbgLBMIk (ORCPT ); Wed, 2 Dec 2020 07:08:40 -0500 Received: from mail-ej1-x643.google.com (mail-ej1-x643.google.com [IPv6:2a00:1450:4864:20::643]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DF6C3C061A4E for ; Wed, 2 Dec 2020 04:07:23 -0800 (PST) Received: by mail-ej1-x643.google.com with SMTP id f23so3815465ejt.8 for ; Wed, 02 Dec 2020 04:07:23 -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 :mime-version:content-transfer-encoding; bh=lKX6zQetXJJsGxnh7QuN6U7Lzwh5cZLmRJU5pvdk5sw=; b=H7Gdcw7W+9XSFD/M3qw6HvvvyITY8Eqk9/j64+s+kxWkYDsrN5WNddeeIDXZl211B/ OgKmnc0ZWbhYq7nCTf+UMHfvuZKt26bkdqMoSt1pIQIo/jKOQJITORalM9RSSIWR9fo8 vyygk/qDSFoa668+XXSdi3Lszuj1ICfpevTGjE+i8FkJuXx2Jc2incX39umSk+4Im6Zi 5XHNVnDNey6u+8YNs42z3zf8K94T64ymVWLua8TrKVSA04YVl0PnyGnqnUHoE2GbK5n4 MDx82wEnCyiV09sEIPDxx0HDwOvWv0Vk7K3z5fO4mkhhLoL8t9rziR8aV5lk9EE8IZBt oXMw== 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:mime-version:content-transfer-encoding; bh=lKX6zQetXJJsGxnh7QuN6U7Lzwh5cZLmRJU5pvdk5sw=; b=n5syL0i8aJihLDIDS7fUguDV5zAi9ufmwaXw7VT19sLBGGnjxo3/z28hYPYAFHqH5/ WBy+R+dbMRPDrkxskLpSJnn+FiwcrDtby/f7fXVqBCI27doYJoBSgpXfjxI30dssa1RC TbRdgm75a6eSGkSy4ep3hi45egkmRJbuswSpzxUQ1HIaJznwkKV6rwsFHX560fu4VG8v H46clN/Sgxt+lcEykHung6xTMkXepDhuv06Beu7d5dGXdaDkJ706Q5MJtLcHSWBInHua c/TJkzek4yOV8D+mPmdQ6GpXxkqFQ1YF5uKg17BoFextEM3UQ4JGk7RkQ8SYiuR+nwwd E6wA== X-Gm-Message-State: AOAM531g+IcId2BFcv0yBHu1Qmrpg/N7W+6wplqTBlpSG8ygM+eDqjcV 36XeNQkrK8Mu/pG/+E18IY3FlSZTNnM= X-Google-Smtp-Source: ABdhPJzURIecKIwgylI3ov4nPTqpyuyvpNc/reNdeYKFOCZuDdqmucdE4CEgMUMAtLNW7FpggFT+yw== X-Received: by 2002:a17:906:d9cf:: with SMTP id qk15mr2026678ejb.453.1606910842614; Wed, 02 Dec 2020 04:07:22 -0800 (PST) Received: from localhost.localdomain ([31.210.181.203]) by smtp.gmail.com with ESMTPSA id b7sm1058227ejj.85.2020.12.02.04.07.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Dec 2020 04:07:22 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 4/7] fsnotify: clarify object type argument Date: Wed, 2 Dec 2020 14:07:10 +0200 Message-Id: <20201202120713.702387-5-amir73il@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201202120713.702387-1-amir73il@gmail.com> References: <20201202120713.702387-1-amir73il@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org In preparation for separating object type from iterator type, rename some 'type' arguments in functions to 'obj_type' and remove the unused interface to clear marks by object type mask. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify_user.c | 8 ++++---- fs/notify/group.c | 2 +- fs/notify/mark.c | 24 ++++++++++++------------ include/linux/fsnotify_backend.h | 25 ++++++++++--------------- 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 3e01d8f2ab90..f9c74fa82038 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -819,7 +819,7 @@ static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group, fsnotify_connp_t *connp, - unsigned int type, + unsigned int obj_type, __kernel_fsid_t *fsid) { struct fsnotify_mark *mark; @@ -833,7 +833,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group, return ERR_PTR(-ENOMEM); fsnotify_init_mark(mark, group); - ret = fsnotify_add_mark_locked(mark, connp, type, 0, fsid); + ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0, fsid); if (ret) { fsnotify_put_mark(mark); return ERR_PTR(ret); @@ -844,7 +844,7 @@ static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group, static int fanotify_add_mark(struct fsnotify_group *group, - fsnotify_connp_t *connp, unsigned int type, + fsnotify_connp_t *connp, unsigned int obj_type, __u32 mask, unsigned int flags, __kernel_fsid_t *fsid) { @@ -854,7 +854,7 @@ static int fanotify_add_mark(struct fsnotify_group *group, mutex_lock(&group->mark_mutex); fsn_mark = fsnotify_find_mark(connp, group); if (!fsn_mark) { - fsn_mark = fanotify_add_new_mark(group, connp, type, fsid); + fsn_mark = fanotify_add_new_mark(group, connp, obj_type, fsid); if (IS_ERR(fsn_mark)) { mutex_unlock(&group->mark_mutex); return PTR_ERR(fsn_mark); diff --git a/fs/notify/group.c b/fs/notify/group.c index a4a4b1c64d32..8255b4c45802 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -58,7 +58,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group) fsnotify_group_stop_queueing(group); /* Clear all marks for this group and queue them for destruction */ - fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES_MASK); + fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_ANY); /* * Some marks can still be pinned when waiting for response from diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 8387937b9d01..7792f5486d61 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -474,7 +474,7 @@ int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b) } static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, - unsigned int type, + unsigned int obj_type, __kernel_fsid_t *fsid) { struct inode *inode = NULL; @@ -485,7 +485,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp, return -ENOMEM; spin_lock_init(&conn->lock); INIT_HLIST_HEAD(&conn->list); - conn->type = type; + conn->type = obj_type; conn->obj = connp; /* Cache fsid of filesystem containing the object */ if (fsid) { @@ -545,7 +545,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector( * priority, highest number first, and then by the group's location in memory. */ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, - fsnotify_connp_t *connp, unsigned int type, + fsnotify_connp_t *connp, unsigned int obj_type, int allow_dups, __kernel_fsid_t *fsid) { struct fsnotify_mark *lmark, *last = NULL; @@ -553,7 +553,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, int cmp; int err = 0; - if (WARN_ON(!fsnotify_valid_obj_type(type))) + if (WARN_ON(!fsnotify_valid_obj_type(obj_type))) return -EINVAL; /* Backend is expected to check for zero fsid (e.g. tmpfs) */ @@ -565,7 +565,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, conn = fsnotify_grab_connector(connp); if (!conn) { spin_unlock(&mark->lock); - err = fsnotify_attach_connector_to_object(connp, type, fsid); + err = fsnotify_attach_connector_to_object(connp, obj_type, fsid); if (err) return err; goto restart; @@ -638,7 +638,7 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark, * event types should be delivered to which group. */ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, - fsnotify_connp_t *connp, unsigned int type, + fsnotify_connp_t *connp, unsigned int obj_type, int allow_dups, __kernel_fsid_t *fsid) { struct fsnotify_group *group = mark->group; @@ -660,7 +660,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, fsnotify_get_mark(mark); /* for g_list */ spin_unlock(&mark->lock); - ret = fsnotify_add_mark_list(mark, connp, type, allow_dups, fsid); + ret = fsnotify_add_mark_list(mark, connp, obj_type, allow_dups, fsid); if (ret) goto err; @@ -681,13 +681,13 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, } int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp, - unsigned int type, int allow_dups, __kernel_fsid_t *fsid) + unsigned int obj_type, int allow_dups, __kernel_fsid_t *fsid) { int ret; struct fsnotify_group *group = mark->group; mutex_lock(&group->mark_mutex); - ret = fsnotify_add_mark_locked(mark, connp, type, allow_dups, fsid); + ret = fsnotify_add_mark_locked(mark, connp, obj_type, allow_dups, fsid); mutex_unlock(&group->mark_mutex); return ret; } @@ -722,14 +722,14 @@ EXPORT_SYMBOL_GPL(fsnotify_find_mark); /* Clear any marks in a group with given type mask */ void fsnotify_clear_marks_by_group(struct fsnotify_group *group, - unsigned int type_mask) + unsigned int obj_type) { struct fsnotify_mark *lmark, *mark; LIST_HEAD(to_free); struct list_head *head = &to_free; /* Skip selection step if we want to clear all marks. */ - if (type_mask == FSNOTIFY_OBJ_ALL_TYPES_MASK) { + if (obj_type == FSNOTIFY_OBJ_TYPE_ANY) { head = &group->marks_list; goto clear; } @@ -744,7 +744,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group, */ mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING); list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) { - if ((1U << mark->connector->type) & type_mask) + if (mark->connector->type == obj_type) list_move(&mark->g_list, &to_free); } mutex_unlock(&group->mark_mutex); diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index a2e42d3cd87c..72bc120a65bc 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -277,6 +277,7 @@ static inline const struct path *fsnotify_data_path(const void *data, } enum fsnotify_obj_type { + FSNOTIFY_OBJ_TYPE_ANY = -1, FSNOTIFY_OBJ_TYPE_INODE, FSNOTIFY_OBJ_TYPE_PARENT, FSNOTIFY_OBJ_TYPE_VFSMOUNT, @@ -285,15 +286,9 @@ enum fsnotify_obj_type { FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT }; -#define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) -#define FSNOTIFY_OBJ_TYPE_PARENT_FL (1U << FSNOTIFY_OBJ_TYPE_PARENT) -#define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) -#define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) -#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) - -static inline bool fsnotify_valid_obj_type(unsigned int type) +static inline bool fsnotify_valid_obj_type(unsigned int obj_type) { - return (type < FSNOTIFY_OBJ_TYPE_COUNT); + return (obj_type < FSNOTIFY_OBJ_TYPE_COUNT); } struct fsnotify_iter_info { @@ -326,7 +321,7 @@ static inline void fsnotify_iter_set_report_type_mark( static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ struct fsnotify_iter_info *iter_info) \ { \ - return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \ + return (iter_info->report_mask & (1U << FSNOTIFY_OBJ_TYPE_##NAME)) ? \ iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \ } @@ -520,11 +515,11 @@ extern int fsnotify_get_conn_fsid(const struct fsnotify_mark_connector *conn, __kernel_fsid_t *fsid); /* attach the mark to the object */ extern int fsnotify_add_mark(struct fsnotify_mark *mark, - fsnotify_connp_t *connp, unsigned int type, + fsnotify_connp_t *connp, unsigned int obj_type, int allow_dups, __kernel_fsid_t *fsid); extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark, fsnotify_connp_t *connp, - unsigned int type, int allow_dups, + unsigned int obj_type, int allow_dups, __kernel_fsid_t *fsid); /* attach the mark to the inode */ @@ -554,21 +549,21 @@ extern void fsnotify_free_mark(struct fsnotify_mark *mark); /* Wait until all marks queued for destruction are destroyed */ extern void fsnotify_wait_marks_destroyed(void); /* run all the marks in a group, and clear all of the marks attached to given object type */ -extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned int type); +extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned int obj_type); /* run all the marks in a group, and clear all of the vfsmount marks */ static inline void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) { - fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL); + fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT); } /* run all the marks in a group, and clear all of the inode marks */ static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group) { - fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL); + fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE); } /* run all the marks in a group, and clear all of the sn marks */ static inline void fsnotify_clear_sb_marks_by_group(struct fsnotify_group *group) { - fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_SB_FL); + fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_SB); } extern void fsnotify_get_mark(struct fsnotify_mark *mark); extern void fsnotify_put_mark(struct fsnotify_mark *mark); From patchwork Wed Dec 2 12:07:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11945853 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3AEBBC83016 for ; Wed, 2 Dec 2020 12:09:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ECD24206F9 for ; Wed, 2 Dec 2020 12:09:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388635AbgLBMJU (ORCPT ); Wed, 2 Dec 2020 07:09:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49118 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388630AbgLBMJT (ORCPT ); Wed, 2 Dec 2020 07:09:19 -0500 Received: from mail-ej1-x643.google.com (mail-ej1-x643.google.com [IPv6:2a00:1450:4864:20::643]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A9CCC061A51 for ; Wed, 2 Dec 2020 04:07:25 -0800 (PST) Received: by mail-ej1-x643.google.com with SMTP id qw4so3765719ejb.12 for ; Wed, 02 Dec 2020 04:07:25 -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 :mime-version:content-transfer-encoding; bh=CBfwF7f1z3lWQIK1kOHunMt4z+tzVG6uRhe6POr10HI=; b=IxChIr6CnTVNZrcMdCT4Swp0nqyI/+TlHeYkLnfuh6OFOsdAkvd/epN3RjEA8j6M03 hE14t1L+c2fbEcLWn/fhYD7IRb43j/VywEc5GXghaIogZFbCNlrv6frnV4hAgCiADzYO 0KWL7epuib/5pm5niWaYLT1KGizWIX6MB8rzm3qV8SwMHNEnomBhgvPK4Rsumj3UHca6 e8f3n1X4s7vCTQfOr0dXI8luqNIUgpM0gujErdjAgjtoBXJMKnRu92KJsjiCTw4pOCyO q7ONAMIFsTQGbIwd4929b16Hx+r6SG7Brh3jPIOa2Qs55d24HympyVinOk3UOLYxl8Dx 29Fg== 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:mime-version:content-transfer-encoding; bh=CBfwF7f1z3lWQIK1kOHunMt4z+tzVG6uRhe6POr10HI=; b=eqPMY8Lglq2rYcaXYe5LFSIbCkZJBWfqCJBIiv0SImTvGfkBAB7U/bexft4xhMXs5j w6exMnax9xIrxmvamfnRHJXwTW+WJefQmxXFoBtPRTP6kCITlWFoDNCQiV1liCRgT7v5 6vzZmW+d8pWfNqdwCHGQW46vI/lJ1fmWlScWVJ6YHJ/5UywWFii7hMylhzi+ivYUeuUb x18Tyi2wRKiBQ3qHBk9Haw1iZVQ2Kxw/zaL80uzZv0nzJxiIvFsVGuXnOOdNbUUTquYR zLTS05i+73NpOvuayVdFXoU9kU3BXjZDpzHjokq2Et9qEXGx/U2rCEgzLWSTJ75/yO1v jEzw== X-Gm-Message-State: AOAM531IlSllSexjRq9qi0HxcpNgvm8IZ19Ls3j5+eubWYteC+aTvjrK YCuOaegP6SdWFNJYr8w4mNA= X-Google-Smtp-Source: ABdhPJyUNw1e6BzyAVzVRCd9UB+8xBe5Rzq8ypjY+72OL0TwNqtBZVnDIMvOQ8vBcEfnhLSk/oPFnw== X-Received: by 2002:a17:906:b857:: with SMTP id ga23mr2059381ejb.122.1606910843884; Wed, 02 Dec 2020 04:07:23 -0800 (PST) Received: from localhost.localdomain ([31.210.181.203]) by smtp.gmail.com with ESMTPSA id b7sm1058227ejj.85.2020.12.02.04.07.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Dec 2020 04:07:23 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 5/7] fsnotify: separate mark iterator type from object type enum Date: Wed, 2 Dec 2020 14:07:11 +0200 Message-Id: <20201202120713.702387-6-amir73il@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201202120713.702387-1-amir73il@gmail.com> References: <20201202120713.702387-1-amir73il@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org They are two different types that use the same enum, so this confusing. Use the object type to indicate the type of object mark is attached to and the iter type to indicate the type of watch. A group can have two different watches of the same object type (parent and child watches) that match the same event. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 6 ++--- fs/notify/fsnotify.c | 26 +++++++++++++------- fs/notify/mark.c | 4 ++-- include/linux/fsnotify_backend.h | 41 ++++++++++++++++++++++---------- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 1192c9953620..8655a1e7c6a6 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -252,7 +252,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, return 0; } - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { if (!fsnotify_iter_should_report_type(iter_info, type)) continue; mark = iter_info->marks[type]; @@ -271,7 +271,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, * If the event is on a child and this mark is on a parent not * watching children, don't send it! */ - if (type == FSNOTIFY_OBJ_TYPE_PARENT && + if (type == FSNOTIFY_ITER_TYPE_PARENT && !(mark->mask & FS_EVENT_ON_CHILD)) continue; @@ -622,7 +622,7 @@ static __kernel_fsid_t fanotify_get_fsid(struct fsnotify_iter_info *iter_info) int type; __kernel_fsid_t fsid = {}; - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { struct fsnotify_mark_connector *conn; if (!fsnotify_iter_should_report_type(iter_info, type)) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 0676ce4d3352..bae3f306ed79 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -321,7 +321,7 @@ static int send_to_group(__u32 mask, const void *data, int data_type, /* clear ignored on inode modification */ if (mask & FS_MODIFY) { - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { if (!fsnotify_iter_should_report_type(iter_info, type)) continue; mark = iter_info->marks[type]; @@ -331,7 +331,7 @@ static int send_to_group(__u32 mask, const void *data, int data_type, } } - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { if (!fsnotify_iter_should_report_type(iter_info, type)) continue; mark = iter_info->marks[type]; @@ -396,7 +396,7 @@ static unsigned int fsnotify_iter_select_report_types( int type; /* Choose max prio group among groups of all queue heads */ - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { mark = iter_info->marks[type]; if (mark && fsnotify_compare_groups(max_prio_group, mark->group) > 0) @@ -408,7 +408,7 @@ static unsigned int fsnotify_iter_select_report_types( /* Set the report mask for marks from same group as max prio group */ iter_info->report_mask = 0; - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { mark = iter_info->marks[type]; if (mark && fsnotify_compare_groups(max_prio_group, mark->group) == 0) @@ -426,7 +426,7 @@ static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info) { int type; - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { if (fsnotify_iter_should_report_type(iter_info, type)) iter_info->marks[type] = fsnotify_next_mark(iter_info->marks[type]); @@ -511,18 +511,26 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); - iter_info.marks[FSNOTIFY_OBJ_TYPE_SB] = + /* + * Just in case some backend still assumes that iterator type means + * object type. We can relax this in the future. + */ + BUILD_BUG_ON(FSNOTIFY_OBJ_TYPE_INODE != (int)FSNOTIFY_ITER_TYPE_INODE); + BUILD_BUG_ON(FSNOTIFY_OBJ_TYPE_VFSMOUNT != (int)FSNOTIFY_ITER_TYPE_VFSMOUNT); + BUILD_BUG_ON(FSNOTIFY_OBJ_TYPE_SB != (int)FSNOTIFY_ITER_TYPE_SB); + + iter_info.marks[FSNOTIFY_ITER_TYPE_SB] = fsnotify_first_mark(&sb->s_fsnotify_marks); if (mnt) { - iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] = + iter_info.marks[FSNOTIFY_ITER_TYPE_VFSMOUNT] = fsnotify_first_mark(&mnt->mnt_fsnotify_marks); } if (inode) { - iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = + iter_info.marks[FSNOTIFY_ITER_TYPE_INODE] = fsnotify_first_mark(&inode->i_fsnotify_marks); } if (parent) { - iter_info.marks[FSNOTIFY_OBJ_TYPE_PARENT] = + iter_info.marks[FSNOTIFY_ITER_TYPE_PARENT] = fsnotify_first_mark(&parent->i_fsnotify_marks); } diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 7792f5486d61..ffa682cb747b 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -329,7 +329,7 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info) { int type; - fsnotify_foreach_obj_type(type) { + fsnotify_foreach_iter_type(type) { /* This can fail if mark is being removed */ if (!fsnotify_get_mark_safe(iter_info->marks[type])) { __release(&fsnotify_mark_srcu); @@ -358,7 +358,7 @@ void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info) int type; iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); - fsnotify_foreach_obj_type(type) + fsnotify_foreach_iter_type(type) fsnotify_put_mark_wake(iter_info->marks[type]); } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 72bc120a65bc..9d03f031a41b 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -276,10 +276,25 @@ static inline const struct path *fsnotify_data_path(const void *data, } } +/* + * Index to merged marks iterator array that correlates to a type of watch. + * The type of watched object can be deduced from the iterator type, but not + * the other way around, because an event can match different watched objects + * of the same object type. + * For example, both parent and child are watching an object of type inode. + */ +enum fsnotify_iter_type { + FSNOTIFY_ITER_TYPE_INODE, + FSNOTIFY_ITER_TYPE_VFSMOUNT, + FSNOTIFY_ITER_TYPE_SB, + FSNOTIFY_ITER_TYPE_PARENT, + FSNOTIFY_ITER_TYPE_COUNT +}; + +/* The type of object that a mark is attached to */ enum fsnotify_obj_type { FSNOTIFY_OBJ_TYPE_ANY = -1, FSNOTIFY_OBJ_TYPE_INODE, - FSNOTIFY_OBJ_TYPE_PARENT, FSNOTIFY_OBJ_TYPE_VFSMOUNT, FSNOTIFY_OBJ_TYPE_SB, FSNOTIFY_OBJ_TYPE_COUNT, @@ -292,37 +307,37 @@ static inline bool fsnotify_valid_obj_type(unsigned int obj_type) } struct fsnotify_iter_info { - struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT]; + struct fsnotify_mark *marks[FSNOTIFY_ITER_TYPE_COUNT]; unsigned int report_mask; int srcu_idx; }; static inline bool fsnotify_iter_should_report_type( - struct fsnotify_iter_info *iter_info, int type) + struct fsnotify_iter_info *iter_info, int iter_type) { - return (iter_info->report_mask & (1U << type)); + return (iter_info->report_mask & (1U << iter_type)); } static inline void fsnotify_iter_set_report_type( - struct fsnotify_iter_info *iter_info, int type) + struct fsnotify_iter_info *iter_info, int iter_type) { - iter_info->report_mask |= (1U << type); + iter_info->report_mask |= (1U << iter_type); } static inline void fsnotify_iter_set_report_type_mark( - struct fsnotify_iter_info *iter_info, int type, + struct fsnotify_iter_info *iter_info, int iter_type, struct fsnotify_mark *mark) { - iter_info->marks[type] = mark; - iter_info->report_mask |= (1U << type); + iter_info->marks[iter_type] = mark; + iter_info->report_mask |= (1U << iter_type); } #define FSNOTIFY_ITER_FUNCS(name, NAME) \ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ struct fsnotify_iter_info *iter_info) \ { \ - return (iter_info->report_mask & (1U << FSNOTIFY_OBJ_TYPE_##NAME)) ? \ - iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \ + return (iter_info->report_mask & (1U << FSNOTIFY_ITER_TYPE_##NAME)) ? \ + iter_info->marks[FSNOTIFY_ITER_TYPE_##NAME] : NULL; \ } FSNOTIFY_ITER_FUNCS(inode, INODE) @@ -330,8 +345,8 @@ FSNOTIFY_ITER_FUNCS(parent, PARENT) FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) FSNOTIFY_ITER_FUNCS(sb, SB) -#define fsnotify_foreach_obj_type(type) \ - for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++) +#define fsnotify_foreach_iter_type(type) \ + for (type = 0; type < FSNOTIFY_ITER_TYPE_COUNT; type++) /* * fsnotify_connp_t is what we embed in objects which connector can be attached From patchwork Wed Dec 2 12:07:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11945851 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 66B3FC64E8A for ; Wed, 2 Dec 2020 12:09:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 06ACC221FE for ; Wed, 2 Dec 2020 12:09:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388591AbgLBMI6 (ORCPT ); Wed, 2 Dec 2020 07:08:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388420AbgLBMIy (ORCPT ); Wed, 2 Dec 2020 07:08:54 -0500 Received: from mail-ej1-x644.google.com (mail-ej1-x644.google.com [IPv6:2a00:1450:4864:20::644]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E1AAC08C5F2 for ; Wed, 2 Dec 2020 04:07:26 -0800 (PST) Received: by mail-ej1-x644.google.com with SMTP id x16so3806558ejj.7 for ; Wed, 02 Dec 2020 04:07:26 -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 :mime-version:content-transfer-encoding; bh=YQPwA+EPK2TqK1y02Hl1Va4w5gZayvzdWcX47Nivrn4=; b=WyPLaZlmv+qDCc4YDtjlbAfFw1K3azM2KWqwmRF476nFY5mjM7RycZprXicIUW6oEF AGbmC7OlOXz/Y5J7Q0HZ5nA/0hJBFmbo5Gxj5f6mE5uWC25+WFYRcrQ0QYm51jQ+u6kJ plxE093R9bcEOTpBeppFoNXGrAo9GBkcCyjtMyK+vvW9GwdV/1UQ2Y/lwFGuubtGXmTL q4p3shVUyP1tjIxFxFQFsgVYe3GVdlEILC+wgdnpSA3l65/67udW2fTYlG9nB3gYNzpx 5IrVWT3wg4A3D9QERqu0ZvAwsfDvC01ey5zrO1CuuHyyqAszoMIVfLQ+4wXsmmM02LxQ 8nPQ== 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:mime-version:content-transfer-encoding; bh=YQPwA+EPK2TqK1y02Hl1Va4w5gZayvzdWcX47Nivrn4=; b=op1AaJi1V7hmIPgSecTVOomzxZHEdQRjY+W4t2aFebj9Zmygg/bEGzzilLVsEP0HXr b2JwmfYgDWtjqaWibCZqiYQhew83F4yMfGLKNJMce+eowl8Azj71NSZ9LMkUlRmudejd XezUwFedBd1eEc56KDKI/QMx6b7Q+b48hUu1DByk0iYLMRcgkowIqLHJO+RFfkjzxRGM 7qsDDVbUnIkvgy0+lPMTLvv1yiCygqGvnEzfEH2iZkWv3bOaYcOtnA2X5gyMDpP1rEcH Jy6JULs0/kWUqdat0pX+EhzwUnmUbN9KAAsYAN29VvzUDBM81q1jyV18/OzpLfiV2cKH s7Gw== X-Gm-Message-State: AOAM531fYmfHsQ6c78zXQoWCTc7eO9jngf3Ilw/wwIZW1oQyG+m+I8Jw nLqV2oZdvowLt3YwUziH4GHhDKvkeQY= X-Google-Smtp-Source: ABdhPJxesR7ONnR6PIdenhcr9wd4E958z6zgIiox9qNPac+nHm18w2MMzTe67IF7fRzPAIgUyX+QVw== X-Received: by 2002:a17:906:b1c8:: with SMTP id bv8mr2000208ejb.208.1606910845088; Wed, 02 Dec 2020 04:07:25 -0800 (PST) Received: from localhost.localdomain ([31.210.181.203]) by smtp.gmail.com with ESMTPSA id b7sm1058227ejj.85.2020.12.02.04.07.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Dec 2020 04:07:24 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 6/7] fsnotify: optimize FS_MODIFY events with no ignored masks Date: Wed, 2 Dec 2020 14:07:12 +0200 Message-Id: <20201202120713.702387-7-amir73il@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201202120713.702387-1-amir73il@gmail.com> References: <20201202120713.702387-1-amir73il@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org fsnotify() treats FS_MODIFY events specially - it does not skip them even if the FS_MODIFY event does not apear in the object's fsnotify mask. This is because send_to_group() checks if FS_MODIFY needs to clear ignored mask of marks. The common case is that an object does not have any mark with ignored mask and in particular, that it does not have a mark with ignored mask and without the FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY flag. Set FS_MODIFY in object's fsnotify mask during fsnotify_recalc_mask() if object has a mark with an ignored mask and without the FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY flag and remove the special treatment of FS_MODIFY in fsnotify(), so that FS_MODIFY events could be optimized in the common case. Call fsnotify_recalc_mask() from fanotify after adding or removing an ignored mask from a mark without FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY or when adding the FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY flag to a mark with ignored mask (the flag cannot be removed by fanotify uapi). Suggested-by: Jan Kara Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify_user.c | 36 ++++++++++++++++++++---------- fs/notify/fsnotify.c | 8 ++++--- fs/notify/mark.c | 2 +- include/linux/fsnotify_backend.h | 15 +++++++++++++ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index f9c74fa82038..80c36da037bb 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -720,17 +720,18 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, __u32 mask, unsigned int flags, __u32 umask, int *destroy) { - __u32 oldmask = 0; + __u32 oldmask, newmask; /* umask bits cannot be removed by user */ mask &= ~umask; spin_lock(&fsn_mark->lock); + oldmask = fsnotify_calc_mask(fsn_mark); if (!(flags & FAN_MARK_IGNORED_MASK)) { - oldmask = fsn_mark->mask; fsn_mark->mask &= ~mask; } else { fsn_mark->ignored_mask &= ~mask; } + newmask = fsnotify_calc_mask(fsn_mark); /* * We need to keep the mark around even if remaining mask cannot * result in any events (e.g. mask == FAN_ONDIR) to support incremenal @@ -740,7 +741,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark, *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask); spin_unlock(&fsn_mark->lock); - return mask & oldmask; + return oldmask & ~newmask; } static int fanotify_remove_mark(struct fsnotify_group *group, @@ -798,23 +799,34 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group, } static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark, - __u32 mask, - unsigned int flags) + __u32 mask, unsigned int flags, + __u32 *removed) { - __u32 oldmask = -1; + __u32 oldmask, newmask; spin_lock(&fsn_mark->lock); + oldmask = fsnotify_calc_mask(fsn_mark); if (!(flags & FAN_MARK_IGNORED_MASK)) { - oldmask = fsn_mark->mask; fsn_mark->mask |= mask; } else { fsn_mark->ignored_mask |= mask; - if (flags & FAN_MARK_IGNORED_SURV_MODIFY) + /* + * Setting FAN_MARK_IGNORED_SURV_MODIFY for the first time + * can lead to the removal of the FS_MODIFY bit in calculated + * mask if it was set because of an ignored mask that from now + * on is going to survive FS_MODIFY. + */ + if ((flags & FAN_MARK_IGNORED_SURV_MODIFY) && + !(fsn_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) { fsn_mark->flags |= FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY; + if (!(fsn_mark->mask & FS_MODIFY)) + *removed = FS_MODIFY; + } } + newmask = fsnotify_calc_mask(fsn_mark); spin_unlock(&fsn_mark->lock); - return mask & ~oldmask; + return newmask & ~oldmask; } static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group, @@ -849,7 +861,7 @@ static int fanotify_add_mark(struct fsnotify_group *group, __kernel_fsid_t *fsid) { struct fsnotify_mark *fsn_mark; - __u32 added; + __u32 added, removed = 0; mutex_lock(&group->mark_mutex); fsn_mark = fsnotify_find_mark(connp, group); @@ -860,8 +872,8 @@ static int fanotify_add_mark(struct fsnotify_group *group, return PTR_ERR(fsn_mark); } } - added = fanotify_mark_add_to_mask(fsn_mark, mask, flags); - if (added & ~fsnotify_conn_mask(fsn_mark->connector)) + added = fanotify_mark_add_to_mask(fsn_mark, mask, flags, &removed); + if (removed || (added & ~fsnotify_conn_mask(fsn_mark->connector))) fsnotify_recalc_mask(fsn_mark->connector); mutex_unlock(&group->mark_mutex); diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index bae3f306ed79..9a26207d1b5d 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -502,11 +502,13 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, /* - * if this is a modify event we may need to clear the ignored masks - * otherwise return if none of the marks care about this type of event. + * If this is a modify event we may need to clear some ignored masks. + * In that case, the object with ignored masks will have the FS_MODIFY + * event in its mask. + * Otherwise, return if none of the marks care about this type of event. */ test_mask = (mask & ALL_FSNOTIFY_EVENTS); - if (!(mask & FS_MODIFY) && !(test_mask & marks_mask)) + if (!(test_mask & marks_mask)) return 0; iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu); diff --git a/fs/notify/mark.c b/fs/notify/mark.c index ffa682cb747b..662963fb510f 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -127,7 +127,7 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) return; hlist_for_each_entry(mark, &conn->list, obj_list) { if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) - new_mask |= mark->mask; + new_mask |= fsnotify_calc_mask(mark); } *fsnotify_conn_mask_p(conn) = new_mask; } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 9d03f031a41b..046fcfb88492 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -516,6 +516,21 @@ extern void fsnotify_remove_queued_event(struct fsnotify_group *group, /* functions used to manipulate the marks attached to inodes */ +/* Get mask for calculating object interest taking ignored mask into account */ +static inline __u32 fsnotify_calc_mask(struct fsnotify_mark *mark) +{ + __u32 mask = mark->mask; + + if (!mark->ignored_mask) + return mask; + + /* Interest in FS_MODIFY may be needed for clearing ignored mask */ + if (!(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) + mask |= FS_MODIFY; + + return mask; +} + /* Get mask of events for a list of marks */ extern __u32 fsnotify_conn_mask(struct fsnotify_mark_connector *conn); /* Calculate mask of events for a list of marks */ From patchwork Wed Dec 2 12:07:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 11945855 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D0D2C83018 for ; Wed, 2 Dec 2020 12:09:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 24C56221FE for ; Wed, 2 Dec 2020 12:09:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2388743AbgLBMJX (ORCPT ); Wed, 2 Dec 2020 07:09:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49134 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388675AbgLBMJW (ORCPT ); Wed, 2 Dec 2020 07:09:22 -0500 Received: from mail-ed1-x544.google.com (mail-ed1-x544.google.com [IPv6:2a00:1450:4864:20::544]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F01B2C08E860 for ; Wed, 2 Dec 2020 04:07:27 -0800 (PST) Received: by mail-ed1-x544.google.com with SMTP id d18so3536584edt.7 for ; Wed, 02 Dec 2020 04:07:27 -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 :mime-version:content-transfer-encoding; bh=JHozK/tuZHUF19wWhEC6pq30khKp2BlBsfQDSbsN/ZI=; b=hNZ2B5D4lMr2ovkUSa/t1ZVNoVohO8AWxFH6s7WSb+P8uiYi9qjnJj+btx4X0cNziL Gkb7la9OtlrxtIA/w1zaQv03TeJwNtSWQ0ssm4rmcpukIKRG5x1+MV8bZC0mc6V54RJo RCNG2WxR5R0w3rwurUnyfZqT5Kimv7Nh1jgR4wMeFl/oX/zxigZtiNZvZRSOa+825RNx M86rHw9J/XC91z9qn/rcl+rxAn5VLz5QEJJypeyCi23yqFOqrLAzpHFCdEJ9Ob2eDtE5 NKLnTZgG2DL3UmeYhW+cAYvNW6DZoUE5SvAoJmNzH3/eBnfjfE76He0jCIP1+P/Aef0R wyzw== 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:mime-version:content-transfer-encoding; bh=JHozK/tuZHUF19wWhEC6pq30khKp2BlBsfQDSbsN/ZI=; b=f2urzULMxZoTQ+3y24ycD/i8rO8TzU3HbMTYWHoVDDj5yQ6mzTrU3T2eCMG3DGwTDu BTUnA1CvWlk4zVE60P2dNGaaqKziU+1zXH0PIb1KR1u2TjFA9vB7XFUBAxFTJDk6ESgu mC8BTVOOa26aXmhuzmvEB7NlX44QKh6TeVbclX6uFp/Y8lQ7GB0ODzEpl8bcBsnyPGHd 53vLrXfqGpvKA99nWXeOUT0Vkk/Q/t9T1/tx/tOjzuMaBr5chO5fZrQoyYyTBV96PBsw iuc0SZaub5Wo2aDE6BCenvBfBYq91n7mcfklshszsu/pXF+L+TFVdpRKTUOELPERSeeo BVuA== X-Gm-Message-State: AOAM531wnm7imV1CD+ydECNRVytjx5FesvRlgXgI7UnZXoVVpXs5zQUM 87pvEgECVyKJcXEa/YOtsfmg8HvfBhU= X-Google-Smtp-Source: ABdhPJzEQFwkllbz1vp3WYCpChN6bwfhyhnNBhy6nWneCUC3lbsI/EhaWfZ8Ht/R4203iaII/QNo/Q== X-Received: by 2002:a50:9518:: with SMTP id u24mr2166773eda.333.1606910846697; Wed, 02 Dec 2020 04:07:26 -0800 (PST) Received: from localhost.localdomain ([31.210.181.203]) by smtp.gmail.com with ESMTPSA id b7sm1058227ejj.85.2020.12.02.04.07.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Dec 2020 04:07:26 -0800 (PST) From: Amir Goldstein To: Jan Kara Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH 7/7] fsnotify: optimize merging of marks with no ignored masks Date: Wed, 2 Dec 2020 14:07:13 +0200 Message-Id: <20201202120713.702387-8-amir73il@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201202120713.702387-1-amir73il@gmail.com> References: <20201202120713.702387-1-amir73il@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org fsnotify() tries to merge marks on all object types (sb, mount, inode) even if the object's mask shows no interest in the specific event type. This is done for the case that the object has marks with the event type in their ignored mask, but the common case is that an object does not have any marks with ignored mask. Set a bit in object's fsnotify mask during fsnotify_recalc_mask() to indicate the existence of any marks with ignored masks. Instead of merging marks of all object types, only merge marks from objects that either showed interest in the specific event type or have any marks with ignored mask. Signed-off-by: Amir Goldstein --- fs/notify/fanotify/fanotify.c | 5 +++++ fs/notify/fsnotify.c | 18 ++++++++++++------ include/linux/fsnotify_backend.h | 12 ++++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 8655a1e7c6a6..4441de2fba11 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -677,6 +677,11 @@ static int fanotify_handle_event(struct fsnotify_group *group, u32 mask, BUILD_BUG_ON(FAN_OPEN_EXEC_PERM != FS_OPEN_EXEC_PERM); BUILD_BUG_ON(HWEIGHT32(ALL_FANOTIFY_EVENT_BITS) != 19); + /* + * FS_HAS_IGNORED_MASK bit is reserved for internal use so should + * not be exposed to fanotify uapi. + */ + BUILD_BUG_ON(ALL_FANOTIFY_EVENT_BITS & FS_HAS_IGNORED_MASK); mask = fanotify_group_event_mask(group, iter_info, mask, data, data_type, dir); diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 9a26207d1b5d..6b3a828db6aa 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -500,7 +500,6 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, if (parent) marks_mask |= parent->i_fsnotify_mask; - /* * If this is a modify event we may need to clear some ignored masks. * In that case, the object with ignored masks will have the FS_MODIFY @@ -521,17 +520,24 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, BUILD_BUG_ON(FSNOTIFY_OBJ_TYPE_VFSMOUNT != (int)FSNOTIFY_ITER_TYPE_VFSMOUNT); BUILD_BUG_ON(FSNOTIFY_OBJ_TYPE_SB != (int)FSNOTIFY_ITER_TYPE_SB); - iter_info.marks[FSNOTIFY_ITER_TYPE_SB] = - fsnotify_first_mark(&sb->s_fsnotify_marks); - if (mnt) { + /* + * Consider only marks that care about this type of event and marks with + * an ignored mask. + */ + test_mask |= FS_HAS_IGNORED_MASK; + if (test_mask && sb->s_fsnotify_mask) { + iter_info.marks[FSNOTIFY_ITER_TYPE_SB] = + fsnotify_first_mark(&sb->s_fsnotify_marks); + } + if (mnt && (test_mask & mnt->mnt_fsnotify_mask)) { iter_info.marks[FSNOTIFY_ITER_TYPE_VFSMOUNT] = fsnotify_first_mark(&mnt->mnt_fsnotify_marks); } - if (inode) { + if (inode && (test_mask & inode->i_fsnotify_mask)) { iter_info.marks[FSNOTIFY_ITER_TYPE_INODE] = fsnotify_first_mark(&inode->i_fsnotify_marks); } - if (parent) { + if (parent && (test_mask & parent->i_fsnotify_mask)) { iter_info.marks[FSNOTIFY_ITER_TYPE_PARENT] = fsnotify_first_mark(&parent->i_fsnotify_marks); } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 046fcfb88492..0615ca2fddf9 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -61,6 +61,14 @@ #define FS_ISDIR 0x40000000 /* event occurred against dir */ #define FS_IN_ONESHOT 0x80000000 /* only send event once */ +/* + * Overload FS_IN_ONESHOT is set only on inotify marks, which never set the + * ignored mask and is not relevant in the object's cumulative mask. + * Overload the flag to indicate the existence of marks on the object that + * have an ignored mask. + */ +#define FS_HAS_IGNORED_MASK FS_IN_ONESHOT + #define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO) /* @@ -522,13 +530,13 @@ static inline __u32 fsnotify_calc_mask(struct fsnotify_mark *mark) __u32 mask = mark->mask; if (!mark->ignored_mask) - return mask; + return mask & ~FS_HAS_IGNORED_MASK; /* Interest in FS_MODIFY may be needed for clearing ignored mask */ if (!(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)) mask |= FS_MODIFY; - return mask; + return mask | FS_HAS_IGNORED_MASK; } /* Get mask of events for a list of marks */