From patchwork Wed Mar 15 10:46:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kara X-Patchwork-Id: 9625285 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 6C79F60424 for ; Wed, 15 Mar 2017 10:47:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6AB8D28173 for ; Wed, 15 Mar 2017 10:47:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5FA5B2833C; Wed, 15 Mar 2017 10:47:25 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 D3FB828173 for ; Wed, 15 Mar 2017 10:47:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753061AbdCOKrX (ORCPT ); Wed, 15 Mar 2017 06:47:23 -0400 Received: from mx2.suse.de ([195.135.220.15]:36590 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753167AbdCOKqq (ORCPT ); Wed, 15 Mar 2017 06:46:46 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EFE48AE08; Wed, 15 Mar 2017 10:46:42 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id C5D791E11FF; Wed, 15 Mar 2017 11:46:39 +0100 (CET) From: Jan Kara To: Cc: Miklos Szeredi , Amir Goldstein , Paul Moore , Jan Kara Subject: [PATCH 11/33] fsnotify: Move locking into fsnotify_recalc_mask() Date: Wed, 15 Mar 2017 11:46:10 +0100 Message-Id: <20170315104632.7037-12-jack@suse.cz> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20170315104632.7037-1-jack@suse.cz> References: <20170315104632.7037-1-jack@suse.cz> 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 Move locking of locks protecting a list of marks into fsnotify_recalc_mask(). This reduces code churn in the following patch which changes the lock protecting the list of marks. Signed-off-by: Jan Kara Reviewed-by: Amir Goldstein --- fs/notify/dnotify/dnotify.c | 3 +-- fs/notify/fsnotify.h | 3 --- fs/notify/inode_mark.c | 18 +++------------- fs/notify/mark.c | 45 +++++++++++++++++++++++++++++++--------- fs/notify/vfsmount_mark.c | 13 +++--------- include/linux/fsnotify_backend.h | 2 ++ 6 files changed, 44 insertions(+), 40 deletions(-) diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 5024729dba23..41b2a070761c 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -69,8 +69,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) if (old_mask == new_mask) return; - if (fsn_mark->connector) - fsnotify_recalc_inode_mask(fsn_mark->connector->inode); + fsnotify_recalc_mask(fsn_mark->connector); } /* diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h index 0354338aad78..96051780d50e 100644 --- a/fs/notify/fsnotify.h +++ b/fs/notify/fsnotify.h @@ -14,9 +14,6 @@ extern void fsnotify_flush_notify(struct fsnotify_group *group); /* protects reads of inode and vfsmount marks list */ extern struct srcu_struct fsnotify_mark_srcu; -/* Calculate mask of events for a list of marks */ -extern u32 fsnotify_recalc_mask(struct fsnotify_mark_connector *conn); - /* compare two groups for sorting of marks lists */ extern int fsnotify_compare_groups(struct fsnotify_group *a, struct fsnotify_group *b); diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 87bef7d802db..9b2f4e6eb8eb 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -30,17 +30,9 @@ #include "../internal.h" -/* - * Recalculate the inode->i_fsnotify_mask, or the mask of all FS_* event types - * any notifier is interested in hearing for this inode. - */ void fsnotify_recalc_inode_mask(struct inode *inode) { - spin_lock(&inode->i_lock); - inode->i_fsnotify_mask = fsnotify_recalc_mask(inode->i_fsnotify_marks); - spin_unlock(&inode->i_lock); - - __fsnotify_update_child_dentry_flags(inode); + fsnotify_recalc_mask(inode->i_fsnotify_marks); } struct inode *fsnotify_destroy_inode_mark(struct fsnotify_mark *mark) @@ -57,14 +49,10 @@ struct inode *fsnotify_destroy_inode_mark(struct fsnotify_mark *mark) empty = hlist_empty(&mark->connector->list); mark->connector = NULL; - /* - * this mark is now off the inode->i_fsnotify_marks list and we - * hold the inode->i_lock, so this is the perfect time to update the - * inode->i_fsnotify_mask - */ - inode->i_fsnotify_mask = fsnotify_recalc_mask(inode->i_fsnotify_marks); spin_unlock(&inode->i_lock); + fsnotify_recalc_mask(inode->i_fsnotify_marks); + return empty ? inode : NULL; } diff --git a/fs/notify/mark.c b/fs/notify/mark.c index e8c707d07f9f..e7929539203a 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -105,18 +105,45 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) } } -/* Calculate mask of events for a list of marks */ -u32 fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) +static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) { u32 new_mask = 0; struct fsnotify_mark *mark; + hlist_for_each_entry(mark, &conn->list, obj_list) { + if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED) + new_mask |= mark->mask; + } + if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) + conn->inode->i_fsnotify_mask = new_mask; + else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) + real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask; +} + +/* + * Calculate mask of events for a list of marks. The caller must make sure list + * cannot disappear under us (usually by holding a mark->lock or + * mark->group->mark_mutex for a mark on this list). + */ +void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) +{ if (!conn) - return 0; + return; + + if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) + spin_lock(&conn->inode->i_lock); + else + spin_lock(&conn->mnt->mnt_root->d_lock); + __fsnotify_recalc_mask(conn); + if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) { + struct inode *inode = igrab(conn->inode); - hlist_for_each_entry(mark, &conn->list, obj_list) - new_mask |= mark->mask; - return new_mask; + spin_unlock(&inode->i_lock); + __fsnotify_update_child_dentry_flags(inode); + iput(inode); + } else { + spin_unlock(&conn->mnt->mnt_root->d_lock); + } } /* @@ -411,10 +438,8 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, if (ret) goto err; - if (inode) - fsnotify_recalc_inode_mask(inode); - else - fsnotify_recalc_vfsmount_mask(mnt); + if (mark->mask) + fsnotify_recalc_mask(mark->connector); return ret; err: diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c index 49ccbdb74f82..ffe0d7098cba 100644 --- a/fs/notify/vfsmount_mark.c +++ b/fs/notify/vfsmount_mark.c @@ -34,17 +34,9 @@ void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group) fsnotify_clear_marks_by_group_flags(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT); } -/* - * Recalculate the mnt->mnt_fsnotify_mask, or the mask of all FS_* event types - * any notifier is interested in hearing for this mount point - */ void fsnotify_recalc_vfsmount_mask(struct vfsmount *mnt) { - struct mount *m = real_mount(mnt); - - spin_lock(&mnt->mnt_root->d_lock); - m->mnt_fsnotify_mask = fsnotify_recalc_mask(m->mnt_fsnotify_marks); - spin_unlock(&mnt->mnt_root->d_lock); + fsnotify_recalc_mask(real_mount(mnt)->mnt_fsnotify_marks); } void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark) @@ -60,8 +52,9 @@ void fsnotify_destroy_vfsmount_mark(struct fsnotify_mark *mark) hlist_del_init_rcu(&mark->obj_list); mark->connector = NULL; - m->mnt_fsnotify_mask = fsnotify_recalc_mask(m->mnt_fsnotify_marks); spin_unlock(&mnt->mnt_root->d_lock); + + fsnotify_recalc_mask(m->mnt_fsnotify_marks); } /* diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 96333fb09309..b954f1b2571c 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -327,6 +327,8 @@ extern struct fsnotify_event *fsnotify_remove_first_event(struct fsnotify_group /* functions used to manipulate the marks attached to inodes */ +/* Calculate mask of events for a list of marks */ +extern void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn); /* run all marks associated with a vfsmount and update mnt->mnt_fsnotify_mask */ extern void fsnotify_recalc_vfsmount_mask(struct vfsmount *mnt); /* run all marks associated with an inode and update inode->i_fsnotify_mask */