Skip to content

Commit

Permalink
Merge tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/ericvh/v9fs

Pull v9fs update from Eric Van Hensbergen.

* tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
  9P: Fix race between p9_write_work() and p9_fd_request()
  9P: Fix race in p9_write_work()
  9P: fix test at the end of p9_write_work()
  9P: Fix race in p9_read_work()
  9p: don't use __getname/__putname for uname/aname
  net/9p: Check errno validity
  fs/9p: avoid debug OOPS when reading a long symlink
  • Loading branch information
Linus Torvalds committed Oct 12, 2012
2 parents 12250d8 + 759f429 commit 940e3a8
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 35 deletions.
30 changes: 19 additions & 11 deletions fs/9p/v9fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,20 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
v9ses->afid = option;
break;
case Opt_uname:
match_strlcpy(v9ses->uname, &args[0], PATH_MAX);
kfree(v9ses->uname);
v9ses->uname = match_strdup(&args[0]);
if (!v9ses->uname) {
ret = -ENOMEM;
goto free_and_return;
}
break;
case Opt_remotename:
match_strlcpy(v9ses->aname, &args[0], PATH_MAX);
kfree(v9ses->aname);
v9ses->aname = match_strdup(&args[0]);
if (!v9ses->aname) {
ret = -ENOMEM;
goto free_and_return;
}
break;
case Opt_nodevmap:
v9ses->nodev = 1;
Expand Down Expand Up @@ -287,30 +297,28 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
struct p9_fid *fid;
int rc;

v9ses->uname = __getname();
v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL);
if (!v9ses->uname)
return ERR_PTR(-ENOMEM);

v9ses->aname = __getname();
v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL);
if (!v9ses->aname) {
__putname(v9ses->uname);
kfree(v9ses->uname);
return ERR_PTR(-ENOMEM);
}
init_rwsem(&v9ses->rename_sem);

rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY);
if (rc) {
__putname(v9ses->aname);
__putname(v9ses->uname);
kfree(v9ses->aname);
kfree(v9ses->uname);
return ERR_PTR(rc);
}

spin_lock(&v9fs_sessionlist_lock);
list_add(&v9ses->slist, &v9fs_sessionlist);
spin_unlock(&v9fs_sessionlist_lock);

strcpy(v9ses->uname, V9FS_DEFUSER);
strcpy(v9ses->aname, V9FS_DEFANAME);
v9ses->uid = ~0;
v9ses->dfltuid = V9FS_DEFUID;
v9ses->dfltgid = V9FS_DEFGID;
Expand Down Expand Up @@ -412,8 +420,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
kfree(v9ses->cachetag);
}
#endif
__putname(v9ses->uname);
__putname(v9ses->aname);
kfree(v9ses->uname);
kfree(v9ses->aname);

bdi_destroy(&v9ses->bdi);

Expand Down
8 changes: 4 additions & 4 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1276,12 +1276,12 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
}

/* copy extension buffer into buffer */
strncpy(buffer, st->extension, buflen);
retval = min(strlen(st->extension)+1, (size_t)buflen);
memcpy(buffer, st->extension, retval);

p9_debug(P9_DEBUG_VFS, "%s -> %s (%s)\n",
dentry->d_name.name, st->extension, buffer);
p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n",
dentry->d_name.name, st->extension, buflen, buffer);

retval = strnlen(buffer, buflen);
done:
p9stat_free(st);
kfree(st);
Expand Down
18 changes: 16 additions & 2 deletions net/9p/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)
}
EXPORT_SYMBOL(p9_is_proto_dotu);

/*
* Some error codes are taken directly from the server replies,
* make sure they are valid.
*/
static int safe_errno(int err)
{
if ((err > 0) || (err < -MAX_ERRNO)) {
p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err);
return -EPROTO;
}
return err;
}


/* Interpret mount option for protocol version */
static int get_protocol_version(char *s)
{
Expand Down Expand Up @@ -782,7 +796,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
return req;
reterr:
p9_free_req(c, req);
return ERR_PTR(err);
return ERR_PTR(safe_errno(err));
}

/**
Expand Down Expand Up @@ -865,7 +879,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
return req;
reterr:
p9_free_req(c, req);
return ERR_PTR(err);
return ERR_PTR(safe_errno(err));
}

static struct p9_fid *p9_fid_create(struct p9_client *clnt)
Expand Down
38 changes: 20 additions & 18 deletions net/9p/trans_fd.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,7 @@ static void p9_read_work(struct work_struct *work)
m->rsize - m->rpos);
p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err);
if (err == -EAGAIN) {
clear_bit(Rworksched, &m->wsched);
return;
goto end_clear;
}

if (err <= 0)
Expand Down Expand Up @@ -379,19 +378,20 @@ static void p9_read_work(struct work_struct *work)
m->req = NULL;
}

end_clear:
clear_bit(Rworksched, &m->wsched);

if (!list_empty(&m->req_list)) {
if (test_and_clear_bit(Rpending, &m->wsched))
n = POLLIN;
else
n = p9_fd_poll(m->client, NULL);

if (n & POLLIN) {
if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) {
p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m);
schedule_work(&m->rq);
} else
clear_bit(Rworksched, &m->wsched);
} else
clear_bit(Rworksched, &m->wsched);
}
}

return;
error:
Expand Down Expand Up @@ -453,12 +453,13 @@ static void p9_write_work(struct work_struct *work)
}

if (!m->wsize) {
spin_lock(&m->client->lock);
if (list_empty(&m->unsent_req_list)) {
clear_bit(Wworksched, &m->wsched);
spin_unlock(&m->client->lock);
return;
}

spin_lock(&m->client->lock);
req = list_entry(m->unsent_req_list.next, struct p9_req_t,
req_list);
req->status = REQ_STATUS_SENT;
Expand All @@ -476,10 +477,9 @@ static void p9_write_work(struct work_struct *work)
clear_bit(Wpending, &m->wsched);
err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos);
p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err);
if (err == -EAGAIN) {
clear_bit(Wworksched, &m->wsched);
return;
}
if (err == -EAGAIN)
goto end_clear;


if (err < 0)
goto error;
Expand All @@ -492,19 +492,21 @@ static void p9_write_work(struct work_struct *work)
if (m->wpos == m->wsize)
m->wpos = m->wsize = 0;

if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
end_clear:
clear_bit(Wworksched, &m->wsched);

if (m->wsize || !list_empty(&m->unsent_req_list)) {
if (test_and_clear_bit(Wpending, &m->wsched))
n = POLLOUT;
else
n = p9_fd_poll(m->client, NULL);

if (n & POLLOUT) {
if ((n & POLLOUT) &&
!test_and_set_bit(Wworksched, &m->wsched)) {
p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m);
schedule_work(&m->wq);
} else
clear_bit(Wworksched, &m->wsched);
} else
clear_bit(Wworksched, &m->wsched);
}
}

return;

Expand Down

0 comments on commit 940e3a8

Please sign in to comment.