Commit bf6993276f74d46776f35c45ddef29b981b1d1c6

Authored by Theodore Ts'o
1 parent 296c355cd6

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>

Showing 5 changed files with 130 additions and 228 deletions Side-by-side Diff

fs/jbd2/checkpoint.c
... ... @@ -643,6 +643,7 @@
643 643  
644 644 int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
645 645 {
  646 + struct transaction_chp_stats_s *stats;
646 647 transaction_t *transaction;
647 648 journal_t *journal;
648 649 int ret = 0;
... ... @@ -679,6 +680,12 @@
679 680  
680 681 /* OK, that was the last buffer for the transaction: we can now
681 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 690 __jbd2_journal_drop_transaction(journal, transaction);
684 691 kfree(transaction);
... ... @@ -410,10 +410,10 @@
410 410 if (commit_transaction->t_synchronous_commit)
411 411 write_op = WRITE_SYNC_PLUG;
412 412 trace_jbd2_commit_locking(journal, commit_transaction);
413   - stats.u.run.rs_wait = commit_transaction->t_max_wait;
414   - stats.u.run.rs_locked = jiffies;
415   - stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
416   - stats.u.run.rs_locked);
  413 + stats.run.rs_wait = commit_transaction->t_max_wait;
  414 + stats.run.rs_locked = jiffies;
  415 + stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
  416 + stats.run.rs_locked);
417 417  
418 418 spin_lock(&commit_transaction->t_handle_lock);
419 419 while (commit_transaction->t_updates) {
... ... @@ -486,9 +486,9 @@
486 486 jbd2_journal_switch_revoke_table(journal);
487 487  
488 488 trace_jbd2_commit_flushing(journal, commit_transaction);
489   - stats.u.run.rs_flushing = jiffies;
490   - stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked,
491   - stats.u.run.rs_flushing);
  489 + stats.run.rs_flushing = jiffies;
  490 + stats.run.rs_locked = jbd2_time_diff(stats.run.rs_locked,
  491 + stats.run.rs_flushing);
492 492  
493 493 commit_transaction->t_state = T_FLUSH;
494 494 journal->j_committing_transaction = commit_transaction;
... ... @@ -523,11 +523,11 @@
523 523 spin_unlock(&journal->j_state_lock);
524 524  
525 525 trace_jbd2_commit_logging(journal, commit_transaction);
526   - stats.u.run.rs_logging = jiffies;
527   - stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing,
528   - stats.u.run.rs_logging);
529   - stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits;
530   - stats.u.run.rs_blocks_logged = 0;
  526 + stats.run.rs_logging = jiffies;
  527 + stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing,
  528 + stats.run.rs_logging);
  529 + stats.run.rs_blocks = commit_transaction->t_outstanding_credits;
  530 + stats.run.rs_blocks_logged = 0;
531 531  
532 532 J_ASSERT(commit_transaction->t_nr_buffers <=
533 533 commit_transaction->t_outstanding_credits);
... ... @@ -695,7 +695,7 @@
695 695 submit_bh(write_op, bh);
696 696 }
697 697 cond_resched();
698   - stats.u.run.rs_blocks_logged += bufs;
  698 + stats.run.rs_blocks_logged += bufs;
699 699  
700 700 /* Force a new descriptor to be generated next
701 701 time round the loop. */
702 702  
703 703  
704 704  
705 705  
706 706  
... ... @@ -988,33 +988,30 @@
988 988 J_ASSERT(commit_transaction->t_state == T_COMMIT);
989 989  
990 990 commit_transaction->t_start = jiffies;
991   - stats.u.run.rs_logging = jbd2_time_diff(stats.u.run.rs_logging,
992   - commit_transaction->t_start);
  991 + stats.run.rs_logging = jbd2_time_diff(stats.run.rs_logging,
  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 997 stats.ts_tid = commit_transaction->t_tid;
999   - stats.u.run.rs_handle_count = commit_transaction->t_handle_count;
1000   - spin_lock(&journal->j_history_lock);
1001   - memcpy(journal->j_history + journal->j_history_cur, &stats,
1002   - sizeof(stats));
1003   - if (++journal->j_history_cur == journal->j_history_max)
1004   - journal->j_history_cur = 0;
  998 + stats.run.rs_handle_count = commit_transaction->t_handle_count;
  999 + trace_jbd2_run_stats(journal->j_fs_dev->bd_dev,
  1000 + commit_transaction->t_tid, &stats.run);
1005 1001  
1006 1002 /*
1007 1003 * Calculate overall stats
1008 1004 */
  1005 + spin_lock(&journal->j_history_lock);
1009 1006 journal->j_stats.ts_tid++;
1010   - journal->j_stats.u.run.rs_wait += stats.u.run.rs_wait;
1011   - journal->j_stats.u.run.rs_running += stats.u.run.rs_running;
1012   - journal->j_stats.u.run.rs_locked += stats.u.run.rs_locked;
1013   - journal->j_stats.u.run.rs_flushing += stats.u.run.rs_flushing;
1014   - journal->j_stats.u.run.rs_logging += stats.u.run.rs_logging;
1015   - journal->j_stats.u.run.rs_handle_count += stats.u.run.rs_handle_count;
1016   - journal->j_stats.u.run.rs_blocks += stats.u.run.rs_blocks;
1017   - journal->j_stats.u.run.rs_blocks_logged += stats.u.run.rs_blocks_logged;
  1007 + journal->j_stats.run.rs_wait += stats.run.rs_wait;
  1008 + journal->j_stats.run.rs_running += stats.run.rs_running;
  1009 + journal->j_stats.run.rs_locked += stats.run.rs_locked;
  1010 + journal->j_stats.run.rs_flushing += stats.run.rs_flushing;
  1011 + journal->j_stats.run.rs_logging += stats.run.rs_logging;
  1012 + journal->j_stats.run.rs_handle_count += stats.run.rs_handle_count;
  1013 + journal->j_stats.run.rs_blocks += stats.run.rs_blocks;
  1014 + journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged;
1018 1015 spin_unlock(&journal->j_history_lock);
1019 1016  
1020 1017 commit_transaction->t_state = T_FINISHED;
... ... @@ -676,153 +676,6 @@
676 676 int max;
677 677 };
678 678  
679   -static 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   -
698   -static 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   -
719   -static 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   -
731   -static 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   -
764   -static void jbd2_seq_history_stop(struct seq_file *seq, void *v)
765   -{
766   -}
767   -
768   -static 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   -
775   -static 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   -
808   -static 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   -
818   -static 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   -
826 679 static void *jbd2_seq_info_start(struct seq_file *seq, loff_t *pos)
827 680 {
828 681 return *pos ? NULL : SEQ_START_TOKEN;
829 682  
830 683  
831 684  
832 685  
833 686  
834 687  
835 688  
836 689  
... ... @@ -839,29 +692,29 @@
839 692  
840 693 if (v != SEQ_START_TOKEN)
841 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 696 s->stats->ts_tid,
844 697 s->journal->j_max_transaction_buffers);
845 698 if (s->stats->ts_tid == 0)
846 699 return 0;
847 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 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 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 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 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 710 seq_printf(seq, " %lluus average transaction commit time\n",
858 711 div_u64(s->journal->j_average_commit_time, 1000));
859 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 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 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 718 return 0;
866 719 }
867 720  
... ... @@ -931,8 +784,6 @@
931 784 {
932 785 journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats);
933 786 if (journal->j_proc_entry) {
934   - proc_create_data("history", S_IRUGO, journal->j_proc_entry,
935   - &jbd2_seq_history_fops, journal);
936 787 proc_create_data("info", S_IRUGO, journal->j_proc_entry,
937 788 &jbd2_seq_info_fops, journal);
938 789 }
939 790  
... ... @@ -941,27 +792,9 @@
941 792 static void jbd2_stats_proc_exit(journal_t *journal)
942 793 {
943 794 remove_proc_entry("info", journal->j_proc_entry);
944   - remove_proc_entry("history", journal->j_proc_entry);
945 795 remove_proc_entry(journal->j_devname, proc_jbd2_stats);
946 796 }
947 797  
948   -static 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 799 * Management for journal control blocks: functions to create and
967 800 * destroy journal_t structures, and to initialise and read existing
... ... @@ -1006,7 +839,7 @@
1006 839 goto fail;
1007 840 }
1008 841  
1009   - journal_init_stats(journal);
  842 + spin_lock_init(&journal->j_history_lock);
