Received: by 2002:ac0:e350:0:0:0:0:0 with SMTP id g16csp2169582imn; Mon, 1 Aug 2022 13:52:54 -0700 (PDT) X-Google-Smtp-Source: AA6agR5Aa2+v9WHcr0+wHdCti9zS8yCPcFMDS2PUOkIwBmk9PBVe/GhCgjIPIRjMxVjTMI5CleSC X-Received: by 2002:a17:906:8474:b0:730:7f7f:e49 with SMTP id hx20-20020a170906847400b007307f7f0e49mr5351045ejc.164.1659387173990; Mon, 01 Aug 2022 13:52:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1659387173; cv=none; d=google.com; s=arc-20160816; b=xfO5FzPN44zdViOiDe/MW3uW1+BnaJSPzP7LNxBnxrIwSjyvRwvspaFOgLVt9MepU1 NuU4Tb1X21XoiXT9moRbALta5fJZc+aAiMQbqrtnVNRREtMiL0lPVEPJgmywVcKliw1s m9cCkXAmvBFPgefHQw0htmBg4wrdrk/rCGuFB8rknk4QDGL0bCXLkwHSiFz8xGDDZAOf CV89JOi1wS0p62krbZDXGltzl7uSK5EH33jLv/H0fQjBYnTnRRJphdIbCz8B5BqwjWBf jfX5R14B1SZqdJ8aYrHAMrQ9ECrqIl69wdgUSkVxXQmzHBns7uf+Nb2mNq+xepTxrGzM UYLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:mime-version:message-id:date :dkim-signature; bh=E1/rW2r70zyzqbkFgkmqJNWOc56RBiTRd890RD2T0+o=; b=cwDf0uX841uHfmW6YmGHshc+E49inchhlI0S0FxKccqP24z1fg8UUmuMzQSZbHtV6c YKCjUhZqOxoy8n0ichaM7K8KjIKs6loTJuaavnAQMIoCqmlu0OqlRNAT/ZWz0vEDlT/+ lUdYCPc5vEyUSLKsyA+iIpUx3dz8AAApyZPU7zOQ0bznp/hb3sUhIFkCJuR0SfXwm4FY dsQEKkNWiF9LukKhtxr5gswx5h1THgkxcvsObtttVC0YMqviTJocaUslwwgWyf/LCCF5 KcWh5dDNlOVIuRXaNITFX3NlzZfX8vPW7iliJne/8RPzGE8lFJhhzMdWM81s72qOTg0K 8HBg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=XRNlLnXN; 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 u18-20020a50c052000000b0043d72da65f8si5936543edd.245.2022.08.01.13.52.28; Mon, 01 Aug 2022 13:52:53 -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=20210112 header.b=XRNlLnXN; 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 S234361AbiHAUus (ORCPT + 99 others); Mon, 1 Aug 2022 16:50:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53256 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231338AbiHAUuq (ORCPT ); Mon, 1 Aug 2022 16:50:46 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE6849FD4 for ; Mon, 1 Aug 2022 13:50:45 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-31f3959ba41so100674817b3.2 for ; Mon, 01 Aug 2022 13:50:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=E1/rW2r70zyzqbkFgkmqJNWOc56RBiTRd890RD2T0+o=; b=XRNlLnXNNNo/3J7ur9PazcMWQXWXdy0i4aGQbhsUznk0w+tMIO9sDu0/7g4O8KG4rj 1ZrxlurF863pz5Ebm+T4N2HcJD52RhpJaFJPFR9aKR7WBPWlwrfGimgPIESCe9w4X19g /DJzSPvoMe13rkKB5nYSXS3rQqPrju6VAZ8rY5Bz4GkUHFeGAacz6MSAJISiWmY+CAYZ X708Q4v77OzFy5rU4nh05vdJy0wsp/2b49O+5Nwzt1fALXz3+IY16QIf8Y48uNcz6Mgy VGsUQxlIf9Mb7z5Xngd0eivSJTu55Ob0xqWvwq1e//6nRxA32t1PzpuWiPPf4FhxenMo 119w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=E1/rW2r70zyzqbkFgkmqJNWOc56RBiTRd890RD2T0+o=; b=eNVwNQsLhKyTkRcVUxzi6VFZAcFh2ubA6rCUb9PuGyVj530JVtzZaOxH4SG0oxCJj6 67XSgTiOHS0/kU92bU4VEHDxSuRAB3Gi5K9asijybUlY4gyOHk2+KqrsLbF9snMmc2ed hVspTKYQnSD3NAu0iBt5S2TcJ0rhNIcAcCrwbVgz7IePvmqt+vgltICh5JApu9xhpXol xi5GV84pIEcabgZ/HXKq5nAWX3WJsFQZu479nv03OJQwv0UaXhlwFDq25t6hO3b24pjz xuRm/5MmaTbWQmrE2qrwow+ixyvPJ1sO0nVUUVBfPHp+XjR7bQmC28dnUmtXIun+jn4n k0VA== X-Gm-Message-State: ACgBeo1rcdmqT0VR00fBAgmSvH2LkM8FuHk3HwKtB9tcg23H8PnynmcO EHEq/uO6/aFnV8HH5t6T8Lzvu+DBiY7bcXCOjHnJx6g7D8go2FfuDryMMSeDydE8gwp5KYcSduS CUWfh4Im6H8QKslJqK7YQffMyLEytMa/QIXccyUqy1EZqDzzg1ESNmdHFISBY8+Y29bFY5Q== X-Received: from haoluo.svl.corp.google.com ([2620:15c:2d4:203:7c9:7b32:e73f:6716]) (user=haoluo job=sendgmr) by 2002:a25:640d:0:b0:670:9077:2203 with SMTP id y13-20020a25640d000000b0067090772203mr12776495ybb.460.1659387045104; Mon, 01 Aug 2022 13:50:45 -0700 (PDT) Date: Mon, 1 Aug 2022 13:50:39 -0700 Message-Id: <20220801205039.2755281-1-haoluo@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.37.1.455.g008518b4e5-goog Subject: [PATCH bpf-next v1] bpf, iter: clean up bpf_seq_read(). From: Hao Luo To: linux-kernel@vger.kernel.org, bpf@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Martin KaFai Lau , Song Liu , Yonghong Song , KP Singh , John Fastabend , Stanislav Fomichev , Jiri Olsa , Hao Luo Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,USER_IN_DEF_DKIM_WL autolearn=ham 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 Refactor bpf_seq_read() by extracting some common logic into helper functions. I hope this makes bpf_seq_read() more readable. This is a refactoring patch, so no behavior change is expected. Signed-off-by: Hao Luo --- kernel/bpf/bpf_iter.c | 156 +++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 63 deletions(-) diff --git a/kernel/bpf/bpf_iter.c b/kernel/bpf/bpf_iter.c index 7e8fd49406f6..39b5b647fdb7 100644 --- a/kernel/bpf/bpf_iter.c +++ b/kernel/bpf/bpf_iter.c @@ -77,6 +77,83 @@ static bool bpf_iter_support_resched(struct seq_file *seq) return iter_priv->tinfo->reg_info->feature & BPF_ITER_RESCHED; } +/* do_copy_to_user, copies seq->buf at offset seq->from to userspace and + * updates corresponding fields in seq. It returns -EFAULT if any error + * happens. The actual number of bytes copied is returned via the argument + * 'copied'. + */ +static int do_copy_to_user(struct seq_file *seq, char __user *buf, size_t size, + size_t *copied) +{ + size_t n; + + n = min(seq->count, size); + if (copy_to_user(buf, seq->buf + seq->from, n)) + return -EFAULT; + + seq->count -= n; + seq->from += n; + *copied = n; + return 0; +} + +/* do_seq_show, shows the given object 'p'. If 'p' is skipped or + * error happens, resets seq->count to 'offs'. + * + * Returns err > 0, indicating show() skips this object. + * Returns err = 0, indicating show() succeeds. + * Returns err < 0, indicating show() fails or overflow happened. + */ +static int do_seq_show(struct seq_file *seq, void *p, size_t offs) +{ + int err; + + WARN_ON(IS_ERR_OR_NULL(p)); + + err = seq->op->show(seq, p); + if (err > 0) { + /* object is skipped, decrease seq_num, so next + * valid object can reuse the same seq_num. + */ + bpf_iter_dec_seq_num(seq); + seq->count = offs; + return err; + } + + if (err < 0 || seq_has_overflowed(seq)) { + seq->count = offs; + return err ? err : -E2BIG; + } + + /* err == 0 and no overflow */ + return 0; +} + +/* do_seq_stop, stops at the given object 'p'. 'p' could be an ERR or NULL. If + * 'p' is an ERR or there was an overflow, reset seq->count to 'offs' and + * returns error. Returns 0 otherwise. + */ +static int do_seq_stop(struct seq_file *seq, void *p, size_t offs) +{ + if (IS_ERR(p)) { + seq->op->stop(seq, NULL); + seq->count = offs; + return PTR_ERR(p); + } + + seq->op->stop(seq, p); + if (!p) { + if (!seq_has_overflowed(seq)) { + bpf_iter_done_stop(seq); + } else { + seq->count = offs; + if (offs == 0) + return -E2BIG; + } + } + return 0; +} + /* maximum visited objects before bailing out */ #define MAX_ITER_OBJECTS 1000000 @@ -91,7 +168,7 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { struct seq_file *seq = file->private_data; - size_t n, offs, copied = 0; + size_t offs, copied = 0; int err = 0, num_objs = 0; bool can_resched; void *p; @@ -108,40 +185,18 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, } if (seq->count) { - n = min(seq->count, size); - err = copy_to_user(buf, seq->buf + seq->from, n); - if (err) { - err = -EFAULT; - goto done; - } - seq->count -= n; - seq->from += n; - copied = n; + err = do_copy_to_user(seq, buf, size, &copied); goto done; } seq->from = 0; p = seq->op->start(seq, &seq->index); - if (!p) + if (IS_ERR_OR_NULL(p)) goto stop; - if (IS_ERR(p)) { - err = PTR_ERR(p); - seq->op->stop(seq, p); - seq->count = 0; - goto done; - } - err = seq->op->show(seq, p); - if (err > 0) { - /* object is skipped, decrease seq_num, so next - * valid object can reuse the same seq_num. - */ - bpf_iter_dec_seq_num(seq); - seq->count = 0; - } else if (err < 0 || seq_has_overflowed(seq)) { - if (!err) - err = -E2BIG; - seq->op->stop(seq, p); + err = do_seq_show(seq, p, 0); + if (err < 0) { + do_seq_stop(seq, p, 0); seq->count = 0; goto done; } @@ -153,7 +208,7 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, num_objs++; offs = seq->count; p = seq->op->next(seq, p, &seq->index); - if (pos == seq->index) { + if (unlikely(pos == seq->index)) { pr_info_ratelimited("buggy seq_file .next function %ps " "did not updated position index\n", seq->op->next); @@ -161,7 +216,7 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, } if (IS_ERR_OR_NULL(p)) - break; + goto stop; /* got a valid next object, increase seq_num */ bpf_iter_inc_seq_num(seq); @@ -172,22 +227,16 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, if (num_objs >= MAX_ITER_OBJECTS) { if (offs == 0) { err = -EAGAIN; - seq->op->stop(seq, p); + do_seq_stop(seq, p, seq->count); goto done; } break; } - err = seq->op->show(seq, p); - if (err > 0) { - bpf_iter_dec_seq_num(seq); - seq->count = offs; - } else if (err < 0 || seq_has_overflowed(seq)) { - seq->count = offs; + err = do_seq_show(seq, p, offs); + if (err < 0) { if (offs == 0) { - if (!err) - err = -E2BIG; - seq->op->stop(seq, p); + do_seq_stop(seq, p, seq->count); goto done; } break; @@ -197,30 +246,11 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size, cond_resched(); } stop: - offs = seq->count; - /* bpf program called if !p */ - seq->op->stop(seq, p); - if (!p) { - if (!seq_has_overflowed(seq)) { - bpf_iter_done_stop(seq); - } else { - seq->count = offs; - if (offs == 0) { - err = -E2BIG; - goto done; - } - } - } - - n = min(seq->count, size); - err = copy_to_user(buf, seq->buf, n); - if (err) { - err = -EFAULT; + err = do_seq_stop(seq, p, seq->count); + if (err) goto done; - } - copied = n; - seq->count -= n; - seq->from = n; + + err = do_copy_to_user(seq, buf, size, &copied); done: if (!copied) copied = err; -- 2.37.1.455.g008518b4e5-goog