@ -49,10 +49,6 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
if ( ! ip - > i_eattr )
return NULL ;
acl = get_cached_acl ( & ip - > i_inode , type ) ;
if ( acl ! = ACL_NOT_CACHED )
return acl ;
name = gfs2_acl_name ( type ) ;
if ( name = = NULL )
return ERR_PTR ( - EINVAL ) ;
@ -80,7 +76,7 @@ static int gfs2_set_mode(struct inode *inode, umode_t mode)
return error ;
}
static int gfs2_acl_ set ( struct inode * inode , int type , struct posix_acl * acl )
int gfs2_set_acl ( struct inode * inode , struct posix_acl * acl , int type )
{
int error ;
int len ;
@ -88,219 +84,49 @@ static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
const char * name = gfs2_acl_name ( type ) ;
BUG_ON ( name = = NULL ) ;
len = posix_acl_to_xattr ( & init_user_ns , acl , NULL , 0 ) ;
if ( len = = 0 )
return 0 ;
data = kmalloc ( len , GFP_NOFS ) ;
if ( data = = NULL )
return - ENOMEM ;
error = posix_acl_to_xattr ( & init_user_ns , acl , data , len ) ;
if ( error < 0 )
goto out ;
error = __gfs2_xattr_set ( inode , name , data , len , 0 , GFS2_EATYPE_SYS ) ;
if ( ! error )
set_cached_acl ( inode , type , acl ) ;
out :
kfree ( data ) ;
return error ;
}
int gfs2_acl_create ( struct gfs2_inode * dip , struct inode * inode )
{
struct gfs2_sbd * sdp = GFS2_SB ( & dip - > i_inode ) ;
struct posix_acl * acl ;
umode_t mode = inode - > i_mode ;
int error = 0 ;
if ( ! sdp - > sd_args . ar_posix_acl )
return 0 ;
if ( S_ISLNK ( inode - > i_mode ) )
return 0 ;
acl = gfs2_get_acl ( & dip - > i_inode , ACL_TYPE_DEFAULT ) ;
if ( IS_ERR ( acl ) )
return PTR_ERR ( acl ) ;
if ( ! acl ) {
mode & = ~ current_umask ( ) ;
return gfs2_set_mode ( inode , mode ) ;
}
if ( S_ISDIR ( inode - > i_mode ) ) {
error = gfs2_acl_set ( inode , ACL_TYPE_DEFAULT , acl ) ;
if ( error )
goto out ;
}
error = __posix_acl_create ( & acl , GFP_NOFS , & mode ) ;
if ( error < 0 )
return error ;
if ( error = = 0 )
goto munge ;
error = gfs2_acl_set ( inode , ACL_TYPE_ACCESS , acl ) ;
if ( error )
goto out ;
munge :
error = gfs2_set_mode ( inode , mode ) ;
out :
posix_acl_release ( acl ) ;
return error ;
}
int gfs2_acl_chmod ( struct gfs2_inode * ip , struct iattr * attr )
{
struct inode * inode = & ip - > i_inode ;
struct posix_acl * acl ;
char * data ;
unsigned int len ;
int error ;
acl = gfs2_get_acl ( & ip - > i_inode , ACL_TYPE_ACCESS ) ;
if ( IS_ERR ( acl ) )
return PTR_ERR ( acl ) ;
if ( ! acl )
return gfs2_setattr_simple ( inode , attr ) ;
error = __posix_acl_chmod ( & acl , GFP_NOFS , attr - > ia_mode ) ;
if ( error )
return error ;
len = posix_acl_to_xattr ( & init_user_ns , acl , NULL , 0 ) ;
data = kmalloc ( len , GFP_NOFS ) ;
error = - ENOMEM ;
if ( data = = NULL )
goto out ;
posix_acl_to_xattr ( & init_user_ns , acl , data , len ) ;
error = gfs2_xattr_acl_chmod ( ip , attr , data ) ;
kfree ( data ) ;
set_cached_acl ( & ip - > i_inode , ACL_TYPE_ACCESS , acl ) ;
out :
posix_acl_release ( acl ) ;
return error ;
}
static int gfs2_acl_type ( const char * name )
{
if ( strcmp ( name , GFS2_POSIX_ACL_ACCESS ) = = 0 )
return ACL_TYPE_ACCESS ;
if ( strcmp ( name , GFS2_POSIX_ACL_DEFAULT ) = = 0 )
return ACL_TYPE_DEFAULT ;
return - EINVAL ;
}
static int gfs2_xattr_system_get ( struct dentry * dentry , const char * name ,
void * buffer , size_t size , int xtype )
{
struct inode * inode = dentry - > d_inode ;
struct gfs2_sbd * sdp = GFS2_SB ( inode ) ;
struct posix_acl * acl ;
int type ;
int error ;
if ( ! sdp - > sd_args . ar_posix_acl )
return - EOPNOTSUPP ;
type = gfs2_acl_type ( name ) ;
if ( type < 0 )
return type ;
acl = gfs2_get_acl ( inode , type ) ;
if ( IS_ERR ( acl ) )
return PTR_ERR ( acl ) ;
if ( acl = = NULL )
return - ENODATA ;
error = posix_acl_to_xattr ( & init_user_ns , acl , buffer , size ) ;
posix_acl_release ( acl ) ;
return error ;
}
static int gfs2_xattr_system_set ( struct dentry * dentry , const char * name ,
const void * value , size_t size , int flags ,
int xtype )
{
struct inode * inode = dentry - > d_inode ;
struct gfs2_sbd * sdp = GFS2_SB ( inode ) ;
struct posix_acl * acl = NULL ;
int error = 0 , type ;
if ( ! sdp - > sd_args . ar_posix_acl )
return - EOPNOTSUPP ;
type = gfs2_acl_type ( name ) ;
if ( type < 0 )
return type ;
if ( flags & XATTR_CREATE )
return - EINVAL ;
if ( type = = ACL_TYPE_DEFAULT & & ! S_ISDIR ( inode - > i_mode ) )
return value ? - EACCES : 0 ;
if ( ! uid_eq ( current_fsuid ( ) , inode - > i_uid ) & & ! capable ( CAP_FOWNER ) )
return - EPERM ;
if ( S_ISLNK ( inode - > i_mode ) )
return - EOPNOTSUPP ;
if ( ! value )
goto set_acl ;
acl = posix_acl_from_xattr ( & init_user_ns , value , size ) ;
if ( ! acl ) {
/*
* acl_set_file ( 3 ) may request that we set default ACLs with
* zero length - - defend ( gracefully ) against that here .
*/
goto out ;
}
if ( IS_ERR ( acl ) ) {
error = PTR_ERR ( acl ) ;
goto out ;
}
error = posix_acl_valid ( acl ) ;
if ( error )
goto out_release ;
error = - EINVAL ;
if ( acl - > a_count > GFS2_ACL_MAX_ENTRIES )
goto out_release ;
return - EINVAL ;
if ( type = = ACL_TYPE_ACCESS ) {
umode_t mode = inode - > i_mode ;
error = posix_acl_equiv_mode ( acl , & mode ) ;
if ( error < 0 )
return error ;
if ( error < = 0 ) {
posix_acl_release ( acl ) ;
if ( error = = 0 )
acl = NULL ;
if ( error < 0 )
return error ;
}
error = gfs2_set_mode ( inode , mode ) ;
if ( error )
goto out_release ;
return error ;
}
set_acl :
error = __gfs2_xattr_set ( inode , name , value , size , 0 , GFS2_EATYPE_SYS ) ;
if ( ! error ) {
if ( acl )
set_cached_acl ( inode , type , acl ) ;
else
forget_cached_acl ( inode , type ) ;
if ( acl ) {
len = posix_acl_to_xattr ( & init_user_ns , acl , NULL , 0 ) ;
if ( len = = 0 )
return 0 ;
data = kmalloc ( len , GFP_NOFS ) ;
if ( data = = NULL )
return - ENOMEM ;
error = posix_acl_to_xattr ( & init_user_ns , acl , data , len ) ;
if ( error < 0 )
goto out ;
} else {
data = NULL ;
len = 0 ;
}
out_release :
posix_acl_release ( acl ) ;
error = __gfs2_xattr_set ( inode , name , data , len , 0 , GFS2_EATYPE_SYS ) ;
if ( error )
goto out ;
if ( acl )
set_cached_acl ( inode , type , acl ) ;
else
forget_cached_acl ( inode , type ) ;
out :
kfree ( data ) ;
return error ;
}
const struct xattr_handler gfs2_xattr_system_handler = {
. prefix = XATTR_SYSTEM_PREFIX ,
. flags = GFS2_EATYPE_SYS ,
. get = gfs2_xattr_system_get ,
. set = gfs2_xattr_system_set ,
} ;