@ -113,6 +113,69 @@ int nfs3_removexattr(struct dentry *dentry, const char *name)
return nfs3_proc_setacl ( inode , type , NULL ) ;
}
static void __nfs3_forget_cached_acls ( struct nfs_inode * nfsi )
{
if ( nfsi - > acl_access ! = ERR_PTR ( - EAGAIN ) ) {
posix_acl_release ( nfsi - > acl_access ) ;
nfsi - > acl_access = ERR_PTR ( - EAGAIN ) ;
}
if ( nfsi - > acl_default ! = ERR_PTR ( - EAGAIN ) ) {
posix_acl_release ( nfsi - > acl_default ) ;
nfsi - > acl_default = ERR_PTR ( - EAGAIN ) ;
}
}
void nfs3_forget_cached_acls ( struct inode * inode )
{
dprintk ( " NFS: nfs3_forget_cached_acls(%s/%ld) \n " , inode - > i_sb - > s_id ,
inode - > i_ino ) ;
spin_lock ( & inode - > i_lock ) ;
__nfs3_forget_cached_acls ( NFS_I ( inode ) ) ;
spin_unlock ( & inode - > i_lock ) ;
}
static struct posix_acl * nfs3_get_cached_acl ( struct inode * inode , int type )
{
struct nfs_inode * nfsi = NFS_I ( inode ) ;
struct posix_acl * acl = ERR_PTR ( - EAGAIN ) ;
spin_lock ( & inode - > i_lock ) ;
switch ( type ) {
case ACL_TYPE_ACCESS :
acl = nfsi - > acl_access ;
break ;
case ACL_TYPE_DEFAULT :
acl = nfsi - > acl_default ;
break ;
default :
return ERR_PTR ( - EINVAL ) ;
}
if ( acl = = ERR_PTR ( - EAGAIN ) )
acl = ERR_PTR ( - EAGAIN ) ;
else
acl = posix_acl_dup ( acl ) ;
spin_unlock ( & inode - > i_lock ) ;
dprintk ( " NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p \n " , inode - > i_sb - > s_id ,
inode - > i_ino , type , acl ) ;
return acl ;
}
static void nfs3_cache_acls ( struct inode * inode , struct posix_acl * acl ,
struct posix_acl * dfacl )
{
struct nfs_inode * nfsi = NFS_I ( inode ) ;
dprintk ( " nfs3_cache_acls(%s/%ld, %p, %p) \n " , inode - > i_sb - > s_id ,
inode - > i_ino , acl , dfacl ) ;
spin_lock ( & inode - > i_lock ) ;
__nfs3_forget_cached_acls ( NFS_I ( inode ) ) ;
nfsi - > acl_access = posix_acl_dup ( acl ) ;
nfsi - > acl_default = posix_acl_dup ( dfacl ) ;
spin_unlock ( & inode - > i_lock ) ;
}
struct posix_acl * nfs3_proc_getacl ( struct inode * inode , int type )
{
struct nfs_server * server = NFS_SERVER ( inode ) ;
@ -126,26 +189,32 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
struct nfs3_getaclres res = {
. fattr = & fattr ,
} ;
struct posix_acl * acl = NULL ;
struct posix_acl * acl ;
int status , count ;
if ( ! nfs_server_capable ( inode , NFS_CAP_ACLS ) )
return ERR_PTR ( - EOPNOTSUPP ) ;
switch ( type ) {
case ACL_TYPE_ACCESS :
args . mask = NFS_ACLCNT | NFS_ACL ;
break ;
case ACL_TYPE_DEFAULT :
if ( ! S_ISDIR ( inode - > i_mode ) )
return NULL ;
args . mask = NFS_DFACLCNT | NFS_DFACL ;
break ;
default :
return ERR_PTR ( - EINVAL ) ;
}
status = nfs_revalidate_inode ( server , inode ) ;
if ( status < 0 )
return ERR_PTR ( status ) ;
acl = nfs3_get_cached_acl ( inode , type ) ;
if ( acl ! = ERR_PTR ( - EAGAIN ) )
return acl ;
acl = NULL ;
/*
* Only get the access acl when explicitly requested : We don ' t
* need it for access decisions , and only some applications use
* it . Applications which request the access acl first are not
* penalized from this optimization .
*/
if ( type = = ACL_TYPE_ACCESS )
args . mask | = NFS_ACLCNT | NFS_ACL ;
if ( S_ISDIR ( inode - > i_mode ) )
args . mask | = NFS_DFACLCNT | NFS_DFACL ;
if ( args . mask = = 0 )
return NULL ;
dprintk ( " NFS call getacl \n " ) ;
status = rpc_call ( server - > client_acl , ACLPROC3_GETACL ,
@ -180,6 +249,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
res . acl_access = NULL ;
}
}
nfs3_cache_acls ( inode , res . acl_access , res . acl_default ) ;
switch ( type ) {
case ACL_TYPE_ACCESS :