@@ -424,27 +424,46 @@ int blockdev_partscan_enabled(int fd) {
424424 * e81cd5a983bb35dabd38ee472cf3fea1c63e0f23, the flag was never used. So, fortunately, we can use
425425 * both the new and old values safely.
426426 *
427+ * With https://github.com/torvalds/linux/commit/b9684a71fca793213378dd410cd11675d973eaa1 (v5.19),
428+ * another flag GD_SUPPRESS_PART_SCAN is introduced for loopback block device, and partition scanning
429+ * is done only when both GENHD_FL_NO_PART and GD_SUPPRESS_PART_SCAN are not set. Before the commit,
430+ * LO_FLAGS_PARTSCAN flag was directly tied with GENHD_FL_NO_PART. But with this change now it is
431+ * tied with GD_SUPPRESS_PART_SCAN. So, LO_FLAGS_PARTSCAN cannot be obtained from 'ext_range'
432+ * sysattr, which corresponds to GENHD_FL_NO_PART, and we need to read 'loop/partscan'. 💣💣💣
433+ *
434+ * With https://github.com/torvalds/linux/commit/73a166d9749230d598320fdae3b687cdc0e2e205 (v6.3),
435+ * the GD_SUPPRESS_PART_SCAN flag is also introduced for userspace block device (ublk). Though, not
436+ * sure if we should support the device...
437+ *
427438 * With https://github.com/torvalds/linux/commit/e81cd5a983bb35dabd38ee472cf3fea1c63e0f23 (v6.3),
428- * the 'capability' sysfs attribute is deprecated, hence we cannot check the flag from it.
439+ * the 'capability' sysfs attribute is deprecated, hence we cannot check flags from it. 💣💣💣
429440 *
430- * With https://github.com/torvalds/linux/commit/a4217c6740dc64a3eb6815868a9260825e8c68c6
431- * ( backported to v6.9), the partscan status is directly exposed as 'partscan' sysattr.
441+ * With https://github.com/torvalds/linux/commit/a4217c6740dc64a3eb6815868a9260825e8c68c6 (v6.10,
442+ * backported to v6.9), the partscan status is directly exposed as 'partscan' sysattr.
432443 *
433- * To support both old and new kernels, we need to do the following: first check 'partscan' attr
434- * where the information is made directly available; then, fall back to 'ext_range' sysfs attribute,
435- * and if '1' we can conclude partition scanning is disabled; otherwise check 'capability' sysattr
436- * for ancient version. */
444+ * To support both old and new kernels, we need to do the following:
445+ * 1) check 'partscan' sysfs attribute where the information is made directly available,
446+ * 2) check 'loop/partscan' sysfs attribute for loopback block devices, and if '0' we can conclude
447+ * partition scanning is disabled,
448+ * 3) check 'ext_range' sysfs attribute, and if '1' we can conclude partition scanning is disabled,
449+ * 4) otherwise check 'capability' sysfs attribute for ancient version. */
437450
438451 assert (fd >= 0 );
439452
440453 r = block_device_new_from_fd (fd , 0 , & dev );
441454 if (r < 0 )
442455 return r ;
443456
457+ /* For v6.10 or newer. */
444458 r = device_get_sysattr_bool (dev , "partscan" );
445459 if (r != - ENOENT )
446460 return r ;
447461
462+ /* For loopback block device, especially for v5.19 or newer. Even if this is enabled, we also need to
463+ * check GENHD_FL_NO_PART flag through 'ext_range' and 'capability' sysfs attributes below. */
464+ if (device_get_sysattr_bool (dev , "loop/partscan" ) == 0 )
465+ return false;
466+
448467 r = device_get_sysattr_int (dev , "ext_range" , & ext_range );
449468 if (r == - ENOENT ) /* If the ext_range file doesn't exist then we are most likely looking at a
450469 * partition block device, not the whole block device. And that means we have no
0 commit comments