lkml.org 
[lkml]   [2009]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 14/16] DRBD: tracepoint_probes
    Date
    There are a number of static tracepoints, mainly for debugging purposis.

    Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
    Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>

    ---
    diff --git a/drivers/block/drbd/drbd_tracing.h b/drivers/block/drbd/drbd_tracing.h
    new file mode 100644
    index 0000000..c4531a1
    --- /dev/null
    +++ b/drivers/block/drbd/drbd_tracing.h
    @@ -0,0 +1,87 @@
    +/*
    + drbd_tracing.h
    +
    + This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
    +
    + Copyright (C) 2003-2008, LINBIT Information Technologies GmbH.
    + Copyright (C) 2003-2008, Philipp Reisner <philipp.reisner@linbit.com>.
    + Copyright (C) 2003-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
    +
    + drbd is free software; you can redistribute it and/or modify
    + it under the terms of the GNU General Public License as published by
    + the Free Software Foundation; either version 2, or (at your option)
    + any later version.
    +
    + drbd is distributed in the hope that it will be useful,
    + but WITHOUT ANY WARRANTY; without even the implied warranty of
    + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + GNU General Public License for more details.
    +
    + You should have received a copy of the GNU General Public License
    + along with drbd; see the file COPYING. If not, write to
    + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    +
    + */
    +
    +#ifndef DRBD_TRACING_H
    +#define DRBD_TRACING_H
    +
    +#include <linux/tracepoint.h>
    +#include "drbd_int.h"
    +#include "drbd_req.h"
    +
    +enum {
    + TRACE_LVL_ALWAYS = 0,
    + TRACE_LVL_SUMMARY,
    + TRACE_LVL_METRICS,
    + TRACE_LVL_ALL,
    + TRACE_LVL_MAX
    +};
    +
    +DECLARE_TRACE(drbd_unplug,
    + TP_PROTO(struct drbd_conf *mdev, char* msg),
    + TP_ARGS(mdev, msg));
    +
    +DECLARE_TRACE(drbd_uuid,
    + TP_PROTO(struct drbd_conf *mdev, enum drbd_uuid_index index),
    + TP_ARGS(mdev, index));
    +
    +DECLARE_TRACE(drbd_ee,
    + TP_PROTO(struct drbd_conf *mdev, struct drbd_epoch_entry *e, char* msg),
    + TP_ARGS(mdev, e, msg));
    +
    +DECLARE_TRACE(drbd_md_io,
    + TP_PROTO(struct drbd_conf *mdev, int rw, struct drbd_backing_dev *bdev),
    + TP_ARGS(mdev, rw, bdev));
    +
    +DECLARE_TRACE(drbd_epoch,
    + TP_PROTO(struct drbd_conf *mdev, struct drbd_epoch *epoch, enum epoch_event ev),
    + TP_ARGS(mdev, epoch, ev));
    +
    +DECLARE_TRACE(drbd_netlink,
    + TP_PROTO(void *data, int is_req),
    + TP_ARGS(data, is_req));
    +
    +DECLARE_TRACE(drbd_actlog,
    + TP_PROTO(struct drbd_conf *mdev, sector_t sector, char* msg),
    + TP_ARGS(mdev, sector, msg));
    +
    +DECLARE_TRACE(drbd_bio,
    + TP_PROTO(struct drbd_conf *mdev, const char *pfx, struct bio *bio, int complete,
    + struct drbd_request *r),
    + TP_ARGS(mdev, pfx, bio, complete, r));
    +
    +DECLARE_TRACE(drbd_req,
    + TP_PROTO(struct drbd_request *req, enum drbd_req_event what, char *msg),
    + TP_ARGS(req, what, msg));
    +
    +DECLARE_TRACE(drbd_packet,
    + TP_PROTO(struct drbd_conf *mdev, struct socket *sock,
    + int recv, union p_polymorph *p, char *file, int line),
    + TP_ARGS(mdev, sock, recv, p, file, line));
    +
    +DECLARE_TRACE(_drbd_resync,
    + TP_PROTO(struct drbd_conf *mdev, int level, const char *fmt, va_list args),
    + TP_ARGS(mdev, level, fmt, args));
    +
    +#endif
    diff --git a/drivers/block/drbd/drbd_tracing.c b/drivers/block/drbd/drbd_tracing.c
    new file mode 100644
    index 0000000..2eff178
    --- /dev/null
    +++ b/drivers/block/drbd/drbd_tracing.c
    @@ -0,0 +1,762 @@
    +/*
    + drbd_tracing.c
    +
    + This file is part of DRBD by Philipp Reisner and Lars Ellenberg.
    +
    + Copyright (C) 2003-2008, LINBIT Information Technologies GmbH.
    + Copyright (C) 2003-2008, Philipp Reisner <philipp.reisner@linbit.com>.
    + Copyright (C) 2003-2008, Lars Ellenberg <lars.ellenberg@linbit.com>.
    +
    + drbd is free software; you can redistribute it and/or modify
    + it under the terms of the GNU General Public License as published by
    + the Free Software Foundation; either version 2, or (at your option)
    + any later version.
    +
    + drbd is distributed in the hope that it will be useful,
    + but WITHOUT ANY WARRANTY; without even the implied warranty of
    + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + GNU General Public License for more details.
    +
    + You should have received a copy of the GNU General Public License
    + along with drbd; see the file COPYING. If not, write to
    + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    +
    + */
    +
    +#include <linux/module.h>
    +#include <linux/drbd.h>
    +#include <linux/ctype.h>
    +#include <linux/marker.h>
    +#include "drbd_int.h"
    +#include "drbd_tracing.h"
    +#include <linux/drbd_tag_magic.h>
    +
    +MODULE_LICENSE("GPL");
    +MODULE_AUTHOR("Philipp Reisner, Lars Ellenberg");
    +MODULE_DESCRIPTION("DRBD tracepoint probes");
    +MODULE_PARM_DESC(trace_mask, "Bitmap of events to trace see drbd_tracing.c");
    +MODULE_PARM_DESC(trace_level, "Current tracing level (changeable in /sys)");
    +MODULE_PARM_DESC(trace_devs, "Bitmap of devices to trace (changeable in /sys)");
    +
    +unsigned int trace_mask = 0; /* Bitmap of events to trace */
    +int trace_level; /* Current trace level */
    +int trace_devs; /* Bitmap of devices to trace */
    +
    +module_param(trace_mask, uint, 0444);
    +module_param(trace_level, int, 0644);
    +module_param(trace_devs, int, 0644);
    +
    +enum {
    + TRACE_PACKET = 0x0001,
    + TRACE_RQ = 0x0002,
    + TRACE_UUID = 0x0004,
    + TRACE_RESYNC = 0x0008,
    + TRACE_EE = 0x0010,
    + TRACE_UNPLUG = 0x0020,
    + TRACE_NL = 0x0040,
    + TRACE_AL_EXT = 0x0080,
    + TRACE_INT_RQ = 0x0100,
    + TRACE_MD_IO = 0x0200,
    + TRACE_EPOCH = 0x0400,
    +};
    +
    +/* Buffer printing support
    + * dbg_print_flags: used for Flags arg to drbd_print_buffer
    + * - DBGPRINT_BUFFADDR; if set, each line starts with the
    + * virtual address of the line being output. If clear,
    + * each line starts with the offset from the beginning
    + * of the buffer. */
    +enum dbg_print_flags {
    + DBGPRINT_BUFFADDR = 0x0001,
    +};
    +
    +/* Macro stuff */
    +STATIC char *nl_packet_name(int packet_type)
    +{
    +/* Generate packet type strings */
    +#define NL_PACKET(name, number, fields) \
    + [P_ ## name] = # name,
    +#define NL_INTEGER Argh!
    +#define NL_BIT Argh!
    +#define NL_INT64 Argh!
    +#define NL_STRING Argh!
    +
    + static char *nl_tag_name[P_nl_after_last_packet] = {
    +#include "linux/drbd_nl.h"
    + };
    +
    + return (packet_type < sizeof(nl_tag_name)/sizeof(nl_tag_name[0])) ?
    + nl_tag_name[packet_type] : "*Unknown*";
    +}
    +/* /Macro stuff */
    +
    +static inline int is_mdev_trace(struct drbd_conf *mdev, unsigned int level)
    +{
    + return trace_level >= level && ((1 << mdev_to_minor(mdev)) & trace_devs);
    +}
    +
    +static void probe_drbd_unplug(struct drbd_conf *mdev, char *msg)
    +{
    + if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS))
    + return;
    +
    + dev_info(DEV, "%s, ap_bio_count=%d\n", msg, atomic_read(&mdev->ap_bio_cnt));
    +}
    +
    +static void probe_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index)
    +{
    + static char *uuid_str[UI_EXTENDED_SIZE] = {
    + [UI_CURRENT] = "CURRENT",
    + [UI_BITMAP] = "BITMAP",
    + [UI_HISTORY_START] = "HISTORY_START",
    + [UI_HISTORY_END] = "HISTORY_END",
    + [UI_SIZE] = "SIZE",
    + [UI_FLAGS] = "FLAGS",
    + };
    +
    + if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS))
    + return;
    +
    + if (index >= UI_EXTENDED_SIZE) {
    + dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n");
    + return;
    + }
    +
    + dev_info(DEV, " uuid[%s] now %016llX\n",
    + uuid_str[index],
    + (unsigned long long)mdev->bc->md.uuid[index]);
    +}
    +
    +static void probe_drbd_md_io(struct drbd_conf *mdev, int rw,
    + struct drbd_backing_dev *bdev)
    +{
    + if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS))
    + return;
    +
    + dev_info(DEV, " %s metadata superblock now\n",
    + rw == READ ? "Reading" : "Writing");
    +}
    +
    +static void probe_drbd_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e, char* msg)
    +{
    + if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS))
    + return;
    +
    + dev_info(DEV, "EE %s sec=%llus size=%u e=%p\n",
    + msg, (unsigned long long)e->sector, e->size, e);
    +}
    +
    +static void probe_drbd_epoch(struct drbd_conf *mdev, struct drbd_epoch *epoch,
    + enum epoch_event ev)
    +{
    + static char *epoch_event_str[] = {
    + [EV_PUT] = "put",
    + [EV_GOT_BARRIER_NR] = "got_barrier_nr",
    + [EV_BARRIER_DONE] = "barrier_done",
    + [EV_BECAME_LAST] = "became_last",
    + [EV_TRACE_FLUSH] = "issuing_flush",
    + [EV_TRACE_ADD_BARRIER] = "added_barrier",
    + [EV_TRACE_SETTING_BI] = "just set barrier_in_next_epoch",
    + };
    +
    + if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS))
    + return;
    +
    + ev &= ~EV_CLEANUP;
    +
    + switch (ev) {
    + case EV_TRACE_ALLOC:
    + dev_info(DEV, "Allocat epoch %p/xxxx { } nr_epochs=%d\n", epoch, mdev->epochs);
    + break;
    + case EV_TRACE_FREE:
    + dev_info(DEV, "Freeing epoch %p/%d { size=%d } nr_epochs=%d\n",
    + epoch, epoch->barrier_nr, atomic_read(&epoch->epoch_size),
    + mdev->epochs);
    + break;
    + default:
    + dev_info(DEV, "Update epoch %p/%d { size=%d active=%d %c%c n%c%c } ev=%s\n",
    + epoch, epoch->barrier_nr, atomic_read(&epoch->epoch_size),
    + atomic_read(&epoch->active),
    + test_bit(DE_HAVE_BARRIER_NUMBER, &epoch->flags) ? 'n' : '-',
    + test_bit(DE_CONTAINS_A_BARRIER, &epoch->flags) ? 'b' : '-',
    + test_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &epoch->flags) ? 'i' : '-',
    + test_bit(DE_BARRIER_IN_NEXT_EPOCH_DONE, &epoch->flags) ? 'd' : '-',
    + epoch_event_str[ev]);
    + }
    +}
    +
    +static void probe_drbd_netlink(void *data, int is_req)
    +{
    + struct cn_msg *msg = data;
    +
    + if (is_req) {
    + struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req *)msg->data;
    +
    + printk(KERN_INFO "drbd%d: "
    + "Netlink: << %s (%d) - seq: %x, ack: %x, len: %x\n",
    + nlp->drbd_minor,
    + nl_packet_name(nlp->packet_type),
    + nlp->packet_type,
    + msg->seq, msg->ack, msg->len);
    + } else {
    + struct drbd_nl_cfg_reply *nlp = (struct drbd_nl_cfg_reply *)msg->data;
    +
    + printk(KERN_INFO "drbd%d: "
    + "Netlink: >> %s (%d) - seq: %x, ack: %x, len: %x\n",
    + nlp->minor,
    + nlp->packet_type == P_nl_after_last_packet ?
    + "Empty-Reply" : nl_packet_name(nlp->packet_type),
    + nlp->packet_type,
    + msg->seq, msg->ack, msg->len);
    + }
    +}
    +
    +static void probe_drbd_actlog(struct drbd_conf *mdev, sector_t sector, char* msg)
    +{
    + unsigned int enr = (sector >> (AL_EXTENT_SIZE_B-9));
    +
    + if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS))
    + return;
    +
    + dev_info(DEV, "%s (sec=%llus, al_enr=%u, rs_enr=%d)\n",
    + msg, (unsigned long long) sector, enr,
    + (int)BM_SECT_TO_EXT(sector));
    +}
    +
    +/*
    + *
    + * drbd_print_buffer
    + *
    + * This routine dumps binary data to the debugging output. Can be
    + * called at interrupt level.
    + *
    + * Arguments:
    + *
    + * prefix - String is output at the beginning of each line output
    + * flags - Control operation of the routine. Currently defined
    + * Flags are:
    + * DBGPRINT_BUFFADDR; if set, each line starts with the
    + * virtual address of the line being outupt. If clear,
    + * each line starts with the offset from the beginning
    + * of the buffer.
    + * size - Indicates the size of each entry in the buffer. Supported
    + * values are sizeof(char), sizeof(short) and sizeof(int)
    + * buffer - Start address of buffer
    + * buffer_va - Virtual address of start of buffer (normally the same
    + * as Buffer, but having it separate allows it to hold
    + * file address for example)
    + * length - length of buffer
    + *
    + */
    +static void drbd_print_buffer(const char *prefix, unsigned int flags, int size,
    + const void *buffer, const void *buffer_va,
    + unsigned int length)
    +
    +#define LINE_SIZE 16
    +#define LINE_ENTRIES (int)(LINE_SIZE/size)
    +{
    + const unsigned char *pstart;
    + const unsigned char *pstart_va;
    + const unsigned char *pend;
    + char bytes_str[LINE_SIZE*3+8], ascii_str[LINE_SIZE+8];
    + char *pbytes = bytes_str, *pascii = ascii_str;
    + int offset = 0;
    + long sizemask;
    + int field_width;
    + int index;
    + const unsigned char *pend_str;
    + const unsigned char *p;
    + int count;
    +
    + /* verify size parameter */
    + if (size != sizeof(char) &&
    + size != sizeof(short) &&
    + size != sizeof(int)) {
    + printk(KERN_DEBUG "drbd_print_buffer: "
    + "ERROR invalid size %d\n", size);
    + return;
    + }
    +
    + sizemask = size-1;
    + field_width = size*2;
    +
    + /* Adjust start/end to be on appropriate boundary for size */
    + buffer = (const char *)((long)buffer & ~sizemask);
    + pend = (const unsigned char *)
    + (((long)buffer + length + sizemask) & ~sizemask);
    +
    + if (flags & DBGPRINT_BUFFADDR) {
    + /* Move start back to nearest multiple of line size,
    + * if printing address. This results in nicely formatted output
    + * with addresses being on line size (16) byte boundaries */
    + pstart = (const unsigned char *)((long)buffer & ~(LINE_SIZE-1));
    + } else {
    + pstart = (const unsigned char *)buffer;
    + }
    +
    + /* Set value of start VA to print if addresses asked for */
    + pstart_va = (const unsigned char *)buffer_va
    + - ((const unsigned char *)buffer-pstart);
    +
    + /* Calculate end position to nicely align right hand side */
    + pend_str = pstart + (((pend-pstart) + LINE_SIZE-1) & ~(LINE_SIZE-1));
    +
    + /* Init strings */
    + *pbytes = *pascii = '\0';
    +
    + /* Start at beginning of first line */
    + p = pstart;
    + count = 0;
    +
    + while (p < pend_str) {
    + if (p < (const unsigned char *)buffer || p >= pend) {
    + /* Before start of buffer or after end- print spaces */
    + pbytes += sprintf(pbytes, "%*c ", field_width, ' ');
    + pascii += sprintf(pascii, "%*c", size, ' ');
    + p += size;
    + } else {
    + /* Add hex and ascii to strings */
    + int val;
    + switch (size) {
    + default:
    + case 1:
    + val = *(unsigned char *)p;
    + break;
    + case 2:
    + val = *(unsigned short *)p;
    + break;
    + case 4:
    + val = *(unsigned int *)p;
    + break;
    + }
    +
    + pbytes += sprintf(pbytes, "%0*x ", field_width, val);
    +
    + for (index = size; index; index--) {
    + *pascii++ = isprint(*p) ? *p : '.';
    + p++;
    + }
    + }
    +
    + count++;
    +
    + if (count == LINE_ENTRIES || p >= pend_str) {
    + /* Null terminate and print record */
    + *pascii = '\0';
    + printk(KERN_DEBUG "%s%8.8lx: %*s|%*s|\n",
    + prefix,
    + (flags & DBGPRINT_BUFFADDR)
    + ? (long)pstart_va:(long)offset,
    + LINE_ENTRIES*(field_width+1), bytes_str,
    + LINE_SIZE, ascii_str);
    +
    + /* Move onto next line */
    + pstart_va += (p-pstart);
    + pstart = p;
    + count = 0;
    + offset += LINE_SIZE;
    +
    + /* Re-init strings */
    + pbytes = bytes_str;
    + pascii = ascii_str;
    + *pbytes = *pascii = '\0';
    + }
    + }
    +}
    +
    +static void probe_drbd_resync(struct drbd_conf *mdev, int level, const char *fmt, va_list args)
    +{
    + char str[256];
    +
    + if (!is_mdev_trace(mdev, level))
    + return;
    +
    + if (vsnprintf(str, 256, fmt, args) >= 256)
    + str[255] = 0;
    +
    + printk(KERN_INFO "%s %s: %s", dev_driver_string(disk_to_dev(mdev->vdisk)),
    + dev_name(disk_to_dev(mdev->vdisk)), str);
    +}
    +
    +static void probe_drbd_bio(struct drbd_conf *mdev, const char *pfx, struct bio *bio, int complete,
    + struct drbd_request *r)
    +{
    +#ifdef CONFIG_LBD
    +#define SECTOR_FORMAT "%Lx"
    +#else
    +#define SECTOR_FORMAT "%lx"
    +#endif
    +#define SECTOR_SHIFT 9
    +
    + unsigned long lowaddr = (unsigned long)(bio->bi_sector << SECTOR_SHIFT);
    + char *faddr = (char *)(lowaddr);
    + char rb[sizeof(void *)*2+6] = { 0, };
    + struct bio_vec *bvec;
    + int segno;
    +
    + const int rw = bio->bi_rw;
    + const int biorw = (rw & (RW_MASK|RWA_MASK));
    + const int biobarrier = (rw & (1<<BIO_RW_BARRIER));
    + const int biosync = (rw & ((1<<BIO_RW_UNPLUG) | (1<<BIO_RW_SYNCIO)));
    +
    + if (!is_mdev_trace(mdev, TRACE_LVL_ALWAYS))
    + return;
    +
    + if (r)
    + sprintf(rb, "Req:%p ", r);
    +
    + dev_info(DEV, "%s %s:%s%s%s Bio:%p %s- %soffset " SECTOR_FORMAT ", size %x\n",
    + complete ? "<<<" : ">>>",
    + pfx,
    + biorw == WRITE ? "Write" : "Read",
    + biobarrier ? " : B" : "",
    + biosync ? " : S" : "",
    + bio,
    + rb,
    + complete ? (bio_flagged(bio, BIO_UPTODATE) ? "Success, " : "Failed, ") : "",
    + bio->bi_sector << SECTOR_SHIFT,
    + bio->bi_size);
    +
    + if (trace_level >= TRACE_LVL_METRICS &&
    + ((biorw == WRITE) ^ complete)) {
    + printk(KERN_DEBUG " ind page offset length\n");
    + __bio_for_each_segment(bvec, bio, segno, 0) {
    + printk(KERN_DEBUG " [%d] %p %8.8x %8.8x\n", segno,
    + bvec->bv_page, bvec->bv_offset, bvec->bv_len);
    +
    + if (trace_level >= TRACE_LVL_ALL) {
    + char *bvec_buf;
    + unsigned long flags;
    +
    + bvec_buf = bvec_kmap_irq(bvec, &flags);
    +
    + drbd_print_buffer(" ", DBGPRINT_BUFFADDR, 1,
    + bvec_buf,
    + faddr,
    + (bvec->bv_len <= 0x80)
    + ? bvec->bv_len : 0x80);
    +
    + bvec_kunmap_irq(bvec_buf, &flags);
    +
    + if (bvec->bv_len > 0x40)
    + printk(KERN_DEBUG " ....\n");
    +
    + faddr += bvec->bv_len;
    + }
    + }
    + }
    +}
    +
    +static void probe_drbd_req(struct drbd_request *req, enum drbd_req_event what, char *msg)
    +{
    + static const char *rq_event_names[] = {
    + [created] = "created",
    + [to_be_send] = "to_be_send",
    + [to_be_submitted] = "to_be_submitted",
    + [queue_for_net_write] = "queue_for_net_write",
    + [queue_for_net_read] = "queue_for_net_read",
    + [send_canceled] = "send_canceled",
    + [send_failed] = "send_failed",
    + [handed_over_to_network] = "handed_over_to_network",
    + [connection_lost_while_pending] =
    + "connection_lost_while_pending",
    + [recv_acked_by_peer] = "recv_acked_by_peer",
    + [write_acked_by_peer] = "write_acked_by_peer",
    + [neg_acked] = "neg_acked",
    + [conflict_discarded_by_peer] = "conflict_discarded_by_peer",
    + [barrier_acked] = "barrier_acked",
    + [data_received] = "data_received",
    + [read_completed_with_error] = "read_completed_with_error",
    + [write_completed_with_error] = "write_completed_with_error",
    + [completed_ok] = "completed_ok",
    + };
    +
    + struct drbd_conf *mdev = req->mdev;
    +
    + const int rw = (req->master_bio == NULL ||
    + bio_data_dir(req->master_bio) == WRITE) ?
    + 'W' : 'R';
    + const unsigned long s = req->rq_state;
    +
    + if (what != nothing) {
    + dev_info(DEV, "_req_mod(%p %c ,%s)\n", req, rw, rq_event_names[what]);
    + } else {
    + dev_info(DEV, "%s %p %c L%c%c%cN%c%c%c%c%c %u (%llus +%u) %s\n",
    + msg, req, rw,
    + s & RQ_LOCAL_PENDING ? 'p' : '-',
    + s & RQ_LOCAL_COMPLETED ? 'c' : '-',
    + s & RQ_LOCAL_OK ? 'o' : '-',
    + s & RQ_NET_PENDING ? 'p' : '-',
    + s & RQ_NET_QUEUED ? 'q' : '-',
    + s & RQ_NET_SENT ? 's' : '-',
    + s & RQ_NET_DONE ? 'd' : '-',
    + s & RQ_NET_OK ? 'o' : '-',
    + req->epoch,
    + (unsigned long long)req->sector,
    + req->size,
    + conns_to_name(mdev->state.conn));
    + }
    +}
    +
    +
    +#define peers_to_name roles_to_name
    +#define pdsks_to_name disks_to_name
    +
    +#define PSM(A) \
    +do { \
    + if (mask.A) { \
    + int i = snprintf(p, len, " " #A "( %s )", \
    + A##s_to_name(val.A)); \
    + if (i >= len) \
    + return op; \
    + p += i; \
    + len -= i; \
    + } \
    +} while (0)
    +
    +STATIC char *dump_st(char *p, int len, union drbd_state mask, union drbd_state val)
    +{
    + char *op = p;
    + *p = '\0';
    + PSM(role);
    + PSM(peer);
    + PSM(conn);
    + PSM(disk);
    + PSM(pdsk);
    +
    + return op;
    +}
    +
    +#define INFOP(fmt, args...) \
    +do { \
    + if (trace_level >= TRACE_LVL_ALL) { \
    + dev_info(DEV, "%s:%d: %s [%d] %s %s " fmt , \
    + file, line, current->comm, current->pid, \
    + sockname, recv ? "<<<" : ">>>" , \
    + ## args); \
    + } else { \
    + dev_info(DEV, "%s %s " fmt, sockname, \
    + recv ? "<<<" : ">>>" , \
    + ## args); \
    + } \
    +} while (0)
    +
    +STATIC char *_dump_block_id(u64 block_id, char *buff)
    +{
    + if (is_syncer_block_id(block_id))
    + strcpy(buff, "SyncerId");
    + else
    + sprintf(buff, "%llx", (unsigned long long)block_id);
    +
    + return buff;
    +}
    +
    +static void probe_drbd_packet(struct drbd_conf *mdev, struct socket *sock,
    + int recv, union p_polymorph *p, char *file, int line)
    +{
    + char *sockname = sock == mdev->meta.socket ? "meta" : "data";
    + int cmd = (recv == 2) ? p->header.command : be16_to_cpu(p->header.command);
    + char tmp[300];
    + union drbd_state m, v;
    +
    + switch (cmd) {
    + case P_HAND_SHAKE:
    + INFOP("%s (protocol %u-%u)\n", cmdname(cmd),
    + be32_to_cpu(p->handshake.protocol_min),
    + be32_to_cpu(p->handshake.protocol_max));
    + break;
    +
    + case P_BITMAP: /* don't report this */
    + case P_COMPRESSED_BITMAP: /* don't report this */
    + break;
    +
    + case P_DATA:
    + INFOP("%s (sector %llus, id %s, seq %u, f %x)\n", cmdname(cmd),
    + (unsigned long long)be64_to_cpu(p->data.sector),
    + _dump_block_id(p->data.block_id, tmp),
    + be32_to_cpu(p->data.seq_num),
    + be32_to_cpu(p->data.dp_flags)
    + );
    + break;
    +
    + case P_DATA_REPLY:
    + case P_RS_DATA_REPLY:
    + INFOP("%s (sector %llus, id %s)\n", cmdname(cmd),
    + (unsigned long long)be64_to_cpu(p->data.sector),
    + _dump_block_id(p->data.block_id, tmp)
    + );
    + break;
    +
    + case P_RECV_ACK:
    + case P_WRITE_ACK:
    + case P_RS_WRITE_ACK:
    + case P_DISCARD_ACK:
    + case P_NEG_ACK:
    + case P_NEG_RS_DREPLY:
    + INFOP("%s (sector %llus, size %u, id %s, seq %u)\n",
    + cmdname(cmd),
    + (long long)be64_to_cpu(p->block_ack.sector),
    + be32_to_cpu(p->block_ack.blksize),
    + _dump_block_id(p->block_ack.block_id, tmp),
    + be32_to_cpu(p->block_ack.seq_num)
    + );
    + break;
    +
    + case P_DATA_REQUEST:
    + case P_RS_DATA_REQUEST:
    + INFOP("%s (sector %llus, size %u, id %s)\n", cmdname(cmd),
    + (long long)be64_to_cpu(p->block_req.sector),
    + be32_to_cpu(p->block_req.blksize),
    + _dump_block_id(p->block_req.block_id, tmp)
    + );
    + break;
    +
    + case P_BARRIER:
    + case P_BARRIER_ACK:
    + INFOP("%s (barrier %u)\n", cmdname(cmd), p->barrier.barrier);
    + break;
    +
    + case P_SYNC_PARAM:
    + case P_SYNC_PARAM89:
    + INFOP("%s (rate %u, verify-alg \"%.64s\", csums-alg \"%.64s\")\n",
    + cmdname(cmd), be32_to_cpu(p->rs_param_89.rate),
    + p->rs_param_89.verify_alg, p->rs_param_89.csums_alg);
    + break;
    +
    + case P_UUIDS:
    + INFOP("%s Curr:%016llX, Bitmap:%016llX, "
    + "HisSt:%016llX, HisEnd:%016llX\n",
    + cmdname(cmd),
    + (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_CURRENT]),
    + (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_BITMAP]),
    + (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_HISTORY_START]),
    + (unsigned long long)be64_to_cpu(p->uuids.uuid[UI_HISTORY_END]));
    + break;
    +
    + case P_SIZES:
    + INFOP("%s (d %lluMiB, u %lluMiB, c %lldMiB, "
    + "max bio %x, q order %x)\n",
    + cmdname(cmd),
    + (long long)(be64_to_cpu(p->sizes.d_size)>>(20-9)),
    + (long long)(be64_to_cpu(p->sizes.u_size)>>(20-9)),
    + (long long)(be64_to_cpu(p->sizes.c_size)>>(20-9)),
    + be32_to_cpu(p->sizes.max_segment_size),
    + be32_to_cpu(p->sizes.queue_order_type));
    + break;
    +
    + case P_STATE:
    + v.i = be32_to_cpu(p->state.state);
    + m.i = 0xffffffff;
    + dump_st(tmp, sizeof(tmp), m, v);
    + INFOP("%s (s %x {%s})\n", cmdname(cmd), v.i, tmp);
    + break;
    +
    + case P_STATE_CHG_REQ:
    + m.i = be32_to_cpu(p->req_state.mask);
    + v.i = be32_to_cpu(p->req_state.val);
    + dump_st(tmp, sizeof(tmp), m, v);
    + INFOP("%s (m %x v %x {%s})\n", cmdname(cmd), m.i, v.i, tmp);
    + break;
    +
    + case P_STATE_CHG_REPLY:
    + INFOP("%s (ret %x)\n", cmdname(cmd),
    + be32_to_cpu(p->req_state_reply.retcode));
    + break;
    +
    + case P_PING:
    + case P_PING_ACK:
    + /*
    + * Dont trace pings at summary level
    + */
    + if (trace_level < TRACE_LVL_ALL)
    + break;
    + /* fall through... */
    + default:
    + INFOP("%s (%u)\n", cmdname(cmd), cmd);
    + break;
    + }
    +}
    +
    +
    +static int __init drbd_trace_init(void)
    +{
    + int ret;
    +
    + if (trace_mask & TRACE_UNPLUG) {
    + ret = register_trace_drbd_unplug(probe_drbd_unplug);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_UUID) {
    + ret = register_trace_drbd_uuid(probe_drbd_uuid);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_EE) {
    + ret = register_trace_drbd_ee(probe_drbd_ee);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_PACKET) {
    + ret = register_trace_drbd_packet(probe_drbd_packet);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_MD_IO) {
    + ret = register_trace_drbd_md_io(probe_drbd_md_io);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_EPOCH) {
    + ret = register_trace_drbd_epoch(probe_drbd_epoch);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_NL) {
    + ret = register_trace_drbd_netlink(probe_drbd_netlink);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_AL_EXT) {
    + ret = register_trace_drbd_actlog(probe_drbd_actlog);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_RQ) {
    + ret = register_trace_drbd_bio(probe_drbd_bio);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_INT_RQ) {
    + ret = register_trace_drbd_req(probe_drbd_req);
    + WARN_ON(ret);
    + }
    + if (trace_mask & TRACE_RESYNC) {
    + ret = register_trace__drbd_resync(probe_drbd_resync);
    + WARN_ON(ret);
    + }
    + return 0;
    +}
    +
    +module_init(drbd_trace_init);
    +
    +static void __exit drbd_trace_exit(void)
    +{
    + if (trace_mask & TRACE_UNPLUG)
    + unregister_trace_drbd_unplug(probe_drbd_unplug);
    + if (trace_mask & TRACE_UUID)
    + unregister_trace_drbd_uuid(probe_drbd_uuid);
    + if (trace_mask & TRACE_EE)
    + unregister_trace_drbd_ee(probe_drbd_ee);
    + if (trace_mask & TRACE_PACKET)
    + unregister_trace_drbd_packet(probe_drbd_packet);
    + if (trace_mask & TRACE_MD_IO)
    + unregister_trace_drbd_md_io(probe_drbd_md_io);
    + if (trace_mask & TRACE_EPOCH)
    + unregister_trace_drbd_epoch(probe_drbd_epoch);
    + if (trace_mask & TRACE_NL)
    + unregister_trace_drbd_netlink(probe_drbd_netlink);
    + if (trace_mask & TRACE_AL_EXT)
    + unregister_trace_drbd_actlog(probe_drbd_actlog);
    + if (trace_mask & TRACE_RQ)
    + unregister_trace_drbd_bio(probe_drbd_bio);
    + if (trace_mask & TRACE_INT_RQ)
    + unregister_trace_drbd_req(probe_drbd_req);
    + if (trace_mask & TRACE_RESYNC)
    + unregister_trace__drbd_resync(probe_drbd_resync);
    +
    + tracepoint_synchronize_unregister();
    +}
    +
    +module_exit(drbd_trace_exit);

    \
     
     \ /
      Last update: 2009-04-30 13:33    [W:0.173 / U:0.380 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site