aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 16:38:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 16:38:50 -0400
commitba5b56cb3e3d2cab73d4fee9a022bb69462a8cd9 (patch)
treeeda7ea059a41ae5d68e2ad5a36a87069187ef22a /fs/ceph/file.c
parent243dd2809a5edd2e0e3e62781083aa44049af37d (diff)
parentd79698da32b317e96216236f265a9b72b78ae568 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: (23 commits) ceph: document unlocked d_parent accesses ceph: explicitly reference rename old_dentry parent dir in request ceph: document locking for ceph_set_dentry_offset ceph: avoid d_parent in ceph_dentry_hash; fix ceph_encode_fh() hashing bug ceph: protect d_parent access in ceph_d_revalidate ceph: protect access to d_parent ceph: handle racing calls to ceph_init_dentry ceph: set dir complete frag after adding capability rbd: set blk_queue request sizes to object size ceph: set up readahead size when rsize is not passed rbd: cancel watch request when releasing the device ceph: ignore lease mask ceph: fix ceph_lookup_open intent usage ceph: only link open operations to directory unsafe list if O_CREAT|O_TRUNC ceph: fix bad parent_inode calc in ceph_lookup_open ceph: avoid carrying Fw cap during write into page cache libceph: don't time out osd requests that haven't been received ceph: report f_bfree based on kb_avail rather than diffing. ceph: only queue capsnap if caps are dirty ceph: fix snap writeback when racing with writes ...
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);