From 1dac06b20dcc8078dab037bd70652c69c67ba672 Mon Sep 17 00:00:00 2001 From: Latchesar Ionkov Date: Sun, 8 Jan 2006 01:05:02 -0800 Subject: [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: Latchesar Ionkov Cc: Eric Van Hensbergen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/9p/9p.c | 10 ---------- fs/9p/9p.h | 3 --- fs/9p/conv.c | 45 +++++++++------------------------------------ fs/9p/error.h | 1 - fs/9p/mux.c | 38 ++++++++++++++++++++++++++------------ fs/9p/mux.h | 3 ++- fs/9p/v9fs.c | 19 ++++++++++++++----- fs/9p/vfs_inode.c | 7 ++++++- fs/9p/vfs_super.c | 3 +-- 9 files changed, 58 insertions(+), 71 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/9p.c b/fs/9p/9p.c index dc3ce44ec83..1a6d08761f3 100644 --- a/fs/9p/9p.c +++ b/fs/9p/9p.c @@ -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, aname, fid, afid); - ret = -ENOMEM; tc = v9fs_create_tattach(fid, afid, uname, aname); if (!IS_ERR(tc)) { ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); @@ -136,7 +135,6 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid) dprintk(DEBUG_9P, "fid %d\n", fid); - ret = -ENOMEM; rc = NULL; tc = v9fs_create_tclunk(fid); if (!IS_ERR(tc)) @@ -165,7 +163,6 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag) 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); @@ -221,7 +218,6 @@ v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid, dprintk(DEBUG_9P, "fid %d\n", fid); - ret = -ENOMEM; tc = v9fs_create_twstat(fid, wstat, v9ses->extended); if (!IS_ERR(tc)) { ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); @@ -259,7 +255,6 @@ v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid, else nwname = 0; - ret = -ENOMEM; tc = v9fs_create_twalk(fid, newfid, nwname, &name); if (!IS_ERR(tc)) { ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); @@ -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); - ret = -ENOMEM; tc = v9fs_create_topen(fid, mode); if (!IS_ERR(tc)) { ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); @@ -317,7 +311,6 @@ v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid, dprintk(DEBUG_9P, "fid %d\n", fid); - ret = -ENOMEM; tc = v9fs_create_tremove(fid); if (!IS_ERR(tc)) { ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); @@ -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", fid, name, perm, mode); - ret = -ENOMEM; tc = v9fs_create_tcreate(fid, name, perm, mode); if (!IS_ERR(tc)) { ret = v9fs_mux_rpc(v9ses->mux, tc, rcp); @@ -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, (long long unsigned) offset, count); - ret = -ENOMEM; tc = v9fs_create_tread(fid, offset, count); if (!IS_ERR(tc)) { 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, dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid, (long long unsigned) offset, count); - ret = -ENOMEM; tc = v9fs_create_twrite(fid, offset, count, data); if (!IS_ERR(tc)) { ret = v9fs_mux_rpc(v9ses->mux, tc, &rc); diff --git a/fs/9p/9p.h b/fs/9p/9p.h index 007ff639777..0cd374d9471 100644 --- a/fs/9p/9p.h +++ b/fs/9p/9p.h @@ -340,9 +340,6 @@ struct v9fs_fcall { fcall?fcall->params.rerror.error.len:0, \ 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, char *version, struct v9fs_fcall **rcall); diff --git a/fs/9p/conv.c b/fs/9p/conv.c index f62434d435b..55ccfa10ee9 100644 --- a/fs/9p/conv.c +++ b/fs/9p/conv.c @@ -45,37 +45,6 @@ struct cbuf { 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) { buf->sp = buf->p = data; @@ -89,11 +58,14 @@ static inline int buf_check_overflow(struct cbuf *buf) static inline int buf_check_size(struct cbuf *buf, int len) { - if (buf->p + len > buf->ep && buf->p < buf->ep) { - eprintk(KERN_ERR, "buffer overflow: want %d has %d\n", - len, (int)(buf->ep - buf->p)); - dump_stack(); - buf->p = buf->ep + 1; + if (buf->p + len > buf->ep) { + if (buf->p < buf->ep) { + eprintk(KERN_ERR, "buffer overflow: want %d has %d\n", + len, (int)(buf->ep - buf->p)); + dump_stack(); + buf->p = buf->ep + 1; + } + return 0; } @@ -527,6 +499,7 @@ v9fs_create_common(struct cbuf *bufp, u32 size, u8 id) void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag) { + fc->tag = tag; *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag); } diff --git a/fs/9p/error.h b/fs/9p/error.h index 8b3176b3f65..a9794e85fe5 100644 --- a/fs/9p/error.h +++ b/fs/9p/error.h @@ -176,4 +176,3 @@ static struct errormap errmap[] = { }; extern int v9fs_error_init(void); -extern int v9fs_errstr2errno(char *errstr, int len); diff --git a/fs/9p/mux.c b/fs/9p/mux.c index f21cf508397..945cb368d45 100644 --- a/fs/9p/mux.c +++ b/fs/9p/mux.c @@ -102,8 +102,6 @@ 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 *); @@ -119,7 +117,7 @@ static int v9fs_mux_num; static int v9fs_mux_poll_task_num; 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; @@ -127,6 +125,10 @@ void v9fs_mux_global_init(void) v9fs_mux_poll_tasks[i].task = NULL; v9fs_mux_wq = create_workqueue("v9fs"); + if (!v9fs_mux_wq) + return -ENOMEM; + + return 0; } void v9fs_mux_global_exit(void) @@ -156,10 +158,11 @@ inline int v9fs_mux_calc_poll_procs(int muxnum) 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; 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, v9fs_mux_poll_task_num); @@ -171,13 +174,16 @@ 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, + pproc = kthread_create(v9fs_poll_proc, vpt, "v9fs-poll"); - INIT_LIST_HEAD(&vpt->mux_list); - vpt->muxnum = 0; - v9fs_mux_poll_task_num++; - wake_up_process(vpt->task); + + if (!IS_ERR(pproc)) { + vpt->task = pproc; + INIT_LIST_HEAD(&vpt->mux_list); + vpt->muxnum = 0; + v9fs_mux_poll_task_num++; + wake_up_process(vpt->task); + } break; } } @@ -207,16 +213,21 @@ static void v9fs_mux_poll_start(struct v9fs_mux_data *m) } if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) { + if (vptlast == NULL) + return -ENOMEM; + dprintk(DEBUG_MUX, "put in proc %d\n", i); list_add(&m->mux_list, &vptlast->mux_list); vptlast->muxnum++; - m->poll_task = vpt; + m->poll_task = vptlast; memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); init_poll_funcptr(&m->pt, v9fs_pollwait); } v9fs_mux_num++; down(&v9fs_mux_task_lock); + + return 0; } 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, INIT_WORK(&m->wq, v9fs_write_work, m); m->wsched = 0; 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); if (n & POLLIN) { diff --git a/fs/9p/mux.h b/fs/9p/mux.h index 02b13b14b05..9473b84f24b 100644 --- a/fs/9p/mux.h +++ b/fs/9p/mux.h @@ -40,7 +40,7 @@ struct v9fs_mux_data; typedef void (*v9fs_mux_req_callback)(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err); -void v9fs_mux_global_init(void); +int v9fs_mux_global_init(void); void v9fs_mux_global_exit(void); 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, void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush); void v9fs_mux_cancel(struct v9fs_mux_data *m, int err); +int v9fs_errstr2errno(char *errstr, int len); diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 519b21d8b15..5250c428fc1 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -269,6 +269,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses, int n = 0; int newfid = -1; int retval = -EINVAL; + struct v9fs_str *version; v9ses->name = __getname(); if (!v9ses->name) @@ -351,13 +352,16 @@ v9fs_session_init(struct v9fs_session_info *v9ses, goto FreeFcall; } - /* Really should check for 9P1 and report error */ - if (!v9fs_str_compare("9P2000.u", &fcall->params.rversion.version)) { + version = &fcall->params.rversion.version; + if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) { dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n"); v9ses->extended = 1; - } else { + } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) { dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n"); v9ses->extended = 0; + } else { + retval = -EREMOTEIO; + goto FreeFcall; } n = fcall->params.rversion.msize; @@ -449,12 +453,17 @@ extern int v9fs_error_init(void); static int __init init_v9fs(void) { + int ret; + v9fs_error_init(); printk(KERN_INFO "Installing v9fs 9P2000 file system support\n"); - v9fs_mux_global_init(); - return register_filesystem(&v9fs_fs_type); + ret = v9fs_mux_global_init(); + if (!ret) + ret = register_filesystem(&v9fs_fs_type); + + return ret; } /** diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 742bcd0dc4a..d933ef1fbd8 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -768,6 +768,7 @@ void v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, struct super_block *sb) { + int n; char ext[32]; struct v9fs_session_info *v9ses = sb->s_fs_info; @@ -791,7 +792,11 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode, int major = -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); switch (type) { case 'c': diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index d4d71a9ca57..ae0f06b3c11 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -122,11 +122,10 @@ static struct super_block *v9fs_get_sb(struct file_system_type dprintk(DEBUG_VFS, " \n"); - v9ses = kmalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); + v9ses = kzalloc(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); -- cgit v1.2.3