diff options
author | Jan Kara <jack@suse.cz> | 2016-11-21 00:09:11 +0100 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2016-11-21 00:09:11 +0100 |
commit | 776722e85d3b0936253ecc3d14db4fba37f191ba (patch) | |
tree | 5f547b90554df18058817b107b1b78790502497e /fs/ext4/file.c | |
parent | ext4: use iomap for zeroing blocks in DAX mode (diff) | |
download | linux-776722e85d3b0936253ecc3d14db4fba37f191ba.tar.xz linux-776722e85d3b0936253ecc3d14db4fba37f191ba.zip |
ext4: DAX iomap write support
Implement DAX writes using the new iomap infrastructure instead of
overloading the direct IO path.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/file.c')
-rw-r--r-- | fs/ext4/file.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 1f25c644cb12..1953fe34f9fe 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -169,6 +169,41 @@ static ssize_t ext4_write_checks(struct kiocb *iocb, struct iov_iter *from) return iov_iter_count(from); } +#ifdef CONFIG_FS_DAX +static ssize_t +ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from) +{ + struct inode *inode = file_inode(iocb->ki_filp); + ssize_t ret; + bool overwrite = false; + + inode_lock(inode); + ret = ext4_write_checks(iocb, from); + if (ret <= 0) + goto out; + ret = file_remove_privs(iocb->ki_filp); + if (ret) + goto out; + ret = file_update_time(iocb->ki_filp); + if (ret) + goto out; + + if (ext4_overwrite_io(inode, iocb->ki_pos, iov_iter_count(from))) { + overwrite = true; + downgrade_write(&inode->i_rwsem); + } + ret = dax_iomap_rw(iocb, from, &ext4_iomap_ops); +out: + if (!overwrite) + inode_unlock(inode); + else + inode_unlock_shared(inode); + if (ret > 0) + ret = generic_write_sync(iocb, ret); + return ret; +} +#endif + static ssize_t ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { @@ -178,6 +213,11 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) int overwrite = 0; ssize_t ret; +#ifdef CONFIG_FS_DAX + if (IS_DAX(inode)) + return ext4_dax_write_iter(iocb, from); +#endif + inode_lock(inode); ret = ext4_write_checks(iocb, from); if (ret <= 0) |