aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext2/inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-06 11:18:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-06 11:18:10 -0400
commit8d370595811e13378243832006f8c52bbc9cca5e (patch)
tree8cab6785c7fedd8d648b51db0ec420f610b2cd2a /fs/ext2/inode.c
parentd230ec72c4efed7d0f414a80a756c54d4c422a6e (diff)
parent155cd433b516506df065866f3d974661f6473572 (diff)
Merge tag 'xfs-for-linus-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs
Pull xfs and iomap updates from Dave Chinner: "The main things in this update are the iomap-based DAX infrastructure, an XFS delalloc rework, and a chunk of fixes to how log recovery schedules writeback to prevent spurious corruption detections when recovery of certain items was not required. The other main chunk of code is some preparation for the upcoming reflink functionality. Most of it is generic and cleanups that stand alone, but they were ready and reviewed so are in this pull request. Speaking of reflink, I'm currently planning to send you another pull request next week containing all the new reflink functionality. I'm working through a similar process to the last cycle, where I sent the reverse mapping code in a separate request because of how large it was. The reflink code merge is even bigger than reverse mapping, so I'll be doing the same thing again.... Summary for this update: - change of XFS mailing list to linux-xfs@vger.kernel.org - iomap-based DAX infrastructure w/ XFS and ext2 support - small iomap fixes and additions - more efficient XFS delayed allocation infrastructure based on iomap - a rework of log recovery writeback scheduling to ensure we don't fail recovery when trying to replay items that are already on disk - some preparation patches for upcoming reflink support - configurable error handling fixes and documentation - aio access time update race fixes for XFS and generic_file_read_iter" * tag 'xfs-for-linus-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs: (40 commits) fs: update atime before I/O in generic_file_read_iter xfs: update atime before I/O in xfs_file_dio_aio_read ext2: fix possible integer truncation in ext2_iomap_begin xfs: log recovery tracepoints to track current lsn and buffer submission xfs: update metadata LSN in buffers during log recovery xfs: don't warn on buffers not being recovered due to LSN xfs: pass current lsn to log recovery buffer validation xfs: rework log recovery to submit buffers on LSN boundaries xfs: quiesce the filesystem after recovery on readonly mount xfs: remote attribute blocks aren't really userdata ext2: use iomap to implement DAX ext2: stop passing buffer_head to ext2_get_blocks xfs: use iomap to implement DAX xfs: refactor xfs_setfilesize xfs: take the ilock shared if possible in xfs_file_iomap_begin xfs: fix locking for DAX writes dax: provide an iomap based fault handler dax: provide an iomap based dax read/write path dax: don't pass buffer_head to copy_user_dax dax: don't pass buffer_head to dax_insert_mapping ...
Diffstat (limited to 'fs/ext2/inode.c')
-rw-r--r--fs/ext2/inode.c100
1 files changed, 81 insertions, 19 deletions
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 303ae2bb269a..1e72d425fd3b 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -32,6 +32,7 @@
32#include <linux/buffer_head.h> 32#include <linux/buffer_head.h>
33#include <linux/mpage.h> 33#include <linux/mpage.h>
34#include <linux/fiemap.h> 34#include <linux/fiemap.h>
35#include <linux/iomap.h>
35#include <linux/namei.h> 36#include <linux/namei.h>
36#include <linux/uio.h> 37#include <linux/uio.h>
37#include "ext2.h" 38#include "ext2.h"
@@ -618,7 +619,7 @@ static void ext2_splice_branch(struct inode *inode,
618 */ 619 */
619static int ext2_get_blocks(struct inode *inode, 620static int ext2_get_blocks(struct inode *inode,
620 sector_t iblock, unsigned long maxblocks, 621 sector_t iblock, unsigned long maxblocks,
621 struct buffer_head *bh_result, 622 u32 *bno, bool *new, bool *boundary,
622 int create) 623 int create)
623{ 624{
624 int err = -EIO; 625 int err = -EIO;
@@ -644,7 +645,6 @@ static int ext2_get_blocks(struct inode *inode,
644 /* Simplest case - block found, no allocation needed */ 645 /* Simplest case - block found, no allocation needed */
645 if (!partial) { 646 if (!partial) {
646 first_block = le32_to_cpu(chain[depth - 1].key); 647 first_block = le32_to_cpu(chain[depth - 1].key);
647 clear_buffer_new(bh_result); /* What's this do? */
648 count++; 648 count++;
649 /*map more blocks*/ 649 /*map more blocks*/
650 while (count < maxblocks && count <= blocks_to_boundary) { 650 while (count < maxblocks && count <= blocks_to_boundary) {
@@ -699,7 +699,6 @@ static int ext2_get_blocks(struct inode *inode,
699 mutex_unlock(&ei->truncate_mutex); 699 mutex_unlock(&ei->truncate_mutex);
700 if (err) 700 if (err)
701 goto cleanup; 701 goto cleanup;
702 clear_buffer_new(bh_result);
703 goto got_it; 702 goto got_it;
704 } 703 }
705 } 704 }
@@ -755,15 +754,16 @@ static int ext2_get_blocks(struct inode *inode,
755 mutex_unlock(&ei->truncate_mutex); 754 mutex_unlock(&ei->truncate_mutex);
756 goto cleanup; 755 goto cleanup;
757 } 756 }
758 } else 757 } else {
759 set_buffer_new(bh_result); 758 *new = true;
759 }
760 760
761 ext2_splice_branch(inode, iblock, partial, indirect_blks, count); 761 ext2_splice_branch(inode, iblock, partial, indirect_blks, count);
762 mutex_unlock(&ei->truncate_mutex); 762 mutex_unlock(&ei->truncate_mutex);
763got_it: 763got_it:
764 map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); 764 *bno = le32_to_cpu(chain[depth-1].key);
765 if (count > blocks_to_boundary) 765 if (count > blocks_to_boundary)
766 set_buffer_boundary(bh_result); 766 *boundary = true;
767 err = count; 767 err = count;
768 /* Clean up and exit */ 768 /* Clean up and exit */
769 partial = chain + depth - 1; /* the whole chain */ 769 partial = chain + depth - 1; /* the whole chain */
@@ -775,19 +775,82 @@ cleanup:
775 return err; 775 return err;
776} 776}
777 777
778int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) 778int ext2_get_block(struct inode *inode, sector_t iblock,
779 struct buffer_head *bh_result, int create)
779{ 780{
780 unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; 781 unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
781 int ret = ext2_get_blocks(inode, iblock, max_blocks, 782 bool new = false, boundary = false;
782 bh_result, create); 783 u32 bno;
783 if (ret > 0) { 784 int ret;
784 bh_result->b_size = (ret << inode->i_blkbits); 785
785 ret = 0; 786 ret = ext2_get_blocks(inode, iblock, max_blocks, &bno, &new, &boundary,
787 create);
788 if (ret <= 0)
789 return ret;
790
791 map_bh(bh_result, inode->i_sb, bno);
792 bh_result->b_size = (ret << inode->i_blkbits);
793 if (new)
794 set_buffer_new(bh_result);
795 if (boundary)
796 set_buffer_boundary(bh_result);
797 return 0;
798
799}
800
801#ifdef CONFIG_FS_DAX
802static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
803 unsigned flags, struct iomap *iomap)
804{
805 unsigned int blkbits = inode->i_blkbits;
806 unsigned long first_block = offset >> blkbits;
807 unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits;
808 bool new = false, boundary = false;
809 u32 bno;
810 int ret;
811
812 ret = ext2_get_blocks(inode, first_block, max_blocks,
813 &bno, &new, &boundary, flags & IOMAP_WRITE);
814 if (ret < 0)
815 return ret;
816
817 iomap->flags = 0;
818 iomap->bdev = inode->i_sb->s_bdev;
819 iomap->offset = (u64)first_block << blkbits;
820
821 if (ret == 0) {
822 iomap->type = IOMAP_HOLE;
823 iomap->blkno = IOMAP_NULL_BLOCK;
824 iomap->length = 1 << blkbits;
825 } else {
826 iomap->type = IOMAP_MAPPED;
827 iomap->blkno = (sector_t)bno << (blkbits - 9);
828 iomap->length = (u64)ret << blkbits;
829 iomap->flags |= IOMAP_F_MERGED;
786 } 830 }
787 return ret;
788 831
832 if (new)
833 iomap->flags |= IOMAP_F_NEW;
834 return 0;
789} 835}
790 836
837static int
838ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
839 ssize_t written, unsigned flags, struct iomap *iomap)
840{
841 if (iomap->type == IOMAP_MAPPED &&
842 written < length &&
843 (flags & IOMAP_WRITE))
844 ext2_write_failed(inode->i_mapping, offset + length);
845 return 0;
846}
847
848struct iomap_ops ext2_iomap_ops = {
849 .iomap_begin = ext2_iomap_begin,
850 .iomap_end = ext2_iomap_end,
851};
852#endif /* CONFIG_FS_DAX */
853
791int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 854int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
792 u64 start, u64 len) 855 u64 start, u64 len)
793{ 856{
@@ -873,11 +936,10 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
873 loff_t offset = iocb->ki_pos; 936 loff_t offset = iocb->ki_pos;
874 ssize_t ret; 937 ssize_t ret;
875 938
876 if (IS_DAX(inode)) 939 if (WARN_ON_ONCE(IS_DAX(inode)))
877 ret = dax_do_io(iocb, inode, iter, ext2_get_block, NULL, 940 return -EIO;
878 DIO_LOCKING); 941
879 else 942 ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
880 ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
881 if (ret < 0 && iov_iter_rw(iter) == WRITE) 943 if (ret < 0 && iov_iter_rw(iter) == WRITE)
882 ext2_write_failed(mapping, offset + count); 944 ext2_write_failed(mapping, offset + count);
883 return ret; 945 return ret;