diff options
Diffstat (limited to 'fs/gfs2/meta_io.c')
| -rw-r--r-- | fs/gfs2/meta_io.c | 127 | 
1 files changed, 37 insertions, 90 deletions
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 939739c7b3f..b984a6e190b 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -31,13 +31,14 @@  #include "rgrp.h"  #include "trans.h"  #include "util.h" +#include "trace_gfs2.h"  static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wbc)  {  	struct buffer_head *bh, *head;  	int nr_underway = 0; -	int write_op = REQ_META | -		(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC_PLUG : WRITE); +	int write_op = REQ_META | REQ_PRIO | +		(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);  	BUG_ON(!PageLocked(page));  	BUG_ON(!page_has_buffers(page)); @@ -51,7 +52,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb  		/*  		 * If it's a fully non-blocking write attempt and we cannot  		 * lock the buffer then redirty the page.  Note that this can -		 * potentially cause a busy-wait loop from pdflush and kswapd +		 * potentially cause a busy-wait loop from flusher thread and kswapd  		 * activity, but those code paths have their own higher-level  		 * throttling.  		 */ @@ -94,26 +95,12 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb  const struct address_space_operations gfs2_meta_aops = {  	.writepage = gfs2_aspace_writepage,  	.releasepage = gfs2_releasepage, -	.sync_page = block_sync_page,  }; -/** - * gfs2_meta_sync - Sync all buffers associated with a glock - * @gl: The glock - * - */ - -void gfs2_meta_sync(struct gfs2_glock *gl) -{ -	struct address_space *mapping = gfs2_glock2aspace(gl); -	int error; - -	filemap_fdatawrite(mapping); -	error = filemap_fdatawait(mapping); - -	if (error) -		gfs2_io_error(gl->gl_sbd); -} +const struct address_space_operations gfs2_rgrp_aops = { +	.writepage = gfs2_aspace_writepage, +	.releasepage = gfs2_releasepage, +};  /**   * gfs2_getbuf - Get a buffer with a given address space @@ -134,6 +121,9 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)  	unsigned long index;  	unsigned int bufnum; +	if (mapping == NULL) +		mapping = &sdp->sd_aspace; +  	shift = PAGE_CACHE_SHIFT - sdp->sd_sb.sb_bsize_shift;  	index = blkno >> shift;             /* convert block to page */  	bufnum = blkno - (index << shift);  /* block buf index within page */ @@ -146,7 +136,8 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)  			yield();  		}  	} else { -		page = find_lock_page(mapping, index); +		page = find_get_page_flags(mapping, index, +						FGP_LOCK|FGP_ACCESSED);  		if (!page)  			return NULL;  	} @@ -163,7 +154,6 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)  		map_bh(bh, sdp->sd_vfs, blkno);  	unlock_page(page); -	mark_page_accessed(page);  	page_cache_release(page);  	return bh; @@ -213,8 +203,10 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,  	struct gfs2_sbd *sdp = gl->gl_sbd;  	struct buffer_head *bh; -	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) +	if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) { +		*bhp = NULL;  		return -EIO; +	}  	*bhp = bh = gfs2_getbuf(gl, blkno, CREATE); @@ -225,7 +217,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,  	}  	bh->b_end_io = end_buffer_read_sync;  	get_bh(bh); -	submit_bh(READ_SYNC | REQ_META, bh); +	submit_bh(READ_SYNC | REQ_META | REQ_PRIO, bh);  	if (!(flags & DIO_WAIT))  		return 0; @@ -235,6 +227,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,  		if (tr && tr->tr_touched)  			gfs2_io_error_bh(sdp, bh);  		brelse(bh); +		*bhp = NULL;  		return -EIO;  	} @@ -268,71 +261,34 @@ int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)  	return 0;  } -/** - * gfs2_attach_bufdata - attach a struct gfs2_bufdata structure to a buffer - * @gl: the glock the buffer belongs to - * @bh: The buffer to be attached to - * @meta: Flag to indicate whether its metadata or not - */ - -void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, -			 int meta) -{ -	struct gfs2_bufdata *bd; - -	if (meta) -		lock_page(bh->b_page); - -	if (bh->b_private) { -		if (meta) -			unlock_page(bh->b_page); -		return; -	} - -	bd = kmem_cache_zalloc(gfs2_bufdata_cachep, GFP_NOFS | __GFP_NOFAIL); -	bd->bd_bh = bh; -	bd->bd_gl = gl; - -	INIT_LIST_HEAD(&bd->bd_list_tr); -	if (meta) -		lops_init_le(&bd->bd_le, &gfs2_buf_lops); -	else -		lops_init_le(&bd->bd_le, &gfs2_databuf_lops); -	bh->b_private = bd; - -	if (meta) -		unlock_page(bh->b_page); -} -  void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta)  {  	struct address_space *mapping = bh->b_page->mapping;  	struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping);  	struct gfs2_bufdata *bd = bh->b_private; +	int was_pinned = 0;  	if (test_clear_buffer_pinned(bh)) { +		trace_gfs2_pin(bd, 0);  		atomic_dec(&sdp->sd_log_pinned); -		list_del_init(&bd->bd_le.le_list); -		if (meta) { -			gfs2_assert_warn(sdp, sdp->sd_log_num_buf); -			sdp->sd_log_num_buf--; +		list_del_init(&bd->bd_list); +		if (meta)  			tr->tr_num_buf_rm++; -		} else { -			gfs2_assert_warn(sdp, sdp->sd_log_num_databuf); -			sdp->sd_log_num_databuf--; +		else  			tr->tr_num_databuf_rm++; -		}  		tr->tr_touched = 1; +		was_pinned = 1;  		brelse(bh);  	}  	if (bd) { -		if (bd->bd_ail) { -			gfs2_remove_from_ail(bd); -			bh->b_private = NULL; -			bd->bd_bh = NULL; -			bd->bd_blkno = bh->b_blocknr; +		spin_lock(&sdp->sd_ail_lock); +		if (bd->bd_tr) {  			gfs2_trans_add_revoke(sdp, bd); +		} else if (was_pinned) { +			bh->b_private = NULL; +			kmem_cache_free(gfs2_bufdata_cachep, bd);  		} +		spin_unlock(&sdp->sd_ail_lock);  	}  	clear_buffer_dirty(bh);  	clear_buffer_uptodate(bh); @@ -372,33 +328,24 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)   * @ip: The GFS2 inode   * @height: The level of this buf in the metadata (indir addr) tree (if any)   * @num: The block number (device relative) of the buffer - * @new: Non-zero if we may create a new buffer   * @bhp: the buffer is returned here   *   * Returns: errno   */  int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, -			      int new, struct buffer_head **bhp) +			      struct buffer_head **bhp)  {  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);  	struct gfs2_glock *gl = ip->i_gl;  	struct buffer_head *bh;  	int ret = 0; +	u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI; -	if (new) { -		BUG_ON(height == 0); -		bh = gfs2_meta_new(gl, num); -		gfs2_trans_add_bh(ip->i_gl, bh, 1); -		gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); -		gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header)); -	} else { -		u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI; -		ret = gfs2_meta_read(gl, num, DIO_WAIT, &bh); -		if (ret == 0 && gfs2_metatype_check(sdp, bh, mtype)) { -			brelse(bh); -			ret = -EIO; -		} +	ret = gfs2_meta_read(gl, num, DIO_WAIT, &bh); +	if (ret == 0 && gfs2_metatype_check(sdp, bh, mtype)) { +		brelse(bh); +		ret = -EIO;  	}  	*bhp = bh;  	return ret; @@ -441,7 +388,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)  		bh = gfs2_getbuf(gl, dblock, CREATE);  		if (!buffer_uptodate(bh) && !buffer_locked(bh)) -			ll_rw_block(READA, 1, &bh); +			ll_rw_block(READA | REQ_META, 1, &bh);  		brelse(bh);  		dblock++;  		extlen--;  | 
