Re: [PATCHSET] printk: implement printk_header() and merging printk,take #3

From: Tejun Heo
Date: Wed Feb 13 2008 - 19:41:27 EST


Andrew Morton wrote:
>> And mprintk the following.
>>
>> code:
>> DEFINE_MPRINTK(mp, 2 * 80);
>>
>> mprintk_set_header(&mp, KERN_INFO "ata%u.%2u: ", 1, 0);
>> mprintk_push(&mp, "ATA %d", 7);
>> mprintk_push(&mp, ", %u sectors\n", 1024);
>> mprintk(&mp, "everything seems dandy\n");
>>
>> output:
>> <6>ata1.00: ATA 7, 1024 sectors
>> <6>ata1.00 everything seems dandy
>
> And that looks like an awful lot of fuss. Is it really worth doing?

In the above example, s/mprintk(/mprintk_flush(/ and
s/mprintk_push(/mprintk(/

Can you please take a look at ata_eh_link_report() in
drivers/ata/libata-eh.c? Currently, it has some problems.

* All that it wants to do is printing some messages but it's awfully
complex with temp bufs and super-long printk calls containing optional %s's.

* status / error decode print outs are printed separately from cmd/res
making it difficult to tell how they are grouped. Putting them together
would require allocating another temp buf(s) and adding extra %s's to
cmd/res printout.

* For timeouts, result TF isn't available and thus res printout is
misleading. res shouldn't be printed after timeouts. This would
require allocating yest another temp buf and separating out res printing
into separate snprintf.

I was trying to do this and got fed up with all the tricks in the
function. The only sane way out is to build messages piece-by-piece
into a buffer and print it at once. The eh message is gigantic and I
needed to allocate the buffer elsewhere than stack.
ata_eh_link_report() fortunately has fixed place for that -
ap->sector_buf - but let's assume there was no such buffer for the
discussion. I'm still not too sure whether it's wise to use sector_buf
for message building anyway.

The only way is to malloc the buffer. Once the buffer is available,
building message using snprintf is a bit cumbersome but is okay. The
problem is that malloc can fail. To handle that case, we basically need
to do

if (buf)
printed += snprintf(buf + printed, len - printed, ...);
else
printk(...);

which is very cumbersome, so we need a wrapper around the above. As the
wrapper needs to control when the message goes out, a flush function is
necessary too. Combine those with overflow handling - mprintk.

Similar problem exists for ata_dev_configure() in
drivers/ata/libata-core.c although it's a bit better there. Please take
a look at the fifth patch. It doesn't remove a lot of lines but it
streamlines both functions significantly. For ata_dev_configure(),
message reporting becomes what the function does secondarily while
configuring the device, not something it's structured around.

Thanks.

--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/