2007-04-27 02:49:28 +04:00
/* AFS Volume Location Service client
2005-04-17 02:20:36 +04:00
*
* Copyright ( C ) 2002 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 License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# include <linux/init.h>
# include <linux/sched.h>
# include "internal.h"
/*
2007-04-27 02:55:03 +04:00
* map volume locator abort codes to error codes
2005-04-17 02:20:36 +04:00
*/
2007-04-27 02:55:03 +04:00
static int afs_vl_abort_to_error ( u32 abort_code )
2005-04-17 02:20:36 +04:00
{
2007-04-27 02:55:03 +04:00
_enter ( " %u " , abort_code ) ;
switch ( abort_code ) {
case AFSVL_IDEXIST : return - EEXIST ;
case AFSVL_IO : return - EREMOTEIO ;
case AFSVL_NAMEEXIST : return - EEXIST ;
case AFSVL_CREATEFAIL : return - EREMOTEIO ;
case AFSVL_NOENT : return - ENOMEDIUM ;
case AFSVL_EMPTY : return - ENOMEDIUM ;
case AFSVL_ENTDELETED : return - ENOMEDIUM ;
case AFSVL_BADNAME : return - EINVAL ;
case AFSVL_BADINDEX : return - EINVAL ;
case AFSVL_BADVOLTYPE : return - EINVAL ;
case AFSVL_BADSERVER : return - EINVAL ;
case AFSVL_BADPARTITION : return - EINVAL ;
case AFSVL_REPSFULL : return - EFBIG ;
case AFSVL_NOREPSERVER : return - ENOENT ;
case AFSVL_DUPREPSERVER : return - EEXIST ;
case AFSVL_RWNOTFOUND : return - ENOENT ;
case AFSVL_BADREFCOUNT : return - EINVAL ;
case AFSVL_SIZEEXCEEDED : return - EINVAL ;
case AFSVL_BADENTRY : return - EINVAL ;
case AFSVL_BADVOLIDBUMP : return - EINVAL ;
case AFSVL_IDALREADYHASHED : return - EINVAL ;
case AFSVL_ENTRYLOCKED : return - EBUSY ;
case AFSVL_BADVOLOPER : return - EBADRQC ;
case AFSVL_BADRELLOCKTYPE : return - EINVAL ;
case AFSVL_RERELEASE : return - EREMOTEIO ;
case AFSVL_BADSERVERFLAG : return - EINVAL ;
case AFSVL_PERM : return - EACCES ;
case AFSVL_NOMEM : return - EREMOTEIO ;
2005-04-17 02:20:36 +04:00
default :
2007-04-27 02:55:03 +04:00
return afs_abort_to_error ( abort_code ) ;
2005-04-17 02:20:36 +04:00
}
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
2007-04-27 02:55:03 +04:00
* deliver reply data to a VL . GetEntryByXXX call
2005-04-17 02:20:36 +04:00
*/
2007-04-27 02:55:03 +04:00
static int afs_deliver_vl_get_entry_by_xxx ( struct afs_call * call ,
struct sk_buff * skb , bool last )
2005-04-17 02:20:36 +04:00
{
2007-04-27 02:55:03 +04:00
struct afs_cache_vlocation * entry ;
__be32 * bp ;
u32 tmp ;
int loop ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
_enter ( " ,,%u " , last ) ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
afs_transfer_reply ( call , skb ) ;
if ( ! last )
return 0 ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
if ( call - > reply_size ! = call - > reply_max )
return - EBADMSG ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
/* unmarshall the reply once we've received all of it */
entry = call - > reply ;
bp = call - > buffer ;
2005-04-17 02:20:36 +04:00
for ( loop = 0 ; loop < 64 ; loop + + )
entry - > name [ loop ] = ntohl ( * bp + + ) ;
2007-04-27 02:55:03 +04:00
entry - > name [ loop ] = 0 ;
2005-04-17 02:20:36 +04:00
bp + + ; /* final NUL */
bp + + ; /* type */
entry - > nservers = ntohl ( * bp + + ) ;
for ( loop = 0 ; loop < 8 ; loop + + )
entry - > servers [ loop ] . s_addr = * bp + + ;
bp + = 8 ; /* partition IDs */
for ( loop = 0 ; loop < 8 ; loop + + ) {
tmp = ntohl ( * bp + + ) ;
2007-04-27 02:55:03 +04:00
entry - > srvtmask [ loop ] = 0 ;
2005-04-17 02:20:36 +04:00
if ( tmp & AFS_VLSF_RWVOL )
entry - > srvtmask [ loop ] | = AFS_VOL_VTM_RW ;
if ( tmp & AFS_VLSF_ROVOL )
entry - > srvtmask [ loop ] | = AFS_VOL_VTM_RO ;
if ( tmp & AFS_VLSF_BACKVOL )
entry - > srvtmask [ loop ] | = AFS_VOL_VTM_BAK ;
}
entry - > vid [ 0 ] = ntohl ( * bp + + ) ;
entry - > vid [ 1 ] = ntohl ( * bp + + ) ;
entry - > vid [ 2 ] = ntohl ( * bp + + ) ;
bp + + ; /* clone ID */
tmp = ntohl ( * bp + + ) ; /* flags */
2007-04-27 02:55:03 +04:00
entry - > vidmask = 0 ;
2005-04-17 02:20:36 +04:00
if ( tmp & AFS_VLF_RWEXISTS )
entry - > vidmask | = AFS_VOL_VTM_RW ;
if ( tmp & AFS_VLF_ROEXISTS )
entry - > vidmask | = AFS_VOL_VTM_RO ;
if ( tmp & AFS_VLF_BACKEXISTS )
entry - > vidmask | = AFS_VOL_VTM_BAK ;
if ( ! entry - > vidmask )
2007-04-27 02:55:03 +04:00
return - EBADMSG ;
_leave ( " = 0 [done] " ) ;
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
2007-04-27 02:55:03 +04:00
* VL . GetEntryByName operation type
2005-04-17 02:20:36 +04:00
*/
2007-04-27 02:55:03 +04:00
static const struct afs_call_type afs_RXVLGetEntryByName = {
2007-04-27 02:57:07 +04:00
. name = " VL.GetEntryByName " ,
2007-04-27 02:55:03 +04:00
. deliver = afs_deliver_vl_get_entry_by_xxx ,
. abort_to_error = afs_vl_abort_to_error ,
. destructor = afs_flat_call_destructor ,
} ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
/*
* VL . GetEntryById operation type
*/
static const struct afs_call_type afs_RXVLGetEntryById = {
2007-04-27 02:57:07 +04:00
. name = " VL.GetEntryById " ,
2007-04-27 02:55:03 +04:00
. deliver = afs_deliver_vl_get_entry_by_xxx ,
. abort_to_error = afs_vl_abort_to_error ,
. destructor = afs_flat_call_destructor ,
} ;
2005-04-17 02:20:36 +04:00
/*
2007-04-27 02:55:03 +04:00
* dispatch a get volume entry by name operation
2005-04-17 02:20:36 +04:00
*/
2007-04-27 02:55:03 +04:00
int afs_vl_get_entry_by_name ( struct in_addr * addr ,
2007-04-27 02:57:07 +04:00
struct key * key ,
2007-04-27 02:55:03 +04:00
const char * volname ,
struct afs_cache_vlocation * entry ,
const struct afs_wait_mode * wait_mode )
2005-04-17 02:20:36 +04:00
{
2007-04-27 02:55:03 +04:00
struct afs_call * call ;
size_t volnamesz , reqsz , padsz ;
__be32 * bp ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
_enter ( " " ) ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
volnamesz = strlen ( volname ) ;
padsz = ( 4 - ( volnamesz & 3 ) ) & 3 ;
reqsz = 8 + volnamesz + padsz ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
call = afs_alloc_flat_call ( & afs_RXVLGetEntryByName , reqsz , 384 ) ;
if ( ! call )
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:57:07 +04:00
call - > key = key ;
2007-04-27 02:55:03 +04:00
call - > reply = entry ;
call - > service_id = VL_SERVICE ;
call - > port = htons ( AFS_VL_PORT ) ;
2005-04-17 02:20:36 +04:00
/* marshall the parameters */
2007-04-27 02:55:03 +04:00
bp = call - > request ;
* bp + + = htonl ( VLGETENTRYBYNAME ) ;
* bp + + = htonl ( volnamesz ) ;
memcpy ( bp , volname , volnamesz ) ;
if ( padsz > 0 )
memset ( ( void * ) bp + volnamesz , 0 , padsz ) ;
/* initiate the call */
return afs_make_call ( addr , call , GFP_KERNEL , wait_mode ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
2007-04-27 02:55:03 +04:00
* dispatch a get volume entry by ID operation
2005-04-17 02:20:36 +04:00
*/
2007-04-27 02:55:03 +04:00
int afs_vl_get_entry_by_id ( struct in_addr * addr ,
2007-04-27 02:57:07 +04:00
struct key * key ,
2007-04-27 02:55:03 +04:00
afs_volid_t volid ,
afs_voltype_t voltype ,
struct afs_cache_vlocation * entry ,
const struct afs_wait_mode * wait_mode )
2005-04-17 02:20:36 +04:00
{
2007-04-27 02:55:03 +04:00
struct afs_call * call ;
2005-04-17 02:20:36 +04:00
__be32 * bp ;
2007-04-27 02:55:03 +04:00
_enter ( " " ) ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
call = afs_alloc_flat_call ( & afs_RXVLGetEntryById , 12 , 384 ) ;
if ( ! call )
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:57:07 +04:00
call - > key = key ;
2007-04-27 02:55:03 +04:00
call - > reply = entry ;
call - > service_id = VL_SERVICE ;
call - > port = htons ( AFS_VL_PORT ) ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
/* marshall the parameters */
bp = call - > request ;
* bp + + = htonl ( VLGETENTRYBYID ) ;
* bp + + = htonl ( volid ) ;
* bp = htonl ( voltype ) ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
/* initiate the call */
return afs_make_call ( addr , call , GFP_KERNEL , wait_mode ) ;
2007-04-27 02:49:28 +04:00
}