@ -139,6 +139,7 @@ struct p9_rdma_opts {
int sq_depth ;
int rq_depth ;
long timeout ;
int privport ;
} ;
/*
@ -146,7 +147,10 @@ struct p9_rdma_opts {
*/
enum {
/* Options that take integer arguments */
Opt_port , Opt_rq_depth , Opt_sq_depth , Opt_timeout , Opt_err ,
Opt_port , Opt_rq_depth , Opt_sq_depth , Opt_timeout ,
/* Options that take no argument */
Opt_privport ,
Opt_err ,
} ;
static match_table_t tokens = {
@ -154,6 +158,7 @@ static match_table_t tokens = {
{ Opt_sq_depth , " sq=%u " } ,
{ Opt_rq_depth , " rq=%u " } ,
{ Opt_timeout , " timeout=%u " } ,
{ Opt_privport , " privport " } ,
{ Opt_err , NULL } ,
} ;
@ -175,6 +180,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
opts - > sq_depth = P9_RDMA_SQ_DEPTH ;
opts - > rq_depth = P9_RDMA_RQ_DEPTH ;
opts - > timeout = P9_RDMA_TIMEOUT ;
opts - > privport = 0 ;
if ( ! params )
return 0 ;
@ -193,13 +199,13 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
if ( ! * p )
continue ;
token = match_token ( p , tokens , args ) ;
if ( token = = Opt_err )
continue ;
r = match_int ( & args [ 0 ] , & option ) ;
if ( r < 0 ) {
p9_debug ( P9_DEBUG_ERROR ,
" integer field, but no integer? \n " ) ;
continue ;
if ( ( token ! = Opt_err ) & & ( token ! = Opt_privport ) ) {
r = match_int ( & args [ 0 ] , & option ) ;
if ( r < 0 ) {
p9_debug ( P9_DEBUG_ERROR ,
" integer field, but no integer? \n " ) ;
continue ;
}
}
switch ( token ) {
case Opt_port :
@ -214,6 +220,9 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
case Opt_timeout :
opts - > timeout = option ;
break ;
case Opt_privport :
opts - > privport = 1 ;
break ;
default :
continue ;
}
@ -607,6 +616,23 @@ static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req)
return 0 ;
}
static int p9_rdma_bind_privport ( struct p9_trans_rdma * rdma )
{
struct sockaddr_in cl = {
. sin_family = AF_INET ,
. sin_addr . s_addr = htonl ( INADDR_ANY ) ,
} ;
int port , err = - EINVAL ;
for ( port = P9_DEF_MAX_RESVPORT ; port > = P9_DEF_MIN_RESVPORT ; port - - ) {
cl . sin_port = htons ( ( ushort ) port ) ;
err = rdma_bind_addr ( rdma - > cm_id , ( struct sockaddr * ) & cl ) ;
if ( err ! = - EADDRINUSE )
break ;
}
return err ;
}
/**
* trans_create_rdma - Transport method for creating atransport instance
* @ client : client instance
@ -642,6 +668,16 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
/* Associate the client with the transport */
client - > trans = rdma ;
/* Bind to a privileged port if we need to */
if ( opts . privport ) {
err = p9_rdma_bind_privport ( rdma ) ;
if ( err < 0 ) {
pr_err ( " %s (%d): problem binding to privport: %d \n " ,
__func__ , task_pid_nr ( current ) , - err ) ;
goto error ;
}
}
/* Resolve the server's address */
rdma - > addr . sin_family = AF_INET ;
rdma - > addr . sin_addr . s_addr = in_aton ( addr ) ;