diff options
Diffstat (limited to 'fs/ocfs2/extent_map.c')
| -rw-r--r-- | fs/ocfs2/extent_map.c | 110 | 
1 files changed, 100 insertions, 10 deletions
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 09e3fdfa6d3..767370b656c 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -28,7 +28,6 @@  #include <linux/types.h>  #include <linux/fiemap.h> -#define MLOG_MASK_PREFIX ML_EXTENT_MAP  #include <cluster/masklog.h>  #include "ocfs2.h" @@ -39,6 +38,7 @@  #include "inode.h"  #include "super.h"  #include "symlink.h" +#include "ocfs2_trace.h"  #include "buffer_head_io.h" @@ -282,8 +282,7 @@ search:  	spin_unlock(&oi->ip_lock);  out: -	if (new_emi) -		kfree(new_emi); +	kfree(new_emi);  }  static int ocfs2_last_eb_is_empty(struct inode *inode, @@ -782,7 +781,6 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  	cpos = map_start >> osb->s_clustersize_bits;  	mapping_end = ocfs2_clusters_for_bytes(inode->i_sb,  					       map_start + map_len); -	mapping_end -= cpos;  	is_last = 0;  	while (cpos < mapping_end && !is_last) {  		u32 fe_flags; @@ -791,7 +789,7 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,  						 &hole_size, &rec, &is_last);  		if (ret) {  			mlog_errno(ret); -			goto out; +			goto out_unlock;  		}  		if (rec.e_blkno == 0ULL) { @@ -832,6 +830,100 @@ out:  	return ret;  } +int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int whence) +{ +	struct inode *inode = file->f_mapping->host; +	int ret; +	unsigned int is_last = 0, is_data = 0; +	u16 cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits; +	u32 cpos, cend, clen, hole_size; +	u64 extoff, extlen; +	struct buffer_head *di_bh = NULL; +	struct ocfs2_extent_rec rec; + +	BUG_ON(whence != SEEK_DATA && whence != SEEK_HOLE); + +	ret = ocfs2_inode_lock(inode, &di_bh, 0); +	if (ret) { +		mlog_errno(ret); +		goto out; +	} + +	down_read(&OCFS2_I(inode)->ip_alloc_sem); + +	if (*offset >= i_size_read(inode)) { +		ret = -ENXIO; +		goto out_unlock; +	} + +	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { +		if (whence == SEEK_HOLE) +			*offset = i_size_read(inode); +		goto out_unlock; +	} + +	clen = 0; +	cpos = *offset >> cs_bits; +	cend = ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode)); + +	while (cpos < cend && !is_last) { +		ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, &hole_size, +						 &rec, &is_last); +		if (ret) { +			mlog_errno(ret); +			goto out_unlock; +		} + +		extoff = cpos; +		extoff <<= cs_bits; + +		if (rec.e_blkno == 0ULL) { +			clen = hole_size; +			is_data = 0; +		} else { +			clen = le16_to_cpu(rec.e_leaf_clusters) - +				(cpos - le32_to_cpu(rec.e_cpos)); +			is_data = (rec.e_flags & OCFS2_EXT_UNWRITTEN) ?  0 : 1; +		} + +		if ((!is_data && whence == SEEK_HOLE) || +		    (is_data && whence == SEEK_DATA)) { +			if (extoff > *offset) +				*offset = extoff; +			goto out_unlock; +		} + +		if (!is_last) +			cpos += clen; +	} + +	if (whence == SEEK_HOLE) { +		extoff = cpos; +		extoff <<= cs_bits; +		extlen = clen; +		extlen <<=  cs_bits; + +		if ((extoff + extlen) > i_size_read(inode)) +			extlen = i_size_read(inode) - extoff; +		extoff += extlen; +		if (extoff > *offset) +			*offset = extoff; +		goto out_unlock; +	} + +	ret = -ENXIO; + +out_unlock: + +	brelse(di_bh); + +	up_read(&OCFS2_I(inode)->ip_alloc_sem); + +	ocfs2_inode_unlock(inode, 0); +out: +	return ret; +} +  int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,  			   struct buffer_head *bhs[], int flags,  			   int (*validate)(struct super_block *sb, @@ -841,10 +933,9 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,  	u64 p_block, p_count;  	int i, count, done = 0; -	mlog_entry("(inode = %p, v_block = %llu, nr = %d, bhs = %p, " -		   "flags = %x, validate = %p)\n", -		   inode, (unsigned long long)v_block, nr, bhs, flags, -		   validate); +	trace_ocfs2_read_virt_blocks( +	     inode, (unsigned long long)v_block, nr, bhs, flags, +	     validate);  	if (((v_block + nr - 1) << inode->i_sb->s_blocksize_bits) >=  	    i_size_read(inode)) { @@ -897,7 +988,6 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,  	}  out: -	mlog_exit(rc);  	return rc;  }  | 
