diff options
author | Joseph Qi <joseph.qi@huawei.com> | 2015-04-14 18:43:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-14 19:48:57 -0400 |
commit | 14a5275d8c31ba24832f45eeb2469e835ded660d (patch) | |
tree | 91f7ea53e0fcfa73088ca9b71af6aac4610b5321 /fs/ocfs2 | |
parent | 37a8d89aee2a5b58812e19520d96632efe987f54 (diff) |
ocfs2: do not use ocfs2_zero_extend during direct IO
In ocfs2_direct_IO_write, we use ocfs2_zero_extend to zero allocated
clusters in case of cluster not aligned. But ocfs2_zero_extend uses page
cache, this may happen that it clears the data which blockdev_direct_IO
has already written.
We should use blkdev_issue_zeroout instead of ocfs2_zero_extend during
direct IO.
So fix this issue by introducing ocfs2_direct_IO_zero_extend and
ocfs2_direct_IO_extend_no_holes.
Reported-by: Yiwen Jiang <jiangyiwen@huawei.com>
Signed-off-by: Joseph Qi <joseph.qi@huawei.com>
Tested-by: Yiwen Jiang <jiangyiwen@huawei.com>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/aops.c | 138 |
1 files changed, 130 insertions, 8 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 973a636285d1..1b0463a92b17 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -663,6 +663,117 @@ static int ocfs2_is_overwrite(struct ocfs2_super *osb, | |||
663 | return 0; | 663 | return 0; |
664 | } | 664 | } |
665 | 665 | ||
666 | static int ocfs2_direct_IO_zero_extend(struct ocfs2_super *osb, | ||
667 | struct inode *inode, loff_t offset, | ||
668 | u64 zero_len, int cluster_align) | ||
669 | { | ||
670 | u32 p_cpos = 0; | ||
671 | u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, i_size_read(inode)); | ||
672 | unsigned int num_clusters = 0; | ||
673 | unsigned int ext_flags = 0; | ||
674 | int ret = 0; | ||
675 | |||
676 | if (offset <= i_size_read(inode) || cluster_align) | ||
677 | return 0; | ||
678 | |||
679 | ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos, &num_clusters, | ||
680 | &ext_flags); | ||
681 | if (ret < 0) { | ||
682 | mlog_errno(ret); | ||
683 | return ret; | ||
684 | } | ||
685 | |||
686 | if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) { | ||
687 | u64 s = i_size_read(inode); | ||
688 | sector_t sector = (p_cpos << (osb->s_clustersize_bits - 9)) + | ||
689 | (do_div(s, osb->s_clustersize) >> 9); | ||
690 | |||
691 | ret = blkdev_issue_zeroout(osb->sb->s_bdev, sector, | ||
692 | zero_len >> 9, GFP_NOFS, false); | ||
693 | if (ret < 0) | ||
694 | mlog_errno(ret); | ||
695 | } | ||
696 | |||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | static int ocfs2_direct_IO_extend_no_holes(struct ocfs2_super *osb, | ||
701 | struct inode *inode, loff_t offset) | ||
702 | { | ||
703 | u64 zero_start, zero_len, total_zero_len; | ||
704 | u32 p_cpos = 0, clusters_to_add; | ||
705 | u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, i_size_read(inode)); | ||
706 | unsigned int num_clusters = 0; | ||
707 | unsigned int ext_flags = 0; | ||
708 | u32 size_div, offset_div; | ||
709 | int ret = 0; | ||
710 | |||
711 | { | ||
712 | u64 o = offset; | ||
713 | u64 s = i_size_read(inode); | ||
714 | |||
715 | offset_div = do_div(o, osb->s_clustersize); | ||
716 | size_div = do_div(s, osb->s_clustersize); | ||
717 | } | ||
718 | |||
719 | if (offset <= i_size_read(inode)) | ||
720 | return 0; | ||
721 | |||
722 | clusters_to_add = ocfs2_bytes_to_clusters(inode->i_sb, offset) - | ||
723 | ocfs2_bytes_to_clusters(inode->i_sb, i_size_read(inode)); | ||
724 | total_zero_len = offset - i_size_read(inode); | ||
725 | if (clusters_to_add) | ||
726 | total_zero_len -= offset_div; | ||
727 | |||
728 | /* Allocate clusters to fill out holes, and this is only needed | ||
729 | * when we add more than one clusters. Otherwise the cluster will | ||
730 | * be allocated during direct IO */ | ||
731 | if (clusters_to_add > 1) { | ||
732 | ret = ocfs2_extend_allocation(inode, | ||
733 | OCFS2_I(inode)->ip_clusters, | ||
734 | clusters_to_add - 1, 0); | ||
735 | if (ret) { | ||
736 | mlog_errno(ret); | ||
737 | goto out; | ||
738 | } | ||
739 | } | ||
740 | |||
741 | while (total_zero_len) { | ||
742 | ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos, &num_clusters, | ||
743 | &ext_flags); | ||
744 | if (ret < 0) { | ||
745 | mlog_errno(ret); | ||
746 | goto out; | ||
747 | } | ||
748 | |||
749 | zero_start = ocfs2_clusters_to_bytes(osb->sb, p_cpos) + | ||
750 | size_div; | ||
751 | zero_len = ocfs2_clusters_to_bytes(osb->sb, num_clusters) - | ||
752 | size_div; | ||
753 | zero_len = min(total_zero_len, zero_len); | ||
754 | |||
755 | if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) { | ||
756 | ret = blkdev_issue_zeroout(osb->sb->s_bdev, | ||
757 | zero_start >> 9, zero_len >> 9, | ||
758 | GFP_NOFS, false); | ||
759 | if (ret < 0) { | ||
760 | mlog_errno(ret); | ||
761 | goto out; | ||
762 | } | ||
763 | } | ||
764 | |||
765 | total_zero_len -= zero_len; | ||
766 | v_cpos += ocfs2_bytes_to_clusters(osb->sb, zero_len + size_div); | ||
767 | |||
768 | /* Only at first iteration can be cluster not aligned. | ||
769 | * So set size_div to 0 for the rest */ | ||
770 | size_div = 0; | ||
771 | } | ||
772 | |||
773 | out: | ||
774 | return ret; | ||
775 | } | ||
776 | |||
666 | static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, | 777 | static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, |
667 | struct iov_iter *iter, | 778 | struct iov_iter *iter, |
668 | loff_t offset) | 779 | loff_t offset) |
@@ -677,8 +788,8 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, | |||
677 | struct buffer_head *di_bh = NULL; | 788 | struct buffer_head *di_bh = NULL; |
678 | size_t count = iter->count; | 789 | size_t count = iter->count; |
679 | journal_t *journal = osb->journal->j_journal; | 790 | journal_t *journal = osb->journal->j_journal; |
680 | u32 zero_len; | 791 | u64 zero_len_head, zero_len_tail; |
681 | int cluster_align; | 792 | int cluster_align_head, cluster_align_tail; |
682 | loff_t final_size = offset + count; | 793 | loff_t final_size = offset + count; |
683 | int append_write = offset >= i_size_read(inode) ? 1 : 0; | 794 | int append_write = offset >= i_size_read(inode) ? 1 : 0; |
684 | unsigned int num_clusters = 0; | 795 | unsigned int num_clusters = 0; |
@@ -686,9 +797,16 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, | |||
686 | 797 | ||
687 | { | 798 | { |
688 | u64 o = offset; | 799 | u64 o = offset; |
800 | u64 s = i_size_read(inode); | ||
801 | |||
802 | zero_len_head = do_div(o, 1 << osb->s_clustersize_bits); | ||
803 | cluster_align_head = !zero_len_head; | ||
689 | 804 | ||
690 | zero_len = do_div(o, 1 << osb->s_clustersize_bits); | 805 | zero_len_tail = osb->s_clustersize - |
691 | cluster_align = !zero_len; | 806 | do_div(s, osb->s_clustersize); |
807 | if ((offset - i_size_read(inode)) < zero_len_tail) | ||
808 | zero_len_tail = offset - i_size_read(inode); | ||
809 | cluster_align_tail = !zero_len_tail; | ||
692 | } | 810 | } |
693 | 811 | ||
694 | /* | 812 | /* |
@@ -712,10 +830,13 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, | |||
712 | goto clean_orphan; | 830 | goto clean_orphan; |
713 | } | 831 | } |
714 | 832 | ||
833 | /* zeroing out the previously allocated cluster tail | ||
834 | * that but not zeroed */ | ||
715 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | 835 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) |
716 | ret = ocfs2_zero_extend(inode, di_bh, offset); | 836 | ret = ocfs2_direct_IO_zero_extend(osb, inode, offset, |
837 | zero_len_tail, cluster_align_tail); | ||
717 | else | 838 | else |
718 | ret = ocfs2_extend_no_holes(inode, di_bh, offset, | 839 | ret = ocfs2_direct_IO_extend_no_holes(osb, inode, |
719 | offset); | 840 | offset); |
720 | if (ret < 0) { | 841 | if (ret < 0) { |
721 | mlog_errno(ret); | 842 | mlog_errno(ret); |
@@ -768,7 +889,8 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, | |||
768 | mlog_errno(ret); | 889 | mlog_errno(ret); |
769 | } | 890 | } |
770 | } else if (written > 0 && append_write && !is_overwrite && | 891 | } else if (written > 0 && append_write && !is_overwrite && |
771 | !cluster_align) { | 892 | !cluster_align_head) { |
893 | /* zeroing out the allocated cluster head */ | ||
772 | u32 p_cpos = 0; | 894 | u32 p_cpos = 0; |
773 | u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, offset); | 895 | u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, offset); |
774 | 896 | ||
@@ -790,7 +912,7 @@ static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb, | |||
790 | 912 | ||
791 | ret = blkdev_issue_zeroout(osb->sb->s_bdev, | 913 | ret = blkdev_issue_zeroout(osb->sb->s_bdev, |
792 | p_cpos << (osb->s_clustersize_bits - 9), | 914 | p_cpos << (osb->s_clustersize_bits - 9), |
793 | zero_len >> 9, GFP_NOFS, false); | 915 | zero_len_head >> 9, GFP_NOFS, false); |
794 | if (ret < 0) | 916 | if (ret < 0) |
795 | mlog_errno(ret); | 917 | mlog_errno(ret); |
796 | 918 | ||