Message ID | 20230312191031.551204-1-hi@alyssa.is |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp847580wrd; Sun, 12 Mar 2023 12:32:16 -0700 (PDT) X-Google-Smtp-Source: AK7set+qlL1CKuO0HSS28rGyqEchOe/m2wEq4AvLTGQ9qi0584ksGCopTZJKK7xseBtbBMhnUymw X-Received: by 2002:a05:6a20:3d87:b0:be:da1c:df65 with SMTP id s7-20020a056a203d8700b000beda1cdf65mr36843198pzi.28.1678649536242; Sun, 12 Mar 2023 12:32:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1678649536; cv=none; d=google.com; s=arc-20160816; b=FtseoGg5K0FtT1ATwtbrP8+dTfZP+wzkZ5ApisUWzc1wPWY7Fg80G7lCB4YVBCYVAJ 9A0CWZa5gNFOtXU+42m9eGnYfFNN7fYQXfjjBfm0SBXiz67Yy8E/QmNMHDEGyVf3XTm1 i1NGXk9n4CtzJict6K719oJxZlMToyg7xBl2+rPWVO5Nlz825UzLm5hogVt0HXZjTk2r Sq9Z/GOgZC9VIrgO9RZDXM5v3dTGnxRm1yfEdCG8zm3VRPQYKIZCEsbkNHK2F15hRtkX j0PCqkomfKz42MeGtsYCmjv/Bff+u8euKIEYKnXFPRq0QHai3EZK2FVIv8DRJBNMQtwY Lk0A== 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 :message-id:date:subject:cc:to:from:feedback-id:dkim-signature :dkim-signature; bh=Cvh4ZiacG5VE6kcR8Gk7s5+fYYDWMIvbwr/3VYeaQZ4=; b=G3DQpsGtzcR6qzmopuGDaNaPDxdSX/xj1w/Eg2xQtT8h2zxbhH2emCATjvIaIehljG bDf+nCNRsYLt23NSVh3aceuZxOxG3t3Nb2jx68Onye0HXAaOaTZGeANWvHKyFmJDgrce /ItOvUyUBuYBQlkRM0/WKR79apviFtj8tIb+yZhP3ksOJuAYizYg3pr3tNThP65JoWal cuqTw4FLCTXcKCb8LfoTRwsF/wtZ0aGRMJRE/6kUum6Cuxh9lhAaTMyFDRI8OJcluLe1 Zlq8B+Hqrw02EaUYUvP0XU+Y7jFtW7qMY5jj3UUVqgPHG22BBa+vrYTfZmkKeisBiv0p cX/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@alyssa.is header.s=fm1 header.b=kX+AnLqL; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b="vRA11/tA"; 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 Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id q139-20020a632a91000000b005091105ca8bsi3432061pgq.35.2023.03.12.12.32.01; Sun, 12 Mar 2023 12:32:16 -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=@alyssa.is header.s=fm1 header.b=kX+AnLqL; dkim=pass header.i=@messagingengine.com header.s=fm2 header.b="vRA11/tA"; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230040AbjCLTLB (ORCPT <rfc822;realc9580@gmail.com> + 99 others); Sun, 12 Mar 2023 15:11:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58794 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229925AbjCLTK7 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Sun, 12 Mar 2023 15:10:59 -0400 Received: from wout2-smtp.messagingengine.com (wout2-smtp.messagingengine.com [64.147.123.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0BBB5303DB; Sun, 12 Mar 2023 12:10:49 -0700 (PDT) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.west.internal (Postfix) with ESMTP id 9E524320046E; Sun, 12 Mar 2023 15:10:47 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Sun, 12 Mar 2023 15:10:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alyssa.is; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:message-id:mime-version:reply-to :sender:subject:subject:to:to; s=fm1; t=1678648247; x= 1678734647; bh=Cvh4ZiacG5VE6kcR8Gk7s5+fYYDWMIvbwr/3VYeaQZ4=; b=k X+AnLqLq4MLdXHy+t+2is0PlLlD7ud3YWETgaLWAP5nQ5kVuhBCdwSpTx/S62NbI 7+HRx3jRkN8Y9B20bCvyDPtTtw90qRFZN/yYrGoOqmHJAFBf/vH98xKQ67lmAw/u KjxdDaVXs/16cCRKyOo2k2YsI8uaS7OIHVHl07X+RFw5ioITxeDzYHDI1qPpC3OX y+s/fD+64p6BgPXxh8an5lGc1fxOQnah4SCsxpkZ1qR9o/NYnBsN6eMnXFPQmZWv 1fE9DzScWIgzbgLGEzid6asztQno2ltg5GchMSRfbOR1tDKe+1if8zHxsC1WMBZg 0KFocWKYPbS3ghXDRGTHA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:message-id:mime-version:reply-to:sender :subject:subject:to:to:x-me-proxy:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm2; t=1678648247; x=1678734647; bh=C vh4ZiacG5VE6kcR8Gk7s5+fYYDWMIvbwr/3VYeaQZ4=; b=vRA11/tAGCHarmsIR s2nKwyc0GCeCAKvbfF/ZhBJjEU9Ip+gCnurM6Q6qsHCjpfzv4P3zgeNGgrymWjP3 zdZhqeAQ74Nw7uYu/YDthOvq5OU4T7MZnOo6aqLgXNQbxGWX6RWQcoyR9Ph+dZ55 ikt7jS71lk2v99aigtZJPV5SBDKrM7USbnWnd/30jyiAOiqDoGMuPErUiANvXYWg z4Yhn5qlMQsqxSb1pFpivhpZrpSdptpfTINywVNShyBf/uf72k+8T49MyBPVNmlJ vO/2m892Am6rNSeqbV/5f5uNLXAbSoitMz88bjl870TnV0M1WHokeBraj1EnO8ep FFl2g== X-ME-Sender: <xms:tiMOZLZNPbBlvpD6EebseWHHRnEqRjmlf5aiOIBqu63oPF5vzTQmOQ> <xme:tiMOZKa2qd2vmYwvG563FWj-7y6bbJLguiPcVQWrDxfgPApc4DNXkUf3Z1Of2hbl8 EyWwfpGfK82CBnWig> X-ME-Received: <xmr:tiMOZN9AxCea0RtN7VS-V5g9W_lhgHtqZ4Z7MASgGYYz32B6Anonfxs_mZBL_t0PR3bV6SdyaN1NP50c_GJhgGz1wO4YZpuRNQ> X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvddvvddguddvtdcutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpefhvfevufffkffogggtgfesthekredtredtjeenucfhrhhomheptehlhihs shgrucftohhsshcuoehhihesrghlhihsshgrrdhisheqnecuggftrfgrthhtvghrnhepve evgfehledtieelffegvdegveeukeevhfdtteeggeejvdduveegvefftefgueffnecuffho mhgrihhnpehkvghrnhgvlhdrohhrghenucevlhhushhtvghrufhiiigvpedtnecurfgrrh grmhepmhgrihhlfhhrohhmpehhihesrghlhihsshgrrdhish X-ME-Proxy: <xmx:tiMOZBplT7Ushm42rQUl_PyR8nzY1xxCu5d4WQoxjE2P6scdIaPo2A> <xmx:tiMOZGos34MSyNMXe1A5gz_SZ37XCx9Oiwvn2QIp7qW4qclqABcjuQ> <xmx:tiMOZHTBiwYW4eJunuRWqjo6hKX36y0tBYRLz3aB2sR8olTWfbUc1g> <xmx:tyMOZN2cd5oNEs6W7sGqAtYnM0uOJhcwEfv26X93_i8j8BFExTswrw> Feedback-ID: i12284293:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 12 Mar 2023 15:10:46 -0400 (EDT) Received: by x220.qyliss.net (Postfix, from userid 1000) id 3B3C423881; Sun, 12 Mar 2023 19:10:39 +0000 (UTC) From: Alyssa Ross <hi@alyssa.is> To: Jens Axboe <axboe@kernel.dk> Cc: linux-kernel@vger.kernel.org, Alyssa Ross <hi@alyssa.is>, Martijn Coenen <maco@android.com>, linux-block@vger.kernel.org Subject: [PATCH v2] loop: LOOP_CONFIGURE: send uevents for partitions Date: Sun, 12 Mar 2023 19:10:31 +0000 Message-Id: <20230312191031.551204-1-hi@alyssa.is> X-Mailer: git-send-email 2.37.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1760191616096116699?= X-GMAIL-MSGID: =?utf-8?q?1760191616096116699?= |
Series |
[v2] loop: LOOP_CONFIGURE: send uevents for partitions
|
|
Commit Message
Alyssa Ross
March 12, 2023, 7:10 p.m. UTC
LOOP_CONFIGURE is, as far as I understand it, supposed to be a way to
combine LOOP_SET_FD and LOOP_SET_STATUS64 into a single syscall. When
using LOOP_SET_FD+LOOP_SET_STATUS64, a single uevent would be sent for
each partition found on the loop device after the second ioctl(), but
when using LOOP_CONFIGURE, no such uevent was being sent.
In the old setup, uevents are disabled for LOOP_SET_FD, but not for
LOOP_SET_STATUS64. This makes sense, as it prevents uevents being
sent for a partially configured device during LOOP_SET_FD — they're
only sent at the end of LOOP_SET_STATUS64. But for LOOP_CONFIGURE,
uevents were disabled for the entire operation, so that final
notification was never issued. To fix this, I've moved the
loop_reread_partitions() call, which causes the uevents to be issued,
to after uevents are re-enabled, matching the behaviour of the
LOOP_SET_FD+LOOP_SET_STATUS64 combination.
I noticed this because Busybox's losetup program recently changed from
using LOOP_SET_FD+LOOP_SET_STATUS64 to LOOP_CONFIGURE, and this broke
my setup, for which I want a notification from the kernel any time a
new partition becomes available.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
Fixes: 3448914e8cc5 ("loop: Add LOOP_CONFIGURE ioctl")
---
v1: https://lore.kernel.org/linux-block/20230221222847.607096-1-hi@alyssa.is/
v1 was an RFC, because I was looking for advice on how to handle
distinguishing between LOOP_SET_FD with non-zero max_part (in which
case partscan will be true, but a uevent should not be emitted), and
LOOP_CONFIGURE (where a uevent should be emitted). I didn't hear
anything, but I did some experimentation of my own, and adding a
partscan_uevent parameter to distinguish between LOOP_SET_FD and
LOOP_CONFIGURE feels like the least bad solution to me.
drivers/block/loop.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
Comments
On Sun, Mar 12, 2023 at 07:10:31PM +0000, Alyssa Ross wrote: > + * Now that we are done, reread the partitions with uevent > + * re-enabled if appropriate to let userspace know about the > + * changes. > + */ > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), !partscan_uevent); > + if (partscan) > + loop_reread_partitions(lo); > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); What worries me here is that you move the partition re-read out of the exclusive claim, which is another potentially user visible change (and user visible behavior changes are a field of landmines in loop as you have noticed). But in the end we only need to suppress the events until Lo_Bound is set. So something like the patch below that reduces the no even critical section might do the job? diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 839373451c2b7d..9d61c027185141 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1010,9 +1010,6 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, /* This is safe, since we have a reference from open(). */ __module_get(THIS_MODULE); - /* suppress uevents while reconfiguring the device */ - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); - /* * If we don't hold exclusive handle for the device, upgrade to it * here to avoid changing device under exclusive owner. @@ -1067,6 +1064,9 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, } } + /* suppress uevents while reconfiguring the device */ + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); + disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0); @@ -1109,17 +1109,17 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, if (partscan) clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); + /* enable and uncork uevent now that we are done */ + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); + loop_global_unlock(lo, is_loop); if (partscan) loop_reread_partitions(lo); + if (!(mode & FMODE_EXCL)) bd_abort_claiming(bdev, loop_configure); - error = 0; -done: - /* enable and uncork uevent now that we are done */ - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); - return error; + return 0; out_unlock: loop_global_unlock(lo, is_loop); @@ -1130,7 +1130,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, fput(file); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); - goto done; + return error; } static void __loop_clr_fd(struct loop_device *lo, bool release)
On Wed, Mar 15, 2023 at 08:48:40AM -0700, Christoph Hellwig wrote: > On Sun, Mar 12, 2023 at 07:10:31PM +0000, Alyssa Ross wrote: > > + * Now that we are done, reread the partitions with uevent > > + * re-enabled if appropriate to let userspace know about the > > + * changes. > > + */ > > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), !partscan_uevent); > > + if (partscan) > > + loop_reread_partitions(lo); > > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); > > What worries me here is that you move the partition re-read out of > the exclusive claim, which is another potentially user visible > change (and user visible behavior changes are a field of landmines > in loop as you have noticed). Makes sense. > But in the end we only need to suppress the events until Lo_Bound > is set. So something like the patch below that reduces the no even > critical section might do the job? If you say so! I had trouble understanding which parts of the function uevents needed to be suppressed for, so I was trying to move as little as possible out of that section. What happens next? I'm still getting up to speed on the kernel development process — will you submit this as a patch with a patch body and a S-o-b? Or am I supposed to do something with it? I know enough to know that I should give you a: Tested-by: Alyssa Ross <hi@alyssa.is> > diff --git a/drivers/block/loop.c b/drivers/block/loop.c > index 839373451c2b7d..9d61c027185141 100644 > --- a/drivers/block/loop.c > +++ b/drivers/block/loop.c > @@ -1010,9 +1010,6 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > /* This is safe, since we have a reference from open(). */ > __module_get(THIS_MODULE); > > - /* suppress uevents while reconfiguring the device */ > - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); > - > /* > * If we don't hold exclusive handle for the device, upgrade to it > * here to avoid changing device under exclusive owner. > @@ -1067,6 +1064,9 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > } > } > > + /* suppress uevents while reconfiguring the device */ > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); > + > disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); > set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0); > > @@ -1109,17 +1109,17 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > if (partscan) > clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); > > + /* enable and uncork uevent now that we are done */ > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); > + > loop_global_unlock(lo, is_loop); > if (partscan) > loop_reread_partitions(lo); > + > if (!(mode & FMODE_EXCL)) > bd_abort_claiming(bdev, loop_configure); > > - error = 0; > -done: > - /* enable and uncork uevent now that we are done */ > - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); > - return error; > + return 0; > > out_unlock: > loop_global_unlock(lo, is_loop); > @@ -1130,7 +1130,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > fput(file); > /* This is safe: open() is still holding a reference. */ > module_put(THIS_MODULE); > - goto done; > + return error; > } > > static void __loop_clr_fd(struct loop_device *lo, bool release)
On Sat, Mar 18, 2023 at 01:50:05AM +0000, Alyssa Ross wrote: > If you say so! I had trouble understanding which parts of the function > uevents needed to be suppressed for, so I was trying to move as little > as possible out of that section. > > What happens next? I'm still getting up to speed on the kernel > development process — will you submit this as a patch with a patch body > and a S-o-b? Or am I supposed to do something with it? Given that you're done all the hard work, and I've just reduced the critical section, I'd prefer to give all the credit to you. If you're fine with it, I'll send out this version later: --- From 4648015b4193c81d3de8c1632876314b4a2ab40d Mon Sep 17 00:00:00 2001 Subject: loop: LOOP_CONFIGURE: send uevents for partitions LOOP_CONFIGURE is, as far as I understand it, supposed to be a way to combine LOOP_SET_FD and LOOP_SET_STATUS64 into a single syscall. When using LOOP_SET_FD+LOOP_SET_STATUS64, a single uevent would be sent for each partition found on the loop device after the second ioctl(), but when using LOOP_CONFIGURE, no such uevent was being sent. In the old setup, uevents are disabled for LOOP_SET_FD, but not for LOOP_SET_STATUS64. This makes sense, as it prevents uevents being sent for a partially configured device during LOOP_SET_FD - they're only sent at the end of LOOP_SET_STATUS64. But for LOOP_CONFIGURE, uevents were disabled for the entire operation, so that final notification was never issued. To fix this, reduce the critical section to exclude the loop_reread_partitions() call, which causes the uevents to be issued, to after uevents are re-enabled, matching the behaviour of the LOOP_SET_FD+LOOP_SET_STATUS64 combination. I noticed this because Busybox's losetup program recently changed from using LOOP_SET_FD+LOOP_SET_STATUS64 to LOOP_CONFIGURE, and this broke my setup, for which I want a notification from the kernel any time a new partition becomes available. Signed-off-by: Alyssa Ross <hi@alyssa.is> [hch: reduced the critical section] Signed-off-by: Christoph Hellwig <hch@lst.de> Fixes: 3448914e8cc5 ("loop: Add LOOP_CONFIGURE ioctl") --- drivers/block/loop.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 839373451c2b7d..9d61c027185141 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1010,9 +1010,6 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, /* This is safe, since we have a reference from open(). */ __module_get(THIS_MODULE); - /* suppress uevents while reconfiguring the device */ - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); - /* * If we don't hold exclusive handle for the device, upgrade to it * here to avoid changing device under exclusive owner. @@ -1067,6 +1064,9 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, } } + /* suppress uevents while reconfiguring the device */ + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); + disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0); @@ -1109,17 +1109,17 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, if (partscan) clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); + /* enable and uncork uevent now that we are done */ + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); + loop_global_unlock(lo, is_loop); if (partscan) loop_reread_partitions(lo); + if (!(mode & FMODE_EXCL)) bd_abort_claiming(bdev, loop_configure); - error = 0; -done: - /* enable and uncork uevent now that we are done */ - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); - return error; + return 0; out_unlock: loop_global_unlock(lo, is_loop); @@ -1130,7 +1130,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, fput(file); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); - goto done; + return error; } static void __loop_clr_fd(struct loop_device *lo, bool release)
On Sun, Mar 19, 2023 at 11:22:25PM -0700, Christoph Hellwig wrote: > On Sat, Mar 18, 2023 at 01:50:05AM +0000, Alyssa Ross wrote: > > What happens next? I'm still getting up to speed on the kernel > > development process — will you submit this as a patch with a patch body > > and a S-o-b? Or am I supposed to do something with it? > > Given that you're done all the hard work, and I've just reduced the > critical section, I'd prefer to give all the credit to you. If you're > fine with it, I'll send out this version later: LGTM, thanks! > --- > From 4648015b4193c81d3de8c1632876314b4a2ab40d Mon Sep 17 00:00:00 2001 > Subject: loop: LOOP_CONFIGURE: send uevents for partitions > > LOOP_CONFIGURE is, as far as I understand it, supposed to be a way to > combine LOOP_SET_FD and LOOP_SET_STATUS64 into a single syscall. When > using LOOP_SET_FD+LOOP_SET_STATUS64, a single uevent would be sent for > each partition found on the loop device after the second ioctl(), but > when using LOOP_CONFIGURE, no such uevent was being sent. > > In the old setup, uevents are disabled for LOOP_SET_FD, but not for > LOOP_SET_STATUS64. This makes sense, as it prevents uevents being > sent for a partially configured device during LOOP_SET_FD - they're > only sent at the end of LOOP_SET_STATUS64. But for LOOP_CONFIGURE, > uevents were disabled for the entire operation, so that final > notification was never issued. To fix this, reduce the critical > section to exclude the loop_reread_partitions() call, which causes > the uevents to be issued, to after uevents are re-enabled, matching > the behaviour of the LOOP_SET_FD+LOOP_SET_STATUS64 combination. > > I noticed this because Busybox's losetup program recently changed from > using LOOP_SET_FD+LOOP_SET_STATUS64 to LOOP_CONFIGURE, and this broke > my setup, for which I want a notification from the kernel any time a > new partition becomes available. > > Signed-off-by: Alyssa Ross <hi@alyssa.is> > [hch: reduced the critical section] > Signed-off-by: Christoph Hellwig <hch@lst.de> > Fixes: 3448914e8cc5 ("loop: Add LOOP_CONFIGURE ioctl") > --- > drivers/block/loop.c | 18 +++++++++--------- > 1 file changed, 9 insertions(+), 9 deletions(-) > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c > index 839373451c2b7d..9d61c027185141 100644 > --- a/drivers/block/loop.c > +++ b/drivers/block/loop.c > @@ -1010,9 +1010,6 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > /* This is safe, since we have a reference from open(). */ > __module_get(THIS_MODULE); > > - /* suppress uevents while reconfiguring the device */ > - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); > - > /* > * If we don't hold exclusive handle for the device, upgrade to it > * here to avoid changing device under exclusive owner. > @@ -1067,6 +1064,9 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > } > } > > + /* suppress uevents while reconfiguring the device */ > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); > + > disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); > set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0); > > @@ -1109,17 +1109,17 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > if (partscan) > clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); > > + /* enable and uncork uevent now that we are done */ > + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); > + > loop_global_unlock(lo, is_loop); > if (partscan) > loop_reread_partitions(lo); > + > if (!(mode & FMODE_EXCL)) > bd_abort_claiming(bdev, loop_configure); > > - error = 0; > -done: > - /* enable and uncork uevent now that we are done */ > - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); > - return error; > + return 0; > > out_unlock: > loop_global_unlock(lo, is_loop); > @@ -1130,7 +1130,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, > fput(file); > /* This is safe: open() is still holding a reference. */ > module_put(THIS_MODULE); > - goto done; > + return error; > } > > static void __loop_clr_fd(struct loop_device *lo, bool release) > -- > 2.39.2 >
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 839373451c2b..f00a0209b522 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -992,7 +992,8 @@ loop_set_status_from_info(struct loop_device *lo, static int loop_configure(struct loop_device *lo, fmode_t mode, struct block_device *bdev, - const struct loop_config *config) + const struct loop_config *config, + bool partscan_uevent) { struct file *file = fget(config->fd); struct inode *inode; @@ -1110,15 +1111,21 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); loop_global_unlock(lo, is_loop); - if (partscan) - loop_reread_partitions(lo); if (!(mode & FMODE_EXCL)) bd_abort_claiming(bdev, loop_configure); + /* + * Now that we are done, reread the partitions with uevent + * re-enabled if appropriate to let userspace know about the + * changes. + */ + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), !partscan_uevent); + if (partscan) + loop_reread_partitions(lo); + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); + error = 0; done: - /* enable and uncork uevent now that we are done */ - dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); return error; out_unlock: @@ -1130,6 +1136,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, fput(file); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); + dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0); goto done; } @@ -1547,7 +1554,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, memset(&config, 0, sizeof(config)); config.fd = arg; - return loop_configure(lo, mode, bdev, &config); + return loop_configure(lo, mode, bdev, &config, false); } case LOOP_CONFIGURE: { struct loop_config config; @@ -1555,7 +1562,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, if (copy_from_user(&config, argp, sizeof(config))) return -EFAULT; - return loop_configure(lo, mode, bdev, &config); + return loop_configure(lo, mode, bdev, &config, true); } case LOOP_CHANGE_FD: return loop_change_fd(lo, bdev, arg);