@ -251,7 +251,8 @@ static int orangefs_inode_is_stale(struct inode *inode, int new,
return 0 ;
}
int orangefs_inode_getattr ( struct inode * inode , int new , int bypass )
int orangefs_inode_getattr ( struct inode * inode , int new , int bypass ,
u32 request_mask )
{
struct orangefs_inode_s * orangefs_inode = ORANGEFS_I ( inode ) ;
struct orangefs_kernel_op_s * new_op ;
@ -262,7 +263,13 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
get_khandle_from_ino ( inode ) ) ;
if ( ! new & & ! bypass ) {
if ( time_before ( jiffies , orangefs_inode - > getattr_time ) )
/*
* Must have all the attributes in the mask and be within cache
* time .
*/
if ( ( request_mask & orangefs_inode - > getattr_mask ) = =
request_mask & &
time_before ( jiffies , orangefs_inode - > getattr_time ) )
return 0 ;
}
@ -270,7 +277,15 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
if ( ! new_op )
return - ENOMEM ;
new_op - > upcall . req . getattr . refn = orangefs_inode - > refn ;
new_op - > upcall . req . getattr . mask = ORANGEFS_ATTR_SYS_ALL_NOHINT ;
/*
* Size is the hardest attribute to get . The incremental cost of any
* other attribute is essentially zero .
*/
if ( request_mask & STATX_SIZE | | new )
new_op - > upcall . req . getattr . mask = ORANGEFS_ATTR_SYS_ALL_NOHINT ;
else
new_op - > upcall . req . getattr . mask =
ORANGEFS_ATTR_SYS_ALL_NOHINT & ~ ORANGEFS_ATTR_SYS_SIZE ;
ret = service_operation ( new_op , __func__ ,
get_interruptible_flag ( inode ) ) ;
@ -291,25 +306,29 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
case S_IFREG :
inode - > i_flags = orangefs_inode_flags ( & new_op - >
downcall . resp . getattr . attributes ) ;
inode_size = ( loff_t ) new_op - >
downcall . resp . getattr . attributes . size ;
rounded_up_size =
( inode_size + ( 4096 - ( inode_size % 4096 ) ) ) ;
inode - > i_size = inode_size ;
orangefs_inode - > blksize =
new_op - > downcall . resp . getattr . attributes . blksize ;
spin_lock ( & inode - > i_lock ) ;
inode - > i_bytes = inode_size ;
inode - > i_blocks =
( unsigned long ) ( rounded_up_size / 512 ) ;
spin_unlock ( & inode - > i_lock ) ;
if ( request_mask & STATX_SIZE | | new ) {
inode_size = ( loff_t ) new_op - >
downcall . resp . getattr . attributes . size ;
rounded_up_size =
( inode_size + ( 4096 - ( inode_size % 4096 ) ) ) ;
inode - > i_size = inode_size ;
orangefs_inode - > blksize =
new_op - > downcall . resp . getattr . attributes . blksize ;
spin_lock ( & inode - > i_lock ) ;
inode - > i_bytes = inode_size ;
inode - > i_blocks =
( unsigned long ) ( rounded_up_size / 512 ) ;
spin_unlock ( & inode - > i_lock ) ;
}
break ;
case S_IFDIR :
inode - > i_size = PAGE_SIZE ;
orangefs_inode - > blksize = i_blocksize ( inode ) ;
spin_lock ( & inode - > i_lock ) ;
inode_set_bytes ( inode , inode - > i_size ) ;
spin_unlock ( & inode - > i_lock ) ;
if ( request_mask & STATX_SIZE | | new ) {
inode - > i_size = PAGE_SIZE ;
orangefs_inode - > blksize = i_blocksize ( inode ) ;
spin_lock ( & inode - > i_lock ) ;
inode_set_bytes ( inode , inode - > i_size ) ;
spin_unlock ( & inode - > i_lock ) ;
}
set_nlink ( inode , 1 ) ;
break ;
case S_IFLNK :
@ -349,6 +368,10 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass)
orangefs_inode - > getattr_time = jiffies +
orangefs_getattr_timeout_msecs * HZ / 1000 ;
if ( request_mask & STATX_SIZE | | new )
orangefs_inode - > getattr_mask = STATX_BASIC_STATS ;
else
orangefs_inode - > getattr_mask = STATX_BASIC_STATS & ~ STATX_SIZE ;
ret = 0 ;
out :
op_release ( new_op ) ;