]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/io-util: invert return value from IOVEC_INCREMENT()
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 26 Apr 2021 21:30:26 +0000 (23:30 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 4 May 2021 12:57:49 +0000 (14:57 +0200)
We would try to return a value that could be nonzero only if the kernel
reported writing more bytes than we gave to it, hopefully a rare occurence.
Instead, assert that this doesn't happen.

Instead, return true if we got to the end of the iovec array. The caller
can use this information to know that the whole iovec array was written.
This allows one loop to be dropped in write_to_syslog().

Also drop _unlikely_: this function is called with very short arrays, and
it *is* likely that we trigger this condition. Let's just let the compiler
generate normal code without giving it a potentially false hint.

src/basic/io-util.h
src/basic/log.c

index d98817f760955104a6b655a27d79de05d31b9051..d4bb14fba43704d3b9326c4f3264128df95246b9 100644 (file)
@@ -33,14 +33,17 @@ static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, size_t n) {
         return r;
 }
 
-static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
-        size_t j;
+static inline bool IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
+        /* Returns true if there is nothing else to send (bytes written cover all of the iovec),
+         * false if there's still work to do. */
 
-        for (j = 0; j < n; j++) {
+        for (size_t j = 0; j < n; j++) {
                 size_t sub;
 
-                if (_unlikely_(k <= 0))
-                        break;
+                if (i[j].iov_len == 0)
+                        continue;
+                if (k == 0)
+                        return false;
 
                 sub = MIN(i[j].iov_len, k);
                 i[j].iov_len -= sub;
@@ -48,7 +51,9 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) {
                 k -= sub;
         }
 
-        return k;
+        assert(k == 0); /* Anything else would mean that we wrote more bytes than available,
+                         * or the kernel reported writing more bytes than sent. */
+        return true;
 }
 
 static inline bool FILE_SIZE_VALID(uint64_t l) {
index 595db0c395ac44ebc51bbdf4144741a7097df713..c098939ed1c6135f9afdc0771c3c9e91e84068c6 100644 (file)
@@ -491,11 +491,11 @@ static int write_to_syslog(
                 if (n < 0)
                         return -errno;
 
-                if (!syslog_is_stream ||
-                    (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
+                if (!syslog_is_stream)
                         break;
 
-                IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
+                if (IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n))
+                        break;
         }
 
         return 1;