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

Commit bd238fb4 authored by Latchesar Ionkov's avatar Latchesar Ionkov Committed by Eric Van Hensbergen
Browse files

9p: Reorganization of 9p file system code



This patchset moves non-filesystem interfaces of v9fs from fs/9p to net/9p.
It moves the transport, packet marshalling and connection layers to net/9p
leaving only the VFS related files in fs/9p.  This work is being done in
preparation for in-kernel 9p servers as well as alternate 9p clients (other
than VFS).

Signed-off-by: default avatarLatchesar Ionkov <lucho@ionkov.net>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 8d9107e8
Loading
Loading
Loading
Loading

fs/9p/9p.h

deleted100644 → 0
+0 −375
Original line number Original line Diff line number Diff line
/*
 * linux/fs/9p/9p.h
 *
 * 9P protocol definitions.
 *
 *  Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
 *
 *  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
 *
 */

/* Message Types */
enum {
	TVERSION = 100,
	RVERSION,
	TAUTH = 102,
	RAUTH,
	TATTACH = 104,
	RATTACH,
	TERROR = 106,
	RERROR,
	TFLUSH = 108,
	RFLUSH,
	TWALK = 110,
	RWALK,
	TOPEN = 112,
	ROPEN,
	TCREATE = 114,
	RCREATE,
	TREAD = 116,
	RREAD,
	TWRITE = 118,
	RWRITE,
	TCLUNK = 120,
	RCLUNK,
	TREMOVE = 122,
	RREMOVE,
	TSTAT = 124,
	RSTAT,
	TWSTAT = 126,
	RWSTAT,
};

/* modes */
enum {
	V9FS_OREAD = 0x00,
	V9FS_OWRITE = 0x01,
	V9FS_ORDWR = 0x02,
	V9FS_OEXEC = 0x03,
	V9FS_OEXCL = 0x04,
	V9FS_OTRUNC = 0x10,
	V9FS_OREXEC = 0x20,
	V9FS_ORCLOSE = 0x40,
	V9FS_OAPPEND = 0x80,
};

/* permissions */
enum {
	V9FS_DMDIR = 0x80000000,
	V9FS_DMAPPEND = 0x40000000,
	V9FS_DMEXCL = 0x20000000,
	V9FS_DMMOUNT = 0x10000000,
	V9FS_DMAUTH = 0x08000000,
	V9FS_DMTMP = 0x04000000,
	V9FS_DMSYMLINK = 0x02000000,
	V9FS_DMLINK = 0x01000000,
	/* 9P2000.u extensions */
	V9FS_DMDEVICE = 0x00800000,
	V9FS_DMNAMEDPIPE = 0x00200000,
	V9FS_DMSOCKET = 0x00100000,
	V9FS_DMSETUID = 0x00080000,
	V9FS_DMSETGID = 0x00040000,
};

/* qid.types */
enum {
	V9FS_QTDIR = 0x80,
	V9FS_QTAPPEND = 0x40,
	V9FS_QTEXCL = 0x20,
	V9FS_QTMOUNT = 0x10,
	V9FS_QTAUTH = 0x08,
	V9FS_QTTMP = 0x04,
	V9FS_QTSYMLINK = 0x02,
	V9FS_QTLINK = 0x01,
	V9FS_QTFILE = 0x00,
};

#define V9FS_NOTAG	(u16)(~0)
#define V9FS_NOFID	(u32)(~0)
#define V9FS_MAXWELEM	16

/* ample room for Twrite/Rread header (iounit) */
#define V9FS_IOHDRSZ	24

struct v9fs_str {
	u16 len;
	char *str;
};

/* qids are the unique ID for a file (like an inode */
struct v9fs_qid {
	u8 type;
	u32 version;
	u64 path;
};

