ext4: add EXT4_IOC_ALLOC_DA_BLKS ioctl
Add an ioctl which forces all of the delay allocated blocks to be allocated. This also provides a function ext4_alloc_da_blocks() which will be used by the following commits to force files to be fully allocated to preserve application-expected ext3 behaviour. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
f63e6005bc
commit
ccd2506bd4
3 changed files with 59 additions and 0 deletions
|
@ -317,7 +317,9 @@ struct ext4_new_group_data {
|
||||||
#define EXT4_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long)
|
#define EXT4_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long)
|
||||||
#define EXT4_IOC_GROUP_ADD _IOW('f', 8, struct ext4_new_group_input)
|
#define EXT4_IOC_GROUP_ADD _IOW('f', 8, struct ext4_new_group_input)
|
||||||
#define EXT4_IOC_MIGRATE _IO('f', 9)
|
#define EXT4_IOC_MIGRATE _IO('f', 9)
|
||||||
|
/* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
|
||||||
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
|
/* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
|
||||||
|
#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ioctl commands in 32 bit emulation
|
* ioctl commands in 32 bit emulation
|
||||||
|
@ -1094,6 +1096,7 @@ extern int ext4_can_truncate(struct inode *inode);
|
||||||
extern void ext4_truncate(struct inode *);
|
extern void ext4_truncate(struct inode *);
|
||||||
extern void ext4_set_inode_flags(struct inode *);
|
extern void ext4_set_inode_flags(struct inode *);
|
||||||
extern void ext4_get_inode_flags(struct ext4_inode_info *);
|
extern void ext4_get_inode_flags(struct ext4_inode_info *);
|
||||||
|
extern int ext4_alloc_da_blocks(struct inode *inode);
|
||||||
extern void ext4_set_aops(struct inode *inode);
|
extern void ext4_set_aops(struct inode *inode);
|
||||||
extern int ext4_writepage_trans_blocks(struct inode *);
|
extern int ext4_writepage_trans_blocks(struct inode *);
|
||||||
extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks);
|
extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks);
|
||||||
|
|
|
@ -2837,6 +2837,48 @@ static void ext4_da_invalidatepage(struct page *page, unsigned long offset)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force all delayed allocation blocks to be allocated for a given inode.
|
||||||
|
*/
|
||||||
|
int ext4_alloc_da_blocks(struct inode *inode)
|
||||||
|
{
|
||||||
|
if (!EXT4_I(inode)->i_reserved_data_blocks &&
|
||||||
|
!EXT4_I(inode)->i_reserved_meta_blocks)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We do something simple for now. The filemap_flush() will
|
||||||
|
* also start triggering a write of the data blocks, which is
|
||||||
|
* not strictly speaking necessary (and for users of
|
||||||
|
* laptop_mode, not even desirable). However, to do otherwise
|
||||||
|
* would require replicating code paths in:
|
||||||
|
*
|
||||||
|
* ext4_da_writepages() ->
|
||||||
|
* write_cache_pages() ---> (via passed in callback function)
|
||||||
|
* __mpage_da_writepage() -->
|
||||||
|
* mpage_add_bh_to_extent()
|
||||||
|
* mpage_da_map_blocks()
|
||||||
|
*
|
||||||
|
* The problem is that write_cache_pages(), located in
|
||||||
|
* mm/page-writeback.c, marks pages clean in preparation for
|
||||||
|
* doing I/O, which is not desirable if we're not planning on
|
||||||
|
* doing I/O at all.
|
||||||
|
*
|
||||||
|
* We could call write_cache_pages(), and then redirty all of
|
||||||
|
* the pages by calling redirty_page_for_writeback() but that
|
||||||
|
* would be ugly in the extreme. So instead we would need to
|
||||||
|
* replicate parts of the code in the above functions,
|
||||||
|
* simplifying them becuase we wouldn't actually intend to
|
||||||
|
* write out the pages, but rather only collect contiguous
|
||||||
|
* logical block extents, call the multi-block allocator, and
|
||||||
|
* then update the buffer heads with the block allocations.
|
||||||
|
*
|
||||||
|
* For now, though, we'll cheat by calling filemap_flush(),
|
||||||
|
* which will map the blocks, and start the I/O, but not
|
||||||
|
* actually wait for the I/O to complete.
|
||||||
|
*/
|
||||||
|
return filemap_flush(inode->i_mapping);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bmap() is special. It gets used by applications such as lilo and by
|
* bmap() is special. It gets used by applications such as lilo and by
|
||||||
|
|
|
@ -262,6 +262,20 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EXT4_IOC_ALLOC_DA_BLKS:
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if (!is_owner_or_cap(inode))
|
||||||
|
return -EACCES;
|
||||||
|
|
||||||
|
err = mnt_want_write(filp->f_path.mnt);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = ext4_alloc_da_blocks(inode);
|
||||||
|
mnt_drop_write(filp->f_path.mnt);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue