qemu/hw/virtio-9p-debug.c
Venkateswararao Jujjuri (JV) 0db09dd2ab Flush the debug message out to the log file.
This patch fluesh the debug messages to the log file  at the end of each
debug message.

Changes from V1:
Used fflush instead fseek for the flush.

Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-06-22 15:15:30 -05:00

487 lines
13 KiB
C

/*
* Virtio 9p PDU debug
*
* Copyright IBM, Corp. 2010
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#include "virtio.h"
#include "pc.h"
#include "virtio-9p.h"
#include "virtio-9p-debug.h"
#define BUG_ON(cond) assert(!(cond))
static FILE *llogfile;
static struct iovec *get_sg(V9fsPDU *pdu, int rx)
{
if (rx) {
return pdu->elem.in_sg;
}
return pdu->elem.out_sg;
}
static int get_sg_count(V9fsPDU *pdu, int rx)
{
if (rx) {
return pdu->elem.in_num;
}
return pdu->elem.out_num;
}
static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
const char *name)
{
size_t copied;
int count = get_sg_count(pdu, rx);
size_t offset = *offsetp;
struct iovec *sg = get_sg(pdu, rx);
int8_t value;
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
BUG_ON(copied != sizeof(value));
offset += sizeof(value);
fprintf(llogfile, "%s=0x%x", name, value);
*offsetp = offset;
}
static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
const char *name)
{
size_t copied;
int count = get_sg_count(pdu, rx);
struct iovec *sg = get_sg(pdu, rx);
size_t offset = *offsetp;
int16_t value;
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
BUG_ON(copied != sizeof(value));
offset += sizeof(value);
fprintf(llogfile, "%s=0x%x", name, value);
*offsetp = offset;
}
static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
const char *name)
{
size_t copied;
int count = get_sg_count(pdu, rx);
struct iovec *sg = get_sg(pdu, rx);
size_t offset = *offsetp;
int32_t value;
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
BUG_ON(copied != sizeof(value));
offset += sizeof(value);
fprintf(llogfile, "%s=0x%x", name, value);
*offsetp = offset;
}
static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
const char *name)
{
size_t copied;
int count = get_sg_count(pdu, rx);
struct iovec *sg = get_sg(pdu, rx);
size_t offset = *offsetp;
int64_t value;
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
BUG_ON(copied != sizeof(value));
offset += sizeof(value);
fprintf(llogfile, "%s=0x%" PRIx64, name, value);
*offsetp = offset;
}
static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
{
int sg_count = get_sg_count(pdu, rx);
struct iovec *sg = get_sg(pdu, rx);
size_t offset = *offsetp;
uint16_t tmp_size, size;
size_t result;
size_t copied = 0;
int i = 0;
/* get the size */
copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size));
BUG_ON(copied != sizeof(tmp_size));
size = le16_to_cpupu(&tmp_size);
offset += copied;
fprintf(llogfile, "%s=", name);
for (i = 0; size && i < sg_count; i++) {
size_t len;
if (offset >= sg[i].iov_len) {
/* skip this sg */
offset -= sg[i].iov_len;
continue;
} else {
len = MIN(sg[i].iov_len - offset, size);
result = fwrite(sg[i].iov_base + offset, 1, len, llogfile);
BUG_ON(result != len);
size -= len;
copied += len;
if (size) {
offset = 0;
continue;
}
}
}
*offsetp += copied;
}
static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
{
fprintf(llogfile, "%s={", name);
pprint_int8(pdu, rx, offsetp, "type");
pprint_int32(pdu, rx, offsetp, ", version");
pprint_int64(pdu, rx, offsetp, ", path");
fprintf(llogfile, "}");
}
static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
{
fprintf(llogfile, "%s={", name);
pprint_int16(pdu, rx, offsetp, "size");
pprint_int16(pdu, rx, offsetp, ", type");
pprint_int32(pdu, rx, offsetp, ", dev");
pprint_qid(pdu, rx, offsetp, ", qid");
pprint_int32(pdu, rx, offsetp, ", mode");
pprint_int32(pdu, rx, offsetp, ", atime");
pprint_int32(pdu, rx, offsetp, ", mtime");
pprint_int64(pdu, rx, offsetp, ", length");
pprint_str(pdu, rx, offsetp, ", name");
pprint_str(pdu, rx, offsetp, ", uid");
pprint_str(pdu, rx, offsetp, ", gid");
pprint_str(pdu, rx, offsetp, ", muid");
if (dotu) {
pprint_str(pdu, rx, offsetp, ", extension");
pprint_int32(pdu, rx, offsetp, ", uid");
pprint_int32(pdu, rx, offsetp, ", gid");
pprint_int32(pdu, rx, offsetp, ", muid");
}
fprintf(llogfile, "}");
}
static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
{
int sg_count = get_sg_count(pdu, rx);
struct iovec *sg = get_sg(pdu, rx);
size_t offset = *offsetp;
uint16_t tmp_count, count, i;
size_t copied = 0;
fprintf(llogfile, "%s={", name);
/* Get the count */
copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
BUG_ON(copied != sizeof(tmp_count));
count = le16_to_cpupu(&tmp_count);
offset += copied;
for (i = 0; i < count; i++) {
char str[512];
if (i) {
fprintf(llogfile, ", ");
}
snprintf(str, sizeof(str), "[%d]", i);
pprint_str(pdu, rx, &offset, str);
}
fprintf(llogfile, "}");
*offsetp = offset;
}
static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
{
int sg_count = get_sg_count(pdu, rx);
struct iovec *sg = get_sg(pdu, rx);
size_t offset = *offsetp;
uint16_t tmp_count, count, i;
size_t copied = 0;
fprintf(llogfile, "%s={", name);
copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
BUG_ON(copied != sizeof(tmp_count));
count = le16_to_cpupu(&tmp_count);
offset += copied;
for (i = 0; i < count; i++) {
char str[512];
if (i) {
fprintf(llogfile, ", ");
}
snprintf(str, sizeof(str), "[%d]", i);
pprint_qid(pdu, rx, &offset, str);
}
fprintf(llogfile, "}");
*offsetp = offset;
}
static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
{
struct iovec *sg = get_sg(pdu, rx);
unsigned int count;
int i;
if (rx) {
count = pdu->elem.in_num;
} else {
count = pdu->elem.out_num;
}
fprintf(llogfile, "%s={", name);
for (i = 0; i < count; i++) {
if (i) {
fprintf(llogfile, ", ");
}
fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
}
fprintf(llogfile, "}");
}
/* FIXME: read from a directory fid returns serialized stat_t's */
#ifdef DEBUG_DATA
static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
{
struct iovec *sg = get_sg(pdu, rx);
size_t offset = *offsetp;
unsigned int count;
int32_t size;
int total, i, j;
ssize_t len;
if (rx) {
count = pdu->elem.in_num;
} else
count = pdu->elem.out_num;
}
BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
memcpy(&size, sg[0].iov_base + offset, sizeof(size));
offset += sizeof(size);
fprintf(llogfile, "size: %x\n", size);
sg[0].iov_base += 11; /* skip header */
sg[0].iov_len -= 11;
total = 0;
for (i = 0; i < count; i++) {
total += sg[i].iov_len;
if (total >= size) {
/* trim sg list so writev does the right thing */
sg[i].iov_len -= (total - size);
i++;
break;
}
}
fprintf(llogfile, "%s={\"", name);
fflush(llogfile);
for (j = 0; j < i; j++) {
if (j) {
fprintf(llogfile, "\", \"");
fflush(llogfile);
}
do {
len = writev(fileno(llogfile), &sg[j], 1);
} while (len == -1 && errno == EINTR);
fprintf(llogfile, "len == %ld: %m\n", len);
BUG_ON(len != sg[j].iov_len);
}
fprintf(llogfile, "\"}");
sg[0].iov_base -= 11;
sg[0].iov_len += 11;
}
#endif
void pprint_pdu(V9fsPDU *pdu)
{
size_t offset = 7;
if (llogfile == NULL) {
llogfile = fopen("/tmp/pdu.log", "w");
}
switch (pdu->id) {
case P9_TVERSION:
fprintf(llogfile, "TVERSION: (");
pprint_int32(pdu, 0, &offset, "msize");
pprint_str(pdu, 0, &offset, ", version");
break;
case P9_RVERSION:
fprintf(llogfile, "RVERSION: (");
pprint_int32(pdu, 1, &offset, "msize");
pprint_str(pdu, 1, &offset, ", version");
break;
case P9_TAUTH:
fprintf(llogfile, "TAUTH: (");
pprint_int32(pdu, 0, &offset, "afid");
pprint_str(pdu, 0, &offset, ", uname");
pprint_str(pdu, 0, &offset, ", aname");
if (dotu) {
pprint_int32(pdu, 0, &offset, ", n_uname");
}
break;
case P9_RAUTH:
fprintf(llogfile, "RAUTH: (");
pprint_qid(pdu, 1, &offset, "qid");
break;
case P9_TATTACH:
fprintf(llogfile, "TATTACH: (");
pprint_int32(pdu, 0, &offset, "fid");
pprint_int32(pdu, 0, &offset, ", afid");
pprint_str(pdu, 0, &offset, ", uname");
pprint_str(pdu, 0, &offset, ", aname");
if (dotu) {
pprint_int32(pdu, 0, &offset, ", n_uname");
}
break;
case P9_RATTACH:
fprintf(llogfile, "RATTACH: (");
pprint_qid(pdu, 1, &offset, "qid");
break;
case P9_TERROR:
fprintf(llogfile, "TERROR: (");
break;
case P9_RERROR:
fprintf(llogfile, "RERROR: (");
pprint_str(pdu, 1, &offset, "ename");
if (dotu) {
pprint_int32(pdu, 1, &offset, ", ecode");
}
break;
case P9_TFLUSH:
fprintf(llogfile, "TFLUSH: (");
pprint_int16(pdu, 0, &offset, "oldtag");
break;
case P9_RFLUSH:
fprintf(llogfile, "RFLUSH: (");
break;
case P9_TWALK:
fprintf(llogfile, "TWALK: (");
pprint_int32(pdu, 0, &offset, "fid");
pprint_int32(pdu, 0, &offset, ", newfid");
pprint_strs(pdu, 0, &offset, ", wnames");
break;
case P9_RWALK:
fprintf(llogfile, "RWALK: (");
pprint_qids(pdu, 1, &offset, "wqids");
break;
case P9_TOPEN:
fprintf(llogfile, "TOPEN: (");
pprint_int32(pdu, 0, &offset, "fid");
pprint_int8(pdu, 0, &offset, ", mode");
break;
case P9_ROPEN:
fprintf(llogfile, "ROPEN: (");
pprint_qid(pdu, 1, &offset, "qid");
pprint_int32(pdu, 1, &offset, ", iounit");
break;
case P9_TCREATE:
fprintf(llogfile, "TCREATE: (");
pprint_int32(pdu, 0, &offset, "fid");
pprint_str(pdu, 0, &offset, ", name");
pprint_int32(pdu, 0, &offset, ", perm");
pprint_int8(pdu, 0, &offset, ", mode");
if (dotu) {
pprint_str(pdu, 0, &offset, ", extension");
}
break;
case P9_RCREATE:
fprintf(llogfile, "RCREATE: (");
pprint_qid(pdu, 1, &offset, "qid");
pprint_int32(pdu, 1, &offset, ", iounit");
break;
case P9_TREAD:
fprintf(llogfile, "TREAD: (");
pprint_int32(pdu, 0, &offset, "fid");
pprint_int64(pdu, 0, &offset, ", offset");
pprint_int32(pdu, 0, &offset, ", count");
pprint_sg(pdu, 0, &offset, ", sg");
break;
case P9_RREAD:
fprintf(llogfile, "RREAD: (");
pprint_int32(pdu, 1, &offset, "count");
pprint_sg(pdu, 1, &offset, ", sg");
offset = 7;
#ifdef DEBUG_DATA
pprint_data(pdu, 1, &offset, ", data");
#endif
break;
case P9_TWRITE:
fprintf(llogfile, "TWRITE: (");
pprint_int32(pdu, 0, &offset, "fid");
pprint_int64(pdu, 0, &offset, ", offset");
pprint_int32(pdu, 0, &offset, ", count");
break;
case P9_RWRITE:
fprintf(llogfile, "RWRITE: (");
pprint_int32(pdu, 1, &offset, "count");
break;
case P9_TCLUNK:
fprintf(llogfile, "TCLUNK: (");
pprint_int32(pdu, 0, &offset, "fid");
break;
case P9_RCLUNK:
fprintf(llogfile, "RCLUNK: (");
break;
case P9_TREMOVE:
fprintf(llogfile, "TREMOVE: (");
pprint_int32(pdu, 0, &offset, "fid");
break;
case P9_RREMOVE:
fprintf(llogfile, "RREMOVE: (");
break;
case P9_TSTAT:
fprintf(llogfile, "TSTAT: (");
pprint_int32(pdu, 0, &offset, "fid");
break;
case P9_RSTAT:
fprintf(llogfile, "RSTAT: (");
offset += 2; /* ignored */
pprint_stat(pdu, 1, &offset, "stat");
break;
case P9_TWSTAT:
fprintf(llogfile, "TWSTAT: (");
pprint_int32(pdu, 0, &offset, "fid");
offset += 2; /* ignored */
pprint_stat(pdu, 0, &offset, ", stat");
break;
case P9_RWSTAT:
fprintf(llogfile, "RWSTAT: (");
break;
default:
fprintf(llogfile, "unknown(%d): (", pdu->id);
break;
}
fprintf(llogfile, ")\n");
/* Flush the log message out */
fflush(llogfile);
}