/* Plan 9 file metadata (stat) structure */
struct v9fs_stat {
	u16 size;
	u16 type;
	u32 dev;
	struct v9fs_qid qid;
	u32 mode;
	u32 atime;
	u32 mtime;
	u64 length;
	struct v9fs_str name;
	struct v9fs_str uid;
	struct v9fs_str gid;
	struct v9fs_str muid;
	struct v9fs_str extension;	/* 9p2000.u extensions */
	u32 n_uid;		/* 9p2000.u extensions */
	u32 n_gid;		/* 9p2000.u extensions */
	u32 n_muid;		/* 9p2000.u extensions */
};

/* file metadata (stat) structure used to create Twstat message
   The is similar to v9fs_stat, but the strings don't point to
   the same memory block and should be freed separately
*/
struct v9fs_wstat {
	u16 size;
	u16 type;
	u32 dev;
	struct v9fs_qid qid;
	u32 mode;
	u32 atime;
	u32 mtime;
	u64 length;
	char *name;
	char *uid;
	char *gid;
	char *muid;
	char *extension;	/* 9p2000.u extensions */
	u32 n_uid;		/* 9p2000.u extensions */
	u32 n_gid;		/* 9p2000.u extensions */
	u32 n_muid;		/* 9p2000.u extensions */
};

/* Structures for Protocol Operations */

struct Tversion {
	u32 msize;
	struct v9fs_str version;
};

struct Rversion {
	u32 msize;
	struct v9fs_str version;
};

struct Tauth {
	u32 afid;
	struct v9fs_str uname;
	struct v9fs_str aname;
};

struct Rauth {
	struct v9fs_qid qid;
};

struct Rerror {
	struct v9fs_str error;
	u32 errno;		/* 9p2000.u extension */
};

struct Tflush {
	u16 oldtag;
};

struct Rflush {
};

struct Tattach {
	u32 fid;
	u32 afid;
	struct v9fs_str uname;
	struct v9fs_str aname;
};

struct Rattach {
	struct v9fs_qid qid;
};

struct Twalk {
	u32 fid;
	u32 newfid;
	u16 nwname;
	struct v9fs_str wnames[16];
};

struct Rwalk {
	u16 nwqid;
	struct v9fs_qid wqids[16];
};

struct Topen {
	u32 fid;
	u8 mode;
};

struct Ropen {
	struct v9fs_qid qid;
	u32 iounit;
};

struct Tcreate {
	u32 fid;
	struct v9fs_str name;
	u32 perm;
	u8 mode;
	struct v9fs_str extension;
};

struct Rcreate {
	struct v9fs_qid qid;
	u32 iounit;
};

struct Tread {
	u32 fid;
	u64 offset;
	u32 count;
};

struct Rread {
	u32 count;
	u8 *data;
};

struct Twrite {
	u32 fid;
	u64 offset;
	u32 count;
	u8 *data;
};

struct Rwrite {
	u32 count;
};

struct Tclunk {
	u32 fid;
};

struct Rclunk {
};

struct Tremove {
	u32 fid;
};

struct Rremove {
};

struct Tstat {
	u32 fid;
};

struct Rstat {
	struct v9fs_stat stat;
};

struct Twstat {
	u32 fid;
	struct v9fs_stat stat;
};

struct Rwstat {
};

/*
  * fcall is the primary packet structure
  *
  */

struct v9fs_fcall {
	u32 size;
	u8 id;
	u16 tag;
	void *sdata;

	union {
		struct Tversion tversion;
		struct Rversion rversion;
		struct Tauth tauth;
		struct Rauth rauth;
		struct Rerror rerror;
		struct Tflush tflush;
		struct Rflush rflush;
		struct Tattach tattach;
		struct Rattach rattach;
		struct Twalk twalk;
		struct Rwalk rwalk;
		struct Topen topen;
		struct Ropen ropen;
		struct Tcreate tcreate;
		struct Rcreate rcreate;
		struct Tread tread;
		struct Rread rread;
		struct Twrite twrite;
		struct Rwrite rwrite;
		struct Tclunk tclunk;
		struct Rclunk rclunk;
		struct Tremove tremove;
		struct Rremove rremove;
		struct Tstat tstat;
		struct Rstat rstat;
		struct Twstat twstat;
		struct Rwstat rwstat;
	} params;
};

