]> git.sesse.net Git - bcachefs-tools-debian/blob - include/linux/printbuf.h
New upstream release
[bcachefs-tools-debian] / include / linux / printbuf.h
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /* Copyright (C) 2022 Kent Overstreet */
3
4 #ifndef _LINUX_PRINTBUF_H
5 #define _LINUX_PRINTBUF_H
6
7 /*
8  * Printbufs: Simple strings for printing to, with optional heap allocation
9  *
10  * This code has provisions for use in userspace, to aid in making other code
11  * portable between kernelspace and userspace.
12  *
13  * Basic example:
14  *   struct printbuf buf = PRINTBUF;
15  *
16  *   prt_printf(&buf, "foo=");
17  *   foo_to_text(&buf, foo);
18  *   printk("%s", buf.buf);
19  *   printbuf_exit(&buf);
20  *
21  * Or
22  *   struct printbuf buf = PRINTBUF_EXTERN(char_buf, char_buf_size)
23  *
24  * We can now write pretty printers instead of writing code that dumps
25  * everything to the kernel log buffer, and then those pretty-printers can be
26  * used by other code that outputs to kernel log, sysfs, debugfs, etc.
27  *
28  * Memory allocation: Outputing to a printbuf may allocate memory. This
29  * allocation is done with GFP_KERNEL, by default: use the newer
30  * memalloc_*_(save|restore) functions as needed.
31  *
32  * Since no equivalent yet exists for GFP_ATOMIC/GFP_NOWAIT, memory allocations
33  * will be done with GFP_NOWAIT if printbuf->atomic is nonzero.
34  *
35  * It's allowed to grab the output buffer and free it later with kfree() instead
36  * of using printbuf_exit(), if the user just needs a heap allocated string at
37  * the end.
38  *
39  * Memory allocation failures: We don't return errors directly, because on
40  * memory allocation failure we usually don't want to bail out and unwind - we
41  * want to print what we've got, on a best-effort basis. But code that does want
42  * to return -ENOMEM may check printbuf.allocation_failure.
43  *
44  * Indenting, tabstops:
45  *
46  * To aid is writing multi-line pretty printers spread across multiple
47  * functions, printbufs track the current indent level.
48  *
49  * printbuf_indent_push() and printbuf_indent_pop() increase and decrease the current indent
50  * level, respectively.
51  *
52  * To use tabstops, set printbuf->tabstops[]; they are in units of spaces, from
53  * start of line. Once set, prt_tab() will output spaces up to the next tabstop.
54  * prt_tab_rjust() will also advance the current line of text up to the next
55  * tabstop, but it does so by shifting text since the previous tabstop up to the
56  * next tabstop - right justifying it.
57  *
58  * Make sure you use prt_newline() instead of \n in the format string for indent
59  * level and tabstops to work corretly.
60  *
61  * Output units: printbuf->units exists to tell pretty-printers how to output
62  * numbers: a raw value (e.g. directly from a superblock field), as bytes, or as
63  * human readable bytes. prt_units() obeys it.
64  */
65
66 #include <linux/kernel.h>
67 #include <linux/string.h>
68
69 enum printbuf_si {
70         PRINTBUF_UNITS_2,       /* use binary powers of 2^10 */
71         PRINTBUF_UNITS_10,      /* use powers of 10^3 (standard SI) */
72 };
73
74 #define PRINTBUF_INLINE_TABSTOPS        4
75
76 struct printbuf {
77         char                    *buf;
78         unsigned                size;
79         unsigned                pos;
80         unsigned                last_newline;
81         unsigned                last_field;
82         unsigned                indent;
83         /*
84          * If nonzero, allocations will be done with GFP_ATOMIC:
85          */
86         u8                      atomic;
87         bool                    allocation_failure:1;
88         bool                    heap_allocated:1;
89         enum printbuf_si        si_units:1;
90         bool                    human_readable_units:1;
91         bool                    has_indent_or_tabstops:1;
92         bool                    suppress_indent_tabstop_handling:1;
93         u8                      nr_tabstops;
94
95         /*
96          * Do not modify directly: use printbuf_tabstop_add(),
97          * printbuf_tabstop_get()
98          */
99         u8                      cur_tabstop;
100         u8                      _tabstops[PRINTBUF_INLINE_TABSTOPS];
101 };
102
103 int printbuf_make_room(struct printbuf *, unsigned);
104 const char *printbuf_str(const struct printbuf *);
105 void printbuf_exit(struct printbuf *);
106
107 void printbuf_tabstops_reset(struct printbuf *);
108 void printbuf_tabstop_pop(struct printbuf *);
109 int printbuf_tabstop_push(struct printbuf *, unsigned);
110
111 void printbuf_indent_add(struct printbuf *, unsigned);
112 void printbuf_indent_sub(struct printbuf *, unsigned);
113
114 void prt_newline(struct printbuf *);
115 void prt_tab(struct printbuf *);
116 void prt_tab_rjust(struct printbuf *);
117
118 void prt_bytes_indented(struct printbuf *, const char *, unsigned);
119 void prt_human_readable_u64(struct printbuf *, u64);
120 void prt_human_readable_s64(struct printbuf *, s64);
121 void prt_units_u64(struct printbuf *, u64);
122 void prt_units_s64(struct printbuf *, s64);
123
124 /* Initializer for a heap allocated printbuf: */
125 #define PRINTBUF ((struct printbuf) { .heap_allocated = true })
126
127 /* Initializer a printbuf that points to an external buffer: */
128 #define PRINTBUF_EXTERN(_buf, _size)                    \
129 ((struct printbuf) {                                    \
130         .buf    = _buf,                                 \
131         .size   = _size,                                \
132 })
133
134 /*
135  * Returns size remaining of output buffer:
136  */
137 static inline unsigned printbuf_remaining_size(struct printbuf *out)
138 {
139         return out->pos < out->size ? out->size - out->pos : 0;
140 }
141
142 /*
143  * Returns number of characters we can print to the output buffer - i.e.
144  * excluding the terminating nul:
145  */
146 static inline unsigned printbuf_remaining(struct printbuf *out)
147 {
148         return out->pos < out->size ? out->size - out->pos - 1 : 0;
149 }
150
151 static inline unsigned printbuf_written(struct printbuf *out)
152 {
153         return out->size ? min(out->pos, out->size - 1) : 0;
154 }
155
156 /*
157  * Returns true if output was truncated:
158  */
159 static inline bool printbuf_overflowed(struct printbuf *out)
160 {
161         return out->pos >= out->size;
162 }
163
164 static inline void printbuf_nul_terminate(struct printbuf *out)
165 {
166         printbuf_make_room(out, 1);
167
168         if (out->pos < out->size)
169                 out->buf[out->pos] = 0;
170         else if (out->size)
171                 out->buf[out->size - 1] = 0;
172 }
173
174 /* Doesn't call printbuf_make_room(), doesn't nul terminate: */
175 static inline void __prt_char_reserved(struct printbuf *out, char c)
176 {
177         if (printbuf_remaining(out))
178                 out->buf[out->pos] = c;
179         out->pos++;
180 }
181
182 /* Doesn't nul terminate: */
183 static inline void __prt_char(struct printbuf *out, char c)
184 {
185         printbuf_make_room(out, 1);
186         __prt_char_reserved(out, c);
187 }
188
189 static inline void prt_char(struct printbuf *out, char c)
190 {
191         __prt_char(out, c);
192         printbuf_nul_terminate(out);
193 }
194
195 static inline void __prt_chars_reserved(struct printbuf *out, char c, unsigned n)
196 {
197         unsigned i, can_print = min(n, printbuf_remaining(out));
198
199         for (i = 0; i < can_print; i++)
200                 out->buf[out->pos++] = c;
201         out->pos += n - can_print;
202 }
203
204 static inline void prt_chars(struct printbuf *out, char c, unsigned n)
205 {
206         printbuf_make_room(out, n);
207         __prt_chars_reserved(out, c, n);
208         printbuf_nul_terminate(out);
209 }
210
211 static inline void prt_bytes(struct printbuf *out, const void *b, unsigned n)
212 {
213         unsigned i, can_print;
214
215         printbuf_make_room(out, n);
216
217         can_print = min(n, printbuf_remaining(out));
218
219         for (i = 0; i < can_print; i++)
220                 out->buf[out->pos++] = ((char *) b)[i];
221         out->pos += n - can_print;
222
223         printbuf_nul_terminate(out);
224 }
225
226 static inline void prt_str(struct printbuf *out, const char *str)
227 {
228         prt_bytes(out, str, strlen(str));
229 }
230
231 static inline void prt_str_indented(struct printbuf *out, const char *str)
232 {
233         prt_bytes_indented(out, str, strlen(str));
234 }
235
236 static inline void prt_hex_byte(struct printbuf *out, u8 byte)
237 {
238         printbuf_make_room(out, 2);
239         __prt_char_reserved(out, hex_asc_hi(byte));
240         __prt_char_reserved(out, hex_asc_lo(byte));
241         printbuf_nul_terminate(out);
242 }
243
244 static inline void prt_hex_byte_upper(struct printbuf *out, u8 byte)
245 {
246         printbuf_make_room(out, 2);
247         __prt_char_reserved(out, hex_asc_upper_hi(byte));
248         __prt_char_reserved(out, hex_asc_upper_lo(byte));
249         printbuf_nul_terminate(out);
250 }
251
252 /**
253  * printbuf_reset - re-use a printbuf without freeing and re-initializing it:
254  */
255 static inline void printbuf_reset(struct printbuf *buf)
256 {
257         buf->pos                = 0;
258         buf->allocation_failure = 0;
259         buf->indent             = 0;
260         buf->nr_tabstops        = 0;
261         buf->cur_tabstop        = 0;
262 }
263
264 /**
265  * printbuf_atomic_inc - mark as entering an atomic section
266  */
267 static inline void printbuf_atomic_inc(struct printbuf *buf)
268 {
269         buf->atomic++;
270 }
271
272 /**
273  * printbuf_atomic_inc - mark as leaving an atomic section
274  */
275 static inline void printbuf_atomic_dec(struct printbuf *buf)
276 {
277         buf->atomic--;
278 }
279
280 /*
281  * This is used for the %pf(%p) sprintf format extension, where we pass a pretty
282  * printer and arguments to the pretty-printer to sprintf
283  *
284  * Instead of passing a pretty-printer function to sprintf directly, we pass it
285  * a pointer to a struct call_pp, so that sprintf can check that the magic
286  * number is present, which in turn ensures that the CALL_PP() macro has been
287  * used in order to typecheck the arguments to the pretty printer function
288  *
289  * Example usage:
290  *   sprintf("%pf(%p)", CALL_PP(prt_bdev, bdev));
291  */
292 struct call_pp {
293         unsigned long   magic;
294         void            *fn;
295 };
296
297 #define PP_TYPECHECK(fn, ...)                                   \
298         ({ while (0) fn((struct printbuf *) NULL, ##__VA_ARGS__); })
299
300 #define CALL_PP_MAGIC           (unsigned long) 0xce0b92d22f6b6be4
301
302 #define CALL_PP(fn, ...)                                        \
303         (PP_TYPECHECK(fn, ##__VA_ARGS__),                       \
304          &((struct call_pp) { CALL_PP_MAGIC, fn })), ##__VA_ARGS__
305
306 #endif /* _LINUX_PRINTBUF_H */