Loading fs/ext2/Kconfig +1 −0 Original line number Diff line number Diff line config EXT2_FS tristate "Second extended fs support" select FS_IOMAP if FS_DAX help Ext2 is a standard Linux file system for hard disks. Loading fs/ext2/ext2.h +1 −0 Original line number Diff line number Diff line Loading @@ -814,6 +814,7 @@ extern const struct file_operations ext2_file_operations; /* inode.c */ extern const struct address_space_operations ext2_aops; extern const struct address_space_operations ext2_nobh_aops; extern struct iomap_ops ext2_iomap_ops; /* namei.c */ extern const struct inode_operations ext2_dir_inode_operations; Loading fs/ext2/file.c +69 −7 Original line number Diff line number Diff line Loading @@ -22,11 +22,59 @@ #include <linux/pagemap.h> #include <linux/dax.h> #include <linux/quotaops.h> #include <linux/iomap.h> #include <linux/uio.h> #include "ext2.h" #include "xattr.h" #include "acl.h" #ifdef CONFIG_FS_DAX static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct inode *inode = iocb->ki_filp->f_mapping->host; ssize_t ret; if (!iov_iter_count(to)) return 0; /* skip atime */ inode_lock_shared(inode); ret = iomap_dax_rw(iocb, to, &ext2_iomap_ops); inode_unlock_shared(inode); file_accessed(iocb->ki_filp); return ret; } static ssize_t ext2_dax_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; ssize_t ret; inode_lock(inode); ret = generic_write_checks(iocb, from); if (ret <= 0) goto out_unlock; ret = file_remove_privs(file); if (ret) goto out_unlock; ret = file_update_time(file); if (ret) goto out_unlock; ret = iomap_dax_rw(iocb, from, &ext2_iomap_ops); if (ret > 0 && iocb->ki_pos > i_size_read(inode)) { i_size_write(inode, iocb->ki_pos); mark_inode_dirty(inode); } out_unlock: inode_unlock(inode); if (ret > 0) ret = generic_write_sync(iocb, ret); return ret; } /* * The lock ordering for ext2 DAX fault paths is: * Loading @@ -51,7 +99,7 @@ static int ext2_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } down_read(&ei->dax_sem); ret = dax_fault(vma, vmf, ext2_get_block); ret = iomap_dax_fault(vma, vmf, &ext2_iomap_ops); up_read(&ei->dax_sem); if (vmf->flags & FAULT_FLAG_WRITE) Loading Loading @@ -156,14 +204,28 @@ int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync) return ret; } /* * We have mostly NULL's here: the current defaults are ok for * the ext2 filesystem. */ static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { #ifdef CONFIG_FS_DAX if (IS_DAX(iocb->ki_filp->f_mapping->host)) return ext2_dax_read_iter(iocb, to); #endif return generic_file_read_iter(iocb, to); } static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { #ifdef CONFIG_FS_DAX if (IS_DAX(iocb->ki_filp->f_mapping->host)) return ext2_dax_write_iter(iocb, from); #endif return generic_file_write_iter(iocb, from); } const struct file_operations ext2_file_operations = { .llseek = generic_file_llseek, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .read_iter = ext2_file_read_iter, .write_iter = ext2_file_write_iter, .unlocked_ioctl = ext2_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ext2_compat_ioctl, Loading fs/ext2/inode.c +58 −5 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <linux/buffer_head.h> #include <linux/mpage.h> #include <linux/fiemap.h> #include <linux/iomap.h> #include <linux/namei.h> #include <linux/uio.h> #include "ext2.h" Loading Loading @@ -787,6 +788,59 @@ int ext2_get_block(struct inode *inode, sector_t iblock, } #ifdef CONFIG_FS_DAX static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length, unsigned flags, struct iomap *iomap) { unsigned int blkbits = inode->i_blkbits; unsigned long first_block = offset >> blkbits; unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits; bool new = false, boundary = false; u32 bno; int ret; ret = ext2_get_blocks(inode, first_block, max_blocks, &bno, &new, &boundary, flags & IOMAP_WRITE); if (ret < 0) return ret; iomap->flags = 0; iomap->bdev = inode->i_sb->s_bdev; iomap->offset = first_block << blkbits; if (ret == 0) { iomap->type = IOMAP_HOLE; iomap->blkno = IOMAP_NULL_BLOCK; iomap->length = 1 << blkbits; } else { iomap->type = IOMAP_MAPPED; iomap->blkno = (sector_t)bno << (blkbits - 9); iomap->length = (u64)ret << blkbits; iomap->flags |= IOMAP_F_MERGED; } if (new) iomap->flags |= IOMAP_F_NEW; return 0; } static int ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length, ssize_t written, unsigned flags, struct iomap *iomap) { if (iomap->type == IOMAP_MAPPED && written < length && (flags & IOMAP_WRITE)) ext2_write_failed(inode->i_mapping, offset + length); return 0; } struct iomap_ops ext2_iomap_ops = { .iomap_begin = ext2_iomap_begin, .iomap_end = ext2_iomap_end, }; #endif /* CONFIG_FS_DAX */ int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { Loading Loading @@ -872,10 +926,9 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) loff_t offset = iocb->ki_pos; ssize_t ret; if (IS_DAX(inode)) ret = dax_do_io(iocb, inode, iter, ext2_get_block, NULL, DIO_LOCKING); else if (WARN_ON_ONCE(IS_DAX(inode))) return -EIO; ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block); if (ret < 0 && iov_iter_rw(iter) == WRITE) ext2_write_failed(mapping, offset + count); Loading Loading
fs/ext2/Kconfig +1 −0 Original line number Diff line number Diff line config EXT2_FS tristate "Second extended fs support" select FS_IOMAP if FS_DAX help Ext2 is a standard Linux file system for hard disks. Loading
fs/ext2/ext2.h +1 −0 Original line number Diff line number Diff line Loading @@ -814,6 +814,7 @@ extern const struct file_operations ext2_file_operations; /* inode.c */ extern const struct address_space_operations ext2_aops; extern const struct address_space_operations ext2_nobh_aops; extern struct iomap_ops ext2_iomap_ops; /* namei.c */ extern const struct inode_operations ext2_dir_inode_operations; Loading
fs/ext2/file.c +69 −7 Original line number Diff line number Diff line Loading @@ -22,11 +22,59 @@ #include <linux/pagemap.h> #include <linux/dax.h> #include <linux/quotaops.h> #include <linux/iomap.h> #include <linux/uio.h> #include "ext2.h" #include "xattr.h" #include "acl.h" #ifdef CONFIG_FS_DAX static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to) { struct inode *inode = iocb->ki_filp->f_mapping->host; ssize_t ret; if (!iov_iter_count(to)) return 0; /* skip atime */ inode_lock_shared(inode); ret = iomap_dax_rw(iocb, to, &ext2_iomap_ops); inode_unlock_shared(inode); file_accessed(iocb->ki_filp); return ret; } static ssize_t ext2_dax_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; ssize_t ret; inode_lock(inode); ret = generic_write_checks(iocb, from); if (ret <= 0) goto out_unlock; ret = file_remove_privs(file); if (ret) goto out_unlock; ret = file_update_time(file); if (ret) goto out_unlock; ret = iomap_dax_rw(iocb, from, &ext2_iomap_ops); if (ret > 0 && iocb->ki_pos > i_size_read(inode)) { i_size_write(inode, iocb->ki_pos); mark_inode_dirty(inode); } out_unlock: inode_unlock(inode); if (ret > 0) ret = generic_write_sync(iocb, ret); return ret; } /* * The lock ordering for ext2 DAX fault paths is: * Loading @@ -51,7 +99,7 @@ static int ext2_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } down_read(&ei->dax_sem); ret = dax_fault(vma, vmf, ext2_get_block); ret = iomap_dax_fault(vma, vmf, &ext2_iomap_ops); up_read(&ei->dax_sem); if (vmf->flags & FAULT_FLAG_WRITE) Loading Loading @@ -156,14 +204,28 @@ int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync) return ret; } /* * We have mostly NULL's here: the current defaults are ok for * the ext2 filesystem. */ static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { #ifdef CONFIG_FS_DAX if (IS_DAX(iocb->ki_filp->f_mapping->host)) return ext2_dax_read_iter(iocb, to); #endif return generic_file_read_iter(iocb, to); } static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { #ifdef CONFIG_FS_DAX if (IS_DAX(iocb->ki_filp->f_mapping->host)) return ext2_dax_write_iter(iocb, from); #endif return generic_file_write_iter(iocb, from); } const struct file_operations ext2_file_operations = { .llseek = generic_file_llseek, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .read_iter = ext2_file_read_iter, .write_iter = ext2_file_write_iter, .unlocked_ioctl = ext2_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ext2_compat_ioctl, Loading
fs/ext2/inode.c +58 −5 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <linux/buffer_head.h> #include <linux/mpage.h> #include <linux/fiemap.h> #include <linux/iomap.h> #include <linux/namei.h> #include <linux/uio.h> #include "ext2.h" Loading Loading @@ -787,6 +788,59 @@ int ext2_get_block(struct inode *inode, sector_t iblock, } #ifdef CONFIG_FS_DAX static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length, unsigned flags, struct iomap *iomap) { unsigned int blkbits = inode->i_blkbits; unsigned long first_block = offset >> blkbits; unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits; bool new = false, boundary = false; u32 bno; int ret; ret = ext2_get_blocks(inode, first_block, max_blocks, &bno, &new, &boundary, flags & IOMAP_WRITE); if (ret < 0) return ret; iomap->flags = 0; iomap->bdev = inode->i_sb->s_bdev; iomap->offset = first_block << blkbits; if (ret == 0) { iomap->type = IOMAP_HOLE; iomap->blkno = IOMAP_NULL_BLOCK; iomap->length = 1 << blkbits; } else { iomap->type = IOMAP_MAPPED; iomap->blkno = (sector_t)bno << (blkbits - 9); iomap->length = (u64)ret << blkbits; iomap->flags |= IOMAP_F_MERGED; } if (new) iomap->flags |= IOMAP_F_NEW; return 0; } static int ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length, ssize_t written, unsigned flags, struct iomap *iomap) { if (iomap->type == IOMAP_MAPPED && written < length && (flags & IOMAP_WRITE)) ext2_write_failed(inode->i_mapping, offset + length); return 0; } struct iomap_ops ext2_iomap_ops = { .iomap_begin = ext2_iomap_begin, .iomap_end = ext2_iomap_end, }; #endif /* CONFIG_FS_DAX */ int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { Loading Loading @@ -872,10 +926,9 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) loff_t offset = iocb->ki_pos; ssize_t ret; if (IS_DAX(inode)) ret = dax_do_io(iocb, inode, iter, ext2_get_block, NULL, DIO_LOCKING); else if (WARN_ON_ONCE(IS_DAX(inode))) return -EIO; ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block); if (ret < 0 && iov_iter_rw(iter) == WRITE) ext2_write_failed(mapping, offset + count); Loading