#define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \
	fcall?fcall->params.rerror.error.len:0, \
	fcall?fcall->params.rerror.error.str:"");

int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
		   char *version, struct v9fs_fcall **rcall);

int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
		  u32 fid, u32 afid, struct v9fs_fcall **rcall);

int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid);

int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid,
		struct v9fs_fcall **rcall);

int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
		 struct v9fs_wstat *wstat, struct v9fs_fcall **rcall);

int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
		char *name, struct v9fs_fcall **rcall);

int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
		struct v9fs_fcall **rcall);

int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
		  struct v9fs_fcall **rcall);

int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
	u32 perm, u8 mode, char *extension, struct v9fs_fcall **rcall);

int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
		u64 offset, u32 count, struct v9fs_fcall **rcall);

int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
		 u32 count, const char __user * data,
		 struct v9fs_fcall **rcall);
int v9fs_printfcall(char *, int, struct v9fs_fcall *, int);
+0 −6
Original line number Original line Diff line number Diff line
obj-$(CONFIG_9P_FS) := 9p.o
obj-$(CONFIG_9P_FS) := 9p.o


9p-objs := \
9p-objs := \
	trans_fd.o \
	mux.o \
	fcall.o \
	conv.o \
	vfs_super.o \
	vfs_super.o \
	vfs_inode.o \
	vfs_inode.o \
	vfs_addr.o \
	vfs_addr.o \
	vfs_file.o \
	vfs_file.o \
	vfs_dir.o \
	vfs_dir.o \
	vfs_dentry.o \
	vfs_dentry.o \
	error.o \
	v9fs.o \
	v9fs.o \
	fid.o \
	fid.o \
	fcprint.o

fs/9p/debug.h

deleted100644 → 0
+0 −77
Original line number Original line Diff line number Diff line
/*
 *  linux/fs/9p/debug.h - V9FS Debug Definitions
 *
 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
 *
 *  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
 *
 */

#define DEBUG_ERROR		(1<<0)
#define DEBUG_CURRENT		(1<<1)
#define DEBUG_9P	        (1<<2)
#define DEBUG_VFS	        (1<<3)
#define DEBUG_CONV		(1<<4)
#define DEBUG_MUX		(1<<5)
#define DEBUG_TRANS		(1<<6)
#define DEBUG_SLABS	      	(1<<7)
#define DEBUG_FCALL		(1<<8)

#define DEBUG_DUMP_PKT		0

extern int v9fs_debug_level;

#define dprintk(level, format, arg...) \
do {  \
	if((v9fs_debug_level & level)==level) \
		printk(KERN_NOTICE "-- %s (%d): " \
		format , __FUNCTION__, current->pid , ## arg); \
} while(0)

#define eprintk(level, format, arg...) \
do { \
	printk(level "v9fs: %s (%d): " \
		format , __FUNCTION__, current->pid , ## arg); \
} while(0)

#if DEBUG_DUMP_PKT
static inline void dump_data(const unsigned char *data, unsigned int datalen)
{
	int i, n;
	char buf[5*8];

	n = 0;
	i = 0;
	while (i < datalen) {
		n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]);
		if (i%4 == 0)
			n += snprintf(buf+n, sizeof(buf)-n, " ");

		if (i%16 == 0) {
			dprintk(DEBUG_ERROR, "%s\n", buf);
			n = 0;
		}
	}

	dprintk(DEBUG_ERROR, "%s\n", buf);
}
#else				/* DEBUG_DUMP_PKT */
static inline void dump_data(const unsigned char *data, unsigned int datalen)
{

}
#endif				/* DEBUG_DUMP_PKT */

fs/9p/fcall.c

