diff options
Diffstat (limited to '')
-rw-r--r-- | src/shared/blockdev-util.c | 60 | ||||
-rw-r--r-- | src/shared/conf-parser.c | 6 | ||||
-rw-r--r-- | src/shared/discover-image.c | 62 | ||||
-rw-r--r-- | src/shared/journal-importer.c | 14 | ||||
-rw-r--r-- | src/shared/libcrypt-util.c | 2 | ||||
-rw-r--r-- | src/shared/ptyfwd.c | 3 |
6 files changed, 117 insertions, 30 deletions
diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index 99e37fd..3be617b 100644 --- a/src/shared/blockdev-util.c +++ b/src/shared/blockdev-util.c @@ -410,15 +410,43 @@ int blockdev_partscan_enabled(int fd) { * is 1, which can be check with 'ext_range' sysfs attribute. Explicit flag ('GENHD_FL_NO_PART_SCAN') * can be obtained from 'capability' sysattr. * - * With https://github.com/torvalds/linux/commit/1ebe2e5f9d68e94c524aba876f27b945669a7879 (v5.17), we - * can check the flag from 'ext_range' sysfs attribute directly. + * With https://github.com/torvalds/linux/commit/46e7eac647b34ed4106a8262f8bedbb90801fadd (v5.17), + * the flag is renamed to GENHD_FL_NO_PART. + * + * With https://github.com/torvalds/linux/commit/1ebe2e5f9d68e94c524aba876f27b945669a7879 (v5.17), + * we can check the flag from 'ext_range' sysfs attribute directly. + * + * With https://github.com/torvalds/linux/commit/430cc5d3ab4d0ba0bd011cfbb0035e46ba92920c (v5.17), + * the value of GENHD_FL_NO_PART is changed from 0x0200 to 0x0004. 💣💣💣 + * Note, the new value was used by the GENHD_FL_MEDIA_CHANGE_NOTIFY flag, which was introduced by + * 86ce18d7b7925bfd6b64c061828ca2a857ee83b8 (v2.6.22), and removed by + * 9243c6f3e012a92dd900d97ef45efaf8a8edc448 (v5.7). If we believe the commit message of + * e81cd5a983bb35dabd38ee472cf3fea1c63e0f23, the flag was never used. So, fortunately, we can use + * both the new and old values safely. + * + * With https://github.com/torvalds/linux/commit/b9684a71fca793213378dd410cd11675d973eaa1 (v5.19), + * another flag GD_SUPPRESS_PART_SCAN is introduced for loopback block device, and partition scanning + * is done only when both GENHD_FL_NO_PART and GD_SUPPRESS_PART_SCAN are not set. Before the commit, + * LO_FLAGS_PARTSCAN flag was directly tied with GENHD_FL_NO_PART. But with this change now it is + * tied with GD_SUPPRESS_PART_SCAN. So, LO_FLAGS_PARTSCAN cannot be obtained from 'ext_range' + * sysattr, which corresponds to GENHD_FL_NO_PART, and we need to read 'loop/partscan'. 💣💣💣 + * + * With https://github.com/torvalds/linux/commit/73a166d9749230d598320fdae3b687cdc0e2e205 (v6.3), + * the GD_SUPPRESS_PART_SCAN flag is also introduced for userspace block device (ublk). Though, not + * sure if we should support the device... * * With https://github.com/torvalds/linux/commit/e81cd5a983bb35dabd38ee472cf3fea1c63e0f23 (v6.3), - * the 'capability' sysfs attribute is deprecated, hence we cannot check the flag from it. + * the 'capability' sysfs attribute is deprecated, hence we cannot check flags from it. 💣💣💣 + * + * With https://github.com/torvalds/linux/commit/a4217c6740dc64a3eb6815868a9260825e8c68c6 (v6.10, + * backported to v6.9), the partscan status is directly exposed as 'partscan' sysattr. * - * To support both old and new kernels, we need to do the following: first check 'ext_range' sysfs - * attribute, and if '1' we can conclude partition scanning is disabled, otherwise check 'capability' - * sysattr for older version. */ + * To support both old and new kernels, we need to do the following: + * 1) check 'partscan' sysfs attribute where the information is made directly available, + * 2) check 'loop/partscan' sysfs attribute for loopback block devices, and if '0' we can conclude + * partition scanning is disabled, + * 3) check 'ext_range' sysfs attribute, and if '1' we can conclude partition scanning is disabled, + * 4) otherwise check 'capability' sysfs attribute for ancient version. */ assert(fd >= 0); @@ -426,6 +454,16 @@ int blockdev_partscan_enabled(int fd) { if (r < 0) return r; + /* For v6.10 or newer. */ + r = device_get_sysattr_bool(dev, "partscan"); + if (r != -ENOENT) + return r; + + /* For loopback block device, especially for v5.19 or newer. Even if this is enabled, we also need to + * check GENHD_FL_NO_PART flag through 'ext_range' and 'capability' sysfs attributes below. */ + if (device_get_sysattr_bool(dev, "loop/partscan") == 0) + return false; + r = device_get_sysattr_int(dev, "ext_range", &ext_range); if (r == -ENOENT) /* If the ext_range file doesn't exist then we are most likely looking at a * partition block device, not the whole block device. And that means we have no @@ -445,12 +483,10 @@ int blockdev_partscan_enabled(int fd) { if (r < 0) return r; -#ifndef GENHD_FL_NO_PART_SCAN -#define GENHD_FL_NO_PART_SCAN (0x0200) -#endif - - /* If 0x200 is set, part scanning is definitely off. */ - if (FLAGS_SET(capability, GENHD_FL_NO_PART_SCAN)) +#define GENHD_FL_NO_PART_OLD 0x0200 +#define GENHD_FL_NO_PART_NEW 0x0004 + /* If one of the NO_PART flags is set, part scanning is definitely off. */ + if ((capability & (GENHD_FL_NO_PART_OLD | GENHD_FL_NO_PART_NEW)) != 0) return false; /* Otherwise, assume part scanning is on, we have no further checks available. Assume the best. */ diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 327dc38..55301af 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -155,7 +155,11 @@ static int next_assignment( /* Warn about unknown non-extension fields. */ if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-")) log_syntax(unit, LOG_WARNING, filename, line, 0, - "Unknown key name '%s' in section '%s', ignoring.", lvalue, section); + "Unknown key '%s'%s%s%s, ignoring.", + lvalue, + section ? " in section [" : "", + strempty(section), + section ? "]" : ""); return 0; } diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c index 0350dd1..11729d0 100644 --- a/src/shared/discover-image.c +++ b/src/shared/discover-image.c @@ -202,6 +202,44 @@ static int extract_pretty(const char *path, const char *suffix, char **ret) { return 0; } +static int image_update_quota(Image *i, int fd) { + _cleanup_close_ int fd_close = -EBADF; + int r; + + assert(i); + + if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i)) + return -EROFS; + + if (i->type != IMAGE_SUBVOLUME) + return -EOPNOTSUPP; + + if (fd < 0) { + fd_close = open(i->path, O_CLOEXEC|O_NOCTTY|O_DIRECTORY); + if (fd_close < 0) + return -errno; + fd = fd_close; + } + + r = btrfs_quota_scan_ongoing(fd); + if (r < 0) + return r; + if (r > 0) + return 0; + + BtrfsQuotaInfo quota; + r = btrfs_subvol_get_subtree_quota_fd(fd, 0, "a); + if (r < 0) + return r; + + i->usage = quota.referenced; + i->usage_exclusive = quota.exclusive; + i->limit = quota.referenced_max; + i->limit_exclusive = quota.exclusive_max; + + return 1; +} + static int image_make( const char *pretty, int dfd, @@ -288,19 +326,7 @@ static int image_make( if (r < 0) return r; - if (btrfs_quota_scan_ongoing(fd) == 0) { - BtrfsQuotaInfo quota; - - r = btrfs_subvol_get_subtree_quota_fd(fd, 0, "a); - if (r >= 0) { - (*ret)->usage = quota.referenced; - (*ret)->usage_exclusive = quota.exclusive; - - (*ret)->limit = quota.referenced_max; - (*ret)->limit_exclusive = quota.exclusive_max; - } - } - + (void) image_update_quota(*ret, fd); return 0; } } @@ -1002,6 +1028,7 @@ int image_read_only(Image *i, bool b) { return -EOPNOTSUPP; } + i->read_only = b; return 0; } @@ -1100,6 +1127,8 @@ int image_path_lock(const char *path, int operation, LockFile *global, LockFile } int image_set_limit(Image *i, uint64_t referenced_max) { + int r; + assert(i); if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i)) @@ -1115,7 +1144,12 @@ int image_set_limit(Image *i, uint64_t referenced_max) { (void) btrfs_qgroup_set_limit(i->path, 0, referenced_max); (void) btrfs_subvol_auto_qgroup(i->path, 0, true); - return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max); + r = btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max); + if (r < 0) + return r; + + (void) image_update_quota(i, -EBADF); + return 0; } int image_read_metadata(Image *i) { diff --git a/src/shared/journal-importer.c b/src/shared/journal-importer.c index d9eabec..1914e74 100644 --- a/src/shared/journal-importer.c +++ b/src/shared/journal-importer.c @@ -92,7 +92,12 @@ static int get_line(JournalImporter *imp, char **line, size_t *size) { imp->buf + imp->filled, MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled); if (n < 0) { - if (errno != EAGAIN) + if (ERRNO_IS_DISCONNECT(errno)) { + log_debug_errno(errno, "Got disconnect for importer %s.", strna(imp->name)); + return 0; + } + + if (!ERRNO_IS_TRANSIENT(errno)) log_error_errno(errno, "read(%d, ..., %zu): %m", imp->fd, MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled); @@ -133,7 +138,12 @@ static int fill_fixed_size(JournalImporter *imp, void **data, size_t size) { n = read(imp->fd, imp->buf + imp->filled, MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled); if (n < 0) { - if (errno != EAGAIN) + if (ERRNO_IS_DISCONNECT(errno)) { + log_debug_errno(errno, "Got disconnect for importer %s.", strna(imp->name)); + return 0; + } + + if (!ERRNO_IS_TRANSIENT(errno)) log_error_errno(errno, "read(%d, ..., %zu): %m", imp->fd, MALLOC_SIZEOF_SAFE(imp->buf) - imp->filled); return -errno; diff --git a/src/shared/libcrypt-util.c b/src/shared/libcrypt-util.c index 81e6f17..5ccf75a 100644 --- a/src/shared/libcrypt-util.c +++ b/src/shared/libcrypt-util.c @@ -114,7 +114,7 @@ static char* systemd_crypt_ra(const char *phrase, const char *setting, void **da if (!*data) { *data = new0(struct crypt_data, 1); if (!*data) { - errno = -ENOMEM; + errno = ENOMEM; return NULL; } diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 6ffe86e..21cfe1d 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -406,6 +406,9 @@ int pty_forward_new( struct winsize ws; int r; + assert(master >= 0); + assert(ret); + f = new(PTYForward, 1); if (!f) return -ENOMEM; |