提交 1dac06b2 编写于 作者: L Latchesar Ionkov 提交者: Linus Torvalds

[PATCH] v9fs: handle kthread_create failure, minor bugfixes

- remove unnecessary -ENOMEM assignments
- return correct value when buf_check_size for second time in a buffer
- handle failures when create_workqueue and kthread_create are called
- use kzalloc instead of kmalloc/memset 0
- v9fs_str_copy and v9fs_str_compare were buggy, were used only in one
  place, correct the logic and move it to the place it is used.
Signed-off-by: NLatchesar Ionkov <lucho@ionkov.net>
Cc: Eric Van Hensbergen <ericvh@ericvh.myip.org>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 531b1094
...@@ -86,7 +86,6 @@ v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname, ...@@ -86,7 +86,6 @@ v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname, dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
aname, fid, afid); aname, fid, afid);
ret = -ENOMEM;
tc = v9fs_create_tattach(fid, afid, uname, aname); tc = v9fs_create_tattach(fid, afid, uname, aname);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
...@@ -136,7 +135,6 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) ...@@ -136,7 +135,6 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
dprintk(DEBUG_9P, "fid %d\n", fid); dprintk(DEBUG_9P, "fid %d\n", fid);
ret = -ENOMEM;
rc = NULL; rc = NULL;
tc = v9fs_create_tclunk(fid); tc = v9fs_create_tclunk(fid);
if (!IS_ERR(tc)) if (!IS_ERR(tc))
...@@ -165,7 +163,6 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag) ...@@ -165,7 +163,6 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
dprintk(DEBUG_9P, "oldtag %d\n", oldtag); dprintk(DEBUG_9P, "oldtag %d\n", oldtag);
ret = -ENOMEM;
tc = v9fs_create_tflush(oldtag); tc = v9fs_create_tflush(oldtag);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, NULL); ret = v9fs_mux_rpc(v9ses->mux, tc, NULL);
...@@ -221,7 +218,6 @@ v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, ...@@ -221,7 +218,6 @@ v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
dprintk(DEBUG_9P, "fid %d\n", fid); dprintk(DEBUG_9P, "fid %d\n", fid);
ret = -ENOMEM;
tc = v9fs_create_twstat(fid, wstat, v9ses->extended); tc = v9fs_create_twstat(fid, wstat, v9ses->extended);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
...@@ -259,7 +255,6 @@ v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, ...@@ -259,7 +255,6 @@ v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
else else
nwname = 0; nwname = 0;
ret = -ENOMEM;
tc = v9fs_create_twalk(fid, newfid, nwname, &name); tc = v9fs_create_twalk(fid, newfid, nwname, &name);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
...@@ -289,7 +284,6 @@ v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode, ...@@ -289,7 +284,6 @@ v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode); dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
ret = -ENOMEM;
tc = v9fs_create_topen(fid, mode); tc = v9fs_create_topen(fid, mode);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
...@@ -317,7 +311,6 @@ v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, ...@@ -317,7 +311,6 @@ v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
dprintk(DEBUG_9P, "fid %d\n", fid); dprintk(DEBUG_9P, "fid %d\n", fid);
ret = -ENOMEM;
tc = v9fs_create_tremove(fid); tc = v9fs_create_tremove(fid);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
...@@ -349,7 +342,6 @@ v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, ...@@ -349,7 +342,6 @@ v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n", dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
fid, name, perm, mode); fid, name, perm, mode);
ret = -ENOMEM;
tc = v9fs_create_tcreate(fid, name, perm, mode); tc = v9fs_create_tcreate(fid, name, perm, mode);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
...@@ -380,7 +372,6 @@ v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset, ...@@ -380,7 +372,6 @@ v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
(long long unsigned) offset, count); (long long unsigned) offset, count);
ret = -ENOMEM;
tc = v9fs_create_tread(fid, offset, count); tc = v9fs_create_tread(fid, offset, count);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
...@@ -418,7 +409,6 @@ v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count, ...@@ -418,7 +409,6 @@ v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count,
dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
(long long unsigned) offset, count); (long long unsigned) offset, count);
ret = -ENOMEM;
tc = v9fs_create_twrite(fid, offset, count, data); tc = v9fs_create_twrite(fid, offset, count, data);
if (!IS_ERR(tc)) { if (!IS_ERR(tc)) {
ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
......
...@@ -340,9 +340,6 @@ struct v9fs_fcall { ...@@ -340,9 +340,6 @@ struct v9fs_fcall {
fcall?fcall->params.rerror.error.len:0, \ fcall?fcall->params.rerror.error.len:0, \
fcall?fcall->params.rerror.error.str:""); fcall?fcall->params.rerror.error.str:"");
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, int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
char *version, struct v9fs_fcall **rcall); char *version, struct v9fs_fcall **rcall);
......
...@@ -45,37 +45,6 @@ struct cbuf { ...@@ -45,37 +45,6 @@ struct cbuf {
unsigned char *ep; unsigned char *ep;
}; };
char *v9fs_str_copy(char *buf, int buflen, struct v9fs_str *str)
{
int n;
if (buflen < str->len)
n = buflen;
else
n = str->len;
memmove(buf, str->str, n - 1);
return buf;
}
int v9fs_str_compare(char *buf, struct v9fs_str *str)
{
int n, ret;
ret = strncmp(buf, str->str, str->len);
if (!ret) {
n = strlen(buf);
if (n < str->len)
ret = -1;
else if (n > str->len)
ret = 1;
}
return ret;
}
static inline void buf_init(struct cbuf *buf, void *data, int datalen) static inline void buf_init(struct cbuf *buf, void *data, int datalen)
{ {
buf->sp = buf->p = data; buf->sp = buf->p = data;
...@@ -89,11 +58,14 @@ static inline int buf_check_overflow(struct cbuf *buf) ...@@ -89,11 +58,14 @@ static inline int buf_check_overflow(struct cbuf *buf)
static inline int buf_check_size(struct cbuf *buf, int len) static inline int buf_check_size(struct cbuf *buf, int len)
{ {
if (buf->p + len > buf->ep && buf->p < buf->ep) { if (buf->p + len > buf->ep) {
eprintk(KERN_ERR, "buffer overflow: want %d has %d\n", if (buf->p < buf->ep) {
len, (int)(buf->ep - buf->p)); eprintk(KERN_ERR, "buffer overflow: want %d has %d\n",
dump_stack(); len, (int)(buf->ep - buf->p));
buf->p = buf->ep + 1; dump_stack();
buf->p = buf->ep + 1;
}
return 0; return 0;
} }
...@@ -527,6 +499,7 @@ v9fs_create_common(struct cbuf *bufp, u32 size, u8 id) ...@@ -527,6 +499,7 @@ v9fs_create_common(struct cbuf *bufp, u32 size, u8 id)
void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag) void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag)
{ {
fc->tag = tag;
*(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
} }
......
...@@ -176,4 +176,3 @@ static struct errormap errmap[] = { ...@@ -176,4 +176,3 @@ static struct errormap errmap[] = {
}; };
extern int v9fs_error_init(void); extern int v9fs_error_init(void);
extern int v9fs_errstr2errno(char *errstr, int len);
...@@ -102,8 +102,6 @@ struct v9fs_mux_rpc { ...@@ -102,8 +102,6 @@ struct v9fs_mux_rpc {
wait_queue_head_t wqueue; wait_queue_head_t wqueue;
}; };
extern int v9fs_errstr2errno(char *str, int len);
static int v9fs_poll_proc(void *); static int v9fs_poll_proc(void *);
static void v9fs_read_work(void *); static void v9fs_read_work(void *);
static void v9fs_write_work(void *); static void v9fs_write_work(void *);
...@@ -119,7 +117,7 @@ static int v9fs_mux_num; ...@@ -119,7 +117,7 @@ static int v9fs_mux_num;
static int v9fs_mux_poll_task_num; static int v9fs_mux_poll_task_num;
static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100]; static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100];
void v9fs_mux_global_init(void) int v9fs_mux_global_init(void)
{ {
int i; int i;
...@@ -127,6 +125,10 @@ void v9fs_mux_global_init(void) ...@@ -127,6 +125,10 @@ void v9fs_mux_global_init(void)
v9fs_mux_poll_tasks[i].task = NULL; v9fs_mux_poll_tasks[i].task = NULL;
v9fs_mux_wq = create_workqueue("v9fs"); v9fs_mux_wq = create_workqueue("v9fs");
if (!v9fs_mux_wq)
return -ENOMEM;
return 0;
} }
void v9fs_mux_global_exit(void) void v9fs_mux_global_exit(void)
...@@ -156,10 +158,11 @@ inline int v9fs_mux_calc_poll_procs(int muxnum) ...@@ -156,10 +158,11 @@ inline int v9fs_mux_calc_poll_procs(int muxnum)
return n; return n;
} }
static void v9fs_mux_poll_start(struct v9fs_mux_data *m) static int v9fs_mux_poll_start(struct v9fs_mux_data *m)
{ {
int i, n; int i, n;
struct v9fs_mux_poll_task *vpt, *vptlast; struct v9fs_mux_poll_task *vpt, *vptlast;
struct task_struct *pproc;
dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num, dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num,
v9fs_mux_poll_task_num); v9fs_mux_poll_task_num);
...@@ -171,13 +174,16 @@ static void v9fs_mux_poll_start(struct v9fs_mux_data *m) ...@@ -171,13 +174,16 @@ static void v9fs_mux_poll_start(struct v9fs_mux_data *m)
if (v9fs_mux_poll_tasks[i].task == NULL) { if (v9fs_mux_poll_tasks[i].task == NULL) {
vpt = &v9fs_mux_poll_tasks[i]; vpt = &v9fs_mux_poll_tasks[i];
dprintk(DEBUG_MUX, "create proc %p\n", vpt); dprintk(DEBUG_MUX, "create proc %p\n", vpt);
vpt->task = pproc = kthread_create(v9fs_poll_proc, vpt,
kthread_create(v9fs_poll_proc, vpt,
"v9fs-poll"); "v9fs-poll");
INIT_LIST_HEAD(&vpt->mux_list);
vpt->muxnum = 0; if (!IS_ERR(pproc)) {
v9fs_mux_poll_task_num++; vpt->task = pproc;
wake_up_process(vpt->task); INIT_LIST_HEAD(&vpt->mux_list);
vpt->muxnum = 0;
v9fs_mux_poll_task_num++;
wake_up_process(vpt->task);
}
break; break;
} }
} }
...@@ -207,16 +213,21 @@ static void v9fs_mux_poll_start(struct v9fs_mux_data *m) ...@@ -207,16 +213,21 @@ static void v9fs_mux_poll_start(struct v9fs_mux_data *m)
} }
if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) { if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) {
if (vptlast == NULL)
return -ENOMEM;
dprintk(DEBUG_MUX, "put in proc %d\n", i); dprintk(DEBUG_MUX, "put in proc %d\n", i);
list_add(&m->mux_list, &vptlast->mux_list); list_add(&m->mux_list, &vptlast->mux_list);
vptlast->muxnum++; vptlast->muxnum++;
m->poll_task = vpt; m->poll_task = vptlast;
memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
init_poll_funcptr(&m->pt, v9fs_pollwait); init_poll_funcptr(&m->pt, v9fs_pollwait);
} }
v9fs_mux_num++; v9fs_mux_num++;
down(&v9fs_mux_task_lock); down(&v9fs_mux_task_lock);
return 0;
} }
static void v9fs_mux_poll_stop(struct v9fs_mux_data *m) static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
...@@ -283,7 +294,10 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, ...@@ -283,7 +294,10 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
INIT_WORK(&m->wq, v9fs_write_work, m); INIT_WORK(&m->wq, v9fs_write_work, m);
m->wsched = 0; m->wsched = 0;
memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
v9fs_mux_poll_start(m); m->poll_task = NULL;
n = v9fs_mux_poll_start(m);
if (n)
return ERR_PTR(n);
n = trans->poll(trans, &m->pt); n = trans->poll(trans, &m->pt);
if (n & POLLIN) { if (n & POLLIN) {
......
...@@ -40,7 +40,7 @@ struct v9fs_mux_data; ...@@ -40,7 +40,7 @@ struct v9fs_mux_data;
typedef void (*v9fs_mux_req_callback)(void *a, struct v9fs_fcall *tc, typedef void (*v9fs_mux_req_callback)(void *a, struct v9fs_fcall *tc,
struct v9fs_fcall *rc, int err); struct v9fs_fcall *rc, int err);
void v9fs_mux_global_init(void); int v9fs_mux_global_init(void);
void v9fs_mux_global_exit(void); void v9fs_mux_global_exit(void);
struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize, struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
...@@ -55,3 +55,4 @@ int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc, ...@@ -55,3 +55,4 @@ int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush); void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush);
void v9fs_mux_cancel(struct v9fs_mux_data *m, int err); void v9fs_mux_cancel(struct v9fs_mux_data *m, int err);
int v9fs_errstr2errno(char *errstr, int len);
...@@ -269,6 +269,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses, ...@@ -269,6 +269,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
int n = 0; int n = 0;
int newfid = -1; int newfid = -1;
int retval = -EINVAL; int retval = -EINVAL;
struct v9fs_str *version;
v9ses->name = __getname(); v9ses->name = __getname();
if (!v9ses->name) if (!v9ses->name)
...@@ -351,13 +352,16 @@ v9fs_session_init(struct v9fs_session_info *v9ses, ...@@ -351,13 +352,16 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
goto FreeFcall; goto FreeFcall;
} }
/* Really should check for 9P1 and report error */ version = &fcall->params.rversion.version;
if (!v9fs_str_compare("9P2000.u", &fcall->params.rversion.version)) { if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) {
dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
v9ses->extended = 1; v9ses->extended = 1;
} else { } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) {
dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n"); dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
v9ses->extended = 0; v9ses->extended = 0;
} else {
retval = -EREMOTEIO;
goto FreeFcall;
} }
n = fcall->params.rversion.msize; n = fcall->params.rversion.msize;
...@@ -449,12 +453,17 @@ extern int v9fs_error_init(void); ...@@ -449,12 +453,17 @@ extern int v9fs_error_init(void);
static int __init init_v9fs(void) static int __init init_v9fs(void)
{ {
int ret;
v9fs_error_init(); v9fs_error_init();
printk(KERN_INFO "Installing v9fs 9P2000 file system support\n"); printk(KERN_INFO "Installing v9fs 9P2000 file system support\n");
v9fs_mux_global_init(); ret = v9fs_mux_global_init();
return register_filesystem(&v9fs_fs_type); if (!ret)
ret = register_filesystem(&v9fs_fs_type);
return ret;
} }
/** /**
......
...@@ -768,6 +768,7 @@ void ...@@ -768,6 +768,7 @@ void
v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
struct super_block *sb) struct super_block *sb)
{ {
int n;
char ext[32]; char ext[32];
struct v9fs_session_info *v9ses = sb->s_fs_info; struct v9fs_session_info *v9ses = sb->s_fs_info;
...@@ -791,7 +792,11 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, ...@@ -791,7 +792,11 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
int major = -1; int major = -1;
int minor = -1; int minor = -1;
v9fs_str_copy(ext, sizeof(ext), &stat->extension); n = stat->extension.len;
if (n > sizeof(ext)-1)
n = sizeof(ext)-1;
memmove(ext, stat->extension.str, n);
ext[n] = 0;
sscanf(ext, "%c %u %u", &type, &major, &minor); sscanf(ext, "%c %u %u", &type, &major, &minor);
switch (type) { switch (type) {
case 'c': case 'c':
......
...@@ -122,11 +122,10 @@ static struct super_block *v9fs_get_sb(struct file_system_type ...@@ -122,11 +122,10 @@ static struct super_block *v9fs_get_sb(struct file_system_type
dprintk(DEBUG_VFS, " \n"); dprintk(DEBUG_VFS, " \n");
v9ses = kmalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
if (!v9ses) if (!v9ses)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
memset(v9ses, 0, sizeof(struct v9fs_session_info));
if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
dprintk(DEBUG_ERROR, "problem initiating session\n"); dprintk(DEBUG_ERROR, "problem initiating session\n");
kfree(v9ses); kfree(v9ses);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册