@@ -95,13 +95,26 @@ int ext4_defrag_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
{
int err = 0;
- if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) {
+ if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL ||
+ cmd == EXT4_IOC_FIBMAP)) {
printk(KERN_ERR "ext4 defrag: ino[%lu] is not extents "
"based file\n", inode->i_ino);
return -EOPNOTSUPP;
}
- if (cmd == EXT4_IOC_DEFRAG) {
+ if (cmd == EXT4_IOC_FIBMAP) {
+ ext4_fsblk_t __user *p = (ext4_fsblk_t __user *)arg;
+ ext4_fsblk_t block = 0;
+ struct address_space *mapping = filp->f_mapping;
+
+ if (copy_from_user(&block, (ext4_fsblk_t __user *)arg,
+ sizeof(block)))
+ return -EFAULT;
+
+ block = ext4_bmap(mapping, block);
+
+ return put_user(block, p);
+ } else if (cmd == EXT4_IOC_DEFRAG) {
struct ext4_ext_defrag_data defrag;
struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es;
@@ -303,6 +303,7 @@ struct ext4_new_group_data {
#define EXT4_IOC_MIGRATE _IO('f', 9)
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
#define EXT4_IOC_DEFRAG _IOW('f', 15, struct ext4_ext_defrag_data)
+#define EXT4_IOC_FIBMAP _IOW('f', 16, ext4_fsblk_t)
/*
* ioctl commands in 32 bit emulation
@@ -1017,6 +1018,7 @@ extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash,
__u32 minor_hash,
struct ext4_dir_entry_2 *dirent);
extern void ext4_htree_free_dir_info(struct dir_private_info *p);
+extern sector_t ext4_bmap(struct address_space *mapping, sector_t block);
/* fsync.c */
extern int ext4_sync_file(struct file *, struct dentry *, int);
@@ -2706,7 +2706,7 @@ out:
* So, if we see any bmap calls here on a modified, data-journaled file,
* take extra steps to flush any blocks which might be in the cache.
*/
-static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+sector_t ext4_bmap(struct address_space *mapping, sector_t block)
{
struct inode *inode = mapping->host;
journal_t *journal;
@@ -256,6 +256,7 @@ setversion_out:
return err;
}
+ case EXT4_IOC_FIBMAP:
case EXT4_IOC_DEFRAG: {
return ext4_defrag_ioctl(inode, filp, cmd, arg);
}