From: Luca Boccassi Date: Tue, 20 Jul 2021 14:25:06 +0000 (+0100) Subject: loop: parse and store disk sequence number X-Git-Tag: v250-rc1~754^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bcef1743a5e9e972df6c38e0b263bbd9de7fac44;p=thirdparty%2Fsystemd.git loop: parse and store disk sequence number When loop devices are re-used, the disk sequence number is increased. Parse it when creating a loop device and store it. The kernel will never return DISKSEQ=0, so use it to signal that it's not supported by the current kernel. --- diff --git a/src/basic/missing_loop.h b/src/basic/missing_loop.h index b22ebda9fda..99e90543ffa 100644 --- a/src/basic/missing_loop.h +++ b/src/basic/missing_loop.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include #include #ifndef LOOP_CONFIGURE @@ -13,3 +14,7 @@ struct loop_config { #define LOOP_CONFIGURE 0x4C0A #endif + +#ifndef BLKGETDISKSEQ +#define BLKGETDISKSEQ _IOR(0x12,128,__u64) +#endif diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index c038e7aae6c..933756cf80b 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -127,6 +127,27 @@ static int device_has_block_children(sd_device *d) { return 0; } +static int loop_get_diskseq(int fd, uint64_t *ret_diskseq) { + uint64_t diskseq; + + assert(fd >= 0); + assert(ret_diskseq); + + if (ioctl(fd, BLKGETDISKSEQ, &diskseq) < 0) { + /* Note that the kernel is weird: non-existing ioctls currently return EINVAL + * rather than ENOTTY on loopback block devices. They should fix that in the kernel, + * but in the meantime we accept both here. */ + if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EINVAL) + return -errno; + + return -EOPNOTSUPP; + } + + *ret_diskseq = diskseq; + + return 0; +} + static int loop_configure( int fd, int nr, @@ -388,6 +409,7 @@ int loop_device_make( if (offset == 0 && IN_SET(size, 0, UINT64_MAX)) { _cleanup_close_ int copy = -1; + uint64_t diskseq = 0; /* If this is already a block device, store a copy of the fd as it is */ @@ -395,6 +417,10 @@ int loop_device_make( if (copy < 0) return -errno; + r = loop_get_diskseq(copy, &diskseq); + if (r < 0 && r != -EOPNOTSUPP) + return r; + d = new(LoopDevice, 1); if (!d) return -ENOMEM; @@ -404,6 +430,7 @@ int loop_device_make( .node = TAKE_PTR(loopdev), .relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */ .devno = st.st_rdev, + .diskseq = diskseq, .uevent_seqnum_not_before = UINT64_MAX, .timestamp_not_before = USEC_INFINITY, }; @@ -482,6 +509,11 @@ int loop_device_make( return -errno; assert(S_ISBLK(st.st_mode)); + uint64_t diskseq = 0; + r = loop_get_diskseq(loop_with_fd, &diskseq); + if (r < 0 && r != -EOPNOTSUPP) + return r; + d = new(LoopDevice, 1); if (!d) return -ENOMEM; @@ -490,6 +522,7 @@ int loop_device_make( .node = TAKE_PTR(loopdev), .nr = nr, .devno = st.st_rdev, + .diskseq = diskseq, .uevent_seqnum_not_before = seqnum, .timestamp_not_before = timestamp, }; diff --git a/src/shared/loop-util.h b/src/shared/loop-util.h index e06dfebb7c6..964ce3ed083 100644 --- a/src/shared/loop-util.h +++ b/src/shared/loop-util.h @@ -14,6 +14,7 @@ struct LoopDevice { dev_t devno; char *node; bool relinquished; + uint64_t diskseq; /* Block device sequence number, monothonically incremented by the kernel on create/attach, or 0 if we don't know */ uint64_t uevent_seqnum_not_before; /* uevent sequm right before we attached the loopback device, or UINT64_MAX if we don't know */ usec_t timestamp_not_before; /* CLOCK_MONOTONIC timestamp taken immediately before attaching the loopback device, or USEC_INFINITY if we don't know */ };