From: Thomas Zimmermann <tzimmermann@suse.de>
To: deller@gmx.de, geert+renesas@glider.be, timur@kernel.org,
rdunlap@infradead.org, paulus@samba.org,
benh@kernel.crashing.org, linux@armlinux.org.uk,
pjones@redhat.com, adaplas@gmail.com, s.hauer@pengutronix.de,
shawnguo@kernel.org, mbroemme@libmpq.org,
thomas@winischhofer.net, James.Bottomley@HansenPartnership.com,
sudipm.mukherjee@gmail.com, teddy.wang@siliconmotion.com,
corbet@lwn.net
Cc: linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org,
Thomas Zimmermann <tzimmermann@suse.de>
Subject: [PATCH v2 001/101] lib: Add option iterator
Date: Thu, 9 Mar 2023 17:00:21 +0100 [thread overview]
Message-ID: <20230309160201.5163-2-tzimmermann@suse.de> (raw)
In-Reply-To: <20230309160201.5163-1-tzimmermann@suse.de>
Add struct option_iter and helpers that walk over individual options
of an option string. Add documentation.
Kernel parameters often have the format of
param=opt1,opt2:val,opt3
where the option string contains a number of comma-separated options.
Drivers usually use strsep() in a loop to extract individual options
from the string. Each call to strsep() modifies the given string, so
callers have to duplicate kernel parameters that are to be parsed
multiple times.
The new struct option_iter and its helpers wrap this code behind a
clean interface. Drivers can iterate over the options without having
to know the details of the option-string format. The iterator handles
string memory internally without modifying the original options.
v2:
* improve documentation (Randy)
* implement option_iter_next() as function
* allow modification of the returned options
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
Documentation/core-api/kernel-api.rst | 9 +++
include/linux/cmdline.h | 36 +++++++++
lib/Makefile | 2 +-
lib/cmdline_iter.c | 109 ++++++++++++++++++++++++++
4 files changed, 155 insertions(+), 1 deletion(-)
create mode 100644 include/linux/cmdline.h
create mode 100644 lib/cmdline_iter.c
diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst
index 62f961610773..cdc7ba8decf9 100644
--- a/Documentation/core-api/kernel-api.rst
+++ b/Documentation/core-api/kernel-api.rst
@@ -93,9 +93,18 @@ Bitmap Operations
Command-line Parsing
--------------------
+.. kernel-doc:: lib/cmdline_iter.c
+ :doc: overview
+
.. kernel-doc:: lib/cmdline.c
:export:
+.. kernel-doc:: lib/cmdline_iter.c
+ :export:
+
+.. kernel-doc:: include/linux/cmdline.h
+ :internal:
+
Sorting
-------
diff --git a/include/linux/cmdline.h b/include/linux/cmdline.h
new file mode 100644
index 000000000000..e9e0eb68e176
--- /dev/null
+++ b/include/linux/cmdline.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef LINUX_CMDLINE_H
+#define LINUX_CMDLINE_H
+
+#include <linux/types.h>
+
+/**
+ * struct option_iter - Iterates over string of kernel or module options
+ */
+struct option_iter {
+ char *optbuf;
+ char *next_opt;
+};
+
+void option_iter_init(struct option_iter *iter, const char *options);
+void option_iter_release(struct option_iter *iter);
+char *option_iter_incr(struct option_iter *iter);
+
+/**
+ * option_iter_next - Loop condition to move over options
+ * @iter: the iterator
+ * @opt: the name of the option variable
+ *
+ * Iterates over option strings as part of a while loop and
+ * stores the current option in @opt.
+ *
+ * Return:
+ * True to continue the loop, or false if no further option has been found.
+ */
+static inline bool option_iter_next(struct option_iter *iter, char **opt)
+{
+ return ((*opt = option_iter_incr(iter)) != NULL);
+}
+
+#endif
diff --git a/lib/Makefile b/lib/Makefile
index 4d9461bfea42..829ea6647d7a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -27,7 +27,7 @@ KASAN_SANITIZE_string.o := n
CFLAGS_string.o += -fno-stack-protector
endif
-lib-y := ctype.o string.o vsprintf.o cmdline.o \
+lib-y := ctype.o string.o vsprintf.o cmdline.o cmdline_iter.o \
rbtree.o radix-tree.o timerqueue.o xarray.o \
maple_tree.o idr.o extable.o irq_regs.o argv_split.o \
flex_proportions.o ratelimit.o show_mem.o \
diff --git a/lib/cmdline_iter.c b/lib/cmdline_iter.c
new file mode 100644
index 000000000000..3e53aa8d8a3d
--- /dev/null
+++ b/lib/cmdline_iter.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/cmdline.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+
+/**
+ * DOC: overview
+ *
+ * A kernel parameter's option string can contain multiple comma-separated
+ * options. Struct &option_iter and its helpers parse the string and return
+ * the individual substrings.
+ *
+ * After obtaining the string from the kernel, initialize an instance of the
+ * option iterator and loop over its content as show below.
+ *
+ * .. code-block:: c
+ *
+ * const char *options = ...; // kernel-provided option string
+ *
+ * struct option_iter iter;
+ * char *opt;
+ *
+ * option_iter_init(&iter, options);
+ *
+ * while (option_iter_next(&iter, &opt)) {
+ * if (!strcmp(opt, "foo"))
+ * ...
+ * else (strcmp(opt, "bar"))
+ * ...
+ * else
+ * pr_warn("unknown option %s\n", opt);
+ * }
+ *
+ * option_iter_release(&iter);
+ *
+ * The functions option_iter_init() and option_iter_release() enclose
+ * all code that uses struct &option_iter. The call to option_iter_init()
+ * initializes the iterator instance from the option string and sets it
+ * up to return the first contained substring. The iterator owns a copy
+ * of the option string, which is later freed by option_iter_release().
+ * The state of an instance of struct &option_iter is undefined after the
+ * release function has returned.
+ *
+ * The loop walks over the individual options while option_iter_next()
+ * succeeds. In this case, the second argument returns a pointer to the
+ * contained substring. If the option string contains an empty option
+ * (i.e., two commas next to each other), option_iter_next() skips the
+ * empty option automatically.
+ *
+ * The parsing process does not modify the original option string that
+ * was used to initialize the iterator. The memory returned by
+ * option_iter_next() is owned by the iterator instance. Callers are
+ * allowed to modify its content but may not free it. References to the
+ * returned string become stale after option_iter_release() has returned.
+ */
+
+/**
+ * option_iter_init - Initializes an option iterator
+ * @iter: the iterator to initialize
+ * @options: the options string
+ */
+void option_iter_init(struct option_iter *iter, const char *options)
+{
+ if (options && *options)
+ iter->optbuf = kstrdup(options, GFP_KERNEL); // can be NULL
+ else
+ iter->optbuf = NULL;
+ iter->next_opt = iter->optbuf;
+}
+EXPORT_SYMBOL(option_iter_init);
+
+/**
+ * option_iter_release - Releases an option iterator's resources
+ * @iter: the iterator
+ */
+void option_iter_release(struct option_iter *iter)
+{
+ kfree(iter->optbuf);
+ iter->next_opt = NULL;
+}
+EXPORT_SYMBOL(option_iter_release);
+
+/**
+ * option_iter_incr - Return current option and advance to the next
+ * @iter: the iterator
+ *
+ * Return:
+ * The current option string, or NULL if there are no more options.
+ */
+char *option_iter_incr(struct option_iter *iter)
+{
+ char *opt;
+
+ if (!iter->next_opt) { // can be OK if kstrdup failed
+ if (iter->optbuf) // iter has already been released; logic error
+ pr_err("Incrementing option iterator without string\n");
+ return NULL;
+ }
+
+ do {
+ opt = strsep(&iter->next_opt, ",");
+ if (!opt)
+ return NULL;
+ } while (!*opt); // found empty option string, try next
+
+ return opt;
+}
+EXPORT_SYMBOL(option_iter_incr);
--
2.39.2
next prev parent reply other threads:[~2023-03-09 16:02 UTC|newest]
Thread overview: 112+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-09 16:00 [PATCH v2 000/101] fbdev: Fix memory leak in option parsing Thomas Zimmermann
2023-03-09 16:00 ` Thomas Zimmermann [this message]
2023-03-10 8:21 ` [PATCH v2 001/101] lib: Add option iterator Geert Uytterhoeven
2023-03-10 12:38 ` Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 002/101] fbdev/68328fb: Remove trailing whitespaces Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 003/101] fbdev/68328fb: Remove unused option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 004/101] fbdev/acornfb: Only init fb_info once Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 005/101] fbdev/acornfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 006/101] fbdev/amifb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 007/101] fbdev/amifb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 008/101] fbdev/arkfb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 009/101] fbdev/atafb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 010/101] fbdev/atafb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 011/101] fbdev/aty: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 012/101] fbdev/aty: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 013/101] fbdev/au1100fb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 014/101] fbdev/au1200fb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 015/101] fbdev/cirrusfb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 016/101] fbdev/cirrusfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 017/101] fbdev/controlfb: Remove trailing whitespaces Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 018/101] fbdev/controlfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 019/101] fbdev/cyber2000fb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 020/101] fbdev/efifb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 021/101] fbdev/fm2fb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 022/101] fbdev/fsl-diu-fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 023/101] fbdev/fsl-diu-fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 024/101] fbdev/gbefb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 025/101] fbdev/gbefb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 026/101] fbdev/geode: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 027/101] fbdev/geode: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 028/101] fbdev/grvga: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 029/101] fbdev/grvga: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 030/101] fbdev/gxt4500: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 031/101] fbdev/hyperv_fb: " Thomas Zimmermann
2023-03-12 10:51 ` Michael Kelley (LINUX)
2023-03-09 16:00 ` [PATCH v2 032/101] fbdev/i740fb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 033/101] fbdev/i740fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 034/101] fbdev/i810: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 035/101] fbdev/i810: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 036/101] fbdev/imsttfb: " Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 037/101] fbdev/intelfb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 038/101] fbdev/intelfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:00 ` [PATCH v2 039/101] fbdev/imxfb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 040/101] fbdev/imxfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 041/101] fbdev/kyrofb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 042/101] fbdev/kyrofb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 043/101] fbdev/macfb: Remove trailing whitespaces Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 044/101] fbdev/macfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 045/101] fbdev/matroxfb: " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 046/101] fbdev/mx3fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 047/101] fbdev/mx3fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 048/101] fbdev/neofb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 049/101] fbdev/neofb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 050/101] fbdev/nvidiafb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 051/101] fbdev/nvidiafb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 052/101] fbdev/ocfb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 053/101] fbdev/ocfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 054/101] fbdev/omapfb: " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 055/101] fbdev/platinumfb: Remove trailing whitespaces Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 056/101] fbdev/platinumfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 057/101] fbdev/pm2fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 058/101] fbdev/pm2fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 059/101] fbdev/pm3fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 060/101] fbdev/pm3fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 061/101] fbdev/ps3fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-10 8:18 ` Geert Uytterhoeven
2023-03-10 12:21 ` Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 062/101] fbdev/ps3fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 063/101] fbdev/pvr2fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 064/101] fbdev/pvr2fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 065/101] fbdev/pxafb: " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 066/101] fbdev/rivafb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 067/101] fbdev/rivafb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 068/101] fbdev/s3fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 069/101] fbdev/s3fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 070/101] fbdev/savagefb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 071/101] fbdev/savagefb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 072/101] fbdev/sisfb: Constify mode string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 073/101] fbdev/sisfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 074/101] fbdev/skeletonfb: " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 075/101] fbdev/sm712fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 076/101] fbdev/sstfb: " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 077/101] fbdev/sstfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 078/101] fbdev/stifb: Remove trailing whitespaces Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 079/101] fbdev/stifb: Constify option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 080/101] fbdev/tdfxfb: Duplicate video-mode " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 081/101] fbdev/tdfxfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 082/101] fbdev/tgafb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 083/101] fbdev/tgafb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 084/101] fbdev/tmiofb: Remove unused option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 085/101] fbdev/tridentfb: Duplicate video-mode " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 086/101] fbdev/tridentfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 087/101] fbdev/uvesafb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 088/101] fbdev/uvesafb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 089/101] fbdev/valkyriefb: Remove trailing whitespaces Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 090/101] fbdev/valkyriefb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 091/101] fbdev/vermilion: Remove unused option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 092/101] fbdev/vesafb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 093/101] fbdev/vfb: Remove trailing whitespaces Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 094/101] fbdev/vfb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 095/101] fbdev/vfb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 096/101] fbdev/viafb: " Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 097/101] fbdev/vt8623fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 098/101] staging/sm750fb: Release g_settings in module-exit function Thomas Zimmermann
2023-03-09 16:01 ` [PATCH v2 099/101] staging/sm750fb: Duplicate video-mode option string Thomas Zimmermann
2023-03-09 16:02 ` [PATCH v2 100/101] staging/sm750fb: Parse option string with struct option_iter Thomas Zimmermann
2023-03-09 16:02 ` [PATCH v2 101/101] fbdev: Constify option strings Thomas Zimmermann
2023-03-10 8:24 ` [PATCH v2 000/101] fbdev: Fix memory leak in option parsing Geert Uytterhoeven
2023-03-10 12:44 ` Thomas Zimmermann
2023-03-20 10:07 ` Thomas Zimmermann
2023-03-20 19:25 ` Helge Deller
2023-03-21 8:53 ` Thomas Zimmermann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230309160201.5163-2-tzimmermann@suse.de \
--to=tzimmermann@suse.de \
--cc=James.Bottomley@HansenPartnership.com \
--cc=adaplas@gmail.com \
--cc=benh@kernel.crashing.org \
--cc=corbet@lwn.net \
--cc=deller@gmx.de \
--cc=dri-devel@lists.freedesktop.org \
--cc=geert+renesas@glider.be \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=mbroemme@libmpq.org \
--cc=paulus@samba.org \
--cc=pjones@redhat.com \
--cc=rdunlap@infradead.org \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.org \
--cc=sudipm.mukherjee@gmail.com \
--cc=teddy.wang@siliconmotion.com \
--cc=thomas@winischhofer.net \
--cc=timur@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®