[PATCH v3 6/6] loop: increment sequence number

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Matteo Croce <mcroce@xxxxxxxxxxxxx>

On a very loaded system, if there are many events queued up from multiple
attach/detach cycles, it's impossible to match them up with the
LOOP_CONFIGURE or LOOP_SET_FD call, since we don't know where the position
of our own association in the queue is[1].
Not even an empty uevent queue is a reliable indication that we already
received the uevent we were waiting for, since with multi-partition block
devices each partition's event is queued asynchronously and might be
delivered later.

Increment the disk sequence number when setting or changing the backing
file, so the userspace knows which backing file generated the event:

    # udevadm monitor -kp |grep -e ^DEVNAME -e ^DISKSEQ &
    [1] 263
    # losetup -fP 3part
    [   12.309974] loop0: detected capacity change from 0 to 2048
    DEVNAME=/dev/loop0
    DISKSEQ=8
    [   12.360252]  loop0: p1 p2 p3
    DEVNAME=/dev/loop0
    DISKSEQ=8
    DEVNAME=/dev/loop0p1
    DISKSEQ=8
    DEVNAME=/dev/loop0p2
    DISKSEQ=8
    DEVNAME=/dev/loop0p3
    DISKSEQ=8
    # losetup -D
    DEVNAME=/dev/loop0
    DISKSEQ=9
    DEVNAME=/dev/loop0p1
    DISKSEQ=9
    DEVNAME=/dev/loop0p2
    DISKSEQ=9
    DEVNAME=/dev/loop0p3
    DISKSEQ=9
    # losetup -fP 2part
    [   29.001344] loop0: detected capacity change from 0 to 2048
    DEVNAME=/dev/loop0
    DISKSEQ=10
    [   29.040226]  loop0: p1 p2
    DEVNAME=/dev/loop0
    DISKSEQ=10
    DEVNAME=/dev/loop0p1
    DISKSEQ=10
    DEVNAME=/dev/loop0p2
    DISKSEQ=10

[1] https://github.com/systemd/systemd/issues/17469#issuecomment-762919781

Signed-off-by: Matteo Croce <mcroce@xxxxxxxxxxxxx>
---
 drivers/block/loop.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 76e12f3482a9..b1c638d23306 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -735,6 +735,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
 		goto out_err;
 
 	/* and ... switch */
+	inc_diskseq(lo->lo_disk);
 	blk_mq_freeze_queue(lo->lo_queue);
 	mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
 	lo->lo_backing_file = file;
@@ -1123,6 +1124,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
 	if (error)
 		goto out_unlock;
 
+	inc_diskseq(lo->lo_disk);
+
 	if (!(file->f_mode & FMODE_WRITE) || !(mode & FMODE_WRITE) ||
 	    !file->f_op->write_iter)
 		lo->lo_flags |= LO_FLAGS_READ_ONLY;
@@ -1223,6 +1226,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
 	lo->lo_backing_file = NULL;
 	spin_unlock_irq(&lo->lo_lock);
 
+	inc_diskseq(lo->lo_disk);
+
 	loop_release_xfer(lo);
 	lo->transfer = NULL;
 	lo->ioctl = NULL;
-- 
2.31.1




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux