Import stdio handling code to logger_aio_write() 33/268733/4
authorŁukasz Stelmach <l.stelmach@samsung.com>
Wed, 15 Dec 2021 23:32:13 +0000 (00:32 +0100)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Tue, 4 Jan 2022 21:14:36 +0000 (22:14 +0100)
Copy the stdio handling code from logger_write_iter()

Change-Id: I94be88c5db2e7482106ddd537d763726a89aad5a
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
kernel/logger.c

index b5a8d2bd99a333c9b948136046dd26cef243fbe6..9dbe22ada13f89a997ff84e07e0899434f1ef0b6 100644 (file)
@@ -623,6 +623,7 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
        struct logger_entry header;
        struct timespec now;
        ssize_t ret = 0;
+       size_t count;
        bool from_stdio = false;
 
        if (writer->tag && writer->prio >= 2)
@@ -646,7 +647,93 @@ static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
 
        /* Prepend messages from STDOUT and STDERR with a tag and prio */
        if (from_stdio) {
-               return 0;
+               char *p;
+               size_t chunk_len = 0, c = 0;
+               /* -2 : priority byte and tag terminating '\0' */
+               size_t max_payload = LOGGER_ENTRY_MAX_PAYLOAD - writer->tag_len - 2;
+
+               if (writer->owner != current->group_leader) {
+                       struct file *nfile;
+
+                       nfile = make_new_file(file);
+                       if (IS_ERR(nfile)) {
+                               mutex_unlock(&log->mutex);
+                               return PTR_ERR(nfile);
+                       }
+
+                       file = nfile;
+                       writer = file->private_data;
+               }
+
+               /* Allocate STDIO line buffer */
+               if (!writer->buffer) {
+                       writer->buffer = kzalloc(LOGGER_ENTRY_MAX_PAYLOAD, GFP_KERNEL);
+                       writer->b_off = 0;
+
+                       if (!writer->buffer) {
+                               mutex_unlock(&log->mutex);
+                               return -ENOMEM;
+                       }
+               }
+
+               /* flush message from a different thread */
+               if (writer->b_owner != current && writer->b_off)
+                       flush_thread_data(file);
+
+               count = 0;
+               /* -1 : leave space for message terminating '\0' */
+               c = min_t(size_t, iov_iter_count(from),
+                         max_payload - writer->b_off - 1);
+
+               do {
+                       size_t i;
+
+                       if (copy_from_iter(writer->buffer + writer->b_off, c, from) != c) {
+                               mutex_unlock(&log->mutex);
+                               return -EFAULT;
+                       }
+                       count += c;
+                       p = NULL;
+                       for (i = 0; i < c; ++i) {
+                               char *t = &writer->buffer[writer->b_off + i];
+                               if (*t == '\0')
+                                       *t = '\n';
+                               if (*t == '\n')
+                                       p = t;
+                       }
+                       if (p) {
+                               *p++ = '\0';
+                               chunk_len = p - writer->buffer;
+                       } else {
+                               writer->buffer[writer->b_off + c++] = '\0';
+                               p = &writer->buffer[writer->b_off + c];
+                               chunk_len = p - writer->buffer;
+
+                               BUG_ON(chunk_len > max_payload);
+                               if (chunk_len < max_payload ) {
+                                       writer->b_off = writer->b_off + c - 1;
+                                       continue;
+                               }
+
+                       }
+
+                       header.len = chunk_len + writer->tag_len + 2;
+                       fix_up_readers(log, sizeof(struct logger_entry) + header.len);
+
+                       write_log_data(log, &header, writer, chunk_len);
+
+                       /* move the remaining part of the message */
+                       memmove(writer->buffer, p, writer->b_off + c - chunk_len);
+
+                       /* new b_off points where the rimainder of the string ends */
+                       writer->b_off = writer->b_off + c - chunk_len;
+                       writer->buffer[writer->b_off] = '\0';
+
+               } while ((c = min_t(size_t, iov_iter_count(from), max_payload - 1)));
+
+               /* save for remaining unfinished line */
+               writer->b_header = header;
+               writer->b_owner = current;
        } else {
                orig = log->w_off;