mirror of https://gitee.com/openkylin/linux.git
[PATCH] v9fs: zero copy implementation
Performance enhancement reducing the number of copies in the data and stat paths. Signed-off-by: Latchesar Ionkov <lucho@ionkov.net> Cc: Eric Van Hensbergen <ericvh@ericvh.myip.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
d8da097afb
commit
531b1094b7
292
fs/9p/9p.c
292
fs/9p/9p.c
|
@ -1,8 +1,9 @@
|
|||
/*
|
||||
* linux/fs/9p/9p.c
|
||||
*
|
||||
* This file contains functions 9P2000 functions
|
||||
* 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>
|
||||
*
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "debug.h"
|
||||
#include "v9fs.h"
|
||||
#include "9p.h"
|
||||
#include "conv.h"
|
||||
#include "mux.h"
|
||||
|
||||
/**
|
||||
|
@ -46,17 +48,21 @@
|
|||
|
||||
int
|
||||
v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
|
||||
char *version, struct v9fs_fcall **fcall)
|
||||
char *version, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
|
||||
dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
|
||||
msg.id = TVERSION;
|
||||
msg.tag = ~0;
|
||||
msg.params.tversion.msize = msize;
|
||||
msg.params.tversion.version = version;
|
||||
tc = v9fs_create_tversion(msize, version);
|
||||
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
if (!IS_ERR(tc)) {
|
||||
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
|
||||
kfree(tc);
|
||||
} else
|
||||
ret = PTR_ERR(tc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,19 +78,23 @@ v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
|
|||
|
||||
int
|
||||
v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
|
||||
u32 fid, u32 afid, struct v9fs_fcall **fcall)
|
||||
u32 fid, u32 afid, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall* tc;
|
||||
|
||||
dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
|
||||
aname, fid, afid);
|
||||
msg.id = TATTACH;
|
||||
msg.params.tattach.fid = fid;
|
||||
msg.params.tattach.afid = afid;
|
||||
msg.params.tattach.uname = uname;
|
||||
msg.params.tattach.aname = aname;
|
||||
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
ret = -ENOMEM;
|
||||
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,
|
||||
|
@ -117,24 +127,28 @@ static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
|
|||
* @fcall: pointer to response fcall pointer
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
|
||||
{
|
||||
int err;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc, *rc;
|
||||
|
||||
tc = kmalloc(sizeof(struct v9fs_fcall), GFP_KERNEL);
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d\n", fid);
|
||||
tc->id = TCLUNK;
|
||||
tc->params.tclunk.fid = fid;
|
||||
|
||||
err = v9fs_mux_rpc(v9ses->mux, tc, &rc);
|
||||
if (err >= 0) {
|
||||
v9fs_t_clunk_cb(v9ses, tc, rc, 0);
|
||||
}
|
||||
ret = -ENOMEM;
|
||||
rc = NULL;
|
||||
tc = v9fs_create_tclunk(fid);
|
||||
if (!IS_ERR(tc))
|
||||
ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
|
||||
else
|
||||
ret = PTR_ERR(tc);
|
||||
|
||||
return err;
|
||||
if (ret)
|
||||
dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret);
|
||||
|
||||
v9fs_t_clunk_cb(v9ses, tc, rc, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,14 +158,22 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
|
|||
*
|
||||
*/
|
||||
|
||||
int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
|
||||
int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
|
||||
dprintk(DEBUG_9P, "oldtag %d\n", tag);
|
||||
msg.id = TFLUSH;
|
||||
msg.params.tflush.oldtag = tag;
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, NULL);
|
||||
dprintk(DEBUG_9P, "oldtag %d\n", oldtag);
|
||||
|
||||
ret = -ENOMEM;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,17 +185,22 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
|
|||
*/
|
||||
|
||||
int
|
||||
v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
|
||||
v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d\n", fid);
|
||||
if (fcall)
|
||||
*fcall = NULL;
|
||||
|
||||
msg.id = TSTAT;
|
||||
msg.params.tstat.fid = fid;
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -187,16 +214,22 @@ v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
|
|||
|
||||
int
|
||||
v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
|
||||
struct v9fs_stat *stat, struct v9fs_fcall **fcall)
|
||||
struct v9fs_wstat *wstat, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d length %d\n", fid, (int)stat->length);
|
||||
msg.id = TWSTAT;
|
||||
msg.params.twstat.fid = fid;
|
||||
msg.params.twstat.stat = stat;
|
||||
dprintk(DEBUG_9P, "fid %d\n", fid);
|
||||
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
ret = -ENOMEM;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,23 +246,28 @@ v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
|
|||
|
||||
int
|
||||
v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
|
||||
char *name, struct v9fs_fcall **fcall)
|
||||
char *name, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
int nwname;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
|
||||
msg.id = TWALK;
|
||||
msg.params.twalk.fid = fid;
|
||||
msg.params.twalk.newfid = newfid;
|
||||
|
||||
if (name) {
|
||||
msg.params.twalk.nwname = 1;
|
||||
msg.params.twalk.wnames = &name;
|
||||
} else {
|
||||
msg.params.twalk.nwname = 0;
|
||||
}
|
||||
if (name)
|
||||
nwname = 1;
|
||||
else
|
||||
nwname = 0;
|
||||
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
ret = -ENOMEM;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,19 +282,22 @@ v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
|
|||
|
||||
int
|
||||
v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
|
||||
struct v9fs_fcall **fcall)
|
||||
struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int errorno = -1;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
|
||||
msg.id = TOPEN;
|
||||
msg.params.topen.fid = fid;
|
||||
msg.params.topen.mode = mode;
|
||||
|
||||
errorno = v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
ret = -ENOMEM;
|
||||
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 errorno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,14 +310,22 @@ v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
|
|||
|
||||
int
|
||||
v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
|
||||
struct v9fs_fcall **fcall)
|
||||
struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d\n", fid);
|
||||
msg.id = TREMOVE;
|
||||
msg.params.tremove.fid = fid;
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
|
||||
ret = -ENOMEM;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -292,20 +341,23 @@ 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 **fcall)
|
||||
u32 perm, u8 mode, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
|
||||
fid, name, perm, mode);
|
||||
|
||||
msg.id = TCREATE;
|
||||
msg.params.tcreate.fid = fid;
|
||||
msg.params.tcreate.name = name;
|
||||
msg.params.tcreate.perm = perm;
|
||||
msg.params.tcreate.mode = mode;
|
||||
ret = -ENOMEM;
|
||||
tc = v9fs_create_tcreate(fid, name, perm, mode);
|
||||
if (!IS_ERR(tc)) {
|
||||
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
|
||||
kfree(tc);
|
||||
} else
|
||||
ret = PTR_ERR(tc);
|
||||
|
||||
return v9fs_mux_rpc(v9ses->mux, &msg, fcall);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,31 +372,30 @@ v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
|
|||
|
||||
int
|
||||
v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
|
||||
u32 count, struct v9fs_fcall **fcall)
|
||||
u32 count, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
struct v9fs_fcall *rc = NULL;
|
||||
long errorno = -1;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc, *rc;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d offset 0x%lx count 0x%x\n", fid,
|
||||
(long unsigned int)offset, count);
|
||||
msg.id = TREAD;
|
||||
msg.params.tread.fid = fid;
|
||||
msg.params.tread.offset = offset;
|
||||
msg.params.tread.count = count;
|
||||
errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc);
|
||||
dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
|
||||
(long long unsigned) offset, count);
|
||||
|
||||
if (!errorno) {
|
||||
errorno = rc->params.rread.count;
|
||||
dump_data(rc->params.rread.data, rc->params.rread.count);
|
||||
}
|
||||
ret = -ENOMEM;
|
||||
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);
|
||||
|
||||
if (fcall)
|
||||
*fcall = rc;
|
||||
else
|
||||
kfree(rc);
|
||||
kfree(tc);
|
||||
} else
|
||||
ret = PTR_ERR(tc);
|
||||
|
||||
return errorno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -358,32 +409,31 @@ v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
|
|||
*/
|
||||
|
||||
int
|
||||
v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid,
|
||||
u64 offset, u32 count, void *data, struct v9fs_fcall **fcall)
|
||||
v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count,
|
||||
const char __user *data, struct v9fs_fcall **rcp)
|
||||
{
|
||||
struct v9fs_fcall msg;
|
||||
struct v9fs_fcall *rc = NULL;
|
||||
long errorno = -1;
|
||||
int ret;
|
||||
struct v9fs_fcall *tc, *rc;
|
||||
|
||||
dprintk(DEBUG_9P, "fid %d offset 0x%llx count 0x%x\n", fid,
|
||||
(unsigned long long)offset, count);
|
||||
dump_data(data, count);
|
||||
dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
|
||||
(long long unsigned) offset, count);
|
||||
|
||||
msg.id = TWRITE;
|
||||
msg.params.twrite.fid = fid;
|
||||
msg.params.twrite.offset = offset;
|
||||
msg.params.twrite.count = count;
|
||||
msg.params.twrite.data = data;
|
||||
ret = -ENOMEM;
|
||||
tc = v9fs_create_twrite(fid, offset, count, data);
|
||||
if (!IS_ERR(tc)) {
|
||||
ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
|
||||
|
||||
errorno = v9fs_mux_rpc(v9ses->mux, &msg, &rc);
|
||||
if (!ret)
|
||||
ret = rc->params.rwrite.count;
|
||||
if (rcp)
|
||||
*rcp = rc;
|
||||
else
|
||||
kfree(rc);
|
||||
|
||||
if (!errorno)
|
||||
errorno = rc->params.rwrite.count;
|
||||
kfree(tc);
|
||||
} else
|
||||
ret = PTR_ERR(tc);
|
||||
|
||||
if (fcall)
|
||||
*fcall = rc;
|
||||
else
|
||||
kfree(rc);
|
||||
|
||||
return errorno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
75
fs/9p/9p.h
75
fs/9p/9p.h
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* 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>
|
||||
*
|
||||
|
@ -102,10 +103,16 @@ enum {
|
|||
|
||||
#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;
|
||||
|
@ -115,6 +122,29 @@ struct v9fs_qid {
|
|||
|
||||
/* 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;
|
||||
|
@ -131,25 +161,24 @@ struct v9fs_stat {
|
|||
u32 n_uid; /* 9p2000.u extensions */
|
||||
u32 n_gid; /* 9p2000.u extensions */
|
||||
u32 n_muid; /* 9p2000.u extensions */
|
||||
char data[0];
|
||||
};
|
||||
|
||||
/* Structures for Protocol Operations */
|
||||
|
||||
struct Tversion {
|
||||
u32 msize;
|
||||
char *version;
|
||||
struct v9fs_str version;
|
||||
};
|
||||
|
||||
struct Rversion {
|
||||
u32 msize;
|
||||
char *version;
|
||||
struct v9fs_str version;
|
||||
};
|
||||
|
||||
struct Tauth {
|
||||
u32 afid;
|
||||
char *uname;
|
||||
char *aname;
|
||||
struct v9fs_str uname;
|
||||
struct v9fs_str aname;
|
||||
};
|
||||
|
||||
struct Rauth {
|
||||
|
@ -157,12 +186,12 @@ struct Rauth {
|
|||
};
|
||||
|
||||
struct Rerror {
|
||||
char *error;
|
||||
struct v9fs_str error;
|
||||
u32 errno; /* 9p2000.u extension */
|
||||
};
|
||||
|
||||
struct Tflush {
|
||||
u32 oldtag;
|
||||
u16 oldtag;
|
||||
};
|
||||
|
||||
struct Rflush {
|
||||
|
@ -171,8 +200,8 @@ struct Rflush {
|
|||
struct Tattach {
|
||||
u32 fid;
|
||||
u32 afid;
|
||||
char *uname;
|
||||
char *aname;
|
||||
struct v9fs_str uname;
|
||||
struct v9fs_str aname;
|
||||
};
|
||||
|
||||
struct Rattach {
|
||||
|
@ -182,13 +211,13 @@ struct Rattach {
|
|||
struct Twalk {
|
||||
u32 fid;
|
||||
u32 newfid;
|
||||
u32 nwname;
|
||||
char **wnames;
|
||||
u16 nwname;
|
||||
struct v9fs_str wnames[16];
|
||||
};
|
||||
|
||||
struct Rwalk {
|
||||
u32 nwqid;
|
||||
struct v9fs_qid *wqids;
|
||||
u16 nwqid;
|
||||
struct v9fs_qid wqids[16];
|
||||
};
|
||||
|
||||
struct Topen {
|
||||
|
@ -203,7 +232,7 @@ struct Ropen {
|
|||
|
||||
struct Tcreate {
|
||||
u32 fid;
|
||||
char *name;
|
||||
struct v9fs_str name;
|
||||
u32 perm;
|
||||
u8 mode;
|
||||
};
|
||||
|
@ -254,12 +283,12 @@ struct Tstat {
|
|||
};
|
||||
|
||||
struct Rstat {
|
||||
struct v9fs_stat *stat;
|
||||
struct v9fs_stat stat;
|
||||
};
|
||||
|
||||
struct Twstat {
|
||||
u32 fid;
|
||||
struct v9fs_stat *stat;
|
||||
struct v9fs_stat stat;
|
||||
};
|
||||
|
||||
struct Rwstat {
|
||||
|
@ -274,6 +303,7 @@ struct v9fs_fcall {
|
|||
u32 size;
|
||||
u8 id;
|
||||
u16 tag;
|
||||
void *sdata;
|
||||
|
||||
union {
|
||||
struct Tversion tversion;
|
||||
|
@ -306,10 +336,12 @@ struct v9fs_fcall {
|
|||
} params;
|
||||
};
|
||||
|
||||
#define V9FS_FCALLHDRSZ (sizeof(struct v9fs_fcall) + \
|
||||
sizeof(struct v9fs_stat) + 16*sizeof(struct v9fs_qid) + 16)
|
||||
#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:"");
|
||||
|
||||
#define FCALL_ERROR(fcall) (fcall ? fcall->params.rerror.error : "")
|
||||
char *v9fs_str_copy(char *buf, int buflen, struct v9fs_str *str);
|
||||
int v9fs_str_compare(char *buf, struct v9fs_str *str);
|
||||
|
||||
int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
|
||||
char *version, struct v9fs_fcall **rcall);
|
||||
|
@ -325,7 +357,7 @@ 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_stat *stat, struct v9fs_fcall **rcall);
|
||||
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);
|
||||
|
@ -343,4 +375,5 @@ 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, void *data, struct v9fs_fcall **rcall);
|
||||
u32 count, const char __user * data,
|
||||
struct v9fs_fcall **rcall);
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
obj-$(CONFIG_9P_FS) := 9p2000.o
|
||||
|
||||
9p2000-objs := \
|
||||
trans_fd.o \
|
||||
trans_sock.o \
|
||||
mux.o \
|
||||
9p.o \
|
||||
conv.o \
|
||||
vfs_super.o \
|
||||
vfs_inode.o \
|
||||
vfs_file.o \
|
||||
vfs_dir.o \
|
||||
vfs_dentry.o \
|
||||
error.o \
|
||||
mux.o \
|
||||
trans_fd.o \
|
||||
trans_sock.o \
|
||||
9p.o \
|
||||
conv.o \
|
||||
v9fs.o \
|
||||
fid.o
|
||||
|
||||
|
|
897
fs/9p/conv.c
897
fs/9p/conv.c
File diff suppressed because it is too large
Load Diff
28
fs/9p/conv.h
28
fs/9p/conv.h
|
@ -1,8 +1,9 @@
|
|||
/*
|
||||
* linux/fs/9p/conv.h
|
||||
*
|
||||
* 9P protocol conversion definitions
|
||||
* 9P protocol conversion 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>
|
||||
*
|
||||
|
@ -25,11 +26,26 @@
|
|||
*/
|
||||
|
||||
int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
|
||||
u32 statlen, int extended);
|
||||
int v9fs_serialize_fcall(struct v9fs_fcall *tcall, void *buf, u32 buflen,
|
||||
int extended);
|
||||
int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
|
||||
int rcalllen, int extended);
|
||||
int extended);
|
||||
|
||||
/* this one is actually in error.c right now */
|
||||
int v9fs_errstr2errno(char *errstr);
|
||||
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_tread(u32 fid, u64 offset, u32 count);
|
||||
struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
|
||||
const char __user *data);
|
||||
struct v9fs_fcall *v9fs_create_tclunk(u32 fid);
|
||||
struct v9fs_fcall *v9fs_create_tremove(u32 fid);
|
||||
struct v9fs_fcall *v9fs_create_tstat(u32 fid);
|
||||
struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
|
||||
int extended);
|
||||
|
|
|
@ -51,16 +51,23 @@ do { \
|
|||
#if DEBUG_DUMP_PKT
|
||||
static inline void dump_data(const unsigned char *data, unsigned int datalen)
|
||||
{
|
||||
int i, j;
|
||||
int len = datalen;
|
||||
int i, n;
|
||||
char buf[5*8];
|
||||
|
||||
printk(KERN_DEBUG "data ");
|
||||
for (i = 0; i < len; i += 4) {
|
||||
for (j = 0; (j < 4) && (i + j < len); j++)
|
||||
printk(KERN_DEBUG "%02x", data[i + j]);
|
||||
printk(KERN_DEBUG " ");
|
||||
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;
|
||||
}
|
||||
}
|
||||
printk(KERN_DEBUG "\n");
|
||||
|
||||
dprintk(DEBUG_ERROR, "%s\n", buf);
|
||||
}
|
||||
#else /* DEBUG_DUMP_PKT */
|
||||
static inline void dump_data(const unsigned char *data, unsigned int datalen)
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include <linux/list.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "error.h"
|
||||
|
@ -55,7 +54,8 @@ int v9fs_error_init(void)
|
|||
|
||||
/* load initial error map into hash table */
|
||||
for (c = errmap; c->name != NULL; c++) {
|
||||
bucket = jhash(c->name, strlen(c->name), 0) % ERRHASHSZ;
|
||||
c->namelen = strlen(c->name);
|
||||
bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
|
||||
INIT_HLIST_NODE(&c->list);
|
||||
hlist_add_head(&c->list, &hash_errmap[bucket]);
|
||||
}
|
||||
|
@ -69,15 +69,15 @@ int v9fs_error_init(void)
|
|||
*
|
||||
*/
|
||||
|
||||
int v9fs_errstr2errno(char *errstr)
|
||||
int v9fs_errstr2errno(char *errstr, int len)
|
||||
{
|
||||
int errno = 0;
|
||||
struct hlist_node *p = NULL;
|
||||
struct errormap *c = NULL;
|
||||
int bucket = jhash(errstr, strlen(errstr), 0) % ERRHASHSZ;
|
||||
int bucket = jhash(errstr, len, 0) % ERRHASHSZ;
|
||||
|
||||
hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
|
||||
if (!strcmp(c->name, errstr)) {
|
||||
if (c->namelen==len && !memcmp(c->name, errstr, len)) {
|
||||
errno = c->val;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ struct errormap {
|
|||
char *name;
|
||||
int val;
|
||||
|
||||
int namelen;
|
||||
struct hlist_node list;
|
||||
};
|
||||
|
||||
|
@ -175,4 +176,4 @@ static struct errormap errmap[] = {
|
|||
};
|
||||
|
||||
extern int v9fs_error_init(void);
|
||||
extern int v9fs_errstr2errno(char *errstr);
|
||||
extern int v9fs_errstr2errno(char *errstr, int len);
|
||||
|
|
|
@ -31,9 +31,6 @@
|
|||
#include "v9fs.h"
|
||||
#include "9p.h"
|
||||
#include "v9fs_vfs.h"
|
||||
#include "transport.h"
|
||||
#include "mux.h"
|
||||
#include "conv.h"
|
||||
#include "fid.h"
|
||||
|
||||
/**
|
||||
|
|
157
fs/9p/mux.c
157
fs/9p/mux.c
|
@ -35,8 +35,8 @@
|
|||
#include "debug.h"
|
||||
#include "v9fs.h"
|
||||
#include "9p.h"
|
||||
#include "transport.h"
|
||||
#include "conv.h"
|
||||
#include "transport.h"
|
||||
#include "mux.h"
|
||||
|
||||
#define ERREQFLUSH 1
|
||||
|
@ -74,6 +74,7 @@ struct v9fs_mux_data {
|
|||
wait_queue_head_t equeue;
|
||||
struct list_head req_list;
|
||||
struct list_head unsent_req_list;
|
||||
struct v9fs_fcall *rcall;
|
||||
int rpos;
|
||||
char *rbuf;
|
||||
int wpos;
|
||||
|
@ -101,11 +102,15 @@ struct v9fs_mux_rpc {
|
|||
wait_queue_head_t wqueue;
|
||||
};
|
||||
|
||||
extern int v9fs_errstr2errno(char *str, int len);
|
||||
|
||||
static int v9fs_poll_proc(void *);
|
||||
static void v9fs_read_work(void *);
|
||||
static void v9fs_write_work(void *);
|
||||
static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
|
||||
poll_table * p);
|
||||
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 struct workqueue_struct *v9fs_mux_wq;
|
||||
|
@ -166,8 +171,9 @@ static void v9fs_mux_poll_start(struct v9fs_mux_data *m)
|
|||
if (v9fs_mux_poll_tasks[i].task == NULL) {
|
||||
vpt = &v9fs_mux_poll_tasks[i];
|
||||
dprintk(DEBUG_MUX, "create proc %p\n", vpt);
|
||||
vpt->task = kthread_create(v9fs_poll_proc,
|
||||
vpt, "v9fs-poll");
|
||||
vpt->task =
|
||||
kthread_create(v9fs_poll_proc, vpt,
|
||||
"v9fs-poll");
|
||||
INIT_LIST_HEAD(&vpt->mux_list);
|
||||
vpt->muxnum = 0;
|
||||
v9fs_mux_poll_task_num++;
|
||||
|
@ -253,7 +259,7 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
|
|||
struct v9fs_mux_data *m, *mtmp;
|
||||
|
||||
dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize);
|
||||
m = kmalloc(sizeof(struct v9fs_mux_data) + 2 * msize, GFP_KERNEL);
|
||||
m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL);
|
||||
if (!m)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -268,10 +274,11 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
|
|||
init_waitqueue_head(&m->equeue);
|
||||
INIT_LIST_HEAD(&m->req_list);
|
||||
INIT_LIST_HEAD(&m->unsent_req_list);
|
||||
m->rcall = NULL;
|
||||
m->rpos = 0;
|
||||
m->rbuf = (char *)m + sizeof(struct v9fs_mux_data);
|
||||
m->rbuf = NULL;
|
||||
m->wpos = m->wsize = 0;
|
||||
m->wbuf = m->rbuf + msize;
|
||||
m->wbuf = NULL;
|
||||
INIT_WORK(&m->rq, v9fs_read_work, m);
|
||||
INIT_WORK(&m->wq, v9fs_write_work, m);
|
||||
m->wsched = 0;
|
||||
|
@ -427,29 +434,6 @@ static int v9fs_poll_proc(void *a)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int v9fs_write_req(struct v9fs_mux_data *m, struct v9fs_req *req)
|
||||
{
|
||||
int n;
|
||||
|
||||
list_move_tail(&req->req_list, &m->req_list);
|
||||
n = v9fs_serialize_fcall(req->tcall, m->wbuf, m->msize, *m->extended);
|
||||
if (n < 0) {
|
||||
req->err = n;
|
||||
list_del(&req->req_list);
|
||||
if (req->cb) {
|
||||
spin_unlock(&m->lock);
|
||||
(*req->cb) (req->cba, req->tcall, req->rcall, req->err);
|
||||
req->cb = NULL;
|
||||
spin_lock(&m->lock);
|
||||
} else
|
||||
kfree(req->rcall);
|
||||
|
||||
kfree(req);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_write_work - called when a transport can send some data
|
||||
*/
|
||||
|
@ -457,7 +441,7 @@ static void v9fs_write_work(void *a)
|
|||
{
|
||||
int n, err;
|
||||
struct v9fs_mux_data *m;
|
||||
struct v9fs_req *req, *rtmp;
|
||||
struct v9fs_req *req;
|
||||
|
||||
m = a;
|
||||
|
||||
|
@ -472,17 +456,15 @@ static void v9fs_write_work(void *a)
|
|||
return;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
spin_lock(&m->lock);
|
||||
list_for_each_entry_safe(req, rtmp, &m->unsent_req_list,
|
||||
req_list) {
|
||||
err = v9fs_write_req(m, req);
|
||||
if (err > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
m->wsize = err;
|
||||
req =
|
||||
list_entry(m->unsent_req_list.next, struct v9fs_req,
|
||||
req_list);
|
||||
list_move_tail(&req->req_list, &m->req_list);
|
||||
m->wbuf = req->tcall->sdata;
|
||||
m->wsize = req->tcall->size;
|
||||
m->wpos = 0;
|
||||
dump_data(m->wbuf, m->wsize);
|
||||
spin_unlock(&m->lock);
|
||||
}
|
||||
|
||||
|
@ -526,24 +508,23 @@ static void v9fs_write_work(void *a)
|
|||
static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
|
||||
{
|
||||
int ecode, tag;
|
||||
char *ename;
|
||||
struct v9fs_str *ename;
|
||||
|
||||
tag = req->tag;
|
||||
if (req->rcall->id == RERROR && !req->err) {
|
||||
ecode = req->rcall->params.rerror.errno;
|
||||
ename = req->rcall->params.rerror.error;
|
||||
ename = &req->rcall->params.rerror.error;
|
||||
|
||||
dprintk(DEBUG_MUX, "Rerror %s\n", ename);
|
||||
dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str);
|
||||
|
||||
if (*m->extended)
|
||||
req->err = -ecode;
|
||||
|
||||
if (!req->err) {
|
||||
req->err = v9fs_errstr2errno(ename);
|
||||
req->err = v9fs_errstr2errno(ename->str, ename->len);
|
||||
|
||||
if (!req->err) { /* string match failed */
|
||||
dprintk(DEBUG_ERROR, "unknown error: %s\n",
|
||||
ename);
|
||||
PRINT_FCALL_ERROR("unknown error", req->rcall);
|
||||
}
|
||||
|
||||
if (!req->err)
|
||||
|
@ -565,8 +546,7 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
|
|||
} else
|
||||
kfree(req->rcall);
|
||||
|
||||
if (tag != V9FS_NOTAG)
|
||||
v9fs_put_idpool(tag, &m->tidpool);
|
||||
v9fs_mux_put_tag(m, tag);
|
||||
|
||||
wake_up(&m->equeue);
|
||||
kfree(req);
|
||||
|
@ -577,10 +557,11 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
|
|||
*/
|
||||
static void v9fs_read_work(void *a)
|
||||
{
|
||||
int n, err, rcallen;
|
||||
int n, err;
|
||||
struct v9fs_mux_data *m;
|
||||
struct v9fs_req *req, *rptr, *rreq;
|
||||
struct v9fs_fcall *rcall;
|
||||
char *rbuf;
|
||||
|
||||
m = a;
|
||||
|
||||
|
@ -589,6 +570,19 @@ static void v9fs_read_work(void *a)
|
|||
|
||||
rcall = NULL;
|
||||
dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
|
||||
|
||||
if (!m->rcall) {
|
||||
m->rcall =
|
||||
kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL);
|
||||
if (!m->rcall) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
|
||||
m->rpos = 0;
|
||||
}
|
||||
|
||||
clear_bit(Rpending, &m->wsched);
|
||||
err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos);
|
||||
dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err);
|
||||
|
@ -613,19 +607,30 @@ static void v9fs_read_work(void *a)
|
|||
if (m->rpos < n)
|
||||
break;
|
||||
|
||||
rcallen = n + V9FS_FCALLHDRSZ;
|
||||
rcall = kmalloc(rcallen, GFP_KERNEL);
|
||||
if (!rcall) {
|
||||
err = -ENOMEM;
|
||||
dump_data(m->rbuf, n);
|
||||
err =
|
||||
v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended);
|
||||
if (err < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
dump_data(m->rbuf, n);
|
||||
err = v9fs_deserialize_fcall(m->rbuf, n, rcall, rcallen,
|
||||
*m->extended);
|
||||
if (err < 0) {
|
||||
kfree(rcall);
|
||||
goto error;
|
||||
rcall = m->rcall;
|
||||
rbuf = m->rbuf;
|
||||
if (m->rpos > n) {
|
||||
m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize,
|
||||
GFP_KERNEL);
|
||||
if (!m->rcall) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
|
||||
memmove(m->rbuf, rbuf + n, m->rpos - n);
|
||||
m->rpos -= n;
|
||||
} else {
|
||||
m->rcall = NULL;
|
||||
m->rbuf = NULL;
|
||||
m->rpos = 0;
|
||||
}
|
||||
|
||||
dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id,
|
||||
|
@ -642,6 +647,7 @@ static void v9fs_read_work(void *a)
|
|||
process_request(m, req);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!req) {
|
||||
|
@ -652,10 +658,6 @@ static void v9fs_read_work(void *a)
|
|||
m, rcall->id, rcall->tag);
|
||||
kfree(rcall);
|
||||
}
|
||||
|
||||
if (m->rpos > n)
|
||||
memmove(m->rbuf, m->rbuf + n, m->rpos - n);
|
||||
m->rpos -= n;
|
||||
}
|
||||
|
||||
if (!list_empty(&m->req_list)) {
|
||||
|
@ -710,12 +712,13 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
|
|||
if (tc->id == TVERSION)
|
||||
n = V9FS_NOTAG;
|
||||
else
|
||||
n = v9fs_get_idpool(&m->tidpool);
|
||||
n = v9fs_mux_get_tag(m);
|
||||
|
||||
if (n < 0)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
tc->tag = n;
|
||||
v9fs_set_tag(tc, n);
|
||||
|
||||
req->tag = n;
|
||||
req->tcall = tc;
|
||||
req->rcall = NULL;
|
||||
|
@ -773,9 +776,7 @@ v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc,
|
|||
if (!cb)
|
||||
spin_unlock(&m->lock);
|
||||
|
||||
if (v9fs_check_idpool(tag, &m->tidpool))
|
||||
v9fs_put_idpool(tag, &m->tidpool);
|
||||
|
||||
v9fs_mux_put_tag(m, tag);
|
||||
kfree(tc);
|
||||
kfree(rc);
|
||||
}
|
||||
|
@ -787,10 +788,7 @@ v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
|
|||
|
||||
dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
|
||||
|
||||
fc = kmalloc(sizeof(struct v9fs_fcall), GFP_KERNEL);
|
||||
fc->id = TFLUSH;
|
||||
fc->params.tflush.oldtag = req->tag;
|
||||
|
||||
fc = v9fs_create_tflush(req->tag);
|
||||
v9fs_send_request(m, fc, v9fs_mux_flush_cb, m);
|
||||
}
|
||||
|
||||
|
@ -939,3 +937,20 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
|
|||
|
||||
wake_up(&m->equeue);
|
||||
}
|
||||
|
||||
static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
|
||||
{
|
||||
int tag;
|
||||
|
||||
tag = v9fs_get_idpool(&m->tidpool);
|
||||
if (tag < 0)
|
||||
return V9FS_NOTAG;
|
||||
else
|
||||
return (u16) tag;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,6 @@ static int v9fs_sock_send(struct v9fs_transport *trans, void *v, int len)
|
|||
if (!(ts->filp->f_flags & O_NONBLOCK))
|
||||
dprintk(DEBUG_ERROR, "blocking write ...\n");
|
||||
|
||||
dump_data(v, len);
|
||||
oldfs = get_fs();
|
||||
set_fs(get_ds());
|
||||
ret = vfs_write(ts->filp, (void __user *)v, len, &ts->filp->f_pos);
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "v9fs_vfs.h"
|
||||
#include "transport.h"
|
||||
#include "mux.h"
|
||||
#include "conv.h"
|
||||
|
||||
/* TODO: sysfs or debugfs interface */
|
||||
int v9fs_debug_level = 0; /* feature-rific global debug level */
|
||||
|
@ -353,7 +352,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
|
|||
}
|
||||
|
||||
/* Really should check for 9P1 and report error */
|
||||
if (!strcmp(fcall->params.rversion.version, "9P2000.u")) {
|
||||
if (!v9fs_str_compare("9P2000.u", &fcall->params.rversion.version)) {
|
||||
dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
|
||||
v9ses->extended = 1;
|
||||
} else {
|
||||
|
|
|
@ -45,9 +45,8 @@ extern struct dentry_operations v9fs_dentry_operations;
|
|||
|
||||
struct inode *v9fs_get_inode(struct super_block *sb, int mode);
|
||||
ino_t v9fs_qid2ino(struct v9fs_qid *qid);
|
||||
void v9fs_mistat2inode(struct v9fs_stat *, struct inode *,
|
||||
struct super_block *);
|
||||
void v9fs_stat2inode(struct v9fs_stat *, struct inode *, struct super_block *);
|
||||
int v9fs_dir_release(struct inode *inode, struct file *filp);
|
||||
int v9fs_file_open(struct inode *inode, struct file *file);
|
||||
void v9fs_inode2mistat(struct inode *inode, struct v9fs_stat *mistat);
|
||||
void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat);
|
||||
void v9fs_dentry_release(struct dentry *);
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "v9fs.h"
|
||||
#include "9p.h"
|
||||
#include "v9fs_vfs.h"
|
||||
#include "conv.h"
|
||||
#include "fid.h"
|
||||
|
||||
/**
|
||||
|
@ -108,7 +107,8 @@ void v9fs_dentry_release(struct dentry *dentry)
|
|||
err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid);
|
||||
|
||||
if (err < 0)
|
||||
dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
|
||||
dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n",
|
||||
err, dentry->d_iname);
|
||||
|
||||
v9fs_fid_destroy(current_fid);
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
#include "debug.h"
|
||||
#include "v9fs.h"
|
||||
#include "9p.h"
|
||||
#include "v9fs_vfs.h"
|
||||
#include "conv.h"
|
||||
#include "v9fs_vfs.h"
|
||||
#include "fid.h"
|
||||
|
||||
/**
|
||||
|
@ -77,17 +77,13 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||
unsigned int i, n, s;
|
||||
int fid = -1;
|
||||
int ret = 0;
|
||||
struct v9fs_stat *mi = NULL;
|
||||
struct v9fs_stat stat;
|
||||
int over = 0;
|
||||
|
||||
dprintk(DEBUG_VFS, "name %s\n", filp->f_dentry->d_name.name);
|
||||
|
||||
fid = file->fid;
|
||||
|
||||
mi = kmalloc(v9ses->maxdata, GFP_KERNEL);
|
||||
if (!mi)
|
||||
return -ENOMEM;
|
||||
|
||||
if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) {
|
||||
kfree(file->rdir_fcall);
|
||||
file->rdir_fcall = NULL;
|
||||
|
@ -99,18 +95,18 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||
while (i < n) {
|
||||
s = v9fs_deserialize_stat(
|
||||
file->rdir_fcall->params.rread.data + i,
|
||||
n - i, mi, v9ses->maxdata, v9ses->extended);
|
||||
n - i, &stat, v9ses->extended);
|
||||
|
||||
if (s == 0) {
|
||||
dprintk(DEBUG_ERROR,
|
||||
"error while deserializing mistat\n");
|
||||
"error while deserializing stat\n");
|
||||
ret = -EIO;
|
||||
goto FreeStructs;
|
||||
}
|
||||
|
||||
over = filldir(dirent, mi->name, strlen(mi->name),
|
||||
filp->f_pos, v9fs_qid2ino(&mi->qid),
|
||||
dt_type(mi));
|
||||
over = filldir(dirent, stat.name.str, stat.name.len,
|
||||
filp->f_pos, v9fs_qid2ino(&stat.qid),
|
||||
dt_type(&stat));
|
||||
|
||||
if (over) {
|
||||
file->rdir_fpos = i;
|
||||
|
@ -130,7 +126,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||
|
||||
while (!over) {
|
||||
ret = v9fs_t_read(v9ses, fid, filp->f_pos,
|
||||
v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
|
||||
v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
|
||||
if (ret < 0) {
|
||||
dprintk(DEBUG_ERROR, "error while reading: %d: %p\n",
|
||||
ret, fcall);
|
||||
|
@ -142,17 +138,17 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||
i = 0;
|
||||
while (i < n) {
|
||||
s = v9fs_deserialize_stat(fcall->params.rread.data + i,
|
||||
n - i, mi, v9ses->maxdata, v9ses->extended);
|
||||
n - i, &stat, v9ses->extended);
|
||||
|
||||
if (s == 0) {
|
||||
dprintk(DEBUG_ERROR,
|
||||
"error while deserializing mistat\n");
|
||||
"error while deserializing stat\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
over = filldir(dirent, mi->name, strlen(mi->name),
|
||||
filp->f_pos, v9fs_qid2ino(&mi->qid),
|
||||
dt_type(mi));
|
||||
over = filldir(dirent, stat.name.str, stat.name.len,
|
||||
filp->f_pos, v9fs_qid2ino(&stat.qid),
|
||||
dt_type(&stat));
|
||||
|
||||
if (over) {
|
||||
file->rdir_fcall = fcall;
|
||||
|
@ -171,7 +167,6 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||
|
||||
FreeStructs:
|
||||
kfree(fcall);
|
||||
kfree(mi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/inet.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/list.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/idr.h>
|
||||
|
@ -117,9 +118,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
|
|||
|
||||
result = v9fs_t_open(v9ses, newfid, open_mode, &fcall);
|
||||
if (result < 0) {
|
||||
dprintk(DEBUG_ERROR,
|
||||
"open failed, open_mode 0x%x: %s\n", open_mode,
|
||||
FCALL_ERROR(fcall));
|
||||
PRINT_FCALL_ERROR("open failed", fcall);
|
||||
kfree(fcall);
|
||||
return result;
|
||||
}
|
||||
|
@ -256,7 +255,6 @@ v9fs_file_write(struct file *filp, const char __user * data,
|
|||
int result = -EIO;
|
||||
int rsize = 0;
|
||||
int total = 0;
|
||||
char *buf;
|
||||
|
||||
dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count,
|
||||
(int)*offset);
|
||||
|
@ -264,28 +262,14 @@ v9fs_file_write(struct file *filp, const char __user * data,
|
|||
if (v9fid->iounit != 0 && rsize > v9fid->iounit)
|
||||
rsize = v9fid->iounit;
|
||||
|
||||
buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
if (count < rsize)
|
||||
rsize = count;
|
||||
|
||||
result = copy_from_user(buf, data, rsize);
|
||||
if (result) {
|
||||
dprintk(DEBUG_ERROR, "Problem copying from user\n");
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
dump_data(buf, rsize);
|
||||
result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall);
|
||||
result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall);
|
||||
if (result < 0) {
|
||||
eprintk(KERN_ERR, "error while writing: %s(%d)\n",
|
||||
FCALL_ERROR(fcall), result);
|
||||
PRINT_FCALL_ERROR("error while writing", fcall);
|
||||
kfree(fcall);
|
||||
kfree(buf);
|
||||
return result;
|
||||
} else
|
||||
*offset += result;
|
||||
|
@ -305,7 +289,6 @@ v9fs_file_write(struct file *filp, const char __user * data,
|
|||
total += result;
|
||||
} while (count);
|
||||
|
||||
kfree(buf);
|
||||
return total;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "v9fs.h"
|
||||
#include "9p.h"
|
||||
#include "v9fs_vfs.h"
|
||||
#include "conv.h"
|
||||
#include "fid.h"
|
||||
|
||||
static struct inode_operations v9fs_dir_inode_operations;
|
||||
|
@ -127,100 +126,32 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
|
|||
}
|
||||
|
||||
/**
|
||||
* v9fs_blank_mistat - helper function to setup a 9P stat structure
|
||||
* v9fs_blank_wstat - helper function to setup a 9P stat structure
|
||||
* @v9ses: 9P session info (for determining extended mode)
|
||||
* @mistat: structure to initialize
|
||||
* @wstat: structure to initialize
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
v9fs_blank_mistat(struct v9fs_session_info *v9ses, struct v9fs_stat *mistat)
|
||||
v9fs_blank_wstat(struct v9fs_wstat *wstat)
|
||||
{
|
||||
mistat->type = ~0;
|
||||
mistat->dev = ~0;
|
||||
mistat->qid.type = ~0;
|
||||
mistat->qid.version = ~0;
|
||||
*((long long *)&mistat->qid.path) = ~0;
|
||||
mistat->mode = ~0;
|
||||
mistat->atime = ~0;
|
||||
mistat->mtime = ~0;
|
||||
mistat->length = ~0;
|
||||
mistat->name = mistat->data;
|
||||
mistat->uid = mistat->data;
|
||||
mistat->gid = mistat->data;
|
||||
mistat->muid = mistat->data;
|
||||
if (v9ses->extended) {
|
||||
mistat->n_uid = ~0;
|
||||
mistat->n_gid = ~0;
|
||||
mistat->n_muid = ~0;
|
||||
mistat->extension = mistat->data;
|
||||
}
|
||||
*mistat->data = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_mistat2unix - convert mistat to unix stat
|
||||
* @mistat: Plan 9 metadata (mistat) structure
|
||||
* @buf: unix metadata (stat) structure to populate
|
||||
* @sb: superblock
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
v9fs_mistat2unix(struct v9fs_stat *mistat, struct stat *buf,
|
||||
struct super_block *sb)
|
||||
{
|
||||
struct v9fs_session_info *v9ses = sb ? sb->s_fs_info : NULL;
|
||||
|
||||
buf->st_nlink = 1;
|
||||
|
||||
buf->st_atime = mistat->atime;
|
||||
buf->st_mtime = mistat->mtime;
|
||||
buf->st_ctime = mistat->mtime;
|
||||
|
||||
buf->st_uid = (unsigned short)-1;
|
||||
buf->st_gid = (unsigned short)-1;
|
||||
|
||||
if (v9ses && v9ses->extended) {
|
||||
/* TODO: string to uid mapping via user-space daemon */
|
||||
if (mistat->n_uid != -1)
|
||||
sscanf(mistat->uid, "%x", (unsigned int *)&buf->st_uid);
|
||||
|
||||
if (mistat->n_gid != -1)
|
||||
sscanf(mistat->gid, "%x", (unsigned int *)&buf->st_gid);
|
||||
}
|
||||
|
||||
if (buf->st_uid == (unsigned short)-1)
|
||||
buf->st_uid = v9ses->uid;
|
||||
if (buf->st_gid == (unsigned short)-1)
|
||||
buf->st_gid = v9ses->gid;
|
||||
|
||||
buf->st_mode = p9mode2unixmode(v9ses, mistat->mode);
|
||||
if ((S_ISBLK(buf->st_mode)) || (S_ISCHR(buf->st_mode))) {
|
||||
char type = 0;
|
||||
int major = -1;
|
||||
int minor = -1;
|
||||
sscanf(mistat->extension, "%c %u %u", &type, &major, &minor);
|
||||
switch (type) {
|
||||
case 'c':
|
||||
buf->st_mode &= ~S_IFBLK;
|
||||
buf->st_mode |= S_IFCHR;
|
||||
break;
|
||||
case 'b':
|
||||
break;
|
||||
default:
|
||||
dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
|
||||
type, mistat->extension);
|
||||
};
|
||||
buf->st_rdev = MKDEV(major, minor);
|
||||
} else
|
||||
buf->st_rdev = 0;
|
||||
|
||||
buf->st_size = mistat->length;
|
||||
|
||||
buf->st_blksize = sb->s_blocksize;
|
||||
buf->st_blocks =
|
||||
(buf->st_size + buf->st_blksize - 1) >> sb->s_blocksize_bits;
|
||||
wstat->type = ~0;
|
||||
wstat->dev = ~0;
|
||||
wstat->qid.type = ~0;
|
||||
wstat->qid.version = ~0;
|
||||
*((long long *)&wstat->qid.path) = ~0;
|
||||
wstat->mode = ~0;
|
||||
wstat->atime = ~0;
|
||||
wstat->mtime = ~0;
|
||||
wstat->length = ~0;
|
||||
wstat->name = NULL;
|
||||
wstat->uid = NULL;
|
||||
wstat->gid = NULL;
|
||||
wstat->muid = NULL;
|
||||
wstat->n_uid = ~0;
|
||||
wstat->n_gid = ~0;
|
||||
wstat->n_muid = ~0;
|
||||
wstat->extension = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,7 +243,6 @@ v9fs_create(struct inode *dir,
|
|||
struct inode *file_inode = NULL;
|
||||
struct v9fs_fcall *fcall = NULL;
|
||||
struct v9fs_qid qid;
|
||||
struct stat newstat;
|
||||
int dirfidnum = -1;
|
||||
long newfid = -1;
|
||||
int result = 0;
|
||||
|
@ -350,7 +280,7 @@ v9fs_create(struct inode *dir,
|
|||
|
||||
result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall);
|
||||
if (result < 0) {
|
||||
dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
|
||||
PRINT_FCALL_ERROR("clone error", fcall);
|
||||
v9fs_put_idpool(newfid, &v9ses->fidpool);
|
||||
newfid = -1;
|
||||
goto CleanUpFid;
|
||||
|
@ -362,9 +292,7 @@ v9fs_create(struct inode *dir,
|
|||
result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name,
|
||||
perm, open_mode, &fcall);
|
||||
if (result < 0) {
|
||||
dprintk(DEBUG_ERROR, "create fails: %s(%d)\n",
|
||||
FCALL_ERROR(fcall), result);
|
||||
|
||||
PRINT_FCALL_ERROR("create fails", fcall);
|
||||
goto CleanUpFid;
|
||||
}
|
||||
|
||||
|
@ -400,7 +328,7 @@ v9fs_create(struct inode *dir,
|
|||
result = v9fs_t_walk(v9ses, dirfidnum, wfidno,
|
||||
(char *) file_dentry->d_name.name, &fcall);
|
||||
if (result < 0) {
|
||||
dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
|
||||
PRINT_FCALL_ERROR("clone error", fcall);
|
||||
v9fs_put_idpool(wfidno, &v9ses->fidpool);
|
||||
wfidno = -1;
|
||||
goto CleanUpFid;
|
||||
|
@ -421,21 +349,21 @@ v9fs_create(struct inode *dir,
|
|||
|
||||
result = v9fs_t_stat(v9ses, wfidno, &fcall);
|
||||
if (result < 0) {
|
||||
dprintk(DEBUG_ERROR, "stat error: %s(%d)\n", FCALL_ERROR(fcall),
|
||||
result);
|
||||
PRINT_FCALL_ERROR("stat error", fcall);
|
||||
goto CleanUpFid;
|
||||
}
|
||||
|
||||
v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
|
||||
|
||||
file_inode = v9fs_get_inode(sb, newstat.st_mode);
|
||||
file_inode = v9fs_get_inode(sb,
|
||||
p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode));
|
||||
|
||||
if ((!file_inode) || IS_ERR(file_inode)) {
|
||||
dprintk(DEBUG_ERROR, "create inode failed\n");
|
||||
result = -EBADF;
|
||||
goto CleanUpFid;
|
||||
}
|
||||
|
||||
v9fs_mistat2inode(fcall->params.rstat.stat, file_inode, sb);
|
||||
v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb);
|
||||
kfree(fcall);
|
||||
fcall = NULL;
|
||||
file_dentry->d_op = &v9fs_dentry_operations;
|
||||
|
@ -500,10 +428,9 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
|
|||
}
|
||||
|
||||
result = v9fs_t_remove(v9ses, fid, &fcall);
|
||||
if (result < 0)
|
||||
dprintk(DEBUG_ERROR, "remove of file fails: %s(%d)\n",
|
||||
FCALL_ERROR(fcall), result);
|
||||
else {
|
||||
if (result < 0) {
|
||||
PRINT_FCALL_ERROR("remove fails", fcall);
|
||||
} else {
|
||||
v9fs_put_idpool(fid, &v9ses->fidpool);
|
||||
v9fs_fid_destroy(v9fid);
|
||||
}
|
||||
|
@ -558,7 +485,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
|||
struct v9fs_fid *fid;
|
||||
struct inode *inode;
|
||||
struct v9fs_fcall *fcall = NULL;
|
||||
struct stat newstat;
|
||||
int dirfidnum = -1;
|
||||
int newfid = -1;
|
||||
int result = 0;
|
||||
|
@ -611,8 +537,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
|||
goto FreeFcall;
|
||||
}
|
||||
|
||||
v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
|
||||
inode = v9fs_get_inode(sb, newstat.st_mode);
|
||||
inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses,
|
||||
fcall->params.rstat.stat.mode));
|
||||
|
||||
if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) {
|
||||
eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
|
||||
|
@ -622,7 +548,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
|||
goto FreeFcall;
|
||||
}
|
||||
|
||||
inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid);
|
||||
inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid);
|
||||
|
||||
fid = v9fs_fid_create(dentry, v9ses, newfid, 0);
|
||||
if (fid == NULL) {
|
||||
|
@ -631,10 +557,10 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
|||
goto FreeFcall;
|
||||
}
|
||||
|
||||
fid->qid = fcall->params.rstat.stat->qid;
|
||||
fid->qid = fcall->params.rstat.stat.qid;
|
||||
|
||||
dentry->d_op = &v9fs_dentry_operations;
|
||||
v9fs_mistat2inode(fcall->params.rstat.stat, inode, inode->i_sb);
|
||||
v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
|
||||
|
||||
d_add(dentry, inode);
|
||||
kfree(fcall);
|
||||
|
@ -690,7 +616,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
v9fs_fid_lookup(old_dentry->d_parent);
|
||||
struct v9fs_fid *newdirfid =
|
||||
v9fs_fid_lookup(new_dentry->d_parent);
|
||||
struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
|
||||
struct v9fs_wstat wstat;
|
||||
struct v9fs_fcall *fcall = NULL;
|
||||
int fid = -1;
|
||||
int olddirfidnum = -1;
|
||||
|
@ -699,9 +625,6 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
|
||||
dprintk(DEBUG_VFS, "\n");
|
||||
|
||||
if (!mistat)
|
||||
return -ENOMEM;
|
||||
|
||||
if ((!oldfid) || (!olddirfid) || (!newdirfid)) {
|
||||
dprintk(DEBUG_ERROR, "problem with arguments\n");
|
||||
return -EBADF;
|
||||
|
@ -725,26 +648,15 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
goto FreeFcallnBail;
|
||||
}
|
||||
|
||||
v9fs_blank_mistat(v9ses, mistat);
|
||||
v9fs_blank_wstat(&wstat);
|
||||
wstat.muid = v9ses->name;
|
||||
wstat.name = (char *) new_dentry->d_name.name;
|
||||
|
||||
strcpy(mistat->data + 1, v9ses->name);
|
||||
mistat->name = mistat->data + 1 + strlen(v9ses->name);
|
||||
|
||||
if (new_dentry->d_name.len >
|
||||
(v9ses->maxdata - strlen(v9ses->name) - sizeof(struct v9fs_stat))) {
|
||||
dprintk(DEBUG_ERROR, "new name too long\n");
|
||||
goto FreeFcallnBail;
|
||||
}
|
||||
|
||||
strcpy(mistat->name, new_dentry->d_name.name);
|
||||
retval = v9fs_t_wstat(v9ses, fid, mistat, &fcall);
|
||||
retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall);
|
||||
|
||||
FreeFcallnBail:
|
||||
kfree(mistat);
|
||||
|
||||
if (retval < 0)
|
||||
dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
|
||||
FCALL_ERROR(fcall));
|
||||
PRINT_FCALL_ERROR("wstat error", fcall);
|
||||
|
||||
kfree(fcall);
|
||||
return retval;
|
||||
|
@ -779,7 +691,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
|||
if (err < 0)
|
||||
dprintk(DEBUG_ERROR, "stat error\n");
|
||||
else {
|
||||
v9fs_mistat2inode(fcall->params.rstat.stat, dentry->d_inode,
|
||||
v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode,
|
||||
dentry->d_inode->i_sb);
|
||||
generic_fillattr(dentry->d_inode, stat);
|
||||
}
|
||||
|
@ -800,57 +712,44 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
|
|||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
|
||||
struct v9fs_fid *fid = v9fs_fid_lookup(dentry);
|
||||
struct v9fs_fcall *fcall = NULL;
|
||||
struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
|
||||
struct v9fs_wstat wstat;
|
||||
int res = -EPERM;
|
||||
|
||||
dprintk(DEBUG_VFS, "\n");
|
||||
|
||||
if (!mistat)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!fid) {
|
||||
dprintk(DEBUG_ERROR,
|
||||
"Couldn't find fid associated with dentry\n");
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
v9fs_blank_mistat(v9ses, mistat);
|
||||
v9fs_blank_wstat(&wstat);
|
||||
if (iattr->ia_valid & ATTR_MODE)
|
||||
mistat->mode = unixmode2p9mode(v9ses, iattr->ia_mode);
|
||||
wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
|
||||
|
||||
if (iattr->ia_valid & ATTR_MTIME)
|
||||
mistat->mtime = iattr->ia_mtime.tv_sec;
|
||||
wstat.mtime = iattr->ia_mtime.tv_sec;
|
||||
|
||||
if (iattr->ia_valid & ATTR_ATIME)
|
||||
mistat->atime = iattr->ia_atime.tv_sec;
|
||||
wstat.atime = iattr->ia_atime.tv_sec;
|
||||
|
||||
if (iattr->ia_valid & ATTR_SIZE)
|
||||
mistat->length = iattr->ia_size;
|
||||
wstat.length = iattr->ia_size;
|
||||
|
||||
if (v9ses->extended) {
|
||||
char *ptr = mistat->data+1;
|
||||
if (iattr->ia_valid & ATTR_UID)
|
||||
wstat.n_uid = iattr->ia_uid;
|
||||
|
||||
if (iattr->ia_valid & ATTR_UID) {
|
||||
mistat->uid = ptr;
|
||||
ptr += 1+sprintf(ptr, "%08x", iattr->ia_uid);
|
||||
mistat->n_uid = iattr->ia_uid;
|
||||
}
|
||||
|
||||
if (iattr->ia_valid & ATTR_GID) {
|
||||
mistat->gid = ptr;
|
||||
ptr += 1+sprintf(ptr, "%08x", iattr->ia_gid);
|
||||
mistat->n_gid = iattr->ia_gid;
|
||||
}
|
||||
if (iattr->ia_valid & ATTR_GID)
|
||||
wstat.n_gid = iattr->ia_gid;
|
||||
}
|
||||
|
||||
res = v9fs_t_wstat(v9ses, fid->fid, mistat, &fcall);
|
||||
res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
|
||||
|
||||
if (res < 0)
|
||||
dprintk(DEBUG_ERROR, "wstat error: %s\n", FCALL_ERROR(fcall));
|
||||
PRINT_FCALL_ERROR("wstat error", fcall);
|
||||
|
||||
kfree(mistat);
|
||||
kfree(fcall);
|
||||
|
||||
if (res >= 0)
|
||||
res = inode_setattr(dentry->d_inode, iattr);
|
||||
|
||||
|
@ -858,51 +757,42 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
|
|||
}
|
||||
|
||||
/**
|
||||
* v9fs_mistat2inode - populate an inode structure with mistat info
|
||||
* @mistat: Plan 9 metadata (mistat) structure
|
||||
* v9fs_stat2inode - populate an inode structure with mistat info
|
||||
* @stat: Plan 9 metadata (mistat) structure
|
||||
* @inode: inode to populate
|
||||
* @sb: superblock of filesystem
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode,
|
||||
struct super_block *sb)
|
||||
v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
|
||||
struct super_block *sb)
|
||||
{
|
||||
char ext[32];
|
||||
struct v9fs_session_info *v9ses = sb->s_fs_info;
|
||||
|
||||
inode->i_nlink = 1;
|
||||
|
||||
inode->i_atime.tv_sec = mistat->atime;
|
||||
inode->i_mtime.tv_sec = mistat->mtime;
|
||||
inode->i_ctime.tv_sec = mistat->mtime;
|
||||
inode->i_atime.tv_sec = stat->atime;
|
||||
inode->i_mtime.tv_sec = stat->mtime;
|
||||
inode->i_ctime.tv_sec = stat->mtime;
|
||||
|
||||
inode->i_uid = -1;
|
||||
inode->i_gid = -1;
|
||||
inode->i_uid = v9ses->uid;
|
||||
inode->i_gid = v9ses->gid;
|
||||
|
||||
if (v9ses->extended) {
|
||||
/* TODO: string to uid mapping via user-space daemon */
|
||||
inode->i_uid = mistat->n_uid;
|
||||
inode->i_gid = mistat->n_gid;
|
||||
|
||||
if (mistat->n_uid == -1)
|
||||
sscanf(mistat->uid, "%x", &inode->i_uid);
|
||||
|
||||
if (mistat->n_gid == -1)
|
||||
sscanf(mistat->gid, "%x", &inode->i_gid);
|
||||
inode->i_uid = stat->n_uid;
|
||||
inode->i_gid = stat->n_gid;
|
||||
}
|
||||
|
||||
if (inode->i_uid == -1)
|
||||
inode->i_uid = v9ses->uid;
|
||||
if (inode->i_gid == -1)
|
||||
inode->i_gid = v9ses->gid;
|
||||
|
||||
inode->i_mode = p9mode2unixmode(v9ses, mistat->mode);
|
||||
inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
|
||||
if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
|
||||
char type = 0;
|
||||
int major = -1;
|
||||
int minor = -1;
|
||||
sscanf(mistat->extension, "%c %u %u", &type, &major, &minor);
|
||||
|
||||
v9fs_str_copy(ext, sizeof(ext), &stat->extension);
|
||||
sscanf(ext, "%c %u %u", &type, &major, &minor);
|
||||
switch (type) {
|
||||
case 'c':
|
||||
inode->i_mode &= ~S_IFBLK;
|
||||
|
@ -911,14 +801,14 @@ v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode,
|
|||
case 'b':
|
||||
break;
|
||||
default:
|
||||
dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
|
||||
type, mistat->extension);
|
||||
dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n",
|
||||
type, stat->extension.len, stat->extension.str);
|
||||
};
|
||||
inode->i_rdev = MKDEV(major, minor);
|
||||
} else
|
||||
inode->i_rdev = 0;
|
||||
|
||||
inode->i_size = mistat->length;
|
||||
inode->i_size = stat->length;
|
||||
|
||||
inode->i_blksize = sb->s_blocksize;
|
||||
inode->i_blocks =
|
||||
|
@ -945,72 +835,6 @@ ino_t v9fs_qid2ino(struct v9fs_qid *qid)
|
|||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_vfs_symlink - helper function to create symlinks
|
||||
* @dir: directory inode containing symlink
|
||||
* @dentry: dentry for symlink
|
||||
* @symname: symlink data
|
||||
*
|
||||
* See 9P2000.u RFC for more information
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
|
||||
{
|
||||
int retval = -EPERM;
|
||||
struct v9fs_fid *newfid;
|
||||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
|
||||
struct v9fs_fcall *fcall = NULL;
|
||||
struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
|
||||
int err;
|
||||
|
||||
dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
|
||||
symname);
|
||||
|
||||
if (!mistat)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!v9ses->extended) {
|
||||
dprintk(DEBUG_ERROR, "not extended\n");
|
||||
goto FreeFcall;
|
||||
}
|
||||
|
||||
/* issue a create */
|
||||
retval = v9fs_create(dir, dentry, S_IFLNK, 0);
|
||||
if (retval != 0)
|
||||
goto FreeFcall;
|
||||
|
||||
newfid = v9fs_fid_lookup(dentry);
|
||||
|
||||
/* issue a twstat */
|
||||
v9fs_blank_mistat(v9ses, mistat);
|
||||
strcpy(mistat->data + 1, symname);
|
||||
mistat->extension = mistat->data + 1;
|
||||
retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
|
||||
if (retval < 0) {
|
||||
dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
|
||||
FCALL_ERROR(fcall));
|
||||
goto FreeFcall;
|
||||
}
|
||||
|
||||
kfree(fcall);
|
||||
|
||||
err = v9fs_t_clunk(v9ses, newfid->fid);
|
||||
if (err < 0) {
|
||||
dprintk(DEBUG_ERROR, "clunk for symlink failed: %d\n", err);
|
||||
goto FreeFcall;
|
||||
}
|
||||
|
||||
d_drop(dentry); /* FID - will this also clunk? */
|
||||
|
||||
FreeFcall:
|
||||
kfree(mistat);
|
||||
kfree(fcall);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_readlink - read a symlink's location (internal version)
|
||||
* @dentry: dentry for symlink
|
||||
|
@ -1050,16 +874,17 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
|
|||
if (!fcall)
|
||||
return -EIO;
|
||||
|
||||
if (!(fcall->params.rstat.stat->mode & V9FS_DMSYMLINK)) {
|
||||
if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) {
|
||||
retval = -EINVAL;
|
||||
goto FreeFcall;
|
||||
}
|
||||
|
||||
/* copy extension buffer into buffer */
|
||||
if (strlen(fcall->params.rstat.stat->extension) < buflen)
|
||||
buflen = strlen(fcall->params.rstat.stat->extension);
|
||||
if (fcall->params.rstat.stat.extension.len < buflen)
|
||||
buflen = fcall->params.rstat.stat.extension.len;
|
||||
|
||||
memcpy(buffer, fcall->params.rstat.stat->extension, buflen + 1);
|
||||
memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
|
||||
buffer[buflen-1] = 0;
|
||||
|
||||
retval = buflen;
|
||||
|
||||
|
@ -1149,6 +974,77 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
|
|||
__putname(s);
|
||||
}
|
||||
|
||||
static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
|
||||
int mode, const char *extension)
|
||||
{
|
||||
int err, retval;
|
||||
struct v9fs_session_info *v9ses;
|
||||
struct v9fs_fcall *fcall;
|
||||
struct v9fs_fid *fid;
|
||||
struct v9fs_wstat wstat;
|
||||
|
||||
v9ses = v9fs_inode2v9ses(dir);
|
||||
retval = -EPERM;
|
||||
fcall = NULL;
|
||||
|
||||
if (!v9ses->extended) {
|
||||
dprintk(DEBUG_ERROR, "not extended\n");
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
/* issue a create */
|
||||
retval = v9fs_create(dir, dentry, mode, 0);
|
||||
if (retval != 0)
|
||||
goto free_mem;
|
||||
|
||||
fid = v9fs_fid_get_created(dentry);
|
||||
if (!fid) {
|
||||
dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
/* issue a Twstat */
|
||||
v9fs_blank_wstat(&wstat);
|
||||
wstat.muid = v9ses->name;
|
||||
wstat.extension = (char *) extension;
|
||||
retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
|
||||
if (retval < 0) {
|
||||
PRINT_FCALL_ERROR("wstat error", fcall);
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
err = v9fs_t_clunk(v9ses, fid->fid);
|
||||
if (err < 0) {
|
||||
dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
|
||||
goto free_mem;
|
||||
}
|
||||
|
||||
d_drop(dentry); /* FID - will this also clunk? */
|
||||
|
||||
free_mem:
|
||||
kfree(fcall);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_vfs_symlink - helper function to create symlinks
|
||||
* @dir: directory inode containing symlink
|
||||
* @dentry: dentry for symlink
|
||||
* @symname: symlink data
|
||||
*
|
||||
* See 9P2000.u RFC for more information
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
|
||||
{
|
||||
dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
|
||||
symname);
|
||||
|
||||
return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_vfs_link - create a hardlink
|
||||
* @old_dentry: dentry for file to link to
|
||||
|
@ -1165,66 +1061,24 @@ static int
|
|||
v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
int retval = -EPERM;
|
||||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
|
||||
struct v9fs_fcall *fcall = NULL;
|
||||
struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
|
||||
struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
|
||||
struct v9fs_fid *newfid = NULL;
|
||||
char *symname = __getname();
|
||||
int err;
|
||||
int retval;
|
||||
struct v9fs_fid *oldfid;
|
||||
char *name;
|
||||
|
||||
dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
|
||||
old_dentry->d_name.name);
|
||||
|
||||
if (!v9ses->extended) {
|
||||
dprintk(DEBUG_ERROR, "not extended\n");
|
||||
goto FreeMem;
|
||||
oldfid = v9fs_fid_lookup(old_dentry);
|
||||
if (!oldfid) {
|
||||
dprintk(DEBUG_ERROR, "can't find oldfid\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* get fid of old_dentry */
|
||||
sprintf(symname, "hardlink(%d)\n", oldfid->fid);
|
||||
name = __getname();
|
||||
sprintf(name, "hardlink(%d)\n", oldfid->fid);
|
||||
retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
|
||||
__putname(name);
|
||||
|
||||
/* issue a create */
|
||||
retval = v9fs_create(dir, dentry, V9FS_DMLINK, 0);
|
||||
if (retval != 0)
|
||||
goto FreeMem;
|
||||
|
||||
newfid = v9fs_fid_lookup(dentry);
|
||||
if (!newfid) {
|
||||
dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
|
||||
goto FreeMem;
|
||||
}
|
||||
|
||||
/* issue a twstat */
|
||||
v9fs_blank_mistat(v9ses, mistat);
|
||||
strcpy(mistat->data + 1, symname);
|
||||
mistat->extension = mistat->data + 1;
|
||||
retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
|
||||
if (retval < 0) {
|
||||
dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
|
||||
FCALL_ERROR(fcall));
|
||||
goto FreeMem;
|
||||
}
|
||||
|
||||
kfree(fcall);
|
||||
|
||||
err = v9fs_t_clunk(v9ses, newfid->fid);
|
||||
|
||||
if (err < 0) {
|
||||
dprintk(DEBUG_ERROR, "clunk for symlink failed: %d\n", err);
|
||||
goto FreeMem;
|
||||
}
|
||||
|
||||
d_drop(dentry); /* FID - will this also clunk? */
|
||||
|
||||
kfree(fcall);
|
||||
fcall = NULL;
|
||||
|
||||
FreeMem:
|
||||
kfree(mistat);
|
||||
kfree(fcall);
|
||||
__putname(symname);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -1240,83 +1094,30 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
|
|||
static int
|
||||
v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
|
||||
{
|
||||
int retval = -EPERM;
|
||||
struct v9fs_fid *newfid;
|
||||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
|
||||
struct v9fs_fcall *fcall = NULL;
|
||||
struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
|
||||
char *symname = __getname();
|
||||
int err;
|
||||
int retval;
|
||||
char *name;
|
||||
|
||||
dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
|
||||
dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
|
||||
|
||||
if (!mistat)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!new_valid_dev(rdev)) {
|
||||
retval = -EINVAL;
|
||||
goto FreeMem;
|
||||
}
|
||||
|
||||
if (!v9ses->extended) {
|
||||
dprintk(DEBUG_ERROR, "not extended\n");
|
||||
goto FreeMem;
|
||||
}
|
||||
|
||||
/* issue a create */
|
||||
retval = v9fs_create(dir, dentry, mode, 0);
|
||||
|
||||
if (retval != 0)
|
||||
goto FreeMem;
|
||||
|
||||
newfid = v9fs_fid_lookup(dentry);
|
||||
if (!newfid) {
|
||||
dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n");
|
||||
retval = -EINVAL;
|
||||
goto FreeMem;
|
||||
}
|
||||
if (!new_valid_dev(rdev))
|
||||
return -EINVAL;
|
||||
|
||||
name = __getname();
|
||||
/* build extension */
|
||||
if (S_ISBLK(mode))
|
||||
sprintf(symname, "b %u %u", MAJOR(rdev), MINOR(rdev));
|
||||
sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
|
||||
else if (S_ISCHR(mode))
|
||||
sprintf(symname, "c %u %u", MAJOR(rdev), MINOR(rdev));
|
||||
sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
|
||||
else if (S_ISFIFO(mode))
|
||||
; /* DO NOTHING */
|
||||
*name = 0;
|
||||
else {
|
||||
retval = -EINVAL;
|
||||
goto FreeMem;
|
||||
__putname(name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!S_ISFIFO(mode)) {
|
||||
/* issue a twstat */
|
||||
v9fs_blank_mistat(v9ses, mistat);
|
||||
strcpy(mistat->data + 1, symname);
|
||||
mistat->extension = mistat->data + 1;
|
||||
retval = v9fs_t_wstat(v9ses, newfid->fid, mistat, &fcall);
|
||||
if (retval < 0) {
|
||||
dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
|
||||
FCALL_ERROR(fcall));
|
||||
goto FreeMem;
|
||||
}
|
||||
}
|
||||
|
||||
/* need to update dcache so we show up */
|
||||
kfree(fcall);
|
||||
|
||||
err = v9fs_t_clunk(v9ses, newfid->fid);
|
||||
if (err < 0) {
|
||||
dprintk(DEBUG_ERROR, "clunk for symlink failed: %d\n", err);
|
||||
goto FreeMem;
|
||||
}
|
||||
|
||||
d_drop(dentry); /* FID - will this also clunk? */
|
||||
|
||||
FreeMem:
|
||||
kfree(mistat);
|
||||
kfree(fcall);
|
||||
__putname(symname);
|
||||
retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
|
||||
__putname(name);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "v9fs.h"
|
||||
#include "9p.h"
|
||||
#include "v9fs_vfs.h"
|
||||
#include "conv.h"
|
||||
#include "fid.h"
|
||||
|
||||
static void v9fs_clear_inode(struct inode *);
|
||||
|
@ -123,10 +122,11 @@ static struct super_block *v9fs_get_sb(struct file_system_type
|
|||
|
||||
dprintk(DEBUG_VFS, " \n");
|
||||
|
||||
v9ses = kcalloc(1, sizeof(struct v9fs_session_info), GFP_KERNEL);
|
||||
v9ses = kmalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
|
||||
if (!v9ses)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memset(v9ses, 0, sizeof(struct v9fs_session_info));
|
||||
if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
|
||||
dprintk(DEBUG_ERROR, "problem initiating session\n");
|
||||
kfree(v9ses);
|
||||
|
@ -168,10 +168,10 @@ static struct super_block *v9fs_get_sb(struct file_system_type
|
|||
goto put_back_sb;
|
||||
}
|
||||
|
||||
root_fid->qid = fcall->params.rstat.stat->qid;
|
||||
root_fid->qid = fcall->params.rstat.stat.qid;
|
||||
root->d_inode->i_ino =
|
||||
v9fs_qid2ino(&fcall->params.rstat.stat->qid);
|
||||
v9fs_mistat2inode(fcall->params.rstat.stat, root->d_inode, sb);
|
||||
v9fs_qid2ino(&fcall->params.rstat.stat.qid);
|
||||
v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb);
|
||||
}
|
||||
|
||||
kfree(fcall);
|
||||
|
|
Loading…
Reference in New Issue