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.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 02834cecc3a0..124c0c17a14a 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -344,7 +344,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
344 INIT_LIST_HEAD(&s->s_waiting); 344 INIT_LIST_HEAD(&s->s_waiting);
345 INIT_LIST_HEAD(&s->s_unsafe); 345 INIT_LIST_HEAD(&s->s_unsafe);
346 s->s_num_cap_releases = 0; 346 s->s_num_cap_releases = 0;
347 s->s_iterating_caps = false; 347 s->s_cap_iterator = NULL;
348 INIT_LIST_HEAD(&s->s_cap_releases); 348 INIT_LIST_HEAD(&s->s_cap_releases);
349 INIT_LIST_HEAD(&s->s_cap_releases_done); 349 INIT_LIST_HEAD(&s->s_cap_releases_done);
350 INIT_LIST_HEAD(&s->s_cap_flushing); 350 INIT_LIST_HEAD(&s->s_cap_flushing);
@@ -729,28 +729,61 @@ static int iterate_session_caps(struct ceph_mds_session *session,
729 int (*cb)(struct inode *, struct ceph_cap *, 729 int (*cb)(struct inode *, struct ceph_cap *,
730 void *), void *arg) 730 void *), void *arg)
731{ 731{
732 struct ceph_cap *cap, *ncap; 732 struct list_head *p;
733 struct inode *inode; 733 struct ceph_cap *cap;
734 struct inode *inode, *last_inode = NULL;
735 struct ceph_cap *old_cap = NULL;
734 int ret; 736 int ret;
735 737
736 dout("iterate_session_caps %p mds%d\n", session, session->s_mds); 738 dout("iterate_session_caps %p mds%d\n", session, session->s_mds);
737 spin_lock(&session->s_cap_lock); 739 spin_lock(&session->s_cap_lock);
738 session->s_iterating_caps = true; 740 p = session->s_caps.next;
739 list_for_each_entry_safe(cap, ncap, &session->s_caps, session_caps) { 741 while (p != &session->s_caps) {
742 cap = list_entry(p, struct ceph_cap, session_caps);
740 inode = igrab(&cap->ci->vfs_inode); 743 inode = igrab(&cap->ci->vfs_inode);
741 if (!inode) 744 if (!inode) {
745 p = p->next;
742 continue; 746 continue;
747 }
748 session->s_cap_iterator = cap;
743 spin_unlock(&session->s_cap_lock); 749 spin_unlock(&session->s_cap_lock);
750
751 if (last_inode) {
752 iput(last_inode);
753 last_inode = NULL;
754 }
755 if (old_cap) {
756 ceph_put_cap(old_cap);
757 old_cap = NULL;
758 }
759
744 ret = cb(inode, cap, arg); 760 ret = cb(inode, cap, arg);
745 iput(inode); 761 last_inode = inode;
762
746 spin_lock(&session->s_cap_lock); 763 spin_lock(&session->s_cap_lock);
764 p = p->next;
765 if (cap->ci == NULL) {
766 dout("iterate_session_caps finishing cap %p removal\n",
767 cap);
768 BUG_ON(cap->session != session);
769 list_del_init(&cap->session_caps);
770 session->s_nr_caps--;
771 cap->session = NULL;
772 old_cap = cap; /* put_cap it w/o locks held */
773 }
747 if (ret < 0) 774 if (ret < 0)
748 goto out; 775 goto out;
749 } 776 }
750 ret = 0; 777 ret = 0;
751out: 778out:
752 session->s_iterating_caps = false; 779 session->s_cap_iterator = NULL;
753 spin_unlock(&session->s_cap_lock); 780 spin_unlock(&session->s_cap_lock);
781
782 if (last_inode)
783 iput(last_inode);
784 if (old_cap)
785 ceph_put_cap(old_cap);
786
754 return ret; 787 return ret;
755} 788}
756 789
@@ -942,7 +975,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg)
942 session->s_trim_caps--; 975 session->s_trim_caps--;
943 if (oissued) { 976 if (oissued) {
944 /* we aren't the only cap.. just remove us */ 977 /* we aren't the only cap.. just remove us */
945 __ceph_remove_cap(cap, NULL); 978 __ceph_remove_cap(cap);
946 } else { 979 } else {
947 /* try to drop referring dentries */ 980 /* try to drop referring dentries */
948 spin_unlock(&inode->i_lock); 981 spin_unlock(&inode->i_lock);