1010 843  
1011 844 return journal;
1012 845 fail:
include/linux/jbd2.h
... ... @@ -464,9 +464,9 @@
464 464 */
465 465 struct transaction_chp_stats_s {
466 466 unsigned long cs_chp_time;
467   - unsigned long cs_forced_to_close;
468   - unsigned long cs_written;
469   - unsigned long cs_dropped;
  467 + __u32 cs_forced_to_close;
  468 + __u32 cs_written;
  469 + __u32 cs_dropped;
470 470 };
471 471  
472 472 /* The transaction_t type is the guts of the journaling mechanism. It
473 473  
474 474  
475 475  
... ... @@ -668,23 +668,16 @@
668 668 unsigned long rs_flushing;
669 669 unsigned long rs_logging;
670 670  
671   - unsigned long rs_handle_count;
672   - unsigned long rs_blocks;
673   - unsigned long rs_blocks_logged;
  671 + __u32 rs_handle_count;
  672 + __u32 rs_blocks;
  673 + __u32 rs_blocks_logged;
674 674 };
675 675  
676 676 struct transaction_stats_s {
677   - int ts_type;
678 677 unsigned long ts_tid;
679   - union {
680   - struct transaction_run_stats_s run;
681   - struct transaction_chp_stats_s chp;
682   - } u;
  678 + struct transaction_run_stats_s run;
683 679 };
684 680  
685   -#define JBD2_STATS_RUN 1
686   -#define JBD2_STATS_CHECKPOINT 2
687   -
688 681 static inline unsigned long
689 682 jbd2_time_diff(unsigned long start, unsigned long end)
690 683 {
... ... @@ -987,12 +980,6 @@
987 980  
988 981 /*
989 982 * Journal statistics
990   - */
991   - struct transaction_stats_s *j_history;
992   - int j_history_max;
993   - int j_history_cur;
994   - /*
995   - * Protect the transactions statistics history
996 983 */
997 984 spinlock_t j_history_lock;
998 985 struct proc_dir_entry *j_proc_entry;
include/trace/events/jbd2.h
... ... @@ -7,6 +7,9 @@
7 7 #include <linux/jbd2.h>
8 8 #include <linux/tracepoint.h>
9 9  
  10 +struct transaction_chp_stats_s;
  11 +struct transaction_run_stats_s;
  12 +
