2021-11-02 16:12:01 +03:00
// SPDX-License-Identifier: LGPL-2.1
2010-05-31 11:52:56 +04:00
/*
* Copyright IBM Corporation , 2010
* Author Aneesh Kumar K . V < aneesh . kumar @ linux . vnet . ibm . com >
*/
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/sched.h>
2015-04-02 03:17:51 +03:00
# include <linux/uio.h>
2010-05-31 11:52:56 +04:00
# include <net/9p/9p.h>
# include <net/9p/client.h>
# include "fid.h"
# include "xattr.h"
2010-09-27 22:57:39 +04:00
ssize_t v9fs_fid_xattr_get ( struct p9_fid * fid , const char * name ,
void * buffer , size_t buffer_size )
2010-05-31 11:52:56 +04:00
{
ssize_t retval ;
2015-04-02 06:42:28 +03:00
u64 attr_size ;
2010-09-27 22:57:39 +04:00
struct p9_fid * attr_fid ;
2015-04-02 06:42:28 +03:00
struct kvec kvec = { . iov_base = buffer , . iov_len = buffer_size } ;
struct iov_iter to ;
int err ;
2022-09-16 03:25:47 +03:00
iov_iter_kvec ( & to , ITER_DEST , & kvec , 1 , buffer_size ) ;
2010-05-31 11:52:56 +04:00
attr_fid = p9_client_xattrwalk ( fid , name , & attr_size ) ;
if ( IS_ERR ( attr_fid ) ) {
retval = PTR_ERR ( attr_fid ) ;
2011-11-28 22:40:46 +04:00
p9_debug ( P9_DEBUG_VFS , " p9_client_attrwalk failed %zd \n " ,
retval ) ;
2015-04-02 06:42:28 +03:00
return retval ;
2010-05-31 11:52:56 +04:00
}
if ( attr_size > buffer_size ) {
2015-04-02 06:42:28 +03:00
if ( ! buffer_size ) /* request to get the attr_size */
retval = attr_size ;
2010-05-31 11:52:56 +04:00
else
2015-04-02 06:42:28 +03:00
retval = - ERANGE ;
} else {
iov_iter_truncate ( & to , attr_size ) ;
retval = p9_client_read ( attr_fid , 0 , & to , & err ) ;
if ( err )
retval = err ;
2010-05-31 11:52:56 +04:00
}
2022-06-12 07:42:32 +03:00
p9_fid_put ( attr_fid ) ;
2010-05-31 11:52:56 +04:00
return retval ;
}
2010-09-27 22:57:39 +04:00
/*
* v9fs_xattr_get ( )
*
* Copy an extended attribute into the buffer
* provided , or compute the buffer size required .
* Buffer is NULL to compute the size of the buffer required .
*
* Returns a negative error number on failure , or the number of bytes
* used / required on success .
*/
ssize_t v9fs_xattr_get ( struct dentry * dentry , const char * name ,
void * buffer , size_t buffer_size )
{
struct p9_fid * fid ;
2020-09-23 17:11:46 +03:00
int ret ;
2010-09-27 22:57:39 +04:00
2011-11-28 22:40:46 +04:00
p9_debug ( P9_DEBUG_VFS , " name = %s value_len = %zu \n " ,
name , buffer_size ) ;
2010-09-27 22:57:39 +04:00
fid = v9fs_fid_lookup ( dentry ) ;
if ( IS_ERR ( fid ) )
return PTR_ERR ( fid ) ;
2020-09-23 17:11:46 +03:00
ret = v9fs_fid_xattr_get ( fid , name , buffer , buffer_size ) ;
2022-06-12 07:42:32 +03:00
p9_fid_put ( fid ) ;
2010-09-27 22:57:39 +04:00
2020-09-23 17:11:46 +03:00
return ret ;
2010-09-27 22:57:39 +04:00
}
2010-05-31 11:52:56 +04:00
/*
* v9fs_xattr_set ( )
*
* Create , replace or remove an extended attribute for this inode . Buffer
* is NULL to remove an existing extended attribute , and non - NULL to
* either replace an existing extended attribute , or create a new extended
* attribute . The flags XATTR_REPLACE and XATTR_CREATE
* specify that an extended attribute must exist and must not exist
* previous to the call , respectively .
*
* Returns 0 , or a negative error number on failure .
*/
int v9fs_xattr_set ( struct dentry * dentry , const char * name ,
const void * value , size_t value_len , int flags )
2013-01-31 21:34:58 +04:00
{
2020-09-23 17:11:46 +03:00
int ret ;
struct p9_fid * fid ;
fid = v9fs_fid_lookup ( dentry ) ;
if ( IS_ERR ( fid ) )
return PTR_ERR ( fid ) ;
ret = v9fs_fid_xattr_set ( fid , name , value , value_len , flags ) ;
2022-06-12 07:42:32 +03:00
p9_fid_put ( fid ) ;
2020-09-23 17:11:46 +03:00
return ret ;
2013-01-31 21:34:58 +04:00
}
int v9fs_fid_xattr_set ( struct p9_fid * fid , const char * name ,
const void * value , size_t value_len , int flags )
2010-05-31 11:52:56 +04:00
{
2015-04-02 03:17:51 +03:00
struct kvec kvec = { . iov_base = ( void * ) value , . iov_len = value_len } ;
struct iov_iter from ;
2018-07-25 06:13:16 +03:00
int retval , err ;
2015-04-02 03:17:51 +03:00
2022-09-16 03:25:47 +03:00
iov_iter_kvec ( & from , ITER_SOURCE , & kvec , 1 , value_len ) ;
2010-05-31 11:52:56 +04:00
2011-11-28 22:40:46 +04:00
p9_debug ( P9_DEBUG_VFS , " name = %s value_len = %zu flags = %d \n " ,
name , value_len , flags ) ;
2010-05-31 11:52:56 +04:00
2013-01-31 21:34:58 +04:00
/* Clone it */
2016-08-03 18:12:12 +03:00
fid = clone_fid ( fid ) ;
2013-01-31 21:34:58 +04:00
if ( IS_ERR ( fid ) )
return PTR_ERR ( fid ) ;
2010-05-31 11:52:56 +04:00
/*
* On success fid points to xattr
*/
retval = p9_client_xattrcreate ( fid , name , value_len , flags ) ;
2015-04-02 03:17:51 +03:00
if ( retval < 0 )
2011-11-28 22:40:46 +04:00
p9_debug ( P9_DEBUG_VFS , " p9_client_xattrcreate failed %d \n " ,
retval ) ;
2015-04-02 03:17:51 +03:00
else
p9_client_write ( fid , 0 , & from , & retval ) ;
2022-06-12 07:42:32 +03:00
err = p9_fid_put ( fid ) ;
2018-07-25 06:13:16 +03:00
if ( ! retval & & err )
retval = err ;
2013-10-21 23:47:58 +04:00
return retval ;
2010-05-31 11:52:56 +04:00
}
ssize_t v9fs_listxattr ( struct dentry * dentry , char * buffer , size_t buffer_size )
{
return v9fs_xattr_get ( dentry , NULL , buffer , buffer_size ) ;
}
2015-10-04 20:18:52 +03:00
static int v9fs_xattr_handler_get ( const struct xattr_handler * handler ,
2016-04-11 03:48:24 +03:00
struct dentry * dentry , struct inode * inode ,
const char * name , void * buffer , size_t size )
2015-10-04 20:18:52 +03:00
{
const char * full_name = xattr_full_name ( handler , name ) ;
return v9fs_xattr_get ( dentry , full_name , buffer , size ) ;
}
static int v9fs_xattr_handler_set ( const struct xattr_handler * handler ,
2021-01-21 16:19:27 +03:00
struct user_namespace * mnt_userns ,
2016-05-27 17:19:30 +03:00
struct dentry * dentry , struct inode * inode ,
const char * name , const void * value ,
size_t size , int flags )
2015-10-04 20:18:52 +03:00
{
const char * full_name = xattr_full_name ( handler , name ) ;
return v9fs_xattr_set ( dentry , full_name , value , size , flags ) ;
}
static struct xattr_handler v9fs_xattr_user_handler = {
. prefix = XATTR_USER_PREFIX ,
. get = v9fs_xattr_handler_get ,
. set = v9fs_xattr_handler_set ,
} ;
static struct xattr_handler v9fs_xattr_trusted_handler = {
. prefix = XATTR_TRUSTED_PREFIX ,
. get = v9fs_xattr_handler_get ,
. set = v9fs_xattr_handler_set ,
} ;
# ifdef CONFIG_9P_FS_SECURITY
static struct xattr_handler v9fs_xattr_security_handler = {
. prefix = XATTR_SECURITY_PREFIX ,
. get = v9fs_xattr_handler_get ,
. set = v9fs_xattr_handler_set ,
} ;
# endif
2010-05-31 11:52:56 +04:00
const struct xattr_handler * v9fs_xattr_handlers [ ] = {
& v9fs_xattr_user_handler ,
2013-05-29 23:09:39 +04:00
& v9fs_xattr_trusted_handler ,
2010-09-27 22:57:39 +04:00
# ifdef CONFIG_9P_FS_POSIX_ACL
& v9fs_xattr_acl_access_handler ,
& v9fs_xattr_acl_default_handler ,
2013-05-29 23:09:39 +04:00
# endif
# ifdef CONFIG_9P_FS_SECURITY
& v9fs_xattr_security_handler ,
2010-09-27 22:57:39 +04:00
# endif
2010-05-31 11:52:56 +04:00
NULL
} ;