deleted100644 → 0
+0 −427
Original line number Original line Diff line number Diff line
/*
 *  linux/fs/9p/fcall.c
 *
 *  This file contains functions to perform synchronous 9P calls
 *
 *  Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net>
 *  Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
 *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
 *
 *  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/sched.h>
#include <linux/idr.h>

#include "debug.h"
#include "v9fs.h"
#include "9p.h"
#include "conv.h"
#include "mux.h"

/**
 * v9fs_t_version - negotiate protocol parameters with sever
 * @v9ses: 9P2000 session information
 * @msize: requested max size packet
 * @version: requested version.extension string
 * @fcall: pointer to response fcall pointer
 *
 */

int
v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
	       char *version, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc;

	dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
	tc = v9fs_create_tversion(msize, version);

	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_attach - mount the server
 * @v9ses: 9P2000 session information
 * @uname: user name doing the attach
 * @aname: remote name being attached to
 * @fid: mount fid to attatch to root node
 * @afid: authentication fid (in this case result key)
 * @fcall: pointer to response fcall pointer
 *
 */

int
v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
	      u32 fid, u32 afid, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall* tc;

	dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
		aname, fid, afid);

	tc = v9fs_create_tattach(fid, afid, uname, aname);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
	struct v9fs_fcall *rc, int err)
{
	int fid, id;
	struct v9fs_session_info *v9ses;

	id = 0;
	fid = tc->params.tclunk.fid;
	if (rc)
		id = rc->id;

	kfree(tc);
	kfree(rc);
	if (id == RCLUNK) {
		v9ses = a;
		v9fs_put_idpool(fid, &v9ses->fidpool);
	}
}

/**
 * v9fs_t_clunk - release a fid (finish a transaction)
 * @v9ses: 9P2000 session information
 * @fid: fid to release
 * @fcall: pointer to response fcall pointer
 *
 */

int
v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
{
	int ret;
	struct v9fs_fcall *tc, *rc;

	dprintk(DEBUG_9P, "fid %d\n", fid);

	rc = NULL;
	tc = v9fs_create_tclunk(fid);
	if (!IS_ERR(tc))
		ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
	else
		ret = PTR_ERR(tc);

	if (ret)
		dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret);

	v9fs_t_clunk_cb(v9ses, tc, rc, ret);
	return ret;
}

#if 0
/**
 * v9fs_v9fs_t_flush - flush a pending transaction
 * @v9ses: 9P2000 session information
 * @tag: tag to release
 *
 */
int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
{
	int ret;
	struct v9fs_fcall *tc;

	dprintk(DEBUG_9P, "oldtag %d\n", oldtag);

	tc = v9fs_create_tflush(oldtag);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, NULL);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}
#endif

/**
 * v9fs_t_stat - read a file's meta-data
 * @v9ses: 9P2000 session information
 * @fid: fid pointing to file or directory to get info about
 * @fcall: pointer to response fcall
 *
 */

int
v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc;

	dprintk(DEBUG_9P, "fid %d\n", fid);

	ret = -ENOMEM;
	tc = v9fs_create_tstat(fid);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_wstat - write a file's meta-data
 * @v9ses: 9P2000 session information
 * @fid: fid pointing to file or directory to write info about
 * @stat: metadata
 * @fcall: pointer to response fcall
 *
 */

int
v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
	     struct v9fs_wstat *wstat, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc;

	dprintk(DEBUG_9P, "fid %d\n", fid);

	tc = v9fs_create_twstat(fid, wstat, v9ses->extended);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_walk - walk a fid to a new file or directory
 * @v9ses: 9P2000 session information
 * @fid: fid to walk
 * @newfid: new fid (for clone operations)
 * @name: path to walk fid to
 * @fcall: pointer to response fcall
 *
 */

/* TODO: support multiple walk */

int
v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
	    char *name, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc;
	int nwname;

	dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);

	if (name)
		nwname = 1;
	else
		nwname = 0;

	tc = v9fs_create_twalk(fid, newfid, nwname, &name);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_open - open a file
 *
 * @v9ses - 9P2000 session information
 * @fid - fid to open
 * @mode - mode to open file (R, RW, etc)
 * @fcall - pointer to response fcall
 *
 */

