@@ -549,6 +549,7 @@ struct ext4_new_group_data {
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
#define EXT4_IOC_MOVE_EXT _IOWR('f', 15, struct move_extent)
+#define EXT4_IOC_INIT_EXT _IOWR('f', 20, unsigned long)
#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
/*
@@ -335,6 +335,57 @@ mext_out:
mnt_drop_write(filp->f_path.mnt);
return err;
}
+
+ case EXT4_IOC_INIT_EXT:
+ {
+
+ handle_t *handle;
+ unsigned int max_blocks;
+ unsigned int credits;
+ struct ext4_map_blocks map;
+ unsigned int blkbits = inode->i_blkbits;
+ unsigned long offset = filp->f_pos;
+ unsigned long len = arg;
+ int ret = 0, ret2 = 0;
+
+ if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
+ return -EOPNOTSUPP;
+
+ mutex_lock(&inode->i_mutex);
+ if ((offset + len)> i_size_read(inode)) {
+ mutex_unlock(&inode->i_mutex);
+ return -EINVAL;
+ }
+ map.m_lblk = offset >> blkbits;
+ max_blocks = ((EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) -
+ map.m_lblk);
+
+ credits = ext4_chunk_trans_blocks(inode, max_blocks);
+ while (ret >= 0 && ret < max_blocks) {
+ map.m_lblk += ret;
+ map.m_len = (max_blocks -= ret);
+ handle = ext4_journal_start(inode, credits);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ break;
+ }
+ ret = ext4_map_blocks(handle, inode, &map,
+ EXT4_GET_BLOCKS_CREATE);
+ if (ret <= 0) {
+ WARN_ON(ret <= 0);
+ printk(KERN_ERR "%s: ext4_map_blocks "
+ "returned error inode#%lu, block=%u, "
+ "max_blocks=%u", __func__,
+ inode->i_ino, map.m_lblk, map.m_len);
+ }
+ ext4_mark_inode_dirty(handle, inode);
+ ret2 = ext4_journal_stop(handle);
+ if (ret <= 0 || ret2 )
+ break;
+ }
+ mutex_unlock(&inode->i_mutex);
+ return ret > 0 ? ret2 : ret;
+ }
case FITRIM:
{
@@ -432,6 +483,7 @@ long ext4_compat_ioctl(struct file *file, unsigned
int cmd, unsigned long arg)
return err;
}
case EXT4_IOC_MOVE_EXT:
+ case EXT4_IOC_INIT_EXT:
case FITRIM:
break;