2005-09-09 13:04:21 -07:00
/*
2007-07-10 17:57:28 -05:00
* net / 9 p / conv . c
2005-09-09 13:04:21 -07:00
*
* 9 P protocol conversion functions
*
2005-09-22 21:43:48 -07:00
* Copyright ( C ) 2004 , 2005 by Latchesar Ionkov < lucho @ ionkov . net >
2005-09-09 13:04:21 -07:00
* Copyright ( C ) 2004 by Eric Van Hensbergen < ericvh @ gmail . com >
* Copyright ( C ) 2002 by Ron Minnich < rminnich @ lanl . gov >
*
* This program is free software ; you can redistribute it and / or modify
2006-03-25 03:07:28 -08:00
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation .
2005-09-09 13:04:21 -07:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to :
* Free Software Foundation
* 51 Franklin Street , Fifth Floor
* Boston , MA 02111 - 1301 USA
*
*/
# include <linux/module.h>
# include <linux/errno.h>
# include <linux/fs.h>
2006-10-18 13:55:46 -04:00
# include <linux/sched.h>
2005-09-09 13:04:21 -07:00
# include <linux/idr.h>
2007-07-10 17:57:28 -05:00
# include <linux/uaccess.h>
# include <net/9p/9p.h>
2005-09-09 13:04:21 -07:00
/*
* Buffer to help with string parsing
*/
struct cbuf {
unsigned char * sp ;
unsigned char * p ;
unsigned char * ep ;
} ;
static inline void buf_init ( struct cbuf * buf , void * data , int datalen )
{
buf - > sp = buf - > p = data ;
buf - > ep = data + datalen ;
}
static inline int buf_check_overflow ( struct cbuf * buf )
{
return buf - > p > buf - > ep ;
}
2006-01-14 13:20:43 -08:00
static int buf_check_size ( struct cbuf * buf , int len )
2005-09-09 13:04:21 -07:00
{
2006-01-08 01:05:02 -08:00
if ( buf - > p + len > buf - > ep ) {
if ( buf - > p < buf - > ep ) {
2007-07-10 17:57:28 -05:00
P9_EPRINTK ( KERN_ERR ,
" buffer overflow: want %d has %d \n " , len ,
( int ) ( buf - > ep - buf - > p ) ) ;
2006-01-08 01:05:02 -08:00
dump_stack ( ) ;
buf - > p = buf - > ep + 1 ;
}
2006-01-08 01:05:00 -08:00
return 0 ;
2005-09-09 13:04:21 -07:00
}
2005-09-22 21:43:48 -07:00
return 1 ;
2005-09-09 13:04:21 -07:00
}
2006-01-14 13:20:43 -08:00
static void * buf_alloc ( struct cbuf * buf , int len )
2005-09-09 13:04:21 -07:00
{
void * ret = NULL ;
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , len ) ) {
ret = buf - > p ;
buf - > p + = len ;
}
2005-09-09 13:04:21 -07:00
return ret ;
}
2006-01-14 13:20:43 -08:00
static void buf_put_int8 ( struct cbuf * buf , u8 val )
2005-09-09 13:04:21 -07:00
{
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 1 ) ) {
buf - > p [ 0 ] = val ;
buf - > p + + ;
}
2005-09-09 13:04:21 -07:00
}
2006-01-14 13:20:43 -08:00
static void buf_put_int16 ( struct cbuf * buf , u16 val )
2005-09-09 13:04:21 -07:00
{
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 2 ) ) {
* ( __le16 * ) buf - > p = cpu_to_le16 ( val ) ;
buf - > p + = 2 ;
}
2005-09-09 13:04:21 -07:00
}
2006-01-14 13:20:43 -08:00
static void buf_put_int32 ( struct cbuf * buf , u32 val )
2005-09-09 13:04:21 -07:00
{
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 4 ) ) {
* ( __le32 * ) buf - > p = cpu_to_le32 ( val ) ;
buf - > p + = 4 ;
}
2005-09-09 13:04:21 -07:00
}
2006-01-14 13:20:43 -08:00
static void buf_put_int64 ( struct cbuf * buf , u64 val )
2005-09-09 13:04:21 -07:00
{
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 8 ) ) {
* ( __le64 * ) buf - > p = cpu_to_le64 ( val ) ;
buf - > p + = 8 ;
}
2005-09-09 13:04:21 -07:00
}
2006-02-03 03:04:18 -08:00
static char * buf_put_stringn ( struct cbuf * buf , const char * s , u16 slen )
2005-09-09 13:04:21 -07:00
{
2006-02-03 03:04:18 -08:00
char * ret ;
ret = NULL ;
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , slen + 2 ) ) {
buf_put_int16 ( buf , slen ) ;
2006-02-03 03:04:18 -08:00
ret = buf - > p ;
2005-09-22 21:43:48 -07:00
memcpy ( buf - > p , s , slen ) ;
buf - > p + = slen ;
}
2006-02-03 03:04:18 -08:00
return ret ;
2005-09-09 13:04:21 -07:00
}
2006-01-14 13:20:43 -08:00
static u8 buf_get_int8 ( struct cbuf * buf )
2005-09-09 13:04:21 -07:00
{
u8 ret = 0 ;
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 1 ) ) {
ret = buf - > p [ 0 ] ;
buf - > p + + ;
}
2005-09-09 13:04:21 -07:00
return ret ;
}
2006-01-14 13:20:43 -08:00
static u16 buf_get_int16 ( struct cbuf * buf )
2005-09-09 13:04:21 -07:00
{
u16 ret = 0 ;
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 2 ) ) {
ret = le16_to_cpu ( * ( __le16 * ) buf - > p ) ;
buf - > p + = 2 ;
}
2005-09-09 13:04:21 -07:00
return ret ;
}
2006-01-14 13:20:43 -08:00
static u32 buf_get_int32 ( struct cbuf * buf )
2005-09-09 13:04:21 -07:00
{
u32 ret = 0 ;
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 4 ) ) {
ret = le32_to_cpu ( * ( __le32 * ) buf - > p ) ;
buf - > p + = 4 ;
}
2005-09-09 13:04:21 -07:00
return ret ;
}
2006-01-14 13:20:43 -08:00
static u64 buf_get_int64 ( struct cbuf * buf )
2005-09-09 13:04:21 -07:00
{
u64 ret = 0 ;
2005-09-22 21:43:48 -07:00
if ( buf_check_size ( buf , 8 ) ) {
ret = le64_to_cpu ( * ( __le64 * ) buf - > p ) ;
buf - > p + = 8 ;
}
2005-09-09 13:04:21 -07:00
return ret ;
}
2007-07-10 17:57:28 -05:00
static void buf_get_str ( struct cbuf * buf , struct p9_str * vstr )
2005-09-09 13:04:21 -07:00
{
2006-01-08 01:05:00 -08:00
vstr - > len = buf_get_int16 ( buf ) ;
if ( ! buf_check_overflow ( buf ) & & buf_check_size ( buf , vstr - > len ) ) {
vstr - > str = buf - > p ;
buf - > p + = vstr - > len ;
} else {
vstr - > len = 0 ;
vstr - > str = NULL ;
2005-09-22 21:43:48 -07:00
}
2005-09-09 13:04:21 -07:00
}
2007-07-10 17:57:28 -05:00
static void buf_get_qid ( struct cbuf * bufp , struct p9_qid * qid )
2005-09-09 13:04:21 -07:00
{
2006-01-08 01:05:00 -08:00
qid - > type = buf_get_int8 ( bufp ) ;
qid - > version = buf_get_int32 ( bufp ) ;
qid - > path = buf_get_int64 ( bufp ) ;
2005-09-09 13:04:21 -07:00
}
/**
2007-07-10 17:57:28 -05:00
* p9_size_wstat - calculate the size of a variable length stat struct
2008-03-05 07:08:09 -06:00
* @ wstat : metadata ( stat ) structure
2007-07-10 17:57:28 -05:00
* @ dotu : non - zero if 9 P2000 . u
2005-09-09 13:04:21 -07:00
*
*/
2007-07-10 17:57:28 -05:00
static int p9_size_wstat ( struct p9_wstat * wstat , int dotu )
2005-09-09 13:04:21 -07:00
{
int size = 0 ;
2006-01-08 01:05:00 -08:00
if ( wstat = = NULL ) {
2007-07-10 17:57:28 -05:00
P9_EPRINTK ( KERN_ERR , " p9_size_stat: got a NULL stat pointer \n " ) ;
2005-09-09 13:04:21 -07:00
return 0 ;
}
size = /* 2 + */ /* size[2] */
2 + /* type[2] */
4 + /* dev[4] */
1 + /* qid.type[1] */
4 + /* qid.vers[4] */
8 + /* qid.path[8] */
4 + /* mode[4] */
4 + /* atime[4] */
4 + /* mtime[4] */
8 + /* length[8] */
8 ; /* minimum sum of string lengths */
2006-01-08 01:05:00 -08:00
if ( wstat - > name )
size + = strlen ( wstat - > name ) ;
if ( wstat - > uid )
size + = strlen ( wstat - > uid ) ;
if ( wstat - > gid )
size + = strlen ( wstat - > gid ) ;
if ( wstat - > muid )
size + = strlen ( wstat - > muid ) ;
2005-09-09 13:04:21 -07:00
2007-07-10 17:57:28 -05:00
if ( dotu ) {
2005-09-09 13:04:21 -07:00
size + = 4 + /* n_uid[4] */
4 + /* n_gid[4] */
4 + /* n_muid[4] */
2 ; /* string length of extension[4] */
2006-01-08 01:05:00 -08:00
if ( wstat - > extension )
size + = strlen ( wstat - > extension ) ;
2005-09-09 13:04:21 -07:00
}
return size ;
}
/**
2006-01-08 01:05:00 -08:00
* buf_get_stat - safely decode a recieved metadata ( stat ) structure
2005-09-09 13:04:21 -07:00
* @ bufp : buffer to deserialize
* @ stat : metadata ( stat ) structure
2007-07-10 17:57:28 -05:00
* @ dotu : non - zero if 9 P2000 . u
2005-09-09 13:04:21 -07:00
*
*/
2006-01-14 13:20:43 -08:00
static void
2007-07-10 17:57:28 -05:00
buf_get_stat ( struct cbuf * bufp , struct p9_stat * stat , int dotu )
2005-09-09 13:04:21 -07:00
{
stat - > size = buf_get_int16 ( bufp ) ;
stat - > type = buf_get_int16 ( bufp ) ;
stat - > dev = buf_get_int32 ( bufp ) ;
stat - > qid . type = buf_get_int8 ( bufp ) ;
stat - > qid . version = buf_get_int32 ( bufp ) ;
stat - > qid . path = buf_get_int64 ( bufp ) ;
stat - > mode = buf_get_int32 ( bufp ) ;
stat - > atime = buf_get_int32 ( bufp ) ;
stat - > mtime = buf_get_int32 ( bufp ) ;
stat - > length = buf_get_int64 ( bufp ) ;
2006-01-08 01:05:00 -08:00
buf_get_str ( bufp , & stat - > name ) ;
buf_get_str ( bufp , & stat - > uid ) ;
buf_get_str ( bufp , & stat - > gid ) ;
buf_get_str ( bufp , & stat - > muid ) ;
2005-09-09 13:04:21 -07:00
2007-07-10 17:57:28 -05:00
if ( dotu ) {
2006-01-08 01:05:00 -08:00
buf_get_str ( bufp , & stat - > extension ) ;
2005-09-09 13:04:21 -07:00
stat - > n_uid = buf_get_int32 ( bufp ) ;
stat - > n_gid = buf_get_int32 ( bufp ) ;
stat - > n_muid = buf_get_int32 ( bufp ) ;
}
}
/**
2007-07-10 17:57:28 -05:00
* p9_deserialize_stat - decode a received metadata structure
2005-09-09 13:04:21 -07:00
* @ buf : buffer to deserialize
* @ buflen : length of received buffer
* @ stat : metadata structure to decode into
2007-07-10 17:57:28 -05:00
* @ dotu : non - zero if 9 P2000 . u
2005-09-09 13:04:21 -07:00
*
2006-01-08 01:05:00 -08:00
* Note : stat will point to the buf region .
2005-09-09 13:04:21 -07:00
*/
2006-01-08 01:05:00 -08:00
int
2007-07-10 17:57:28 -05:00
p9_deserialize_stat ( void * buf , u32 buflen , struct p9_stat * stat ,
int dotu )
2005-09-09 13:04:21 -07:00
{
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
2006-01-08 01:05:00 -08:00
unsigned char * p ;
2005-09-09 13:04:21 -07:00
buf_init ( bufp , buf , buflen ) ;
2006-01-08 01:05:00 -08:00
p = bufp - > p ;
2007-07-10 17:57:28 -05:00
buf_get_stat ( bufp , stat , dotu ) ;
2005-09-09 13:04:21 -07:00
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) )
2005-09-09 13:04:21 -07:00
return 0 ;
2006-01-08 01:05:00 -08:00
else
return bufp - > p - p ;
2005-09-09 13:04:21 -07:00
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_deserialize_stat ) ;
2005-09-09 13:04:21 -07:00
/**
* deserialize_fcall - unmarshal a response
* @ buf : recieved buffer
* @ buflen : length of received buffer
* @ rcall : fcall structure to populate
* @ rcalllen : length of fcall structure to populate
2007-07-10 17:57:28 -05:00
* @ dotu : non - zero if 9 P2000 . u
2005-09-09 13:04:21 -07:00
*
*/
int
2007-07-10 17:57:28 -05:00
p9_deserialize_fcall ( void * buf , u32 buflen , struct p9_fcall * rcall ,
int dotu )
2005-09-09 13:04:21 -07:00
{
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
int i = 0 ;
buf_init ( bufp , buf , buflen ) ;
2006-01-08 01:04:58 -08:00
rcall - > size = buf_get_int32 ( bufp ) ;
2005-09-09 13:04:21 -07:00
rcall - > id = buf_get_int8 ( bufp ) ;
rcall - > tag = buf_get_int16 ( bufp ) ;
2007-07-10 17:57:28 -05:00
P9_DPRINTK ( P9_DEBUG_CONV , " size %d id %d tag %d \n " , rcall - > size ,
rcall - > id , rcall - > tag ) ;
2006-01-08 01:05:00 -08:00
2005-09-09 13:04:21 -07:00
switch ( rcall - > id ) {
default :
2007-07-10 17:57:28 -05:00
P9_EPRINTK ( KERN_ERR , " unknown message type: %d \n " , rcall - > id ) ;
2005-09-09 13:04:21 -07:00
return - EPROTO ;
2007-07-10 17:57:28 -05:00
case P9_RVERSION :
2005-09-09 13:04:21 -07:00
rcall - > params . rversion . msize = buf_get_int32 ( bufp ) ;
2006-01-08 01:05:00 -08:00
buf_get_str ( bufp , & rcall - > params . rversion . version ) ;
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_RFLUSH :
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_RATTACH :
2005-09-09 13:04:21 -07:00
rcall - > params . rattach . qid . type = buf_get_int8 ( bufp ) ;
rcall - > params . rattach . qid . version = buf_get_int32 ( bufp ) ;
rcall - > params . rattach . qid . path = buf_get_int64 ( bufp ) ;
break ;
2007-07-10 17:57:28 -05:00
case P9_RWALK :
2005-09-09 13:04:21 -07:00
rcall - > params . rwalk . nwqid = buf_get_int16 ( bufp ) ;
2007-07-10 17:57:28 -05:00
if ( rcall - > params . rwalk . nwqid > P9_MAXWELEM ) {
P9_EPRINTK ( KERN_ERR ,
" Rwalk with more than %d qids: %d \n " ,
P9_MAXWELEM , rcall - > params . rwalk . nwqid ) ;
2006-01-08 01:04:58 -08:00
return - EPROTO ;
}
2006-01-08 01:05:00 -08:00
for ( i = 0 ; i < rcall - > params . rwalk . nwqid ; i + + )
buf_get_qid ( bufp , & rcall - > params . rwalk . wqids [ i ] ) ;
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_ROPEN :
2006-01-08 01:05:00 -08:00
buf_get_qid ( bufp , & rcall - > params . ropen . qid ) ;
2005-09-09 13:04:21 -07:00
rcall - > params . ropen . iounit = buf_get_int32 ( bufp ) ;
break ;
2007-07-10 17:57:28 -05:00
case P9_RCREATE :
2006-01-08 01:05:00 -08:00
buf_get_qid ( bufp , & rcall - > params . rcreate . qid ) ;
2005-09-09 13:04:21 -07:00
rcall - > params . rcreate . iounit = buf_get_int32 ( bufp ) ;
break ;
2007-07-10 17:57:28 -05:00
case P9_RREAD :
2005-09-09 13:04:21 -07:00
rcall - > params . rread . count = buf_get_int32 ( bufp ) ;
2006-01-08 01:05:00 -08:00
rcall - > params . rread . data = bufp - > p ;
buf_check_size ( bufp , rcall - > params . rread . count ) ;
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_RWRITE :
2005-09-09 13:04:21 -07:00
rcall - > params . rwrite . count = buf_get_int32 ( bufp ) ;
break ;
2007-07-10 17:57:28 -05:00
case P9_RCLUNK :
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_RREMOVE :
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_RSTAT :
2005-09-09 13:04:21 -07:00
buf_get_int16 ( bufp ) ;
2007-07-10 17:57:28 -05:00
buf_get_stat ( bufp , & rcall - > params . rstat . stat , dotu ) ;
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_RWSTAT :
2005-09-09 13:04:21 -07:00
break ;
2007-07-10 17:57:28 -05:00
case P9_RERROR :
2006-01-08 01:05:00 -08:00
buf_get_str ( bufp , & rcall - > params . rerror . error ) ;
2007-07-10 17:57:28 -05:00
if ( dotu )
2005-09-09 13:04:21 -07:00
rcall - > params . rerror . errno = buf_get_int16 ( bufp ) ;
break ;
}
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
2007-07-10 17:57:28 -05:00
P9_DPRINTK ( P9_DEBUG_ERROR , " buffer overflow \n " ) ;
2005-09-09 13:04:21 -07:00
return - EIO ;
2006-01-08 01:04:58 -08:00
}
2005-09-09 13:04:21 -07:00
2006-01-08 01:05:00 -08:00
return bufp - > p - bufp - > sp ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_deserialize_fcall ) ;
2006-01-08 01:05:00 -08:00
2007-07-10 17:57:28 -05:00
static inline void p9_put_int8 ( struct cbuf * bufp , u8 val , u8 * p )
2006-01-08 01:05:00 -08:00
{
* p = val ;
buf_put_int8 ( bufp , val ) ;
}
2007-07-10 17:57:28 -05:00
static inline void p9_put_int16 ( struct cbuf * bufp , u16 val , u16 * p )
2006-01-08 01:05:00 -08:00
{
* p = val ;
buf_put_int16 ( bufp , val ) ;
}
2007-07-10 17:57:28 -05:00
static inline void p9_put_int32 ( struct cbuf * bufp , u32 val , u32 * p )
2006-01-08 01:05:00 -08:00
{
* p = val ;
buf_put_int32 ( bufp , val ) ;
}
2007-07-10 17:57:28 -05:00
static inline void p9_put_int64 ( struct cbuf * bufp , u64 val , u64 * p )
2006-01-08 01:05:00 -08:00
{
* p = val ;
buf_put_int64 ( bufp , val ) ;
}
2006-01-14 13:20:43 -08:00
static void
2007-07-10 17:57:28 -05:00
p9_put_str ( struct cbuf * bufp , char * data , struct p9_str * str )
2006-01-08 01:05:00 -08:00
{
2006-02-03 03:04:18 -08:00
int len ;
char * s ;
if ( data )
len = strlen ( data ) ;
else
len = 0 ;
2006-01-08 01:05:00 -08:00
2006-02-03 03:04:18 -08:00
s = buf_put_stringn ( bufp , data , len ) ;
if ( str ) {
str - > len = len ;
str - > str = s ;
}
2006-01-08 01:05:00 -08:00
}
2006-01-14 13:20:43 -08:00
static int
2007-07-10 17:57:28 -05:00
p9_put_data ( struct cbuf * bufp , const char * data , int count ,
unsigned char * * pdata )
{
* pdata = buf_alloc ( bufp , count ) ;
memmove ( * pdata , data , count ) ;
return count ;
}
static int
p9_put_user_data ( struct cbuf * bufp , const char __user * data , int count ,
2006-01-08 01:05:00 -08:00
unsigned char * * pdata )
{
* pdata = buf_alloc ( bufp , count ) ;
return copy_from_user ( * pdata , data , count ) ;
}
static void
2007-07-10 17:57:28 -05:00
p9_put_wstat ( struct cbuf * bufp , struct p9_wstat * wstat ,
struct p9_stat * stat , int statsz , int dotu )
2006-01-08 01:05:00 -08:00
{
2007-07-10 17:57:28 -05:00
p9_put_int16 ( bufp , statsz , & stat - > size ) ;
p9_put_int16 ( bufp , wstat - > type , & stat - > type ) ;
p9_put_int32 ( bufp , wstat - > dev , & stat - > dev ) ;
p9_put_int8 ( bufp , wstat - > qid . type , & stat - > qid . type ) ;
p9_put_int32 ( bufp , wstat - > qid . version , & stat - > qid . version ) ;
p9_put_int64 ( bufp , wstat - > qid . path , & stat - > qid . path ) ;
p9_put_int32 ( bufp , wstat - > mode , & stat - > mode ) ;
p9_put_int32 ( bufp , wstat - > atime , & stat - > atime ) ;
p9_put_int32 ( bufp , wstat - > mtime , & stat - > mtime ) ;
p9_put_int64 ( bufp , wstat - > length , & stat - > length ) ;
2006-01-08 01:05:00 -08:00
2007-07-10 17:57:28 -05:00
p9_put_str ( bufp , wstat - > name , & stat - > name ) ;
p9_put_str ( bufp , wstat - > uid , & stat - > uid ) ;
p9_put_str ( bufp , wstat - > gid , & stat - > gid ) ;
p9_put_str ( bufp , wstat - > muid , & stat - > muid ) ;
2006-01-08 01:05:00 -08:00
2007-07-10 17:57:28 -05:00
if ( dotu ) {
p9_put_str ( bufp , wstat - > extension , & stat - > extension ) ;
p9_put_int32 ( bufp , wstat - > n_uid , & stat - > n_uid ) ;
p9_put_int32 ( bufp , wstat - > n_gid , & stat - > n_gid ) ;
p9_put_int32 ( bufp , wstat - > n_muid , & stat - > n_muid ) ;
2006-01-08 01:05:00 -08:00
}
}
2007-07-10 17:57:28 -05:00
static struct p9_fcall *
p9_create_common ( struct cbuf * bufp , u32 size , u8 id )
2006-01-08 01:05:00 -08:00
{
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
size + = 4 + 1 + 2 ; /* size[4] id[1] tag[2] */
2007-07-10 17:57:28 -05:00
fc = kmalloc ( sizeof ( struct p9_fcall ) + size , GFP_KERNEL ) ;
2006-01-08 01:05:00 -08:00
if ( ! fc )
return ERR_PTR ( - ENOMEM ) ;
fc - > sdata = ( char * ) fc + sizeof ( * fc ) ;
buf_init ( bufp , ( char * ) fc - > sdata , size ) ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , size , & fc - > size ) ;
p9_put_int8 ( bufp , id , & fc - > id ) ;
p9_put_int16 ( bufp , P9_NOTAG , & fc - > tag ) ;
2006-01-08 01:05:00 -08:00
return fc ;
}
2008-03-05 07:08:09 -06:00
/**
* p9_set_tag - set the tag field of an & p9_fcall structure
* @ fc : fcall structure to set tag within
* @ tag : tag id to set
*/
2007-07-10 17:57:28 -05:00
void p9_set_tag ( struct p9_fcall * fc , u16 tag )
2006-01-08 01:05:00 -08:00
{
2006-01-08 01:05:02 -08:00
fc - > tag = tag ;
2006-01-08 01:05:00 -08:00
* ( __le16 * ) ( fc - > sdata + 5 ) = cpu_to_le16 ( tag ) ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_set_tag ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tversion - allocates and creates a T_VERSION request
* @ msize : requested maximum data size
* @ version : version string to negotiate
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_tversion ( u32 msize , char * version )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
size = 4 + 2 + strlen ( version ) ; /* msize[4] version[s] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TVERSION ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , msize , & fc - > params . tversion . msize ) ;
p9_put_str ( bufp , version , & fc - > params . tversion . version ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tversion ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tauth - allocates and creates a T_AUTH request
* @ afid : handle to use for authentication protocol
* @ uname : user name attempting to authenticate
* @ aname : mount specifier for remote server
* @ n_uname : numeric id for user attempting to authneticate
* @ dotu : 9 P2000 . u extension flag
*
*/
2007-10-17 14:31:07 -05:00
struct p9_fcall * p9_create_tauth ( u32 afid , char * uname , char * aname ,
u32 n_uname , int dotu )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
2007-07-10 17:57:28 -05:00
/* afid[4] uname[s] aname[s] */
2007-10-17 14:31:07 -05:00
size = 4 + 2 + 2 ;
if ( uname )
size + = strlen ( uname ) ;
if ( aname )
size + = strlen ( aname ) ;
if ( dotu )
size + = 4 ; /* n_uname */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TAUTH ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , afid , & fc - > params . tauth . afid ) ;
p9_put_str ( bufp , uname , & fc - > params . tauth . uname ) ;
p9_put_str ( bufp , aname , & fc - > params . tauth . aname ) ;
2007-10-17 14:31:07 -05:00
if ( dotu )
p9_put_int32 ( bufp , n_uname , & fc - > params . tauth . n_uname ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tauth ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tattach - allocates and creates a T_ATTACH request
* @ fid : handle to use for the new mount point
* @ afid : handle to use for authentication protocol
* @ uname : user name attempting to attach
* @ aname : mount specifier for remote server
* @ n_uname : numeric id for user attempting to attach
* @ n_uname : numeric id for user attempting to attach
* @ dotu : 9 P2000 . u extension flag
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall *
2007-10-17 14:31:07 -05:00
p9_create_tattach ( u32 fid , u32 afid , char * uname , char * aname ,
u32 n_uname , int dotu )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
2007-07-10 17:57:28 -05:00
/* fid[4] afid[4] uname[s] aname[s] */
2007-10-17 14:31:07 -05:00
size = 4 + 4 + 2 + 2 ;
if ( uname )
size + = strlen ( uname ) ;
if ( aname )
size + = strlen ( aname ) ;
if ( dotu )
size + = 4 ; /* n_uname */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TATTACH ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . tattach . fid ) ;
p9_put_int32 ( bufp , afid , & fc - > params . tattach . afid ) ;
p9_put_str ( bufp , uname , & fc - > params . tattach . uname ) ;
p9_put_str ( bufp , aname , & fc - > params . tattach . aname ) ;
2007-10-17 14:31:07 -05:00
if ( dotu )
p9_put_int32 ( bufp , n_uname , & fc - > params . tattach . n_uname ) ;
2006-01-08 01:05:00 -08:00
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tattach ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tflush - allocates and creates a T_FLUSH request
* @ oldtag : tag id for the transaction we are attempting to cancel
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_tflush ( u16 oldtag )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
size = 2 ; /* oldtag[2] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TFLUSH ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int16 ( bufp , oldtag , & fc - > params . tflush . oldtag ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tflush ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_twalk - allocates and creates a T_FLUSH request
* @ fid : handle we are traversing from
* @ newfid : a new handle for this transaction
* @ nwname : number of path elements to traverse
* @ wnames : array of path elements
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_twalk ( u32 fid , u32 newfid , u16 nwname ,
2006-01-08 01:05:00 -08:00
char * * wnames )
{
int i , size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
2007-07-10 17:57:28 -05:00
if ( nwname > P9_MAXWELEM ) {
P9_DPRINTK ( P9_DEBUG_ERROR , " nwname > %d \n " , P9_MAXWELEM ) ;
2006-01-08 01:05:00 -08:00
return NULL ;
}
size = 4 + 4 + 2 ; /* fid[4] newfid[4] nwname[2] ... */
for ( i = 0 ; i < nwname ; i + + ) {
size + = 2 + strlen ( wnames [ i ] ) ; /* wname[s] */
}
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TWALK ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . twalk . fid ) ;
p9_put_int32 ( bufp , newfid , & fc - > params . twalk . newfid ) ;
p9_put_int16 ( bufp , nwname , & fc - > params . twalk . nwname ) ;
2006-01-08 01:05:00 -08:00
for ( i = 0 ; i < nwname ; i + + ) {
2007-07-10 17:57:28 -05:00
p9_put_str ( bufp , wnames [ i ] , & fc - > params . twalk . wnames [ i ] ) ;
2006-01-08 01:05:00 -08:00
}
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_twalk ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_topen - allocates and creates a T_OPEN request
* @ fid : handle we are trying to open
* @ mode : what mode we are trying to open the file in
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_topen ( u32 fid , u8 mode )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
size = 4 + 1 ; /* fid[4] mode[1] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TOPEN ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . topen . fid ) ;
p9_put_int8 ( bufp , mode , & fc - > params . topen . mode ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_topen ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tcreate - allocates and creates a T_CREATE request
* @ fid : handle of directory we are trying to create in
* @ name : name of the file we are trying to create
* @ perm : permissions for the file we are trying to create
* @ mode : what mode we are trying to open the file in
* @ extension : 9 p2000 . u extension string ( for special files )
* @ dotu : 9 p2000 . u enabled flag
*
* Note : Plan 9 create semantics include opening the resulting file
* which is why mode is included .
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_tcreate ( u32 fid , char * name , u32 perm , u8 mode ,
char * extension , int dotu )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
2007-07-10 17:57:28 -05:00
/* fid[4] name[s] perm[4] mode[1] */
size = 4 + 2 + strlen ( name ) + 4 + 1 ;
if ( dotu ) {
2006-07-30 03:04:15 -07:00
size + = 2 + /* extension[s] */
( extension = = NULL ? 0 : strlen ( extension ) ) ;
}
2006-03-25 03:07:26 -08:00
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TCREATE ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . tcreate . fid ) ;
p9_put_str ( bufp , name , & fc - > params . tcreate . name ) ;
p9_put_int32 ( bufp , perm , & fc - > params . tcreate . perm ) ;
p9_put_int8 ( bufp , mode , & fc - > params . tcreate . mode ) ;
if ( dotu )
p9_put_str ( bufp , extension , & fc - > params . tcreate . extension ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tcreate ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tread - allocates and creates a T_READ request
* @ fid : handle of the file we are trying to read
* @ offset : offset to start reading from
* @ count : how many bytes to read
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_tread ( u32 fid , u64 offset , u32 count )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
size = 4 + 8 + 4 ; /* fid[4] offset[8] count[4] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TREAD ) ;
if ( IS_ERR ( fc ) )
goto error ;
p9_put_int32 ( bufp , fid , & fc - > params . tread . fid ) ;
p9_put_int64 ( bufp , offset , & fc - > params . tread . offset ) ;
p9_put_int32 ( bufp , count , & fc - > params . tread . count ) ;
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
error :
return fc ;
}
EXPORT_SYMBOL ( p9_create_tread ) ;
2008-03-05 07:08:09 -06:00
/**
* p9_create_twrite - allocates and creates a T_WRITE request from the kernel
* @ fid : handle of the file we are trying to write
* @ offset : offset to start writing at
* @ count : how many bytes to write
* @ data : data to write
*
* This function will create a requst with data buffers from the kernel
* such as the page cache .
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_twrite ( u32 fid , u64 offset , u32 count ,
const char * data )
{
int size , err ;
struct p9_fcall * fc ;
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
/* fid[4] offset[8] count[4] data[count] */
size = 4 + 8 + 4 + count ;
fc = p9_create_common ( bufp , size , P9_TWRITE ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . twrite . fid ) ;
p9_put_int64 ( bufp , offset , & fc - > params . twrite . offset ) ;
p9_put_int32 ( bufp , count , & fc - > params . twrite . count ) ;
err = p9_put_data ( bufp , data , count , & fc - > params . twrite . data ) ;
if ( err ) {
kfree ( fc ) ;
fc = ERR_PTR ( err ) ;
2007-07-31 00:39:13 -07:00
goto error ;
2007-07-10 17:57:28 -05:00
}
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_twrite ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_twrite_u - allocates and creates a T_WRITE request from userspace
* @ fid : handle of the file we are trying to write
* @ offset : offset to start writing at
* @ count : how many bytes to write
* @ data : data to write
*
* This function will create a request with data buffers from userspace
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_twrite_u ( u32 fid , u64 offset , u32 count ,
const char __user * data )
2006-01-08 01:05:00 -08:00
{
int size , err ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
2007-07-10 17:57:28 -05:00
/* fid[4] offset[8] count[4] data[count] */
size = 4 + 8 + 4 + count ;
fc = p9_create_common ( bufp , size , P9_TWRITE ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . twrite . fid ) ;
p9_put_int64 ( bufp , offset , & fc - > params . twrite . offset ) ;
p9_put_int32 ( bufp , count , & fc - > params . twrite . count ) ;
err = p9_put_user_data ( bufp , data , count , & fc - > params . twrite . data ) ;
2006-01-08 01:05:00 -08:00
if ( err ) {
kfree ( fc ) ;
fc = ERR_PTR ( err ) ;
2007-08-23 10:24:28 -05:00
goto error ;
2006-01-08 01:05:00 -08:00
}
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_twrite_u ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tclunk - allocate a request to forget about a file handle
* @ fid : handle of the file we closing or forgetting about
*
* clunk is used both to close open files and to discard transient handles
* which may be created during meta - data operations and hierarchy traversal .
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_tclunk ( u32 fid )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
size = 4 ; /* fid[4] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TCLUNK ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . tclunk . fid ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tclunk ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tremove - allocate and create a request to remove a file
* @ fid : handle of the file or directory we are removing
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_tremove ( u32 fid )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
size = 4 ; /* fid[4] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TREMOVE ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . tremove . fid ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tremove ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tstat - allocate and populate a request for attributes
* @ fid : handle of the file or directory we are trying to get the attributes of
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_tstat ( u32 fid )
2006-01-08 01:05:00 -08:00
{
int size ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
size = 4 ; /* fid[4] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TSTAT ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . tstat . fid ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_tstat ) ;
2006-01-08 01:05:00 -08:00
2008-03-05 07:08:09 -06:00
/**
* p9_create_tstat - allocate and populate a request to change attributes
* @ fid : handle of the file or directory we are trying to change
* @ wstat : & p9_stat structure with attributes we wish to set
* @ dotu : 9 p2000 . u enabled flag
*
*/
2007-07-10 17:57:28 -05:00
struct p9_fcall * p9_create_twstat ( u32 fid , struct p9_wstat * wstat ,
int dotu )
2006-01-08 01:05:00 -08:00
{
int size , statsz ;
2007-07-10 17:57:28 -05:00
struct p9_fcall * fc ;
2006-01-08 01:05:00 -08:00
struct cbuf buffer ;
struct cbuf * bufp = & buffer ;
2007-07-10 17:57:28 -05:00
statsz = p9_size_wstat ( wstat , dotu ) ;
2006-01-08 01:05:00 -08:00
size = 4 + 2 + 2 + statsz ; /* fid[4] stat[n] */
2007-07-10 17:57:28 -05:00
fc = p9_create_common ( bufp , size , P9_TWSTAT ) ;
2006-01-08 01:05:00 -08:00
if ( IS_ERR ( fc ) )
goto error ;
2007-07-10 17:57:28 -05:00
p9_put_int32 ( bufp , fid , & fc - > params . twstat . fid ) ;
2006-01-08 01:05:00 -08:00
buf_put_int16 ( bufp , statsz + 2 ) ;
2007-07-10 17:57:28 -05:00
p9_put_wstat ( bufp , wstat , & fc - > params . twstat . stat , statsz , dotu ) ;
2006-01-08 01:05:00 -08:00
if ( buf_check_overflow ( bufp ) ) {
kfree ( fc ) ;
fc = ERR_PTR ( - ENOMEM ) ;
}
2007-07-10 17:57:28 -05:00
error :
2006-01-08 01:05:00 -08:00
return fc ;
2005-09-09 13:04:21 -07:00
}
2007-07-10 17:57:28 -05:00
EXPORT_SYMBOL ( p9_create_twstat ) ;
2008-03-05 07:08:09 -06:00