Received: by 2002:a05:6358:a55:b0:ec:fcf4:3ecf with SMTP id 21csp6344rwb; Fri, 13 Jan 2023 18:02:25 -0800 (PST) X-Google-Smtp-Source: AMrXdXvqutLyyfFuYZ7wjgPXT1Zb1N+FsphuMVE+F0Ts42Id7v4rlnQKT6OEolyFzrNKJ0nGibZW X-Received: by 2002:a17:90a:f296:b0:226:fbcc:2bf8 with SMTP id fs22-20020a17090af29600b00226fbcc2bf8mr23913236pjb.8.1673661744896; Fri, 13 Jan 2023 18:02:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1673661744; cv=none; d=google.com; s=arc-20160816; b=aqZbhPllt6EFIIS3SKCiXn4PD9q1C3r+1ej2o9dy4eKNy1mWPKdALg/zc/15sw+aY9 iNxgmKJnWBFvV/DEH7hP/+EMDC2OiG1e9Eri5w2g1/Iqg+U2uKIa/CFpEY4weqTiF06U IgO2YppS+TTcQAjCgjIjgZTE1vmLqaSqaK3HBRGCadtU5SmAGXTm5WoLnUXcEAPJM6f0 MoqRLf0nvPIDAdCx/t2aUq5KpJV2hp2fdj3C6FSMjx1k4AUQZHlx7w+cMBb+AduHdaD/ ojEvA77NsRIyhP2nBmJ18a/H2vgrVAInvPiqLnHT+HswJ8GGRsvdxEfaOLZ+of3lBlux QNKA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=cJ90Zxchzmc6e+rJwjAlDp2N2Rf4gU8ISNXGV/Bg1dg=; b=hejmbYbqN1516CZQ8n0UlEdvfrSNNr2PSkUXMHMm6gJ2/sUDyTUvz9RQ6i/h/Uv5h9 irpLEWyqmoMZA5KDSfX/yEliAhbHxLq1+jHa1f83iN1c74aGx/raZSFvkGnsiKo+LKNy 4roIVrmnOPmZvJkZXs15rZu1ih+nNmjyh9AO4zOxmUfqcG51gXSYpztbN0HdtMovvZkd iN/bRplQYyoYbwJ+jgqUEoK09EVeWZLa5o8aSW+2PhgJA3fyZXqHfPQaZOLRRRLsNg4R gJXWgmTIp2vmI+y1wlY6UxU+D4DPTAB3oCuZ9D0wrNTfqiq5OPf4W9ooyr7dcZgTZOSU tyOw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=bombadil.20210309 header.b=Bmko63eD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h124-20020a636c82000000b0049ca25d4963si22094107pgc.468.2023.01.13.18.02.18; Fri, 13 Jan 2023 18:02:24 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@infradead.org header.s=bombadil.20210309 header.b=Bmko63eD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231596AbjANAgR (ORCPT + 53 others); Fri, 13 Jan 2023 19:36:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34936 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231338AbjANAe2 (ORCPT ); Fri, 13 Jan 2023 19:34:28 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E32418A231; Fri, 13 Jan 2023 16:34:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Sender:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description; bh=cJ90Zxchzmc6e+rJwjAlDp2N2Rf4gU8ISNXGV/Bg1dg=; b=Bmko63eD7gPu/0vVG8MG8Ap5wp mR+pZzA0VA4e5AXYjtGGyGoGnOQLtEztgzD8kW+LGBdCw45ezTi4SrEKPE6BKutkyBBbxOWiqxd2g nEFcHRNN9pbKK22sw2nUUo0uYMPTXN9QtIMfMcyqM4XwyCpo4dVcfy8TPEgAFHeZas0aAN5ApbVb/ umumRBNAAIZrveBXgcdqpUpa+VeO98Tf3PHc6KhfRF/7cXomuWMGeOpjr3MLzBAwTcqYiDaU58U7n uXZdnfNkDi8cxrAQ2tvabzoUY8m+rynguTdZ2be2DMq6HGmbD2Xlv/1oBXjG9b9vPNUJdU8wzVrBm cVUzghEw==; Received: from mcgrof by bombadil.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1pGUUt-004tw3-1e; Sat, 14 Jan 2023 00:34:11 +0000 From: Luis Chamberlain To: hch@infradead.org, djwong@kernel.org, song@kernel.org, rafael@kernel.org, gregkh@linuxfoundation.org, viro@zeniv.linux.org.uk, jack@suse.cz, bvanassche@acm.org, ebiederm@xmission.com Cc: mchehab@kernel.org, keescook@chromium.org, p.raghav@samsung.com, linux-fsdevel@vger.kernel.org, kernel@tuxforce.de, kexec@lists.infradead.org, linux-kernel@vger.kernel.org, Luis Chamberlain Subject: [RFC v3 04/24] fs: add iterate_supers_excl() and iterate_supers_reverse_excl() Date: Fri, 13 Jan 2023 16:33:49 -0800 Message-Id: <20230114003409.1168311-5-mcgrof@kernel.org> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20230114003409.1168311-1-mcgrof@kernel.org> References: <20230114003409.1168311-1-mcgrof@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: Luis Chamberlain X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org There are use cases where we wish to traverse the superblock list but also capture errors, and in which case we want to avoid having our callers issue a lock themselves since we can do the locking for the callers. Provide a iterate_supers_excl() which calls a function with the write lock held. If an error occurs we capture it and propagate it. Likewise there are use cases where we wish to traverse the superblock list but in reverse order. The new iterate_supers_reverse_excl() helpers does this but also also captures any errors encountered. Reviewed-by: Jan Kara Signed-off-by: Luis Chamberlain --- fs/super.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 + 2 files changed, 93 insertions(+) diff --git a/fs/super.c b/fs/super.c index 0d6b4de8da88..2f77fcb6e555 100644 --- a/fs/super.c +++ b/fs/super.c @@ -732,6 +732,97 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg) spin_unlock(&sb_lock); } +/** + * iterate_supers_excl - exclusively call func for all active superblocks + * @f: function to call + * @arg: argument to pass to it + * + * Scans the superblock list and calls given function, passing it + * locked superblock and given argument. Returns 0 unless an error + * occurred on calling the function on any superblock. + */ +int iterate_supers_excl(int (*f)(struct super_block *, void *), void *arg) +{ + struct super_block *sb, *p = NULL; + int error = 0; + + spin_lock(&sb_lock); + list_for_each_entry(sb, &super_blocks, s_list) { + if (hlist_unhashed(&sb->s_instances)) + continue; + sb->s_count++; + spin_unlock(&sb_lock); + + down_write(&sb->s_umount); + if (sb->s_root && (sb->s_flags & SB_BORN)) { + error = f(sb, arg); + if (error) { + up_write(&sb->s_umount); + spin_lock(&sb_lock); + __put_super(sb); + break; + } + } + up_write(&sb->s_umount); + + spin_lock(&sb_lock); + if (p) + __put_super(p); + p = sb; + } + if (p) + __put_super(p); + spin_unlock(&sb_lock); + + return error; +} + +/** + * iterate_supers_reverse_excl - exclusively calls func in reverse order + * @f: function to call + * @arg: argument to pass to it + * + * Scans the superblock list and calls given function, passing it + * locked superblock and given argument, in reverse order, and holding + * the s_umount write lock. Returns if an error occurred. + */ +int iterate_supers_reverse_excl(int (*f)(struct super_block *, void *), + void *arg) +{ + struct super_block *sb, *p = NULL; + int error = 0; + + spin_lock(&sb_lock); + list_for_each_entry_reverse(sb, &super_blocks, s_list) { + if (hlist_unhashed(&sb->s_instances)) + continue; + sb->s_count++; + spin_unlock(&sb_lock); + + down_write(&sb->s_umount); + if (sb->s_root && (sb->s_flags & SB_BORN)) { + error = f(sb, arg); + if (error) { + up_write(&sb->s_umount); + spin_lock(&sb_lock); + __put_super(sb); + break; + } + } + up_write(&sb->s_umount); + + spin_lock(&sb_lock); + if (p) + __put_super(p); + p = sb; + } + if (p) + __put_super(p); + spin_unlock(&sb_lock); + + return error; +} + /** * iterate_supers_type - call function for superblocks of given type * @type: fs type diff --git a/include/linux/fs.h b/include/linux/fs.h index 3b2586de4364..f168e72f6ca1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2916,6 +2916,8 @@ extern struct super_block *get_active_super(struct block_device *bdev); extern void drop_super(struct super_block *sb); extern void drop_super_exclusive(struct super_block *sb); extern void iterate_supers(void (*)(struct super_block *, void *), void *); +extern int iterate_supers_excl(int (*f)(struct super_block *, void *), void *arg); +extern int iterate_supers_reverse_excl(int (*)(struct super_block *, void *), void *); extern void iterate_supers_type(struct file_system_type *, void (*)(struct super_block *, void *), void *); -- 2.35.1