diff options
author | Sage Weil <sage@newdream.net> | 2011-07-26 14:31:14 -0400 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2011-07-26 14:31:14 -0400 |
commit | 41b02e1f9bb87b07d792b64aaeb7af3d00d69cd2 (patch) | |
tree | 87c9524ff96cbff2ff29d659cbefd516b553ca1f /fs/ceph/mds_client.c | |
parent | 4f1772645296a230e04f5c53e79cfb6f841ce634 (diff) |
ceph: explicitly reference rename old_dentry parent dir in request
We carry a pin on the parent directory for the rename source and dest
dentries. For the source it's r_locked_dir; we need to explicitly
reference the old_dentry parent as well, since the dentry's d_parent may
change between when the request was created and pinned and when it is
freed.
Reviewed-by: Yehuda Sadeh <yehuda@hq.newdream.net>
Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 8a09cd5a659e..66a8939cc518 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -483,22 +483,26 @@ void ceph_mdsc_release_request(struct kref *kref) | |||
483 | destroy_reply_info(&req->r_reply_info); | 483 | destroy_reply_info(&req->r_reply_info); |
484 | } | 484 | } |
485 | if (req->r_inode) { | 485 | if (req->r_inode) { |
486 | ceph_put_cap_refs(ceph_inode(req->r_inode), | 486 | ceph_put_cap_refs(ceph_inode(req->r_inode), CEPH_CAP_PIN); |
487 | CEPH_CAP_PIN); | ||
488 | iput(req->r_inode); | 487 | iput(req->r_inode); |
489 | } | 488 | } |
490 | if (req->r_locked_dir) | 489 | if (req->r_locked_dir) |
491 | ceph_put_cap_refs(ceph_inode(req->r_locked_dir), | 490 | ceph_put_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN); |
492 | CEPH_CAP_PIN); | ||
493 | if (req->r_target_inode) | 491 | if (req->r_target_inode) |
494 | iput(req->r_target_inode); | 492 | iput(req->r_target_inode); |
495 | if (req->r_dentry) | 493 | if (req->r_dentry) |
496 | dput(req->r_dentry); | 494 | dput(req->r_dentry); |
497 | if (req->r_old_dentry) { | 495 | if (req->r_old_dentry) { |
498 | ceph_put_cap_refs( | 496 | /* |
499 | ceph_inode(req->r_old_dentry->d_parent->d_inode), | 497 | * track (and drop pins for) r_old_dentry_dir |
500 | CEPH_CAP_PIN); | 498 | * separately, since r_old_dentry's d_parent may have |
499 | * changed between the dir mutex being dropped and | ||
500 | * this request being freed. | ||
501 | */ | ||
502 | ceph_put_cap_refs(ceph_inode(req->r_old_dentry_dir), | ||
503 | CEPH_CAP_PIN); | ||
501 | dput(req->r_old_dentry); | 504 | dput(req->r_old_dentry); |
505 | iput(req->r_old_dentry_dir); | ||
502 | } | 506 | } |
503 | kfree(req->r_path1); | 507 | kfree(req->r_path1); |
504 | kfree(req->r_path2); | 508 | kfree(req->r_path2); |
@@ -1931,9 +1935,8 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc, | |||
1931 | if (req->r_locked_dir) | 1935 | if (req->r_locked_dir) |
1932 | ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN); | 1936 | ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN); |
1933 | if (req->r_old_dentry) | 1937 | if (req->r_old_dentry) |
1934 | ceph_get_cap_refs( | 1938 | ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir), |
1935 | ceph_inode(req->r_old_dentry->d_parent->d_inode), | 1939 | CEPH_CAP_PIN); |
1936 | CEPH_CAP_PIN); | ||
1937 | 1940 | ||
1938 | /* issue */ | 1941 | /* issue */ |
1939 | mutex_lock(&mdsc->mutex); | 1942 | mutex_lock(&mdsc->mutex); |