📄 jbd-stats-2.6-sles10.patch
字号:
Index: linux-2.6.16.46-0.14/include/linux/jbd.h===================================================================--- linux-2.6.16.46-0.14.orig/include/linux/jbd.h+++ linux-2.6.16.46-0.14/include/linux/jbd.h@@ -422,6 +422,16 @@ struct handle_s }; +/*+ * Some stats for checkpoint phase+ */+struct transaction_chp_stats_s {+ unsigned long cs_chp_time;+ unsigned long cs_forced_to_close;+ unsigned long cs_written;+ unsigned long cs_dropped;+};+ /* The transaction_t type is the guts of the journaling mechanism. It * tracks a compound transaction through its various states: *@@ -553,6 +563,21 @@ struct transaction_s spinlock_t t_handle_lock; /*+ * Longest time some handle had to wait for running transaction+ */+ unsigned long t_max_wait;++ /*+ * When transaction started+ */+ unsigned long t_start;++ /*+ * Checkpointing stats [j_checkpoint_sem]+ */+ struct transaction_chp_stats_s t_chp_stats;++ /* * Number of outstanding updates running on this transaction * [t_handle_lock] */@@ -592,6 +617,57 @@ struct transaction_s struct list_head t_jcb; }; +struct transaction_run_stats_s {+ unsigned long rs_wait;+ unsigned long rs_running;+ unsigned long rs_locked;+ unsigned long rs_flushing;+ unsigned long rs_logging;++ unsigned long rs_handle_count;+ unsigned long rs_blocks;+ unsigned long rs_blocks_logged;+};++struct transaction_stats_s+{+ int ts_type;+ unsigned long ts_tid;+ union {+ struct transaction_run_stats_s run;+ struct transaction_chp_stats_s chp;+ } u;+};++#define JBD_STATS_RUN 1+#define JBD_STATS_CHECKPOINT 2++#define ts_wait u.run.rs_wait+#define ts_running u.run.rs_running+#define ts_locked u.run.rs_locked+#define ts_flushing u.run.rs_flushing+#define ts_logging u.run.rs_logging+#define ts_handle_count u.run.rs_handle_count+#define ts_blocks u.run.rs_blocks+#define ts_blocks_logged u.run.rs_blocks_logged++#define ts_chp_time u.chp.cs_chp_time+#define ts_forced_to_close u.chp.cs_forced_to_close+#define ts_written u.chp.cs_written+#define ts_dropped u.chp.cs_dropped++#define CURRENT_MSECS (jiffies_to_msecs(jiffies))++static inline unsigned int+jbd_time_diff(unsigned int start, unsigned int end)+{+ if (unlikely(start > end))+ end = end + (~0UL - start);+ else+ end -= start;+ return end;+}+ /** * struct journal_s - The journal_s type is the concrete type associated with * journal_t.@@ -845,6 +921,16 @@ struct journal_s pid_t j_last_sync_writer; /*+ *+ */+ struct transaction_stats_s *j_history;+ int j_history_max;+ int j_history_cur;+ spinlock_t j_history_lock;+ struct proc_dir_entry *j_proc_entry;+ struct transaction_stats_s j_stats;++ /* * An opaque pointer to fs-private information. ext3 puts its * superblock pointer here */Index: linux-2.6.16.46-0.14/fs/jbd/transaction.c===================================================================--- linux-2.6.16.46-0.14.orig/fs/jbd/transaction.c+++ linux-2.6.16.46-0.14/fs/jbd/transaction.c@@ -60,6 +60,8 @@ get_transaction(journal_t *journal, tran J_ASSERT(journal->j_running_transaction == NULL); journal->j_running_transaction = transaction;+ transaction->t_max_wait = 0;+ transaction->t_start = CURRENT_MSECS; return transaction; }@@ -86,6 +88,7 @@ static int start_this_handle(journal_t * int nblocks = handle->h_buffer_credits; transaction_t *new_transaction = NULL; int ret = 0;+ unsigned long ts = CURRENT_MSECS; if (nblocks > journal->j_max_transaction_buffers) { printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n",@@ -219,6 +222,12 @@ repeat_locked: /* OK, account for the buffers that this operation expects to * use and add the handle to the running transaction. */ + if (time_after(transaction->t_start, ts)) {+ ts = jbd_time_diff(ts, transaction->t_start);+ if (ts > transaction->t_max_wait)+ transaction->t_max_wait= ts;+ }+ handle->h_transaction = transaction; transaction->t_outstanding_credits += nblocks; transaction->t_updates++;Index: linux-2.6.16.46-0.14/fs/jbd/journal.c===================================================================--- linux-2.6.16.46-0.14.orig/fs/jbd/journal.c+++ linux-2.6.16.46-0.14/fs/jbd/journal.c@@ -36,6 +36,7 @@ #include <asm/uaccess.h> #include <asm/page.h> #include <linux/proc_fs.h>+#include <linux/seq_file.h> EXPORT_SYMBOL(journal_start); EXPORT_SYMBOL(journal_restart);@@ -637,6 +638,300 @@ struct journal_head *journal_get_descrip return journal_add_journal_head(bh); } +struct jbd_stats_proc_session {+ journal_t *journal;+ struct transaction_stats_s *stats;+ int start;+ int max;+};++static void *jbd_history_skip_empty(struct jbd_stats_proc_session *s,+ struct transaction_stats_s *ts,+ int first)+{+ if (ts == s->stats + s->max)+ ts = s->stats;+ if (!first && ts == s->stats + s->start)+ return NULL;+ while (ts->ts_type == 0) {+ ts++;+ if (ts == s->stats + s->max)+ ts = s->stats;+ if (ts == s->stats + s->start)+ return NULL;+ }+ return ts;++}++static void *jbd_seq_history_start(struct seq_file *seq, loff_t *pos)+{+ struct jbd_stats_proc_session *s = seq->private;+ struct transaction_stats_s *ts;+ int l = *pos;++ if (l == 0)+ return SEQ_START_TOKEN;+ ts = jbd_history_skip_empty(s, s->stats + s->start, 1);+ if (!ts)+ return NULL;+ while (--l && (ts = jbd_history_skip_empty(s, ++ts, 0)) != NULL);+ return ts;+}++static void *jbd_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)+{+ struct jbd_stats_proc_session *s = seq->private;+ struct transaction_stats_s *ts = v;++ ++*pos;+ if (v == SEQ_START_TOKEN)+ return jbd_history_skip_empty(s, s->stats + s->start, 1);+ else+ return jbd_history_skip_empty(s, ++ts, 0);+}++static int jbd_seq_history_show(struct seq_file *seq, void *v)+{+ struct transaction_stats_s *ts = v;+ if (v == SEQ_START_TOKEN) {+ seq_printf(seq, "%-4s %-5s %-5s %-5s %-5s %-5s %-5s %-6s %-5s "+ "%-5s %-5s %-5s %-5s %-5s\n", "R/C", "tid",+ "wait", "run", "lock", "flush", "log", "hndls",+ "block", "inlog", "ctime", "write", "drop",+ "close");+ return 0;+ }+ if (ts->ts_type == JBD_STATS_RUN)+ seq_printf(seq, "%-4s %-5lu %-5lu %-5lu %-5lu %-5lu %-5lu "+ "%-6lu %-5lu %-5lu\n", "R", ts->ts_tid,+ ts->ts_wait, ts->ts_running, ts->ts_locked,+ ts->ts_flushing, ts->ts_logging,+ ts->ts_handle_count, ts->ts_blocks,+ ts->ts_blocks_logged);+ else if (ts->ts_type == JBD_STATS_CHECKPOINT)+ seq_printf(seq, "%-4s %-5lu %48s %-5lu %-5lu %-5lu %-5lu\n",+ "C", ts->ts_tid, " ", ts->ts_chp_time,+ ts->ts_written, ts->ts_dropped,+ ts->ts_forced_to_close);+ else+ J_ASSERT(0);+ return 0;+}++static void jbd_seq_history_stop(struct seq_file *seq, void *v)+{+}++static struct seq_operations jbd_seq_history_ops = {+ .start = jbd_seq_history_start,+ .next = jbd_seq_history_next,+ .stop = jbd_seq_history_stop,+ .show = jbd_seq_history_show,+};++static int jbd_seq_history_open(struct inode *inode, struct file *file)+{+ journal_t *journal = PDE(inode)->data;+ struct jbd_stats_proc_session *s;+ int rc, size;++ s = kmalloc(sizeof(*s), GFP_KERNEL);+ if (s == NULL)+ return -EIO;+ size = sizeof(struct transaction_stats_s) * journal->j_history_max;+ s->stats = kmalloc(size, GFP_KERNEL);+ if (s->stats == NULL) {+ kfree(s);+ return -EIO;+ }+ spin_lock(&journal->j_history_lock);+ memcpy(s->stats, journal->j_history, size);+ s->max = journal->j_history_max;+ s->start = journal->j_history_cur % s->max;+ spin_unlock(&journal->j_history_lock);++ rc = seq_open(file, &jbd_seq_history_ops);+ if (rc == 0) {+ struct seq_file *m = (struct seq_file *)file->private_data;+ m->private = s;+ } else {+ kfree(s->stats);+ kfree(s);+ }+ return rc;++}++static int jbd_seq_history_release(struct inode *inode, struct file *file)+{+ struct seq_file *seq = (struct seq_file *)file->private_data;+ struct jbd_stats_proc_session *s = seq->private;+ kfree(s->stats);+ kfree(s);+ return seq_release(inode, file);+}++static struct file_operations jbd_seq_history_fops = {+ .owner = THIS_MODULE,+ .open = jbd_seq_history_open,+ .read = seq_read,+ .llseek = seq_lseek,+ .release = jbd_seq_history_release,+};++static void *jbd_seq_info_start(struct seq_file *seq, loff_t *pos)+{+ return *pos ? NULL : SEQ_START_TOKEN;+}++static void *jbd_seq_info_next(struct seq_file *seq, void *v, loff_t *pos)+{+ return NULL;+}++static int jbd_seq_info_show(struct seq_file *seq, void *v)+{+ struct jbd_stats_proc_session *s = seq->private;+ if (v != SEQ_START_TOKEN)+ return 0;+ seq_printf(seq, "%lu transaction, each upto %u blocks\n",+ s->stats->ts_tid,+ s->journal->j_max_transaction_buffers);+ if (s->stats->ts_tid == 0)+ return 0;+ seq_printf(seq, "average: \n %lums waiting for transaction\n",+ s->stats->ts_wait / s->stats->ts_tid);+ seq_printf(seq, " %lums running transaction\n",+ s->stats->ts_running / s->stats->ts_tid);+ seq_printf(seq, " %lums transaction was being locked\n",+ s->stats->ts_locked / s->stats->ts_tid);+ seq_printf(seq, " %lums flushing data (in ordered mode)\n",+ s->stats->ts_flushing / s->stats->ts_tid);+ seq_printf(seq, " %lums logging transaction\n",+ s->stats->ts_logging / s->stats->ts_tid);+ seq_printf(seq, " %lu handles per transaction\n",+ s->stats->ts_handle_count / s->stats->ts_tid);+ seq_printf(seq, " %lu blocks per transaction\n",+ s->stats->ts_blocks / s->stats->ts_tid);+ seq_printf(seq, " %lu logged blocks per transaction\n",+ s->stats->ts_blocks_logged / s->stats->ts_tid);+ return 0;+}++static void jbd_seq_info_stop(struct seq_file *seq, void *v)+{+}++static struct seq_operations jbd_seq_info_ops = {+ .start = jbd_seq_info_start,+ .next = jbd_seq_info_next,+ .stop = jbd_seq_info_stop,+ .show = jbd_seq_info_show,+};++static int jbd_seq_info_open(struct inode *inode, struct file *file)+{+ journal_t *journal = PDE(inode)->data;+ struct jbd_stats_proc_session *s;+ int rc, size;++ s = kmalloc(sizeof(*s), GFP_KERNEL);+ if (s == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -