summaryrefslogtreecommitdiffstats
path: root/fs/afs/callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/callback.c')
-rw-r--r--fs/afs/callback.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 4876079aa643..d441bef72163 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -94,15 +94,15 @@ int afs_register_server_cb_interest(struct afs_vnode *vnode,
94 struct afs_server *server = entry->server; 94 struct afs_server *server = entry->server;
95 95
96again: 96again:
97 if (vnode->cb_interest && 97 vcbi = rcu_dereference_protected(vnode->cb_interest,
98 likely(vnode->cb_interest == entry->cb_interest)) 98 lockdep_is_held(&vnode->io_lock));
99 if (vcbi && likely(vcbi == entry->cb_interest))
99 return 0; 100 return 0;
100 101
101 read_lock(&slist->lock); 102 read_lock(&slist->lock);
102 cbi = afs_get_cb_interest(entry->cb_interest); 103 cbi = afs_get_cb_interest(entry->cb_interest);
103 read_unlock(&slist->lock); 104 read_unlock(&slist->lock);
104 105
105 vcbi = vnode->cb_interest;
106 if (vcbi) { 106 if (vcbi) {
107 if (vcbi == cbi) { 107 if (vcbi == cbi) {
108 afs_put_cb_interest(afs_v2net(vnode), cbi); 108 afs_put_cb_interest(afs_v2net(vnode), cbi);
@@ -114,8 +114,9 @@ again:
114 */ 114 */
115 if (cbi && vcbi->server == cbi->server) { 115 if (cbi && vcbi->server == cbi->server) {
116 write_seqlock(&vnode->cb_lock); 116 write_seqlock(&vnode->cb_lock);
117 old = vnode->cb_interest; 117 old = rcu_dereference_protected(vnode->cb_interest,
118 vnode->cb_interest = cbi; 118 lockdep_is_held(&vnode->cb_lock.lock));
119 rcu_assign_pointer(vnode->cb_interest, cbi);
119 write_sequnlock(&vnode->cb_lock); 120 write_sequnlock(&vnode->cb_lock);
120 afs_put_cb_interest(afs_v2net(vnode), old); 121 afs_put_cb_interest(afs_v2net(vnode), old);
121 return 0; 122 return 0;
@@ -160,8 +161,9 @@ again:
160 */ 161 */
161 write_seqlock(&vnode->cb_lock); 162 write_seqlock(&vnode->cb_lock);
162 163
163 old = vnode->cb_interest; 164 old = rcu_dereference_protected(vnode->cb_interest,
164 vnode->cb_interest = cbi; 165 lockdep_is_held(&vnode->cb_lock.lock));
166 rcu_assign_pointer(vnode->cb_interest, cbi);
165 vnode->cb_s_break = cbi->server->cb_s_break; 167 vnode->cb_s_break = cbi->server->cb_s_break;
166 vnode->cb_v_break = vnode->volume->cb_v_break; 168 vnode->cb_v_break = vnode->volume->cb_v_break;
167 clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); 169 clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
@@ -191,10 +193,11 @@ void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi)
191 vi = NULL; 193 vi = NULL;
192 194
193 write_unlock(&cbi->server->cb_break_lock); 195 write_unlock(&cbi->server->cb_break_lock);
194 kfree(vi); 196 if (vi)
197 kfree_rcu(vi, rcu);
195 afs_put_server(net, cbi->server); 198 afs_put_server(net, cbi->server);
196 } 199 }
197 kfree(cbi); 200 kfree_rcu(cbi, rcu);
198 } 201 }
199} 202}
200 203