aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext2/inode.c
diff options
context:
space:
mode:
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 d5c7d09919f3..c7dbb4661119 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 }
@@ -745,15 +744,16 @@ static int ext2_get_blocks(struct inode *inode,
745 mutex_unlock(&ei->truncate_mutex); 744 mutex_unlock(&ei->truncate_mutex);
746 goto cleanup; 745 goto cleanup;
747 } 746 }
748 } else 747 } else {
749 set_buffer_new(bh_result); 748 *new = true;
749 }
750 750
751 ext2_splice_branch(inode, iblock, partial, indirect_blks, count); 751 ext2_splice_branch(inode, iblock, partial, indirect_blks, count);
752 mutex_unlock(&ei->truncate_mutex); 752 mutex_unlock(&ei->truncate_mutex);
753got_it: 753got_it:
754 map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); 754 *bno = le32_to_cpu(chain[depth-1].key);
755 if (count > blocks_to_boundary) 755 if (count > blocks_to_boundary)
756 set_buffer_boundary(bh_result); 756 *boundary = true;
757 err = count; 757 err = count;
758 /* Clean up and exit */ 758 /* Clean up and exit */
759 partial = chain + depth - 1; /* the whole chain */ 759 partial = chain + depth - 1; /* the whole chain */
@@ -765,19 +765,82 @@ cleanup:
765 return err; 765 return err;
766} 766}
767 767
768int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) 768int ext2_get_block(struct inode *inode, sector_t iblock,
769 struct buffer_head *bh_result, int create)
769{ 770{
770 unsigned max_blocks = bh_result->b_size >> inode->i_blkbits; 771 unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
771 int ret = ext2_get_blocks(inode, iblock, max_blocks, 772 bool new = false, boundary = false;
772 bh_result, create); 773 u32 bno;
773 if (ret > 0) { 774 int ret;
774 bh_result->b_size = (ret << inode->i_blkbits); 775
775 ret = 0; 776 ret = ext2_get_blocks(inode, iblock, max_blocks, &bno, &new, &boundary,
777 create);
778 if (ret <= 0)
779 return ret;
780
781 map_bh(bh_result, inode->i_sb, bno);
782 bh_result->b_size = (ret << inode->i_blkbits);
783 if (new)
784 set_buffer_new(bh_result);
785 if (boundary)
786 set_buffer_boundary(bh_result);
787 return 0;
788
789}
790
791#ifdef CONFIG_FS_DAX
792static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
793 unsigned flags, struct iomap *iomap)
794{
795 unsigned int blkbits = inode->i_blkbits;
796 unsigned long first_block = offset >> blkbits;
797 unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits;
798 bool new = false, boundary = false;
799 u32 bno;
800 int ret;
801
802 ret = ext2_get_blocks(inode, first_block, max_blocks,
803 &bno, &new, &boundary, flags & IOMAP_WRITE);
804 if (ret < 0)
805 return ret;
806
807 iomap->flags = 0;
808 iomap->bdev = inode->i_sb->s_bdev;
809 iomap->offset = (u64)first_block << blkbits;
810
811 if (ret == 0) {
812 iomap->type = IOMAP_HOLE;
813 iomap->blkno = IOMAP_NULL_BLOCK;
814 iomap->length = 1 << blkbits;
815 } else {
816 iomap->type = IOMAP_MAPPED;
817 iomap->blkno = (sector_t)bno << (blkbits - 9);
818 iomap->length = (u64)ret << blkbits;
819 iomap->flags |= IOMAP_F_MERGED;
776 } 820 }
777 return ret;
778 821
822 if (new)
823 iomap->flags |= IOMAP_F_NEW;
824 return 0;
779} 825}
780 826
827static int
828ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
829 ssize_t written, unsigned flags, struct iomap *iomap)
830{
831 if (iomap->type == IOMAP_MAPPED &&
832 written < length &&
833 (flags & IOMAP_WRITE))
834 ext2_write_failed(inode->i_mapping, offset + length);
835 return 0;
836}
837
838struct iomap_ops ext2_iomap_ops = {
839 .iomap_begin = ext2_iomap_begin,
840 .iomap_end = ext2_iomap_end,
841};
842#endif /* CONFIG_FS_DAX */
843
781int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 844int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
782 u64 start, u64 len) 845 u64 start, u64 len)
783{ 846{
@@ -863,11 +926,10 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
863 loff_t offset = iocb->ki_pos; 926 loff_t offset = iocb->ki_pos;
864 ssize_t ret; 927 ssize_t ret;
865 928
866 if (IS_DAX(inode)) 929 if (WARN_ON_ONCE(IS_DAX(inode)))
867 ret = dax_do_io(iocb, inode, iter, ext2_get_block, NULL, 930 return -EIO;
868 DIO_LOCKING); 931
869 else 932 ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
870 ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
871 if (ret < 0 && iov_iter_rw(iter) == WRITE) 933 if (ret < 0 && iov_iter_rw(iter) == WRITE)
872 ext2_write_failed(mapping, offset + count); 934 ext2_write_failed(mapping, offset + count);
873 return ret; 935 return ret;