aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/mds_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r--fs/ceph/mds_client.c56
1 files changed, 31 insertions, 25 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 0c1d91756528..fee028b5332e 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);
@@ -617,6 +621,12 @@ static void __unregister_request(struct ceph_mds_client *mdsc,
617 */ 621 */
618struct dentry *get_nonsnap_parent(struct dentry *dentry) 622struct dentry *get_nonsnap_parent(struct dentry *dentry)
619{ 623{
624 /*
625 * we don't need to worry about protecting the d_parent access
626 * here because we never renaming inside the snapped namespace
627 * except to resplice to another snapdir, and either the old or new
628 * result is a valid result.
629 */
620 while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP) 630 while (!IS_ROOT(dentry) && ceph_snap(dentry->d_inode) != CEPH_NOSNAP)
621 dentry = dentry->d_parent; 631 dentry = dentry->d_parent;
622 return dentry; 632 return dentry;
@@ -652,7 +662,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
652 if (req->r_inode) { 662 if (req->r_inode) {
653 inode = req->r_inode; 663 inode = req->r_inode;
654 } else if (req->r_dentry) { 664 } else if (req->r_dentry) {
655 struct inode *dir = req->r_dentry->d_parent->d_inode; 665 /* ignore race with rename; old or new d_parent is okay */
666 struct dentry *parent = req->r_dentry->d_parent;
667 struct inode *dir = parent->d_inode;
656 668
657 if (dir->i_sb != mdsc->fsc->sb) { 669 if (dir->i_sb != mdsc->fsc->sb) {
658 /* not this fs! */ 670 /* not this fs! */
@@ -660,8 +672,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
660 } else if (ceph_snap(dir) != CEPH_NOSNAP) { 672 } else if (ceph_snap(dir) != CEPH_NOSNAP) {
661 /* direct snapped/virtual snapdir requests 673 /* direct snapped/virtual snapdir requests
662 * based on parent dir inode */ 674 * based on parent dir inode */
663 struct dentry *dn = 675 struct dentry *dn = get_nonsnap_parent(parent);
664 get_nonsnap_parent(req->r_dentry->d_parent);
665 inode = dn->d_inode; 676 inode = dn->d_inode;
666 dout("__choose_mds using nonsnap parent %p\n", inode); 677 dout("__choose_mds using nonsnap parent %p\n", inode);
667 } else if (req->r_dentry->d_inode) { 678 } else if (req->r_dentry->d_inode) {
@@ -670,7 +681,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
670 } else { 681 } else {
671 /* dir + name */ 682 /* dir + name */
672 inode = dir; 683 inode = dir;
673 hash = ceph_dentry_hash(req->r_dentry); 684 hash = ceph_dentry_hash(dir, req->r_dentry);
674 is_hash = true; 685 is_hash = true;
675 } 686 }
676 } 687 }
@@ -1931,9 +1942,8 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
1931 if (req->r_locked_dir) 1942 if (req->r_locked_dir)
1932 ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN); 1943 ceph_get_cap_refs(ceph_inode(req->r_locked_dir), CEPH_CAP_PIN);
1933 if (req->r_old_dentry) 1944 if (req->r_old_dentry)
1934 ceph_get_cap_refs( 1945 ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
1935 ceph_inode(req->r_old_dentry->d_parent->d_inode), 1946 CEPH_CAP_PIN);
1936 CEPH_CAP_PIN);
1937 1947
1938 /* issue */ 1948 /* issue */
1939 mutex_lock(&mdsc->mutex); 1949 mutex_lock(&mdsc->mutex);
@@ -2714,7 +2724,6 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2714 struct ceph_mds_lease *h = msg->front.iov_base; 2724 struct ceph_mds_lease *h = msg->front.iov_base;
2715 u32 seq; 2725 u32 seq;
2716 struct ceph_vino vino; 2726 struct ceph_vino vino;
2717 int mask;
2718 struct qstr dname; 2727 struct qstr dname;
2719 int release = 0; 2728 int release = 0;
2720 2729
@@ -2725,7 +2734,6 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2725 goto bad; 2734 goto bad;
2726 vino.ino = le64_to_cpu(h->ino); 2735 vino.ino = le64_to_cpu(h->ino);
2727 vino.snap = CEPH_NOSNAP; 2736 vino.snap = CEPH_NOSNAP;
2728 mask = le16_to_cpu(h->mask);
2729 seq = le32_to_cpu(h->seq); 2737 seq = le32_to_cpu(h->seq);
2730 dname.name = (void *)h + sizeof(*h) + sizeof(u32); 2738 dname.name = (void *)h + sizeof(*h) + sizeof(u32);
2731 dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32); 2739 dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
@@ -2737,8 +2745,8 @@ static void handle_lease(struct ceph_mds_client *mdsc,
2737 2745
2738 /* lookup inode */ 2746 /* lookup inode */
2739 inode = ceph_find_inode(sb, vino); 2747 inode = ceph_find_inode(sb, vino);
2740 dout("handle_lease %s, mask %d, ino %llx %p %.*s\n", 2748 dout("handle_lease %s, ino %llx %p %.*s\n",
2741 ceph_lease_op_name(h->action), mask, vino.ino, inode, 2749 ceph_lease_op_name(h->action), vino.ino, inode,
2742 dname.len, dname.name); 2750 dname.len, dname.name);
2743 if (inode == NULL) { 2751 if (inode == NULL) {
2744 dout("handle_lease no inode %llx\n", vino.ino); 2752 dout("handle_lease no inode %llx\n", vino.ino);
@@ -2828,7 +2836,6 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
2828 return; 2836 return;
2829 lease = msg->front.iov_base; 2837 lease = msg->front.iov_base;
2830 lease->action = action; 2838 lease->action = action;
2831 lease->mask = cpu_to_le16(1);
2832 lease->ino = cpu_to_le64(ceph_vino(inode).ino); 2839 lease->ino = cpu_to_le64(ceph_vino(inode).ino);
2833 lease->first = lease->last = cpu_to_le64(ceph_vino(inode).snap); 2840 lease->first = lease->last = cpu_to_le64(ceph_vino(inode).snap);
2834 lease->seq = cpu_to_le32(seq); 2841 lease->seq = cpu_to_le32(seq);
@@ -2850,7 +2857,7 @@ void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
2850 * Pass @inode always, @dentry is optional. 2857 * Pass @inode always, @dentry is optional.
2851 */ 2858 */
2852void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode, 2859void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
2853 struct dentry *dentry, int mask) 2860 struct dentry *dentry)
2854{ 2861{
2855 struct ceph_dentry_info *di; 2862 struct ceph_dentry_info *di;
2856 struct ceph_mds_session *session; 2863 struct ceph_mds_session *session;
@@ -2858,7 +2865,6 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
2858 2865
2859 BUG_ON(inode == NULL); 2866 BUG_ON(inode == NULL);
2860 BUG_ON(dentry == NULL); 2867 BUG_ON(dentry == NULL);
2861 BUG_ON(mask == 0);
2862 2868
2863 /* is dentry lease valid? */ 2869 /* is dentry lease valid? */
2864 spin_lock(&dentry->d_lock); 2870 spin_lock(&dentry->d_lock);
@@ -2868,8 +2874,8 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
2868 di->lease_gen != di->lease_session->s_cap_gen || 2874 di->lease_gen != di->lease_session->s_cap_gen ||
2869 !time_before(jiffies, dentry->d_time)) { 2875 !time_before(jiffies, dentry->d_time)) {
2870 dout("lease_release inode %p dentry %p -- " 2876 dout("lease_release inode %p dentry %p -- "
2871 "no lease on %d\n", 2877 "no lease\n",
2872 inode, dentry, mask); 2878 inode, dentry);
2873 spin_unlock(&dentry->d_lock); 2879 spin_unlock(&dentry->d_lock);
2874 return; 2880 return;
2875 } 2881 }
@@ -2880,8 +2886,8 @@ void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode,
2880 __ceph_mdsc_drop_dentry_lease(dentry); 2886 __ceph_mdsc_drop_dentry_lease(dentry);
2881 spin_unlock(&dentry->d_lock); 2887 spin_unlock(&dentry->d_lock);
2882 2888
2883 dout("lease_release inode %p dentry %p mask %d to mds%d\n", 2889 dout("lease_release inode %p dentry %p to mds%d\n",
2884 inode, dentry, mask, session->s_mds); 2890 inode, dentry, session->s_mds);
2885 ceph_mdsc_lease_send_msg(session, inode, dentry, 2891 ceph_mdsc_lease_send_msg(session, inode, dentry,
2886 CEPH_MDS_LEASE_RELEASE, seq); 2892 CEPH_MDS_LEASE_RELEASE, seq);
2887 ceph_put_mds_session(session); 2893 ceph_put_mds_session(session);