mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	[GFS2] Fix leak of gfs2_bufdata
This fixes a memory leak of struct gfs2_bufdata and also some problems in the ordered write handling code. It needs a bit more testing, but I believe that the reference counting of ordered write buffers should now be correct. This is aimed at fixing Red Hat bugzilla: #201028 and #201082 Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
		
							parent
							
								
									fcc8abc8d4
								
							
						
					
					
						commit
						15d00c0b91
					
				
					 4 changed files with 6 additions and 11 deletions
				
			
		| 
						 | 
					@ -464,7 +464,7 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
 | 
				
			||||||
	struct gfs2_inode *ip = GFS2_I(mapping->host);
 | 
						struct gfs2_inode *ip = GFS2_I(mapping->host);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tr->tr_touched = 1;
 | 
						tr->tr_touched = 1;
 | 
				
			||||||
	if (!list_empty(&bd->bd_list_tr) &&
 | 
						if (list_empty(&bd->bd_list_tr) &&
 | 
				
			||||||
	    (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
 | 
						    (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
 | 
				
			||||||
		tr->tr_num_buf++;
 | 
							tr->tr_num_buf++;
 | 
				
			||||||
		list_add(&bd->bd_list_tr, &tr->tr_list_buf);
 | 
							list_add(&bd->bd_list_tr, &tr->tr_list_buf);
 | 
				
			||||||
| 
						 | 
					@ -473,7 +473,7 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	gfs2_trans_add_gl(bd->bd_gl);
 | 
						gfs2_trans_add_gl(bd->bd_gl);
 | 
				
			||||||
	gfs2_log_lock(sdp);
 | 
						gfs2_log_lock(sdp);
 | 
				
			||||||
	if (!list_empty(&le->le_list)) {
 | 
						if (list_empty(&le->le_list)) {
 | 
				
			||||||
		if (ip->i_di.di_flags & GFS2_DIF_JDATA)
 | 
							if (ip->i_di.di_flags & GFS2_DIF_JDATA)
 | 
				
			||||||
			sdp->sd_log_num_jdata++;
 | 
								sdp->sd_log_num_jdata++;
 | 
				
			||||||
		sdp->sd_log_num_databuf++;
 | 
							sdp->sd_log_num_databuf++;
 | 
				
			||||||
| 
						 | 
					@ -640,10 +640,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
 | 
				
			||||||
				 bd_le.le_list);
 | 
									 bd_le.le_list);
 | 
				
			||||||
		list_del(&bd1->bd_le.le_list);
 | 
							list_del(&bd1->bd_le.le_list);
 | 
				
			||||||
		sdp->sd_log_num_databuf--;
 | 
							sdp->sd_log_num_databuf--;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		bh = bd1->bd_bh;
 | 
							bh = bd1->bd_bh;
 | 
				
			||||||
		if (bh) {
 | 
							if (bh) {
 | 
				
			||||||
			bh->b_private = NULL;
 | 
								bh->b_private = NULL;
 | 
				
			||||||
 | 
								get_bh(bh);
 | 
				
			||||||
			gfs2_log_unlock(sdp);
 | 
								gfs2_log_unlock(sdp);
 | 
				
			||||||
			wait_on_buffer(bh);
 | 
								wait_on_buffer(bh);
 | 
				
			||||||
			brelse(bh);
 | 
								brelse(bh);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -464,7 +464,6 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
 | 
				
			||||||
		lops_init_le(&bd->bd_le, &gfs2_buf_lops);
 | 
							lops_init_le(&bd->bd_le, &gfs2_buf_lops);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		lops_init_le(&bd->bd_le, &gfs2_databuf_lops);
 | 
							lops_init_le(&bd->bd_le, &gfs2_databuf_lops);
 | 
				
			||||||
		get_bh(bh);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	bh->b_private = bd;
 | 
						bh->b_private = bd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -581,10 +581,8 @@ static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh)
 | 
				
			||||||
	if (bd) {
 | 
						if (bd) {
 | 
				
			||||||
		bd->bd_bh = NULL;
 | 
							bd->bd_bh = NULL;
 | 
				
			||||||
		bh->b_private = NULL;
 | 
							bh->b_private = NULL;
 | 
				
			||||||
		gfs2_log_unlock(sdp);
 | 
						}
 | 
				
			||||||
		brelse(bh);
 | 
						gfs2_log_unlock(sdp);
 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		gfs2_log_unlock(sdp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lock_buffer(bh);
 | 
						lock_buffer(bh);
 | 
				
			||||||
	clear_buffer_dirty(bh);
 | 
						clear_buffer_dirty(bh);
 | 
				
			||||||
| 
						 | 
					@ -598,7 +596,7 @@ static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gfs2_invalidatepage(struct page *page, unsigned long offset)
 | 
					static void gfs2_invalidatepage(struct page *page, unsigned long offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct gfs2_sbd *sdp = page->mapping->host->i_sb->s_fs_info;
 | 
						struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
 | 
				
			||||||
	struct buffer_head *head, *bh, *next;
 | 
						struct buffer_head *head, *bh, *next;
 | 
				
			||||||
	unsigned int curr_off = 0;
 | 
						unsigned int curr_off = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,8 +216,6 @@ static int gfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(buf, 0, sizeof(struct kstatfs));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	buf->f_type = GFS2_MAGIC;
 | 
						buf->f_type = GFS2_MAGIC;
 | 
				
			||||||
	buf->f_bsize = sdp->sd_sb.sb_bsize;
 | 
						buf->f_bsize = sdp->sd_sb.sb_bsize;
 | 
				
			||||||
	buf->f_blocks = sc.sc_total;
 | 
						buf->f_blocks = sc.sc_total;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue