2017-07-06 17:50:27 +03:00
/* Extended attribute handling for AFS. We use xattrs to get and set metadata
* instead of providing pioctl ( ) .
*
* Copyright ( C ) 2017 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation ; either version
* 2 of the Licence , or ( at your option ) any later version .
*/
# include <linux/slab.h>
# include <linux/fs.h>
# include <linux/xattr.h>
# include "internal.h"
static const char afs_xattr_list [ ] =
" afs.cell \0 "
" afs.fid \0 "
" afs.volume " ;
/*
* Retrieve a list of the supported xattrs .
*/
ssize_t afs_listxattr ( struct dentry * dentry , char * buffer , size_t size )
{
if ( size = = 0 )
return sizeof ( afs_xattr_list ) ;
if ( size < sizeof ( afs_xattr_list ) )
return - ERANGE ;
memcpy ( buffer , afs_xattr_list , sizeof ( afs_xattr_list ) ) ;
return sizeof ( afs_xattr_list ) ;
}
/*
* Get the name of the cell on which a file resides .
*/
static int afs_xattr_get_cell ( const struct xattr_handler * handler ,
struct dentry * dentry ,
struct inode * inode , const char * name ,
void * buffer , size_t size )
{
struct afs_vnode * vnode = AFS_FS_I ( inode ) ;
struct afs_cell * cell = vnode - > volume - > cell ;
size_t namelen ;
2017-11-02 18:27:50 +03:00
namelen = cell - > name_len ;
2017-07-06 17:50:27 +03:00
if ( size = = 0 )
return namelen ;
if ( namelen > size )
return - ERANGE ;
memcpy ( buffer , cell - > name , size ) ;
return namelen ;
}
static const struct xattr_handler afs_xattr_afs_cell_handler = {
. name = " afs.cell " ,
. get = afs_xattr_get_cell ,
} ;
/*
* Get the volume ID , vnode ID and vnode uniquifier of a file as a sequence of
* hex numbers separated by colons .
*/
static int afs_xattr_get_fid ( const struct xattr_handler * handler ,
struct dentry * dentry ,
struct inode * inode , const char * name ,
void * buffer , size_t size )
{
struct afs_vnode * vnode = AFS_FS_I ( inode ) ;
char text [ 8 + 1 + 8 + 1 + 8 + 1 ] ;
size_t len ;
len = sprintf ( text , " %x:%x:%x " ,
vnode - > fid . vid , vnode - > fid . vnode , vnode - > fid . unique ) ;
if ( size = = 0 )
return len ;
if ( len > size )
return - ERANGE ;
memcpy ( buffer , text , len ) ;
return len ;
}
static const struct xattr_handler afs_xattr_afs_fid_handler = {
. name = " afs.fid " ,
. get = afs_xattr_get_fid ,
} ;
/*
* Get the name of the volume on which a file resides .
*/
static int afs_xattr_get_volume ( const struct xattr_handler * handler ,
struct dentry * dentry ,
struct inode * inode , const char * name ,
void * buffer , size_t size )
{
struct afs_vnode * vnode = AFS_FS_I ( inode ) ;
const char * volname = vnode - > volume - > vlocation - > vldb . name ;
size_t namelen ;
namelen = strlen ( volname ) ;
if ( size = = 0 )
return namelen ;
if ( namelen > size )
return - ERANGE ;
memcpy ( buffer , volname , size ) ;
return namelen ;
}
static const struct xattr_handler afs_xattr_afs_volume_handler = {
. name = " afs.volume " ,
. get = afs_xattr_get_volume ,
} ;
const struct xattr_handler * afs_xattr_handlers [ ] = {
& afs_xattr_afs_cell_handler ,
& afs_xattr_afs_fid_handler ,
& afs_xattr_afs_volume_handler ,
NULL
} ;