aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorJoseph Qi <joseph.qi@huawei.com>2015-02-16 19:00:00 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-16 20:56:05 -0500
commit24c40b329e03dd38a1ca2225c739db67f4441343 (patch)
treeac44a8faee0103987e75fd01885042745d645421 /fs/ocfs2
parented460cffc26ba4ec663a89589d81290ca92c5010 (diff)
ocfs2: implement ocfs2_direct_IO_write
Implement ocfs2_direct_IO_write. Add the inode to orphan dir first, and then delete it once append O_DIRECT finished. This is to make sure block allocation and inode size are consistent. [akpm@linux-foundation.org: fix it for "block: Add discard flag to blkdev_issue_zeroout() function"] Signed-off-by: Joseph Qi <joseph.qi@huawei.com> Cc: Weiwei Wang <wangww631@huawei.com> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Xuejiufei <xuejiufei@huawei.com> Cc: alex chen <alex.chen@huawei.com> 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.c197
-rw-r--r--fs/ocfs2/ocfs2.h10
2 files changed, 204 insertions, 3 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 46d93e941f3d..be5986b7e5c6 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -28,6 +28,7 @@
28#include <linux/pipe_fs_i.h> 28#include <linux/pipe_fs_i.h>
29#include <linux/mpage.h> 29#include <linux/mpage.h>
30#include <linux/quotaops.h> 30#include <linux/quotaops.h>
31#include <linux/blkdev.h>
31 32
32#include <cluster/masklog.h> 33#include <cluster/masklog.h>
33 34
@@ -47,6 +48,9 @@
47#include "ocfs2_trace.h" 48#include "ocfs2_trace.h"
48 49
49#include "buffer_head_io.h" 50#include "buffer_head_io.h"
51#include "dir.h"
52#include "namei.h"
53#include "sysfile.h"
50 54
51static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, 55static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
52 struct buffer_head *bh_result, int create) 56 struct buffer_head *bh_result, int create)
@@ -597,6 +601,184 @@ static int ocfs2_releasepage(struct page *page, gfp_t wait)
597 return try_to_free_buffers(page); 601 return try_to_free_buffers(page);
598} 602}
599 603
604static int ocfs2_is_overwrite(struct ocfs2_super *osb,
605 struct inode *inode, loff_t offset)
606{
607 int ret = 0;
608 u32 v_cpos = 0;
609 u32 p_cpos = 0;
610 unsigned int num_clusters = 0;
611 unsigned int ext_flags = 0;
612
613 v_cpos = ocfs2_bytes_to_clusters(osb->sb, offset);
614 ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos,
615 &num_clusters, &ext_flags);
616 if (ret < 0) {
617 mlog_errno(ret);
618 return ret;
619 }
620
621 if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN))
622 return 1;
623
624 return 0;
625}
626
627static ssize_t ocfs2_direct_IO_write(struct kiocb *iocb,
628 struct iov_iter *iter,
629 loff_t offset)
630{
631 ssize_t ret = 0;
632 ssize_t written = 0;
633 bool orphaned = false;
634 int is_overwrite = 0;
635 struct file *file = iocb->ki_filp;
636 struct inode *inode = file_inode(file)->i_mapping->host;
637 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
638 struct buffer_head *di_bh = NULL;
639 size_t count = iter->count;
640 journal_t *journal = osb->journal->j_journal;
641 u32 zero_len;
642 int cluster_align;
643 loff_t final_size = offset + count;
644 int append_write = offset >= i_size_read(inode) ? 1 : 0;
645 unsigned int num_clusters = 0;
646 unsigned int ext_flags = 0;
647
648 {
649 u64 o = offset;
650
651 zero_len = do_div(o, 1 << osb->s_clustersize_bits);
652 cluster_align = !zero_len;
653 }
654
655 /*
656 * when final_size > inode->i_size, inode->i_size will be
657 * updated after direct write, so add the inode to orphan
658 * dir first.
659 */
660 if (final_size > i_size_read(inode)) {
661 ret = ocfs2_add_inode_to_orphan(osb, inode);
662 if (ret < 0) {
663 mlog_errno(ret);
664 goto out;
665 }
666 orphaned = true;
667 }
668
669 if (append_write) {
670 ret = ocfs2_inode_lock(inode, &di_bh, 1);
671 if (ret < 0) {
672 mlog_errno(ret);
673 goto clean_orphan;
674 }
675
676 if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
677 ret = ocfs2_zero_extend(inode, di_bh, offset);
678 else
679 ret = ocfs2_extend_no_holes(inode, di_bh, offset,
680 offset);
681 if (ret < 0) {
682 mlog_errno(ret);
683 ocfs2_inode_unlock(inode, 1);
684 brelse(di_bh);
685 goto clean_orphan;
686 }
687
688 is_overwrite = ocfs2_is_overwrite(osb, inode, offset);
689 if (is_overwrite < 0) {
690 mlog_errno(is_overwrite);
691 ocfs2_inode_unlock(inode, 1);
692 brelse(di_bh);
693 goto clean_orphan;
694 }
695
696 ocfs2_inode_unlock(inode, 1);
697 brelse(di_bh);
698 di_bh = NULL;
699 }
700
701 written = __blockdev_direct_IO(WRITE, iocb, inode, inode->i_sb->s_bdev,
702 iter, offset,
703 ocfs2_direct_IO_get_blocks,
704 ocfs2_dio_end_io, NULL, 0);
705 if (unlikely(written < 0)) {
706 loff_t i_size = i_size_read(inode);
707
708 if (offset + count > i_size) {
709 ret = ocfs2_inode_lock(inode, &di_bh, 1);
710 if (ret < 0) {
711 mlog_errno(ret);
712 goto clean_orphan;
713 }
714
715 if (i_size == i_size_read(inode)) {
716 ret = ocfs2_truncate_file(inode, di_bh,
717 i_size);
718 if (ret < 0) {
719 if (ret != -ENOSPC)
720 mlog_errno(ret);
721
722 ocfs2_inode_unlock(inode, 1);
723 brelse(di_bh);
724 goto clean_orphan;
725 }
726 }
727
728 ocfs2_inode_unlock(inode, 1);
729 brelse(di_bh);
730
731 ret = jbd2_journal_force_commit(journal);
732 if (ret < 0)
733 mlog_errno(ret);
734 }
735 } else if (written < 0 && append_write && !is_overwrite &&
736 !cluster_align) {
737 u32 p_cpos = 0;
738 u32 v_cpos = ocfs2_bytes_to_clusters(osb->sb, offset);
739
740 ret = ocfs2_get_clusters(inode, v_cpos, &p_cpos,
741 &num_clusters, &ext_flags);
742 if (ret < 0) {
743 mlog_errno(ret);
744 goto clean_orphan;
745 }
746
747 BUG_ON(!p_cpos || (ext_flags & OCFS2_EXT_UNWRITTEN));
748
749 ret = blkdev_issue_zeroout(osb->sb->s_bdev,
750 p_cpos << (osb->s_clustersize_bits - 9),
751 zero_len >> 9, GFP_KERNEL, false);
752 if (ret < 0)
753 mlog_errno(ret);
754 }
755
756clean_orphan:
757 if (orphaned) {
758 int tmp_ret;
759 int update_isize = written > 0 ? 1 : 0;
760 loff_t end = update_isize ? offset + written : 0;
761
762 tmp_ret = ocfs2_del_inode_from_orphan(osb, inode,
763 update_isize, end);
764 if (tmp_ret < 0) {
765 ret = tmp_ret;
766 goto out;
767 }
768
769 tmp_ret = jbd2_journal_force_commit(journal);
770 if (tmp_ret < 0) {
771 ret = tmp_ret;
772 mlog_errno(tmp_ret);
773 }
774 }
775
776out:
777 if (ret >= 0)
778 ret = written;
779 return ret;
780}
781
600static ssize_t ocfs2_direct_IO(int rw, 782static ssize_t ocfs2_direct_IO(int rw,
601 struct kiocb *iocb, 783 struct kiocb *iocb,
602 struct iov_iter *iter, 784 struct iov_iter *iter,
@@ -604,6 +786,9 @@ static ssize_t ocfs2_direct_IO(int rw,
604{ 786{
605 struct file *file = iocb->ki_filp; 787 struct file *file = iocb->ki_filp;
606 struct inode *inode = file_inode(file)->i_mapping->host; 788 struct inode *inode = file_inode(file)->i_mapping->host;
789 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
790 int full_coherency = !(osb->s_mount_opt &
791 OCFS2_MOUNT_COHERENCY_BUFFERED);
607 792
608 /* 793 /*
609 * Fallback to buffered I/O if we see an inode without 794 * Fallback to buffered I/O if we see an inode without
@@ -612,14 +797,20 @@ static ssize_t ocfs2_direct_IO(int rw,
612 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) 797 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
613 return 0; 798 return 0;
614 799
615 /* Fallback to buffered I/O if we are appending. */ 800 /* Fallback to buffered I/O if we are appending and
616 if (i_size_read(inode) <= offset) 801 * concurrent O_DIRECT writes are allowed.
802 */
803 if (i_size_read(inode) <= offset && !full_coherency)
617 return 0; 804 return 0;
618 805
619 return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, 806 if (rw == READ)
807 return __blockdev_direct_IO(rw, iocb, inode,
808 inode->i_sb->s_bdev,
620 iter, offset, 809 iter, offset,
621 ocfs2_direct_IO_get_blocks, 810 ocfs2_direct_IO_get_blocks,
622 ocfs2_dio_end_io, NULL, 0); 811 ocfs2_dio_end_io, NULL, 0);
812 else
813 return ocfs2_direct_IO_write(iocb, iter, offset);
623} 814}
624 815
625static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb, 816static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb,
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index df9a95cbea3a..7e39cd654834 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -731,6 +731,16 @@ static inline unsigned int ocfs2_clusters_for_bytes(struct super_block *sb,
731 return clusters; 731 return clusters;
732} 732}
733 733
734static inline unsigned int ocfs2_bytes_to_clusters(struct super_block *sb,
735 u64 bytes)
736{
737 int cl_bits = OCFS2_SB(sb)->s_clustersize_bits;
738 unsigned int clusters;
739
740 clusters = (unsigned int)(bytes >> cl_bits);
741 return clusters;
742}
743
734static inline u64 ocfs2_blocks_for_bytes(struct super_block *sb, 744static inline u64 ocfs2_blocks_for_bytes(struct super_block *sb,
735 u64 bytes) 745 u64 bytes)
736{ 746{