diff options
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r-- | fs/ceph/file.c | 53 |
1 files changed, 31 insertions, 22 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index ed6f19721d6e..8c044a4f0457 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -230,7 +230,7 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
230 | /* do the open */ | 230 | /* do the open */ |
231 | req = prepare_open_request(dir->i_sb, flags, mode); | 231 | req = prepare_open_request(dir->i_sb, flags, mode); |
232 | if (IS_ERR(req)) | 232 | if (IS_ERR(req)) |
233 | return ERR_PTR(PTR_ERR(req)); | 233 | return ERR_CAST(req); |
234 | req->r_dentry = dget(dentry); | 234 | req->r_dentry = dget(dentry); |
235 | req->r_num_caps = 2; | 235 | req->r_num_caps = 2; |
236 | if (flags & O_CREAT) { | 236 | if (flags & O_CREAT) { |
@@ -265,7 +265,7 @@ int ceph_release(struct inode *inode, struct file *file) | |||
265 | kmem_cache_free(ceph_file_cachep, cf); | 265 | kmem_cache_free(ceph_file_cachep, cf); |
266 | 266 | ||
267 | /* wake up anyone waiting for caps on this inode */ | 267 | /* wake up anyone waiting for caps on this inode */ |
268 | wake_up(&ci->i_cap_wq); | 268 | wake_up_all(&ci->i_cap_wq); |
269 | return 0; | 269 | return 0; |
270 | } | 270 | } |
271 | 271 | ||
@@ -317,16 +317,16 @@ void ceph_release_page_vector(struct page **pages, int num_pages) | |||
317 | /* | 317 | /* |
318 | * allocate a vector new pages | 318 | * allocate a vector new pages |
319 | */ | 319 | */ |
320 | static struct page **alloc_page_vector(int num_pages) | 320 | static struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags) |
321 | { | 321 | { |
322 | struct page **pages; | 322 | struct page **pages; |
323 | int i; | 323 | int i; |
324 | 324 | ||
325 | pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS); | 325 | pages = kmalloc(sizeof(*pages) * num_pages, flags); |
326 | if (!pages) | 326 | if (!pages) |
327 | return ERR_PTR(-ENOMEM); | 327 | return ERR_PTR(-ENOMEM); |
328 | for (i = 0; i < num_pages; i++) { | 328 | for (i = 0; i < num_pages; i++) { |
329 | pages[i] = alloc_page(GFP_NOFS); | 329 | pages[i] = __page_cache_alloc(flags); |
330 | if (pages[i] == NULL) { | 330 | if (pages[i] == NULL) { |
331 | ceph_release_page_vector(pages, i); | 331 | ceph_release_page_vector(pages, i); |
332 | return ERR_PTR(-ENOMEM); | 332 | return ERR_PTR(-ENOMEM); |
@@ -540,7 +540,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data, | |||
540 | * in sequence. | 540 | * in sequence. |
541 | */ | 541 | */ |
542 | } else { | 542 | } else { |
543 | pages = alloc_page_vector(num_pages); | 543 | pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); |
544 | } | 544 | } |
545 | if (IS_ERR(pages)) | 545 | if (IS_ERR(pages)) |
546 | return PTR_ERR(pages); | 546 | return PTR_ERR(pages); |
@@ -649,8 +649,8 @@ more: | |||
649 | do_sync, | 649 | do_sync, |
650 | ci->i_truncate_seq, ci->i_truncate_size, | 650 | ci->i_truncate_seq, ci->i_truncate_size, |
651 | &mtime, false, 2); | 651 | &mtime, false, 2); |
652 | if (IS_ERR(req)) | 652 | if (!req) |
653 | return PTR_ERR(req); | 653 | return -ENOMEM; |
654 | 654 | ||
655 | num_pages = calc_pages_for(pos, len); | 655 | num_pages = calc_pages_for(pos, len); |
656 | 656 | ||
@@ -665,10 +665,10 @@ more: | |||
665 | * throw out any page cache pages in this range. this | 665 | * throw out any page cache pages in this range. this |
666 | * may block. | 666 | * may block. |
667 | */ | 667 | */ |
668 | truncate_inode_pages_range(inode->i_mapping, pos, | 668 | truncate_inode_pages_range(inode->i_mapping, pos, |
669 | (pos+len) | (PAGE_CACHE_SIZE-1)); | 669 | (pos+len) | (PAGE_CACHE_SIZE-1)); |
670 | } else { | 670 | } else { |
671 | pages = alloc_page_vector(num_pages); | 671 | pages = ceph_alloc_page_vector(num_pages, GFP_NOFS); |
672 | if (IS_ERR(pages)) { | 672 | if (IS_ERR(pages)) { |
673 | ret = PTR_ERR(pages); | 673 | ret = PTR_ERR(pages); |
674 | goto out; | 674 | goto out; |
@@ -740,28 +740,32 @@ static ssize_t ceph_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
740 | unsigned long nr_segs, loff_t pos) | 740 | unsigned long nr_segs, loff_t pos) |
741 | { | 741 | { |
742 | struct file *filp = iocb->ki_filp; | 742 | struct file *filp = iocb->ki_filp; |
743 | struct ceph_file_info *fi = filp->private_data; | ||
743 | loff_t *ppos = &iocb->ki_pos; | 744 | loff_t *ppos = &iocb->ki_pos; |
744 | size_t len = iov->iov_len; | 745 | size_t len = iov->iov_len; |
745 | struct inode *inode = filp->f_dentry->d_inode; | 746 | struct inode *inode = filp->f_dentry->d_inode; |
746 | struct ceph_inode_info *ci = ceph_inode(inode); | 747 | struct ceph_inode_info *ci = ceph_inode(inode); |
747 | void *base = iov->iov_base; | 748 | void __user *base = iov->iov_base; |
748 | ssize_t ret; | 749 | ssize_t ret; |
749 | int got = 0; | 750 | int want, got = 0; |
750 | int checkeof = 0, read = 0; | 751 | int checkeof = 0, read = 0; |
751 | 752 | ||
752 | dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n", | 753 | dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n", |
753 | inode, ceph_vinop(inode), pos, (unsigned)len, inode); | 754 | inode, ceph_vinop(inode), pos, (unsigned)len, inode); |
754 | again: | 755 | again: |
755 | __ceph_do_pending_vmtruncate(inode); | 756 | __ceph_do_pending_vmtruncate(inode); |
756 | ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, CEPH_CAP_FILE_CACHE, | 757 | if (fi->fmode & CEPH_FILE_MODE_LAZY) |
757 | &got, -1); | 758 | want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO; |
759 | else | ||
760 | want = CEPH_CAP_FILE_CACHE; | ||
761 | ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, &got, -1); | ||
758 | if (ret < 0) | 762 | if (ret < 0) |
759 | goto out; | 763 | goto out; |
760 | dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n", | 764 | dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n", |
761 | inode, ceph_vinop(inode), pos, (unsigned)len, | 765 | inode, ceph_vinop(inode), pos, (unsigned)len, |
762 | ceph_cap_string(got)); | 766 | ceph_cap_string(got)); |
763 | 767 | ||
764 | if ((got & CEPH_CAP_FILE_CACHE) == 0 || | 768 | if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 || |
765 | (iocb->ki_filp->f_flags & O_DIRECT) || | 769 | (iocb->ki_filp->f_flags & O_DIRECT) || |
766 | (inode->i_sb->s_flags & MS_SYNCHRONOUS)) | 770 | (inode->i_sb->s_flags & MS_SYNCHRONOUS)) |
767 | /* hmm, this isn't really async... */ | 771 | /* hmm, this isn't really async... */ |
@@ -807,11 +811,12 @@ static ssize_t ceph_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
807 | unsigned long nr_segs, loff_t pos) | 811 | unsigned long nr_segs, loff_t pos) |
808 | { | 812 | { |
809 | struct file *file = iocb->ki_filp; | 813 | struct file *file = iocb->ki_filp; |
814 | struct ceph_file_info *fi = file->private_data; | ||
810 | struct inode *inode = file->f_dentry->d_inode; | 815 | struct inode *inode = file->f_dentry->d_inode; |
811 | struct ceph_inode_info *ci = ceph_inode(inode); | 816 | struct ceph_inode_info *ci = ceph_inode(inode); |
812 | struct ceph_osd_client *osdc = &ceph_client(inode->i_sb)->osdc; | 817 | struct ceph_osd_client *osdc = &ceph_sb_to_client(inode->i_sb)->osdc; |
813 | loff_t endoff = pos + iov->iov_len; | 818 | loff_t endoff = pos + iov->iov_len; |
814 | int got = 0; | 819 | int want, got = 0; |
815 | int ret, err; | 820 | int ret, err; |
816 | 821 | ||
817 | if (ceph_snap(inode) != CEPH_NOSNAP) | 822 | if (ceph_snap(inode) != CEPH_NOSNAP) |
@@ -824,8 +829,11 @@ retry_snap: | |||
824 | dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n", | 829 | dout("aio_write %p %llx.%llx %llu~%u getting caps. i_size %llu\n", |
825 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, | 830 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, |
826 | inode->i_size); | 831 | inode->i_size); |
827 | ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, CEPH_CAP_FILE_BUFFER, | 832 | if (fi->fmode & CEPH_FILE_MODE_LAZY) |
828 | &got, endoff); | 833 | want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO; |
834 | else | ||
835 | want = CEPH_CAP_FILE_BUFFER; | ||
836 | ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff); | ||
829 | if (ret < 0) | 837 | if (ret < 0) |
830 | goto out; | 838 | goto out; |
831 | 839 | ||
@@ -833,7 +841,7 @@ retry_snap: | |||
833 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, | 841 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, |
834 | ceph_cap_string(got)); | 842 | ceph_cap_string(got)); |
835 | 843 | ||
836 | if ((got & CEPH_CAP_FILE_BUFFER) == 0 || | 844 | if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 || |
837 | (iocb->ki_filp->f_flags & O_DIRECT) || | 845 | (iocb->ki_filp->f_flags & O_DIRECT) || |
838 | (inode->i_sb->s_flags & MS_SYNCHRONOUS)) { | 846 | (inode->i_sb->s_flags & MS_SYNCHRONOUS)) { |
839 | ret = ceph_sync_write(file, iov->iov_base, iov->iov_len, | 847 | ret = ceph_sync_write(file, iov->iov_base, iov->iov_len, |
@@ -844,8 +852,7 @@ retry_snap: | |||
844 | if ((ret >= 0 || ret == -EIOCBQUEUED) && | 852 | if ((ret >= 0 || ret == -EIOCBQUEUED) && |
845 | ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host) | 853 | ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host) |
846 | || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) { | 854 | || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) { |
847 | err = vfs_fsync_range(file, file->f_path.dentry, | 855 | err = vfs_fsync_range(file, pos, pos + ret - 1, 1); |
848 | pos, pos + ret - 1, 1); | ||
849 | if (err < 0) | 856 | if (err < 0) |
850 | ret = err; | 857 | ret = err; |
851 | } | 858 | } |
@@ -931,6 +938,8 @@ const struct file_operations ceph_file_fops = { | |||
931 | .aio_write = ceph_aio_write, | 938 | .aio_write = ceph_aio_write, |
932 | .mmap = ceph_mmap, | 939 | .mmap = ceph_mmap, |
933 | .fsync = ceph_fsync, | 940 | .fsync = ceph_fsync, |
941 | .lock = ceph_lock, | ||
942 | .flock = ceph_flock, | ||
934 | .splice_read = generic_file_splice_read, | 943 | .splice_read = generic_file_splice_read, |
935 | .splice_write = generic_file_splice_write, | 944 | .splice_write = generic_file_splice_write, |
936 | .unlocked_ioctl = ceph_ioctl, | 945 | .unlocked_ioctl = ceph_ioctl, |