diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2009-04-29 17:45:27 +0200 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2009-07-29 10:26:26 +0200 |
commit | 95eaef1cbc63f73df4ff8559dd66b1d29b462535 (patch) | |
tree | a667d9b136ca600b975b2699c8cff6fbe703dbd8 /drivers/block | |
parent | c733785235d1cf1e37e70446182a21c06e69d519 (diff) |
Replaced our own tracing stuff with Linux's tracepoints
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/Kconfig | 10 | ||||
-rw-r--r-- | drivers/block/drbd/Makefile | 3 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 111 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 5 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 130 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 483 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 85 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_proc.c | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 101 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 89 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 1 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_tracing.c | 762 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_tracing.h | 87 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 25 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_wrappers.h | 5 |
15 files changed, 1006 insertions, 895 deletions
diff --git a/drivers/block/drbd/Kconfig b/drivers/block/drbd/Kconfig index c5847ddb24b3..7ad8c2a3c2f3 100644 --- a/drivers/block/drbd/Kconfig +++ b/drivers/block/drbd/Kconfig @@ -35,3 +35,13 @@ config BLK_DEV_DRBD See also: http://www.drbd.org/, http://www.linux-ha.org If unsure, say N. + +config DRBD_TRACE + tristate "DRBD tracing" + depends on BLK_DEV_DRBD + select TRACEPOINTS + help + + Say Y here if you want to be able to trace various events in DRBD. + + If unsure, say N. diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile index 7237c339f7da..f0f805cd2051 100644 --- a/drivers/block/drbd/Makefile +++ b/drivers/block/drbd/Makefile @@ -2,4 +2,7 @@ drbd-y := drbd_buildtag.o drbd_bitmap.o drbd_proc.o drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o drbd-y += lru_cache.o drbd_main.o drbd_strings.o drbd_nl.o +drbd_trace-y := drbd_tracing.o drbd_strings.o + obj-$(CONFIG_BLK_DEV_DRBD) += drbd.o +obj-$(CONFIG_DRBD_TRACE) += drbd_trace.o diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index fbbddd3d7f31..c894b4fa6af0 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -26,6 +26,7 @@ #include <linux/slab.h> #include <linux/drbd.h> #include "drbd_int.h" +#include "drbd_tracing.h" #include "drbd_wrappers.h" /* I do not believe that all storage medias can guarantee atomic @@ -65,6 +66,17 @@ struct drbd_atodb_wait { int w_al_write_transaction(struct drbd_conf *, struct drbd_work *, int); +/* The actual tracepoint needs to have constant number of known arguments... + */ +void trace_drbd_resync(struct drbd_conf *mdev, int level, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + trace__drbd_resync(mdev, level, fmt, ap); + va_end(ap); +} + STATIC int _drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, struct page *page, sector_t sector, @@ -93,7 +105,7 @@ STATIC int _drbd_md_sync_page_io(struct drbd_conf *mdev, bio->bi_end_io = drbd_md_io_complete; bio->bi_rw = rw; - dump_internal_bio("Md", mdev, bio, 0); + trace_drbd_bio(mdev, "Md", bio, 0, NULL); if (FAULT_ACTIVE(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) bio_endio(bio, -EIO); @@ -223,11 +235,7 @@ void drbd_al_begin_io(struct drbd_conf *mdev, sector_t sector) D_ASSERT(atomic_read(&mdev->local_cnt) > 0); - MTRACE(TRACE_TYPE_AL_EXTS, TRACE_LVL_METRICS, - dev_info(DEV, "al_begin_io( sec=%llus (al_enr=%u) (rs_enr=%d) )\n", - (unsigned long long) sector, enr, - (int)BM_SECT_TO_EXT(sector)); - ); + trace_drbd_actlog(mdev, sector, "al_begin_io"); wait_event(mdev->al_wait, (al_ext = _al_get(mdev, enr))); @@ -260,11 +268,7 @@ void drbd_al_complete_io(struct drbd_conf *mdev, sector_t sector) struct lc_element *extent; unsigned long flags; - MTRACE(TRACE_TYPE_AL_EXTS, TRACE_LVL_METRICS, - dev_info(DEV, "al_complete_io( sec=%llus (al_enr=%u) (rs_enr=%d) )\n", - (unsigned long long) sector, enr, - (int)BM_SECT_TO_EXT(sector)); - ); + trace_drbd_actlog(mdev, sector, "al_complete_io"); spin_lock_irqsave(&mdev->al_lock, flags); @@ -763,11 +767,6 @@ static inline int _try_lc_del(struct drbd_conf *mdev, struct lc_element *al_ext) lc_del(mdev->act_log, al_ext); spin_unlock_irq(&mdev->al_lock); - MTRACE(TRACE_TYPE_AL_EXTS, TRACE_LVL_METRICS, - if (unlikely(!rv)) - dev_info(DEV, "Waiting for extent in drbd_al_shrink()\n"); - ); - return rv; } @@ -953,10 +952,9 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, ebnr = BM_SECT_TO_BIT(esector - (BM_SECT_PER_BIT-1)); sbnr = BM_SECT_TO_BIT(sector + BM_SECT_PER_BIT-1); - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_METRICS, - dev_info(DEV, "drbd_set_in_sync: sector=%llus size=%u sbnr=%lu ebnr=%lu\n", - (unsigned long long)sector, size, sbnr, ebnr); - ); + trace_drbd_resync(mdev, TRACE_LVL_METRICS, + "drbd_set_in_sync: sector=%llus size=%u sbnr=%lu ebnr=%lu\n", + (unsigned long long)sector, size, sbnr, ebnr); if (sbnr > ebnr) return; @@ -1032,11 +1030,9 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, sbnr = BM_SECT_TO_BIT(sector); ebnr = BM_SECT_TO_BIT(esector); - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_METRICS, - dev_info(DEV, "drbd_set_out_of_sync: sector=%llus size=%u " - "sbnr=%lu ebnr=%lu\n", - (unsigned long long)sector, size, sbnr, ebnr); - ); + trace_drbd_resync(mdev, TRACE_LVL_METRICS, + "drbd_set_out_of_sync: sector=%llus size=%u sbnr=%lu ebnr=%lu\n", + (unsigned long long)sector, size, sbnr, ebnr); /* ok, (capacity & 7) != 0 sometimes, but who cares... * we count rs_{total,left} in bits, not sectors. */ @@ -1133,10 +1129,9 @@ int drbd_rs_begin_io(struct drbd_conf *mdev, sector_t sector) struct bm_extent *bm_ext; int i, sig; - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "drbd_rs_begin_io: sector=%llus (rs_end=%d)\n", - (unsigned long long)sector, enr); - ); + trace_drbd_resync(mdev, TRACE_LVL_ALL, + "drbd_rs_begin_io: sector=%llus (rs_end=%d)\n", + (unsigned long long)sector, enr); sig = wait_event_interruptible(mdev->al_wait, (bm_ext = _bme_get(mdev, enr))); @@ -1183,10 +1178,8 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector) struct bm_extent *bm_ext; int i; - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "drbd_try_rs_begin_io: sector=%llus\n", - (unsigned long long)sector); - ); + trace_drbd_resync(mdev, TRACE_LVL_ALL, "drbd_try_rs_begin_io: sector=%llus\n", + (unsigned long long)sector); spin_lock_irq(&mdev->al_lock); if (mdev->resync_wenr != LC_FREE && mdev->resync_wenr != enr) { @@ -1203,10 +1196,11 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector) * the lc_put here... * we also have to wake_up */ - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "dropping %u, aparently got 'synced' " - "by application io\n", mdev->resync_wenr); - ); + + trace_drbd_resync(mdev, TRACE_LVL_ALL, + "dropping %u, aparently got 'synced' by application io\n", + mdev->resync_wenr); + bm_ext = (struct bm_extent *) lc_find(mdev->resync, mdev->resync_wenr); if (bm_ext) { @@ -1232,18 +1226,18 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector) * but then could not set BME_LOCKED, * so we tried again. * drop the extra reference. */ - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "dropping extra reference on %u\n", enr); - ); + trace_drbd_resync(mdev, TRACE_LVL_ALL, + "dropping extra reference on %u\n", enr); + bm_ext->lce.refcnt--; D_ASSERT(bm_ext->lce.refcnt > 0); } goto check_al; } else { if (mdev->resync_locked > mdev->resync->nr_elements-3) { - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "resync_locked = %u!\n", mdev->resync_locked); - ); + trace_drbd_resync(mdev, TRACE_LVL_ALL, + "resync_locked = %u!\n", mdev->resync_locked); + goto try_again; } bm_ext = (struct bm_extent *)lc_get(mdev->resync, enr); @@ -1268,9 +1262,8 @@ int drbd_try_rs_begin_io(struct drbd_conf *mdev, sector_t sector) goto check_al; } check_al: - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "checking al for %u\n", enr); - ); + trace_drbd_resync(mdev, TRACE_LVL_ALL, "checking al for %u\n", enr); + for (i = 0; i < AL_EXT_PER_BM_SECT; i++) { if (unlikely(al_enr+i == mdev->act_log->new_number)) goto try_again; @@ -1284,9 +1277,7 @@ proceed: return 0; try_again: - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "need to try again for %u\n", enr); - ); + trace_drbd_resync(mdev, TRACE_LVL_ALL, "need to try again for %u\n", enr); if (bm_ext) mdev->resync_wenr = enr; spin_unlock_irq(&mdev->al_lock); @@ -1299,10 +1290,9 @@ void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector) struct bm_extent *bm_ext; unsigned long flags; - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_ALL, - dev_info(DEV, "drbd_rs_complete_io: sector=%llus (rs_enr=%d)\n", - (long long)sector, enr); - ); + trace_drbd_resync(mdev, TRACE_LVL_ALL, + "drbd_rs_complete_io: sector=%llus (rs_enr=%d)\n", + (long long)sector, enr); spin_lock_irqsave(&mdev->al_lock, flags); bm_ext = (struct bm_extent *) lc_find(mdev->resync, enr); @@ -1336,9 +1326,7 @@ void drbd_rs_complete_io(struct drbd_conf *mdev, sector_t sector) */ void drbd_rs_cancel_all(struct drbd_conf *mdev) { - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_METRICS, - dev_info(DEV, "drbd_rs_cancel_all\n"); - ); + trace_drbd_resync(mdev, TRACE_LVL_METRICS, "drbd_rs_cancel_all\n"); spin_lock_irq(&mdev->al_lock); @@ -1363,9 +1351,7 @@ int drbd_rs_del_all(struct drbd_conf *mdev) struct bm_extent *bm_ext; int i; - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_METRICS, - dev_info(DEV, "drbd_rs_del_all\n"); - ); + trace_drbd_resync(mdev, TRACE_LVL_METRICS, "drbd_rs_del_all\n"); spin_lock_irq(&mdev->al_lock); @@ -1417,10 +1403,9 @@ void drbd_rs_failed_io(struct drbd_conf *mdev, sector_t sector, int size) sector_t esector, nr_sectors; int wake_up = 0; - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_SUMMARY, - dev_info(DEV, "drbd_rs_failed_io: sector=%llus, size=%u\n", - (unsigned long long)sector, size); - ); + trace_drbd_resync(mdev, TRACE_LVL_SUMMARY, + "drbd_rs_failed_io: sector=%llus, size=%u\n", + (unsigned long long)sector, size); if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) { dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n", diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 0614f2c96f15..c160f7ab9e01 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -842,11 +842,6 @@ STATIC int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local) drbd_blk_run_queue(bdev_get_queue(mdev->bc->md_bdev)); wait_event(b->bm_io_wait, atomic_read(&b->bm_async_io) == 0); - MTRACE(TRACE_TYPE_MD_IO, TRACE_LVL_SUMMARY, - dev_info(DEV, "%s of bitmap took %lu jiffies\n", - rw == READ ? "reading" : "writing", jiffies - now); - ); - if (test_bit(BM_MD_IO_ERROR, &b->bm_flags)) { dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n"); drbd_chk_io_error(mdev, 1, TRUE); diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index ba43fa57b750..175de11d31e4 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -151,6 +151,8 @@ enum { DRBD_FAULT_MAX, }; +extern void trace_drbd_resync(struct drbd_conf *mdev, int level, const char *fmt, ...); + #ifdef DRBD_ENABLE_FAULTS extern unsigned int _drbd_insert_fault(struct drbd_conf *mdev, unsigned int type); @@ -713,6 +715,19 @@ enum { DE_IS_FINISHING, }; +enum epoch_event { + EV_PUT, + EV_GOT_BARRIER_NR, + EV_BARRIER_DONE, + EV_BECAME_LAST, + EV_TRACE_FLUSH, /* TRACE_ are not real events, only used for tracing */ + EV_TRACE_ADD_BARRIER, /* Doing the first write as a barrier write */ + EV_TRACE_SETTING_BI, /* Barrier is expressed with the first write of the next epoch */ + EV_TRACE_ALLOC, + EV_TRACE_FREE, + EV_CLEANUP = 32, /* used as flag */ +}; + struct drbd_epoch_entry { struct drbd_work w; struct drbd_conf *mdev; @@ -1350,117 +1365,7 @@ extern rwlock_t global_state_lock; extern struct drbd_conf *drbd_new_device(unsigned int minor); extern void drbd_free_mdev(struct drbd_conf *mdev); -/* Dynamic tracing framework */ -#ifdef ENABLE_DYNAMIC_TRACE - extern int proc_details; -extern int trace_type; -extern int trace_devs; -extern int trace_level; - -enum { - TRACE_LVL_ALWAYS = 0, - TRACE_LVL_SUMMARY, - TRACE_LVL_METRICS, - TRACE_LVL_ALL, - TRACE_LVL_MAX -}; - -enum { - TRACE_TYPE_PACKET = 0x00000001, - TRACE_TYPE_RQ = 0x00000002, - TRACE_TYPE_UUID = 0x00000004, - TRACE_TYPE_RESYNC = 0x00000008, - TRACE_TYPE_EE = 0x00000010, - TRACE_TYPE_UNPLUG = 0x00000020, - TRACE_TYPE_NL = 0x00000040, - TRACE_TYPE_AL_EXTS = 0x00000080, - TRACE_TYPE_INT_RQ = 0x00000100, - TRACE_TYPE_MD_IO = 0x00000200, - TRACE_TYPE_EPOCHS = 0x00000400, -}; - -static inline int -is_trace(unsigned int type, unsigned int level) { - return (trace_level >= level) && (type & trace_type); -} -static inline int -is_mdev_trace(struct drbd_conf *mdev, unsigned int type, unsigned int level) { - return is_trace(type, level) && - ((1 << mdev_to_minor(mdev)) & trace_devs); -} - -#define MTRACE(type, lvl, code...) \ -do { \ - if (unlikely(is_mdev_trace(mdev, type, lvl))) { \ - code \ - } \ -} while (0) - -#define TRACE(type, lvl, code...) \ -do { \ - if (unlikely(is_trace(type, lvl))) { \ - code \ - } \ -} while (0) - -/* 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, -}; - -extern void drbd_print_uuid(struct drbd_conf *mdev, unsigned int idx); - -extern void drbd_print_buffer(const char *prefix, unsigned int flags, int size, - const void *buffer, const void *buffer_va, - unsigned int length); - -/* Bio printing support */ -extern void _dump_bio(const char *pfx, struct drbd_conf *mdev, struct bio *bio, int complete, struct drbd_request *r); - -static inline void dump_bio(struct drbd_conf *mdev, - struct bio *bio, int complete, struct drbd_request *r) -{ - MTRACE(TRACE_TYPE_RQ, TRACE_LVL_SUMMARY, - _dump_bio("Rq", mdev, bio, complete, r); - ); -} - -static inline void dump_internal_bio(const char *pfx, struct drbd_conf *mdev, struct bio *bio, int complete) -{ - MTRACE(TRACE_TYPE_INT_RQ, TRACE_LVL_SUMMARY, - _dump_bio(pfx, mdev, bio, complete, NULL); - ); -} - -/* Packet dumping support */ -extern void _dump_packet(struct drbd_conf *mdev, struct socket *sock, - int recv, union p_polymorph *p, - char *file, int line); - -static inline void -dump_packet(struct drbd_conf *mdev, struct socket *sock, - int recv, union p_polymorph *p, char *file, int line) -{ - MTRACE(TRACE_TYPE_PACKET, TRACE_LVL_SUMMARY, - _dump_packet(mdev, sock, recv, p, file, line); - ); -} - -#else - -#define MTRACE(ignored...) ((void)0) -#define TRACE(ignored...) ((void)0) - -#define dump_bio(ignored...) ((void)0) -#define dump_internal_bio(ignored...) ((void)0) -#define dump_packet(ignored...) ((void)0) -#endif /* drbd_req */ extern int drbd_make_request_26(struct request_queue *q, struct bio *bio); @@ -2237,11 +2142,6 @@ static inline void dec_ap_bio(struct drbd_conf *mdev) static inline void drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val) { mdev->ed_uuid = val; - - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_METRICS, - dev_info(DEV, " exposed data uuid now %016llX\n", - (unsigned long long)val); - ); } static inline int seq_cmp(u32 a, u32 b) diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 79cb0183f817..4a2593ce1d37 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -53,6 +53,7 @@ #include <linux/drbd.h> #include <linux/drbd_limits.h> #include "drbd_int.h" +#include "drbd_tracing.h" #include "drbd_req.h" /* only for _req_mod in tl_release and tl_clear */ #include "drbd_vli.h" @@ -79,6 +80,18 @@ STATIC int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused); STATIC void md_sync_timer_fn(unsigned long data); STATIC int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused); +DEFINE_TRACE(drbd_unplug); +DEFINE_TRACE(drbd_uuid); +DEFINE_TRACE(drbd_ee); +DEFINE_TRACE(drbd_packet); +DEFINE_TRACE(drbd_md_io); +DEFINE_TRACE(drbd_epoch); +DEFINE_TRACE(drbd_netlink); +DEFINE_TRACE(drbd_actlog); +DEFINE_TRACE(drbd_bio); +DEFINE_TRACE(_drbd_resync); +DEFINE_TRACE(drbd_req); + MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, " "Lars Ellenberg <lars@linbit.com>"); MODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION); @@ -95,6 +108,7 @@ module_param(minor_count, uint, 0444); module_param(disable_sendpage, bool, 0644); module_param(allow_oos, bool, 0); module_param(cn_idx, uint, 0444); +module_param(proc_details, int, 0644); #ifdef DRBD_ENABLE_FAULTS int enable_faults; @@ -116,19 +130,8 @@ unsigned int minor_count = 32; int disable_sendpage; int allow_oos; unsigned int cn_idx = CN_IDX_DRBD; - -#ifdef ENABLE_DYNAMIC_TRACE -int trace_type; /* UI_BITMAP of trace types to enable */ -int trace_level; /* UI_CURRENT trace level */ -int trace_devs; /* UI_BITMAP of devices to trace */ int proc_details; /* Detail level in proc drbd*/ -module_param(trace_level, int, 0644); -module_param(trace_type, int, 0644); -module_param(trace_devs, int, 0644); -module_param(proc_details, int, 0644); -#endif - /* Module parameter for setting the user mode helper program * to run. Default is /sbin/drbdadm */ char usermode_helper[80] = "/sbin/drbdadm"; @@ -1458,7 +1461,7 @@ int _drbd_send_cmd(struct drbd_conf *mdev, struct socket *sock, h->command = cpu_to_be16(cmd); h->length = cpu_to_be16(size-sizeof(struct p_header)); - dump_packet(mdev, sock, 0, (void *)h, __FILE__, __LINE__); + trace_drbd_packet(mdev, sock, 0, (void *)h, __FILE__, __LINE__); sent = drbd_send(mdev, sock, h, size, msg_flags); ok = (sent == size); @@ -1510,7 +1513,7 @@ int drbd_send_cmd2(struct drbd_conf *mdev, enum drbd_packets cmd, char *data, if (!drbd_get_data_sock(mdev)) return 0; - dump_packet(mdev, mdev->data.socket, 0, (void *)&h, __FILE__, __LINE__); + trace_drbd_packet(mdev, mdev->data.socket, 0, (void *)&h, __FILE__, __LINE__); ok = (sizeof(h) == drbd_send(mdev, mdev->data.socket, &h, sizeof(h), 0)); @@ -2227,7 +2230,7 @@ int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req) dp_flags |= DP_MAY_SET_IN_SYNC; p.dp_flags = cpu_to_be32(dp_flags); - dump_packet(mdev, mdev->data.socket, 0, (void *)&p, __FILE__, __LINE__); + trace_drbd_packet(mdev, mdev->data.socket, 0, (void *)&p, __FILE__, __LINE__); set_bit(UNPLUG_REMOTE, &mdev->flags); ok = (sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE)); @@ -2278,7 +2281,7 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, if (!drbd_get_data_sock(mdev)) return 0; - dump_packet(mdev, mdev->data.socket, 0, (void *)&p, __FILE__, __LINE__); + trace_drbd_packet(mdev, mdev->data.socket, 0, (void *)&p, __FILE__, __LINE__); ok = sizeof(p) == drbd_send(mdev, mdev->data.socket, &p, sizeof(p), MSG_MORE); if (ok && dgs) { @@ -2414,10 +2417,7 @@ STATIC void drbd_unplug_fn(struct request_queue *q) { struct drbd_conf *mdev = q->queuedata; - MTRACE(TRACE_TYPE_UNPLUG, TRACE_LVL_SUMMARY, - dev_info(DEV, "got unplugged ap_bio_count=%d\n", - atomic_read(&mdev->ap_bio_cnt)); - ); + trace_drbd_unplug(mdev, "got unplugged"); /* unplug FIRST */ spin_lock_irq(q->queue_lock); @@ -3098,9 +3098,7 @@ void drbd_md_sync(struct drbd_conf *mdev) if (!inc_local_if_state(mdev, D_FAILED)) return; - MTRACE(TRACE_TYPE_MD_IO, TRACE_LVL_SUMMARY, - dev_info(DEV, "Writing meta data super block now.\n"); - ); + trace_drbd_md_io(mdev, WRITE, mdev->bc); mutex_lock(&mdev->md_io_mutex); buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page); @@ -3156,6 +3154,8 @@ int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) if (!inc_local_if_state(mdev, D_ATTACHING)) return ERR_IO_MD_DISK; + trace_drbd_md_io(mdev, READ, bdev); + mutex_lock(&mdev->md_io_mutex); buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page); @@ -3235,9 +3235,7 @@ STATIC void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local) for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) { mdev->bc->md.uuid[i+1] = mdev->bc->md.uuid[i]; - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_ALL, - drbd_print_uuid(mdev, i+1); - ); + trace_drbd_uuid(mdev, i+1); } } @@ -3253,11 +3251,7 @@ void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) } mdev->bc->md.uuid[idx] = val; - - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_SUMMARY, - drbd_print_uuid(mdev, idx); - ); - + trace_drbd_uuid(mdev, idx); drbd_md_mark_dirty(mdev); } @@ -3267,9 +3261,7 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) if (mdev->bc->md.uuid[idx]) { drbd_uuid_move_history(mdev); mdev->bc->md.uuid[UI_HISTORY_START] = mdev->bc->md.uuid[idx]; - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_METRICS, - drbd_print_uuid(mdev, UI_HISTORY_START); - ); + trace_drbd_uuid(mdev, UI_HISTORY_START); } _drbd_uuid_set(mdev, idx, val); } @@ -3286,9 +3278,7 @@ void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local) dev_info(DEV, "Creating new current UUID\n"); D_ASSERT(mdev->bc->md.uuid[UI_BITMAP] == 0); mdev->bc->md.uuid[UI_BITMAP] = mdev->bc->md.uuid[UI_CURRENT]; - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_METRICS, - drbd_print_uuid(mdev, UI_BITMAP); - ); + trace_drbd_uuid(mdev, UI_BITMAP); get_random_bytes(&val, sizeof(u64)); _drbd_uuid_set(mdev, UI_CURRENT, val); @@ -3303,11 +3293,8 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local) drbd_uuid_move_history(mdev); mdev->bc->md.uuid[UI_HISTORY_START] = mdev->bc->md.uuid[UI_BITMAP]; mdev->bc->md.uuid[UI_BITMAP] = 0; - - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_METRICS, - drbd_print_uuid(mdev, UI_HISTORY_START); - drbd_print_uuid(mdev, UI_BITMAP); - ); + trace_drbd_uuid(mdev, UI_HISTORY_START); + trace_drbd_uuid(mdev, UI_BITMAP); } else { if (mdev->bc->md.uuid[UI_BITMAP]) dev_warn(DEV, "bm UUID already set"); @@ -3315,9 +3302,7 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local) mdev->bc->md.uuid[UI_BITMAP] = val; mdev->bc->md.uuid[UI_BITMAP] &= ~((u64)1); - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_METRICS, - drbd_print_uuid(mdev, UI_BITMAP); - ); + trace_drbd_uuid(mdev, UI_BITMAP); } drbd_md_mark_dirty(mdev); } @@ -3553,415 +3538,5 @@ _drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) } #endif -#ifdef ENABLE_DYNAMIC_TRACE - -STATIC char *_drbd_uuid_str(unsigned int idx) -{ - static char *uuid_str[] = { - "Current", - "Bitmap", - "History_start", - "History_end", - "UUID_SIZE", - "UUID_FLAGS", - }; - - return (idx < UI_EXTENDED_SIZE) ? uuid_str[idx] : "*Unknown UUID index*"; -} - -/* Pretty print a UUID value */ -void drbd_print_uuid(struct drbd_conf *mdev, unsigned int idx) __must_hold(local) -{ - dev_info(DEV, " uuid[%s] now %016llX\n", - _drbd_uuid_str(idx), (unsigned long long)mdev->bc->md.uuid[idx]); -} - - -/* - * - * 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 - * - */ -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'; - } - } -} - -#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; -} - -void -_dump_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; - } -} - -/* Debug routine to dump info about bio */ - -void _dump_bio(const char *pfx, struct drbd_conf *mdev, 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 (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 ? (drbd_bio_uptodate(bio) ? "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; - } - } - } -} -#endif - module_init(drbd_init) module_exit(drbd_cleanup) diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index c72c5adbbfd6..c388478a0188 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -34,8 +34,8 @@ #include <linux/drbd.h> #include <linux/blkpg.h> #include <linux/cpumask.h> - #include "drbd_int.h" +#include "drbd_tracing.h" #include "drbd_wrappers.h" #include <linux/drbd_tag_magic.h> #include <linux/drbd_limits.h> @@ -124,51 +124,6 @@ name ## _to_tags(struct drbd_conf *mdev, \ void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name); void drbd_nl_send_reply(struct cn_msg *, int); -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*"; -} - -STATIC void nl_trace_packet(void *data) -{ - struct cn_msg *req = data; - struct drbd_nl_cfg_req *nlp = (struct drbd_nl_cfg_req *)req->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, - req->seq, req->ack, req->len); -} - -STATIC void nl_trace_reply(void *data) -{ - struct cn_msg *req = data; - struct drbd_nl_cfg_reply *nlp = (struct drbd_nl_cfg_reply *)req->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, - req->seq, req->ack, req->len); -} - int drbd_khelper(struct drbd_conf *mdev, char *cmd) { char mb[12]; @@ -711,15 +666,6 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu max_seg_s = min(b->max_sectors * b->hardsect_size, max_seg_s); - MTRACE(TRACE_TYPE_RQ, TRACE_LVL_SUMMARY, - DUMPI(b->max_sectors); - DUMPI(b->max_phys_segments); - DUMPI(b->max_hw_segments); - DUMPI(b->max_segment_size); - DUMPI(b->hardsect_size); - DUMPI(b->seg_boundary_mask); - ); - q->max_sectors = max_seg_s >> 9; if (max_segments) { q->max_phys_segments = max_segments; @@ -733,15 +679,6 @@ void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __mu q->seg_boundary_mask = PAGE_SIZE-1; blk_queue_stack_limits(q, b); - MTRACE(TRACE_TYPE_RQ, TRACE_LVL_SUMMARY, - DUMPI(q->max_sectors); - DUMPI(q->max_phys_segments); - DUMPI(q->max_hw_segments); - DUMPI(q->max_segment_size); - DUMPI(q->hardsect_size); - DUMPI(q->seg_boundary_mask); - ); - if (b->merge_bvec_fn) dev_warn(DEV, "Backing device's merge_bvec_fn() = %p\n", b->merge_bvec_fn); @@ -2055,7 +1992,7 @@ STATIC void drbd_connector_callback(void *data) goto fail; } - TRACE(TRACE_TYPE_NL, TRACE_LVL_SUMMARY, nl_trace_packet(data);); + trace_drbd_netlink(data, 1); if (nlp->packet_type >= P_nl_after_last_packet) { retcode = ERR_PACKET_NR; @@ -2093,8 +2030,7 @@ STATIC void drbd_connector_callback(void *data) cn_reply->len = sizeof(struct drbd_nl_cfg_reply) + rr; cn_reply->flags = 0; - TRACE(TRACE_TYPE_NL, TRACE_LVL_SUMMARY, nl_trace_reply(cn_reply);); - + trace_drbd_netlink(cn_reply, 0); rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); if (rr && rr != -ESRCH) printk(KERN_INFO "drbd: cn_netlink_send()=%d\n", rr); @@ -2193,8 +2129,7 @@ void drbd_bcast_state(struct drbd_conf *mdev, union drbd_state state) reply->minor = mdev_to_minor(mdev); reply->ret_code = NO_ERROR; - TRACE(TRACE_TYPE_NL, TRACE_LVL_SUMMARY, nl_trace_reply(cn_reply);); - + trace_drbd_netlink(cn_reply, 0); cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); } @@ -2232,8 +2167,7 @@ void drbd_bcast_ev_helper(struct drbd_conf *mdev, char *helper_name) reply->minor = mdev_to_minor(mdev); reply->ret_code = NO_ERROR; - TRACE(TRACE_TYPE_NL, TRACE_LVL_SUMMARY, nl_trace_reply(cn_reply);); - + trace_drbd_netlink(cn_reply, 0); cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); } @@ -2302,8 +2236,7 @@ void drbd_bcast_ee(struct drbd_conf *mdev, reply->minor = mdev_to_minor(mdev); reply->ret_code = NO_ERROR; - TRACE(TRACE_TYPE_NL, TRACE_LVL_SUMMARY, nl_trace_reply(cn_reply);); - + trace_drbd_netlink(cn_reply, 0); cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); kfree(cn_reply); } @@ -2346,8 +2279,7 @@ void drbd_bcast_sync_progress(struct drbd_conf *mdev) reply->minor = mdev_to_minor(mdev); reply->ret_code = NO_ERROR; - TRACE(TRACE_TYPE_NL, TRACE_LVL_SUMMARY, nl_trace_reply(cn_reply);); - + trace_drbd_netlink(cn_reply, 0); cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); } @@ -2401,8 +2333,7 @@ void drbd_nl_send_reply(struct cn_msg *req, int ret_code) reply->minor = ((struct drbd_nl_cfg_req *)req->data)->drbd_minor; reply->ret_code = ret_code; - TRACE(TRACE_TYPE_NL, TRACE_LVL_SUMMARY, nl_trace_reply(cn_reply);); - + trace_drbd_netlink(cn_reply, 0); rr = cn_netlink_send(cn_reply, CN_IDX_DRBD, GFP_KERNEL); if (rr && rr != -ESRCH) printk(KERN_INFO "drbd: cn_netlink_send()=%d\n", rr); diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 76b512180606..7de68d9d6aba 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -135,7 +135,6 @@ STATIC void drbd_syncer_progress(struct drbd_conf *mdev, struct seq_file *seq) seq_printf(seq, " K/sec\n"); } -#ifdef ENABLE_DYNAMIC_TRACE STATIC void resync_dump_detail(struct seq_file *seq, struct lc_element *e) { struct bm_extent *bme = (struct bm_extent *)e; @@ -145,7 +144,6 @@ STATIC void resync_dump_detail(struct seq_file *seq, struct lc_element *e) bme->flags & BME_LOCKED ? "LOCKED" : "------" ); } -#endif STATIC int drbd_seq_show(struct seq_file *seq, void *v) { @@ -245,7 +243,6 @@ STATIC int drbd_seq_show(struct seq_file *seq, void *v) mdev->rs_total - mdev->ov_left, mdev->rs_total); -#ifdef ENABLE_DYNAMIC_TRACE if (proc_details >= 1 && inc_local_if_state(mdev, D_FAILED)) { lc_printf_stats(seq, mdev->resync); lc_printf_stats(seq, mdev->act_log); @@ -258,7 +255,6 @@ STATIC int drbd_seq_show(struct seq_file *seq, void *v) resync_dump_detail); } } -#endif } return 0; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 078ce728a2fc..077480fe6923 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -49,6 +49,7 @@ #include <linux/scatterlist.h> #include <linux/drbd.h> #include "drbd_int.h" +#include "drbd_tracing.h" #include "drbd_req.h" #include "drbd_vli.h" @@ -58,14 +59,6 @@ struct flush_work { struct drbd_epoch *epoch; }; -enum epoch_event { - EV_PUT, - EV_GOT_BARRIER_NR, - EV_BARRIER_DONE, - EV_BECAME_LAST, - EV_CLEANUP = 32, /* used as flag */ -}; - enum finish_epoch { FE_STILL_LIVE, FE_DESTROYED, @@ -284,10 +277,7 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev, e->epoch = NULL; e->flags = 0; - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "allocated EE sec=%llus size=%u ee=%p\n", - (unsigned long long)sector, data_size, e); - ); + trace_drbd_ee(mdev, e, "allocated"); return e; @@ -308,10 +298,7 @@ void drbd_free_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e) struct bio_vec *bvec; int i; - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "Free EE sec=%llus size=%u ee=%p\n", - (unsigned long long)e->sector, e->size, e); - ); + trace_drbd_ee(mdev, e, "freed"); __bio_for_each_segment(bvec, bio, i, 0) { drbd_pp_free(mdev, bvec->bv_page); @@ -390,10 +377,7 @@ STATIC int drbd_process_done_ee(struct drbd_conf *mdev) * all ignore the last argument. */ list_for_each_entry_safe(e, t, &work_list, w.list) { - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "Process EE on done_ee sec=%llus size=%u ee=%p\n", - (unsigned long long)e->sector, e->size, e); - ); + trace_drbd_ee(mdev, e, "process_done_ee"); /* list_del not necessary, next/prev members not touched */ if (e->w.cb(mdev, &e->w, 0) == 0) ok = 0; @@ -998,13 +982,6 @@ STATIC enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev, int schedule_flush = 0; enum finish_epoch rv = FE_STILL_LIVE; - 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", - }; - spin_lock(&mdev->epoch_lock); do { next_epoch = NULL; @@ -1034,15 +1011,7 @@ STATIC enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev, break; } - MTRACE(TRACE_TYPE_EPOCHS, TRACE_LVL_ALL, - dev_info(DEV, "Update epoch %p/%d { size=%d active=%d %c%c n%c%c } ev=%s\n", - epoch, epoch->barrier_nr, 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]); - ); + trace_drbd_epoch(mdev, epoch, ev); if (epoch_size != 0 && atomic_read(&epoch->active) == 0 && @@ -1075,10 +1044,7 @@ STATIC enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev, list_del(&epoch->list); ev = EV_BECAME_LAST | (ev & EV_CLEANUP); mdev->epochs--; - MTRACE(TRACE_TYPE_EPOCHS, TRACE_LVL_SUMMARY, - dev_info(DEV, "Freeing epoch %p/%d { size=%d } nr_epochs=%d\n", - epoch, epoch->barrier_nr, epoch_size, mdev->epochs); - ); + trace_drbd_epoch(mdev, epoch, EV_TRACE_FREE); kfree(epoch); if (rv == FE_STILL_LIVE) @@ -1104,10 +1070,7 @@ STATIC enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev, struct flush_work *fw; fw = kmalloc(sizeof(*fw), GFP_ATOMIC); if (fw) { - MTRACE(TRACE_TYPE_EPOCHS, TRACE_LVL_METRICS, - dev_info(DEV, "Schedul flush %p/%d { size=%d } nr_epochs=%d\n", - epoch, epoch->barrier_nr, epoch_size, mdev->epochs); - ); + trace_drbd_epoch(mdev, epoch, EV_TRACE_FLUSH); fw->w.cb = w_flush; fw->epoch = epoch; drbd_queue_work(&mdev->data.work, &fw->w); @@ -1273,9 +1236,7 @@ STATIC int receive_Barrier(struct drbd_conf *mdev, struct p_header *h) list_add(&epoch->list, &mdev->current_epoch->list); mdev->current_epoch = epoch; mdev->epochs++; - MTRACE(TRACE_TYPE_EPOCHS, TRACE_LVL_METRICS, - dev_info(DEV, "Allocat epoch %p/xxxx { } nr_epochs=%d\n", epoch, mdev->epochs); - ); + trace_drbd_epoch(mdev, epoch, EV_TRACE_ALLOC); } else { /* The current_epoch got recycled while we allocated this one... */ kfree(epoch); @@ -1485,11 +1446,8 @@ STATIC int recv_resync_read(struct drbd_conf *mdev, sector_t sector, int data_si list_add(&e->w.list, &mdev->sync_ee); spin_unlock_irq(&mdev->req_lock); - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "submit EE (RS)WRITE sec=%llus size=%u ee=%p\n", - (unsigned long long)e->sector, e->size, e); - ); - dump_internal_bio("Sec", mdev, e->private_bio, 0); + trace_drbd_ee(mdev, e, "submitting for (rs)write"); + trace_drbd_bio(mdev, "Sec", e->private_bio, 0, NULL); drbd_generic_make_request(mdev, DRBD_FAULT_RS_WR, e->private_bio); /* accounting done in endio */ @@ -1752,23 +1710,17 @@ STATIC int receive_Data(struct drbd_conf *mdev, struct p_header *h) a Barrier. */ epoch = list_entry(e->epoch->list.prev, struct drbd_epoch, list); if (epoch == e->epoch) { - MTRACE(TRACE_TYPE_EPOCHS, TRACE_LVL_METRICS, - dev_info(DEV, "Add barrier %p/%d\n", - epoch, epoch->barrier_nr); - ); set_bit(DE_CONTAINS_A_BARRIER, &e->epoch->flags); + trace_drbd_epoch(mdev, e->epoch, EV_TRACE_ADD_BARRIER); rw |= (1<<BIO_RW_BARRIER); e->flags |= EE_IS_BARRIER; } else { if (atomic_read(&epoch->epoch_size) > 1 || !test_bit(DE_CONTAINS_A_BARRIER, &epoch->flags)) { - MTRACE(TRACE_TYPE_EPOCHS, TRACE_LVL_METRICS, - dev_info(DEV, "Add barrier %p/%d, setting bi in %p/%d\n", - e->epoch, e->epoch->barrier_nr, - epoch, epoch->barrier_nr); - ); set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &epoch->flags); + trace_drbd_epoch(mdev, epoch, EV_TRACE_SETTING_BI); set_bit(DE_CONTAINS_A_BARRIER, &e->epoch->flags); + trace_drbd_epoch(mdev, e->epoch, EV_TRACE_ADD_BARRIER); rw |= (1<<BIO_RW_BARRIER); e->flags |= EE_IS_BARRIER; } @@ -1940,13 +1892,9 @@ STATIC int receive_Data(struct drbd_conf *mdev, struct p_header *h) drbd_al_begin_io(mdev, e->sector); } - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "submit EE (DATA)WRITE sec=%llus size=%u ee=%p\n", - (unsigned long long)e->sector, e->size, e); - ); - e->private_bio->bi_rw = rw; - dump_internal_bio("Sec", mdev, e->private_bio, 0); + trace_drbd_ee(mdev, e, "submitting for (data)write"); + trace_drbd_bio(mdev, "Sec", e->private_bio, 0, NULL); drbd_generic_make_request(mdev, DRBD_FAULT_DT_WR, e->private_bio); /* accounting done in endio */ @@ -2104,12 +2052,8 @@ STATIC int receive_DataRequest(struct drbd_conf *mdev, struct p_header *h) inc_unacked(mdev); - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "submit EE READ sec=%llus size=%u ee=%p\n", - (unsigned long long)e->sector, e->size, e); - ); - - dump_internal_bio("Sec", mdev, e->private_bio, 0); + trace_drbd_ee(mdev, e, "submitting for read"); + trace_drbd_bio(mdev, "Sec", e->private_bio, 0, NULL); drbd_generic_make_request(mdev, fault_type, e->private_bio); maybe_kick_lo(mdev); @@ -2331,15 +2275,12 @@ STATIC int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l /* lowest bit is set when we were primary, * next bit (weight 2) is set when peer was primary */ - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_METRICS, DUMPI(rct);); - switch (rct) { case 0: /* !self_pri && !peer_pri */ return 0; case 1: /* self_pri && !peer_pri */ return 1; case 2: /* !self_pri && peer_pri */ return -1; case 3: /* self_pri && peer_pri */ dc = test_bit(DISCARD_CONCURRENT, &mdev->flags); - MTRACE(TRACE_TYPE_UUID, TRACE_LVL_METRICS, DUMPI(dc);); return dc ? -1 : 1; } } @@ -3467,7 +3408,7 @@ STATIC void drbdd(struct drbd_conf *mdev) break; } - dump_packet(mdev, mdev->data.socket, 2, &mdev->data.rbuf, + trace_drbd_packet(mdev, mdev->data.socket, 2, &mdev->data.rbuf, __FILE__, __LINE__); } } @@ -3729,7 +3670,7 @@ int drbd_do_handshake(struct drbd_conf *mdev) return 0; } - dump_packet(mdev, mdev->data.socket, 2, &mdev->data.rbuf, + trace_drbd_packet(mdev, mdev->data.socket, 2, &mdev->data.rbuf, __FILE__, __LINE__); p->protocol_min = be32_to_cpu(p->protocol_min); @@ -4309,14 +4250,14 @@ STATIC int drbd_asender(struct drbd_thread *thi) } expect = cmd->pkt_size; ERR_IF(len != expect-sizeof(struct p_header)) { - dump_packet(mdev, mdev->meta.socket, 1, (void *)h, __FILE__, __LINE__); + trace_drbd_packet(mdev, mdev->meta.socket, 1, (void *)h, __FILE__, __LINE__); DUMPI(expect); goto reconnect; } } if (received == expect) { D_ASSERT(cmd != NULL); - dump_packet(mdev, mdev->meta.socket, 1, (void *)h, __FILE__, __LINE__); + trace_drbd_packet(mdev, mdev->meta.socket, 1, (void *)h, __FILE__, __LINE__); if (!cmd->process(mdev, h)) goto reconnect; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index cbfcb6b8b4d4..dcf642563c77 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -29,82 +29,9 @@ #include <linux/slab.h> #include <linux/drbd.h> #include "drbd_int.h" +#include "drbd_tracing.h" #include "drbd_req.h" -/* outside of the ifdef - * because of the _print_rq_state(,FIXME) in barrier_acked */ -STATIC void _print_rq_state(struct drbd_request *req, const char *txt) -{ - const unsigned long s = req->rq_state; - struct drbd_conf *mdev = req->mdev; - const int rw = (req->master_bio == NULL || - bio_data_dir(req->master_bio) == WRITE) ? - 'W' : 'R'; - - dev_info(DEV, "%s %p %c L%c%c%cN%c%c%c%c%c %u (%llus +%u) %s\n", - txt, 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 VERBOSE_REQUEST_CODE */ -#if defined(VERBOSE_REQUEST_CODE) || defined(ENABLE_DYNAMIC_TRACE) -STATIC void _print_req_mod(struct drbd_request *req, enum drbd_req_event what) -{ - struct drbd_conf *mdev = req->mdev; - const int rw = (req->master_bio == NULL || - bio_data_dir(req->master_bio) == WRITE) ? - 'W' : 'R'; - - 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", - }; - - dev_info(DEV, "_req_mod(%p %c ,%s)\n", req, rw, rq_event_names[what]); -} - -# ifdef ENABLE_DYNAMIC_TRACE -# define print_rq_state(R, T) \ - MTRACE(TRACE_TYPE_RQ, TRACE_LVL_METRICS, _print_rq_state(R, T);) -# define print_req_mod(T, W) \ - MTRACE(TRACE_TYPE_RQ, TRACE_LVL_METRICS, _print_req_mod(T, W);) -# else -# define print_rq_state(R, T) _print_rq_state(R, T) -# define print_req_mod(T, W) _print_req_mod(T, W) -# endif - -#else -#define print_rq_state(R, T) -#define print_req_mod(T, W) -#endif /* Update disk stats at start of I/O request */ static inline void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req, struct bio *bio) @@ -292,7 +219,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, static void _complete_master_bio(struct drbd_conf *mdev, struct drbd_request *req, int error) { - dump_bio(mdev, req->master_bio, 1, req); + trace_drbd_bio(mdev, "Rq", req->master_bio, 1, req); bio_endio(req->master_bio, error); req->master_bio = NULL; dec_ap_bio(mdev); @@ -304,7 +231,7 @@ void _req_may_be_done(struct drbd_request *req, int error) struct drbd_conf *mdev = req->mdev; int rw; - print_rq_state(req, "_req_may_be_done"); + trace_drbd_req(req, nothing, "_req_may_be_done"); /* we must not complete the master bio, while it is * still being processed by _drbd_send_zc_bio (drbd_send_dblock) @@ -486,7 +413,7 @@ void _req_mod(struct drbd_request *req, enum drbd_req_event what, int error) if (error && (bio_rw(req->master_bio) != READA)) dev_err(DEV, "got an _req_mod() errno of %d\n", error); - print_req_mod(req, what); + trace_drbd_req(req, what, NULL); switch (what) { default: @@ -739,8 +666,8 @@ void _req_mod(struct drbd_request *req, enum drbd_req_event what, int error) /* barrier came in before all requests have been acked. * this is bad, because if the connection is lost now, * we won't be able to clean them up... */ - _print_rq_state(req, - "FIXME (barrier_acked but pending)"); + dev_err(DEV, "FIXME (barrier_acked but pending)\n"); + trace_drbd_req(req, nothing, "FIXME (barrier_acked but pending)"); list_move(&req->tl_requests, &mdev->out_of_sequence_requests); } D_ASSERT(req->rq_state & RQ_NET_SENT); @@ -810,7 +737,7 @@ STATIC int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) return 0; } - dump_bio(mdev, bio, 0, req); + trace_drbd_bio(mdev, "Rq", bio, 0, req); local = inc_local(mdev); if (!local) { @@ -1003,7 +930,7 @@ allocate_barrier: if (local) { req->private_bio->bi_bdev = mdev->bc->backing_bdev; - dump_internal_bio("Pri", mdev, req->private_bio, 0); + trace_drbd_bio(mdev, "Pri", req->private_bio, 0, NULL); if (FAULT_ACTIVE(mdev, rw == WRITE ? DRBD_FAULT_DT_WR : rw == READ ? DRBD_FAULT_DT_RD diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 8866ea62f431..a63a1e9ae5a8 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h @@ -103,6 +103,7 @@ enum drbd_req_event { read_completed_with_error, write_completed_with_error, completed_ok, + nothing, /* for tracing only */ }; /* encoding of request states for now. we don't actually need that many bits. diff --git a/drivers/block/drbd/drbd_tracing.c b/drivers/block/drbd/drbd_tracing.c new file mode 100644 index 000000000000..2eff178fbb0f --- /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); diff --git a/drivers/block/drbd/drbd_tracing.h b/drivers/block/drbd/drbd_tracing.h new file mode 100644 index 000000000000..c4531a137f65 --- /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_worker.c b/drivers/block/drbd/drbd_worker.c index 4be8814fd50d..81f3a4e8ea49 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -43,6 +43,7 @@ #include <linux/drbd.h> #include "drbd_int.h" #include "drbd_req.h" +#include "drbd_tracing.h" #define SLEEP_TIME (HZ/10) @@ -88,7 +89,7 @@ void drbd_md_io_complete(struct bio *bio, int error) md_io->error = error; - dump_internal_bio("Md", md_io->mdev, bio, 1); + trace_drbd_bio(md_io->mdev, "Md", bio, 1, NULL); complete(&md_io->event); } @@ -116,7 +117,7 @@ void drbd_endio_read_sec(struct bio *bio, int error) __releases(local) D_ASSERT(e->block_id != ID_VACANT); - dump_internal_bio("Sec", mdev, bio, 1); + trace_drbd_bio(mdev, "Sec", bio, 1, NULL); spin_lock_irqsave(&mdev->req_lock, flags); mdev->read_cnt += e->size >> 9; @@ -129,10 +130,7 @@ void drbd_endio_read_sec(struct bio *bio, int error) __releases(local) drbd_queue_work(&mdev->data.work, &e->w); dec_local(mdev); - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "Moved EE (READ) to worker sec=%llus size=%u ee=%p\n", - (unsigned long long)e->sector, e->size, e); - ); + trace_drbd_ee(mdev, e, "read completed"); } /* writes on behalf of the partner, or resync writes, @@ -175,7 +173,7 @@ void drbd_endio_write_sec(struct bio *bio, int error) __releases(local) D_ASSERT(e->block_id != ID_VACANT); - dump_internal_bio("Sec", mdev, bio, 1); + trace_drbd_bio(mdev, "Sec", bio, 1, NULL); spin_lock_irqsave(&mdev->req_lock, flags); mdev->writ_cnt += e->size >> 9; @@ -191,10 +189,7 @@ void drbd_endio_write_sec(struct bio *bio, int error) __releases(local) list_del(&e->w.list); /* has been on active_ee or sync_ee */ list_add_tail(&e->w.list, &mdev->done_ee); - MTRACE(TRACE_TYPE_EE, TRACE_LVL_ALL, - dev_info(DEV, "Moved EE (WRITE) to done_ee sec=%llus size=%u ee=%p\n", - (unsigned long long)e->sector, e->size, e); - ); + trace_drbd_ee(mdev, e, "write completed"); /* No hlist_del_init(&e->colision) here, we did not send the Ack yet, * neither did we wake possibly waiting conflicting requests. @@ -241,7 +236,7 @@ void drbd_endio_pri(struct bio *bio, int error) error = -EIO; } - dump_internal_bio("Pri", mdev, bio, 1); + trace_drbd_bio(mdev, "Pri", bio, 1, NULL); /* to avoid recursion in _req_mod */ what = error @@ -1265,10 +1260,8 @@ void drbd_start_resync(struct drbd_conf *mdev, enum drbd_conns side) union drbd_state ns; int r; - MTRACE(TRACE_TYPE_RESYNC, TRACE_LVL_SUMMARY, - dev_info(DEV, "Resync starting: side=%s\n", - side == C_SYNC_TARGET ? "SyncTarget" : "SyncSource"); - ); + trace_drbd_resync(mdev, TRACE_LVL_SUMMARY, "Resync starting: side=%s\n", + side == C_SYNC_TARGET ? "SyncTarget" : "SyncSource"); drbd_bm_recount_bits(mdev); diff --git a/drivers/block/drbd/drbd_wrappers.h b/drivers/block/drbd/drbd_wrappers.h index 501ca2ed31f7..b7ce5acca0bb 100644 --- a/drivers/block/drbd/drbd_wrappers.h +++ b/drivers/block/drbd/drbd_wrappers.h @@ -1,3 +1,6 @@ +#ifndef _DRBD_WRAPPERS_H +#define _DRBD_WRAPPERS_H + #include <linux/ctype.h> #include <linux/mm.h> @@ -90,3 +93,5 @@ static inline int drbd_crypto_is_hash(struct crypto_tfm *tfm) # undef __cond_lock # define __cond_lock(x,c) (c) #endif + +#endif |