Skip to content

Commit

Permalink
9p: Make transports dynamic
Browse files Browse the repository at this point in the history
This patch abstracts out the interfaces to underlying transports so that
new transports can be added as modules.  This should also allow kernel
configuration of transports without ifdef-hell.

Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
  • Loading branch information
Eric Van Hensbergen authored and Eric Van Hensbergen committed Oct 17, 2007
1 parent 0eafaae commit a80d923
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 285 deletions.
8 changes: 4 additions & 4 deletions Documentation/filesystems/9p.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ For remote file server:

For Plan 9 From User Space applications (http://swtch.com/plan9)

mount -t 9p `namespace`/acme /mnt/9 -o proto=unix,uname=$USER
mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER

OPTIONS
=======

proto=name select an alternative transport. Valid options are
trans=name select an alternative transport. Valid options are
currently:
unix - specifying a named pipe mount point
tcp - specifying a normal TCP/IP connection
Expand Down Expand Up @@ -68,9 +68,9 @@ OPTIONS
0x40 = display transport debug
0x80 = display allocation debug

rfdno=n the file descriptor for reading with proto=fd
rfdno=n the file descriptor for reading with trans=fd

wfdno=n the file descriptor for writing with proto=fd
wfdno=n the file descriptor for writing with trans=fd

maxdata=n the number of bytes to use for 9p packet payload (msize)

Expand Down
149 changes: 72 additions & 77 deletions fs/9p/v9fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,59 @@
#include "v9fs.h"
#include "v9fs_vfs.h"

/*
* Dynamic Transport Registration Routines
*
*/

static LIST_HEAD(v9fs_trans_list);
static struct p9_trans_module *v9fs_default_trans;

/**
* v9fs_register_trans - register a new transport with 9p
* @m - structure describing the transport module and entry points
*
*/
void v9fs_register_trans(struct p9_trans_module *m)
{
list_add_tail(&m->list, &v9fs_trans_list);
if (m->def)
v9fs_default_trans = m;
}
EXPORT_SYMBOL(v9fs_register_trans);

/**
* v9fs_match_trans - match transport versus registered transports
* @arg: string identifying transport
*
*/
static struct p9_trans_module *v9fs_match_trans(const substring_t *name)
{
struct list_head *p;
struct p9_trans_module *t = NULL;

list_for_each(p, &v9fs_trans_list) {
t = list_entry(p, struct p9_trans_module, list);
if (strncmp(t->name, name->from, name->to-name->from) == 0) {
P9_DPRINTK(P9_DEBUG_TRANS, "trans=%s\n", t->name);
break;
}
}
return t;
}

/*
* Option Parsing (code inspired by NFS code)
*
* NOTE: each transport will parse its own options
*/

enum {
/* Options that take integer arguments */
Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid,
Opt_rfdno, Opt_wfdno,
Opt_debug, Opt_msize, Opt_uid, Opt_gid, Opt_afid,
/* String options */
Opt_uname, Opt_remotename,
Opt_uname, Opt_remotename, Opt_trans,
/* Options that take no arguments */
Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci,
Opt_legacy, Opt_nodevmap,
/* Cache options */
Opt_cache_loose,
/* Error token */
Expand All @@ -57,61 +97,42 @@ enum {

static match_table_t tokens = {
{Opt_debug, "debug=%x"},
{Opt_port, "port=%u"},
{Opt_msize, "msize=%u"},
{Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
{Opt_afid, "afid=%u"},
{Opt_rfdno, "rfdno=%u"},
{Opt_wfdno, "wfdno=%u"},
{Opt_uname, "uname=%s"},
{Opt_remotename, "aname=%s"},
{Opt_unix, "proto=unix"},
{Opt_tcp, "proto=tcp"},
{Opt_fd, "proto=fd"},
#ifdef CONFIG_PCI_9P
{Opt_pci, "proto=pci"},
#endif
{Opt_tcp, "tcp"},
{Opt_unix, "unix"},
{Opt_fd, "fd"},
{Opt_trans, "trans=%s"},
{Opt_legacy, "noextend"},
{Opt_nodevmap, "nodevmap"},
{Opt_cache_loose, "cache=loose"},
{Opt_cache_loose, "loose"},
{Opt_err, NULL}
};

extern struct p9_transport *p9pci_trans_create(void);

/*
* Parse option string.
*/

/**
* v9fs_parse_options - parse mount options into session structure
* @options: options string passed from mount
* @v9ses: existing v9fs session information
*
*/

static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
static void v9fs_parse_options(struct v9fs_session_info *v9ses)
{
char *p;
char *options = v9ses->options;
substring_t args[MAX_OPT_ARGS];
char *p;
int option;
int ret;

/* setup defaults */
v9ses->port = V9FS_PORT;
v9ses->maxdata = 9000;
v9ses->proto = PROTO_TCP;
v9ses->maxdata = 8192;
v9ses->extended = 1;
v9ses->afid = ~0;
v9ses->debug = 0;
v9ses->rfdno = ~0;
v9ses->wfdno = ~0;
v9ses->cache = 0;
v9ses->trans = v9fs_default_trans;

if (!options)
return;
Expand All @@ -135,9 +156,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
p9_debug_level = option;
#endif
break;
case Opt_port:
v9ses->port = option;
break;
case Opt_msize:
v9ses->maxdata = option;
break;
Expand All @@ -150,23 +168,8 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
case Opt_afid:
v9ses->afid = option;
break;
case Opt_rfdno:
v9ses->rfdno = option;
break;
case Opt_wfdno:
v9ses->wfdno = option;
break;
case Opt_tcp:
v9ses->proto = PROTO_TCP;
break;
case Opt_unix:
v9ses->proto = PROTO_UNIX;
break;
case Opt_pci:
v9ses->proto = PROTO_PCI;
break;
case Opt_fd:
v9ses->proto = PROTO_FD;
case Opt_trans:
v9ses->trans = v9fs_match_trans(&args[0]);
break;
case Opt_uname:
match_strcpy(v9ses->name, &args[0]);
Expand Down Expand Up @@ -201,7 +204,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
const char *dev_name, char *data)
{
int retval = -EINVAL;
struct p9_transport *trans;
struct p9_trans *trans = NULL;
struct p9_fid *fid;

v9ses->name = __getname();
Expand All @@ -217,39 +220,30 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
strcpy(v9ses->name, V9FS_DEFUSER);
strcpy(v9ses->remotename, V9FS_DEFANAME);

v9fs_parse_options(data, v9ses);

switch (v9ses->proto) {
case PROTO_TCP:
trans = p9_trans_create_tcp(dev_name, v9ses->port);
break;
case PROTO_UNIX:
trans = p9_trans_create_unix(dev_name);
*v9ses->remotename = 0;
break;
case PROTO_FD:
trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno);
*v9ses->remotename = 0;
break;
#ifdef CONFIG_PCI_9P
case PROTO_PCI:
trans = p9pci_trans_create();
*v9ses->remotename = 0;
break;
#endif
default:
printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
retval = -ENOPROTOOPT;
v9ses->options = kstrdup(data, GFP_KERNEL);
v9fs_parse_options(v9ses);

if ((v9ses->trans == NULL) && !list_empty(&v9fs_trans_list))
v9ses->trans = list_first_entry(&v9fs_trans_list,
struct p9_trans_module, list);

if (v9ses->trans == NULL) {
retval = -EPROTONOSUPPORT;
P9_DPRINTK(P9_DEBUG_ERROR,
"No transport defined or default transport\n");
goto error;
};
}

trans = v9ses->trans->create(dev_name, v9ses->options);
if (IS_ERR(trans)) {
retval = PTR_ERR(trans);
trans = NULL;
goto error;
}
if ((v9ses->maxdata+P9_IOHDRSZ) > v9ses->trans->maxsize)
v9ses->maxdata = v9ses->trans->maxsize-P9_IOHDRSZ;

v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ,
v9ses->clnt = p9_client_create(trans, v9ses->maxdata+P9_IOHDRSZ,
v9ses->extended);

if (IS_ERR(v9ses->clnt)) {
Expand Down Expand Up @@ -290,6 +284,7 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)

__putname(v9ses->name);
__putname(v9ses->remotename);
kfree(v9ses->options);
}

/**
Expand All @@ -311,7 +306,7 @@ extern int v9fs_error_init(void);
static int __init init_v9fs(void)
{
printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");

/* TODO: Setup list of registered trasnport modules */
return register_filesystem(&v9fs_fs_type);
}

Expand Down
15 changes: 2 additions & 13 deletions fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,20 @@ struct v9fs_session_info {
unsigned int maxdata;
unsigned char extended; /* set to 1 if we are using UNIX extensions */
unsigned char nodev; /* set to 1 if no disable device mapping */
unsigned short port; /* port to connect to */
unsigned short debug; /* debug level */
unsigned short proto; /* protocol to use */
unsigned int afid; /* authentication fid */
unsigned int rfdno; /* read file descriptor number */
unsigned int wfdno; /* write file descriptor number */
unsigned int cache; /* cache mode */

char *options; /* copy of mount options */
char *name; /* user name to mount as */
char *remotename; /* name of remote hierarchy being mounted */
unsigned int uid; /* default uid/muid for legacy support */
unsigned int gid; /* default gid for legacy support */

struct p9_trans_module *trans; /* 9p transport */
struct p9_client *clnt; /* 9p client */
struct dentry *debugfs_dir;
};

/* possible values of ->proto */
enum {
PROTO_TCP,
PROTO_UNIX,
PROTO_FD,
PROTO_PCI,
};

/* possible values of ->cache */
/* eventually support loose, tight, time, session, default always none */
enum {
Expand Down
19 changes: 1 addition & 18 deletions fs/9p/vfs_super.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,24 +216,7 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
{
struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;

if (v9ses->debug != 0)
seq_printf(m, ",debug=%x", v9ses->debug);
if (v9ses->port != V9FS_PORT)
seq_printf(m, ",port=%u", v9ses->port);
if (v9ses->maxdata != 9000)
seq_printf(m, ",msize=%u", v9ses->maxdata);
if (v9ses->afid != ~0)
seq_printf(m, ",afid=%u", v9ses->afid);
if (v9ses->proto == PROTO_UNIX)
seq_puts(m, ",proto=unix");
if (v9ses->extended == 0)
seq_puts(m, ",noextend");
if (v9ses->nodev == 1)
seq_puts(m, ",nodevmap");
seq_printf(m, ",name=%s", v9ses->name);
seq_printf(m, ",aname=%s", v9ses->remotename);
seq_printf(m, ",uid=%u", v9ses->uid);
seq_printf(m, ",gid=%u", v9ses->gid);
seq_printf(m, "%s", v9ses->options);
return 0;
}

Expand Down
4 changes: 2 additions & 2 deletions include/net/9p/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct p9_client {
spinlock_t lock; /* protect client structure */
int msize;
unsigned char dotu;
struct p9_transport *trans;
struct p9_trans *trans;
struct p9_conn *conn;

struct p9_idpool *fidpool;
Expand All @@ -52,7 +52,7 @@ struct p9_fid {
struct list_head dlist; /* list of all fids attached to a dentry */
};

struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
struct p9_client *p9_client_create(struct p9_trans *trans, int msize,
int dotu);
void p9_client_destroy(struct p9_client *clnt);
void p9_client_disconnect(struct p9_client *clnt);
Expand Down
4 changes: 2 additions & 2 deletions include/net/9p/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ struct p9_req;
*/
typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a);

struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
unsigned char *dotu);
struct p9_conn *p9_conn_create(struct p9_trans *trans, int msize,
unsigned char *dotu);
void p9_conn_destroy(struct p9_conn *);
int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc);

Expand Down
Loading

0 comments on commit a80d923

Please sign in to comment.