summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2013-07-25 10:42:44 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2013-07-25 10:42:44 +1000
commit11d6308c773253cc202b09488767e4c2e86c7e1b (patch)
tree428fa33f7eabcee7e85882342ba0352731e3e7dc
parent543d1b776a23a0e83c7cae5df93d50a8b92182f0 (diff)
parent71b43258fca50da88f9d800c7f05ccc742dc7937 (diff)
Merge remote-tracking branch 'ceph/master'
-rw-r--r--fs/ceph/dir.c2
-rw-r--r--fs/ceph/inode.c9
-rw-r--r--fs/ceph/ioctl.c4
-rw-r--r--net/ceph/osd_client.c3
4 files changed, 15 insertions, 3 deletions
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index a40ceda47a32..868b61d56cac 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -793,6 +793,8 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
req->r_locked_dir = dir;
req->r_dentry_drop = CEPH_CAP_FILE_SHARED;
req->r_dentry_unless = CEPH_CAP_FILE_EXCL;
+ /* release LINK_SHARED on source inode (mds will lock it) */
+ req->r_old_inode_drop = CEPH_CAP_LINK_SHARED;
err = ceph_mdsc_do_request(mdsc, dir, req);
if (err) {
d_drop(dentry);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index f3a2abf28a77..2f5edff2f980 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1465,7 +1465,14 @@ static void ceph_vmtruncate_work(struct work_struct *work)
struct inode *inode = &ci->vfs_inode;
dout("vmtruncate_work %p\n", inode);
- mutex_lock(&inode->i_mutex);
+ if (!mutex_trylock(&inode->i_mutex)) {
+ /*
+ * the i_mutex can be hold by a writer who is waiting for
+ * caps. wake up waiters, they will do pending vmtruncate.
+ */
+ wake_up_all(&ci->i_cap_wq);
+ mutex_lock(&inode->i_mutex);
+ }
__ceph_do_pending_vmtruncate(inode);
mutex_unlock(&inode->i_mutex);
iput(inode);
diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c
index e0b4ef31d3c8..a5ce62eb7806 100644
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -196,8 +196,10 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)
r = ceph_calc_file_object_mapping(&ci->i_layout, dl.file_offset, len,
&dl.object_no, &dl.object_offset,
&olen);
- if (r < 0)
+ if (r < 0) {
+ up_read(&osdc->map_sem);
return -EIO;
+ }
dl.file_offset -= dl.object_offset;
dl.object_size = ceph_file_layout_object_size(ci->i_layout);
dl.block_size = ceph_file_layout_su(ci->i_layout);
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index dd47889adc4a..7d40a612232a 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2129,7 +2129,8 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
dout("osdc_start_request failed map, "
" will retry %lld\n", req->r_tid);
rc = 0;
- }
+ } else
+ __unregister_request(osdc, req);
goto out_unlock;
}
if (req->r_osd == NULL) {