summaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/9p.h11
-rw-r--r--fs/9p/Makefile10
-rw-r--r--fs/9p/conv.c15
-rw-r--r--fs/9p/conv.h9
-rw-r--r--fs/9p/debug.h6
-rw-r--r--fs/9p/error.c5
-rw-r--r--fs/9p/error.h5
-rw-r--r--fs/9p/fcall.c (renamed from fs/9p/9p.c)20
-rw-r--r--fs/9p/fcprint.c346
-rw-r--r--fs/9p/fid.c5
-rw-r--r--fs/9p/fid.h5
-rw-r--r--fs/9p/mux.c54
-rw-r--r--fs/9p/mux.h7
-rw-r--r--fs/9p/trans_fd.c301
-rw-r--r--fs/9p/trans_sock.c334
-rw-r--r--fs/9p/transport.h5
-rw-r--r--fs/9p/v9fs.c15
-rw-r--r--fs/9p/v9fs.h8
-rw-r--r--fs/9p/v9fs_vfs.h9
-rw-r--r--fs/9p/vfs_addr.c5
-rw-r--r--fs/9p/vfs_dentry.c7
-rw-r--r--fs/9p/vfs_dir.c7
-rw-r--r--fs/9p/vfs_file.c39
-rw-r--r--fs/9p/vfs_inode.c59
-rw-r--r--fs/9p/vfs_super.c7
25 files changed, 696 insertions, 598 deletions
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
index 0cd374d94717..94e2f92ab2e8 100644
--- a/fs/9p/9p.h
+++ b/fs/9p/9p.h
@@ -8,9 +8,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -235,6 +234,7 @@ struct Tcreate {
struct v9fs_str name;
u32 perm;
u8 mode;
+ struct v9fs_str extension;
};
struct Rcreate {
@@ -348,8 +348,6 @@ int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid);
-int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag);
-
int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid,
struct v9fs_fcall **rcall);
@@ -366,7 +364,7 @@ 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, struct v9fs_fcall **rcall);
+ 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);
@@ -374,3 +372,4 @@ int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
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);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 2f4ce43f7b6c..87897f84dfb6 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -1,10 +1,9 @@
-obj-$(CONFIG_9P_FS) := 9p2000.o
+obj-$(CONFIG_9P_FS) := 9p.o
-9p2000-objs := \
+9p-objs := \
trans_fd.o \
- trans_sock.o \
mux.o \
- 9p.o \
+ fcall.o \
conv.o \
vfs_super.o \
vfs_inode.o \
@@ -14,5 +13,6 @@ obj-$(CONFIG_9P_FS) := 9p2000.o
vfs_dentry.o \
error.o \
v9fs.o \
- fid.o
+ fid.o \
+ fcprint.o
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
index bf1f10067960..a767e05b60bf 100644
--- a/fs/9p/conv.c
+++ b/fs/9p/conv.c
@@ -8,9 +8,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -536,6 +535,7 @@ struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version)
return fc;
}
+#if 0
struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
{
int size;
@@ -559,6 +559,7 @@ struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
error:
return fc;
}
+#endif /* 0 */
struct v9fs_fcall *
v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
@@ -664,7 +665,8 @@ struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode)
return fc;
}
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode)
+struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+ char *extension, int extended)
{
int size;
struct v9fs_fcall *fc;
@@ -672,6 +674,9 @@ struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode)
struct cbuf *bufp = &buffer;
size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */
+ if (extended && extension!=NULL)
+ size += 2 + strlen(extension); /* extension[s] */
+
fc = v9fs_create_common(bufp, size, TCREATE);
if (IS_ERR(fc))
goto error;
@@ -680,6 +685,8 @@ struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode)
v9fs_put_str(bufp, name, &fc->params.tcreate.name);
v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm);
v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode);
+ if (extended)
+ v9fs_put_str(bufp, extension, &fc->params.tcreate.extension);
if (buf_check_overflow(bufp)) {
kfree(fc);
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
index 26a736e4a2e7..dd5b6b1b610f 100644
--- a/fs/9p/conv.h
+++ b/fs/9p/conv.h
@@ -8,9 +8,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -33,14 +32,14 @@ int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag);
struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version);
-struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname);
struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname,
char *aname);
struct v9fs_fcall *v9fs_create_tflush(u16 oldtag);
struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
char **wnames);
struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode);
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode);
+struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+ char *extension, int extended);
struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count);
struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
const char __user *data);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
index fe551032788b..4228c0bb3c32 100644
--- a/fs/9p/debug.h
+++ b/fs/9p/debug.h
@@ -5,9 +5,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -30,6 +29,7 @@
#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
diff --git a/fs/9p/error.c b/fs/9p/error.c
index e4b6f8f38b6f..981fe8ecd780 100644
--- a/fs/9p/error.c
+++ b/fs/9p/error.c
@@ -11,9 +11,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
diff --git a/fs/9p/error.h b/fs/9p/error.h
index a9794e85fe51..5f3ca522b316 100644
--- a/fs/9p/error.h
+++ b/fs/9p/error.h
@@ -12,9 +12,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
diff --git a/fs/9p/9p.c b/fs/9p/fcall.c
index f86a28d1d6a6..71742ba150c4 100644
--- a/fs/9p/9p.c
+++ b/fs/9p/fcall.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/9p/9p.c
+ * linux/fs/9p/fcall.c
*
* This file contains functions to perform synchronous 9P calls
*
@@ -8,9 +8,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -148,13 +147,13 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
return ret;
}
+#if 0
/**
* v9fs_v9fs_t_flush - flush a pending transaction
* @v9ses: 9P2000 session information
- * @tag: tid to release
+ * @tag: tag to release
*
*/
-
int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
{
int ret;
@@ -171,6 +170,7 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
return ret;
}
+#endif
/**
* v9fs_t_stat - read a file's meta-data
@@ -332,8 +332,8 @@ v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
*/
int
-v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
- u32 perm, u8 mode, struct v9fs_fcall **rcp)
+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;
@@ -341,7 +341,9 @@ v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
fid, name, perm, mode);
- tc = v9fs_create_tcreate(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);
diff --git a/fs/9p/fcprint.c b/fs/9p/fcprint.c
new file mode 100644
index 000000000000..583e827baebd
--- /dev/null
+++ b/fs/9p/fcprint.c
@@ -0,0 +1,346 @@
+/*
+ * linux/fs/9p/fcprint.c
+ *
+ * Print 9P call.
+ *
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "mux.h"
+
+static int
+v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q)
+{
+ int n;
+ char b[10];
+
+ n = 0;
+ if (q->type & V9FS_QTDIR)
+ b[n++] = 'd';
+ if (q->type & V9FS_QTAPPEND)
+ b[n++] = 'a';
+ if (q->type & V9FS_QTAUTH)
+ b[n++] = 'A';
+ if (q->type & V9FS_QTEXCL)
+ b[n++] = 'l';
+ if (q->type & V9FS_QTTMP)
+ b[n++] = 't';
+ if (q->type & V9FS_QTSYMLINK)
+ b[n++] = 'L';
+ b[n] = '\0';
+
+ return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path,
+ q->version, b);
+}
+
+static int
+v9fs_printperm(char *buf, int buflen, int perm)
+{
+ int n;
+ char b[15];
+
+ n = 0;
+ if (perm & V9FS_DMDIR)
+ b[n++] = 'd';
+ if (perm & V9FS_DMAPPEND)
+ b[n++] = 'a';
+ if (perm & V9FS_DMAUTH)
+ b[n++] = 'A';
+ if (perm & V9FS_DMEXCL)
+ b[n++] = 'l';
+ if (perm & V9FS_DMTMP)
+ b[n++] = 't';
+ if (perm & V9FS_DMDEVICE)
+ b[n++] = 'D';
+ if (perm & V9FS_DMSOCKET)
+ b[n++] = 'S';
+ if (perm & V9FS_DMNAMEDPIPE)
+ b[n++] = 'P';
+ if (perm & V9FS_DMSYMLINK)
+ b[n++] = 'L';
+ b[n] = '\0';
+
+ return scnprintf(buf, buflen, "%s%03o", b, perm&077);
+}
+
+static int
+v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
+{
+ int n;
+
+ n = scnprintf(buf, buflen, "'%.*s' '%.*s'", st->name.len,
+ st->name.str, st->uid.len, st->uid.str);
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, "(%d)", st->n_uid);
+
+ n += scnprintf(buf+n, buflen-n, " '%.*s'", st->gid.len, st->gid.str);
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, "(%d)", st->n_gid);
+
+ n += scnprintf(buf+n, buflen-n, " '%.*s'", st->muid.len, st->muid.str);
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid);
+
+ n += scnprintf(buf+n, buflen-n, " q ");
+ n += v9fs_printqid(buf+n, buflen-n, &st->qid);
+ n += scnprintf(buf+n, buflen-n, " m ");
+ n += v9fs_printperm(buf+n, buflen-n, st->mode);
+ n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld",
+ st->atime, st->mtime, (long long int) st->length);
+
+ if (extended)
+ n += scnprintf(buf+n, buflen-n, " ext '%.*s'",
+ st->extension.len, st->extension.str);
+
+ return n;
+}
+
+static int
+v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen)
+{
+ int i, n;
+
+ i = n = 0;
+ while (i < datalen) {
+ n += scnprintf(buf + n, buflen - n, "%02x", data[i]);
+ if (i%4 == 3)
+ n += scnprintf(buf + n, buflen - n, " ");
+ if (i%32 == 31)
+ n += scnprintf(buf + n, buflen - n, "\n");
+
+ i++;
+ }
+ n += scnprintf(buf + n, buflen - n, "\n");
+
+ return n;
+}
+
+static int
+v9fs_printdata(char *buf, int buflen, u8 *data, int datalen)
+{
+ return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16);
+}
+
+int
+v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
+{
+ int i, ret, type, tag;
+
+ if (!fc)
+ return scnprintf(buf, buflen, "<NULL>");
+
+ type = fc->id;
+ tag = fc->tag;
+
+ ret = 0;
+ switch (type) {
+ case TVERSION:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tversion tag %u msize %u version '%.*s'", tag,
+ fc->params.tversion.msize, fc->params.tversion.version.len,
+ fc->params.tversion.version.str);
+ break;
+
+ case RVERSION:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Rversion tag %u msize %u version '%.*s'", tag,
+ fc->params.rversion.msize, fc->params.rversion.version.len,
+ fc->params.rversion.version.str);
+ break;
+
+ case TAUTH:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag,
+ fc->params.tauth.afid, fc->params.tauth.uname.len,
+ fc->params.tauth.uname.str, fc->params.tauth.aname.len,
+ fc->params.tauth.aname.str);
+ break;
+
+ case RAUTH:
+ ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag);
+ v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid);
+ break;
+
+ case TATTACH:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'",
+ tag, fc->params.tattach.fid, fc->params.tattach.afid,
+ fc->params.tattach.uname.len, fc->params.tattach.uname.str,
+ fc->params.tattach.aname.len, fc->params.tattach.aname.str);
+ break;
+
+ case RATTACH:
+ ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag);
+ v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid);
+ break;
+
+ case RERROR:
+ ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'",
+ tag, fc->params.rerror.error.len,
+ fc->params.rerror.error.str);
+ if (extended)
+ ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n",
+ fc->params.rerror.errno);
+ break;
+
+ case TFLUSH:
+ ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u",
+ tag, fc->params.tflush.oldtag);
+ break;
+
+ case RFLUSH:
+ ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag);
+ break;
+
+ case TWALK:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Twalk tag %u fid %d newfid %d nwname %d", tag,
+ fc->params.twalk.fid, fc->params.twalk.newfid,
+ fc->params.twalk.nwname);
+ for(i = 0; i < fc->params.twalk.nwname; i++)
+ ret += scnprintf(buf+ret, buflen-ret," '%.*s'",
+ fc->params.twalk.wnames[i].len,
+ fc->params.twalk.wnames[i].str);
+ break;
+
+ case RWALK:
+ ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d",
+ tag, fc->params.rwalk.nwqid);
+ for(i = 0; i < fc->params.rwalk.nwqid; i++)
+ ret += v9fs_printqid(buf+ret, buflen-ret,
+ &fc->params.rwalk.wqids[i]);
+ break;
+
+ case TOPEN:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Topen tag %u fid %d mode %d", tag,
+ fc->params.topen.fid, fc->params.topen.mode);
+ break;
+
+ case ROPEN:
+ ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag);
+ ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid);
+ ret += scnprintf(buf+ret, buflen-ret," iounit %d",
+ fc->params.ropen.iounit);
+ break;
+
+ case TCREATE:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tcreate tag %u fid %d name '%.*s' perm ", tag,
+ fc->params.tcreate.fid, fc->params.tcreate.name.len,
+ fc->params.tcreate.name.str);
+
+ ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm);
+ ret += scnprintf(buf+ret, buflen-ret, " mode %d",
+ fc->params.tcreate.mode);
+ break;
+
+ case RCREATE:
+ ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag);
+ ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid);
+ ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
+ fc->params.rcreate.iounit);
+ break;
+
+ case TREAD:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Tread tag %u fid %d offset %lld count %u", tag,
+ fc->params.tread.fid,
+ (long long int) fc->params.tread.offset,
+ fc->params.tread.count);
+ break;
+
+ case RREAD:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Rread tag %u count %u data ", tag,
+ fc->params.rread.count);
+ ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data,
+ fc->params.rread.count);
+ break;
+
+ case TWRITE:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Twrite tag %u fid %d offset %lld count %u data ",
+ tag, fc->params.twrite.fid,
+ (long long int) fc->params.twrite.offset,
+ fc->params.twrite.count);
+ ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data,
+ fc->params.twrite.count);
+ break;
+
+ case RWRITE:
+ ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u",
+ tag, fc->params.rwrite.count);
+ break;
+
+ case TCLUNK:
+ ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d",
+ tag, fc->params.tclunk.fid);
+ break;
+
+ case RCLUNK:
+ ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag);
+ break;
+
+ case TREMOVE:
+ ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d",
+ tag, fc->params.tremove.fid);
+ break;
+
+ case RREMOVE:
+ ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag);
+ break;
+
+ case TSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d",
+ tag, fc->params.tstat.fid);
+ break;
+
+ case RSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag);
+ ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat,
+ extended);
+ break;
+
+ case TWSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ",
+ tag, fc->params.twstat.fid);
+ ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat,
+ extended);
+ break;
+
+ case RWSTAT:
+ ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag);
+ break;
+
+ default:
+ ret += scnprintf(buf+ret, buflen-ret, "unknown type %d", type);
+ break;
+ }
+
+ return ret;
+}
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index c4d13bf904d2..b7608af07ce8 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -4,9 +4,8 @@
* Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 1fc2dd08d75a..aa974d6875c3 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -4,9 +4,8 @@
* Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index ea1134eb47c8..3e5b124a7212 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -7,9 +7,8 @@
* Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -31,6 +30,7 @@
#include <linux/poll.h>
#include <linux/kthread.h>
#include <linux/idr.h>
+#include <linux/mutex.h>
#include "debug.h"
#include "v9fs.h"
@@ -69,7 +69,7 @@ struct v9fs_mux_data {
int msize;
unsigned char *extended;
struct v9fs_transport *trans;
- struct v9fs_idpool tidpool;
+ struct v9fs_idpool tagpool;
int err;
wait_queue_head_t equeue;
struct list_head req_list;
@@ -110,7 +110,7 @@ static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
static u16 v9fs_mux_get_tag(struct v9fs_mux_data *);
static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16);
-static DECLARE_MUTEX(v9fs_mux_task_lock);
+static DEFINE_MUTEX(v9fs_mux_task_lock);
static struct workqueue_struct *v9fs_mux_wq;
static int v9fs_mux_num;
@@ -142,7 +142,7 @@ void v9fs_mux_global_exit(void)
*
* The current implementation returns sqrt of the number of mounts.
*/
-inline int v9fs_mux_calc_poll_procs(int muxnum)
+static int v9fs_mux_calc_poll_procs(int muxnum)
{
int n;
@@ -166,7 +166,7 @@ static int v9fs_mux_poll_start(struct v9fs_mux_data *m)
dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num,
v9fs_mux_poll_task_num);
- up(&v9fs_mux_task_lock);
+ mutex_lock(&v9fs_mux_task_lock);
n = v9fs_mux_calc_poll_procs(v9fs_mux_num + 1);
if (n > v9fs_mux_poll_task_num) {
@@ -225,7 +225,7 @@ static int v9fs_mux_poll_start(struct v9fs_mux_data *m)
}
v9fs_mux_num++;
- down(&v9fs_mux_task_lock);
+ mutex_unlock(&v9fs_mux_task_lock);
return 0;
}
@@ -235,7 +235,7 @@ static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
int i;
struct v9fs_mux_poll_task *vpt;
- up(&v9fs_mux_task_lock);
+ mutex_lock(&v9fs_mux_task_lock);
vpt = m->poll_task;
list_del(&m->mux_list);
for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
@@ -252,7 +252,7 @@ static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
v9fs_mux_poll_task_num--;
}
v9fs_mux_num--;
- down(&v9fs_mux_task_lock);
+ mutex_unlock(&v9fs_mux_task_lock);
}
/**
@@ -279,8 +279,8 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
m->msize = msize;
m->extended = extended;
m->trans = trans;
- idr_init(&m->tidpool.pool);
- init_MUTEX(&m->tidpool.lock);
+ idr_init(&m->tagpool.pool);
+ init_MUTEX(&m->tagpool.lock);
m->err = 0;
init_waitqueue_head(&m->equeue);
INIT_LIST_HEAD(&m->req_list);
@@ -383,7 +383,7 @@ v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
/**
* v9fs_poll_mux - polls a mux and schedules read or write works if necessary
*/
-static inline void v9fs_poll_mux(struct v9fs_mux_data *m)
+static void v9fs_poll_mux(struct v9fs_mux_data *m)
{
int n;
@@ -634,6 +634,14 @@ static void v9fs_read_work(void *a)
goto error;
}
+ if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
+ char buf[150];
+
+ v9fs_printfcall(buf, sizeof(buf), m->rcall,
+ *m->extended);
+ printk(KERN_NOTICE ">>> %p %s\n", m, buf);
+ }
+
rcall = m->rcall;
rbuf = m->rbuf;
if (m->rpos > n) {
@@ -739,6 +747,13 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
v9fs_set_tag(tc, n);
+ if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
+ char buf[150];
+
+ v9fs_printfcall(buf, sizeof(buf), tc, *m->extended);
+ printk(KERN_NOTICE "<<< %p %s\n", m, buf);
+ }
+
req->tag = n;
req->tcall = tc;
req->rcall = NULL;
@@ -761,9 +776,8 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
return req;
}
-static inline void
-v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc,
- int err)
+static void v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc,
+ struct v9fs_fcall *rc, int err)
{
v9fs_mux_req_callback cb;
int tag;
@@ -901,6 +915,7 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
return err;
}
+#if 0
/**
* v9fs_mux_rpcnb - sends 9P request without waiting for response.
* @m: mux data
@@ -924,6 +939,7 @@ int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
dprintk(DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
return 0;
}
+#endif /* 0 */
/**
* v9fs_mux_cancel - cancel all pending requests with error
@@ -963,7 +979,7 @@ static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
{
int tag;
- tag = v9fs_get_idpool(&m->tidpool);
+ tag = v9fs_get_idpool(&m->tagpool);
if (tag < 0)
return V9FS_NOTAG;
else
@@ -972,6 +988,6 @@ static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag)
{
- if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tidpool))
- v9fs_put_idpool(tag, &m->tidpool);
+ if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tagpool))
+ v9fs_put_idpool(tag, &m->tagpool);
}
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
index 9473b84f24b2..e90bfd32ea42 100644
--- a/fs/9p/mux.h
+++ b/fs/9p/mux.h
@@ -7,9 +7,8 @@
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -50,8 +49,6 @@ void v9fs_mux_destroy(struct v9fs_mux_data *);
int v9fs_mux_send(struct v9fs_mux_data *m, struct v9fs_fcall *tc);
struct v9fs_fcall *v9fs_mux_recv(struct v9fs_mux_data *m);
int v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, struct v9fs_fcall **rc);
-int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
- v9fs_mux_req_callback cb, void *a);
void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush);
void v9fs_mux_cancel(struct v9fs_mux_data *m, int err);
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
index 5b2ce21b10fa..94e0a7fd9fc2 100644
--- a/fs/9p/trans_fd.c
+++ b/fs/9p/trans_fd.c
@@ -1,15 +1,16 @@
/*
* linux/fs/9p/trans_fd.c
*
- * File Descriptor Transport Layer
+ * Fd transport layer. Includes deprecated socket layer.
*
- * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
+ * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -25,6 +26,7 @@
*/
#include <linux/config.h>
+#include <linux/in.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/ipv6.h>
@@ -40,89 +42,119 @@
#include "v9fs.h"
#include "transport.h"
+#define V9FS_PORT 564
+
struct v9fs_trans_fd {
- struct file *in_file;
- struct file *out_file;
+ struct file *rd;
+ struct file *wr;
};
/**
- * v9fs_fd_recv - receive from a socket
+ * v9fs_fd_read- read from a fd
* @v9ses: session information
* @v: buffer to receive data into
* @len: size of receive buffer
*
*/
-
-static int v9fs_fd_recv(struct v9fs_transport *trans, void *v, int len)
+static int v9fs_fd_read(struct v9fs_transport *trans, void *v, int len)
{
- struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
+ int ret;
+ struct v9fs_trans_fd *ts;
- if (!trans || trans->status != Connected || !ts)
- return -EIO;
+ if (!trans || trans->status == Disconnected || !(ts = trans->priv))
+ return -EREMOTEIO;
- return kernel_read(ts->in_file, ts->in_file->f_pos, v, len);
+ if (!(ts->rd->f_flags & O_NONBLOCK))
+ dprintk(DEBUG_ERROR, "blocking read ...\n");
+
+ ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
+ if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+ trans->status = Disconnected;
+ return ret;
}
/**
- * v9fs_fd_send - send to a socket
+ * v9fs_fd_write - write to a socket
* @v9ses: session information
* @v: buffer to send data from
* @len: size of send buffer
*
*/
-
-static int v9fs_fd_send(struct v9fs_transport *trans, void *v, int len)
+static int v9fs_fd_write(struct v9fs_transport *trans, void *v, int len)
{
- struct v9fs_trans_fd *ts = trans ? trans->priv : NULL;
- mm_segment_t oldfs = get_fs();
- int ret = 0;
+ int ret;
+ mm_segment_t oldfs;
+ struct v9fs_trans_fd *ts;
- if (!trans || trans->status != Connected || !ts)
- return -EIO;
+ if (!trans || trans->status == Disconnected || !(ts = trans->priv))
+ return -EREMOTEIO;
+
+ if (!(ts->wr->f_flags & O_NONBLOCK))
+ dprintk(DEBUG_ERROR, "blocking write ...\n");
oldfs = get_fs();
set_fs(get_ds());
/* The cast to a user pointer is valid due to the set_fs() */
- ret = vfs_write(ts->out_file, (void __user *)v, len, &ts->out_file->f_pos);
+ ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
set_fs(oldfs);
+ if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+ trans->status = Disconnected;
return ret;
}
-/**
- * v9fs_fd_init - initialize file descriptor transport
- * @v9ses: session information
- * @addr: address of server to mount
- * @data: mount options
- *
- */
-
-static int
-v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+static unsigned int
+v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
{
- struct v9fs_trans_fd *ts = NULL;
- struct v9fs_transport *trans = v9ses->transport;
+ int ret, n;
+ struct v9fs_trans_fd *ts;
+ mm_segment_t oldfs;
- if((v9ses->wfdno == ~0) || (v9ses->rfdno == ~0)) {
- printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
- return -ENOPROTOOPT;
- }
+ if (!trans || trans->status != Connected || !(ts = trans->priv))
+ return -EREMOTEIO;
- ts = kmalloc(sizeof(struct v9fs_trans_fd), GFP_KERNEL);
+ if (!ts->rd->f_op || !ts->rd->f_op->poll)
+ return -EIO;
- if (!ts)
- return -ENOMEM;
+ if (!ts->wr->f_op || !ts->wr->f_op->poll)
+ return -EIO;
- ts->in_file = fget( v9ses->rfdno );
- ts->out_file = fget( v9ses->wfdno );
+ oldfs = get_fs();
+ set_fs(get_ds());
- if (!ts->in_file || !ts->out_file) {
- if (ts->in_file)
- fput(ts->in_file);
+ ret = ts->rd->f_op->poll(ts->rd, pt);
+ if (ret < 0)
+ goto end;
- if (ts->out_file)
- fput(ts->out_file);
+ if (ts->rd != ts->wr) {
+ n = ts->wr->f_op->poll(ts->wr, pt);
+ if (n < 0) {
+ ret = n;
+ goto end;
+ }
+ ret = (ret & ~POLLOUT) | (n & ~POLLIN);
+ }
+ end:
+ set_fs(oldfs);
+ return ret;
+}
+
+static int v9fs_fd_open(struct v9fs_session_info *v9ses, int rfd, int wfd)
+{
+ struct v9fs_transport *trans = v9ses->transport;
+ struct v9fs_trans_fd *ts = kmalloc(sizeof(struct v9fs_trans_fd),
+ GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->rd = fget(rfd);
+ ts->wr = fget(wfd);
+ if (!ts->rd || !ts->wr) {
+ if (ts->rd)
+ fput(ts->rd);
+ if (ts->wr)
+ fput(ts->wr);
kfree(ts);
return -EIO;
}
@@ -133,84 +165,145 @@ v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
return 0;
}
-
-/**
- * v9fs_fd_close - shutdown file descriptor
- * @trans: private socket structure
- *
- */
-
-static void v9fs_fd_close(struct v9fs_transport *trans)
+static int v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr,
+ char *data)
{
- struct v9fs_trans_fd *ts;
-
- if (!trans)
- return;
-
- ts = xchg(&trans->priv, NULL);
+ if (v9ses->rfdno == ~0 || v9ses->wfdno == ~0) {
+ printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
+ return -ENOPROTOOPT;
+ }
- if (!ts)
- return;
+ return v9fs_fd_open(v9ses, v9ses->rfdno, v9ses->wfdno);
+}
- trans->status = Disconnected;
- if (ts->in_file)
- fput(ts->in_file);
+static int v9fs_socket_open(struct v9fs_session_info *v9ses,
+ struct socket *csocket)
+{
+ int fd, ret;
+
+ csocket->sk->sk_allocation = GFP_NOIO;
+ if ((fd = sock_map_fd(csocket)) < 0) {
+ eprintk(KERN_ERR, "v9fs_socket_open: failed to map fd\n");
+ ret = fd;
+ release_csocket:
+ sock_release(csocket);
+ return ret;
+ }
- if (ts->out_file)
- fput(ts->out_file);
+ if ((ret = v9fs_fd_open(v9ses, fd, fd)) < 0) {
+ sockfd_put(csocket);
+ eprintk(KERN_ERR, "v9fs_socket_open: failed to open fd\n");
+ goto release_csocket;
+ }
- kfree(ts);
+ ((struct v9fs_trans_fd *)v9ses->transport->priv)->rd->f_flags |=
+ O_NONBLOCK;
+ return 0;
}
-static unsigned int
-v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
+static int v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr,
+ char *data)
{
- int ret, n;
- struct v9fs_trans_fd *ts;
- mm_segment_t oldfs;
+ int ret;
+ struct socket *csocket = NULL;
+ struct sockaddr_in sin_server;
+
+ sin_server.sin_family = AF_INET;
+ sin_server.sin_addr.s_addr = in_aton(addr);
+ sin_server.sin_port = htons(v9ses->port);
+ sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+
+ if (!csocket) {
+ eprintk(KERN_ERR, "v9fs_trans_tcp: problem creating socket\n");
+ return -1;
+ }
- if (!trans)
- return -EIO;
+ ret = csocket->ops->connect(csocket,
+ (struct sockaddr *)&sin_server,
+ sizeof(struct sockaddr_in), 0);
+ if (ret < 0) {
+ eprintk(KERN_ERR,
+ "v9fs_trans_tcp: problem connecting socket to %s\n",
+ addr);
+ return ret;
+ }
- ts = trans->priv;
- if (trans->status != Connected || !ts)
- return -EIO;
+ return v9fs_socket_open(v9ses, csocket);
+}
- oldfs = get_fs();
- set_fs(get_ds());
+static int
+v9fs_unix_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
+{
+ int ret;
+ struct socket *csocket;
+ struct sockaddr_un sun_server;
+
+ if (strlen(addr) > UNIX_PATH_MAX) {
+ eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
+ addr);
+ return -ENAMETOOLONG;
+ }
- if (!ts->in_file->f_op || !ts->in_file->f_op->poll) {
- ret = -EIO;
- goto end;
+ sun_server.sun_family = PF_UNIX;
+ strcpy(sun_server.sun_path, addr);
+ sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+ ret = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
+ sizeof(struct sockaddr_un) - 1, 0);
+ if (ret < 0) {
+ eprintk(KERN_ERR,
+ "v9fs_trans_unix: problem connecting socket: %s: %d\n",
+ addr, ret);
+ return ret;
}
- ret = ts->in_file->f_op->poll(ts->in_file, pt);
+ return v9fs_socket_open(v9ses, csocket);
+}
- if (ts->out_file != ts->in_file) {
- if (!ts->out_file->f_op || !ts->out_file->f_op->poll) {
- ret = -EIO;
- goto end;
- }
+/**
+ * v9fs_sock_close - shutdown socket
+ * @trans: private socket structure
+ *
+ */
+static void v9fs_fd_close(struct v9fs_transport *trans)
+{
+ struct v9fs_trans_fd *ts;
- n = ts->out_file->f_op->poll(ts->out_file, pt);
+ if (!trans)
+ return;
- ret &= ~POLLOUT;
- n &= ~POLLIN;
+ ts = xchg(&trans->priv, NULL);
- ret |= n;
- }
+ if (!ts)
+ return;
-end:
- set_fs(oldfs);
- return ret;
+ trans->status = Disconnected;
+ if (ts->rd)
+ fput(ts->rd);
+ if (ts->wr)
+ fput(ts->wr);
+ kfree(ts);
}
-
struct v9fs_transport v9fs_trans_fd = {
.init = v9fs_fd_init,
- .write = v9fs_fd_send,
- .read = v9fs_fd_recv,
+ .write = v9fs_fd_write,
+ .read = v9fs_fd_read,
.close = v9fs_fd_close,
.poll = v9fs_fd_poll,
};
+struct v9fs_transport v9fs_trans_tcp = {
+ .init = v9fs_tcp_init,
+ .write = v9fs_fd_write,
+ .read = v9fs_fd_read,
+ .close = v9fs_fd_close,
+ .poll = v9fs_fd_poll,
+};
+
+struct v9fs_transport v9fs_trans_unix = {
+ .init = v9fs_unix_init,
+ .write = v9fs_fd_write,
+ .read = v9fs_fd_read,
+ .close = v9fs_fd_close,
+ .poll = v9fs_fd_poll,
+};
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c
deleted file mode 100644
index 44e830697acb..000000000000
--- a/fs/9p/trans_sock.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * linux/fs/9p/trans_socket.c
- *
- * Socket Transport Layer
- *
- * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.com>
- * Copyright (C) 1995, 1996 by Olaf Kirch <okir@monad.swb.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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/config.h>
-#include <linux/in.h>
-#include <linux/module.h>
-#include <linux/net.h>
-#include <linux/ipv6.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/un.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/idr.h>
-#include <linux/file.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "transport.h"
-
-#define V9FS_PORT 564
-
-struct v9fs_trans_sock {
- struct socket *s;
- struct file *filp;
-};
-
-/**
- * v9fs_sock_recv - receive from a socket
- * @v9ses: session information
- * @v: buffer to receive data into
- * @len: size of receive buffer
- *
- */
-
-static int v9fs_sock_recv(struct v9fs_transport *trans, void *v, int len)
-{
- int ret;
- struct v9fs_trans_sock *ts;
-
- if (!trans || trans->status == Disconnected) {
- dprintk(DEBUG_ERROR, "disconnected ...\n");
- return -EREMOTEIO;
- }
-
- ts = trans->priv;
-
- if (!(ts->filp->f_flags & O_NONBLOCK))
- dprintk(DEBUG_ERROR, "blocking read ...\n");
-
- ret = kernel_read(ts->filp, ts->filp->f_pos, v, len);
- if (ret <= 0) {
- if (ret != -ERESTARTSYS && ret != -EAGAIN)
- trans->status = Disconnected;
- }
-
- return ret;
-}
-
-/**
- * v9fs_sock_send - send to a socket
- * @v9ses: session information
- * @v: buffer to send data from
- * @len: size of send buffer
- *
- */
-
-static int v9fs_sock_send(struct v9fs_transport *trans, void *v, int len)
-{
- int ret;
- mm_segment_t oldfs;
- struct v9fs_trans_sock *ts;
-
- if (!trans || trans->status == Disconnected) {
- dprintk(DEBUG_ERROR, "disconnected ...\n");
- return -EREMOTEIO;
- }
-
- ts = trans->priv;
- if (!ts) {
- dprintk(DEBUG_ERROR, "no transport ...\n");
- return -EREMOTEIO;
- }
-
- if (!(ts->filp->f_flags & O_NONBLOCK))
- dprintk(DEBUG_ERROR, "blocking write ...\n");
-
- oldfs = get_fs();
- set_fs(get_ds());
- ret = vfs_write(ts->filp, (void __user *)v, len, &ts->filp->f_pos);
- set_fs(oldfs);
-
- if (ret < 0) {
- if (ret != -ERESTARTSYS)
- trans->status = Disconnected;
- }
-
- return ret;
-}
-
-static unsigned int v9fs_sock_poll(struct v9fs_transport *trans,
- struct poll_table_struct *pt) {
-
- int ret;
- struct v9fs_trans_sock *ts;
- mm_segment_t oldfs;
-
- if (!trans) {
- dprintk(DEBUG_ERROR, "no transport\n");
- return -EIO;
- }
-
- ts = trans->priv;
- if (trans->status != Connected || !ts) {
- dprintk(DEBUG_ERROR, "transport disconnected: %d\n", trans->status);
- return -EIO;
- }
-
- oldfs = get_fs();
- set_fs(get_ds());
-
- if (!ts->filp->f_op || !ts->filp->f_op->poll) {
- dprintk(DEBUG_ERROR, "no poll operation\n");
- ret = -EIO;
- goto end;
- }
-
- ret = ts->filp->f_op->poll(ts->filp, pt);
-
-end:
- set_fs(oldfs);
- return ret;
-}
-
-
-/**
- * v9fs_tcp_init - initialize TCP socket
- * @v9ses: session information
- * @addr: address of server to mount
- * @data: mount options
- *
- */
-
-static int
-v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
-{
- struct socket *csocket = NULL;
- struct sockaddr_in sin_server;
- int rc = 0;
- struct v9fs_trans_sock *ts = NULL;
- struct v9fs_transport *trans = v9ses->transport;
- int fd;
-
- trans->status = Disconnected;
-
- ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
-
- if (!ts)
- return -ENOMEM;
-
- trans->priv = ts;
- ts->s = NULL;
- ts->filp = NULL;
-
- if (!addr)
- return -EINVAL;
-
- dprintk(DEBUG_TRANS, "Connecting to %s\n", addr);
-
- sin_server.sin_family = AF_INET;
- sin_server.sin_addr.s_addr = in_aton(addr);
- sin_server.sin_port = htons(v9ses->port);
- sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
- rc = csocket->ops->connect(csocket,
- (struct sockaddr *)&sin_server,
- sizeof(struct sockaddr_in), 0);
- if (rc < 0) {
- eprintk(KERN_ERR,
- "v9fs_trans_tcp: problem connecting socket to %s\n",
- addr);
- return rc;
- }
- csocket->sk->sk_allocation = GFP_NOIO;
-
- fd = sock_map_fd(csocket);
- if (fd < 0) {
- sock_release(csocket);
- kfree(ts);
- trans->priv = NULL;
- return fd;
- }
-
- ts->s = csocket;
- ts->filp = fget(fd);
- ts->filp->f_flags |= O_NONBLOCK;
- trans->status = Connected;
-
- return 0;
-}
-
-/**
- * v9fs_unix_init - initialize UNIX domain socket
- * @v9ses: session information
- * @dev_name: path to named pipe
- * @data: mount options
- *
- */
-
-static int
-v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
- char *data)
-{
- int rc, fd;
- struct socket *csocket;
- struct sockaddr_un sun_server;
- struct v9fs_transport *trans;
- struct v9fs_trans_sock *ts;
-
- rc = 0;
- csocket = NULL;
- trans = v9ses->transport;
-
- trans->status = Disconnected;
-
- if (strlen(dev_name) > UNIX_PATH_MAX) {
- eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
- dev_name);
- return -ENOMEM;
- }
-
- ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
- if (!ts)
- return -ENOMEM;
-
- trans->priv = ts;
- ts->s = NULL;
- ts->filp = NULL;
-
- sun_server.sun_family = PF_UNIX;
- strcpy(sun_server.sun_path, dev_name);
- sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
- rc = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
- sizeof(struct sockaddr_un) - 1, 0); /* -1 *is* important */
- if (rc < 0) {
- eprintk(KERN_ERR,
- "v9fs_trans_unix: problem connecting socket: %s: %d\n",
- dev_name, rc);
- return rc;
- }
- csocket->sk->sk_allocation = GFP_NOIO;
-
- fd = sock_map_fd(csocket);
- if (fd < 0) {
- sock_release(csocket);
- kfree(ts);
- trans->priv = NULL;
- return fd;
- }
-
- ts->s = csocket;
- ts->filp = fget(fd);
- ts->filp->f_flags |= O_NONBLOCK;
- trans->status = Connected;
-
- return 0;
-}
-
-/**
- * v9fs_sock_close - shutdown socket
- * @trans: private socket structure
- *
- */
-
-static void v9fs_sock_close(struct v9fs_transport *trans)
-{
- struct v9fs_trans_sock *ts;
-
- if (!trans)
- return;
-
- ts = trans->priv;
-
- if ((ts) && (ts->filp)) {
- fput(ts->filp);
- ts->filp = NULL;
- ts->s = NULL;
- trans->status = Disconnected;
- }
-
- kfree(ts);
-
- trans->priv = NULL;
-}
-
-struct v9fs_transport v9fs_trans_tcp = {
- .init = v9fs_tcp_init,
- .write = v9fs_sock_send,
- .read = v9fs_sock_recv,
- .close = v9fs_sock_close,
- .poll = v9fs_sock_poll,
-};
-
-struct v9fs_transport v9fs_trans_unix = {
- .init = v9fs_unix_init,
- .write = v9fs_sock_send,
- .read = v9fs_sock_recv,
- .close = v9fs_sock_close,
- .poll = v9fs_sock_poll,
-};
diff --git a/fs/9p/transport.h b/fs/9p/transport.h
index 91fcdb94b361..b38a4b8a41ce 100644
--- a/fs/9p/transport.h
+++ b/fs/9p/transport.h
@@ -7,9 +7,8 @@
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 61352491ba36..d37416eb5791 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -7,9 +7,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -51,7 +50,7 @@ enum {
Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug,
Opt_rfdno, Opt_wfdno,
/* String options */
- Opt_name, Opt_remotename,
+ Opt_uname, Opt_remotename,
/* Options that take no arguments */
Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
/* Error token */
@@ -67,7 +66,7 @@ static match_table_t tokens = {
{Opt_rfdno, "rfdno=%u"},
{Opt_wfdno, "wfdno=%u"},
{Opt_debug, "debug=%x"},
- {Opt_name, "name=%s"},
+ {Opt_uname, "uname=%s"},
{Opt_remotename, "aname=%s"},
{Opt_unix, "proto=unix"},
{Opt_tcp, "proto=tcp"},
@@ -116,7 +115,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
if (!*p)
continue;
token = match_token(p, tokens, args);
- if (token < Opt_name) {
+ if (token < Opt_uname) {
if ((ret = match_int(&args[0], &option)) < 0) {
dprintk(DEBUG_ERROR,
"integer field, but no integer?\n");
@@ -158,7 +157,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
case Opt_fd:
v9ses->proto = PROTO_FD;
break;
- case Opt_name:
+ case Opt_uname:
match_strcpy(v9ses->name, &args[0]);
break;
case Opt_remotename:
@@ -289,7 +288,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
/* set global debug level */
v9fs_debug_level = v9ses->debug;
- /* id pools that are session-dependent: FIDs and TIDs */
+ /* id pools that are session-dependent: fids and tags */
idr_init(&v9ses->fidpool.pool);
init_MUTEX(&v9ses->fidpool.lock);
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index f337da7a0eec..c134d104cb28 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -5,9 +5,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -91,6 +90,3 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses);
#define V9FS_DEFUSER "nobody"
#define V9FS_DEFANAME ""
-/* inital pool sizes for fids and tags */
-#define V9FS_START_FIDS 8192
-#define V9FS_START_TIDS 256
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index a759278acaae..f867b8d3e973 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -5,9 +5,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -40,8 +39,8 @@
extern struct file_system_type v9fs_fs_type;
extern struct address_space_operations v9fs_addr_operations;
-extern struct file_operations v9fs_file_operations;
-extern struct file_operations v9fs_dir_operations;
+extern const struct file_operations v9fs_file_operations;
+extern const struct file_operations v9fs_dir_operations;
extern struct dentry_operations v9fs_dentry_operations;
struct inode *v9fs_get_inode(struct super_block *sb, int mode);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 8100fb5171b7..efda46fb64d9 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -7,9 +7,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 12c9cc926b71..062daa6000ab 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -7,9 +7,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -51,7 +50,7 @@
*
*/
-int v9fs_dentry_delete(struct dentry *dentry)
+static int v9fs_dentry_delete(struct dentry *dentry)
{
dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
return 1;
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index cd5eeb032d64..e32d5971039b 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -7,9 +7,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -205,7 +204,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
return 0;
}
-struct file_operations v9fs_dir_operations = {
+const struct file_operations v9fs_dir_operations = {
.read = generic_read_dir,
.readdir = v9fs_dir_readdir,
.open = v9fs_file_open,
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index de3a129698da..083dcfcd158e 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -7,9 +7,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -69,29 +68,30 @@ int v9fs_file_open(struct inode *inode, struct file *file)
fid = v9fs_get_idpool(&v9ses->fidpool);
if (fid < 0) {
- eprintk(KERN_WARNING, "newfid fails!\n");
- return -ENOSPC;
- }
+ eprintk(KERN_WARNING, "newfid fails!\n");
+ return -ENOSPC;
+ }
err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL);
if (err < 0) {
- dprintk(DEBUG_ERROR, "rewalk didn't work\n");
+ dprintk(DEBUG_ERROR, "rewalk didn't work\n");
goto put_fid;
}
- vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
- if (vfid == NULL) {
- dprintk(DEBUG_ERROR, "out of memory\n");
- goto clunk_fid;
- }
-
- /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
- /* translate open mode appropriately */
+ /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
+ /* translate open mode appropriately */
omode = v9fs_uflags2omode(file->f_flags);
err = v9fs_t_open(v9ses, fid, omode, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("open failed", fcall);
- goto destroy_vfid;
+ goto clunk_fid;
+ }
+
+ vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
+ if (vfid == NULL) {
+ dprintk(DEBUG_ERROR, "out of memory\n");
+ err = -ENOMEM;
+ goto clunk_fid;
}
file->private_data = vfid;
@@ -106,15 +106,12 @@ int v9fs_file_open(struct inode *inode, struct file *file)
return 0;
-destroy_vfid:
- v9fs_fid_destroy(vfid);
-
clunk_fid:
v9fs_t_clunk(v9ses, fid);
put_fid:
v9fs_put_idpool(fid, &v9ses->fidpool);
- kfree(fcall);
+ kfree(fcall);
return err;
}
@@ -269,7 +266,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
return total;
}
-struct file_operations v9fs_file_operations = {
+const struct file_operations v9fs_file_operations = {
.llseek = generic_file_llseek,
.read = v9fs_file_read,
.write = v9fs_file_write,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 3ad8455f8577..133db366d306 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -7,9 +7,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -255,8 +254,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
}
static int
-v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
- u32 perm, u8 mode, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
+v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
+ u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
{
u32 fid;
int err;
@@ -271,14 +270,14 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("clone error", fcall);
- goto error;
+ goto put_fid;
}
kfree(fcall);
- err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall);
+ err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("create fails", fcall);
- goto error;
+ goto clunk_fid;
}
if (iounit)
@@ -293,7 +292,11 @@ v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name,
kfree(fcall);
return 0;
-error:
+clunk_fid:
+ v9fs_t_clunk(v9ses, fid);
+ fid = V9FS_NOFID;
+
+put_fid:
if (fid >= 0)
v9fs_put_idpool(fid, &v9ses->fidpool);
@@ -348,7 +351,7 @@ error:
return ERR_PTR(err);
}
-struct inode *
+static struct inode *
v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
struct super_block *sb)
{
@@ -474,7 +477,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
flags = O_RDWR;
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit);
+ perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
if (err)
goto error;
@@ -550,7 +553,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, V9FS_OREAD, &fid, NULL, NULL);
+ perm, V9FS_OREAD, NULL, &fid, NULL, NULL);
if (err) {
dprintk(DEBUG_ERROR, "create error %d\n", err);
@@ -614,6 +617,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
sb = dir->i_sb;
v9ses = v9fs_inode2v9ses(dir);
+ dentry->d_op = &v9fs_dentry_operations;
dirfid = v9fs_fid_lookup(dentry->d_parent);
if (!dirfid) {
@@ -681,8 +685,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
goto FreeFcall;
fid->qid = fcall->params.rstat.stat.qid;
-
- dentry->d_op = &v9fs_dentry_operations;
v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
d_add(dentry, inode);
@@ -1009,11 +1011,13 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
/* copy extension buffer into buffer */
if (fcall->params.rstat.stat.extension.len < buflen)
- buflen = fcall->params.rstat.stat.extension.len;
+ buflen = fcall->params.rstat.stat.extension.len + 1;
- memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
+ memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
buffer[buflen-1] = 0;
+ dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len,
+ fcall->params.rstat.stat.extension.str, buffer);
retval = buflen;
FreeFcall:
@@ -1073,7 +1077,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
if (!link)
link = ERR_PTR(-ENOMEM);
else {
- len = v9fs_readlink(dentry, link, strlen(link));
+ len = v9fs_readlink(dentry, link, PATH_MAX);
if (len < 0) {
__putname(link);
@@ -1110,10 +1114,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
struct v9fs_session_info *v9ses;
struct v9fs_fid *dfid, *vfid;
struct inode *inode;
- struct v9fs_fcall *fcall;
- struct v9fs_wstat wstat;
- fcall = NULL;
inode = NULL;
vfid = NULL;
v9ses = v9fs_inode2v9ses(dir);
@@ -1126,7 +1127,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
}
err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, V9FS_OREAD, &fid, NULL, NULL);
+ perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
if (err)
goto error;
@@ -1149,23 +1150,11 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
goto error;
}
- /* issue a Twstat */
- v9fs_blank_wstat(&wstat);
- wstat.muid = v9ses->name;
- wstat.extension = (char *) extension;
- err = v9fs_t_wstat(v9ses, vfid->fid, &wstat, &fcall);
- if (err < 0) {
- PRINT_FCALL_ERROR("wstat error", fcall);
- goto error;
- }
-
- kfree(fcall);
dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode);
return 0;
error:
- kfree(fcall);
if (vfid)
v9fs_fid_destroy(vfid);
@@ -1225,7 +1214,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
}
name = __getname();
- sprintf(name, "hardlink(%d)\n", oldfid->fid);
+ sprintf(name, "%d\n", oldfid->fid);
retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
__putname(name);
@@ -1254,6 +1243,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
return -EINVAL;
name = __getname();
+ if (!name)
+ return -ENOMEM;
/* build extension */
if (S_ISBLK(mode))
sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index d05318fa684e..b0a0ae509c00 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -8,9 +8,8 @@
* 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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
@@ -262,7 +261,7 @@ static struct super_operations v9fs_super_ops = {
};
struct file_system_type v9fs_fs_type = {
- .name = "9P",
+ .name = "9p",
.get_sb = v9fs_get_sb,
.kill_sb = v9fs_kill_super,
.owner = THIS_MODULE,