Received: by 2002:a05:6358:9144:b0:117:f937:c515 with SMTP id r4csp3705462rwr; Sun, 7 May 2023 18:19:54 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4EIviRZffwIUSVtrwfcNNUni80jJi0ixDTZaUb+7FbBG69XnmVTcZOBf0E6/nOIJuSuiBp X-Received: by 2002:a17:903:1252:b0:1aa:f0a7:933 with SMTP id u18-20020a170903125200b001aaf0a70933mr10885517plh.25.1683508794655; Sun, 07 May 2023 18:19:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683508794; cv=none; d=google.com; s=arc-20160816; b=uzDLYDE3d4nYaqMcm4Ga4KO+E39Lk6HFxABndTRY2j9PmpxguKbjRGRBbajrP1/kl4 rULlfOd8zWmgIc0AsSSmSJvt7uEf0TMSuUG9b3CnPO58hJKvKV6JVAvgjAHkExsXmNp2 cSgMhqx8aaQLMW6Xs8j9VZtZgix6ueba0kmoVMGRkTkCqEEEENNYM/s2xXBGJwLoakBM yk9+T+gFtsE8sbxc89zo/p+Uu27WlL1GZ5Uhfc4qHVAw3IXzlSkRixLdTXF3Tmcji6f7 0ofhd/i0MLgInBRePRnKzD8UPL8u6DU3YFjQ2b4BWufkFjRpBblNyc8bTa31/AwC9vV7 uGVw== 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=MQBqMg9ABCp7pDR5MHiqFyaBRKQveeMslSclfU7uPrc=; b=QYCxbBLo5HK69qggdWiij96sea4c5wr9e2bC3WneCoG1FkkdU0/CBRjHqqx1EzFCu6 ypngD6U0chftuKGMkGrZDZoCDB3i6KhdEUy7CaGRjbOWKZXIP44h21tldbXQQpcFin86 4GyuTDoY6XLzxoDtPl36MHbWGEFfXPzXry3/+Ifb2f6ijZtLWFSjyYjpE160X2HoaKO0 i66a1sIbNaBm7oYqafUBVTUQ6zk2htVhRfYAqDQGrztTGeXaBvSPgqib38QqMCLlXY/X FX+v334Z5AMJ5ioUSTJ1ZRWOELnhFVG2Wx45cuT6w+47sCG0coKVSnKTlL6hcDiHvrtw 8rAA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=bombadil.20210309 header.b="MvC8FF9/"; 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 i9-20020a17090332c900b001a50dcd10c2si7286444plr.247.2023.05.07.18.19.39; Sun, 07 May 2023 18:19:54 -0700 (PDT) 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="MvC8FF9/"; 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 S232349AbjEHBRs (ORCPT + 99 others); Sun, 7 May 2023 21:17:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37076 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231624AbjEHBRf (ORCPT ); Sun, 7 May 2023 21:17:35 -0400 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E533F4692; Sun, 7 May 2023 18:17:33 -0700 (PDT) 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=MQBqMg9ABCp7pDR5MHiqFyaBRKQveeMslSclfU7uPrc=; b=MvC8FF9/n/HakVu5oKPLJ2ZVxz Xp42ENNEf8J37Xp5gi7XSkaEjOPxEAbiiZGvLvZS1Ryoa313IgvKue8jNUUWXm4q9Zok7muvzRc0j 4Ja2yzkwpg42KbxDFp683ZK735f9W90iM1BDHjQjaMM7gX3u1Z85PbB13OMoxaPfr6TGmJCX5PnDW u2i3zET0FDORhzINnP8cGAF/eeRbBzkw7Ehd9JxbaC7K6MTGJDUk2GJvEGiWmL6i+I0pFWnveoUEt GK53/l2x59kAY24U1GYm1GWVSZVRLWxTUkAHxFxo8sUXFM1mIpeuDbUMv72PuDeNekOhYq8oVwJfh 26HfsNpg==; Received: from mcgrof by bombadil.infradead.org with local (Exim 4.96 #2 (Red Hat Linux)) id 1pvpV7-00GvZ6-3A; Mon, 08 May 2023 01:17:17 +0000 From: Luis Chamberlain To: hch@infradead.org, djwong@kernel.org, sandeen@sandeen.net, song@kernel.org, rafael@kernel.org, gregkh@linuxfoundation.org, viro@zeniv.linux.org.uk, jack@suse.cz, jikos@kernel.org, bvanassche@acm.org, ebiederm@xmission.com Cc: mchehab@kernel.org, keescook@chromium.org, p.raghav@samsung.com, da.gomez@samsung.com, linux-fsdevel@vger.kernel.org, kernel@tuxforce.de, kexec@lists.infradead.org, linux-kernel@vger.kernel.org, Luis Chamberlain Subject: [PATCH 5/6] fs: add iterate_supers_excl() and iterate_supers_reverse_excl() Date: Sun, 7 May 2023 18:17:16 -0700 Message-Id: <20230508011717.4034511-6-mcgrof@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230508011717.4034511-1-mcgrof@kernel.org> References: <20230508011717.4034511-1-mcgrof@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: Luis Chamberlain X-Spam-Status: No, score=-4.1 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,T_SCC_BODY_TEXT_LINE 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 28c633b81f8f..d5eab6b38b03 100644 --- a/fs/super.c +++ b/fs/super.c @@ -753,6 +753,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 d9b46c858103..22dd697ab703 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2935,6 +2935,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.39.2