diff options
Diffstat (limited to 'fs/ceph/file.c')
-rw-r--r-- | fs/ceph/file.c | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 0d0eae05598f..ce549d31eeb7 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -122,7 +122,7 @@ int ceph_open(struct inode *inode, struct file *file) | |||
122 | struct ceph_mds_client *mdsc = fsc->mdsc; | 122 | struct ceph_mds_client *mdsc = fsc->mdsc; |
123 | struct ceph_mds_request *req; | 123 | struct ceph_mds_request *req; |
124 | struct ceph_file_info *cf = file->private_data; | 124 | struct ceph_file_info *cf = file->private_data; |
125 | struct inode *parent_inode = file->f_dentry->d_parent->d_inode; | 125 | struct inode *parent_inode = NULL; |
126 | int err; | 126 | int err; |
127 | int flags, fmode, wanted; | 127 | int flags, fmode, wanted; |
128 | 128 | ||
@@ -194,7 +194,10 @@ int ceph_open(struct inode *inode, struct file *file) | |||
194 | req->r_inode = inode; | 194 | req->r_inode = inode; |
195 | ihold(inode); | 195 | ihold(inode); |
196 | req->r_num_caps = 1; | 196 | req->r_num_caps = 1; |
197 | if (flags & (O_CREAT|O_TRUNC)) | ||
198 | parent_inode = ceph_get_dentry_parent_inode(file->f_dentry); | ||
197 | err = ceph_mdsc_do_request(mdsc, parent_inode, req); | 199 | err = ceph_mdsc_do_request(mdsc, parent_inode, req); |
200 | iput(parent_inode); | ||
198 | if (!err) | 201 | if (!err) |
199 | err = ceph_init_file(inode, file, req->r_fmode); | 202 | err = ceph_init_file(inode, file, req->r_fmode); |
200 | ceph_mdsc_put_request(req); | 203 | ceph_mdsc_put_request(req); |
@@ -222,9 +225,9 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
222 | { | 225 | { |
223 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); | 226 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
224 | struct ceph_mds_client *mdsc = fsc->mdsc; | 227 | struct ceph_mds_client *mdsc = fsc->mdsc; |
225 | struct file *file = nd->intent.open.file; | 228 | struct file *file; |
226 | struct inode *parent_inode = get_dentry_parent_inode(file->f_dentry); | ||
227 | struct ceph_mds_request *req; | 229 | struct ceph_mds_request *req; |
230 | struct dentry *ret; | ||
228 | int err; | 231 | int err; |
229 | int flags = nd->intent.open.flags; | 232 | int flags = nd->intent.open.flags; |
230 | 233 | ||
@@ -242,16 +245,24 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
242 | req->r_dentry_unless = CEPH_CAP_FILE_EXCL; | 245 | req->r_dentry_unless = CEPH_CAP_FILE_EXCL; |
243 | } | 246 | } |
244 | req->r_locked_dir = dir; /* caller holds dir->i_mutex */ | 247 | req->r_locked_dir = dir; /* caller holds dir->i_mutex */ |
245 | err = ceph_mdsc_do_request(mdsc, parent_inode, req); | 248 | err = ceph_mdsc_do_request(mdsc, |
246 | dentry = ceph_finish_lookup(req, dentry, err); | 249 | (flags & (O_CREAT|O_TRUNC)) ? dir : NULL, |
247 | if (!err && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry) | 250 | req); |
251 | err = ceph_handle_snapdir(req, dentry, err); | ||
252 | if (err) | ||
253 | goto out; | ||
254 | if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry) | ||
248 | err = ceph_handle_notrace_create(dir, dentry); | 255 | err = ceph_handle_notrace_create(dir, dentry); |
249 | if (!err) | 256 | if (err) |
250 | err = ceph_init_file(req->r_dentry->d_inode, file, | 257 | goto out; |
251 | req->r_fmode); | 258 | file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open); |
259 | if (IS_ERR(file)) | ||
260 | err = PTR_ERR(file); | ||
261 | out: | ||
262 | ret = ceph_finish_lookup(req, dentry, err); | ||
252 | ceph_mdsc_put_request(req); | 263 | ceph_mdsc_put_request(req); |
253 | dout("ceph_lookup_open result=%p\n", dentry); | 264 | dout("ceph_lookup_open result=%p\n", ret); |
254 | return dentry; | 265 | return ret; |
255 | } | 266 | } |
256 | 267 | ||
257 | int ceph_release(struct inode *inode, struct file *file) | 268 | int ceph_release(struct inode *inode, struct file *file) |
@@ -643,7 +654,8 @@ again: | |||
643 | 654 | ||
644 | if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 || | 655 | if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 || |
645 | (iocb->ki_filp->f_flags & O_DIRECT) || | 656 | (iocb->ki_filp->f_flags & O_DIRECT) || |
646 | (inode->i_sb->s_flags & MS_SYNCHRONOUS)) | 657 | (inode->i_sb->s_flags & MS_SYNCHRONOUS) || |
658 | (fi->flags & CEPH_F_SYNC)) | ||
647 | /* hmm, this isn't really async... */ | 659 | /* hmm, this isn't really async... */ |
648 | ret = ceph_sync_read(filp, base, len, ppos, &checkeof); | 660 | ret = ceph_sync_read(filp, base, len, ppos, &checkeof); |
649 | else | 661 | else |
@@ -712,7 +724,7 @@ retry_snap: | |||
712 | want = CEPH_CAP_FILE_BUFFER; | 724 | want = CEPH_CAP_FILE_BUFFER; |
713 | ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff); | 725 | ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, &got, endoff); |
714 | if (ret < 0) | 726 | if (ret < 0) |
715 | goto out; | 727 | goto out_put; |
716 | 728 | ||
717 | dout("aio_write %p %llx.%llx %llu~%u got cap refs on %s\n", | 729 | dout("aio_write %p %llx.%llx %llu~%u got cap refs on %s\n", |
718 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, | 730 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, |
@@ -720,12 +732,23 @@ retry_snap: | |||
720 | 732 | ||
721 | if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 || | 733 | if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 || |
722 | (iocb->ki_filp->f_flags & O_DIRECT) || | 734 | (iocb->ki_filp->f_flags & O_DIRECT) || |
723 | (inode->i_sb->s_flags & MS_SYNCHRONOUS)) { | 735 | (inode->i_sb->s_flags & MS_SYNCHRONOUS) || |
736 | (fi->flags & CEPH_F_SYNC)) { | ||
724 | ret = ceph_sync_write(file, iov->iov_base, iov->iov_len, | 737 | ret = ceph_sync_write(file, iov->iov_base, iov->iov_len, |
725 | &iocb->ki_pos); | 738 | &iocb->ki_pos); |
726 | } else { | 739 | } else { |
727 | ret = generic_file_aio_write(iocb, iov, nr_segs, pos); | 740 | /* |
741 | * buffered write; drop Fw early to avoid slow | ||
742 | * revocation if we get stuck on balance_dirty_pages | ||
743 | */ | ||
744 | int dirty; | ||
728 | 745 | ||
746 | spin_lock(&inode->i_lock); | ||
747 | dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); | ||
748 | spin_unlock(&inode->i_lock); | ||
749 | ceph_put_cap_refs(ci, got); | ||
750 | |||
751 | ret = generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
729 | if ((ret >= 0 || ret == -EIOCBQUEUED) && | 752 | if ((ret >= 0 || ret == -EIOCBQUEUED) && |
730 | ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host) | 753 | ((file->f_flags & O_SYNC) || IS_SYNC(file->f_mapping->host) |
731 | || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) { | 754 | || ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))) { |
@@ -733,7 +756,12 @@ retry_snap: | |||
733 | if (err < 0) | 756 | if (err < 0) |
734 | ret = err; | 757 | ret = err; |
735 | } | 758 | } |
759 | |||
760 | if (dirty) | ||
761 | __mark_inode_dirty(inode, dirty); | ||
762 | goto out; | ||
736 | } | 763 | } |
764 | |||
737 | if (ret >= 0) { | 765 | if (ret >= 0) { |
738 | int dirty; | 766 | int dirty; |
739 | spin_lock(&inode->i_lock); | 767 | spin_lock(&inode->i_lock); |
@@ -743,12 +771,13 @@ retry_snap: | |||
743 | __mark_inode_dirty(inode, dirty); | 771 | __mark_inode_dirty(inode, dirty); |
744 | } | 772 | } |
745 | 773 | ||
746 | out: | 774 | out_put: |
747 | dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n", | 775 | dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n", |
748 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, | 776 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len, |
749 | ceph_cap_string(got)); | 777 | ceph_cap_string(got)); |
750 | ceph_put_cap_refs(ci, got); | 778 | ceph_put_cap_refs(ci, got); |
751 | 779 | ||
780 | out: | ||
752 | if (ret == -EOLDSNAPC) { | 781 | if (ret == -EOLDSNAPC) { |
753 | dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n", | 782 | dout("aio_write %p %llx.%llx %llu~%u got EOLDSNAPC, retrying\n", |
754 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len); | 783 | inode, ceph_vinop(inode), pos, (unsigned)iov->iov_len); |