diff options
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 56 |
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 | */ |
618 | struct dentry *get_nonsnap_parent(struct dentry *dentry) | 622 | struct 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 | */ |
2852 | void ceph_mdsc_lease_release(struct ceph_mds_client *mdsc, struct inode *inode, | 2859 | void 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); |