The following changes since commit 4cbe5a555fa58a79b6ecbb6c531b8bab0650778d:
Linux 3.6-rc4 (2012-09-01 10:39:58 -0700) are available in the git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git for-next for you to fetch changes up to 552aad02a283ee88406b102b4d6455eef7127196: 9P: Fix race between p9_write_work() and p9_fd_request() (2012-09-17 14:54:11 -0500) ---------------------------------------------------------------- Jeff Layton (1): 9p: don't use __getname/__putname for uname/aname Jim Meyering (1): fs/9p: avoid debug OOPS when reading a long symlink Simon Derr (5): net/9p: Check errno validity 9P: Fix race in p9_read_work() 9P: fix test at the end of p9_write_work() 9P: Fix race in p9_write_work() 9P: Fix race between p9_write_work() and p9_fd_request() fs/9p/v9fs.c | 30 +++++++++++++++++++----------- fs/9p/vfs_inode.c | 8 ++++---- net/9p/client.c | 18 ++++++++++++++++-- net/9p/trans_fd.c | 38 ++++++++++++++++++++------------------ 4 files changed, 59 insertions(+), 35 deletions(-) Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.17 (Darwin) Comment: GPGTools - http://gpgtools.org iQIcBAABAgAGBQJQdvxdAAoJEDZk62b0Tg6xru8QAL1I6YH+O6c+sHONQQnifkl/ WciZDUSYx7Pd4Ffy48m6y5J6M2VNFUIzqpIKnm4xAiHUwct/E/+yuyfK2zAe1Jxc nqPxoU2iyFWXc1Hu5HQhrjMXMlqePPuF1kwTYd0vCXXbVgWfbhwYfjoRr3PGuVTD 3SpQrBxIvQj1aWRMyyQTcnqnmTLPFr1kX0TRBgvipSfQETVFR5gCXK8sJUDvU+0S 4kywmb3y31/EpcKdDs7CE1m5kCi6T2mguP5NR4dHtN8YT76IW4urIqyAw6069wQV AMmoqhJP2cJ6kyyh93ltZSgcMIUgfrDj2pIsGT3hILusTh9vBT10Db8iNT2ledy8 W+TxjK0/H0h5rfitHYqD+XnCF4pKFRm5aOOYL8jg02Uh8jU9MzkAIw1/fmXUOZ7O rht+HttJht2QCFniV1C442hbzL0J5mYsGPwpWZ5j4dN7PBIi8SYh+Ik0la4rRa8I m9C04HHvPsc0gRXPAp1+Ptby4FnPS846a9Ffm4xrkNhFl3z916ef67MnoCGu3roM GU9FEOdWhSWJ+52qLcXZwqkrPvlUMOehwnSjlab3BCThPRVK0D7gdTzBN4NDQZWo AzhK5sNRFwEidnYo7gy0g2UsRWRgPP7fiUe/xtlWaBlm0DU1+jZc/uzjEn6/h77R fQfniKFcMRFIeksGts5e =hADE -----END PGP SIGNATURE----- Merge tag 'for-linus-merge-3.7' of git://git.kernel.org/pub/scm/linux/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
This commit is contained in:
Коммит
940e3a8dd6
30
fs/9p/v9fs.c
30
fs/9p/v9fs.c
|
@ -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;
|
||||
|
@ -287,21 +297,21 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -309,8 +319,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
|
|||
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;
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -782,7 +796,7 @@ again:
|
|||
return req;
|
||||
reterr:
|
||||
p9_free_req(c, req);
|
||||
return ERR_PTR(err);
|
||||
return ERR_PTR(safe_errno(err));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче