diff options
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 51 |
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; |
751 | out: | 778 | out: |
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); |