10 13 TRACE_EVENT(jbd2_checkpoint,
11 14  
12 15 TP_PROTO(journal_t *journal, int result),
... ... @@ -160,6 +163,81 @@
160 163  
161 164 TP_printk("dev %s ino %lu",
162 165 jbd2_dev_to_name(__entry->dev), (unsigned long) __entry->ino)
  166 +);
  167 +
  168 +TRACE_EVENT(jbd2_run_stats,
  169 + TP_PROTO(dev_t dev, unsigned long tid,
  170 + struct transaction_run_stats_s *stats),
  171 +
  172 + TP_ARGS(dev, tid, stats),
  173 +
  174 + TP_STRUCT__entry(
  175 + __field( dev_t, dev )
  176 + __field( unsigned long, tid )
  177 + __field( unsigned long, wait )
  178 + __field( unsigned long, running )
  179 + __field( unsigned long, locked )
  180 + __field( unsigned long, flushing )
  181 + __field( unsigned long, logging )
  182 + __field( __u32, handle_count )
  183 + __field( __u32, blocks )
  184 + __field( __u32, blocks_logged )
  185 + ),
  186 +
  187 + TP_fast_assign(
  188 + __entry->dev = dev;
  189 + __entry->tid = tid;
  190 + __entry->wait = stats->rs_wait;
  191 + __entry->running = stats->rs_running;
  192 + __entry->locked = stats->rs_locked;
  193 + __entry->flushing = stats->rs_flushing;
  194 + __entry->logging = stats->rs_logging;
  195 + __entry->handle_count = stats->rs_handle_count;
  196 + __entry->blocks = stats->rs_blocks;
  197 + __entry->blocks_logged = stats->rs_blocks_logged;
  198 + ),
  199 +
  200 + TP_printk("dev %s tid %lu wait %u running %u locked %u flushing %u "
  201 + "logging %u handle_count %u blocks %u blocks_logged %u",
  202 + jbd2_dev_to_name(__entry->dev), __entry->tid,
  203 + jiffies_to_msecs(__entry->wait),
  204 + jiffies_to_msecs(__entry->running),
  205 + jiffies_to_msecs(__entry->locked),
  206 + jiffies_to_msecs(__entry->flushing),
  207 + jiffies_to_msecs(__entry->logging),
  208 + __entry->handle_count, __entry->blocks,
  209 + __entry->blocks_logged)
  210 +);
  211 +
  212 +TRACE_EVENT(jbd2_checkpoint_stats,
  213 + TP_PROTO(dev_t dev, unsigned long tid,
  214 + struct transaction_chp_stats_s *stats),
  215 +
  216 + TP_ARGS(dev, tid, stats),
  217 +
  218 + TP_STRUCT__entry(
  219 + __field( dev_t, dev )
  220 + __field( unsigned long, tid )
  221 + __field( unsigned long, chp_time )
  222 + __field( __u32, forced_to_close )
  223 + __field( __u32, written )
  224 + __field( __u32, dropped )
  225 + ),
  226 +
  227 + TP_fast_assign(
  228 + __entry->dev = dev;
  229 + __entry->tid = tid;
  230 + __entry->chp_time = stats->cs_chp_time;
  231 + __entry->forced_to_close= stats->cs_forced_to_close;
  232 + __entry->written = stats->cs_written;
  233 + __entry->dropped = stats->cs_dropped;
  234 + ),
  235 +
  236 + TP_printk("dev %s tid %lu chp_time %u forced_to_close %u "
  237 + "written %u dropped %u",
  238 + jbd2_dev_to_name(__entry->dev), __entry->tid,
  239 + jiffies_to_msecs(__entry->chp_time),
  240 + __entry->forced_to_close, __entry->written, __entry->dropped)
163 241 );
164 242  
165 243 #endif /* _TRACE_JBD2_H */