Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F175662412
D59086.id189208.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D59086.id189208.diff
View Options
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_log.h b/sys/dev/bnxt/bnxt_en/bnxt_log.h
--- a/sys/dev/bnxt/bnxt_en/bnxt_log.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt_log.h
@@ -47,6 +47,10 @@
uint32_t max_live_buff_size;
uint32_t live_msgs_len;
void (*log_live_op)(void *dev);
+ /* Pin count held while log_lock is dropped for log_live_op(). */
+ u_int refcnt;
+ /* Set by bnxt_unregister_logger() when refcnt > 0; defers the free. */
+ bool unregister_pending;
};
struct bnxt_coredump_segment_hdr {
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_log.c b/sys/dev/bnxt/bnxt_en/bnxt_log.c
--- a/sys/dev/bnxt/bnxt_en/bnxt_log.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_log.c
@@ -99,21 +99,30 @@
bnxt_unregister_logger(struct bnxt_softc *bp, int logger_id)
{
struct bnxt_logger *l = NULL, *tmp;
+ bool found = false, defer = false;
mtx_lock(&bp->log_lock);
TAILQ_FOREACH_SAFE(l, &bp->loggers_list, list, tmp) {
if (l->logger_id == logger_id) {
TAILQ_REMOVE(&bp->loggers_list, l, list);
+ found = true;
break;
}
}
+ if (found && l->refcnt > 0) {
+ /* Pinned by coredump collection; defer the free. */
+ l->unregister_pending = true;
+ defer = true;
+ }
mtx_unlock(&bp->log_lock);
- if (!l) {
+ if (!found) {
device_printf(bp->dev, "logger id %d not registered\n",
logger_id);
return;
}
+ if (defer)
+ return;
free(l->msgs, M_BNXT_LOG);
free(l, M_BNXT_LOG);
@@ -137,9 +146,11 @@
else if (text[text_len] == '\0')
text[text_len] = '\n';
- if (text_len > max_len) {
- /* Truncate */
- text_len = max_len;
+ /* memcpy() below writes text_len + 1 bytes; leave room for it. */
+ if (max_len == 0)
+ return (0);
+ if (text_len >= max_len) {
+ text_len = max_len - 1;
text[text_len] = '\n';
}
@@ -192,17 +203,22 @@
bnxt_log_live(struct bnxt_softc *bp, uint16_t logger_id,
const char *format, ...)
{
- struct bnxt_logger *logger = NULL, *tmp;
+ struct bnxt_logger *logger = NULL;
va_list args;
int len;
- TAILQ_FOREACH_SAFE(logger, &bp->loggers_list, list, tmp) {
+ mtx_lock(&bp->log_lock);
+ /* log_lock stays held for this traversal, so plain TAILQ_FOREACH is safe here. */
+ TAILQ_FOREACH(logger, &bp->loggers_list, list) {
if (logger->logger_id == logger_id)
break;
}
- if (!logger || !logger->live_msgs)
+ if (!logger || !logger->live_msgs ||
+ logger->live_msgs_len >= logger->max_live_buff_size) {
+ mtx_unlock(&bp->log_lock);
return;
+ }
va_start(args, format);
len = bnxt_log_info(
@@ -212,6 +228,7 @@
va_end(args);
logger->live_msgs_len += len;
+ mtx_unlock(&bp->log_lock);
}
static size_t
@@ -269,7 +286,7 @@
int
bnxt_start_logging_driver_coredump(struct bnxt_softc *bp, char *dest_buf)
{
- struct bnxt_logger *logger, *tmp;
+ struct bnxt_logger *logger;
size_t offset = 0;
uint32_t seg_id = 0;
@@ -277,27 +294,64 @@
return (0);
mtx_lock(&bp->log_lock);
- TAILQ_FOREACH_SAFE(logger, &bp->loggers_list, list, tmp) {
+ logger = TAILQ_FIRST(&bp->loggers_list);
+ while (logger != NULL) {
struct bnxt_coredump_segment_hdr seg_hdr;
void *seg_hdr_dest = dest_buf + offset;
- size_t len;
+ struct bnxt_logger *next;
+ uint16_t next_id = 0;
+ bool have_next;
+ size_t len, live_len;
offset += sizeof(seg_hdr);
/* First collect logs from buffer */
len = bnxt_collect_logs_buffer(logger, dest_buf + offset);
offset += len;
- /* Let logger to collect live messages */
+
+ /* Pin logger and remember successor by id; log_lock drops below. */
+ logger->refcnt++;
+ next = TAILQ_NEXT(logger, list);
+ have_next = (next != NULL);
+ if (have_next)
+ next_id = next->logger_id;
+
+ /* log_live_op() calls bnxt_log_live(), which takes log_lock itself. */
logger->live_msgs = dest_buf + offset;
logger->live_msgs_len = 0;
+ mtx_unlock(&bp->log_lock);
+
logger->log_live_op(bp);
- len += logger->buffer_size;
- offset += logger->buffer_size;
+ mtx_lock(&bp->log_lock);
+ logger->live_msgs = NULL;
+ /* Actual bytes written, not buffer_size, or offset desyncs. */
+ live_len = logger->live_msgs_len;
+ logger->live_msgs_len = 0;
+
+ len += live_len;
+ offset += live_len;
bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, len,
0, 0, 0, 13, seg_id);
memcpy(seg_hdr_dest, &seg_hdr, sizeof(seg_hdr));
seg_id++;
+
+ logger->refcnt--;
+ if (logger->refcnt == 0 && logger->unregister_pending) {
+ free(logger->msgs, M_BNXT_LOG);
+ free(logger, M_BNXT_LOG);
+ }
+
+ /* Re-find successor by id; stop if it was unregistered meanwhile. */
+ logger = NULL;
+ if (have_next) {
+ TAILQ_FOREACH(next, &bp->loggers_list, list) {
+ if (next->logger_id == next_id) {
+ logger = next;
+ break;
+ }
+ }
+ }
}
mtx_unlock(&bp->log_lock);
return (offset);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Oct 13, 8:47 AM (3 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39939624
Default Alt Text
D59086.id189208.diff (4 KB)
Attached To
Mode
D59086: if_bnxt: log: fix missing lock coverage in bnxt_log_live()
Attached
Detach File
Event Timeline
Log In to Comment