Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

jbd2: add tracepoints which provide per-handle statistics

Handles which stay open a long time are problematic when it comes time
to close down a transaction so it can be committed. These tracepoints
will help us determine which ones are the problematic ones, and to
validate whether changes makes things better or worse.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

+131 -3
+26 -2
fs/jbd2/transaction.c
··· 30 30 #include <linux/bug.h> 31 31 #include <linux/module.h> 32 32 33 + #include <trace/events/jbd2.h> 34 + 33 35 static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); 34 36 static void __jbd2_journal_unfile_buffer(struct journal_head *jh); 35 37 ··· 309 307 */ 310 308 update_t_max_wait(transaction, ts); 311 309 handle->h_transaction = transaction; 310 + handle->h_requested_credits = nblocks; 311 + handle->h_start_jiffies = jiffies; 312 312 atomic_inc(&transaction->t_updates); 313 313 atomic_inc(&transaction->t_handle_count); 314 314 jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", ··· 357 353 * Return a pointer to a newly allocated handle, or an ERR_PTR() value 358 354 * on failure. 359 355 */ 360 - handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask) 356 + handle_t *jbd2__journal_start(journal_t *journal, int nblocks, gfp_t gfp_mask, 357 + unsigned int type, unsigned int line_no) 361 358 { 362 359 handle_t *handle = journal_current_handle(); 363 360 int err; ··· 384 379 current->journal_info = NULL; 385 380 handle = ERR_PTR(err); 386 381 } 382 + handle->h_type = type; 383 + handle->h_line_no = line_no; 384 + trace_jbd2_handle_start(journal->j_fs_dev->bd_dev, 385 + handle->h_transaction->t_tid, type, 386 + line_no, nblocks); 387 387 return handle; 388 388 } 389 389 EXPORT_SYMBOL(jbd2__journal_start); ··· 396 386 397 387 handle_t *jbd2_journal_start(journal_t *journal, int nblocks) 398 388 { 399 - return jbd2__journal_start(journal, nblocks, GFP_NOFS); 389 + return jbd2__journal_start(journal, nblocks, GFP_NOFS, 0, 0); 400 390 } 401 391 EXPORT_SYMBOL(jbd2_journal_start); 402 392 ··· 458 448 goto unlock; 459 449 } 460 450 451 + trace_jbd2_handle_extend(journal->j_fs_dev->bd_dev, 452 + handle->h_transaction->t_tid, 453 + handle->h_type, handle->h_line_no, 454 + handle->h_buffer_credits, 455 + nblocks); 456 + 461 457 handle->h_buffer_credits += nblocks; 458 + handle->h_requested_credits += nblocks; 462 459 atomic_add(nblocks, &transaction->t_outstanding_credits); 463 460 result = 0; 464 461 ··· 1394 1377 } 1395 1378 1396 1379 jbd_debug(4, "Handle %p going down\n", handle); 1380 + trace_jbd2_handle_stats(journal->j_fs_dev->bd_dev, 1381 + handle->h_transaction->t_tid, 1382 + handle->h_type, handle->h_line_no, 1383 + jiffies - handle->h_start_jiffies, 1384 + handle->h_sync, handle->h_requested_credits, 1385 + (handle->h_requested_credits - 1386 + handle->h_buffer_credits)); 1397 1387 1398 1388 /* 1399 1389 * Implement synchronous transaction batching. If the handle
+7 -1
include/linux/jbd2.h
··· 400 400 unsigned int h_sync: 1; /* sync-on-close */ 401 401 unsigned int h_jdata: 1; /* force data journaling */ 402 402 unsigned int h_aborted: 1; /* fatal error on handle */ 403 + unsigned int h_type: 8; /* for handle statistics */ 404 + unsigned int h_line_no: 16; /* for handle statistics */ 405 + 406 + unsigned long h_start_jiffies; 407 + unsigned int h_requested_credits; 403 408 404 409 #ifdef CONFIG_DEBUG_LOCK_ALLOC 405 410 struct lockdep_map h_lockdep_map; ··· 1076 1071 */ 1077 1072 1078 1073 extern handle_t *jbd2_journal_start(journal_t *, int nblocks); 1079 - extern handle_t *jbd2__journal_start(journal_t *, int nblocks, gfp_t gfp_mask); 1074 + extern handle_t *jbd2__journal_start(journal_t *, int nblocks, gfp_t gfp_mask, 1075 + unsigned int type, unsigned int line_no); 1080 1076 extern int jbd2_journal_restart(handle_t *, int nblocks); 1081 1077 extern int jbd2__journal_restart(handle_t *, int nblocks, gfp_t gfp_mask); 1082 1078 extern int jbd2_journal_extend (handle_t *, int nblocks);
+98
include/trace/events/jbd2.h
··· 132 132 (unsigned long) __entry->ino) 133 133 ); 134 134 135 + TRACE_EVENT(jbd2_handle_start, 136 + TP_PROTO(dev_t dev, unsigned long tid, unsigned int type, 137 + unsigned int line_no, int requested_blocks), 138 + 139 + TP_ARGS(dev, tid, type, line_no, requested_blocks), 140 + 141 + TP_STRUCT__entry( 142 + __field( dev_t, dev ) 143 + __field( unsigned long, tid ) 144 + __field( unsigned int, type ) 145 + __field( unsigned int, line_no ) 146 + __field( int, requested_blocks) 147 + ), 148 + 149 + TP_fast_assign( 150 + __entry->dev = dev; 151 + __entry->tid = tid; 152 + __entry->type = type; 153 + __entry->line_no = line_no; 154 + __entry->requested_blocks = requested_blocks; 155 + ), 156 + 157 + TP_printk("dev %d,%d tid %lu type %u line_no %u " 158 + "requested_blocks %d", 159 + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, 160 + __entry->type, __entry->line_no, __entry->requested_blocks) 161 + ); 162 + 163 + TRACE_EVENT(jbd2_handle_extend, 164 + TP_PROTO(dev_t dev, unsigned long tid, unsigned int type, 165 + unsigned int line_no, int buffer_credits, 166 + int requested_blocks), 167 + 168 + TP_ARGS(dev, tid, type, line_no, buffer_credits, requested_blocks), 169 + 170 + TP_STRUCT__entry( 171 + __field( dev_t, dev ) 172 + __field( unsigned long, tid ) 173 + __field( unsigned int, type ) 174 + __field( unsigned int, line_no ) 175 + __field( int, buffer_credits ) 176 + __field( int, requested_blocks) 177 + ), 178 + 179 + TP_fast_assign( 180 + __entry->dev = dev; 181 + __entry->tid = tid; 182 + __entry->type = type; 183 + __entry->line_no = line_no; 184 + __entry->buffer_credits = buffer_credits; 185 + __entry->requested_blocks = requested_blocks; 186 + ), 187 + 188 + TP_printk("dev %d,%d tid %lu type %u line_no %u " 189 + "buffer_credits %d requested_blocks %d", 190 + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, 191 + __entry->type, __entry->line_no, __entry->buffer_credits, 192 + __entry->requested_blocks) 193 + ); 194 + 195 + TRACE_EVENT(jbd2_handle_stats, 196 + TP_PROTO(dev_t dev, unsigned long tid, unsigned int type, 197 + unsigned int line_no, int interval, int sync, 198 + int requested_blocks, int dirtied_blocks), 199 + 200 + TP_ARGS(dev, tid, type, line_no, interval, sync, 201 + requested_blocks, dirtied_blocks), 202 + 203 + TP_STRUCT__entry( 204 + __field( dev_t, dev ) 205 + __field( unsigned long, tid ) 206 + __field( unsigned int, type ) 207 + __field( unsigned int, line_no ) 208 + __field( int, interval ) 209 + __field( int, sync ) 210 + __field( int, requested_blocks) 211 + __field( int, dirtied_blocks ) 212 + ), 213 + 214 + TP_fast_assign( 215 + __entry->dev = dev; 216 + __entry->tid = tid; 217 + __entry->type = type; 218 + __entry->line_no = line_no; 219 + __entry->interval = interval; 220 + __entry->sync = sync; 221 + __entry->requested_blocks = requested_blocks; 222 + __entry->dirtied_blocks = dirtied_blocks; 223 + ), 224 + 225 + TP_printk("dev %d,%d tid %lu type %u line_no %u interval %d " 226 + "sync %d requested_blocks %d dirtied_blocks %d", 227 + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, 228 + __entry->type, __entry->line_no, __entry->interval, 229 + __entry->sync, __entry->requested_blocks, 230 + __entry->dirtied_blocks) 231 + ); 232 + 135 233 TRACE_EVENT(jbd2_run_stats, 136 234 TP_PROTO(dev_t dev, unsigned long tid, 137 235 struct transaction_run_stats_s *stats),