Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 112967
b: refs/heads/master
c: 68c9d70
h: refs/heads/master
i:
  112965: ff37b02
  112963: 8fe3ac7
  112959: 77f0a3c
v: v3
  • Loading branch information
Josef Bacik authored and Theodore Ts'o committed Oct 3, 2008
1 parent e53ab7e commit 21849b4
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 00dc417fa3e763345b34ccb6034d72de76eea0a1
refs/heads/master: 68c9d702bb72f367f3b148963ec6cf5e07ff7f65
2 changes: 2 additions & 0 deletions trunk/fs/ext2/ext2.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ extern void ext2_truncate (struct inode *);
extern int ext2_setattr (struct dentry *, struct iattr *);
extern void ext2_set_inode_flags(struct inode *inode);
extern void ext2_get_inode_flags(struct ext2_inode_info *);
extern int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len);
int __ext2_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata);
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/ext2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ const struct inode_operations ext2_file_inode_operations = {
#endif
.setattr = ext2_setattr,
.permission = ext2_permission,
.fiemap = ext2_fiemap,
};
8 changes: 8 additions & 0 deletions trunk/fs/ext2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/writeback.h>
#include <linux/buffer_head.h>
#include <linux/mpage.h>
#include <linux/fiemap.h>
#include "ext2.h"
#include "acl.h"
#include "xip.h"
Expand Down Expand Up @@ -704,6 +705,13 @@ int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_

}

int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len)
{
return generic_block_fiemap(inode, fieinfo, start, len,
ext2_get_block);
}

static int ext2_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, ext2_get_block, wbc);
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/ext3/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,6 @@ const struct inode_operations ext3_file_inode_operations = {
.removexattr = generic_removexattr,
#endif
.permission = ext3_permission,
.fiemap = ext3_fiemap,
};

8 changes: 8 additions & 0 deletions trunk/fs/ext3/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/mpage.h>
#include <linux/uio.h>
#include <linux/bio.h>
#include <linux/fiemap.h>
#include "xattr.h"
#include "acl.h"

Expand Down Expand Up @@ -981,6 +982,13 @@ static int ext3_get_block(struct inode *inode, sector_t iblock,
return ret;
}

int ext3_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len)
{
return generic_block_fiemap(inode, fieinfo, start, len,
ext3_get_block);
}

/*
* `handle' can be NULL if create is zero
*/
Expand Down
118 changes: 118 additions & 0 deletions trunk/fs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h>

#include <asm/ioctls.h>

Expand Down Expand Up @@ -224,6 +226,122 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg)
return error;
}

#define blk_to_logical(inode, blk) (blk << (inode)->i_blkbits)
#define logical_to_blk(inode, offset) (offset >> (inode)->i_blkbits);

/*
* @inode - the inode to map
* @arg - the pointer to userspace where we copy everything to
* @get_block - the fs's get_block function
*
* This does FIEMAP for block based inodes. Basically it will just loop
* through get_block until we hit the number of extents we want to map, or we
* go past the end of the file and hit a hole.
*
* If it is possible to have data blocks beyond a hole past @inode->i_size, then
* please do not use this function, it will stop at the first unmapped block
* beyond i_size
*/
int generic_block_fiemap(struct inode *inode,
struct fiemap_extent_info *fieinfo, u64 start,
u64 len, get_block_t *get_block)
{
struct buffer_head tmp;
unsigned int start_blk;
long long length = 0, map_len = 0;
u64 logical = 0, phys = 0, size = 0;
u32 flags = FIEMAP_EXTENT_MERGED;
int ret = 0;

if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC)))
return ret;

start_blk = logical_to_blk(inode, start);

/* guard against change */
mutex_lock(&inode->i_mutex);

length = (long long)min_t(u64, len, i_size_read(inode));
map_len = length;

do {
/*
* we set b_size to the total size we want so it will map as
* many contiguous blocks as possible at once
*/
memset(&tmp, 0, sizeof(struct buffer_head));
tmp.b_size = map_len;

ret = get_block(inode, start_blk, &tmp, 0);
if (ret)
break;

/* HOLE */
if (!buffer_mapped(&tmp)) {
/*
* first hole after going past the EOF, this is our
* last extent
*/
if (length <= 0) {
flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size,
flags);
break;
}

length -= blk_to_logical(inode, 1);

/* if we have holes up to/past EOF then we're done */
if (length <= 0)
break;

start_blk++;
} else {
if (length <= 0 && size) {
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size,
flags);
if (ret)
break;
}

logical = blk_to_logical(inode, start_blk);
phys = blk_to_logical(inode, tmp.b_blocknr);
size = tmp.b_size;
flags = FIEMAP_EXTENT_MERGED;

length -= tmp.b_size;
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 (length <= 0)
continue;

ret = fiemap_fill_next_extent(fieinfo, logical, phys,
size, flags);
if (ret)
break;
}
cond_resched();
} while (1);

mutex_unlock(&inode->i_mutex);

/* if ret is 1 then we just hit the end of the extent array */
if (ret == 1)
ret = 0;

return ret;
}
EXPORT_SYMBOL(generic_block_fiemap);

static int file_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/ext3_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,8 @@ extern void ext3_truncate (struct inode *);
extern void ext3_set_inode_flags(struct inode *);
extern void ext3_get_inode_flags(struct ext3_inode_info *);
extern void ext3_set_aops(struct inode *inode);
extern int ext3_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len);

/* ioctl.c */
extern int ext3_ioctl (struct inode *, struct file *, unsigned int,
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1998,6 +1998,9 @@ extern int vfs_fstat(unsigned int, struct kstat *);

extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
unsigned long arg);
extern int generic_block_fiemap(struct inode *inode,
struct fiemap_extent_info *fieinfo, u64 start,
u64 len, get_block_t *get_block);

extern void get_filesystem(struct file_system_type *fs);
extern void put_filesystem(struct file_system_type *fs);
Expand Down

0 comments on commit 21849b4

Please sign in to comment.