diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 14:51:52 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-26 14:51:52 -0800 | 
| commit | bbbd27e694ce2c5fde9c8fcedbea618dd9153fe7 (patch) | |
| tree | 8811b690085ac784ef73c7b4cdff30c6bedd0e34 /fs/udf/inode.c | |
| parent | a6590b9f01dca2d45a38b8387f59812c44f68a2f (diff) | |
| parent | 712ddc52ffa1f5324cd8f682d9e5b047b91f34d3 (diff) | |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull ext2, ext3, udf updates from Jan Kara:
 "Several UDF fixes, a support for UDF extent cache, and couple of ext2
  and ext3 cleanups and minor fixes"
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  Ext2: remove the static function release_blocks to optimize the kernel
  Ext2: mark inode dirty after the function dquot_free_block_nodirty is called
  Ext2: remove the overhead check about sb in the function ext2_new_blocks
  udf: Remove unused s_extLength from udf_bitmap
  udf: Make s_block_bitmap standard array
  udf: Fix bitmap overflow on large filesystems with small block size
  udf: add extent cache support in case of file reading
  udf: Write LVID to disk after opening / closing
  Ext3: return ENOMEM rather than EIO if sb_getblk fails
  Ext2: return ENOMEM rather than EIO if sb_getblk fails
  Ext3: use unlikely to improve the efficiency of the kernel
  Ext2: use unlikely to improve the efficiency of the kernel
  Ext3: add necessary check in case IO error happens
  Ext2: free memory allocated and forget buffer head when io error happens
  ext3: Fix memory leak when quota options are specified multiple times
  ext3, ext4, ocfs2: remove unused macro NAMEI_RA_INDEX
Diffstat (limited to 'fs/udf/inode.c')
| -rw-r--r-- | fs/udf/inode.c | 86 | 
1 files changed, 80 insertions, 6 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index cbae1ed0b7c1..7a12e48ad819 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -67,6 +67,74 @@ static void udf_update_extents(struct inode *,  			       struct extent_position *);  static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); +static void __udf_clear_extent_cache(struct inode *inode) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); + +	if (iinfo->cached_extent.lstart != -1) { +		brelse(iinfo->cached_extent.epos.bh); +		iinfo->cached_extent.lstart = -1; +	} +} + +/* Invalidate extent cache */ +static void udf_clear_extent_cache(struct inode *inode) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); + +	spin_lock(&iinfo->i_extent_cache_lock); +	__udf_clear_extent_cache(inode); +	spin_unlock(&iinfo->i_extent_cache_lock); +} + +/* Return contents of extent cache */ +static int udf_read_extent_cache(struct inode *inode, loff_t bcount, +				 loff_t *lbcount, struct extent_position *pos) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); +	int ret = 0; + +	spin_lock(&iinfo->i_extent_cache_lock); +	if ((iinfo->cached_extent.lstart <= bcount) && +	    (iinfo->cached_extent.lstart != -1)) { +		/* Cache hit */ +		*lbcount = iinfo->cached_extent.lstart; +		memcpy(pos, &iinfo->cached_extent.epos, +		       sizeof(struct extent_position)); +		if (pos->bh) +			get_bh(pos->bh); +		ret = 1; +	} +	spin_unlock(&iinfo->i_extent_cache_lock); +	return ret; +} + +/* Add extent to extent cache */ +static void udf_update_extent_cache(struct inode *inode, loff_t estart, +				    struct extent_position *pos, int next_epos) +{ +	struct udf_inode_info *iinfo = UDF_I(inode); + +	spin_lock(&iinfo->i_extent_cache_lock); +	/* Invalidate previously cached extent */ +	__udf_clear_extent_cache(inode); +	if (pos->bh) +		get_bh(pos->bh); +	memcpy(&iinfo->cached_extent.epos, pos, +	       sizeof(struct extent_position)); +	iinfo->cached_extent.lstart = estart; +	if (next_epos) +		switch (iinfo->i_alloc_type) { +		case ICBTAG_FLAG_AD_SHORT: +			iinfo->cached_extent.epos.offset -= +			sizeof(struct short_ad); +			break; +		case ICBTAG_FLAG_AD_LONG: +			iinfo->cached_extent.epos.offset -= +			sizeof(struct long_ad); +		} +	spin_unlock(&iinfo->i_extent_cache_lock); +}  void udf_evict_inode(struct inode *inode)  { @@ -90,6 +158,7 @@ void udf_evict_inode(struct inode *inode)  	}  	kfree(iinfo->i_ext.i_data);  	iinfo->i_ext.i_data = NULL; +	udf_clear_extent_cache(inode);  	if (want_delete) {  		udf_free_inode(inode);  	} @@ -105,6 +174,7 @@ static void udf_write_failed(struct address_space *mapping, loff_t to)  		truncate_pagecache(inode, to, isize);  		if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {  			down_write(&iinfo->i_data_sem); +			udf_clear_extent_cache(inode);  			udf_truncate_extents(inode);  			up_write(&iinfo->i_data_sem);  		} @@ -372,7 +442,7 @@ static int udf_get_block(struct inode *inode, sector_t block,  		iinfo->i_next_alloc_goal++;  	} - +	udf_clear_extent_cache(inode);  	phys = inode_getblk(inode, block, &err, &new);  	if (!phys)  		goto abort; @@ -1171,6 +1241,7 @@ set_size:  	} else {  		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {  			down_write(&iinfo->i_data_sem); +			udf_clear_extent_cache(inode);  			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize,  			       0x00, bsize - newsize -  			       udf_file_entry_alloc_offset(inode)); @@ -1184,6 +1255,7 @@ set_size:  		if (err)  			return err;  		down_write(&iinfo->i_data_sem); +		udf_clear_extent_cache(inode);  		truncate_setsize(inode, newsize);  		udf_truncate_extents(inode);  		up_write(&iinfo->i_data_sem); @@ -2156,11 +2228,12 @@ int8_t inode_bmap(struct inode *inode, sector_t block,  	struct udf_inode_info *iinfo;  	iinfo = UDF_I(inode); -	pos->offset = 0; -	pos->block = iinfo->i_location; -	pos->bh = NULL; +	if (!udf_read_extent_cache(inode, bcount, &lbcount, pos)) { +		pos->offset = 0; +		pos->block = iinfo->i_location; +		pos->bh = NULL; +	}  	*elen = 0; -  	do {  		etype = udf_next_aext(inode, pos, eloc, elen, 1);  		if (etype == -1) { @@ -2170,7 +2243,8 @@ int8_t inode_bmap(struct inode *inode, sector_t block,  		}  		lbcount += *elen;  	} while (lbcount <= bcount); - +	/* update extent cache */ +	udf_update_extent_cache(inode, lbcount - *elen, pos, 1);  	*offset = (bcount + *elen - lbcount) >> blocksize_bits;  	return etype;  | 
