aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-09-30 00:32:06 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-09-30 00:32:06 -0400
commitbf6993276f74d46776f35c45ddef29b981b1d1c6 (patch)
tree5c9cb128fed29a83add1932b12443edaa6fd06cc /fs
parent296c355cd6443d89fa251885a8d78778fe111dc4 (diff)
jbd2: Use tracepoints for history file
The /proc/fs/jbd2/<dev>/history was maintained manually; by using tracepoints, we can get all of the existing functionality of the /proc file plus extra capabilities thanks to the ftrace infrastructure. We save memory as a bonus. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/jbd2/checkpoint.c7
-rw-r--r--fs/jbd2/commit.c59
-rw-r--r--fs/jbd2/journal.c187
3 files changed, 45 insertions, 208 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 5d70b3e6d49b..ca0f5eb62b20 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -643,6 +643,7 @@ out:
643 643
644int __jbd2_journal_remove_checkpoint(struct journal_head *jh) 644int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
645{ 645{
646 struct transaction_chp_stats_s *stats;
646 transaction_t *transaction; 647 transaction_t *transaction;
647 journal_t *journal; 648 journal_t *journal;
648 int ret = 0; 649 int ret = 0;
@@ -679,6 +680,12 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
679 680
680 /* OK, that was the last buffer for the transaction: we can now 681 /* OK, that was the last buffer for the transaction: we can now
681 safely remove this transaction from the log */ 682 safely remove this transaction from the log */
683 stats = &transaction->t_chp_stats;
684 if (stats->cs_chp_time)
685 stats->cs_chp_time = jbd2_time_diff(stats->cs_chp_time,
686 jiffies);
687 trace_jbd2_checkpoint_stats(journal->j_fs_dev->bd_dev,
688 transaction->t_tid, stats);
682 689
683 __jbd2_journal_drop_transaction(journal, transaction); 690 __jbd2_journal_drop_transaction(journal, transaction);
684 kfree(transaction); 691 kfree(transaction);
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 26d991ddc1e6..d4cfd6d2779e 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -410,10 +410,10 @@ void jbd2_journal_commit_transaction(journal_t *journal)
410 if (commit_transaction->t_synchronous_commit) 410 if (commit_transaction->t_synchronous_commit)
411 write_op = WRITE_SYNC_PLUG; 411 write_op = WRITE_SYNC_PLUG;
412 trace_jbd2_commit_locking(journal, commit_transaction); 412 trace_jbd2_commit_locking(journal, commit_transaction);
413 stats.u.run.rs_wait = commit_transaction->t_max_wait; 413 stats.run.rs_wait = commit_transaction->t_max_wait;
414 stats.u.run.rs_locked = jiffies; 414 stats.run.rs_locked = jiffies;
415 stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start, 415 stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
416 stats.u.run.rs_locked); 416 stats.run.rs_locked);
417 417
418 spin_lock(&commit_transaction->t_handle_lock); 418 spin_lock(&commit_transaction->t_handle_lock);
419 while (commit_transaction->t_updates) { 419 while (commit_transaction->t_updates) {
@@ -486,9 +486,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
486 jbd2_journal_switch_revoke_table(journal); 486 jbd2_journal_switch_revoke_table(journal);
487 487
488 trace_jbd2_commit_flushing(journal, commit_transaction); 488 trace_jbd2_commit_flushing(journal, commit_transaction);
489 stats.u.run.rs_flushing = jiffies; 489 stats.run.rs_flushing = jiffies;
490 stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked, 490 stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked,
491 stats.u.run.rs_flushing); 491 stats.run.rs_flushing);
492 492
493 commit_transaction->t_state = T_FLUSH; 493 commit_transaction->t_state = T_FLUSH;
494 journal->j_committing_transaction = commit_transaction; 494 journal->j_committing_transaction = commit_transaction;
@@ -523,11 +523,11 @@ void jbd2_journal_commit_transaction(journal_t *journal)
523 spin_unlock(&journal->j_state_lock); 523 spin_unlock(&journal->j_state_lock);
524 524
525 trace_jbd2_commit_logging(journal, commit_transaction); 525 trace_jbd2_commit_logging(journal, commit_transaction);
526 stats.u.run.rs_logging = jiffies; 526 stats.run.rs_logging = jiffies;
527 stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing, 527 stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing,
528 stats.u.run.rs_logging); 528 stats.run.rs_logging);
529 stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits; 529 stats.run.rs_blocks = commit_transaction->t_outstanding_credits;
530 stats.u.run.rs_blocks_logged = 0; 530 stats.run.rs_blocks_logged = 0;
531 531
532 J_ASSERT(commit_transaction->t_nr_buffers <= 532 J_ASSERT(commit_transaction->t_nr_buffers <=
533 commit_transaction->t_outstanding_credits); 533 commit_transaction->t_outstanding_credits);
@@ -695,7 +695,7 @@ start_journal_io:
695 submit_bh(write_op, bh); 695 submit_bh(write_op, bh);
696 } 696 }
697 cond_resched(); 697 cond_resched();
698 stats.u.run.rs_blocks_logged += bufs; 698 stats.run.rs_blocks_logged += bufs;
699 699
700 /* Force a new descriptor to be generated next 700 /* Force a new descriptor to be generated next
701 time round the loop. */ 701 time round the loop. */
@@ -988,33 +988,30 @@ restart_loop:
988 J_ASSERT(commit_transaction->t_state == T_COMMIT); 988 J_ASSERT(commit_transaction->t_state == T_COMMIT);
989 989
990 commit_transaction->t_start = jiffies; 990 commit_transaction->t_start = jiffies;
991 stats.u.run.rs_logging = jbd2_time_diff(stats.u.run.rs_logging, 991 stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging,
992 commit_transaction->t_start); 992 commit_transaction->t_start);
993 993
994 /* 994 /*
995 * File the transaction for history 995 * File the transaction statistics
996 */ 996 */
997 stats.ts_type = JBD2_STATS_RUN;
998 stats.ts_tid = commit_transaction->t_tid; 997 stats.ts_tid = commit_transaction->t_tid;
999 stats.u.run.rs_handle_count = commit_transaction->t_handle_count; 998 stats.run.rs_handle_count = commit_transaction->t_handle_count;
1000 spin_lock(&journal->j_history_lock); 999 trace_jbd2_run_stats(journal->j_fs_dev->bd_dev,
1001 memcpy(journal->j_history + journal->j_history_cur, &stats, 1000 commit_transaction->t_tid, &stats.run);
1002 sizeof(stats));
1003 if (++journal->j_history_cur == journal->j_history_max)
1004 journal->j_history_cur = 0;
1005 1001
1006 /* 1002 /*
1007 * Calculate overall stats 1003 * Calculate overall stats
1008 */ 1004 */
1005 spin_lock(&journal->j_history_lock);
1009 journal->j_stats.ts_tid++; 1006 journal->j_stats.ts_tid++;
1010 journal->j_stats.u.run.rs_wait += stats.u.run.rs_wait; 1007 journal->j_stats.run.rs_wait += stats.run.rs_wait;
1011 journal->j_stats.u.run.rs_running += stats.u.run.rs_running; 1008 journal->j_stats.run.rs_running += stats.run.rs_running;
1012 journal->j_stats.u.run.rs_locked += stats.u.run.rs_locked; 1009 journal->j_stats.run.rs_locked += stats.run.rs_locked;
1013 journal->j_stats.u.run.rs_flushing += stats.u.run.rs_flushing; 1010 journal->j_stats.run.rs_flushing += stats.run.rs_flushing;
1014 journal->j_stats.u.run.rs_logging += stats.u.run.rs_logging; 1011 journal->j_stats.run.rs_logging += stats.run.rs_logging;
1015 journal->j_stats.u.run.rs_handle_count += stats.u.run.rs_handle_count; 1012 journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count;
1016 journal->j_stats.u.run.rs_blocks += stats.u.run.rs_blocks; 1013 journal->j_stats.run.rs_blocks += stats.run.rs_blocks;
1017 journal->j_stats.u.run.rs_blocks_logged += stats.u.run.rs_blocks_logged; 1014 journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
1018 spin_unlock(&journal->j_history_lock); 1015 spin_unlock(&journal->j_history_lock);
1019 1016
1020 commit_transaction->t_state = T_FINISHED; 1017 commit_transaction->t_state = T_FINISHED;
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 977a8dafb76d..761af77491f5 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -676,153 +676,6 @@ struct jbd2_stats_proc_session {
676 int max; 676 int max;
677}; 677};
678 678
679static void *jbd2_history_skip_empty(struct jbd2_stats_proc_session *s,
680 struct transaction_stats_s *ts,
681 int first)
682{
683 if (ts == s->stats + s->max)
684 ts = s->stats;
685 if (!first && ts == s->stats + s->start)
686 return NULL;
687 while (ts->ts_type == 0) {
688 ts++;
689 if (ts == s->stats + s->max)
690 ts = s->stats;
691 if (ts == s->stats + s->start)
692 return NULL;
693 }
694 return ts;
695
696}
697
698static void *jbd2_seq_history_start(struct seq_file *seq, loff_t *pos)
699{
700 struct jbd2_stats_proc_session *s = seq->private;
701 struct transaction_stats_s *ts;
702 int l = *pos;
703
704 if (l == 0)
705 return SEQ_START_TOKEN;
706 ts = jbd2_history_skip_empty(s, s->stats + s->start, 1);
707 if (!ts)
708 return NULL;
709 l--;
710 while (l) {
711 ts = jbd2_history_skip_empty(s, ++ts, 0);
712 if (!ts)
713 break;
714 l--;
715 }
716 return ts;
717}
718
719static void *jbd2_seq_history_next(struct seq_file *seq, void *v, loff_t *pos)
720{
721 struct jbd2_stats_proc_session *s = seq->private;
722 struct transaction_stats_s *ts = v;
723
724 ++*pos;
725 if (v == SEQ_START_TOKEN)
726 return jbd2_history_skip_empty(s, s->stats + s->start, 1);
727 else
728 return jbd2_history_skip_empty(s, ++ts, 0);
729}
730
731static int jbd2_seq_history_show(struct seq_file *seq, void *v)
732{
733 struct transaction_stats_s *ts = v;
734 if (v == SEQ_START_TOKEN) {
735 seq_printf(seq, "%-4s %-5s %-5s %-5s %-5s %-5s %-5s %-6s %-5s "
736 "%-5s %-5s %-5s %-5s %-5s\n", "R/C", "tid",
737 "wait", "run", "lock", "flush", "log", "hndls",
738 "block", "inlog", "ctime", "write", "drop",
739 "close");
740 return 0;
741 }
742 if (ts->ts_type == JBD2_STATS_RUN)
743 seq_printf(seq, "%-4s %-5lu %-5u %-5u %-5u %-5u %-5u "
744 "%-6lu %-5lu %-5lu\n", "R", ts->ts_tid,
745 jiffies_to_msecs(ts->u.run.rs_wait),
746 jiffies_to_msecs(ts->u.run.rs_running),
747 jiffies_to_msecs(ts->u.run.rs_locked),
748 jiffies_to_msecs(ts->u.run.rs_flushing),
749 jiffies_to_msecs(ts->u.run.rs_logging),
750 ts->u.run.rs_handle_count,
751 ts->u.run.rs_blocks,
752 ts->u.run.rs_blocks_logged);
753 else if (ts->ts_type == JBD2_STATS_CHECKPOINT)
754 seq_printf(seq, "%-4s %-5lu %48s %-5u %-5lu %-5lu %-5lu\n",
755 "C", ts->ts_tid, " ",
756 jiffies_to_msecs(ts->u.chp.cs_chp_time),
757 ts->u.chp.cs_written, ts->u.chp.cs_dropped,
758 ts->u.chp.cs_forced_to_close);
759 else
760 J_ASSERT(0);
761 return 0;
762}
763
764static void jbd2_seq_history_stop(struct seq_file *seq, void *v)
765{
766}
767
768static const struct seq_operations jbd2_seq_history_ops = {
769 .start = jbd2_seq_history_start,
770 .next = jbd2_seq_history_next,
771 .stop = jbd2_seq_history_stop,
772 .show = jbd2_seq_history_show,
773};
774
775static int jbd2_seq_history_open(struct inode *inode, struct file *file)
776{
777 journal_t *journal = PDE(inode)->data;
778 struct jbd2_stats_proc_session *s;
779 int rc, size;
780
781 s = kmalloc(sizeof(*s), GFP_KERNEL);
782 if (s == NULL)
783 return -ENOMEM;
784 size = sizeof(struct transaction_stats_s) * journal->j_history_max;
785 s->stats = kmalloc(size, GFP_KERNEL);
786 if (s->stats == NULL) {
787 kfree(s);
788 return -ENOMEM;
789 }
790 spin_lock(&journal->j_history_lock);
791 memcpy(s->stats, journal->j_history, size);
792 s->max = journal->j_history_max;
793 s->start = journal->j_history_cur % s->max;
794 spin_unlock(&journal->j_history_lock);
795
796 rc = seq_open(file, &jbd2_seq_history_ops);
797 if (rc == 0) {
798 struct seq_file *m = file->private_data;
799 m->private = s;
800 } else {
801 kfree(s->stats);
802 kfree(s);
803 }
804 return rc;
805
806}
807
808static int jbd2_seq_history_release(struct inode *inode, struct file *file)
809{
810 struct seq_file *seq = file->private_data;
811 struct jbd2_stats_proc_session *s = seq->private;
812
813 kfree(s->stats);
814 kfree(s);
815 return seq_release(inode, file);
816}
817
818static struct file_operations jbd2_seq_history_fops = {
819 .owner = THIS_MODULE,
820 .open = jbd2_seq_history_open,
821 .read = seq_read,
822 .llseek = seq_lseek,
823 .release = jbd2_seq_history_release,
824};
825
826static void *jbd2_seq_info_start(struct seq_file *seq, loff_t *pos) 679static void *jbd2_seq_info_start(struct seq_file *seq, loff_t *pos)
827{ 680{
828 return *pos ? NULL : SEQ_START_TOKEN; 681 return *pos ? NULL : SEQ_START_TOKEN;
@@ -839,29 +692,29 @@ static int jbd2_seq_info_show(struct seq_file *seq, void *v)
839 692
840 if (v != SEQ_START_TOKEN) 693 if (v != SEQ_START_TOKEN)
841 return 0; 694 return 0;
842 seq_printf(seq, "%lu transaction, each upto %u blocks\n", 695 seq_printf(seq, "%lu transaction, each up to %u blocks\n",
843 s->stats->ts_tid, 696 s->stats->ts_tid,
844 s->journal->j_max_transaction_buffers); 697 s->journal->j_max_transaction_buffers);
845 if (s->stats->ts_tid == 0) 698 if (s->stats->ts_tid == 0)
846 return 0; 699 return 0;
847 seq_printf(seq, "average: \n %ums waiting for transaction\n", 700 seq_printf(seq, "average: \n %ums waiting for transaction\n",
848 jiffies_to_msecs(s->stats->u.run.rs_wait / s->stats->ts_tid)); 701 jiffies_to_msecs(s->stats->run.rs_wait / s->stats->ts_tid));
849 seq_printf(seq, " %ums running transaction\n", 702 seq_printf(seq, " %ums running transaction\n",
850 jiffies_to_msecs(s->stats->u.run.rs_running / s->stats->ts_tid)); 703 jiffies_to_msecs(s->stats->run.rs_running / s->stats->ts_tid));
851 seq_printf(seq, " %ums transaction was being locked\n", 704 seq_printf(seq, " %ums transaction was being locked\n",
852 jiffies_to_msecs(s->stats->u.run.rs_locked / s->stats->ts_tid)); 705 jiffies_to_msecs(s->stats->run.rs_locked / s->stats->ts_tid));
853 seq_printf(seq, " %ums flushing data (in ordered mode)\n", 706 seq_printf(seq, " %ums flushing data (in ordered mode)\n",
854 jiffies_to_msecs(s->stats->u.run.rs_flushing / s->stats->ts_tid)); 707 jiffies_to_msecs(s->stats->run.rs_flushing / s->stats->ts_tid));
855 seq_printf(seq, " %ums logging transaction\n", 708 seq_printf(seq, " %ums logging transaction\n",
856 jiffies_to_msecs(s->stats->u.run.rs_logging / s->stats->ts_tid)); 709 jiffies_to_msecs(s->stats->run.rs_logging / s->stats->ts_tid));
857 seq_printf(seq, " %lluus average transaction commit time\n", 710 seq_printf(seq, " %lluus average transaction commit time\n",
858 div_u64(s->journal->j_average_commit_time, 1000)); 711 div_u64(s->journal->j_average_commit_time, 1000));
859 seq_printf(seq, " %lu handles per transaction\n", 712 seq_printf(seq, " %lu handles per transaction\n",
860 s->stats->u.run.rs_handle_count / s->stats->ts_tid); 713 s->stats->run.rs_handle_count / s->stats->ts_tid);
861 seq_printf(seq, " %lu blocks per transaction\n", 714 seq_printf(seq, " %lu blocks per transaction\n",
862 s->stats->u.run.rs_blocks / s->stats->ts_tid); 715 s->stats->run.rs_blocks / s->stats->ts_tid);
863 seq_printf(seq, " %lu logged blocks per transaction\n", 716 seq_printf(seq, " %lu logged blocks per transaction\n",
864 s->stats->u.run.rs_blocks_logged / s->stats->ts_tid); 717 s->stats->run.rs_blocks_logged / s->stats->ts_tid);
865 return 0; 718 return 0;
866} 719}
867 720
@@ -931,8 +784,6 @@ static void jbd2_stats_proc_init(journal_t *journal)
931{ 784{
932 journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats); 785 journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats);
933 if (journal->j_proc_entry) { 786 if (journal->j_proc_entry) {
934 proc_create_data("history", S_IRUGO, journal->j_proc_entry,
935 &jbd2_seq_history_fops, journal);
936 proc_create_data("info", S_IRUGO, journal->j_proc_entry, 787 proc_create_data("info", S_IRUGO, journal->j_proc_entry,
937 &jbd2_seq_info_fops, journal); 788 &jbd2_seq_info_fops, journal);
938 } 789 }
@@ -941,27 +792,9 @@ static void jbd2_stats_proc_init(journal_t *journal)
941static void jbd2_stats_proc_exit(journal_t *journal) 792static void jbd2_stats_proc_exit(journal_t *journal)
942{ 793{
943 remove_proc_entry("info", journal->j_proc_entry); 794 remove_proc_entry("info", journal->j_proc_entry);
944 remove_proc_entry("history", journal->j_proc_entry);
945 remove_proc_entry(journal->j_devname, proc_jbd2_stats); 795 remove_proc_entry(journal->j_devname, proc_jbd2_stats);
946} 796}
947 797
948static void journal_init_stats(journal_t *journal)
949{
950 int size;
951
952 if (!proc_jbd2_stats)
953 return;
954
955 journal->j_history_max = 100;
956 size = sizeof(struct transaction_stats_s) * journal->j_history_max;
957 journal->j_history = kzalloc(size, GFP_KERNEL);
958 if (!journal->j_history) {
959 journal->j_history_max = 0;
960 return;
961 }
962 spin_lock_init(&journal->j_history_lock);
963}
964
965/* 798/*
966 * Management for journal control blocks: functions to create and 799 * Management for journal control blocks: functions to create and
967 * destroy journal_t structures, and to initialise and read existing 800 * destroy journal_t structures, and to initialise and read existing
@@ -1006,7 +839,7 @@ static journal_t * journal_init_common (void)
1006 goto fail; 839 goto fail;
1007 } 840 }
1008 841
1009 journal_init_stats(journal); 842 spin_lock_init(&journal->j_history_lock);
1010 843
1011 return journal; 844 return journal;
1012fail: 845fail: