Received: by 2002:ac8:5491:0:b0:40f:fb00:664b with SMTP id h17csp619871qtq; Thu, 10 Aug 2023 10:44:08 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHBK3VlK6FZedNL83xi5JfEnlSQdhURUTlLxaRgLe8zvdkdY7EhSgZuJ0KOuH4X5c8gUDx5 X-Received: by 2002:a2e:840b:0:b0:2b9:4093:a873 with SMTP id z11-20020a2e840b000000b002b94093a873mr2195226ljg.5.1691689447986; Thu, 10 Aug 2023 10:44:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1691689447; cv=none; d=google.com; s=arc-20160816; b=F8HyJvVpd1aLNqePBeOK8rmGJEx7SlKFsTSQGg2A/Pp5PF3SpZyr2KMu6rGWglWpjT CT1xLLtqaxkMaJ2DQ3higNhaaJxi/uYWukaPzdvzm8JnwDwVzIfRJbE1Dn01tm6f/W3E Vky0Hxq6eswlu6PS+HgQPSjoHu28+F9Ew+HONVOTMZxduUrflMtmtY1Rhs4N8Ur5z17Z Tf2uQdLL4IGKrO1QrrqdXoa7FeNlz/eCkd4bU/t49TJ6XXs1a9iiBU53OZI7I+K8OqWF FqDkD5kEtm+MtAc5IomwB6z57izzTJVLoZJxbx5G2+eUSvJebj6rMrxJNBxa4Mzi/+1F sCdg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=/rSFSko1Ell2IsXnK0mfdf1tdTOfrdOtQZjuqb27Lh0=; fh=9FarDAFJaA4MeBPK3Ku0jD1OKUJL2GU7mJ8+LFkdrew=; b=e9wkkVD3H/fIK1nXi/YCwQcX0aXDu5viDSbzR60hOgvbhW+FLO++ik++pe1AemT0Tt ScDSSHNoecxLxTG5LIaxIyc0Vjvzufu5YHNWc5IJ2Dlp5/1XvXIi6Z1lIpoPgvipUTuK KMUraBFCP/5xpwrmM+szfdMTewrsOKTI0uTxFAGo3Q5cbOsuI+wl0L5aKl3YY+kKhl65 RDCXvXrcrbmDoWmhncgz/AFfzjTItSkaR4pjtoaqiXT8yzvNLW4i7YK8AfPjTp+k91Lf 0SR2Ox93IewCjJZMSZ6IxLkhdj2ToeFcpmnt5kEbmzr8n5caEPxW6mtLEhZgEZa0aFZd nbSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b="wM+sRrw/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z13-20020a170906714d00b0098e42bef73asi1968909ejj.98.2023.08.10.10.43.42; Thu, 10 Aug 2023 10:44:07 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b="wM+sRrw/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233464AbjHJOiU (ORCPT + 99 others); Thu, 10 Aug 2023 10:38:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44508 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235809AbjHJOiS (ORCPT ); Thu, 10 Aug 2023 10:38:18 -0400 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FA7326B5 for ; Thu, 10 Aug 2023 07:38:17 -0700 (PDT) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-3fe2d620d17so79435e9.0 for ; Thu, 10 Aug 2023 07:38:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1691678296; x=1692283096; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=/rSFSko1Ell2IsXnK0mfdf1tdTOfrdOtQZjuqb27Lh0=; b=wM+sRrw/HBGsyGvgkWXw59Ae3RTYS06bqzvnDTJ3/nQyK8WilBlKlisPIBC9HhwViS NFLonCbjpAMTtAgTxE3qYxo/k0XWceirR39a71qLsUz2PqhKMWZjfmFmoKMy4nkKwZjT TCGkfmPTeb6jQbKvku0AkY3XR/D/FqmC3PQadw3fyMqhTb1JDDFPORAt97HNn6r6URyv 15fspW22goip0OqNaUya+xHeIjHdt3NXwHu+CePGCYEFQxVO4+WRZfWy4rEw7TIO/wt/ blYlbP6L0gvel84dG6He55llEFGlS87whlcVXAUybgNjQKH1qAZ835uoLtXZMqxbGvZh 9r2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691678296; x=1692283096; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=/rSFSko1Ell2IsXnK0mfdf1tdTOfrdOtQZjuqb27Lh0=; b=hDtIyhh0YXDrtd2ClKQDO/X1+fMU541dC4DLKleXr1JyEEktfDJT6FN5USBsvRhX/Y 0pocKvNlnpi73+KV1kXiL0jLepn49n/My92/uSShstVrccOHF+SIS4SO0ffvycslEAul hIONFc+/zja3wWUu8epsoKEZ/Zu8j5qNwTDeQsrlyzyc0y8yHla9oK1MkJzxh7TWbvmW rvpBBqhG4XaReIlB+v47hVADzKFFldXxpEkeAeeXXZhUBZ62GNbIIIUuGFwpkM2HtGKW C7hDJD5Z3hA0uUsD5xFyhqbNC/hT5cjtSbytjzk9XQCpvixpL/vkiDJ3rMqxx6mre0v8 kAJw== X-Gm-Message-State: AOJu0YwDmEdJKuW3dEayJmWBO0bosntzsPW+AUgIixWbcmtC9ME1H+9h 839qZ1HcMuZ5dPl+TAJgwcsLWX4/JJPQryzT3viiQg== X-Received: by 2002:a05:600c:3b8f:b0:3f1:70d1:21a6 with SMTP id n15-20020a05600c3b8f00b003f170d121a6mr237435wms.0.1691678295931; Thu, 10 Aug 2023 07:38:15 -0700 (PDT) MIME-Version: 1.0 References: <20230809155438.22470-1-rf@opensource.cirrus.com> <20230809155438.22470-4-rf@opensource.cirrus.com> In-Reply-To: <20230809155438.22470-4-rf@opensource.cirrus.com> From: David Gow Date: Thu, 10 Aug 2023 22:38:02 +0800 Message-ID: Subject: Re: [PATCH v3 3/7] kunit: Handle logging of lines longer than the fragment buffer size To: Richard Fitzgerald Cc: brendan.higgins@linux.dev, rmoar@google.com, linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com, linux-kernel@vger.kernel.org, patches@opensource.cirrus.com Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-17.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF, ENV_AND_HDR_SPF_MATCH,RCVD_IN_DNSWL_BLOCKED,SPF_HELO_NONE,SPF_PASS, USER_IN_DEF_DKIM_WL,USER_IN_DEF_SPF_WL autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, 9 Aug 2023 at 23:54, Richard Fitzgerald wrote: > > Add handling to kunit_log_append() for log messages that are longer than > a single buffer fragment. > > The initial implementation of fragmented buffers did not change the logic > of the original kunit_log_append(). A consequence was that it still had > the original assumption that a log line will fit into one buffer. > > This patch checks for log messages that are larger than one fragment > buffer. In that case, kvasprintf() is used to format it into a temporary > buffer and that content is then split across as many fragments as > necessary. > > Signed-off-by: Richard Fitzgerald > --- I think this looks good (and is a long-overdue addition to the logging functionality). One thought I have (and I'm kicking myself for not thinking of it earlier) is that this is starting to get very similar to the "string stream" functionality in lib/kunit/string-stream.{h,c}. Now, I actually think this implementation is much more efficient (using larger fragments, whereas the string stream uses variable-sized ones). Particularly since there are a lot of cases where string streams are created, converted to a string, and then logged, there's almost certainly a bunch of redundant work being done here. My gut feeling is that we should stick with this as-is, and maybe try to either work out some better integration between string streams and logging (to avoid that extra string allocation) or find some way of combining them. Regardless, this seems good as-is to me. There are some minor comments below, but nothing disastrous. I'll let Rae have a look over the various strscpy and strlcat calls, though, as while I did check them carefully (and KASAN hasn't complained), it's always best to have as many eyes on C string code as possible. :-) But in my eyes, this is Reviewed-by: David Gow Cheers, -- David > lib/kunit/test.c | 65 +++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 61 insertions(+), 4 deletions(-) > > diff --git a/lib/kunit/test.c b/lib/kunit/test.c > index dfe51bc2b387..28d0048d6171 100644 > --- a/lib/kunit/test.c > +++ b/lib/kunit/test.c > @@ -140,25 +140,82 @@ static struct kunit_log_frag *kunit_log_extend(struct list_head *log) > return frag; > } > > +static void kunit_log_append_string(struct list_head *log, const char *src) > +{ > + struct kunit_log_frag *frag, *new_frag; > + int log_len, bytes_left; > + ssize_t written; > + char *p; > + > + frag = list_last_entry(log, struct kunit_log_frag, list); > + log_len = strlen(frag->buf); > + bytes_left = sizeof(frag->buf) - log_len; > + > + written = strscpy(frag->buf + log_len, src, bytes_left); > + if (written != -E2BIG) > + goto newline; > + > + src += bytes_left - 1; > + do { > + new_frag = kunit_log_extend(log); > + if (!new_frag) > + goto newline; > + > + frag = new_frag; > + written = strscpy(frag->buf, src, sizeof(frag->buf)); > + src += sizeof(frag->buf) - 1; > + } while (written == -E2BIG); > + > +newline: > + if (written == -E2BIG) I think that this can only be true if kunit_log_extend() fails. If the do/while loop ends naturally, then written != -E2BIG, as is the case with the strscpy goto above. Do you think it's cleaner to move the 'written = strlen(frag->buf) into the if (!new_frag) statement within the loop? > + written = strlen(frag->buf); > + > + p = &frag->buf[written - 1]; > + if (*p != '\n') { > + if (strlcat(frag->buf, "\n", sizeof(frag->buf)) >= sizeof(frag->buf)) { > + frag = kunit_log_extend(log); > + if (!frag) { A comment here could be useful. Something like "If we can't extend the log to add a newline, truncate the last message". > + *p = '\n'; > + return; > + } > + > + frag->buf[0] = '\n'; > + frag->buf[1] = '\0'; > + } > + } > +} > + > /* Append formatted message to log, extending the log buffer if necessary. */ > void kunit_log_append(struct list_head *log, const char *fmt, ...) > { > va_list args; > struct kunit_log_frag *frag; > int len, log_len, len_left; > + char *tmp = NULL; > > if (!log) > return; > > - frag = list_last_entry(log, struct kunit_log_frag, list); > - log_len = strlen(frag->buf); > - len_left = sizeof(frag->buf) - log_len - 1; > - > /* Evaluate length of line to add to log */ > va_start(args, fmt); > len = vsnprintf(NULL, 0, fmt, args) + 1; > va_end(args); > > + if (len > sizeof(frag->buf) - 1) { > + va_start(args, fmt); > + tmp = kvasprintf(GFP_KERNEL, fmt, args); > + va_end(args); > + Should we handle the case where kvasprintf() fails here and drop the log message? > + kunit_log_append_string(log, tmp); > + kfree(tmp); > + > + return; > + } > + > + frag = list_last_entry(log, struct kunit_log_frag, list); > + log_len = strlen(frag->buf); > + len_left = sizeof(frag->buf) - log_len - 1; > + > if (len > len_left) { > frag = kunit_log_extend(log); > if (!frag) > -- > 2.30.2 >