提交 8b81ef58 编写于 作者: E Eric Van Hensbergen 提交者: Eric Van Hensbergen

9p: consolidate transport structure

Right now there is a transport module structure which provides per-transport
type functions and data and a transport structure which contains per-instance
public data as well as function pointers to instance specific functions.

This patch moves public transport visible instance data to the client
structure (which in some cases had duplicate data) and consolidates the
functions into the transport module structure.
Signed-off-by: NEric Van Hensbergen <ericvh@gmail.com>
上级 992b3f1d
...@@ -30,8 +30,8 @@ ...@@ -30,8 +30,8 @@
#include <linux/parser.h> #include <linux/parser.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <net/9p/9p.h> #include <net/9p/9p.h>
#include <net/9p/transport.h>
#include <net/9p/client.h> #include <net/9p/client.h>
#include <net/9p/transport.h>
#include "v9fs.h" #include "v9fs.h"
#include "v9fs_vfs.h" #include "v9fs_vfs.h"
......
...@@ -26,6 +26,22 @@ ...@@ -26,6 +26,22 @@
#ifndef NET_9P_CLIENT_H #ifndef NET_9P_CLIENT_H
#define NET_9P_CLIENT_H #define NET_9P_CLIENT_H
/**
* enum p9_trans_status - different states of underlying transports
* @Connected: transport is connected and healthy
* @Disconnected: transport has been disconnected
* @Hung: transport is connected by wedged
*
* This enumeration details the various states a transport
* instatiation can be in.
*/
enum p9_trans_status {
Connected,
Disconnected,
Hung,
};
/** /**
* struct p9_client - per client instance state * struct p9_client - per client instance state
* @lock: protect @fidlist * @lock: protect @fidlist
...@@ -48,7 +64,8 @@ struct p9_client { ...@@ -48,7 +64,8 @@ struct p9_client {
int msize; int msize;
unsigned char dotu; unsigned char dotu;
struct p9_trans_module *trans_mod; struct p9_trans_module *trans_mod;
struct p9_trans *trans; enum p9_trans_status status;
void *trans;
struct p9_conn *conn; struct p9_conn *conn;
struct p9_idpool *fidpool; struct p9_idpool *fidpool;
......
...@@ -26,52 +26,6 @@ ...@@ -26,52 +26,6 @@
#ifndef NET_9P_TRANSPORT_H #ifndef NET_9P_TRANSPORT_H
#define NET_9P_TRANSPORT_H #define NET_9P_TRANSPORT_H
#include <linux/module.h>
/**
* enum p9_trans_status - different states of underlying transports
* @Connected: transport is connected and healthy
* @Disconnected: transport has been disconnected
* @Hung: transport is connected by wedged
*
* This enumeration details the various states a transport
* instatiation can be in.
*/
enum p9_trans_status {
Connected,
Disconnected,
Hung,
};
/**
* struct p9_trans - per-transport state and API
* @status: transport &p9_trans_status
* @msize: negotiated maximum packet size (duplicate from client)
* @extended: negotiated protocol extensions (duplicate from client)
* @priv: transport private data
* @close: member function to disconnect and close the transport
* @rpc: member function to issue a request to the transport
*
* This is the basic API for a transport instance. It is used as
* a handle by the client to issue requests. This interface is currently
* in flux during reorganization.
*
* Bugs: there is lots of duplicated data here and its not clear that
* the member functions need to be per-instance versus per transport
* module.
*/
struct p9_trans {
enum p9_trans_status status;
int msize;
unsigned char extended;
void *priv;
void (*close) (struct p9_trans *);
int (*rpc) (struct p9_trans *t, struct p9_fcall *tc,
struct p9_fcall **rc);
};
/** /**
* struct p9_trans_module - transport module interface * struct p9_trans_module - transport module interface
* @list: used to maintain a list of currently available transports * @list: used to maintain a list of currently available transports
...@@ -79,12 +33,14 @@ struct p9_trans { ...@@ -79,12 +33,14 @@ struct p9_trans {
* @maxsize: transport provided maximum packet size * @maxsize: transport provided maximum packet size
* @def: set if this transport should be considered the default * @def: set if this transport should be considered the default
* @create: member function to create a new connection on this transport * @create: member function to create a new connection on this transport
* @close: member function to disconnect and close the transport
* @rpc: member function to issue a request to the transport
* *
* This is the basic API for a transport module which is registered by the * This is the basic API for a transport module which is registered by the
* transport module with the 9P core network module and used by the client * transport module with the 9P core network module and used by the client
* to instantiate a new connection on a transport. * to instantiate a new connection on a transport.
* *
* Bugs: the transport module list isn't protected. * BUGS: the transport module list isn't protected.
*/ */
struct p9_trans_module { struct p9_trans_module {
...@@ -92,8 +48,11 @@ struct p9_trans_module { ...@@ -92,8 +48,11 @@ struct p9_trans_module {
char *name; /* name of transport */ char *name; /* name of transport */
int maxsize; /* max message size of transport */ int maxsize; /* max message size of transport */
int def; /* this transport should be default */ int def; /* this transport should be default */
struct p9_trans * (*create)(const char *, char *, int, unsigned char);
struct module *owner; struct module *owner;
int (*create)(struct p9_client *, const char *, char *);
void (*close) (struct p9_client *);
int (*rpc) (struct p9_client *t, struct p9_fcall *tc,
struct p9_fcall **rc);
}; };
void v9fs_register_trans(struct p9_trans_module *m); void v9fs_register_trans(struct p9_trans_module *m);
......
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <net/9p/9p.h> #include <net/9p/9p.h>
#include <linux/parser.h> #include <linux/parser.h>
#include <net/9p/transport.h>
#include <net/9p/client.h> #include <net/9p/client.h>
#include <net/9p/transport.h>
static struct p9_fid *p9_fid_create(struct p9_client *clnt); static struct p9_fid *p9_fid_create(struct p9_client *clnt);
static void p9_fid_destroy(struct p9_fid *fid); static void p9_fid_destroy(struct p9_fid *fid);
...@@ -136,7 +136,7 @@ int ...@@ -136,7 +136,7 @@ int
p9_client_rpc(struct p9_client *c, struct p9_fcall *tc, p9_client_rpc(struct p9_client *c, struct p9_fcall *tc,
struct p9_fcall **rc) struct p9_fcall **rc)
{ {
return c->trans->rpc(c->trans, tc, rc); return c->trans_mod->rpc(c, tc, rc);
} }
struct p9_client *p9_client_create(const char *dev_name, char *options) struct p9_client *p9_client_create(const char *dev_name, char *options)
...@@ -179,13 +179,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) ...@@ -179,13 +179,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
clnt, clnt->trans_mod, clnt->msize, clnt->dotu); clnt, clnt->trans_mod, clnt->msize, clnt->dotu);
clnt->trans = clnt->trans_mod->create(dev_name, options, clnt->msize, err = clnt->trans_mod->create(clnt, dev_name, options);
clnt->dotu); if (err)
if (IS_ERR(clnt->trans)) {
err = PTR_ERR(clnt->trans);
clnt->trans = NULL;
goto error; goto error;
}
if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
...@@ -233,11 +229,8 @@ void p9_client_destroy(struct p9_client *clnt) ...@@ -233,11 +229,8 @@ void p9_client_destroy(struct p9_client *clnt)
P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
if (clnt->trans) { if (clnt->trans_mod)
clnt->trans->close(clnt->trans); clnt->trans_mod->close(clnt);
kfree(clnt->trans);
clnt->trans = NULL;
}
v9fs_put_trans(clnt->trans_mod); v9fs_put_trans(clnt->trans_mod);
...@@ -254,7 +247,7 @@ EXPORT_SYMBOL(p9_client_destroy); ...@@ -254,7 +247,7 @@ EXPORT_SYMBOL(p9_client_destroy);
void p9_client_disconnect(struct p9_client *clnt) void p9_client_disconnect(struct p9_client *clnt)
{ {
P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt); P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
clnt->trans->status = Disconnected; clnt->status = Disconnected;
} }
EXPORT_SYMBOL(p9_client_disconnect); EXPORT_SYMBOL(p9_client_disconnect);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <net/9p/9p.h> #include <net/9p/9p.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/parser.h> #include <linux/parser.h>
#include <net/9p/client.h>
#include <net/9p/transport.h> #include <net/9p/transport.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/parser.h> #include <linux/parser.h>
#include <net/9p/9p.h> #include <net/9p/9p.h>
#include <net/9p/client.h>
#include <net/9p/transport.h> #include <net/9p/transport.h>
#define P9_PORT 564 #define P9_PORT 564
...@@ -146,7 +147,7 @@ struct p9_poll_wait { ...@@ -146,7 +147,7 @@ struct p9_poll_wait {
* @mux_list: list link for mux to manage multiple connections (?) * @mux_list: list link for mux to manage multiple connections (?)
* @msize: maximum size for connection (dup) * @msize: maximum size for connection (dup)
* @extended: 9p2000.u flag (dup) * @extended: 9p2000.u flag (dup)
* @trans: reference to transport instance for this connection * @client: reference to client instance for this connection
* @tagpool: id accounting for transactions * @tagpool: id accounting for transactions
* @err: error state * @err: error state
* @req_list: accounting for requests which have been sent * @req_list: accounting for requests which have been sent
...@@ -171,7 +172,7 @@ struct p9_conn { ...@@ -171,7 +172,7 @@ struct p9_conn {
struct list_head mux_list; struct list_head mux_list;
int msize; int msize;
unsigned char extended; unsigned char extended;
struct p9_trans *trans; struct p9_client *client;
struct p9_idpool *tagpool; struct p9_idpool *tagpool;
int err; int err;
struct list_head req_list; struct list_head req_list;
...@@ -214,8 +215,8 @@ static void p9_read_work(struct work_struct *work); ...@@ -214,8 +215,8 @@ static void p9_read_work(struct work_struct *work);
static void p9_write_work(struct work_struct *work); static void p9_write_work(struct work_struct *work);
static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
poll_table *p); poll_table *p);
static int p9_fd_write(struct p9_trans *trans, void *v, int len); static int p9_fd_write(struct p9_client *client, void *v, int len);
static int p9_fd_read(struct p9_trans *trans, void *v, int len); static int p9_fd_read(struct p9_client *client, void *v, int len);
static DEFINE_SPINLOCK(p9_poll_lock); static DEFINE_SPINLOCK(p9_poll_lock);
static LIST_HEAD(p9_poll_pending_list); static LIST_HEAD(p9_poll_pending_list);
...@@ -223,7 +224,7 @@ static struct workqueue_struct *p9_mux_wq; ...@@ -223,7 +224,7 @@ static struct workqueue_struct *p9_mux_wq;
static struct task_struct *p9_poll_task; static struct task_struct *p9_poll_task;
static void p9_conn_destroy(struct p9_conn *); static void p9_conn_destroy(struct p9_conn *);
static unsigned int p9_fd_poll(struct p9_trans *trans, static unsigned int p9_fd_poll(struct p9_client *client,
struct poll_table_struct *pt); struct poll_table_struct *pt);
#ifdef P9_NONBLOCK #ifdef P9_NONBLOCK
...@@ -271,27 +272,26 @@ static void p9_mux_poll_stop(struct p9_conn *m) ...@@ -271,27 +272,26 @@ static void p9_mux_poll_stop(struct p9_conn *m)
/** /**
* p9_conn_create - allocate and initialize the per-session mux data * p9_conn_create - allocate and initialize the per-session mux data
* @trans: transport structure * @client: client instance
* *
* Note: Creates the polling task if this is the first session. * Note: Creates the polling task if this is the first session.
*/ */
static struct p9_conn *p9_conn_create(struct p9_trans *trans) static struct p9_conn *p9_conn_create(struct p9_client *client)
{ {
int i, n; int i, n;
struct p9_conn *m; struct p9_conn *m;
P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, P9_DPRINTK(P9_DEBUG_MUX, "client %p msize %d\n", client, client->msize);
trans->msize);
m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL); m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL);
if (!m) if (!m)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
spin_lock_init(&m->lock); spin_lock_init(&m->lock);
INIT_LIST_HEAD(&m->mux_list); INIT_LIST_HEAD(&m->mux_list);
m->msize = trans->msize; m->msize = client->msize;
m->extended = trans->extended; m->extended = client->dotu;
m->trans = trans; m->client = client;
m->tagpool = p9_idpool_create(); m->tagpool = p9_idpool_create();
if (IS_ERR(m->tagpool)) { if (IS_ERR(m->tagpool)) {
kfree(m); kfree(m);
...@@ -305,7 +305,7 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans) ...@@ -305,7 +305,7 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans)
INIT_LIST_HEAD(&m->poll_pending_link); INIT_LIST_HEAD(&m->poll_pending_link);
init_poll_funcptr(&m->pt, p9_pollwait); init_poll_funcptr(&m->pt, p9_pollwait);
n = p9_fd_poll(trans, &m->pt); n = p9_fd_poll(client, &m->pt);
if (n & POLLIN) { if (n & POLLIN) {
P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m); P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
set_bit(Rpending, &m->wsched); set_bit(Rpending, &m->wsched);
...@@ -345,7 +345,7 @@ static void p9_conn_destroy(struct p9_conn *m) ...@@ -345,7 +345,7 @@ static void p9_conn_destroy(struct p9_conn *m)
p9_conn_cancel(m, -ECONNRESET); p9_conn_cancel(m, -ECONNRESET);
m->trans = NULL; m->client = NULL;
p9_idpool_destroy(m->tagpool); p9_idpool_destroy(m->tagpool);
kfree(m); kfree(m);
} }
...@@ -420,7 +420,7 @@ static void p9_poll_mux(struct p9_conn *m) ...@@ -420,7 +420,7 @@ static void p9_poll_mux(struct p9_conn *m)
if (m->err < 0) if (m->err < 0)
return; return;
n = p9_fd_poll(m->trans, NULL); n = p9_fd_poll(m->client, NULL);
if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n); P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
if (n >= 0) if (n >= 0)
...@@ -533,7 +533,7 @@ static void p9_write_work(struct work_struct *work) ...@@ -533,7 +533,7 @@ static void p9_write_work(struct work_struct *work)
P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
m->wsize); m->wsize);
clear_bit(Wpending, &m->wsched); clear_bit(Wpending, &m->wsched);
err = p9_fd_write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos); err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err); P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
if (err == -EAGAIN) { if (err == -EAGAIN) {
clear_bit(Wworksched, &m->wsched); clear_bit(Wworksched, &m->wsched);
...@@ -555,7 +555,7 @@ static void p9_write_work(struct work_struct *work) ...@@ -555,7 +555,7 @@ static void p9_write_work(struct work_struct *work)
if (test_and_clear_bit(Wpending, &m->wsched)) if (test_and_clear_bit(Wpending, &m->wsched))
n = POLLOUT; n = POLLOUT;
else else
n = p9_fd_poll(m->trans, NULL); n = p9_fd_poll(m->client, NULL);
if (n & POLLOUT) { if (n & POLLOUT) {
P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m); P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
...@@ -640,7 +640,7 @@ static void p9_read_work(struct work_struct *work) ...@@ -640,7 +640,7 @@ static void p9_read_work(struct work_struct *work)
} }
clear_bit(Rpending, &m->wsched); clear_bit(Rpending, &m->wsched);
err = p9_fd_read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos); err = p9_fd_read(m->client, m->rbuf + m->rpos, m->msize - m->rpos);
P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err); P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err);
if (err == -EAGAIN) { if (err == -EAGAIN) {
clear_bit(Rworksched, &m->wsched); clear_bit(Rworksched, &m->wsched);
...@@ -735,7 +735,7 @@ static void p9_read_work(struct work_struct *work) ...@@ -735,7 +735,7 @@ static void p9_read_work(struct work_struct *work)
if (test_and_clear_bit(Rpending, &m->wsched)) if (test_and_clear_bit(Rpending, &m->wsched))
n = POLLIN; n = POLLIN;
else else
n = p9_fd_poll(m->trans, NULL); n = p9_fd_poll(m->client, NULL);
if (n & POLLIN) { if (n & POLLIN) {
P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m); P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
...@@ -819,7 +819,7 @@ static struct p9_req *p9_send_request(struct p9_conn *m, ...@@ -819,7 +819,7 @@ static struct p9_req *p9_send_request(struct p9_conn *m,
if (test_and_clear_bit(Wpending, &m->wsched)) if (test_and_clear_bit(Wpending, &m->wsched))
n = POLLOUT; n = POLLOUT;
else else
n = p9_fd_poll(m->trans, NULL); n = p9_fd_poll(m->client, NULL);
if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
queue_work(p9_mux_wq, &m->wq); queue_work(p9_mux_wq, &m->wq);
...@@ -933,16 +933,16 @@ p9_conn_rpc_cb(struct p9_req *req, void *a) ...@@ -933,16 +933,16 @@ p9_conn_rpc_cb(struct p9_req *req, void *a)
/** /**
* p9_fd_rpc- sends 9P request and waits until a response is available. * p9_fd_rpc- sends 9P request and waits until a response is available.
* The function can be interrupted. * The function can be interrupted.
* @t: transport data * @client: client instance
* @tc: request to be sent * @tc: request to be sent
* @rc: pointer where a pointer to the response is stored * @rc: pointer where a pointer to the response is stored
* *
*/ */
int int
p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) p9_fd_rpc(struct p9_client *client, struct p9_fcall *tc, struct p9_fcall **rc)
{ {
struct p9_trans_fd *p = t->priv; struct p9_trans_fd *p = client->trans;
struct p9_conn *m = p->conn; struct p9_conn *m = p->conn;
int err, sigpending; int err, sigpending;
unsigned long flags; unsigned long flags;
...@@ -975,7 +975,7 @@ p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) ...@@ -975,7 +975,7 @@ p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
if (r.err < 0) if (r.err < 0)
err = r.err; err = r.err;
if (err == -ERESTARTSYS && m->trans->status == Connected if (err == -ERESTARTSYS && client->status == Connected
&& m->err == 0) { && m->err == 0) {
if (p9_mux_flush_request(m, req)) { if (p9_mux_flush_request(m, req)) {
/* wait until we get response of the flush message */ /* wait until we get response of the flush message */
...@@ -984,7 +984,7 @@ p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) ...@@ -984,7 +984,7 @@ p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
err = wait_event_interruptible(r.wqueue, err = wait_event_interruptible(r.wqueue,
r.rcall || r.err); r.rcall || r.err);
} while (!r.rcall && !r.err && err == -ERESTARTSYS && } while (!r.rcall && !r.err && err == -ERESTARTSYS &&
m->trans->status == Connected && !m->err); client->status == Connected && !m->err);
err = -ERESTARTSYS; err = -ERESTARTSYS;
} }
...@@ -1133,7 +1133,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) ...@@ -1133,7 +1133,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
return 0; return 0;
} }
static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd) static int p9_fd_open(struct p9_client *client, int rfd, int wfd)
{ {
struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
GFP_KERNEL); GFP_KERNEL);
...@@ -1151,13 +1151,13 @@ static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd) ...@@ -1151,13 +1151,13 @@ static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd)
return -EIO; return -EIO;
} }
trans->priv = ts; client->trans = ts;
trans->status = Connected; client->status = Connected;
return 0; return 0;
} }
static int p9_socket_open(struct p9_trans *trans, struct socket *csocket) static int p9_socket_open(struct p9_client *client, struct socket *csocket)
{ {
int fd, ret; int fd, ret;
...@@ -1168,33 +1168,33 @@ static int p9_socket_open(struct p9_trans *trans, struct socket *csocket) ...@@ -1168,33 +1168,33 @@ static int p9_socket_open(struct p9_trans *trans, struct socket *csocket)
return fd; return fd;
} }
ret = p9_fd_open(trans, fd, fd); ret = p9_fd_open(client, fd, fd);
if (ret < 0) { if (ret < 0) {
P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n"); P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
sockfd_put(csocket); sockfd_put(csocket);
return ret; return ret;
} }
((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK; ((struct p9_trans_fd *)client->trans)->rd->f_flags |= O_NONBLOCK;
return 0; return 0;
} }
/** /**
* p9_fd_read- read from a fd * p9_fd_read- read from a fd
* @trans: transport instance state * @client: client instance
* @v: buffer to receive data into * @v: buffer to receive data into
* @len: size of receive buffer * @len: size of receive buffer
* *
*/ */
static int p9_fd_read(struct p9_trans *trans, void *v, int len) static int p9_fd_read(struct p9_client *client, void *v, int len)
{ {
int ret; int ret;
struct p9_trans_fd *ts = NULL; struct p9_trans_fd *ts = NULL;
if (trans && trans->status != Disconnected) if (client && client->status != Disconnected)
ts = trans->priv; ts = client->trans;
if (!ts) if (!ts)
return -EREMOTEIO; return -EREMOTEIO;
...@@ -1204,26 +1204,26 @@ static int p9_fd_read(struct p9_trans *trans, void *v, int len) ...@@ -1204,26 +1204,26 @@ static int p9_fd_read(struct p9_trans *trans, void *v, int len)
ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
trans->status = Disconnected; client->status = Disconnected;
return ret; return ret;
} }
/** /**
* p9_fd_write - write to a socket * p9_fd_write - write to a socket
* @trans: transport instance state * @client: client instance
* @v: buffer to send data from * @v: buffer to send data from
* @len: size of send buffer * @len: size of send buffer
* *
*/ */
static int p9_fd_write(struct p9_trans *trans, void *v, int len) static int p9_fd_write(struct p9_client *client, void *v, int len)
{ {
int ret; int ret;
mm_segment_t oldfs; mm_segment_t oldfs;
struct p9_trans_fd *ts = NULL; struct p9_trans_fd *ts = NULL;
if (trans && trans->status != Disconnected) if (client && client->status != Disconnected)
ts = trans->priv; ts = client->trans;
if (!ts) if (!ts)
return -EREMOTEIO; return -EREMOTEIO;
...@@ -1238,18 +1238,18 @@ static int p9_fd_write(struct p9_trans *trans, void *v, int len) ...@@ -1238,18 +1238,18 @@ static int p9_fd_write(struct p9_trans *trans, void *v, int len)
set_fs(oldfs); set_fs(oldfs);
if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
trans->status = Disconnected; client->status = Disconnected;
return ret; return ret;
} }
static unsigned int static unsigned int
p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt)
{ {
int ret, n; int ret, n;
struct p9_trans_fd *ts = NULL; struct p9_trans_fd *ts = NULL;
if (trans && trans->status == Connected) if (client && client->status == Connected)
ts = trans->priv; ts = client->trans;
if (!ts) if (!ts)
return -EREMOTEIO; return -EREMOTEIO;
...@@ -1275,30 +1275,31 @@ p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) ...@@ -1275,30 +1275,31 @@ p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt)
} }
/** /**
* p9_fd_close - shutdown socket * p9_fd_close - shutdown file descriptor transport
* @trans: private socket structure * @client: client instance
* *
*/ */
static void p9_fd_close(struct p9_trans *trans) static void p9_fd_close(struct p9_client *client)
{ {
struct p9_trans_fd *ts; struct p9_trans_fd *ts;
if (!trans) if (!client)
return; return;
ts = xchg(&trans->priv, NULL); ts = client->trans;
if (!ts) if (!ts)
return; return;
client->status = Disconnected;
p9_conn_destroy(ts->conn); p9_conn_destroy(ts->conn);
trans->status = Disconnected;
if (ts->rd) if (ts->rd)
fput(ts->rd); fput(ts->rd);
if (ts->wr) if (ts->wr)
fput(ts->wr); fput(ts->wr);
kfree(ts); kfree(ts);
} }
...@@ -1319,31 +1320,23 @@ static inline int valid_ipaddr4(const char *buf) ...@@ -1319,31 +1320,23 @@ static inline int valid_ipaddr4(const char *buf)
return 0; return 0;
} }
static struct p9_trans * static int
p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args)
{ {
int err; int err;
struct p9_trans *trans;
struct socket *csocket; struct socket *csocket;
struct sockaddr_in sin_server; struct sockaddr_in sin_server;
struct p9_fd_opts opts; struct p9_fd_opts opts;
struct p9_trans_fd *p; struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
err = parse_opts(args, &opts); err = parse_opts(args, &opts);
if (err < 0) if (err < 0)
return ERR_PTR(err); return err;
if (valid_ipaddr4(addr) < 0) if (valid_ipaddr4(addr) < 0)
return ERR_PTR(-EINVAL); return -EINVAL;
csocket = NULL; csocket = NULL;
trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
if (!trans)
return ERR_PTR(-ENOMEM);
trans->msize = msize;
trans->extended = dotu;
trans->rpc = p9_fd_rpc;
trans->close = p9_fd_close;
sin_server.sin_family = AF_INET; sin_server.sin_family = AF_INET;
sin_server.sin_addr.s_addr = in_aton(addr); sin_server.sin_addr.s_addr = in_aton(addr);
...@@ -1366,45 +1359,38 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) ...@@ -1366,45 +1359,38 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
goto error; goto error;
} }
err = p9_socket_open(trans, csocket); err = p9_socket_open(client, csocket);
if (err < 0) if (err < 0)
goto error; goto error;
p = (struct p9_trans_fd *) trans->priv; p = (struct p9_trans_fd *) client->trans;
p->conn = p9_conn_create(trans); p->conn = p9_conn_create(client);
if (IS_ERR(p->conn)) { if (IS_ERR(p->conn)) {
err = PTR_ERR(p->conn); err = PTR_ERR(p->conn);
p->conn = NULL; p->conn = NULL;
goto error; goto error;
} }
return trans; return 0;
error: error:
if (csocket) if (csocket)
sock_release(csocket); sock_release(csocket);
kfree(trans); kfree(p);
return ERR_PTR(err);
return err;
} }
static struct p9_trans * static int
p9_trans_create_unix(const char *addr, char *args, int msize, p9_fd_create_unix(struct p9_client *client, const char *addr, char *args)
unsigned char dotu)
{ {
int err; int err;
struct socket *csocket; struct socket *csocket;
struct sockaddr_un sun_server; struct sockaddr_un sun_server;
struct p9_trans *trans; struct p9_trans_fd *p = NULL; /* this gets allocated in p9_fd_open */
struct p9_trans_fd *p;
csocket = NULL; csocket = NULL;
trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
if (!trans)
return ERR_PTR(-ENOMEM);
trans->rpc = p9_fd_rpc;
trans->close = p9_fd_close;
if (strlen(addr) > UNIX_PATH_MAX) { if (strlen(addr) > UNIX_PATH_MAX) {
P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n", P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
...@@ -1425,79 +1411,68 @@ p9_trans_create_unix(const char *addr, char *args, int msize, ...@@ -1425,79 +1411,68 @@ p9_trans_create_unix(const char *addr, char *args, int msize,
goto error; goto error;
} }
err = p9_socket_open(trans, csocket); err = p9_socket_open(client, csocket);
if (err < 0) if (err < 0)
goto error; goto error;
trans->msize = msize; p = (struct p9_trans_fd *) client->trans;
trans->extended = dotu; p->conn = p9_conn_create(client);
p = (struct p9_trans_fd *) trans->priv;
p->conn = p9_conn_create(trans);
if (IS_ERR(p->conn)) { if (IS_ERR(p->conn)) {
err = PTR_ERR(p->conn); err = PTR_ERR(p->conn);
p->conn = NULL; p->conn = NULL;
goto error; goto error;
} }
return trans; return 0;
error: error:
if (csocket) if (csocket)
sock_release(csocket); sock_release(csocket);
kfree(trans); kfree(p);
return ERR_PTR(err); return err;
} }
static struct p9_trans * static int
p9_trans_create_fd(const char *name, char *args, int msize, p9_fd_create(struct p9_client *client, const char *addr, char *args)
unsigned char extended)
{ {
int err; int err;
struct p9_trans *trans;
struct p9_fd_opts opts; struct p9_fd_opts opts;
struct p9_trans_fd *p; struct p9_trans_fd *p = NULL; /* this get allocated in p9_fd_open */
parse_opts(args, &opts); parse_opts(args, &opts);
if (opts.rfd == ~0 || opts.wfd == ~0) { if (opts.rfd == ~0 || opts.wfd == ~0) {
printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n"); printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
return ERR_PTR(-ENOPROTOOPT); return -ENOPROTOOPT;
} }
trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); err = p9_fd_open(client, opts.rfd, opts.wfd);
if (!trans)
return ERR_PTR(-ENOMEM);
trans->rpc = p9_fd_rpc;
trans->close = p9_fd_close;
err = p9_fd_open(trans, opts.rfd, opts.wfd);
if (err < 0) if (err < 0)
goto error; goto error;
trans->msize = msize; p = (struct p9_trans_fd *) client->trans;
trans->extended = extended; p->conn = p9_conn_create(client);
p = (struct p9_trans_fd *) trans->priv;
p->conn = p9_conn_create(trans);
if (IS_ERR(p->conn)) { if (IS_ERR(p->conn)) {
err = PTR_ERR(p->conn); err = PTR_ERR(p->conn);
p->conn = NULL; p->conn = NULL;
goto error; goto error;
} }
return trans; return 0;
error: error:
kfree(trans); kfree(p);
return ERR_PTR(err); return err;
} }
static struct p9_trans_module p9_tcp_trans = { static struct p9_trans_module p9_tcp_trans = {
.name = "tcp", .name = "tcp",
.maxsize = MAX_SOCK_BUF, .maxsize = MAX_SOCK_BUF,
.def = 1, .def = 1,
.create = p9_trans_create_tcp, .create = p9_fd_create_tcp,
.close = p9_fd_close,
.rpc = p9_fd_rpc,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
...@@ -1505,7 +1480,9 @@ static struct p9_trans_module p9_unix_trans = { ...@@ -1505,7 +1480,9 @@ static struct p9_trans_module p9_unix_trans = {
.name = "unix", .name = "unix",
.maxsize = MAX_SOCK_BUF, .maxsize = MAX_SOCK_BUF,
.def = 0, .def = 0,
.create = p9_trans_create_unix, .create = p9_fd_create_unix,
.close = p9_fd_close,
.rpc = p9_fd_rpc,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
...@@ -1513,7 +1490,9 @@ static struct p9_trans_module p9_fd_trans = { ...@@ -1513,7 +1490,9 @@ static struct p9_trans_module p9_fd_trans = {
.name = "fd", .name = "fd",
.maxsize = MAX_SOCK_BUF, .maxsize = MAX_SOCK_BUF,
.def = 0, .def = 0,
.create = p9_trans_create_fd, .create = p9_fd_create,
.close = p9_fd_close,
.rpc = p9_fd_rpc,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/file.h> #include <linux/file.h>
#include <net/9p/9p.h> #include <net/9p/9p.h>
#include <linux/parser.h> #include <linux/parser.h>
#include <net/9p/client.h>
#include <net/9p/transport.h> #include <net/9p/transport.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/virtio.h> #include <linux/virtio.h>
...@@ -55,7 +56,6 @@ static int chan_index; ...@@ -55,7 +56,6 @@ static int chan_index;
#define P9_INIT_MAXTAG 16 #define P9_INIT_MAXTAG 16
/** /**
* enum p9_req_status_t - virtio request status * enum p9_req_status_t - virtio request status
* @REQ_STATUS_IDLE: request slot unused * @REQ_STATUS_IDLE: request slot unused
...@@ -197,9 +197,9 @@ static unsigned int rest_of_page(void *data) ...@@ -197,9 +197,9 @@ static unsigned int rest_of_page(void *data)
* *
*/ */
static void p9_virtio_close(struct p9_trans *trans) static void p9_virtio_close(struct p9_client *client)
{ {
struct virtio_chan *chan = trans->priv; struct virtio_chan *chan = client->trans;
int count; int count;
unsigned long flags; unsigned long flags;
...@@ -215,7 +215,7 @@ static void p9_virtio_close(struct p9_trans *trans) ...@@ -215,7 +215,7 @@ static void p9_virtio_close(struct p9_trans *trans)
chan->inuse = false; chan->inuse = false;
mutex_unlock(&virtio_9p_lock); mutex_unlock(&virtio_9p_lock);
kfree(trans); client->trans = NULL;
} }
/** /**
...@@ -292,17 +292,17 @@ pack_sg_list(struct scatterlist *sg, int start, int limit, char *data, ...@@ -292,17 +292,17 @@ pack_sg_list(struct scatterlist *sg, int start, int limit, char *data,
*/ */
static int static int
p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) p9_virtio_rpc(struct p9_client *c, struct p9_fcall *tc, struct p9_fcall **rc)
{ {
int in, out; int in, out;
int n, err, size; int n, err, size;
struct virtio_chan *chan = t->priv; struct virtio_chan *chan = c->trans;
char *rdata; char *rdata;
struct p9_req_t *req; struct p9_req_t *req;
unsigned long flags; unsigned long flags;
if (*rc == NULL) { if (*rc == NULL) {
*rc = kmalloc(sizeof(struct p9_fcall) + t->msize, GFP_KERNEL); *rc = kmalloc(sizeof(struct p9_fcall) + c->msize, GFP_KERNEL);
if (!*rc) if (!*rc)
return -ENOMEM; return -ENOMEM;
} }
...@@ -325,7 +325,7 @@ p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) ...@@ -325,7 +325,7 @@ p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio rpc tag %d\n", n); P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio rpc tag %d\n", n);
out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, tc->sdata, tc->size); out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, tc->sdata, tc->size);
in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, t->msize); in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata, c->msize);
req->status = REQ_STATUS_SENT; req->status = REQ_STATUS_SENT;
...@@ -341,7 +341,7 @@ p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) ...@@ -341,7 +341,7 @@ p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
size = le32_to_cpu(*(__le32 *) rdata); size = le32_to_cpu(*(__le32 *) rdata);
err = p9_deserialize_fcall(rdata, size, *rc, t->extended); err = p9_deserialize_fcall(rdata, size, *rc, c->dotu);
if (err < 0) { if (err < 0) {
P9_DPRINTK(P9_DEBUG_TRANS, P9_DPRINTK(P9_DEBUG_TRANS,
"9p debug: virtio rpc deserialize returned %d\n", err); "9p debug: virtio rpc deserialize returned %d\n", err);
...@@ -352,8 +352,8 @@ p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) ...@@ -352,8 +352,8 @@ p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc)
if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) { if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
char buf[150]; char buf[150];
p9_printfcall(buf, sizeof(buf), *rc, t->extended); p9_printfcall(buf, sizeof(buf), *rc, c->dotu);
printk(KERN_NOTICE ">>> %p %s\n", t, buf); printk(KERN_NOTICE ">>> %p %s\n", c, buf);
} }
#endif #endif
...@@ -422,10 +422,9 @@ static int p9_virtio_probe(struct virtio_device *vdev) ...@@ -422,10 +422,9 @@ static int p9_virtio_probe(struct virtio_device *vdev)
/** /**
* p9_virtio_create - allocate a new virtio channel * p9_virtio_create - allocate a new virtio channel
* @client: client instance invoking this transport
* @devname: string identifying the channel to connect to (unused) * @devname: string identifying the channel to connect to (unused)
* @args: args passed from sys_mount() for per-transport options (unused) * @args: args passed from sys_mount() for per-transport options (unused)
* @msize: requested maximum packet size
* @extended: 9p2000.u enabled flag
* *
* This sets up a transport channel for 9p communication. Right now * This sets up a transport channel for 9p communication. Right now
* we only match the first available channel, but eventually we couldlook up * we only match the first available channel, but eventually we couldlook up
...@@ -441,11 +440,9 @@ static int p9_virtio_probe(struct virtio_device *vdev) ...@@ -441,11 +440,9 @@ static int p9_virtio_probe(struct virtio_device *vdev)
* *
*/ */
static struct p9_trans * static int
p9_virtio_create(const char *devname, char *args, int msize, p9_virtio_create(struct p9_client *client, const char *devname, char *args)
unsigned char extended)
{ {
struct p9_trans *trans;
struct virtio_chan *chan = channels; struct virtio_chan *chan = channels;
int index = 0; int index = 0;
...@@ -463,30 +460,21 @@ p9_virtio_create(const char *devname, char *args, int msize, ...@@ -463,30 +460,21 @@ p9_virtio_create(const char *devname, char *args, int msize,
if (index >= MAX_9P_CHAN) { if (index >= MAX_9P_CHAN) {
printk(KERN_ERR "9p: no channels available\n"); printk(KERN_ERR "9p: no channels available\n");
return ERR_PTR(-ENODEV); return -ENODEV;
} }
chan->tagpool = p9_idpool_create(); chan->tagpool = p9_idpool_create();
if (IS_ERR(chan->tagpool)) { if (IS_ERR(chan->tagpool)) {
printk(KERN_ERR "9p: couldn't allocate tagpool\n"); printk(KERN_ERR "9p: couldn't allocate tagpool\n");
return ERR_PTR(-ENOMEM); return -ENOMEM;
} }
p9_idpool_get(chan->tagpool); /* reserve tag 0 */ p9_idpool_get(chan->tagpool); /* reserve tag 0 */
chan->max_tag = 0; chan->max_tag = 0;
chan->reqs = NULL; chan->reqs = NULL;
trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); client->trans = (void *)chan;
if (!trans) {
printk(KERN_ERR "9p: couldn't allocate transport\n");
return ERR_PTR(-ENOMEM);
}
trans->extended = extended;
trans->msize = msize;
trans->close = p9_virtio_close;
trans->rpc = p9_virtio_rpc;
trans->priv = chan;
return trans; return 0;
} }
/** /**
...@@ -526,6 +514,8 @@ static struct virtio_driver p9_virtio_drv = { ...@@ -526,6 +514,8 @@ static struct virtio_driver p9_virtio_drv = {
static struct p9_trans_module p9_virtio_trans = { static struct p9_trans_module p9_virtio_trans = {
.name = "virtio", .name = "virtio",
.create = p9_virtio_create, .create = p9_virtio_create,
.close = p9_virtio_close,
.rpc = p9_virtio_rpc,
.maxsize = PAGE_SIZE*16, .maxsize = PAGE_SIZE*16,
.def = 0, .def = 0,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册