2011-01-15 23:15:31 +03:00
/*
* Copyright ( c ) 2009 , 2010 Jeff Mahoney < jeffm @ suse . com >
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "defs.h"
# include <linux/blkpg.h>
# include <linux/fs.h>
# include <linux/hdreg.h>
/* ioctls <= 114 are present in Linux 2.4. The following ones have been
* added since then and headers containing them may not be available on
* every system . */
# define BLKTRACE_BDEV_SIZE 32
struct blk_user_trace_setup {
char name [ BLKTRACE_BDEV_SIZE ] ; /* output */
uint16_t act_mask ; /* input */
uint32_t buf_size ; /* input */
uint32_t buf_nr ; /* input */
uint64_t start_lba ;
uint64_t end_lba ;
uint32_t pid ;
} ;
# ifndef BLKTRACESETUP
# define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup)
# endif
# ifndef BLKTRACESTART
# define BLKTRACESTART _IO(0x12,116)
# endif
2011-04-07 23:58:10 +04:00
# ifndef BLKTRACESTOP
2011-01-15 23:15:31 +03:00
# define BLKTRACESTOP _IO(0x12,117)
# endif
# ifndef BLKTRACETEARDOWN
# define BLKTRACETEARDOWN _IO(0x12,118)
# endif
# ifndef BLKDISCARD
# define BLKDISCARD _IO(0x12,119)
# endif
# ifndef BLKIOMIN
# define BLKIOMIN _IO(0x12,120)
# endif
# ifndef BLKIOOPT
# define BLKIOOPT _IO(0x12,121)
# endif
# ifndef BLKALIGNOFF
# define BLKALIGNOFF _IO(0x12,122)
# endif
# ifndef BLKPBSZGET
# define BLKPBSZGET _IO(0x12,123)
# endif
# ifndef BLKDISCARDZEROES
# define BLKDISCARDZEROES _IO(0x12,124)
# endif
# ifndef BLKSECDISCARD
# define BLKSECDISCARD _IO(0x12,125)
# endif
static const struct xlat blkpg_ops [ ] = {
{ BLKPG_ADD_PARTITION , " BLKPG_ADD_PARTITION " , } ,
{ BLKPG_DEL_PARTITION , " BLKPG_DEL_PARTITION " , } ,
{ 0 , NULL } ,
} ;
static void
print_blkpg_req ( struct tcb * tcp , struct blkpg_ioctl_arg * blkpg )
{
struct blkpg_partition p ;
2011-09-01 12:00:28 +04:00
tprints ( " { " ) ;
2011-01-17 02:07:51 +03:00
printxval ( blkpg_ops , blkpg - > op , " BLKPG_??? " ) ;
2011-01-15 23:15:31 +03:00
2011-01-17 02:07:51 +03:00
tprintf ( " , flags=%d, datalen=%d, " ,
blkpg - > flags , blkpg - > datalen ) ;
2011-01-15 23:15:31 +03:00
2011-01-17 02:07:51 +03:00
if ( umove ( tcp , ( long ) blkpg - > data , & p ) < 0 )
tprintf ( " %#lx} " , ( long ) blkpg - > data ) ;
else
tprintf ( " {start=%lld, length=%lld, pno=%d, "
" devname= \" %.*s \" , volname= \" %.*s \" }} " ,
p . start , p . length , p . pno ,
( int ) sizeof ( p . devname ) , p . devname ,
( int ) sizeof ( p . volname ) , p . volname ) ;
2011-01-15 23:15:31 +03:00
}
int
block_ioctl ( struct tcb * tcp , long code , long arg )
{
switch ( code ) {
2011-01-17 02:07:51 +03:00
/* take arg as a value, not as a pointer */
2011-01-15 23:15:31 +03:00
case BLKRASET :
case BLKFRASET :
if ( entering ( tcp ) )
tprintf ( " , %ld " , arg ) ;
break ;
2011-01-17 02:07:51 +03:00
/* take a signed int */
2011-01-15 23:15:31 +03:00
case BLKROSET :
case BLKBSZSET :
if ( entering ( tcp ) ) {
2011-01-17 02:07:51 +03:00
int val ;
if ( umove ( tcp , arg , & val ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , %d " , val ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-01-17 02:07:51 +03:00
/* returns an unsigned short */
2011-01-15 23:15:31 +03:00
case BLKSECTGET :
if ( exiting ( tcp ) ) {
2011-01-17 02:07:51 +03:00
unsigned short val ;
if ( syserror ( tcp ) | | umove ( tcp , arg , & val ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2012-04-16 20:12:27 +04:00
tprintf ( " , %u " , ( unsigned ) val ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-01-17 02:07:51 +03:00
/* return a signed int */
2011-01-15 23:15:31 +03:00
case BLKROGET :
case BLKBSZGET :
case BLKSSZGET :
case BLKALIGNOFF :
if ( exiting ( tcp ) ) {
2011-01-17 02:07:51 +03:00
int val ;
if ( syserror ( tcp ) | | umove ( tcp , arg , & val ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , %d " , val ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-01-17 02:07:51 +03:00
/* return an unsigned int */
2011-01-15 23:15:31 +03:00
case BLKPBSZGET :
case BLKIOMIN :
case BLKIOOPT :
case BLKDISCARDZEROES :
if ( exiting ( tcp ) ) {
2011-01-17 02:07:51 +03:00
unsigned int val ;
if ( syserror ( tcp ) | | umove ( tcp , arg , & val ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , %u " , val ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-01-17 02:07:51 +03:00
/* return a signed long */
2011-01-15 23:15:31 +03:00
case BLKRAGET :
case BLKFRAGET :
if ( exiting ( tcp ) ) {
2011-01-17 02:07:51 +03:00
long val ;
if ( syserror ( tcp ) | | umove ( tcp , arg , & val ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , %ld " , val ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-01-17 02:07:51 +03:00
/* returns an unsigned long */
2011-01-15 23:15:31 +03:00
case BLKGETSIZE :
if ( exiting ( tcp ) ) {
2011-01-17 02:07:51 +03:00
unsigned long val ;
if ( syserror ( tcp ) | | umove ( tcp , arg , & val ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , %lu " , val ) ;
2013-03-05 20:46:19 +04:00
}
2011-01-15 23:15:31 +03:00
break ;
2011-08-17 01:36:16 +04:00
# ifdef HAVE_BLKGETSIZE64
2011-01-17 02:07:51 +03:00
/* return an uint64_t */
2011-01-15 23:15:31 +03:00
case BLKGETSIZE64 :
if ( exiting ( tcp ) ) {
2011-01-17 02:07:51 +03:00
uint64_t val ;
if ( syserror ( tcp ) | | umove ( tcp , arg , & val ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , % " PRIu64 , val ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-08-15 13:36:09 +04:00
# endif
2011-01-15 23:15:31 +03:00
/* More complex types */
case BLKDISCARD :
case BLKSECDISCARD :
if ( entering ( tcp ) ) {
uint64_t range [ 2 ] ;
if ( umove ( tcp , arg , range ) < 0 )
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , {% " PRIx64 " , % " PRIx64 " } " ,
range [ 0 ] , range [ 1 ] ) ;
2011-01-15 23:15:31 +03:00
}
break ;
case HDIO_GETGEO :
if ( exiting ( tcp ) ) {
struct hd_geometry geo ;
2011-01-17 02:07:51 +03:00
if ( syserror ( tcp ) | | umove ( tcp , arg , & geo ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2012-04-16 20:12:27 +04:00
tprintf ( " , {heads=%u, sectors=%u, "
" cylinders=%u, start=%lu} " ,
( unsigned ) geo . heads ,
( unsigned ) geo . sectors ,
( unsigned ) geo . cylinders ,
geo . start ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-01-17 02:07:51 +03:00
2011-01-15 23:15:31 +03:00
case BLKPG :
if ( entering ( tcp ) ) {
struct blkpg_ioctl_arg blkpg ;
if ( umove ( tcp , arg , & blkpg ) < 0 )
tprintf ( " , %#lx " , arg ) ;
else {
2011-09-01 12:00:28 +04:00
tprints ( " , " ) ;
2011-01-15 23:15:31 +03:00
print_blkpg_req ( tcp , & blkpg ) ;
}
}
break ;
2011-01-17 02:07:51 +03:00
2011-01-15 23:15:31 +03:00
case BLKTRACESETUP :
if ( entering ( tcp ) ) {
struct blk_user_trace_setup buts ;
if ( umove ( tcp , arg , & buts ) < 0 )
tprintf ( " , %#lx " , arg ) ;
2011-01-17 02:07:51 +03:00
else
2012-04-16 20:12:27 +04:00
tprintf ( " , {act_mask=%u, buf_size=%u, "
2011-01-17 02:07:51 +03:00
" buf_nr=%u, start_lba=% " PRIu64 " , "
" end_lba=% " PRIu64 " , pid=%u} " ,
2012-04-16 20:12:27 +04:00
( unsigned ) buts . act_mask , buts . buf_size ,
2011-01-17 02:07:51 +03:00
buts . buf_nr , buts . start_lba ,
buts . end_lba , buts . pid ) ;
2011-01-15 23:15:31 +03:00
}
if ( exiting ( tcp ) ) {
struct blk_user_trace_setup buts ;
2011-01-17 02:07:51 +03:00
if ( syserror ( tcp ) | | umove ( tcp , arg , & buts ) < 0 )
2011-01-15 23:15:31 +03:00
tprintf ( " , %#lx " , arg ) ;
else
2011-01-17 02:07:51 +03:00
tprintf ( " , {name= \" %.*s \" } " ,
( int ) sizeof ( buts . name ) , buts . name ) ;
2011-01-15 23:15:31 +03:00
}
break ;
2011-01-17 02:07:51 +03:00
2011-01-15 23:15:31 +03:00
/* No arguments or unhandled */
case BLKTRACESTART :
case BLKTRACESTOP :
case BLKTRACETEARDOWN :
case BLKFLSBUF : /* Requires driver knowlege */
case BLKRRPART : /* No args */
default :
if ( entering ( tcp ) )
tprintf ( " , %#lx " , arg ) ;
break ;
} ;
return 1 ;
}