From 7c3b51c469140cdbc1b7e9a232af3f250fea3884 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sun, 26 Dec 2021 16:45:13 +0000 Subject: [PATCH] chrattr-util: return EOPNOTSUPP from chrattr_full if no other failure was observed When chattr_full tries to apply flags one-by-one, and one fails, record which errno was returned. But record EOPNOTSUPP(&friends) only if no other error is observed, and return it only in that case (otherwise keep returning ENOANO), so that callers can respond appropriately to EOPNOTSUPP vs more relevant errors. For example, this lets tmpfiles.d log at debug level when a filesystem flag cannot be applied because the filesystem does not support it, but at warning level if something else went wrong when applying it. Restores logging behaviour of tmpfiles.d to pre-250. Follow-up for: https://github.com/systemd/systemd/commit/c1631ee124a30abfb9c71e2a1534b8afffc3b6a7 Fixes: https://github.com/systemd/systemd/issues/21901 --- src/basic/chattr-util.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c index 807288a6498..eddde132aae 100644 --- a/src/basic/chattr-util.c +++ b/src/basic/chattr-util.c @@ -22,6 +22,7 @@ int chattr_full(const char *path, _cleanup_close_ int fd_will_close = -1; unsigned old_attr, new_attr; + int set_flags_errno = 0; struct stat st; assert(path || fd >= 0); @@ -109,6 +110,12 @@ int chattr_full(const char *path, log_full_errno(FLAGS_SET(flags, CHATTR_WARN_UNSUPPORTED_FLAGS) ? LOG_WARNING : LOG_DEBUG, errno, "Unable to set file attribute 0x%x on %s, ignoring: %m", mask_one, strna(path)); + + /* Ensures that we record whether only EOPNOTSUPP&friends are encountered, or if a more serious + * error (thus worth logging at a different level, etc) was seen too. */ + if (set_flags_errno == 0 || !ERRNO_IS_NOT_SUPPORTED(errno)) + set_flags_errno = -errno; + continue; } @@ -121,7 +128,10 @@ int chattr_full(const char *path, if (ret_final) *ret_final = current_attr; - return current_attr == new_attr ? 1 : -ENOANO; /* -ENOANO indicates that some attributes cannot be set. */ + /* -ENOANO indicates that some attributes cannot be set. ERRNO_IS_NOT_SUPPORTED indicates that all + * encountered failures were due to flags not supported by the FS, so return a specific error in + * that case, so callers can handle it properly (e.g.: tmpfiles.d can use debug level logging). */ + return current_attr == new_attr ? 1 : ERRNO_IS_NOT_SUPPORTED(set_flags_errno) ? set_flags_errno : -ENOANO; } int read_attr_fd(int fd, unsigned *ret) {