Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp208660pxj; Fri, 28 May 2021 01:58:42 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxceCZnrUPVbHNLm247NgzkGzu52T7YkQtiC3u4gEFZFrpxZ+0RuT5NNQuqNaaUgqll3g5a X-Received: by 2002:a50:9549:: with SMTP id v9mr8797429eda.312.1622192321801; Fri, 28 May 2021 01:58:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1622192321; cv=none; d=google.com; s=arc-20160816; b=EENphYKBWD1VbqiwguG6g/WVzpGqFhawzaW3dvexTnlxkw8787Q0PZO2hCLYl/IKTB u+Fj84GBS7OOna0l+BvlIdBgqch+XK50PF+hV8nSF93UL/e8MFhoBpwEsWi4ATO7HVt5 r1z8GFzVQKKVqaa2P4ra9EPnQbuvtJRLc5n5V5m+kWS3X8xh9N1INn0rVxXtYN3CvVzQ mCFojSn0+UcEF/Jw0tB02An/2/o/19g5dheRL07gGJeQXEhHgVDat/lvLSitUSzmiv78 l09NxO7ROWipGuKTKsNeX1F3OZSwzLhHQqO1nMJangRC1RXhLlsSnNATpvVHe1sshb+k +5bQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject; bh=A3s2Kqp9VeGeAc4fV4qjgG70Dv+e8QxNNfXyz0WKqGc=; b=hlitKTvebDJO/xg4wdaEvne1Tjx3HaO+EUuDDRP6YOVks4gLLGGabu3FacZPfqo4E1 /wxtLp9BCxeZvETjXvuSb2QvyDu7p4Gs6MjSRcYUalMRxf86M/bCTiMEHLS0a1v2rt2B 0hk313OU2LQoqrjJ5OSAc7jH7qAaAezMSUabbr7cz3c/DlF/Mf5JZWn0R4J7CeaRru3w eGlozJE01blM/5/xNCqEPaJsvXMXq7903PdLfQ7r2uJdfwTcbIpJMQCq7cRA2d906BUN 1PWTdUa3l9O2eaL+sw016+zaWW5CBGE3EP2HpA1HtfjNVhnZj8GWlONP/GUmAkc4tKrb le2g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w22si4339028eju.621.2021.05.28.01.58.18; Fri, 28 May 2021 01:58:41 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234573AbhE1GgV convert rfc822-to-8bit (ORCPT + 99 others); Fri, 28 May 2021 02:36:21 -0400 Received: from us-smtp-delivery-44.mimecast.com ([205.139.111.44]:43680 "EHLO us-smtp-delivery-44.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234286AbhE1GgK (ORCPT ); Fri, 28 May 2021 02:36:10 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-246-IjXKAfTwPtuLZXkY2JvE8g-1; Fri, 28 May 2021 02:34:32 -0400 X-MC-Unique: IjXKAfTwPtuLZXkY2JvE8g-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 245FDFC99; Fri, 28 May 2021 06:34:31 +0000 (UTC) Received: from web.messagingengine.com (ovpn-116-22.sin2.redhat.com [10.67.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id E18215C290; Fri, 28 May 2021 06:34:27 +0000 (UTC) Subject: [REPOST PATCH v4 4/5] kernfs: use i_lock to protect concurrent inode updates From: Ian Kent To: Greg Kroah-Hartman , Tejun Heo Cc: Eric Sandeen , Fox Chen , Brice Goglin , Al Viro , Rick Lindsley , David Howells , Miklos Szeredi , Marcelo Tosatti , linux-fsdevel , Kernel Mailing List Date: Fri, 28 May 2021 14:34:26 +0800 Message-ID: <162218366632.34379.11311748209082333016.stgit@web.messagingengine.com> In-Reply-To: <162218354775.34379.5629941272050849549.stgit@web.messagingengine.com> References: <162218354775.34379.5629941272050849549.stgit@web.messagingengine.com> User-Agent: StGit/0.23 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: themaw.net Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The inode operations .permission() and .getattr() use the kernfs node write lock but all that's needed is to keep the rb tree stable while updating the inode attributes as well as protecting the update itself against concurrent changes. And .permission() is called frequently during path walks and can cause quite a bit of contention between kernfs node operations and path walks when the number of concurrent walks is high. To change kernfs_iop_getattr() and kernfs_iop_permission() to take the rw sem read lock instead of the write lock an additional lock is needed to protect against multiple processes concurrently updating the inode attributes and link count in kernfs_refresh_inode(). The inode i_lock seems like the sensible thing to use to protect these inode attribute updates so use it in kernfs_refresh_inode(). Signed-off-by: Ian Kent --- fs/kernfs/inode.c | 10 ++++++---- fs/kernfs/mount.c | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 3b01e9e61f14e..6728ecd81eb37 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -172,6 +172,7 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) { struct kernfs_iattrs *attrs = kn->iattr; + spin_lock(&inode->i_lock); inode->i_mode = kn->mode; if (attrs) /* @@ -182,6 +183,7 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) if (kernfs_type(kn) == KERNFS_DIR) set_nlink(inode, kn->dir.subdirs + 2); + spin_unlock(&inode->i_lock); } int kernfs_iop_getattr(struct user_namespace *mnt_userns, @@ -191,9 +193,9 @@ int kernfs_iop_getattr(struct user_namespace *mnt_userns, struct inode *inode = d_inode(path->dentry); struct kernfs_node *kn = inode->i_private; - down_write(&kernfs_rwsem); + down_read(&kernfs_rwsem); kernfs_refresh_inode(kn, inode); - up_write(&kernfs_rwsem); + up_read(&kernfs_rwsem); generic_fillattr(&init_user_ns, inode, stat); return 0; @@ -284,9 +286,9 @@ int kernfs_iop_permission(struct user_namespace *mnt_userns, kn = inode->i_private; - down_write(&kernfs_rwsem); + down_read(&kernfs_rwsem); kernfs_refresh_inode(kn, inode); - up_write(&kernfs_rwsem); + up_read(&kernfs_rwsem); return generic_permission(&init_user_ns, inode, mask); } diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index baa4155ba2edf..f2f909d09f522 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -255,9 +255,9 @@ static int kernfs_fill_super(struct super_block *sb, struct kernfs_fs_context *k sb->s_shrink.seeks = 0; /* get root inode, initialize and unlock it */ - down_write(&kernfs_rwsem); + down_read(&kernfs_rwsem); inode = kernfs_get_inode(sb, info->root->kn); - up_write(&kernfs_rwsem); + up_read(&kernfs_rwsem); if (!inode) { pr_debug("kernfs: could not get root inode\n"); return -ENOMEM;