9p: 9P server TCP socket connection support
Subsystems (2)
Latchesar Ionkov
maintainerRFC PATCH 5/6 9p: 9P server TCP socket connection support
This patchset provides support for in-kernel 9P2000 servers.
Support for 9P servers listening on TCP sockets.
Signed-off-by Latchesar Ionkov <[email protected]>
--- net/9p/srv/socksrv.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 252 insertions(+), 0 deletions(-) create mode 100644 net/9p/srv/socksrv.c
net/9p/srv/socksrv.c new file +252 -0
@@ -0,0 +1,252 @@ +/* +* net/9p/srv/socksrv.c +* +* 9P Socket Server +* +* Copyright (C) 2007 by Latchesar Ionkov <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* 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> +#include <linux/poll.h> +#include <linux/kthread.h> +#include <linux/net.h> +#include <linux/in.h> +#include <linux/parser.h> +#include <net/tcp.h> +#include <net/sock.h> +#include <net/9p/9p.h> +#include <net/9p/transport.h> +#include <net/9p/srv.h> +#include "srvimpl.h" + +struct p9srv_socksrv { +struct sockaddr_in saddr; +struct socket *sock; +struct p9srv *srv; +struct work_struct wq; +}; + +void (*p9srv_socksrv_dr_save)(struct sock *sock,int count); + +static void p9srv_socksrv_start (struct p9srv *); +static void p9srv_socksrv_stop (struct p9srv *); +static void p9srv_socksrv_destroy (struct p9srv *); +static void p9srv_socksrv_data_ready (struct sock *sock,int count); +static void p9srv_socksrv_accept (struct work_struct *work); + +struct p9srv *p9srv_socksrv_create (int port) +{ +int n, err; +struct p9srv_socksrv *ss; +struct p9srv *srv; + + srv =NULL ; + ss =kmalloc (sizeof (struct p9srv_socksrv ),GFP_KERNEL ); +if (!ss) +return ERR_PTR (-ENOMEM ); + + ss->sock =NULL ; + err =sock_create_kern (PF_INET ,SOCK_STREAM ,IPPROTO_TCP , &ss->sock); +if (!ss->sock) { +P9_DPRINTK (P9SRV_DEBUG_SRV ,"cannot create socket %d\n" , err); + goto error; + } + + n =1 ; + ss->saddr.sin_family =AF_INET ; +memset (&ss->saddr.sin_zero,0 ,sizeof (ss->saddr.sin_zero)); + ss->saddr.sin_addr.s_addr =htonl (INADDR_ANY ); + ss->saddr.sin_port =htons (port); + err = ss->sock->ops->bind (ss->sock, (struct sockaddr *) &ss->saddr, +sizeof (ss->saddr)); +if (err <0 ) { +P9_DPRINTK (P9SRV_DEBUG_SRV ,"cannot create bind %d\n" , err); + goto error; + } + + err =kernel_setsockopt (ss->sock,SOL_SOCKET ,SO_REUSEADDR , (char *) &n, +sizeof (n)); +if (err <0 ) { +P9_DPRINTK (P9SRV_DEBUG_SRV ,"cannot create setsockopt\n" ); + goto error; + } + + srv =p9srv_srv_create (); +if (!srv) { + err =PTR_ERR (srv); + srv =NULL ; + goto error; + } + + ss->srv = srv; +INIT_WORK (&ss->wq, p9srv_socksrv_accept); + srv->srvaux = ss; + srv->start = p9srv_socksrv_start; + srv->stop = p9srv_socksrv_stop; + srv->destroy = p9srv_socksrv_destroy; + +P9_DPRINTK (P9SRV_DEBUG_SRV ,"server %p on port %d created\n" , + srv, port); +return srv; + +error: +if (ss->sock) +sock_release (ss->sock); + +if (srv) +p9srv_srv_destroy (srv); + +kfree (ss); +return ERR_PTR (err); +} +EXPORT_SYMBOL (p9srv_socksrv_create); + +static void p9srv_socksrv_start (struct p9srv *srv) +{ +int err; +struct p9srv_socksrv *ss; + + ss = srv->srvaux; + err = ss->sock->ops->listen (ss->sock,5 ); +if (err <0 ) { +P9_DPRINTK (P9SRV_DEBUG_SRV ,"cannot listen %d\n" , err); +return ; + } + + p9srv_socksrv_dr_save = ss->sock->sk->sk_data_ready; + ss->sock->sk->sk_data_ready = p9srv_socksrv_data_ready; + ss->sock->sk->sk_user_data = srv; +} + +static void p9srv_socksrv_stop (struct p9srv *srv) +{ +struct p9srv_socksrv *ss; + +P9_DPRINTK (P9SRV_DEBUG_SRV ,"srv %p\n" , srv); + ss = srv->srvaux; +if (ss->sock) { + ss->sock->ops->shutdown (ss->sock,2 ); +sock_release (ss->sock); + ss->sock =NULL ; + } + + ss->sock =NULL ; +} + +static void p9srv_socksrv_destroy (struct p9srv *srv) +{ +struct p9srv_socksrv *ss; + +P9_DPRINTK (P9SRV_DEBUG_SRV ,"srv %p\n" , srv); + ss = srv->srvaux; +if (ss->sock) { + ss->sock->ops->shutdown (ss->sock,2 ); +sock_release (ss->sock); + ss->sock =NULL ; + } + +kfree (ss); +} + +static void p9srv_socksrv_data_ready (struct sock *sock,int count) +{ +struct p9srv *srv; +struct p9srv_socksrv *ss; + + srv = sock->sk_user_data; +if (!srv) { + (*p9srv_socksrv_dr_save)(sock, count); +return ; + } + + ss = srv->srvaux; +queue_work (p9srv_wq, &ss->wq); +} + +static void p9srv_socksrv_accept (struct work_struct *work) +{ +int err, fd; +struct p9srv *srv; +struct p9srv_socksrv *ss; +struct socket *sock; +struct p9_trans *trans; +struct p9srv_conn *conn; +struct p9_trans_module *tmod; +substring_t tname; +char buf[64 ]; + + ss = container_of(work, struct p9srv_socksrv, wq); + srv = ss->srv; +P9_DPRINTK (P9SRV_DEBUG_SRV ,"srv %p\n" , srv); + + tname.from ="fd" ; + tname.to = tname.from +strlen (tname.from); + tmod =v9fs_match_trans (&tname); +if (!tmod) { +P9_EPRINTK (KERN_ERR , +"p9srv_socksrv_accept: fd transport not registered\n" ); +return ; + } + + err =sock_create_kern (PF_INET ,SOCK_STREAM ,IPPROTO_TCP , &sock); +if (!sock) { +P9_EPRINTK (KERN_ERR , +"p9srv_socksrv_accept: cannot create socket %d\n" , err); +return ; + } + + sock->type = ss->sock->type; + sock->ops = ss->sock->ops; + err = ss->sock->ops->accept (ss->sock, sock,0 ); +if (err) { +P9_EPRINTK (KERN_ERR , +"p9srv_socksrv_accept: cannot accept %d\n" , err); +return ; + } + + sock->sk->sk_data_ready = p9srv_socksrv_dr_save; + sock->sk->sk_user_data =NULL ; + sock->sk->sk_allocation =GFP_NOIO ; + + fd =sock_map_fd (sock); +if (fd <0 ) { +P9_EPRINTK (KERN_ERR , +"p9srv_socksrv_accept: cannot map fd %d\n" , fd); +return ; + } + +snprintf (buf,sizeof (buf),"rfdno=%d,wfdno=%d" , fd, fd); + trans = (*tmod->create)(NULL , buf); +if (IS_ERR (trans)) { +P9_EPRINTK (KERN_ERR , +"p9srv_socksrv_accept: cannot create trans %ld\n" , +PTR_ERR (trans)); +return ; + } + + conn =p9srv_conn_create (srv, trans); +if (IS_ERR (conn)) { +P9_EPRINTK (KERN_ERR , +"p9srv_socksrv_accept: cannot create conn %ld\n" , +PTR_ERR (conn)); +return ; + } +}
Signature · 1 line
1.5.2.4