mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 14:13:53 +00:00
bcachefs: printbuf improvements
- fix assorted (harmless) off-by-one errors - we were inconsistent on whether out->pos stays <= out->size on overflow; now it does, and printbuf.overflow exists to indicate if a printbuf has overflowed - factor out printbuf_advance_pos() - printbuf_nul_terminate_reserved(); use this to reduce the number of printbuf_make_room() calls Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
62606398d5
commit
acce32a51e
@ -17,28 +17,28 @@ static inline unsigned printbuf_linelen(struct printbuf *buf)
|
||||
|
||||
int bch2_printbuf_make_room(struct printbuf *out, unsigned extra)
|
||||
{
|
||||
unsigned new_size;
|
||||
char *buf;
|
||||
|
||||
if (!out->heap_allocated)
|
||||
return 0;
|
||||
|
||||
/* Reserved space for terminating nul: */
|
||||
extra += 1;
|
||||
|
||||
if (out->pos + extra < out->size)
|
||||
if (out->pos + extra <= out->size)
|
||||
return 0;
|
||||
|
||||
new_size = roundup_pow_of_two(out->size + extra);
|
||||
if (!out->heap_allocated) {
|
||||
out->overflow = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned new_size = roundup_pow_of_two(out->size + extra);
|
||||
|
||||
/*
|
||||
* Note: output buffer must be freeable with kfree(), it's not required
|
||||
* that the user use printbuf_exit().
|
||||
*/
|
||||
buf = krealloc(out->buf, new_size, !out->atomic ? GFP_KERNEL : GFP_NOWAIT);
|
||||
char *buf = krealloc(out->buf, new_size, !out->atomic ? GFP_KERNEL : GFP_NOWAIT);
|
||||
|
||||
if (!buf) {
|
||||
out->allocation_failure = true;
|
||||
out->overflow = true;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -47,6 +47,11 @@ int bch2_printbuf_make_room(struct printbuf *out, unsigned extra)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void printbuf_advance_pos(struct printbuf *out, unsigned len)
|
||||
{
|
||||
out->pos += min(len, printbuf_remaining(out));
|
||||
}
|
||||
|
||||
void bch2_prt_vprintf(struct printbuf *out, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
@ -55,14 +60,12 @@ void bch2_prt_vprintf(struct printbuf *out, const char *fmt, va_list args)
|
||||
va_list args2;
|
||||
|
||||
va_copy(args2, args);
|
||||
len = vsnprintf(out->buf + out->pos, printbuf_remaining(out), fmt, args2);
|
||||
len = vsnprintf(out->buf + out->pos, printbuf_remaining_size(out), fmt, args2);
|
||||
va_end(args2);
|
||||
} while (len + 1 >= printbuf_remaining(out) &&
|
||||
!bch2_printbuf_make_room(out, len + 1));
|
||||
} while (len > printbuf_remaining(out) &&
|
||||
!bch2_printbuf_make_room(out, len));
|
||||
|
||||
len = min_t(size_t, len,
|
||||
printbuf_remaining(out) ? printbuf_remaining(out) - 1 : 0);
|
||||
out->pos += len;
|
||||
printbuf_advance_pos(out, len);
|
||||
}
|
||||
|
||||
void bch2_prt_printf(struct printbuf *out, const char *fmt, ...)
|
||||
@ -72,14 +75,12 @@ void bch2_prt_printf(struct printbuf *out, const char *fmt, ...)
|
||||
|
||||
do {
|
||||
va_start(args, fmt);
|
||||
len = vsnprintf(out->buf + out->pos, printbuf_remaining(out), fmt, args);
|
||||
len = vsnprintf(out->buf + out->pos, printbuf_remaining_size(out), fmt, args);
|
||||
va_end(args);
|
||||
} while (len + 1 >= printbuf_remaining(out) &&
|
||||
!bch2_printbuf_make_room(out, len + 1));
|
||||
} while (len > printbuf_remaining(out) &&
|
||||
!bch2_printbuf_make_room(out, len));
|
||||
|
||||
len = min_t(size_t, len,
|
||||
printbuf_remaining(out) ? printbuf_remaining(out) - 1 : 0);
|
||||
out->pos += len;
|
||||
printbuf_advance_pos(out, len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -194,18 +195,15 @@ void bch2_printbuf_indent_sub(struct printbuf *buf, unsigned spaces)
|
||||
|
||||
void bch2_prt_newline(struct printbuf *buf)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
bch2_printbuf_make_room(buf, 1 + buf->indent);
|
||||
|
||||
__prt_char(buf, '\n');
|
||||
__prt_char_reserved(buf, '\n');
|
||||
|
||||
buf->last_newline = buf->pos;
|
||||
|
||||
for (i = 0; i < buf->indent; i++)
|
||||
__prt_char(buf, ' ');
|
||||
__prt_chars_reserved(buf, ' ', buf->indent);
|
||||
|
||||
printbuf_nul_terminate(buf);
|
||||
printbuf_nul_terminate_reserved(buf);
|
||||
|
||||
buf->last_field = buf->pos;
|
||||
buf->cur_tabstop = 0;
|
||||
@ -262,7 +260,7 @@ static void __prt_tab_rjust(struct printbuf *buf)
|
||||
memset(buf->buf + buf->last_field, ' ',
|
||||
min((unsigned) pad, buf->size - buf->last_field));
|
||||
|
||||
buf->pos += pad;
|
||||
printbuf_advance_pos(buf, pad);
|
||||
printbuf_nul_terminate(buf);
|
||||
}
|
||||
|
||||
@ -348,9 +346,10 @@ void bch2_prt_bytes_indented(struct printbuf *out, const char *str, unsigned cou
|
||||
void bch2_prt_human_readable_u64(struct printbuf *out, u64 v)
|
||||
{
|
||||
bch2_printbuf_make_room(out, 10);
|
||||
out->pos += string_get_size(v, 1, !out->si_units,
|
||||
out->buf + out->pos,
|
||||
printbuf_remaining_size(out));
|
||||
unsigned len = string_get_size(v, 1, !out->si_units,
|
||||
out->buf + out->pos,
|
||||
printbuf_remaining_size(out));
|
||||
printbuf_advance_pos(out, len);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,9 +401,7 @@ void bch2_prt_string_option(struct printbuf *out,
|
||||
const char * const list[],
|
||||
size_t selected)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; list[i]; i++)
|
||||
for (size_t i = 0; list[i]; i++)
|
||||
bch2_prt_printf(out, i == selected ? "[%s] " : "%s ", list[i]);
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,7 @@ struct printbuf {
|
||||
u8 atomic;
|
||||
bool allocation_failure:1;
|
||||
bool heap_allocated:1;
|
||||
bool overflow:1;
|
||||
enum printbuf_si si_units:1;
|
||||
bool human_readable_units:1;
|
||||
bool has_indent_or_tabstops:1;
|
||||
@ -142,7 +143,9 @@ void bch2_prt_bitflags_vector(struct printbuf *, const char * const[],
|
||||
*/
|
||||
static inline unsigned printbuf_remaining_size(struct printbuf *out)
|
||||
{
|
||||
return out->pos < out->size ? out->size - out->pos : 0;
|
||||
if (WARN_ON(out->size && out->pos >= out->size))
|
||||
out->pos = out->size - 1;
|
||||
return out->size - out->pos;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -151,7 +154,7 @@ static inline unsigned printbuf_remaining_size(struct printbuf *out)
|
||||
*/
|
||||
static inline unsigned printbuf_remaining(struct printbuf *out)
|
||||
{
|
||||
return out->pos < out->size ? out->size - out->pos - 1 : 0;
|
||||
return out->size ? printbuf_remaining_size(out) - 1 : 0;
|
||||
}
|
||||
|
||||
static inline unsigned printbuf_written(struct printbuf *out)
|
||||
@ -159,30 +162,25 @@ static inline unsigned printbuf_written(struct printbuf *out)
|
||||
return out->size ? min(out->pos, out->size - 1) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if output was truncated:
|
||||
*/
|
||||
static inline bool printbuf_overflowed(struct printbuf *out)
|
||||
static inline void printbuf_nul_terminate_reserved(struct printbuf *out)
|
||||
{
|
||||
return out->pos >= out->size;
|
||||
if (WARN_ON(out->size && out->pos >= out->size))
|
||||
out->pos = out->size - 1;
|
||||
if (out->size)
|
||||
out->buf[out->pos] = 0;
|
||||
}
|
||||
|
||||
static inline void printbuf_nul_terminate(struct printbuf *out)
|
||||
{
|
||||
bch2_printbuf_make_room(out, 1);
|
||||
|
||||
if (out->pos < out->size)
|
||||
out->buf[out->pos] = 0;
|
||||
else if (out->size)
|
||||
out->buf[out->size - 1] = 0;
|
||||
printbuf_nul_terminate_reserved(out);
|
||||
}
|
||||
|
||||
/* Doesn't call bch2_printbuf_make_room(), doesn't nul terminate: */
|
||||
static inline void __prt_char_reserved(struct printbuf *out, char c)
|
||||
{
|
||||
if (printbuf_remaining(out))
|
||||
out->buf[out->pos] = c;
|
||||
out->pos++;
|
||||
out->buf[out->pos++] = c;
|
||||
}
|
||||
|
||||
/* Doesn't nul terminate: */
|
||||
@ -194,37 +192,34 @@ static inline void __prt_char(struct printbuf *out, char c)
|
||||
|
||||
static inline void prt_char(struct printbuf *out, char c)
|
||||
{
|
||||
__prt_char(out, c);
|
||||
printbuf_nul_terminate(out);
|
||||
bch2_printbuf_make_room(out, 2);
|
||||
__prt_char_reserved(out, c);
|
||||
printbuf_nul_terminate_reserved(out);
|
||||
}
|
||||
|
||||
static inline void __prt_chars_reserved(struct printbuf *out, char c, unsigned n)
|
||||
{
|
||||
unsigned i, can_print = min(n, printbuf_remaining(out));
|
||||
unsigned can_print = min(n, printbuf_remaining(out));
|
||||
|
||||
for (i = 0; i < can_print; i++)
|
||||
for (unsigned i = 0; i < can_print; i++)
|
||||
out->buf[out->pos++] = c;
|
||||
out->pos += n - can_print;
|
||||
}
|
||||
|
||||
static inline void prt_chars(struct printbuf *out, char c, unsigned n)
|
||||
{
|
||||
bch2_printbuf_make_room(out, n);
|
||||
__prt_chars_reserved(out, c, n);
|
||||
printbuf_nul_terminate(out);
|
||||
printbuf_nul_terminate_reserved(out);
|
||||
}
|
||||
|
||||
static inline void prt_bytes(struct printbuf *out, const void *b, unsigned n)
|
||||
{
|
||||
unsigned i, can_print;
|
||||
|
||||
bch2_printbuf_make_room(out, n);
|
||||
|
||||
can_print = min(n, printbuf_remaining(out));
|
||||
unsigned can_print = min(n, printbuf_remaining(out));
|
||||
|
||||
for (i = 0; i < can_print; i++)
|
||||
for (unsigned i = 0; i < can_print; i++)
|
||||
out->buf[out->pos++] = ((char *) b)[i];
|
||||
out->pos += n - can_print;
|
||||
|
||||
printbuf_nul_terminate(out);
|
||||
}
|
||||
@ -241,18 +236,18 @@ static inline void prt_str_indented(struct printbuf *out, const char *str)
|
||||
|
||||
static inline void prt_hex_byte(struct printbuf *out, u8 byte)
|
||||
{
|
||||
bch2_printbuf_make_room(out, 2);
|
||||
bch2_printbuf_make_room(out, 3);
|
||||
__prt_char_reserved(out, hex_asc_hi(byte));
|
||||
__prt_char_reserved(out, hex_asc_lo(byte));
|
||||
printbuf_nul_terminate(out);
|
||||
printbuf_nul_terminate_reserved(out);
|
||||
}
|
||||
|
||||
static inline void prt_hex_byte_upper(struct printbuf *out, u8 byte)
|
||||
{
|
||||
bch2_printbuf_make_room(out, 2);
|
||||
bch2_printbuf_make_room(out, 3);
|
||||
__prt_char_reserved(out, hex_asc_upper_hi(byte));
|
||||
__prt_char_reserved(out, hex_asc_upper_lo(byte));
|
||||
printbuf_nul_terminate(out);
|
||||
printbuf_nul_terminate_reserved(out);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user