Message ID | 170820142021.6328.15047865406275957018.stgit@91.116.238.104.host.secureserver.net |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-70068-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:693c:2685:b0:108:e6aa:91d0 with SMTP id mn5csp494809dyc; Sat, 17 Feb 2024 12:24:35 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXz4dwzewSmS6DdZSIwovWOLmg+7HETgorEpiCYA5Mato8evuglaRHWXMg1SR9LZU8tmdGLzBU0ztHjJUjIDp469Qt+7Q== X-Google-Smtp-Source: AGHT+IHixLv/tMODPIzSoqSUqDVuo/pmFJ15vccovboazNZjkJsXIn/mcviWeagGbvCwg6/Lab1P X-Received: by 2002:a0c:da08:0:b0:68c:3d2a:47e7 with SMTP id x8-20020a0cda08000000b0068c3d2a47e7mr7792316qvj.27.1708201474864; Sat, 17 Feb 2024 12:24:34 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708201474; cv=pass; d=google.com; s=arc-20160816; b=lnd1/JIrXbFWWPADmvdH4FEeN8akj9oY1Fd6AwkGcq82hVSl8NYHHXRWArpDActmfv Ubvy/7UNCtHttlNDzy0uSgfp4tsBVuZt1EIe/dboE/m0OMbC7fMQFZ9NJdkNYz0lWx6m /CFdODne8aMlh7e4mHllxXcgs8gm22J432i2qNu8fYw8QW93yxb/oIkPINYxfaLhnIf+ IUyt3DZDHZl82VqC735wDo4RDeQKnyDn5y/cUDewyw+BZtSJq/jY6187cxHZ6wrrVnmU P47RitKAvX92ewsHtsXCBHH3o9IUB+hKeGI3Ih7CWTf2JBZL/RMHSo0mRmvwGR9DUx7l bfqg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:user-agent:references:in-reply-to :message-id:date:cc:to:from:subject:dkim-signature; bh=LMwQkCs3Uwwg0hCaF42Dp3GN9kHRnCL1eJ1vax4uPe8=; fh=0JMhqiWEaK+qw2xgbbey7OsRaoj7Z6cFR6nhiwhAbe0=; b=azW94U8YhyFrcCinlrYP1oGtLnQZaeqCxmuJqrNitY0ZdNfQsitjKtQ7KkddXzvcgb K7wWcYgnlMYMZ4wguFIH8i7SeRduYKQGtgfcDt8zzs2Fvwq4iyM3MWVyK6IuJ5M87uha haFg41Lf33c6b990jN/XJUIoZxeb98Va/vq3YL6uZnd1Pjm9KHY53lIhF1rRgkcvVSaj H5al2lp5/lYHOecQLTW/2P2l4dl8tUvhRezBZ+CifPeyZkUA6tuEllBlfA6aXqWV15j3 XS6q/8XEcQcmzVSPSi3juZhYxS6ZH+egkpA51o3IUGsxhMf/mO2KaV8/riijWXYIK8ss A9Gg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=P4X30OxK; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-70068-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-70068-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id fn3-20020ad45d63000000b0068cc38d2032si2694982qvb.364.2024.02.17.12.24.34 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Feb 2024 12:24:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-70068-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=P4X30OxK; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-70068-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-70068-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id A510B1C21BD2 for <ouuuleilei@gmail.com>; Sat, 17 Feb 2024 20:24:34 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 355B07F49E; Sat, 17 Feb 2024 20:23:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="P4X30OxK" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F6DC7F48B; Sat, 17 Feb 2024 20:23:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708201422; cv=none; b=OPCVtslzwYeUx0LNhhbZ+xx97T07EOaZWxcQzjb4C9X6X/t+qEQBRncuuMge1Ed4r5l8aa1ZdWU2i/VO2mHpQOkdZd7g7HVtNJN8jB7CdldziP7VTt43AJtHXDIgiE19rGX5YmjVOYdTtCiET/PSbzcq8LoCsW8tjDkQ0zA06Ik= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708201422; c=relaxed/simple; bh=R5X4D36CuE1wpCsrFE/3Fuex0DnO2GtnjfkqVv5cjQg=; h=Subject:From:To:Cc:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BzUEFfjFPuZ4aoi9hVC7uDl1OA6ZiB7JI7Kq1Qy9L2bjt/iHE06/moj1rpQppUAJUSpiwb3YO1F9SdGdpH7KPhJTTdoRU+gxk417zW5XEqClsIFHldXRi7aae1KuxNvr+2aDrOFAdVDUkrqobXpOZbzt/y1P3e0RSfotP8lYOHQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=P4X30OxK; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32618C433F1; Sat, 17 Feb 2024 20:23:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708201422; bh=R5X4D36CuE1wpCsrFE/3Fuex0DnO2GtnjfkqVv5cjQg=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=P4X30OxKc0EN8nPXm8GE/AdSc3yeT5iVNwWMRGyRMVcJFIie5F4caTrhUc28NAuXO 9voVKSq/opp81jg2cRH3/szMzpTTQ/4XgrT8WdD2WpFkvBWhxoEj1F/vcTYv1kOP4+ FZdDrkL9Ov1gk0qvcx9T66jKl6xWpHB0h4rQB5Ze7WhCUX3SKZ6cEUOGk9Z5vnO5+j XY0aze0RMR8AG9xJitjPfN95aBR+joD0NoDr2zyACqqmGYNchunmvsmDUeW9cgCf9a DCi8QemiRpOkaILmDK6aiHQNcv88w0pNMBL71uYhHVosom/O2z6gP7OwvFkgLUc3ph MCA7wONlVDoYw== Subject: [PATCH v2 1/6] libfs: Re-arrange locking in offset_iterate_dir() From: Chuck Lever <cel@kernel.org> To: viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, hughd@google.com, akpm@linux-foundation.org, Liam.Howlett@oracle.com, oliver.sang@intel.com, feng.tang@intel.com Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, maple-tree@lists.infradead.org, linux-mm@kvack.org, lkp@intel.com Date: Sat, 17 Feb 2024 15:23:40 -0500 Message-ID: <170820142021.6328.15047865406275957018.stgit@91.116.238.104.host.secureserver.net> In-Reply-To: <170820083431.6328.16233178852085891453.stgit@91.116.238.104.host.secureserver.net> References: <170820083431.6328.16233178852085891453.stgit@91.116.238.104.host.secureserver.net> User-Agent: StGit/1.5 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791179069430556207 X-GMAIL-MSGID: 1791179069430556207 |
Series |
Use Maple Trees for simple_offset utilities
|
|
Commit Message
Chuck Lever
Feb. 17, 2024, 8:23 p.m. UTC
From: Chuck Lever <chuck.lever@oracle.com> Liam and Matthew say that once the RCU read lock is released, xa_state is not safe to re-use for the next xas_find() call. But the RCU read lock must be released on each loop iteration so that dput(), which might_sleep(), can be called safely. Thus we are forced to walk the offset tree with fresh state for each directory entry. xa_find() can do this for us, though it might be a little less efficient than maintaining xa_state locally. We believe that in the current code base, inode->i_rwsem provides protection for the xa_state maintained in offset_iterate_dir(). However, there is no guarantee that will continue to be the case in the future. Since offset_iterate_dir() doesn't build xa_state locally any more, there's no longer a strong need for offset_find_next(). Clean up by rolling these two helpers together. Suggested-by: Liam R. Howlett <Liam.Howlett@Oracle.com> Message-ID: <170785993027.11135.8830043889278631735.stgit@91.116.238.104.host.secureserver.net> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- fs/libfs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
Comments
On Sat, Feb 17, 2024 at 03:23:40PM -0500, Chuck Lever wrote: > From: Chuck Lever <chuck.lever@oracle.com> > > Liam and Matthew say that once the RCU read lock is released, > xa_state is not safe to re-use for the next xas_find() call. But the > RCU read lock must be released on each loop iteration so that > dput(), which might_sleep(), can be called safely. Fwiw, functions like this: static struct dentry *offset_find_next(struct xa_state *xas) { struct dentry *child, *found = NULL; rcu_read_lock(); child = xas_next_entry(xas, U32_MAX); if (!child) goto out; spin_lock(&child->d_lock); if (simple_positive(child)) found = dget_dlock(child); spin_unlock(&child->d_lock); out: rcu_read_unlock(); return found; } should use the new guard feature going forward imho. IOW, in the future such helpers should be written as: static struct dentry *offset_find_next(struct xa_state *xas) { struct dentry *child, *found = NULL; guard(rcu)(); child = xas_next_entry(xas, U32_MAX); if (!child) return NULL; spin_lock(&child->d_lock); if (simple_positive(child)) found = dget_dlock(child); spin_unlock(&child->d_lock); return found; } which allows you to eliminate the goto and to have the guarantee that the rcu lock is released when you return. This also works for other locks btw.
On Sat 17-02-24 15:23:40, Chuck Lever wrote: > From: Chuck Lever <chuck.lever@oracle.com> > > Liam and Matthew say that once the RCU read lock is released, > xa_state is not safe to re-use for the next xas_find() call. But the > RCU read lock must be released on each loop iteration so that > dput(), which might_sleep(), can be called safely. > > Thus we are forced to walk the offset tree with fresh state for each > directory entry. xa_find() can do this for us, though it might be a > little less efficient than maintaining xa_state locally. > > We believe that in the current code base, inode->i_rwsem provides > protection for the xa_state maintained in > offset_iterate_dir(). However, there is no guarantee that will > continue to be the case in the future. > > Since offset_iterate_dir() doesn't build xa_state locally any more, > there's no longer a strong need for offset_find_next(). Clean up by > rolling these two helpers together. > > Suggested-by: Liam R. Howlett <Liam.Howlett@Oracle.com> > Message-ID: <170785993027.11135.8830043889278631735.stgit@91.116.238.104.host.secureserver.net> > Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Looks good. Feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > fs/libfs.c | 12 ++++++------ > 1 file changed, 6 insertions(+), 6 deletions(-) > > diff --git a/fs/libfs.c b/fs/libfs.c > index eec6031b0155..752e24c669d9 100644 > --- a/fs/libfs.c > +++ b/fs/libfs.c > @@ -402,12 +402,13 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) > return vfs_setpos(file, offset, U32_MAX); > } > > -static struct dentry *offset_find_next(struct xa_state *xas) > +static struct dentry *offset_find_next(struct offset_ctx *octx, loff_t offset) > { > struct dentry *child, *found = NULL; > + XA_STATE(xas, &octx->xa, offset); > > rcu_read_lock(); > - child = xas_next_entry(xas, U32_MAX); > + child = xas_next_entry(&xas, U32_MAX); > if (!child) > goto out; > spin_lock(&child->d_lock); > @@ -430,12 +431,11 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) > > static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) > { > - struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode); > - XA_STATE(xas, &so_ctx->xa, ctx->pos); > + struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode); > struct dentry *dentry; > > while (true) { > - dentry = offset_find_next(&xas); > + dentry = offset_find_next(octx, ctx->pos); > if (!dentry) > return ERR_PTR(-ENOENT); > > @@ -444,8 +444,8 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) > break; > } > > + ctx->pos = dentry2offset(dentry) + 1; > dput(dentry); > - ctx->pos = xas.xa_index + 1; > } > return NULL; > } > >
diff --git a/fs/libfs.c b/fs/libfs.c index eec6031b0155..752e24c669d9 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -402,12 +402,13 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) return vfs_setpos(file, offset, U32_MAX); } -static struct dentry *offset_find_next(struct xa_state *xas) +static struct dentry *offset_find_next(struct offset_ctx *octx, loff_t offset) { struct dentry *child, *found = NULL; + XA_STATE(xas, &octx->xa, offset); rcu_read_lock(); - child = xas_next_entry(xas, U32_MAX); + child = xas_next_entry(&xas, U32_MAX); if (!child) goto out; spin_lock(&child->d_lock); @@ -430,12 +431,11 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) { - struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode); - XA_STATE(xas, &so_ctx->xa, ctx->pos); + struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode); struct dentry *dentry; while (true) { - dentry = offset_find_next(&xas); + dentry = offset_find_next(octx, ctx->pos); if (!dentry) return ERR_PTR(-ENOENT); @@ -444,8 +444,8 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) break; } + ctx->pos = dentry2offset(dentry) + 1; dput(dentry); - ctx->pos = xas.xa_index + 1; } return NULL; }