On Tue, Dec 11, 2007 at 05:33:16PM -0600, Tom Tucker wrote:
> 
> Update the write handler for the portlist file to allow creating new
> listening endpoints on a transport. The general form of the string is:
> 
> <transport_name><space><port number>
> 
> For example:
> 
> echo "tcp 2049" > /proc/fs/nfsd/portlist
> 
> This is intended to support the creation of a listening endpoint for
> RDMA transports without adding #ifdef code to the nfssvc.c file.
> 
> Transports can also be removed as follows:
> 
> '-'<transport_name><space><port number>
> 
> For example:
> 
> echo "-tcp 2049" > /proc/fs/nfsd/portlist
> 
> Attempting to add a listener with an invalid transport string results
> in EPROTONOSUPPORT and a perror string of "Protocol not supported". 
> 
> Attempting to remove an non-existent listener (.e.g. bad proto or port)
> results in ENOTCONN and a perror string of 
> "Transport endpoint is not connected"
> 
> Signed-off-by: Tom Tucker <[EMAIL PROTECTED]>
> ---
> 
>  fs/nfsd/nfsctl.c      |   52 
> ++++++++++++++++++++++++++++++++++++++++++++++++-
>  net/sunrpc/svc_xprt.c |    1 +
>  2 files changed, 52 insertions(+), 1 deletions(-)
> 
> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> index 77dc989..5b9ed0e 100644
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -540,7 +540,7 @@ static ssize_t write_ports(struct file *file, char *buf, 
> size_t size)
>               }
>               return err < 0 ? err : 0;
>       }
> -     if (buf[0] == '-') {
> +     if (buf[0] == '-' && isdigit(buf[1])) {
>               char *toclose = kstrdup(buf+1, GFP_KERNEL);
>               int len = 0;
>               if (!toclose)
> @@ -554,6 +554,56 @@ static ssize_t write_ports(struct file *file, char *buf, 
> size_t size)
>               kfree(toclose);
>               return len;
>       }
> +     /*
> +      * Add a transport listener by writing it's transport name
> +      */
> +     if (isalpha(buf[0])) {
> +             int err;
> +             char transport[16];
> +             int port;
> +             if (sscanf(buf, "%15s %4d", transport, &port) == 2) {
> +                     err = nfsd_create_serv();
> +                     if (!err) {
> +                             if (svc_find_xprt(nfsd_serv, transport,
> +                                               AF_UNSPEC, port))
> +                                     return -EADDRINUSE;

Shouldn't svc_create_xprt do this check for us itself?  (And if it
doesn't, isn't there some minor race between two writers both checking,
finding nothing, and then both svc_create_xprt()ing?)

> +
> +                             err = svc_create_xprt(nfsd_serv,
> +                                                   transport, port,
> +                                                   SVC_SOCK_ANONYMOUS);
> +                             if (err == -ENOENT)
> +                                     /* Give a reasonable perror msg for
> +                                      * bad transport string */
> +                                     err = -EPROTONOSUPPORT;
> +                     }
> +                     return err < 0 ? err : 0;
> +             }
> +     }
> +     /*
> +      * Remove a transport by writing it's transport name and port number
> +      */
> +     if (buf[0] == '-' && isalpha(buf[1])) {
> +             struct svc_xprt *xprt;
> +             int err = -EINVAL;
> +             char transport[16];
> +             int port;
> +             if (sscanf(&buf[1], "%15s %4d", transport, &port) == 2) {
> +                     if (port == 0)
> +                             return -EINVAL;
> +                     lock_kernel();
> +                     if (nfsd_serv) {
> +                             xprt = svc_find_xprt(nfsd_serv, transport,
> +                                                  AF_UNSPEC, port);
> +                             if (xprt) {
> +                                     svc_close_xprt(xprt);
> +                                     err = 0;

Hm, also: I'd have thought that svc_find_xprt should be incrementing the
reference count on the returned xprt, if we're expecting the caller to
do anything with it other than check it against NULL.

--b.


> +                             } else
> +                                     err = -ENOTCONN;
> +                     }
> +                     unlock_kernel();
> +                     return err < 0 ? err : 0;
> +             }
> +     }
>       return -EINVAL;
>  }
>  
> diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
> index 9815c6f..6708aa2 100644
> --- a/net/sunrpc/svc_xprt.c
> +++ b/net/sunrpc/svc_xprt.c
> @@ -827,6 +827,7 @@ void svc_close_xprt(struct svc_xprt *xprt)
>       clear_bit(XPT_BUSY, &xprt->xpt_flags);
>       svc_xprt_put(xprt);
>  }
> +EXPORT_SYMBOL_GPL(svc_close_xprt);
>  
>  void svc_close_all(struct list_head *xprt_list)
>  {
-
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to