| /* | |
| * Copyright (c) 2002 Red Hat, Inc. All rights reserved. | |
| * | |
| * This software may be freely redistributed under the terms of the | |
| * GNU General Public License. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| * | |
| * Authors: David Woodhouse <dwmw2@cambridge.redhat.com> | |
| * David Howells <dhowells@redhat.com> | |
| * | |
| */ | |
| #include <linux/kernel.h> | |
| #include <linux/module.h> | |
| #include <linux/init.h> | |
| #include "server.h" | |
| #include "vnode.h" | |
| #include "internal.h" | |
| #include "cmservice.h" | |
| /*****************************************************************************/ | |
| /* | |
| * allow the fileserver to request callback state (re-)initialisation | |
| */ | |
| int SRXAFSCM_InitCallBackState(struct afs_server *server) | |
| { | |
| struct list_head callbacks; | |
| _enter("%p", server); | |
| INIT_LIST_HEAD(&callbacks); | |
| /* transfer the callback list from the server to a temp holding area */ | |
| spin_lock(&server->cb_lock); | |
| list_add(&callbacks, &server->cb_promises); | |
| list_del_init(&server->cb_promises); | |
| /* munch our way through the list, grabbing the inode, dropping all the | |
| * locks and regetting them in the right order | |
| */ | |
| while (!list_empty(&callbacks)) { | |
| struct afs_vnode *vnode; | |
| struct inode *inode; | |
| vnode = list_entry(callbacks.next, struct afs_vnode, cb_link); | |
| list_del_init(&vnode->cb_link); | |
| /* try and grab the inode - may fail */ | |
| inode = igrab(AFS_VNODE_TO_I(vnode)); | |
| if (inode) { | |
| int release = 0; | |
| spin_unlock(&server->cb_lock); | |
| spin_lock(&vnode->lock); | |
| if (vnode->cb_server == server) { | |
| vnode->cb_server = NULL; | |
| afs_kafstimod_del_timer(&vnode->cb_timeout); | |
| spin_lock(&afs_cb_hash_lock); | |
| list_del_init(&vnode->cb_hash_link); | |
| spin_unlock(&afs_cb_hash_lock); | |
| release = 1; | |
| } | |
| spin_unlock(&vnode->lock); | |
| iput(inode); | |
| afs_put_server(server); | |
| spin_lock(&server->cb_lock); | |
| } | |
| } | |
| spin_unlock(&server->cb_lock); | |
| _leave(" = 0"); | |
| return 0; | |
| } /* end SRXAFSCM_InitCallBackState() */ | |
| /*****************************************************************************/ | |
| /* | |
| * allow the fileserver to break callback promises | |
| */ | |
| int SRXAFSCM_CallBack(struct afs_server *server, size_t count, | |
| struct afs_callback callbacks[]) | |
| { | |
| _enter("%p,%u,", server, count); | |
| for (; count > 0; callbacks++, count--) { | |
| struct afs_vnode *vnode = NULL; | |
| struct inode *inode = NULL; | |
| int valid = 0; | |
| _debug("- Fid { vl=%08x n=%u u=%u } CB { v=%u x=%u t=%u }", | |
| callbacks->fid.vid, | |
| callbacks->fid.vnode, | |
| callbacks->fid.unique, | |
| callbacks->version, | |
| callbacks->expiry, | |
| callbacks->type | |
| ); | |
| /* find the inode for this fid */ | |
| spin_lock(&afs_cb_hash_lock); | |
| list_for_each_entry(vnode, | |
| &afs_cb_hash(server, &callbacks->fid), | |
| cb_hash_link) { | |
| if (memcmp(&vnode->fid, &callbacks->fid, | |
| sizeof(struct afs_fid)) != 0) | |
| continue; | |
| /* right vnode, but is it same server? */ | |
| if (vnode->cb_server != server) | |
| break; /* no */ | |
| /* try and nail the inode down */ | |
| inode = igrab(AFS_VNODE_TO_I(vnode)); | |
| break; | |
| } | |
| spin_unlock(&afs_cb_hash_lock); | |
| if (inode) { | |
| /* we've found the record for this vnode */ | |
| spin_lock(&vnode->lock); | |
| if (vnode->cb_server == server) { | |
| /* the callback _is_ on the calling server */ | |
| vnode->cb_server = NULL; | |
| valid = 1; | |
| afs_kafstimod_del_timer(&vnode->cb_timeout); | |
| vnode->flags |= AFS_VNODE_CHANGED; | |
| spin_lock(&server->cb_lock); | |
| list_del_init(&vnode->cb_link); | |
| spin_unlock(&server->cb_lock); | |
| spin_lock(&afs_cb_hash_lock); | |
| list_del_init(&vnode->cb_hash_link); | |
| spin_unlock(&afs_cb_hash_lock); | |
| } | |
| spin_unlock(&vnode->lock); | |
| if (valid) { | |
| invalidate_remote_inode(inode); | |
| afs_put_server(server); | |
| } | |
| iput(inode); | |
| } | |
| } | |
| _leave(" = 0"); | |
| return 0; | |
| } /* end SRXAFSCM_CallBack() */ | |
| /*****************************************************************************/ | |
| /* | |
| * allow the fileserver to see if the cache manager is still alive | |
| */ | |
| int SRXAFSCM_Probe(struct afs_server *server) | |
| { | |
| _debug("SRXAFSCM_Probe(%p)\n", server); | |
| return 0; | |
| } /* end SRXAFSCM_Probe() */ |