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 #include "cmservice.h" 23 24 /*****************************************************************************/ 25 /* 26 * allow the fileserver to request callback state (re-)initialisation 27 */ 28 int SRXAFSCM_InitCallBackState(struct afs_server *server) 29 { 30 struct list_head callbacks; 31 32 _enter("%p", server); 33 34 INIT_LIST_HEAD(&callbacks); 35 36 /* transfer the callback list from the server to a temp holding area */ 37 spin_lock(&server->cb_lock); 38 39 list_add(&callbacks, &server->cb_promises); 40 list_del_init(&server->cb_promises); 41 42 /* munch our way through the list, grabbing the inode, dropping all the 43 * locks and regetting them in the right order 44 */ 45 while (!list_empty(&callbacks)) { 46 struct afs_vnode *vnode; 47 struct inode *inode; 48 49 vnode = list_entry(callbacks.next, struct afs_vnode, cb_link); 50 list_del_init(&vnode->cb_link); 51 52 /* try and grab the inode - may fail */ 53 inode = igrab(AFS_VNODE_TO_I(vnode)); 54 if (inode) { 55 int release = 0; 56 57 spin_unlock(&server->cb_lock); 58 spin_lock(&vnode->lock); 59 60 if (vnode->cb_server == server) { 61 vnode->cb_server = NULL; 62 afs_kafstimod_del_timer(&vnode->cb_timeout); 63 spin_lock(&afs_cb_hash_lock); 64 list_del_init(&vnode->cb_hash_link); 65 spin_unlock(&afs_cb_hash_lock); 66 release = 1; 67 } 68 69 spin_unlock(&vnode->lock); 70 71 iput(inode); 72 afs_put_server(server); 73 74 spin_lock(&server->cb_lock); 75 } 76 } 77 78 spin_unlock(&server->cb_lock); 79 80 _leave(" = 0"); 81 return 0; 82 } /* end SRXAFSCM_InitCallBackState() */ 83 84 /*****************************************************************************/ 85 /* 86 * allow the fileserver to break callback promises 87 */ 88 int SRXAFSCM_CallBack(struct afs_server *server, size_t count, 89 struct afs_callback callbacks[]) 90 { 91 _enter("%p,%u,", server, count); 92 93 for (; count > 0; callbacks++, count--) { 94 struct afs_vnode *vnode = NULL; 95 struct inode *inode = NULL; 96 int valid = 0; 97 98 _debug("- Fid { vl=%08x n=%u u=%u } CB { v=%u x=%u t=%u }", 99 callbacks->fid.vid, 100 callbacks->fid.vnode, 101 callbacks->fid.unique, 102 callbacks->version, 103 callbacks->expiry, 104 callbacks->type 105 ); 106 107 /* find the inode for this fid */ 108 spin_lock(&afs_cb_hash_lock); 109 110 list_for_each_entry(vnode, 111 &afs_cb_hash(server, &callbacks->fid), 112 cb_hash_link) { 113 if (memcmp(&vnode->fid, &callbacks->fid, 114 sizeof(struct afs_fid)) != 0) 115 continue; 116 117 /* right vnode, but is it same server? */ 118 if (vnode->cb_server != server) 119 break; /* no */ 120 121 /* try and nail the inode down */ 122 inode = igrab(AFS_VNODE_TO_I(vnode)); 123 break; 124 } 125 126 spin_unlock(&afs_cb_hash_lock); 127 128 if (inode) { 129 /* we've found the record for this vnode */ 130 spin_lock(&vnode->lock); 131 if (vnode->cb_server == server) { 132 /* the callback _is_ on the calling server */ 133 vnode->cb_server = NULL; 134 valid = 1; 135 136 afs_kafstimod_del_timer(&vnode->cb_timeout); 137 vnode->flags |= AFS_VNODE_CHANGED; 138 139 spin_lock(&server->cb_lock); 140 list_del_init(&vnode->cb_link); 141 spin_unlock(&server->cb_lock); 142 143 spin_lock(&afs_cb_hash_lock); 144 list_del_init(&vnode->cb_hash_link); 145 spin_unlock(&afs_cb_hash_lock); 146 } 147 spin_unlock(&vnode->lock); 148 149 if (valid) { 150 invalidate_remote_inode(inode); 151 afs_put_server(server); 152 } 153 iput(inode); 154 } 155 } 156 157 _leave(" = 0"); 158 return 0; 159 } /* end SRXAFSCM_CallBack() */ 160 161 /*****************************************************************************/ 162 /* 163 * allow the fileserver to see if the cache manager is still alive 164 */ 165 int SRXAFSCM_Probe(struct afs_server *server) 166 { 167 _debug("SRXAFSCM_Probe(%p)\n", server); 168 return 0; 169 } /* end SRXAFSCM_Probe() */ 170