diff options
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r-- | fs/ocfs2/file.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index d9ba0a931a03..1be74c4e7814 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/highmem.h> | 30 | #include <linux/highmem.h> |
31 | #include <linux/pagemap.h> | 31 | #include <linux/pagemap.h> |
32 | #include <linux/uio.h> | 32 | #include <linux/uio.h> |
33 | #include <linux/sched.h> | ||
33 | 34 | ||
34 | #define MLOG_MASK_PREFIX ML_INODE | 35 | #define MLOG_MASK_PREFIX ML_INODE |
35 | #include <cluster/masklog.h> | 36 | #include <cluster/masklog.h> |
@@ -691,6 +692,12 @@ static int ocfs2_zero_extend(struct inode *inode, | |||
691 | } | 692 | } |
692 | 693 | ||
693 | start_off += sb->s_blocksize; | 694 | start_off += sb->s_blocksize; |
695 | |||
696 | /* | ||
697 | * Very large extends have the potential to lock up | ||
698 | * the cpu for extended periods of time. | ||
699 | */ | ||
700 | cond_resched(); | ||
694 | } | 701 | } |
695 | 702 | ||
696 | out: | 703 | out: |
@@ -728,31 +735,36 @@ static int ocfs2_extend_file(struct inode *inode, | |||
728 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) - | 735 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) - |
729 | OCFS2_I(inode)->ip_clusters; | 736 | OCFS2_I(inode)->ip_clusters; |
730 | 737 | ||
731 | if (clusters_to_add) { | 738 | /* |
732 | /* | 739 | * protect the pages that ocfs2_zero_extend is going to be |
733 | * protect the pages that ocfs2_zero_extend is going to | 740 | * pulling into the page cache.. we do this before the |
734 | * be pulling into the page cache.. we do this before the | 741 | * metadata extend so that we don't get into the situation |
735 | * metadata extend so that we don't get into the situation | 742 | * where we've extended the metadata but can't get the data |
736 | * where we've extended the metadata but can't get the data | 743 | * lock to zero. |
737 | * lock to zero. | 744 | */ |
738 | */ | 745 | ret = ocfs2_data_lock(inode, 1); |
739 | ret = ocfs2_data_lock(inode, 1); | 746 | if (ret < 0) { |
740 | if (ret < 0) { | 747 | mlog_errno(ret); |
741 | mlog_errno(ret); | 748 | goto out; |
742 | goto out; | 749 | } |
743 | } | ||
744 | 750 | ||
751 | if (clusters_to_add) { | ||
745 | ret = ocfs2_extend_allocation(inode, clusters_to_add); | 752 | ret = ocfs2_extend_allocation(inode, clusters_to_add); |
746 | if (ret < 0) { | 753 | if (ret < 0) { |
747 | mlog_errno(ret); | 754 | mlog_errno(ret); |
748 | goto out_unlock; | 755 | goto out_unlock; |
749 | } | 756 | } |
757 | } | ||
750 | 758 | ||
751 | ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip); | 759 | /* |
752 | if (ret < 0) { | 760 | * Call this even if we don't add any clusters to the tree. We |
753 | mlog_errno(ret); | 761 | * still need to zero the area between the old i_size and the |
754 | goto out_unlock; | 762 | * new i_size. |
755 | } | 763 | */ |
764 | ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip); | ||
765 | if (ret < 0) { | ||
766 | mlog_errno(ret); | ||
767 | goto out_unlock; | ||
756 | } | 768 | } |
757 | 769 | ||
758 | if (!tail_to_skip) { | 770 | if (!tail_to_skip) { |
@@ -764,8 +776,7 @@ static int ocfs2_extend_file(struct inode *inode, | |||
764 | } | 776 | } |
765 | 777 | ||
766 | out_unlock: | 778 | out_unlock: |
767 | if (clusters_to_add) /* this is the only case in which we lock */ | 779 | ocfs2_data_unlock(inode, 1); |
768 | ocfs2_data_unlock(inode, 1); | ||
769 | 780 | ||
770 | out: | 781 | out: |
771 | return ret; | 782 | return ret; |