2015-07-17 17:38:12 +03:00
/*
* ( C ) 2001 Clemson University and The University of Chicago
*
* See COPYING in top - level directory .
*/
/*
* Implementation of dentry ( directory cache ) functions .
*/
# include "protocol.h"
2015-12-04 20:56:14 +03:00
# include "orangefs-kernel.h"
2015-07-17 17:38:12 +03:00
/* Returns 1 if dentry can still be trusted, else 0. */
2015-11-24 23:12:14 +03:00
static int orangefs_revalidate_lookup ( struct dentry * dentry )
2015-07-17 17:38:12 +03:00
{
struct dentry * parent_dentry = dget_parent ( dentry ) ;
struct inode * parent_inode = parent_dentry - > d_inode ;
2015-11-24 23:12:14 +03:00
struct orangefs_inode_s * parent = ORANGEFS_I ( parent_inode ) ;
2015-07-17 17:38:12 +03:00
struct inode * inode = dentry - > d_inode ;
2015-11-24 23:12:14 +03:00
struct orangefs_kernel_op_s * new_op ;
2015-07-17 17:38:12 +03:00
int ret = 0 ;
int err = 0 ;
gossip_debug ( GOSSIP_DCACHE_DEBUG , " %s: attempting lookup. \n " , __func__ ) ;
2015-11-24 23:12:14 +03:00
new_op = op_alloc ( ORANGEFS_VFS_OP_LOOKUP ) ;
2015-07-17 17:38:12 +03:00
if ( ! new_op )
goto out_put_parent ;
2015-11-24 23:12:14 +03:00
new_op - > upcall . req . lookup . sym_follow = ORANGEFS_LOOKUP_LINK_NO_FOLLOW ;
2015-07-17 17:38:12 +03:00
new_op - > upcall . req . lookup . parent_refn = parent - > refn ;
strncpy ( new_op - > upcall . req . lookup . d_name ,
dentry - > d_name . name ,
2015-11-24 23:12:14 +03:00
ORANGEFS_NAME_LEN ) ;
2015-07-17 17:38:12 +03:00
gossip_debug ( GOSSIP_DCACHE_DEBUG ,
" %s:%s:%d interrupt flag [%d] \n " ,
__FILE__ ,
__func__ ,
__LINE__ ,
get_interruptible_flag ( parent_inode ) ) ;
2015-11-24 23:12:14 +03:00
err = service_operation ( new_op , " orangefs_lookup " ,
2015-07-17 17:38:12 +03:00
get_interruptible_flag ( parent_inode ) ) ;
if ( err )
goto out_drop ;
if ( new_op - > downcall . status ! = 0 | |
! match_handle ( new_op - > downcall . resp . lookup . refn . khandle , inode ) ) {
gossip_debug ( GOSSIP_DCACHE_DEBUG ,
" %s:%s:%d "
" lookup failure |%s| or no match |%s|. \n " ,
__FILE__ ,
__func__ ,
__LINE__ ,
new_op - > downcall . status ? " true " : " false " ,
match_handle ( new_op - > downcall . resp . lookup . refn . khandle ,
inode ) ? " false " : " true " ) ;
gossip_debug ( GOSSIP_DCACHE_DEBUG ,
" %s:%s:%d revalidate failed \n " ,
__FILE__ , __func__ , __LINE__ ) ;
goto out_drop ;
}
ret = 1 ;
out_release_op :
op_release ( new_op ) ;
out_put_parent :
dput ( parent_dentry ) ;
return ret ;
out_drop :
d_drop ( dentry ) ;
goto out_release_op ;
}
/*
* Verify that dentry is valid .
*
* Should return 1 if dentry can still be trusted , else 0
*/
2015-11-24 23:12:14 +03:00
static int orangefs_d_revalidate ( struct dentry * dentry , unsigned int flags )
2015-07-17 17:38:12 +03:00
{
struct inode * inode ;
int ret = 0 ;
if ( flags & LOOKUP_RCU )
return - ECHILD ;
gossip_debug ( GOSSIP_DCACHE_DEBUG , " %s: called on dentry %p. \n " ,
__func__ , dentry ) ;
/* find inode from dentry */
if ( ! dentry - > d_inode ) {
gossip_debug ( GOSSIP_DCACHE_DEBUG , " %s: negative dentry. \n " ,
__func__ ) ;
goto invalid_exit ;
}
gossip_debug ( GOSSIP_DCACHE_DEBUG , " %s: inode valid. \n " , __func__ ) ;
inode = dentry - > d_inode ;
/*
* first perform a lookup to make sure that the object not only
* exists , but is still in the expected place in the name space
*/
if ( ! is_root_handle ( inode ) ) {
2015-11-24 23:12:14 +03:00
if ( ! orangefs_revalidate_lookup ( dentry ) )
2015-07-17 17:38:12 +03:00
goto invalid_exit ;
} else {
gossip_debug ( GOSSIP_DCACHE_DEBUG ,
" %s: root handle, lookup skipped. \n " ,
__func__ ) ;
}
/* now perform getattr */
gossip_debug ( GOSSIP_DCACHE_DEBUG ,
" %s: doing getattr: inode: %p, handle: %pU \n " ,
__func__ ,
inode ,
get_khandle_from_ino ( inode ) ) ;
2015-11-24 23:12:14 +03:00
ret = orangefs_inode_getattr ( inode , ORANGEFS_ATTR_SYS_ALL_NOHINT ) ;
2015-07-17 17:38:12 +03:00
gossip_debug ( GOSSIP_DCACHE_DEBUG ,
" %s: getattr %s (ret = %d), returning %s for dentry i_count=%d \n " ,
__func__ ,
( ret = = 0 ? " succeeded " : " failed " ) ,
ret ,
( ret = = 0 ? " valid " : " INVALID " ) ,
atomic_read ( & inode - > i_count ) ) ;
if ( ret ! = 0 )
goto invalid_exit ;
/* dentry is valid! */
return 1 ;
invalid_exit :
return 0 ;
}
2015-11-24 23:12:14 +03:00
const struct dentry_operations orangefs_dentry_operations = {
. d_revalidate = orangefs_d_revalidate ,
2015-07-17 17:38:12 +03:00
} ;