|
@@ -283,8 +283,9 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size)
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
}
|
|
for (col = 0; col < P9_ROW_MAXTAG; col++) {
|
|
for (col = 0; col < P9_ROW_MAXTAG; col++) {
|
|
- c->reqs[row][col].status = REQ_STATUS_IDLE;
|
|
|
|
- c->reqs[row][col].tc = NULL;
|
|
|
|
|
|
+ req = &c->reqs[row][col];
|
|
|
|
+ req->status = REQ_STATUS_IDLE;
|
|
|
|
+ init_waitqueue_head(&req->wq);
|
|
}
|
|
}
|
|
c->max_tag += P9_ROW_MAXTAG;
|
|
c->max_tag += P9_ROW_MAXTAG;
|
|
}
|
|
}
|
|
@@ -294,13 +295,6 @@ p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size)
|
|
col = tag % P9_ROW_MAXTAG;
|
|
col = tag % P9_ROW_MAXTAG;
|
|
|
|
|
|
req = &c->reqs[row][col];
|
|
req = &c->reqs[row][col];
|
|
- if (!req->wq) {
|
|
|
|
- req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS);
|
|
|
|
- if (!req->wq)
|
|
|
|
- goto grow_failed;
|
|
|
|
- init_waitqueue_head(req->wq);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (!req->tc)
|
|
if (!req->tc)
|
|
req->tc = p9_fcall_alloc(alloc_msize);
|
|
req->tc = p9_fcall_alloc(alloc_msize);
|
|
if (!req->rc)
|
|
if (!req->rc)
|
|
@@ -320,9 +314,7 @@ grow_failed:
|
|
pr_err("Couldn't grow tag array\n");
|
|
pr_err("Couldn't grow tag array\n");
|
|
kfree(req->tc);
|
|
kfree(req->tc);
|
|
kfree(req->rc);
|
|
kfree(req->rc);
|
|
- kfree(req->wq);
|
|
|
|
req->tc = req->rc = NULL;
|
|
req->tc = req->rc = NULL;
|
|
- req->wq = NULL;
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -341,7 +333,7 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)
|
|
* buffer to read the data into */
|
|
* buffer to read the data into */
|
|
tag++;
|
|
tag++;
|
|
|
|
|
|
- if(tag >= c->max_tag)
|
|
|
|
|
|
+ if (tag >= c->max_tag)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
row = tag / P9_ROW_MAXTAG;
|
|
row = tag / P9_ROW_MAXTAG;
|
|
@@ -410,7 +402,6 @@ static void p9_tag_cleanup(struct p9_client *c)
|
|
/* free requests associated with tags */
|
|
/* free requests associated with tags */
|
|
for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
|
|
for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) {
|
|
for (col = 0; col < P9_ROW_MAXTAG; col++) {
|
|
for (col = 0; col < P9_ROW_MAXTAG; col++) {
|
|
- kfree(c->reqs[row][col].wq);
|
|
|
|
kfree(c->reqs[row][col].tc);
|
|
kfree(c->reqs[row][col].tc);
|
|
kfree(c->reqs[row][col].rc);
|
|
kfree(c->reqs[row][col].rc);
|
|
}
|
|
}
|
|
@@ -448,12 +439,12 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status)
|
|
|
|
|
|
/*
|
|
/*
|
|
* This barrier is needed to make sure any change made to req before
|
|
* This barrier is needed to make sure any change made to req before
|
|
- * the other thread wakes up will indeed be seen by the waiting side.
|
|
|
|
|
|
+ * the status change is visible to another thread
|
|
*/
|
|
*/
|
|
smp_wmb();
|
|
smp_wmb();
|
|
req->status = status;
|
|
req->status = status;
|
|
|
|
|
|
- wake_up(req->wq);
|
|
|
|
|
|
+ wake_up(&req->wq);
|
|
p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
|
|
p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(p9_client_cb);
|
|
EXPORT_SYMBOL(p9_client_cb);
|
|
@@ -478,20 +469,11 @@ p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
|
|
int err;
|
|
int err;
|
|
|
|
|
|
pdu->offset = 0;
|
|
pdu->offset = 0;
|
|
- if (pdu->size == 0)
|
|
|
|
- pdu->size = 7;
|
|
|
|
|
|
|
|
err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
|
|
err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
|
|
if (err)
|
|
if (err)
|
|
goto rewind_and_exit;
|
|
goto rewind_and_exit;
|
|
|
|
|
|
- pdu->size = r_size;
|
|
|
|
- pdu->id = r_type;
|
|
|
|
- pdu->tag = r_tag;
|
|
|
|
-
|
|
|
|
- p9_debug(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n",
|
|
|
|
- pdu->size, pdu->id, pdu->tag);
|
|
|
|
-
|
|
|
|
if (type)
|
|
if (type)
|
|
*type = r_type;
|
|
*type = r_type;
|
|
if (tag)
|
|
if (tag)
|
|
@@ -499,6 +481,16 @@ p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
|
|
if (size)
|
|
if (size)
|
|
*size = r_size;
|
|
*size = r_size;
|
|
|
|
|
|
|
|
+ if (pdu->size != r_size || r_size < 7) {
|
|
|
|
+ err = -EINVAL;
|
|
|
|
+ goto rewind_and_exit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pdu->id = r_type;
|
|
|
|
+ pdu->tag = r_tag;
|
|
|
|
+
|
|
|
|
+ p9_debug(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n",
|
|
|
|
+ pdu->size, pdu->id, pdu->tag);
|
|
|
|
|
|
rewind_and_exit:
|
|
rewind_and_exit:
|
|
if (rewind)
|
|
if (rewind)
|
|
@@ -525,6 +517,12 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
|
|
int ecode;
|
|
int ecode;
|
|
|
|
|
|
err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
|
|
err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
|
|
|
|
+ if (req->rc->size >= c->msize) {
|
|
|
|
+ p9_debug(P9_DEBUG_ERROR,
|
|
|
|
+ "requested packet size too big: %d\n",
|
|
|
|
+ req->rc->size);
|
|
|
|
+ return -EIO;
|
|
|
|
+ }
|
|
/*
|
|
/*
|
|
* dump the response from server
|
|
* dump the response from server
|
|
* This should be after check errors which poplulate pdu_fcall.
|
|
* This should be after check errors which poplulate pdu_fcall.
|
|
@@ -774,7 +772,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
|
|
}
|
|
}
|
|
again:
|
|
again:
|
|
/* Wait for the response */
|
|
/* Wait for the response */
|
|
- err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD);
|
|
|
|
|
|
+ err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Make sure our req is coherent with regard to updates in other
|
|
* Make sure our req is coherent with regard to updates in other
|
|
@@ -909,34 +907,31 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
struct p9_fid *fid;
|
|
struct p9_fid *fid;
|
|
- unsigned long flags;
|
|
|
|
|
|
|
|
p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt);
|
|
p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt);
|
|
fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
|
|
fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
|
|
if (!fid)
|
|
if (!fid)
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
|
-
|
|
|
|
- ret = p9_idpool_get(clnt->fidpool);
|
|
|
|
- if (ret < 0) {
|
|
|
|
- ret = -ENOSPC;
|
|
|
|
- goto error;
|
|
|
|
- }
|
|
|
|
- fid->fid = ret;
|
|
|
|
|
|
+ return NULL;
|
|
|
|
|
|
memset(&fid->qid, 0, sizeof(struct p9_qid));
|
|
memset(&fid->qid, 0, sizeof(struct p9_qid));
|
|
fid->mode = -1;
|
|
fid->mode = -1;
|
|
fid->uid = current_fsuid();
|
|
fid->uid = current_fsuid();
|
|
fid->clnt = clnt;
|
|
fid->clnt = clnt;
|
|
fid->rdir = NULL;
|
|
fid->rdir = NULL;
|
|
- spin_lock_irqsave(&clnt->lock, flags);
|
|
|
|
- list_add(&fid->flist, &clnt->fidlist);
|
|
|
|
- spin_unlock_irqrestore(&clnt->lock, flags);
|
|
|
|
|
|
+ fid->fid = 0;
|
|
|
|
|
|
- return fid;
|
|
|
|
|
|
+ idr_preload(GFP_KERNEL);
|
|
|
|
+ spin_lock_irq(&clnt->lock);
|
|
|
|
+ ret = idr_alloc_u32(&clnt->fids, fid, &fid->fid, P9_NOFID - 1,
|
|
|
|
+ GFP_NOWAIT);
|
|
|
|
+ spin_unlock_irq(&clnt->lock);
|
|
|
|
+ idr_preload_end();
|
|
|
|
+
|
|
|
|
+ if (!ret)
|
|
|
|
+ return fid;
|
|
|
|
|
|
-error:
|
|
|
|
kfree(fid);
|
|
kfree(fid);
|
|
- return ERR_PTR(ret);
|
|
|
|
|
|
+ return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static void p9_fid_destroy(struct p9_fid *fid)
|
|
static void p9_fid_destroy(struct p9_fid *fid)
|
|
@@ -946,9 +941,8 @@ static void p9_fid_destroy(struct p9_fid *fid)
|
|
|
|
|
|
p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
|
|
p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
|
|
clnt = fid->clnt;
|
|
clnt = fid->clnt;
|
|
- p9_idpool_put(fid->fid, clnt->fidpool);
|
|
|
|
spin_lock_irqsave(&clnt->lock, flags);
|
|
spin_lock_irqsave(&clnt->lock, flags);
|
|
- list_del(&fid->flist);
|
|
|
|
|
|
+ idr_remove(&clnt->fids, fid->fid);
|
|
spin_unlock_irqrestore(&clnt->lock, flags);
|
|
spin_unlock_irqrestore(&clnt->lock, flags);
|
|
kfree(fid->rdir);
|
|
kfree(fid->rdir);
|
|
kfree(fid);
|
|
kfree(fid);
|
|
@@ -958,7 +952,7 @@ static int p9_client_version(struct p9_client *c)
|
|
{
|
|
{
|
|
int err = 0;
|
|
int err = 0;
|
|
struct p9_req_t *req;
|
|
struct p9_req_t *req;
|
|
- char *version;
|
|
|
|
|
|
+ char *version = NULL;
|
|
int msize;
|
|
int msize;
|
|
|
|
|
|
p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
|
|
p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n",
|
|
@@ -1031,7 +1025,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
|
memcpy(clnt->name, client_id, strlen(client_id) + 1);
|
|
memcpy(clnt->name, client_id, strlen(client_id) + 1);
|
|
|
|
|
|
spin_lock_init(&clnt->lock);
|
|
spin_lock_init(&clnt->lock);
|
|
- INIT_LIST_HEAD(&clnt->fidlist);
|
|
|
|
|
|
+ idr_init(&clnt->fids);
|
|
|
|
|
|
err = p9_tag_init(clnt);
|
|
err = p9_tag_init(clnt);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
@@ -1051,18 +1045,12 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
|
goto destroy_tagpool;
|
|
goto destroy_tagpool;
|
|
}
|
|
}
|
|
|
|
|
|
- clnt->fidpool = p9_idpool_create();
|
|
|
|
- if (IS_ERR(clnt->fidpool)) {
|
|
|
|
- err = PTR_ERR(clnt->fidpool);
|
|
|
|
- goto put_trans;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
|
|
p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n",
|
|
clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
|
|
clnt, clnt->trans_mod, clnt->msize, clnt->proto_version);
|
|
|
|
|
|
err = clnt->trans_mod->create(clnt, dev_name, options);
|
|
err = clnt->trans_mod->create(clnt, dev_name, options);
|
|
if (err)
|
|
if (err)
|
|
- goto destroy_fidpool;
|
|
|
|
|
|
+ goto put_trans;
|
|
|
|
|
|
if (clnt->msize > clnt->trans_mod->maxsize)
|
|
if (clnt->msize > clnt->trans_mod->maxsize)
|
|
clnt->msize = clnt->trans_mod->maxsize;
|
|
clnt->msize = clnt->trans_mod->maxsize;
|
|
@@ -1075,8 +1063,6 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
|
|
|
|
|
close_trans:
|
|
close_trans:
|
|
clnt->trans_mod->close(clnt);
|
|
clnt->trans_mod->close(clnt);
|
|
-destroy_fidpool:
|
|
|
|
- p9_idpool_destroy(clnt->fidpool);
|
|
|
|
put_trans:
|
|
put_trans:
|
|
v9fs_put_trans(clnt->trans_mod);
|
|
v9fs_put_trans(clnt->trans_mod);
|
|
destroy_tagpool:
|
|
destroy_tagpool:
|
|
@@ -1089,7 +1075,8 @@ EXPORT_SYMBOL(p9_client_create);
|
|
|
|
|
|
void p9_client_destroy(struct p9_client *clnt)
|
|
void p9_client_destroy(struct p9_client *clnt)
|
|
{
|
|
{
|
|
- struct p9_fid *fid, *fidptr;
|
|
|
|
|
|
+ struct p9_fid *fid;
|
|
|
|
+ int id;
|
|
|
|
|
|
p9_debug(P9_DEBUG_MUX, "clnt %p\n", clnt);
|
|
p9_debug(P9_DEBUG_MUX, "clnt %p\n", clnt);
|
|
|
|
|
|
@@ -1098,14 +1085,11 @@ void p9_client_destroy(struct p9_client *clnt)
|
|
|
|
|
|
v9fs_put_trans(clnt->trans_mod);
|
|
v9fs_put_trans(clnt->trans_mod);
|
|
|
|
|
|
- list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) {
|
|
|
|
|
|
+ idr_for_each_entry(&clnt->fids, fid, id) {
|
|
pr_info("Found fid %d not clunked\n", fid->fid);
|
|
pr_info("Found fid %d not clunked\n", fid->fid);
|
|
p9_fid_destroy(fid);
|
|
p9_fid_destroy(fid);
|
|
}
|
|
}
|
|
|
|
|
|
- if (clnt->fidpool)
|
|
|
|
- p9_idpool_destroy(clnt->fidpool);
|
|
|
|
-
|
|
|
|
p9_tag_cleanup(clnt);
|
|
p9_tag_cleanup(clnt);
|
|
|
|
|
|
kfree(clnt);
|
|
kfree(clnt);
|
|
@@ -1138,9 +1122,8 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
|
|
p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
|
|
p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
|
|
afid ? afid->fid : -1, uname, aname);
|
|
afid ? afid->fid : -1, uname, aname);
|
|
fid = p9_fid_create(clnt);
|
|
fid = p9_fid_create(clnt);
|
|
- if (IS_ERR(fid)) {
|
|
|
|
- err = PTR_ERR(fid);
|
|
|
|
- fid = NULL;
|
|
|
|
|
|
+ if (!fid) {
|
|
|
|
+ err = -ENOMEM;
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
fid->uid = n_uname;
|
|
fid->uid = n_uname;
|
|
@@ -1189,9 +1172,8 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
|
|
clnt = oldfid->clnt;
|
|
clnt = oldfid->clnt;
|
|
if (clone) {
|
|
if (clone) {
|
|
fid = p9_fid_create(clnt);
|
|
fid = p9_fid_create(clnt);
|
|
- if (IS_ERR(fid)) {
|
|
|
|
- err = PTR_ERR(fid);
|
|
|
|
- fid = NULL;
|
|
|
|
|
|
+ if (!fid) {
|
|
|
|
+ err = -ENOMEM;
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1576,7 +1558,7 @@ p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err)
|
|
int count = iov_iter_count(to);
|
|
int count = iov_iter_count(to);
|
|
int rsize, non_zc = 0;
|
|
int rsize, non_zc = 0;
|
|
char *dataptr;
|
|
char *dataptr;
|
|
-
|
|
|
|
|
|
+
|
|
rsize = fid->iounit;
|
|
rsize = fid->iounit;
|
|
if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
|
|
if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
|
|
rsize = clnt->msize - P9_IOHDRSZ;
|
|
rsize = clnt->msize - P9_IOHDRSZ;
|
|
@@ -1790,7 +1772,7 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
|
|
"<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n"
|
|
"<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n"
|
|
"<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n"
|
|
"<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n"
|
|
"<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
|
|
"<<< st_btime_sec=%lld st_btime_nsec=%lld\n"
|
|
- "<<< st_gen=%lld st_data_version=%lld",
|
|
|
|
|
|
+ "<<< st_gen=%lld st_data_version=%lld\n",
|
|
ret->st_result_mask, ret->qid.type, ret->qid.path,
|
|
ret->st_result_mask, ret->qid.type, ret->qid.path,
|
|
ret->qid.version, ret->st_mode, ret->st_nlink,
|
|
ret->qid.version, ret->st_mode, ret->st_nlink,
|
|
from_kuid(&init_user_ns, ret->st_uid),
|
|
from_kuid(&init_user_ns, ret->st_uid),
|
|
@@ -2019,9 +2001,8 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
|
|
err = 0;
|
|
err = 0;
|
|
clnt = file_fid->clnt;
|
|
clnt = file_fid->clnt;
|
|
attr_fid = p9_fid_create(clnt);
|
|
attr_fid = p9_fid_create(clnt);
|
|
- if (IS_ERR(attr_fid)) {
|
|
|
|
- err = PTR_ERR(attr_fid);
|
|
|
|
- attr_fid = NULL;
|
|
|
|
|
|
+ if (!attr_fid) {
|
|
|
|
+ err = -ENOMEM;
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
p9_debug(P9_DEBUG_9P,
|
|
p9_debug(P9_DEBUG_9P,
|