Merge /spare/repo/linux-2.6/
[linux-2.6] / fs / afs / callback.c
1 /*
2  * Copyright (c) 2002 Red Hat, Inc. All rights reserved.
3  *
4  * This software may be freely redistributed under the terms of the
5  * GNU General Public License.
6  *
7  * You should have received a copy of the GNU General Public License
8  * along with this program; if not, write to the Free Software
9  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10  *
11  * Authors: David Woodhouse <dwmw2@cambridge.redhat.com>
12  *          David Howells <dhowells@redhat.com>
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include "server.h"
20 #include "vnode.h"
21 #include "internal.h"
22
23 /*****************************************************************************/
24 /*
25  * allow the fileserver to request callback state (re-)initialisation
26  */
27 int SRXAFSCM_InitCallBackState(struct afs_server *server)
28 {
29         struct list_head callbacks;
30
31         _enter("%p", server);
32
33         INIT_LIST_HEAD(&callbacks);
34
35         /* transfer the callback list from the server to a temp holding area */
36         spin_lock(&server->cb_lock);
37
38         list_add(&callbacks, &server->cb_promises);
39         list_del_init(&server->cb_promises);
40
41         /* munch our way through the list, grabbing the inode, dropping all the
42          * locks and regetting them in the right order
43          */
44         while (!list_empty(&callbacks)) {
45                 struct afs_vnode *vnode;
46                 struct inode *inode;
47
48                 vnode = list_entry(callbacks.next, struct afs_vnode, cb_link);
49                 list_del_init(&vnode->cb_link);
50
51                 /* try and grab the inode - may fail */
52                 inode = igrab(AFS_VNODE_TO_I(vnode));
53                 if (inode) {
54                         int release = 0;
55
56                         spin_unlock(&server->cb_lock);
57                         spin_lock(&vnode->lock);
58
59                         if (vnode->cb_server == server) {
60                                 vnode->cb_server = NULL;
61                                 afs_kafstimod_del_timer(&vnode->cb_timeout);
62                                 spin_lock(&afs_cb_hash_lock);
63                                 list_del_init(&vnode->cb_hash_link);
64                                 spin_unlock(&afs_cb_hash_lock);
65                                 release = 1;
66                         }
67
68                         spin_unlock(&vnode->lock);
69
70                         iput(inode);
71                         afs_put_server(server);
72
73                         spin_lock(&server->cb_lock);
74                 }
75         }
76
77         spin_unlock(&server->cb_lock);
78
79         _leave(" = 0");
80         return 0;
81 } /* end SRXAFSCM_InitCallBackState() */
82
83 /*****************************************************************************/
84 /*
85  * allow the fileserver to break callback promises
86  */
87 int SRXAFSCM_CallBack(struct afs_server *server, size_t count,
88                       struct afs_callback callbacks[])
89 {
90         _enter("%p,%u,", server, count);
91
92         for (; count > 0; callbacks++, count--) {
93                 struct afs_vnode *vnode = NULL;
94                 struct inode *inode = NULL;
95                 int valid = 0;
96
97                 _debug("- Fid { vl=%08x n=%u u=%u }  CB { v=%u x=%u t=%u }",
98                        callbacks->fid.vid,
99                        callbacks->fid.vnode,
100                        callbacks->fid.unique,
101                        callbacks->version,
102                        callbacks->expiry,
103                        callbacks->type
104                        );
105
106                 /* find the inode for this fid */
107                 spin_lock(&afs_cb_hash_lock);
108
109                 list_for_each_entry(vnode,
110                                     &afs_cb_hash(server, &callbacks->fid),
111                                     cb_hash_link) {
112                         if (memcmp(&vnode->fid, &callbacks->fid,
113                                    sizeof(struct afs_fid)) != 0)
114                                 continue;
115
116                         /* right vnode, but is it same server? */
117                         if (vnode->cb_server != server)
118                                 break; /* no */
119
120                         /* try and nail the inode down */
121                         inode = igrab(AFS_VNODE_TO_I(vnode));
122                         break;
123                 }
124
125                 spin_unlock(&afs_cb_hash_lock);
126
127                 if (inode) {
128                         /* we've found the record for this vnode */
129                         spin_lock(&vnode->lock);
130                         if (vnode->cb_server == server) {
131                                 /* the callback _is_ on the calling server */
132                                 vnode->cb_server = NULL;
133                                 valid = 1;
134
135                                 afs_kafstimod_del_timer(&vnode->cb_timeout);
136                                 vnode->flags |= AFS_VNODE_CHANGED;
137
138                                 spin_lock(&server->cb_lock);
139                                 list_del_init(&vnode->cb_link);
140                                 spin_unlock(&server->cb_lock);
141
142                                 spin_lock(&afs_cb_hash_lock);
143                                 list_del_init(&vnode->cb_hash_link);
144                                 spin_unlock(&afs_cb_hash_lock);
145                         }
146                         spin_unlock(&vnode->lock);
147
148                         if (valid) {
149                                 invalidate_remote_inode(inode);
150                                 afs_put_server(server);
151                         }
152                         iput(inode);
153                 }
154         }
155
156         _leave(" = 0");
157         return 0;
158 } /* end SRXAFSCM_CallBack() */
159
160 /*****************************************************************************/
161 /*
162  * allow the fileserver to see if the cache manager is still alive
163  */
164 int SRXAFSCM_Probe(struct afs_server *server)
165 {
166         _debug("SRXAFSCM_Probe(%p)\n", server);
167         return 0;
168 } /* end SRXAFSCM_Probe() */