int
v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
	    struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc;

	dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);

	tc = v9fs_create_topen(fid, mode);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_remove - remove a file or directory
 * @v9ses: 9P2000 session information
 * @fid: fid to remove
 * @fcall: pointer to response fcall
 *
 */

int
v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
	      struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc;

	dprintk(DEBUG_9P, "fid %d\n", fid);

	tc = v9fs_create_tremove(fid);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_create - create a file or directory
 * @v9ses: 9P2000 session information
 * @fid: fid to create
 * @name: name of the file or directory to create
 * @perm: permissions to create with
 * @mode: mode to open file (R, RW, etc)
 * @fcall: pointer to response fcall
 *
 */

int
v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, u32 perm,
	u8 mode, char *extension, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc;

	dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
		fid, name, perm, mode);

	tc = v9fs_create_tcreate(fid, name, perm, mode, extension,
		v9ses->extended);

	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_read - read data
 * @v9ses: 9P2000 session information
 * @fid: fid to read from
 * @offset: offset to start read at
 * @count: how many bytes to read
 * @fcall: pointer to response fcall (with data)
 *
 */

int
v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
	    u32 count, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc, *rc;

	dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
		(long long unsigned) offset, count);

	tc = v9fs_create_tread(fid, offset, count);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
		if (!ret)
			ret = rc->params.rread.count;
		if (rcp)
			*rcp = rc;
		else
			kfree(rc);

		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}

/**
 * v9fs_t_write - write data
 * @v9ses: 9P2000 session information
 * @fid: fid to write to
 * @offset: offset to start write at
 * @count: how many bytes to write
 * @fcall: pointer to response fcall
 *
 */

int
v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count,
	const char __user *data, struct v9fs_fcall **rcp)
{
	int ret;
	struct v9fs_fcall *tc, *rc;

	dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
		(long long unsigned) offset, count);

	tc = v9fs_create_twrite(fid, offset, count, data);
	if (!IS_ERR(tc)) {
		ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);

		if (!ret)
			ret = rc->params.rwrite.count;
		if (rcp)
			*rcp = rc;
		else
			kfree(rc);

		kfree(tc);
	} else
		ret = PTR_ERR(tc);

	return ret;
}
+54 −114
Original line number Original line Diff line number Diff line
@@ -26,10 +26,10 @@
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/idr.h>
#include <linux/idr.h>
#include <asm/semaphore.h>
#include <asm/semaphore.h>
#include <net/9p/9p.h>
#include <net/9p/client.h>


#include "debug.h"
#include "v9fs.h"
#include "v9fs.h"
#include "9p.h"
#include "v9fs_vfs.h"
#include "v9fs_vfs.h"
#include "fid.h"
#include "fid.h"


@@ -40,67 +40,29 @@
 *
 *
 */
 */


int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
{
{
	struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
	struct v9fs_dentry *dent;
	dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
		dentry->d_iname, dentry);
	if (dentry->d_fsdata == NULL) {
		dentry->d_fsdata =
		    kmalloc(sizeof(struct list_head), GFP_KERNEL);
		if (dentry->d_fsdata == NULL) {
			dprintk(DEBUG_ERROR, "Out of memory\n");
			return -ENOMEM;
		}
		fid_list = (struct list_head *)dentry->d_fsdata;
		INIT_LIST_HEAD(fid_list);	/* Initialize list head */
	}

	fid->uid = current->uid;
	list_add(&fid->list, fid_list);
	return 0;
}

/**
 * v9fs_fid_create - allocate a FID structure
 * @dentry - dentry to link newly created fid to
 *
 */


struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
	P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n",
{
					fid->fid, dentry->d_iname);
	struct v9fs_fid *new;


	dprintk(DEBUG_9P, "fid create fid %d\n", fid);
	dent = dentry->d_fsdata;
	new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
	if (!dent) {
	if (new == NULL) {
		dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);
		dprintk(DEBUG_ERROR, "Out of Memory\n");
		if (!dent)
		return ERR_PTR(-ENOMEM);
			return -ENOMEM;
	}


	new->fid = fid;
		spin_lock_init(&dent->lock);
	new->v9ses = v9ses;
		INIT_LIST_HEAD(&dent->fidlist);
	new->fidopen = 0;
		dentry->d_fsdata = dent;
	new->fidclunked = 0;
	new->iounit = 0;
	new->rdir_pos = 0;
	new->rdir_fcall = NULL;
	init_MUTEX(&new->lock);
	INIT_LIST_HEAD(&new->list);

	return new;
	}
	}


/**
	spin_lock(&dent->lock);
 * v9fs_fid_destroy - deallocate a FID structure
	list_add(&fid->dlist, &dent->fidlist);
 * @fid: fid to destroy
	spin_unlock(&dent->lock);
 *
 */


void v9fs_fid_destroy(struct v9fs_fid *fid)
	return 0;
{
	list_del(&fid->list);
	kfree(fid);
}
}


/**
/**
@@ -114,27 +76,39 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
 *
 *
 */
 */


struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
{
{
	struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
	struct v9fs_dentry *dent;
	struct v9fs_fid *return_fid = NULL;
	struct p9_fid *fid;


	dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry);
	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);

	dent = dentry->d_fsdata;
	if (fid_list)
	if (dent)
		return_fid = list_entry(fid_list->next, struct v9fs_fid, list);
		fid = list_entry(dent->fidlist.next, struct p9_fid, dlist);

	else
	if (!return_fid) {
		fid = ERR_PTR(-EBADF);
		dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n");

		return_fid = ERR_PTR(-EBADF);
	P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid);
	return fid;
}
}


	if(down_interruptible(&return_fid->lock))
struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry)
		return ERR_PTR(-EINTR);
{
	struct p9_fid *fid;
	struct v9fs_dentry *dent;

	dent = dentry->d_fsdata;
	fid = v9fs_fid_lookup(dentry);
	if (!IS_ERR(fid)) {
		spin_lock(&dent->lock);
		list_del(&fid->dlist);
		spin_unlock(&dent->lock);
	}


	return return_fid;
	return fid;
}
}



/**
/**
 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
 * 	release it
 * 	release it
@@ -146,49 +120,15 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
 *
 *
 */
 */


struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry)
struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
{
{
	struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
	struct p9_fid *ofid, *fid;
	struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF);
	struct v9fs_fcall *fcall = NULL;
	int fid, err;

	base_fid = v9fs_fid_lookup(dentry);

	if(IS_ERR(base_fid))
		return base_fid;

	if(base_fid) {  /* clone fid */
		fid = v9fs_get_idpool(&v9ses->fidpool);
		if (fid < 0) {
			eprintk(KERN_WARNING, "newfid fails!\n");
			new_fid = ERR_PTR(-ENOSPC);
			goto Release_Fid;
		}


		err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall);
	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
		if (err < 0) {
	ofid = v9fs_fid_lookup(dentry);
			dprintk(DEBUG_ERROR, "clone walk didn't work\n");
	if (IS_ERR(ofid))
			v9fs_put_idpool(fid, &v9ses->fidpool);
		return ofid;
			new_fid = ERR_PTR(err);
			goto Free_Fcall;
		}
		new_fid = v9fs_fid_create(v9ses, fid);
		if (new_fid == NULL) {
			dprintk(DEBUG_ERROR, "out of memory\n");
			new_fid = ERR_PTR(-ENOMEM);
		}
Free_Fcall:
		kfree(fcall);
	}


Release_Fid:
	fid = p9_client_walk(ofid, 0, NULL, 1);
	up(&base_fid->lock);
	return fid;
	return new_fid;
}

void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid)
{
	v9fs_t_clunk(v9ses, fid->fid);
	v9fs_fid_destroy(fid);
}
}
Loading