2005-04-16 15:20:36 -07:00
/*
* 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 0213 9 , 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"
2005-11-08 16:56:17 +01:00
# include "cmservice.h"
2005-04-16 15:20:36 -07:00
/*****************************************************************************/
/*
* 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() */