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.c61
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);
261out:
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
257int ceph_release(struct inode *inode, struct file *file) 268int 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
746out: 774out_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
780out:
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);