aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r--fs/ceph/file.c79
1 files changed, 33 insertions, 46 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 5840d2aaed15..e51558fca3a3 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -712,63 +712,53 @@ static ssize_t ceph_aio_write(struct kiocb *iocb, const struct iovec *iov,
712 struct ceph_osd_client *osdc = 712 struct ceph_osd_client *osdc =
713 &ceph_sb_to_client(inode->i_sb)->client->osdc; 713 &ceph_sb_to_client(inode->i_sb)->client->osdc;
714 loff_t endoff = pos + iov->iov_len; 714 loff_t endoff = pos + iov->iov_len;
715 int want, got = 0; 715 int got = 0;
716 int ret, err; 716 int ret, err, written;
717 717
718 if (ceph_snap(inode) != CEPH_NOSNAP) 718 if (ceph_snap(inode) != CEPH_NOSNAP)
719 return -EROFS; 719 return -EROFS;
720 720
721retry_snap: 721retry_snap:
722 written = 0;
722 if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL)) 723 if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL))
723 return -ENOSPC; 724 return -ENOSPC;
724 __ceph_do_pending_vmtruncate(inode); 725 __ceph_do_pending_vmtruncate(inode);
725 dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
726 inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
727 inode->i_size);
728 if (fi->fmode & CEPH_FILE_MODE_LAZY)
729 want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO;
730 else
731 want = CEPH_CAP_FILE_BUFFER;
732 ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff);
733 if (ret < 0)
734 goto out_put;
735
736 dout("aio_write %p %llx.%llx %llu~%u got cap refs on %s\n",
737 inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len,
738 ceph_cap_string(got));
739
740 if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
741 (iocb->ki_filp->f_flags & O_DIRECT) ||
742 (inode->i_sb->s_flags & MS_SYNCHRONOUS) ||
743 (fi->flags & CEPH_F_SYNC)) {
744 ret = ceph_sync_write(file, iov->iov_base, iov->iov_len,
745 &iocb->ki_pos);
746 } else {
747 /*
748 * buffered write; drop Fw early to avoid slow
749 * revocation if we get stuck on balance_dirty_pages
750 */
751 int dirty;
752
753 spin_lock(&ci->i_ceph_lock);
754 dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
755 spin_unlock(&ci->i_ceph_lock);
756 ceph_put_cap_refs(ci, got);
757 726
727 /*
728 * try to do a buffered write. if we don't have sufficient
729 * caps, we'll get -EAGAIN from generic_file_aio_write, or a
730 * short write if we only get caps for some pages.
731 */
732 if (!(iocb->ki_filp->f_flags & O_DIRECT) &&
733 !(inode->i_sb->s_flags & MS_SYNCHRONOUS) &&
734 !(fi->flags & CEPH_F_SYNC)) {
758 ret = generic_file_aio_write(iocb, iov, nr_segs, pos); 735 ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
736 if (ret >= 0)
737 written = ret;
738
759 if ((ret >= 0 || ret == -EIOCBQUEUED) && 739 if ((ret >= 0 || ret == -EIOCBQUEUED) &&
760 ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host) 740 ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host)
761 || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) { 741 || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) {
762 err = vfs_fsync_range(file, pos, pos + ret - 1, 1); 742 err = vfs_fsync_range(file, pos, pos + written - 1, 1);
763 if (err < 0) 743 if (err < 0)
764 ret = err; 744 ret = err;
765 } 745 }
746 if ((ret < 0 && ret != -EAGAIN) || pos + written >= endoff)
747 goto out;
748 }
766 749
767 if (dirty) 750 dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n",
768 __mark_inode_dirty(inode, dirty); 751 inode, ceph_vinop(inode), pos + written,
752 (unsigned)iov->iov_len - written, inode->i_size);
753 ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, 0, &got, endoff);
754 if (ret < 0)
769 goto out; 755 goto out;
770 }
771 756
757 dout("aio_write %p %llx.%llx %llu~%u got cap refs on %s\n",
758 inode, ceph_vinop(inode), pos + written,
759 (unsigned)iov->iov_len - written, ceph_cap_string(got));
760 ret = ceph_sync_write(file, iov->iov_base + written,
761 iov->iov_len - written, &iocb->ki_pos);
772 if (ret >= 0) { 762 if (ret >= 0) {
773 int dirty; 763 int dirty;
774 spin_lock(&ci->i_ceph_lock); 764 spin_lock(&ci->i_ceph_lock);
@@ -777,13 +767,10 @@ retry_snap:
777 if (dirty) 767 if (dirty)
778 __mark_inode_dirty(inode, dirty); 768 __mark_inode_dirty(inode, dirty);
779 } 769 }
780
781out_put:
782 dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n", 770 dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n",
783 inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, 771 inode, ceph_vinop(inode), pos + written,
784 ceph_cap_string(got)); 772 (unsigned)iov->iov_len - written, ceph_cap_string(got));
785 ceph_put_cap_refs(ci, got); 773 ceph_put_cap_refs(ci, got);
786
787out: 774out:
788 if (ret == -EOLDSNAPC) { 775 if (ret == -EOLDSNAPC) {
789 dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n", 776 dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n",
@@ -797,7 +784,7 @@ out:
797/* 784/*
798 * llseek. be sure to verify file size on SEEK_END. 785 * llseek. be sure to verify file size on SEEK_END.
799 */ 786 */
800static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) 787static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
801{ 788{
802 struct inode *inode = file->f_mapping->host; 789 struct inode *inode = file->f_mapping->host;
803 int ret; 790 int ret;
@@ -805,7 +792,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
805 mutex_lock(&inode->i_mutex); 792 mutex_lock(&inode->i_mutex);
806 __ceph_do_pending_vmtruncate(inode); 793 __ceph_do_pending_vmtruncate(inode);
807 794
808 if (origin == SEEK_END || origin == SEEK_DATA || origin == SEEK_HOLE) { 795 if (whence == SEEK_END || whence == SEEK_DATA || whence == SEEK_HOLE) {
809 ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); 796 ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE);
810 if (ret < 0) { 797 if (ret < 0) {
811 offset = ret; 798 offset = ret;
@@ -813,7 +800,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin)
813 } 800 }
814 } 801 }
815 802
816 switch (origin) { 803 switch (whence) {
817 case SEEK_END: 804 case SEEK_END:
818 offset += inode->i_size; 805 offset += inode->i_size;
819 break; 806 break;