aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2012-08-23 10:37:59 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2012-09-24 05:47:20 -0400
commit9e733d3923fb0e4eeae7b827019332d246576a22 (patch)
tree37fc39212545c6bc3c2de8f0293cb9952802f1e8 /fs
parent137834a696fd51ef8c710a0ad854b585027c7df0 (diff)
GFS2: Improve block reservation tracing
This patch improves the tracing of block reservations by removing some corner cases and also providing more useful detail in the traces. A new field is added to the reservation structure to contain the inode number. This is used since in certain contexts it is not possible to access the inode itself to obtain this information. As a result we can then display the inode number for all tracepoints and also in case we dump the resource group. The "del" tracepoint operation has been removed. This could be called with the reservation rgrp set to NULL. That resulted in not printing the device number, and thus making the information largely useless anyway. Also, the conditional on the rgrp being NULL can then be removed from the tracepoint. After this change, all the block reservation tracepoint calls will be called with the rgrp information. The existing ins,clm and tdel calls to the block reservation tracepoint are sufficient to track the entire life of the block reservation. In gfs2_block_alloc() the error detection is updated to print out the inode number of the problematic inode. This can then be compared against the information in the glock dump,tracepoints, etc. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/incore.h6
-rw-r--r--fs/gfs2/rgrp.c22
-rw-r--r--fs/gfs2/trace_gfs2.h18
3 files changed, 20 insertions, 26 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 99d7c64b5091..6aaa07c7c731 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -268,13 +268,11 @@ struct gfs2_blkreserv {
268 /* components used during write (step 1): */ 268 /* components used during write (step 1): */
269 atomic_t rs_sizehint; /* hint of the write size */ 269 atomic_t rs_sizehint; /* hint of the write size */
270 270
271 /* components used during get_local_rgrp (step 3): */
272 struct gfs2_rbm rs_rbm;
273 struct gfs2_holder rs_rgd_gh; /* Filled in by get_local_rgrp */ 271 struct gfs2_holder rs_rgd_gh; /* Filled in by get_local_rgrp */
274 struct rb_node rs_node; /* link to other block reservations */ 272 struct rb_node rs_node; /* link to other block reservations */
275 273 struct gfs2_rbm rs_rbm; /* Start of reservation */
276 /* components used during block searches and assignments (step 4): */
277 u32 rs_free; /* how many blocks are still free */ 274 u32 rs_free; /* how many blocks are still free */
275 u64 rs_inum; /* Inode number for reservation */
278 276
279 /* ancillary quota stuff */ 277 /* ancillary quota stuff */
280 struct gfs2_quota_data *rs_qa_qd[2 * MAXQUOTAS]; 278 struct gfs2_quota_data *rs_qa_qd[2 * MAXQUOTAS];
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 30c864e70298..87ee0b70f818 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -448,10 +448,11 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
448 return error; 448 return error;
449} 449}
450 450
451static void dump_rs(struct seq_file *seq, struct gfs2_blkreserv *rs) 451static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
452{ 452{
453 gfs2_print_dbg(seq, " r: %llu s:%llu b:%u f:%u\n", 453 gfs2_print_dbg(seq, " B: n:%llu s:%llu b:%u f:%u\n",
454 rs->rs_rbm.rgd->rd_addr, gfs2_rbm_to_block(&rs->rs_rbm), 454 (unsigned long long)rs->rs_inum,
455 (unsigned long long)gfs2_rbm_to_block(&rs->rs_rbm),
455 rs->rs_rbm.offset, rs->rs_free); 456 rs->rs_rbm.offset, rs->rs_free);
456} 457}
457 458
@@ -468,7 +469,7 @@ static void __rs_deltree(struct gfs2_inode *ip, struct gfs2_blkreserv *rs)
468 return; 469 return;
469 470
470 rgd = rs->rs_rbm.rgd; 471 rgd = rs->rs_rbm.rgd;
471 trace_gfs2_rs(ip, rs, TRACE_RS_TREEDEL); 472 trace_gfs2_rs(rs, TRACE_RS_TREEDEL);
472 rb_erase(&rs->rs_node, &rgd->rd_rstree); 473 rb_erase(&rs->rs_node, &rgd->rd_rstree);
473 RB_CLEAR_NODE(&rs->rs_node); 474 RB_CLEAR_NODE(&rs->rs_node);
474 BUG_ON(!rgd->rd_rs_cnt); 475 BUG_ON(!rgd->rd_rs_cnt);
@@ -511,7 +512,6 @@ void gfs2_rs_delete(struct gfs2_inode *ip)
511 down_write(&ip->i_rw_mutex); 512 down_write(&ip->i_rw_mutex);
512 if (ip->i_res) { 513 if (ip->i_res) {
513 gfs2_rs_deltree(ip, ip->i_res); 514 gfs2_rs_deltree(ip, ip->i_res);
514 trace_gfs2_rs(ip, ip->i_res, TRACE_RS_DELETE);
515 BUG_ON(ip->i_res->rs_free); 515 BUG_ON(ip->i_res->rs_free);
516 kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); 516 kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
517 ip->i_res = NULL; 517 ip->i_res = NULL;
@@ -1253,6 +1253,7 @@ static struct gfs2_blkreserv *rs_insert(struct gfs2_bitmap *bi,
1253 rs->rs_free = amount; 1253 rs->rs_free = amount;
1254 rs->rs_rbm.offset = biblk; 1254 rs->rs_rbm.offset = biblk;
1255 rs->rs_rbm.bi = bi; 1255 rs->rs_rbm.bi = bi;
1256 rs->rs_inum = ip->i_no_addr;
1256 rb_link_node(&rs->rs_node, parent, newn); 1257 rb_link_node(&rs->rs_node, parent, newn);
1257 rb_insert_color(&rs->rs_node, &rgd->rd_rstree); 1258 rb_insert_color(&rs->rs_node, &rgd->rd_rstree);
1258 1259
@@ -1260,7 +1261,7 @@ static struct gfs2_blkreserv *rs_insert(struct gfs2_bitmap *bi,
1260 rgd->rd_reserved += amount; /* blocks reserved */ 1261 rgd->rd_reserved += amount; /* blocks reserved */
1261 rgd->rd_rs_cnt++; /* number of in-tree reservations */ 1262 rgd->rd_rs_cnt++; /* number of in-tree reservations */
1262 spin_unlock(&rgd->rd_rsspin); 1263 spin_unlock(&rgd->rd_rsspin);
1263 trace_gfs2_rs(ip, rs, TRACE_RS_INSERT); 1264 trace_gfs2_rs(rs, TRACE_RS_INSERT);
1264 return rs; 1265 return rs;
1265} 1266}
1266 1267
@@ -1966,7 +1967,7 @@ static void gfs2_adjust_reservation(struct gfs2_inode *ip,
1966 rlen = min(rs->rs_free, len); 1967 rlen = min(rs->rs_free, len);
1967 rs->rs_free -= rlen; 1968 rs->rs_free -= rlen;
1968 rgd->rd_reserved -= rlen; 1969 rgd->rd_reserved -= rlen;
1969 trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM); 1970 trace_gfs2_rs(rs, TRACE_RS_CLAIM);
1970 if (rs->rs_free && !ret) 1971 if (rs->rs_free && !ret)
1971 goto out; 1972 goto out;
1972 } 1973 }
@@ -2005,10 +2006,6 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
2005 else 2006 else
2006 goal = rbm.rgd->rd_last_alloc + rbm.rgd->rd_data0; 2007 goal = rbm.rgd->rd_last_alloc + rbm.rgd->rd_data0;
2007 2008
2008 if ((goal < rbm.rgd->rd_data0) ||
2009 (goal >= rbm.rgd->rd_data0 + rbm.rgd->rd_data))
2010 rbm.rgd = gfs2_blk2rgrpd(sdp, goal, 1);
2011
2012 gfs2_rbm_from_block(&rbm, goal); 2009 gfs2_rbm_from_block(&rbm, goal);
2013 error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, ip, false); 2010 error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, ip, false);
2014 2011
@@ -2019,7 +2016,8 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
2019 2016
2020 /* Since all blocks are reserved in advance, this shouldn't happen */ 2017 /* Since all blocks are reserved in advance, this shouldn't happen */
2021 if (error) { 2018 if (error) {
2022 fs_warn(sdp, "error=%d, nblocks=%u, full=%d\n", error, *nblocks, 2019 fs_warn(sdp, "inum=%llu error=%d, nblocks=%u, full=%d\n",
2020 (unsigned long long)ip->i_no_addr, error, *nblocks,
2023 test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags)); 2021 test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags));
2024 goto rgrp_error; 2022 goto rgrp_error;
2025 } 2023 }
diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h
index b947aa4dfca4..bbdc78af60ca 100644
--- a/fs/gfs2/trace_gfs2.h
+++ b/fs/gfs2/trace_gfs2.h
@@ -509,10 +509,9 @@ TRACE_EVENT(gfs2_block_alloc,
509/* Keep track of multi-block reservations as they are allocated/freed */ 509/* Keep track of multi-block reservations as they are allocated/freed */
510TRACE_EVENT(gfs2_rs, 510TRACE_EVENT(gfs2_rs,
511 511
512 TP_PROTO(const struct gfs2_inode *ip, const struct gfs2_blkreserv *rs, 512 TP_PROTO(const struct gfs2_blkreserv *rs, u8 func),
513 u8 func),
514 513
515 TP_ARGS(ip, rs, func), 514 TP_ARGS(rs, func),
516 515
517 TP_STRUCT__entry( 516 TP_STRUCT__entry(
518 __field( dev_t, dev ) 517 __field( dev_t, dev )
@@ -526,18 +525,17 @@ TRACE_EVENT(gfs2_rs,
526 ), 525 ),
527 526
528 TP_fast_assign( 527 TP_fast_assign(
529 __entry->dev = rs->rs_rbm.rgd ? rs->rs_rbm.rgd->rd_sbd->sd_vfs->s_dev : 0; 528 __entry->dev = rs->rs_rbm.rgd->rd_sbd->sd_vfs->s_dev;
530 __entry->rd_addr = rs->rs_rbm.rgd ? rs->rs_rbm.rgd->rd_addr : 0; 529 __entry->rd_addr = rs->rs_rbm.rgd->rd_addr;
531 __entry->rd_free_clone = rs->rs_rbm.rgd ? rs->rs_rbm.rgd->rd_free_clone : 0; 530 __entry->rd_free_clone = rs->rs_rbm.rgd->rd_free_clone;
532 __entry->rd_reserved = rs->rs_rbm.rgd ? rs->rs_rbm.rgd->rd_reserved : 0; 531 __entry->rd_reserved = rs->rs_rbm.rgd->rd_reserved;
533 __entry->inum = ip ? ip->i_no_addr : 0; 532 __entry->inum = rs->rs_inum;
534 __entry->start = gfs2_rbm_to_block(&rs->rs_rbm); 533 __entry->start = gfs2_rbm_to_block(&rs->rs_rbm);
535 __entry->free = rs->rs_free; 534 __entry->free = rs->rs_free;
536 __entry->func = func; 535 __entry->func = func;
537 ), 536 ),
538 537
539 TP_printk("%u,%u bmap %llu resrv %llu rg:%llu rf:%lu rr:%lu %s " 538 TP_printk("%u,%u bmap %llu resrv %llu rg:%llu rf:%lu rr:%lu %s f:%lu",
540 "f:%lu",
541 MAJOR(__entry->dev), MINOR(__entry->dev), 539 MAJOR(__entry->dev), MINOR(__entry->dev),
542 (unsigned long long)__entry->inum, 540 (unsigned long long)__entry->inum,
543 (unsigned long long)__entry->start, 541 (unsigned long long)__entry->start,