Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/subr_sbuf.c
Show First 20 Lines • Show All 363 Lines • ▼ Show 20 Lines | sbuf_drain(struct sbuf *s) | ||||
int len; | int len; | ||||
KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); | KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s)); | ||||
KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); | KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s)); | ||||
if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0) | if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0) | ||||
return (s->s_error = EDEADLK); | return (s->s_error = EDEADLK); | ||||
len = s->s_drain_func(s->s_drain_arg, s->s_buf, | len = s->s_drain_func(s->s_drain_arg, s->s_buf, | ||||
SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len); | SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len); | ||||
if (len < 0) { | if (len <= 0) { | ||||
s->s_error = -len; | s->s_error = len ? -len : EDEADLK; | ||||
return (s->s_error); | return (s->s_error); | ||||
} | } | ||||
KASSERT(len > 0 && len <= s->s_len, | KASSERT(len > 0 && len <= s->s_len, | ||||
("Bad drain amount %d for sbuf %p", len, s)); | ("Bad drain amount %d for sbuf %p", len, s)); | ||||
s->s_len -= len; | s->s_len -= len; | ||||
s->s_rec_off -= len; | s->s_rec_off -= len; | ||||
/* | /* | ||||
* Fast path for the expected case where all the data was | * Fast path for the expected case where all the data was | ||||
▲ Show 20 Lines • Show All 253 Lines • ▼ Show 20 Lines | if (len < 0) { | ||||
return (-1); | return (-1); | ||||
} | } | ||||
va_end(ap_copy); | va_end(ap_copy); | ||||
if (SBUF_FREESPACE(s) >= len) | if (SBUF_FREESPACE(s) >= len) | ||||
break; | break; | ||||
/* Cannot print with the current available space. */ | /* Cannot print with the current available space. */ | ||||
if (s->s_drain_func != NULL && s->s_len > 0) | if (s->s_drain_func != NULL && s->s_len > 0) | ||||
error = sbuf_drain(s); | error = sbuf_drain(s); /* sbuf_drain() sets s_error. */ | ||||
else | else if (sbuf_extend(s, len - SBUF_FREESPACE(s)) != 0) | ||||
error = sbuf_extend(s, len - SBUF_FREESPACE(s)); | s->s_error = error = ENOMEM; | ||||
} while (error == 0); | } while (error == 0); | ||||
/* | /* | ||||
* s->s_len is the length of the string, without the terminating nul. | * s->s_len is the length of the string, without the terminating nul. | ||||
* When updating s->s_len, we must subtract 1 from the length that | * When updating s->s_len, we must subtract 1 from the length that | ||||
* we passed into vsnprintf() because that length includes the | * we passed into vsnprintf() because that length includes the | ||||
* terminating nul. | * terminating nul. | ||||
* | * | ||||
* vsnprintf() returns the amount that would have been copied, | * vsnprintf() returns the amount that would have been copied, | ||||
* given sufficient space, so don't over-increment s_len. | * given sufficient space, so don't over-increment s_len. | ||||
*/ | */ | ||||
if (SBUF_FREESPACE(s) < len) | if (SBUF_FREESPACE(s) < len) | ||||
len = SBUF_FREESPACE(s); | len = SBUF_FREESPACE(s); | ||||
s->s_len += len; | s->s_len += len; | ||||
if (SBUF_ISSECTION(s)) | if (SBUF_ISSECTION(s)) | ||||
s->s_sect_len += len; | s->s_sect_len += len; | ||||
if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s)) | |||||
s->s_error = ENOMEM; | |||||
KASSERT(s->s_len < s->s_size, | KASSERT(s->s_len < s->s_size, | ||||
("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); | ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); | ||||
if (s->s_error != 0) | if (s->s_error != 0) | ||||
return (-1); | return (-1); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 213 Lines • Show Last 20 Lines |