Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a80d923e authored by Eric Van Hensbergen's avatar Eric Van Hensbergen Committed by Eric Van Hensbergen
Browse files

9p: Make transports dynamic



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: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 0eafaae8
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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
@@ -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)

+72 −77
Original line number Diff line number Diff line
@@ -37,18 +37,58 @@
#include "v9fs_vfs.h"

/*
  * Option Parsing (code inspired by NFS code)
 * 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 */
@@ -57,24 +97,13 @@ 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"},
@@ -82,12 +111,6 @@ static match_table_t tokens = {
	{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
@@ -95,23 +118,21 @@ extern struct p9_transport *p9pci_trans_create(void);
 *
 */

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;
@@ -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;
@@ -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]);
@@ -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();
@@ -217,37 +220,28 @@ 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);
	v9ses->options = kstrdup(data, GFP_KERNEL);
	v9fs_parse_options(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;
	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->extended);
@@ -290,6 +284,7 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)

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

/**
@@ -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);
}

+2 −13
Original line number Diff line number Diff line
@@ -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 {
+1 −18
Original line number Diff line number Diff line
@@ -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;
}

+2 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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);
Loading