diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-05-11 12:59:32 +0200 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-05-11 12:59:37 +0200 | 
| commit | 7961386fe9596e6bf03d09948a73c5df9653325b (patch) | |
| tree | 60fa2586a0d340ef8f7473956eef17430d8250c7 /fs/ioctl.c | |
| parent | aa47b7e0f89b9998dad4d1667447e8cb7703ff4e (diff) | |
| parent | 091bf7624d1c90cec9e578a18529f615213ff847 (diff) | |
| download | olio-linux-3.10-7961386fe9596e6bf03d09948a73c5df9653325b.tar.xz olio-linux-3.10-7961386fe9596e6bf03d09948a73c5df9653325b.zip  | |
Merge commit 'v2.6.30-rc5' into sched/core
Merge reason: sched/core was on .30-rc1 before, update to latest fixes
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'fs/ioctl.c')
| -rw-r--r-- | fs/ioctl.c | 75 | 
1 files changed, 55 insertions, 20 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c index ac2d47e4392..82d9c42b8ba 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -258,7 +258,7 @@ int __generic_block_fiemap(struct inode *inode,  	long long length = 0, map_len = 0;  	u64 logical = 0, phys = 0, size = 0;  	u32 flags = FIEMAP_EXTENT_MERGED; -	int ret = 0; +	int ret = 0, past_eof = 0, whole_file = 0;  	if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC)))  		return ret; @@ -266,6 +266,9 @@ int __generic_block_fiemap(struct inode *inode,  	start_blk = logical_to_blk(inode, start);  	length = (long long)min_t(u64, len, i_size_read(inode)); +	if (length < len) +		whole_file = 1; +  	map_len = length;  	do { @@ -282,11 +285,26 @@ int __generic_block_fiemap(struct inode *inode,  		/* HOLE */  		if (!buffer_mapped(&tmp)) { +			length -= blk_to_logical(inode, 1); +			start_blk++; + +			/* +			 * we want to handle the case where there is an +			 * allocated block at the front of the file, and then +			 * nothing but holes up to the end of the file properly, +			 * to make sure that extent at the front gets properly +			 * marked with FIEMAP_EXTENT_LAST +			 */ +			if (!past_eof && +			    blk_to_logical(inode, start_blk) >= +			    blk_to_logical(inode, 0)+i_size_read(inode)) +				past_eof = 1; +  			/*  			 * first hole after going past the EOF, this is our  			 * last extent  			 */ -			if (length <= 0) { +			if (past_eof && size) {  				flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;  				ret = fiemap_fill_next_extent(fieinfo, logical,  							      phys, size, @@ -294,15 +312,37 @@ int __generic_block_fiemap(struct inode *inode,  				break;  			} -			length -= blk_to_logical(inode, 1); -  			/* if we have holes up to/past EOF then we're done */ -			if (length <= 0) +			if (length <= 0 || past_eof)  				break; - -			start_blk++;  		} else { -			if (length <= 0 && size) { +			/* +			 * we have gone over the length of what we wanted to +			 * map, and it wasn't the entire file, so add the extent +			 * we got last time and exit. +			 * +			 * This is for the case where say we want to map all the +			 * way up to the second to the last block in a file, but +			 * the last block is a hole, making the second to last +			 * block FIEMAP_EXTENT_LAST.  In this case we want to +			 * see if there is a hole after the second to last block +			 * so we can mark it properly.  If we found data after +			 * we exceeded the length we were requesting, then we +			 * are good to go, just add the extent to the fieinfo +			 * and break +			 */ +			if (length <= 0 && !whole_file) { +				ret = fiemap_fill_next_extent(fieinfo, logical, +							      phys, size, +							      flags); +				break; +			} + +			/* +			 * if size != 0 then we know we already have an extent +			 * to add, so add it. +			 */ +			if (size) {  				ret = fiemap_fill_next_extent(fieinfo, logical,  							      phys, size,  							      flags); @@ -319,19 +359,14 @@ int __generic_block_fiemap(struct inode *inode,  			start_blk += logical_to_blk(inode, size);  			/* -			 * if we are past the EOF we need to loop again to see -			 * if there is a hole so we can mark this extent as the -			 * last one, and if not keep mapping things until we -			 * find a hole, or we run out of slots in the extent -			 * array +			 * If we are past the EOF, then we need to make sure as +			 * soon as we find a hole that the last extent we found +			 * is marked with FIEMAP_EXTENT_LAST  			 */ -			if (length <= 0) -				continue; - -			ret = fiemap_fill_next_extent(fieinfo, logical, phys, -						      size, flags); -			if (ret) -				break; +			if (!past_eof && +			    logical+size >= +			    blk_to_logical(inode, 0)+i_size_read(inode)) +				past_eof = 1;  		}  		cond_resched();  	} while (1);  |