2005-04-16 15:20:36 -07:00
/*
* linux / fs / nfs / callback_proc . c
*
* Copyright ( C ) 2004 Trond Myklebust
*
* NFSv4 callback procedures
*/
# include <linux/nfs4.h>
# include <linux/nfs_fs.h>
2005-06-22 17:16:21 +00:00
# include "nfs4_fs.h"
2005-04-16 15:20:36 -07:00
# include "callback.h"
# include "delegation.h"
2006-08-22 20:06:10 -04:00
# include "internal.h"
2005-04-16 15:20:36 -07:00
2007-12-10 14:57:23 -05:00
# ifdef NFS_DEBUG
2005-04-16 15:20:36 -07:00
# define NFSDBG_FACILITY NFSDBG_CALLBACK
2007-12-10 14:57:23 -05:00
# endif
2005-04-16 15:20:36 -07:00
2006-10-19 23:28:50 -07:00
__be32 nfs4_callback_getattr ( struct cb_getattrargs * args , struct cb_getattrres * res )
2005-04-16 15:20:36 -07:00
{
2006-08-22 20:06:08 -04:00
struct nfs_client * clp ;
2005-04-16 15:20:36 -07:00
struct nfs_delegation * delegation ;
struct nfs_inode * nfsi ;
struct inode * inode ;
2007-12-10 14:57:23 -05:00
2005-04-16 15:20:36 -07:00
res - > bitmap [ 0 ] = res - > bitmap [ 1 ] = 0 ;
res - > status = htonl ( NFS4ERR_BADHANDLE ) ;
2007-12-10 14:58:44 -05:00
clp = nfs_find_client ( args - > addr , 4 ) ;
2005-04-16 15:20:36 -07:00
if ( clp = = NULL )
goto out ;
2007-12-10 14:57:23 -05:00
dprintk ( " NFS: GETATTR callback request from %s \n " ,
rpc_peeraddr2str ( clp - > cl_rpcclient , RPC_DISPLAY_ADDR ) ) ;
2005-04-16 15:20:36 -07:00
inode = nfs_delegation_find_inode ( clp , & args - > fh ) ;
if ( inode = = NULL )
goto out_putclient ;
nfsi = NFS_I ( inode ) ;
down_read ( & nfsi - > rwsem ) ;
delegation = nfsi - > delegation ;
if ( delegation = = NULL | | ( delegation - > type & FMODE_WRITE ) = = 0 )
goto out_iput ;
res - > size = i_size_read ( inode ) ;
2006-01-03 09:55:37 +01:00
res - > change_attr = delegation - > change_attr ;
if ( nfsi - > npages ! = 0 )
res - > change_attr + + ;
2005-04-16 15:20:36 -07:00
res - > ctime = inode - > i_ctime ;
res - > mtime = inode - > i_mtime ;
res - > bitmap [ 0 ] = ( FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE ) &
args - > bitmap [ 0 ] ;
res - > bitmap [ 1 ] = ( FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY ) &
args - > bitmap [ 1 ] ;
res - > status = 0 ;
out_iput :
up_read ( & nfsi - > rwsem ) ;
iput ( inode ) ;
out_putclient :
2006-08-22 20:06:10 -04:00
nfs_put_client ( clp ) ;
2005-04-16 15:20:36 -07:00
out :
2008-05-02 13:42:44 -07:00
dprintk ( " %s: exit with status = %d \n " , __func__ , ntohl ( res - > status ) ) ;
2005-04-16 15:20:36 -07:00
return res - > status ;
}
2006-10-19 23:28:50 -07:00
__be32 nfs4_callback_recall ( struct cb_recallargs * args , void * dummy )
2005-04-16 15:20:36 -07:00
{
2006-08-22 20:06:08 -04:00
struct nfs_client * clp ;
2005-04-16 15:20:36 -07:00
struct inode * inode ;
2006-10-19 23:28:50 -07:00
__be32 res ;
2005-04-16 15:20:36 -07:00
res = htonl ( NFS4ERR_BADHANDLE ) ;
2007-12-10 14:58:44 -05:00
clp = nfs_find_client ( args - > addr , 4 ) ;
2005-04-16 15:20:36 -07:00
if ( clp = = NULL )
goto out ;
2007-12-10 14:57:23 -05:00
dprintk ( " NFS: RECALL callback request from %s \n " ,
rpc_peeraddr2str ( clp - > cl_rpcclient , RPC_DISPLAY_ADDR ) ) ;
2008-01-26 01:06:40 -05:00
do {
struct nfs_client * prev = clp ;
inode = nfs_delegation_find_inode ( clp , & args - > fh ) ;
if ( inode ! = NULL ) {
/* Set up a helper thread to actually return the delegation */
switch ( nfs_async_inode_return_delegation ( inode , & args - > stateid ) ) {
case 0 :
res = 0 ;
break ;
case - ENOENT :
if ( res ! = 0 )
res = htonl ( NFS4ERR_BAD_STATEID ) ;
break ;
default :
res = htonl ( NFS4ERR_RESOURCE ) ;
}
iput ( inode ) ;
}
clp = nfs_find_client_next ( prev ) ;
nfs_put_client ( prev ) ;
} while ( clp ! = NULL ) ;
2005-04-16 15:20:36 -07:00
out :
2008-05-02 13:42:44 -07:00
dprintk ( " %s: exit with status = %d \n " , __func__ , ntohl ( res ) ) ;
2005-04-16 15:20:36 -07:00
return res ;
}