Added two debugfs entries... one to dump o2hb livenodes and the other to dump osb. $ cat /sys/kernel/debug/ocfs2/BC4F4550BEA74F92BDCC746AAD2EC0BF/fs_state Device => Id: 8,65 Uuid: BC4F4550BEA74F92BDCC746AAD2EC0BF Gen: 0xA02024F2 Label: sunil-xattr Volume => State: 1 Flags: 0x0 Sizes => Block: 4096 Cluster: 4096 Features => Compat: 0x1 Incompat: 0x350 ROcompat: 0x1 Mount => Opts: 0x1 AtimeQuanta: 60 Cluster => Stack: o2cb Name: BC4F4550BEA74F92BDCC746AAD2EC0BF Version: 1.0 DownCnvt => Pid: 7330 Count: 0 WakeSeq: 149 WorkSeq: 149 Recovery => Pid: -1 Nodes: None Commit => Pid: 7335 Interval: 0 Needs: 1 Journal => State: 1 NumTxns: 32521 TxnId: 67 Stats => GlobalAllocs: 140 LocalAllocs: 192825 SubAllocs: 73299 LAWinMoves: 140 SAExtends: 72 Steal => Slot: -1 NumStolen: 0 Slots => Num Node RecoGen * 0 92 2 1 96 0 2 -1 0 3 -1 0 Sunil
Sunil Mushran
2008-Sep-11 03:05 UTC
[Ocfs2-devel] [PATCH 1/4] ocfs2/hb: Exposes list of heartbeating nodes via debugfs
Patch creates a debugfs file, o2hb/livesnodes, which when read will expose the aggregate list of heartbeating node across all heartbeat regions. Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com> --- fs/ocfs2/cluster/heartbeat.c | 140 +++++++++++++++++++++++++++++++++++++++- fs/ocfs2/cluster/heartbeat.h | 3 +- fs/ocfs2/cluster/nodemanager.c | 9 ++- 3 files changed, 148 insertions(+), 4 deletions(-) diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 7dce161..1ea87ee 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -33,6 +33,7 @@ #include <linux/random.h> #include <linux/crc32.h> #include <linux/time.h> +#include <linux/debugfs.h> #include "heartbeat.h" #include "tcp.h" @@ -60,6 +61,11 @@ static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; static LIST_HEAD(o2hb_node_events); static DECLARE_WAIT_QUEUE_HEAD(o2hb_steady_queue); +#define O2HB_DEBUG_DIR "o2hb" +#define O2HB_DEBUG_LIVENODES "livenodes" +static struct dentry *o2hb_debug_dir; +static struct dentry *o2hb_debug_livenodes; + static LIST_HEAD(o2hb_all_regions); static struct o2hb_callback { @@ -905,7 +911,121 @@ static int o2hb_thread(void *data) return 0; } -void o2hb_init(void) +#ifdef CONFIG_DEBUG_FS +struct o2hb_debug_buffer { + int len; + char *buf; +}; + +static int o2hb_debug_open(struct inode *inode, struct file *file) +{ + unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + struct o2hb_debug_buffer *odb = NULL; + int i = -1; + int out = 0; + + odb = kzalloc(sizeof(struct o2hb_debug_buffer), GFP_KERNEL); + if (!odb) + goto bail; + + odb->len = PAGE_SIZE; + odb->buf = kmalloc(odb->len, GFP_KERNEL); + if (!odb->buf) { + kfree(odb); + goto bail; + } + + o2hb_fill_node_map(map, sizeof(map)); + + while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) + out += snprintf(odb->buf + out, odb->len - out, "%d ", i); + out += snprintf(odb->buf + out, odb->len - out, "\n"); + + odb->len = out; + + file->private_data = odb; + + return 0; +bail: + return -ENOMEM; +} + +static int o2hb_debug_release(struct inode *inode, struct file *file) +{ + struct o2hb_debug_buffer *odb + (struct o2hb_debug_buffer *)file->private_data; + + kfree(odb->buf); + kfree(odb); + + return 0; +} + +static ssize_t o2hb_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + struct o2hb_debug_buffer *odb + (struct o2hb_debug_buffer *)file->private_data; + + return simple_read_from_buffer(buf, nbytes, ppos, odb->buf, odb->len); +} + +static loff_t o2hb_debug_llseek(struct file *file, loff_t off, int whence) +{ + struct o2hb_debug_buffer *odb + (struct o2hb_debug_buffer *)file->private_data; + loff_t new = -1; + + switch (whence) { + case 0: + new = off; + break; + case 1: + new = file->f_pos + off; + break; + } + + if (new < 0 || new > odb->len) + return -EINVAL; + + return (file->f_pos = new); +} +#else +static int o2hb_debug_open(struct inode *inode, struct file *file) +{ + return 0; +} +static int o2hb_debug_release(struct inode *inode, struct file *file) +{ + return 0; +} +static ssize_t o2hb_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + return 0; +} +static loff_t o2hb_debug_llseek(struct file *file, loff_t off, int whence) +{ + return 0; +} +#endif /* CONFIG_DEBUG_FS */ + +static struct file_operations o2hb_debug_fops = { + .open = o2hb_debug_open, + .release = o2hb_debug_release, + .read = o2hb_debug_read, + .llseek = o2hb_debug_llseek, +}; + +void o2hb_exit(void) +{ + if (o2hb_debug_livenodes) + debugfs_remove(o2hb_debug_livenodes); + if (o2hb_debug_dir) + debugfs_remove(o2hb_debug_dir); +} + +int o2hb_init(void) { int i; @@ -918,6 +1038,24 @@ void o2hb_init(void) INIT_LIST_HEAD(&o2hb_node_events); memset(o2hb_live_node_bitmap, 0, sizeof(o2hb_live_node_bitmap)); + + o2hb_debug_dir = debugfs_create_dir(O2HB_DEBUG_DIR, NULL); + if (!o2hb_debug_dir) { + mlog_errno(-ENOMEM); + return -ENOMEM; + } + + o2hb_debug_livenodes = debugfs_create_file(O2HB_DEBUG_LIVENODES, + S_IFREG|S_IRUSR, + o2hb_debug_dir, NULL, + &o2hb_debug_fops); + if (!o2hb_debug_livenodes) { + mlog_errno(-ENOMEM); + debugfs_remove(o2hb_debug_dir); + return -ENOMEM; + } + + return 0; } /* if we're already in a callback then we're already serialized by the sem */ diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h index e511339..2f16492 100644 --- a/fs/ocfs2/cluster/heartbeat.h +++ b/fs/ocfs2/cluster/heartbeat.h @@ -75,7 +75,8 @@ void o2hb_unregister_callback(const char *region_uuid, struct o2hb_callback_func *hc); void o2hb_fill_node_map(unsigned long *map, unsigned bytes); -void o2hb_init(void); +void o2hb_exit(void); +int o2hb_init(void); int o2hb_check_node_heartbeating(u8 node_num); int o2hb_check_node_heartbeating_from_callback(u8 node_num); int o2hb_check_local_node_heartbeating(void); diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c index 816a3f6..2ce28d7 100644 --- a/fs/ocfs2/cluster/nodemanager.c +++ b/fs/ocfs2/cluster/nodemanager.c @@ -881,6 +881,7 @@ static void __exit exit_o2nm(void) o2cb_sys_shutdown(); o2net_exit(); + o2hb_exit(); } static int __init init_o2nm(void) @@ -889,11 +890,13 @@ static int __init init_o2nm(void) cluster_print_version(); - o2hb_init(); + ret = o2hb_init(); + if (ret) + goto out; ret = o2net_init(); if (ret) - goto out; + goto out_o2hb; ret = o2net_register_hb_callbacks(); if (ret) @@ -916,6 +919,8 @@ out_callbacks: o2net_unregister_hb_callbacks(); out_o2net: o2net_exit(); +out_o2hb: + o2hb_exit(); out: return ret; } -- 1.5.4.3
Sunil Mushran
2008-Sep-11 03:05 UTC
[Ocfs2-devel] [PATCH 2/4] ocfs2: Moves struct ocfs2_slot_info to a header file
Moves the definition of struct ocfs2_slot_info from slot_map.c to ocfs2.h. Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com> --- fs/ocfs2/ocfs2.h | 16 +++++++++++++++- fs/ocfs2/slot_map.c | 17 ----------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 487487a..b4bf878 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -192,8 +192,22 @@ enum ocfs2_mount_options #define OCFS2_OSB_ERROR_FS 0x0004 #define OCFS2_DEFAULT_ATIME_QUANTUM 60 +struct ocfs2_slot { + int sl_valid; + unsigned int sl_node_num; +}; + +struct ocfs2_slot_info { + int si_extended; + int si_slots_per_block; + struct inode *si_inode; + unsigned int si_blocks; + struct buffer_head **si_bh; + unsigned int si_num_slots; + struct ocfs2_slot *si_slots; +}; + struct ocfs2_journal; -struct ocfs2_slot_info; struct ocfs2_recovery_map; struct ocfs2_super { diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index bb5ff89..bd95205 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -42,23 +42,6 @@ #include "buffer_head_io.h" - -struct ocfs2_slot { - int sl_valid; - unsigned int sl_node_num; -}; - -struct ocfs2_slot_info { - int si_extended; - int si_slots_per_block; - struct inode *si_inode; - unsigned int si_blocks; - struct buffer_head **si_bh; - unsigned int si_num_slots; - struct ocfs2_slot *si_slots; -}; - - static int __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si, unsigned int node_num); -- 1.5.4.3
Sunil Mushran
2008-Sep-11 03:05 UTC
[Ocfs2-devel] [PATCH 3/4] ocfs2: Moves struct recovery_map to a header file
Moves the definition of struct recovery_map from journal.c to ocfs2.h. Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com> --- fs/ocfs2/journal.c | 11 ----------- fs/ocfs2/ocfs2.h | 11 ++++++++++- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 7a37240..9c05e06 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -64,17 +64,6 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, int slot); static int ocfs2_commit_thread(void *arg); - -/* - * The recovery_list is a simple linked list of node numbers to recover. - * It is protected by the recovery_lock. - */ - -struct ocfs2_recovery_map { - unsigned int rm_used; - unsigned int *rm_entries; -}; - int ocfs2_recovery_init(struct ocfs2_super *osb) { struct ocfs2_recovery_map *rm; diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index b4bf878..5ab2211 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -207,8 +207,17 @@ struct ocfs2_slot_info { struct ocfs2_slot *si_slots; }; +/* + * The recovery_list is a simple linked list of node numbers to recover. + * It is protected by the recovery_lock. + */ + +struct ocfs2_recovery_map { + unsigned int rm_used; + unsigned int *rm_entries; +}; + struct ocfs2_journal; -struct ocfs2_recovery_map; struct ocfs2_super { struct task_struct *commit_task; -- 1.5.4.3
Sunil Mushran
2008-Sep-11 03:05 UTC
[Ocfs2-devel] [PATCH 4/4] ocfs2: Exposes the file system state via debugfs
Patch creates a per mount debugfs file, fs_state, which when read will expose information like, cluster stack in use, states of the downconvert, recovery and commit threads, number of journal txns, some allocation stats, list of all slots, etc. Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com> --- fs/ocfs2/ocfs2.h | 1 + fs/ocfs2/super.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+), 0 deletions(-) diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 5ab2211..add2586 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -298,6 +298,7 @@ struct ocfs2_super struct ocfs2_dlm_debug *osb_dlm_debug; struct dentry *osb_debug_root; + struct dentry *osb_ctxt; wait_queue_head_t recovery_event; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index d789c53..ae11040 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -606,6 +606,212 @@ static int ocfs2_verify_userspace_stack(struct ocfs2_super *osb, return 0; } +#ifdef CONFIG_DEBUG_FS +struct ocfs2_debug_buffer { + int len; + char *buf; +}; + +static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len) +{ + int out = 0; + int i; + struct ocfs2_slot_info *si = osb->slot_info; + struct ocfs2_cluster_connection *cconn = osb->cconn; + struct ocfs2_recovery_map *rm = osb->recovery_map; + + out += snprintf(buf + out, len - out, + "%8s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", + "Device", osb->dev_str, osb->uuid_str, + osb->fs_generation, osb->vol_label); + + out += snprintf(buf + out, len - out, + "%8s => State: %d Flags: 0x%lX\n", "Volume", + atomic_read(&osb->vol_state), osb->osb_flags); + + out += snprintf(buf + out, len - out, + "%8s => Block: %lu Cluster: %d\n", "Sizes", + osb->sb->s_blocksize, osb->s_clustersize); + + out += snprintf(buf + out, len - out, + "%8s => Compat: 0x%X Incompat: 0x%X ROcompat: 0x%X\n", + "Features", osb->s_feature_compat, + osb->s_feature_incompat, osb->s_feature_ro_compat); + + out += snprintf(buf + out, len - out, + "%8s => Opts: 0x%lX AtimeQuanta: %u\n", "Mount", + osb->s_mount_opt, osb->s_atime_quantum); + + out += snprintf(buf + out, len - out, + "%8s => Stack: %s Name: %*s Version: %d.%d\n", + "Cluster", + (*osb->osb_cluster_stack == '\0' ? + "o2cb" : osb->osb_cluster_stack), + cconn->cc_namelen, cconn->cc_name, + cconn->cc_version.pv_major, cconn->cc_version.pv_minor); + + spin_lock(&osb->dc_task_lock); + out += snprintf(buf + out, len - out, + "%8s => Pid: %d Count: %lu WakeSeq: %lu " + "WorkSeq: %lu\n", "DownCnvt", + task_pid_nr(osb->dc_task), osb->blocked_lock_count, + osb->dc_wake_sequence, osb->dc_work_sequence); + spin_unlock(&osb->dc_task_lock); + + spin_lock(&osb->osb_lock); + out += snprintf(buf + out, len - out, "%8s => Pid: %d Nodes:", + "Recovery", + (osb->recovery_thread_task ? + task_pid_nr(osb->recovery_thread_task) : -1)); + if (rm->rm_used == 0) + out += snprintf(buf + out, len - out, " None\n"); + else { + for (i = 0; i < rm->rm_used; i++) + out += snprintf(buf + out, len - out, " %d", + rm->rm_entries[i]); + out += snprintf(buf + out, len - out, "\n"); + } + spin_unlock(&osb->osb_lock); + + out += snprintf(buf + out, len - out, + "%8s => Pid: %d Interval: %lu Needs: %d\n", "Commit", + task_pid_nr(osb->commit_task), osb->osb_commit_interval, + atomic_read(&osb->needs_checkpoint)); + + out += snprintf(buf + out, len - out, + "%8s => State: %d NumTxns: %d TxnId: %lu\n", + "Journal", osb->journal->j_state, + atomic_read(&osb->journal->j_num_trans), + osb->journal->j_trans_id); + + out += snprintf(buf + out, len - out, + "%8s => GlobalAllocs: %d LocalAllocs: %d " + "SubAllocs: %d LAWinMoves: %d SAExtends: %d\n", + "Stats", + atomic_read(&osb->alloc_stats.bitmap_data), + atomic_read(&osb->alloc_stats.local_data), + atomic_read(&osb->alloc_stats.bg_allocs), + atomic_read(&osb->alloc_stats.moves), + atomic_read(&osb->alloc_stats.bg_extends)); + + spin_lock(&osb->osb_lock); + out += snprintf(buf + out, len - out, + "%8s => Slot: %d NumStolen: %d\n", "Steal", + osb->s_inode_steal_slot, + atomic_read(&osb->s_num_inodes_stolen)); + spin_unlock(&osb->osb_lock); + + out += snprintf(buf + out, len - out, "%8s => %3s %5s %10s\n", + "Slots", "Num", "Node", "RecoGen"); + + spin_lock(&osb->osb_lock); + for (i = 0; i < si->si_num_slots; i++) { + out += snprintf(buf + out, len - out, + "%8s %c %3d %5d %10d\n", + " ", + (i == osb->slot_num ? '*' : ' '), + i, + (si->si_slots[i].sl_valid ? + si->si_slots[i].sl_node_num : -1), + osb->slot_recovery_generations[i]); + } + spin_unlock(&osb->osb_lock); + + return out; +} + +static int ocfs2_osb_debug_open(struct inode *inode, struct file *file) +{ + struct ocfs2_debug_buffer *odb = NULL; + struct ocfs2_super *osb = inode->i_private; + + odb = kzalloc(sizeof(struct ocfs2_debug_buffer), GFP_KERNEL); + if (!odb) + goto bail; + + odb->len = PAGE_SIZE; + odb->buf = kmalloc(odb->len, GFP_KERNEL); + if (!odb->buf) { + kfree(odb); + goto bail; + } + + odb->len = ocfs2_osb_dump(osb, odb->buf, odb->len); + + file->private_data = odb; + + return 0; +bail: + return -ENOMEM; +} + +static int ocfs2_debug_release(struct inode *inode, struct file *file) +{ + struct ocfs2_debug_buffer *odb + (struct ocfs2_debug_buffer *)file->private_data; + + kfree(odb->buf); + kfree(odb); + + return 0; +} + +static ssize_t ocfs2_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + struct ocfs2_debug_buffer *odb + (struct ocfs2_debug_buffer *)file->private_data; + + return simple_read_from_buffer(buf, nbytes, ppos, odb->buf, odb->len); +} + +static loff_t ocfs2_debug_llseek(struct file *file, loff_t off, int whence) +{ + struct ocfs2_debug_buffer *odb + (struct ocfs2_debug_buffer *)file->private_data; + loff_t new = -1; + + switch (whence) { + case 0: + new = off; + break; + case 1: + new = file->f_pos + off; + break; + } + + if (new < 0 || new > odb->len) + return -EINVAL; + + return (file->f_pos = new); +} +#else +static int ocfs2_osb_debug_open(struct inode *inode, struct file *file) +{ + return 0; +} +static int ocfs2_debug_release(struct inode *inode, struct file *file) +{ + return 0; +} +static ssize_t ocfs2_debug_read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + return 0; +} +static loff_t ocfs2_debug_llseek(struct file *file, loff_t off, int whence) +{ + return NULL; +} +#endif /* CONFIG_DEBUG_FS */ + +static struct file_operations ocfs2_osb_debug_fops = { + .open = ocfs2_osb_debug_open, + .release = ocfs2_debug_release, + .read = ocfs2_debug_read, + .llseek = ocfs2_debug_llseek, +}; + static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) { struct dentry *root; @@ -706,6 +912,16 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) goto read_super_error; } + osb->osb_ctxt = debugfs_create_file("fs_state", S_IFREG|S_IRUSR, + osb->osb_debug_root, + osb, + &ocfs2_osb_debug_fops); + if (!osb->osb_ctxt) { + status = -EINVAL; + mlog_errno(status); + goto read_super_error; + } + status = ocfs2_mount_volume(sb); if (osb->root_inode) inode = igrab(osb->root_inode); @@ -1323,6 +1539,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) if (osb->cconn) ocfs2_dlm_shutdown(osb, hangup_needed); + debugfs_remove(osb->osb_ctxt); debugfs_remove(osb->osb_debug_root); if (hangup_needed) -- 1.5.4.3