Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a217813f9067b785241cb7f31956e51d2071703a
Commit:     a217813f9067b785241cb7f31956e51d2071703a
Parent:     7fcb98d58cb4d18af6386f71025fc5192f25fbca
Author:     Tom Tucker <[EMAIL PROTECTED]>
AuthorDate: Sun Dec 30 21:08:35 2007 -0600
Committer:  J. Bruce Fields <[EMAIL PROTECTED]>
CommitDate: Fri Feb 1 16:42:13 2008 -0500

    knfsd: Support adding transports by writing portlist file
    
    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]>
    Acked-by: Neil Brown <[EMAIL PROTECTED]>
    Reviewed-by: Chuck Lever <[EMAIL PROTECTED]>
    Reviewed-by: Greg Banks <[EMAIL PROTECTED]>
    Signed-off-by: J. Bruce Fields <[EMAIL PROTECTED]>
---
 fs/lockd/svc.c        |   18 +++++++++++++-----
 fs/nfsd/nfsctl.c      |   49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 net/sunrpc/svc_xprt.c |    2 ++
 3 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 470af01..0822646 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -227,17 +227,25 @@ lockd(struct svc_rqst *rqstp)
 static int make_socks(struct svc_serv *serv, int proto)
 {
        static int warned;
+       struct svc_xprt *xprt;
        int err = 0;
 
-       if (proto == IPPROTO_UDP || nlm_udpport)
-               if (!svc_find_xprt(serv, "udp", 0, 0))
+       if (proto == IPPROTO_UDP || nlm_udpport) {
+               xprt = svc_find_xprt(serv, "udp", 0, 0);
+               if (!xprt)
                        err = svc_create_xprt(serv, "udp", nlm_udpport,
                                              SVC_SOCK_DEFAULTS);
-       if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport))
-               if (!svc_find_xprt(serv, "tcp", 0, 0))
+               else
+                       svc_xprt_put(xprt);
+       }
+       if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) {
+               xprt = svc_find_xprt(serv, "tcp", 0, 0);
+               if (!xprt)
                        err = svc_create_xprt(serv, "tcp", nlm_tcpport,
                                              SVC_SOCK_DEFAULTS);
-
+               else
+                       svc_xprt_put(xprt);
+       }
        if (err >= 0) {
                warned = 0;
                err = 0;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 4aba926..eff6a6b 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,53 @@ 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) {
+                               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);
+                                       svc_xprt_put(xprt);
+                                       err = 0;
+                               } 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 512c10f..7835973 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -842,6 +842,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)
 {
@@ -1006,6 +1007,7 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, 
char *xcl_name,
                if (port && port != svc_xprt_local_port(xprt))
                        continue;
                found = xprt;
+               svc_xprt_get(xprt);
                break;
        }
        spin_unlock_bh(&serv->sv_lock);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to