tipc: Fix recursive spinlock invocation in print buffer code
Allan Stephens [Mon, 5 May 2008 08:21:12 +0000 (01:21 -0700)]
This patch fixes two routines that allow the global print buffer
spinlock to be taken recursively.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

net/tipc/dbg.c

index c680691..834319e 100644 (file)
@@ -179,8 +179,10 @@ void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
        }
 
        if (pb_to->size < pb_from->size) {
-               tipc_printbuf_reset(pb_to);
-               tipc_printf(pb_to, "*** PRINT BUFFER MOVE ERROR ***");
+               strcpy(pb_to->buf, "*** PRINT BUFFER MOVE ERROR ***");
+               pb_to->buf[pb_to->size - 1] = ~0;
+               pb_to->crs = strchr(pb_to->buf, 0);
+               pb_to->next = NULL;
                return;
        }
 
@@ -405,27 +407,32 @@ struct sk_buff *tipc_log_dump(void)
        struct sk_buff *reply;
 
        spin_lock_bh(&print_lock);
-       if (!TIPC_LOG->buf)
+       if (!TIPC_LOG->buf) {
+               spin_unlock_bh(&print_lock);
                reply = tipc_cfg_reply_ultra_string("log not activated\n");
-       else if (tipc_printbuf_empty(TIPC_LOG))
+       } else if (tipc_printbuf_empty(TIPC_LOG)) {
+               spin_unlock_bh(&print_lock);
                reply = tipc_cfg_reply_ultra_string("log is empty\n");
+       }
        else {
                struct tlv_desc *rep_tlv;
                struct print_buf pb;
                int str_len;
 
                str_len = min(TIPC_LOG->size, 32768u);
+               spin_unlock_bh(&print_lock);
                reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len));
                if (reply) {
                        rep_tlv = (struct tlv_desc *)reply->data;
                        tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len);
+                       spin_lock_bh(&print_lock);
                        tipc_printbuf_move(&pb, TIPC_LOG);
+                       spin_unlock_bh(&print_lock);
                        str_len = strlen(TLV_DATA(rep_tlv)) + 1;
                        skb_put(reply, TLV_SPACE(str_len));
                        TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
                }
        }
-       spin_unlock_bh(&print_lock);
        return reply;
 }