|
@@ -69,7 +69,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
|
|
|
|
|
|
static int parse_opts(char *opts, struct p9_client *clnt)
|
|
static int parse_opts(char *opts, struct p9_client *clnt)
|
|
{
|
|
{
|
|
- char *options;
|
|
|
|
|
|
+ char *options, *tmp_options;
|
|
char *p;
|
|
char *p;
|
|
substring_t args[MAX_OPT_ARGS];
|
|
substring_t args[MAX_OPT_ARGS];
|
|
int option;
|
|
int option;
|
|
@@ -81,12 +81,13 @@ static int parse_opts(char *opts, struct p9_client *clnt)
|
|
if (!opts)
|
|
if (!opts)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- options = kstrdup(opts, GFP_KERNEL);
|
|
|
|
- if (!options) {
|
|
|
|
|
|
+ tmp_options = kstrdup(opts, GFP_KERNEL);
|
|
|
|
+ if (!tmp_options) {
|
|
P9_DPRINTK(P9_DEBUG_ERROR,
|
|
P9_DPRINTK(P9_DEBUG_ERROR,
|
|
"failed to allocate copy of option string\n");
|
|
"failed to allocate copy of option string\n");
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
+ options = tmp_options;
|
|
|
|
|
|
while ((p = strsep(&options, ",")) != NULL) {
|
|
while ((p = strsep(&options, ",")) != NULL) {
|
|
int token;
|
|
int token;
|
|
@@ -108,6 +109,13 @@ static int parse_opts(char *opts, struct p9_client *clnt)
|
|
break;
|
|
break;
|
|
case Opt_trans:
|
|
case Opt_trans:
|
|
clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
|
|
clnt->trans_mod = v9fs_get_trans_by_name(&args[0]);
|
|
|
|
+ if(clnt->trans_mod == NULL) {
|
|
|
|
+ P9_DPRINTK(P9_DEBUG_ERROR,
|
|
|
|
+ "Could not find request transport: %s\n",
|
|
|
|
+ (char *) &args[0]);
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto free_and_return;
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
case Opt_legacy:
|
|
case Opt_legacy:
|
|
clnt->dotu = 0;
|
|
clnt->dotu = 0;
|
|
@@ -117,7 +125,8 @@ static int parse_opts(char *opts, struct p9_client *clnt)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- kfree(options);
|
|
|
|
|
|
+free_and_return:
|
|
|
|
+ kfree(tmp_options);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -667,18 +676,12 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
|
clnt->trans = NULL;
|
|
clnt->trans = NULL;
|
|
spin_lock_init(&clnt->lock);
|
|
spin_lock_init(&clnt->lock);
|
|
INIT_LIST_HEAD(&clnt->fidlist);
|
|
INIT_LIST_HEAD(&clnt->fidlist);
|
|
- clnt->fidpool = p9_idpool_create();
|
|
|
|
- if (IS_ERR(clnt->fidpool)) {
|
|
|
|
- err = PTR_ERR(clnt->fidpool);
|
|
|
|
- clnt->fidpool = NULL;
|
|
|
|
- goto error;
|
|
|
|
- }
|
|
|
|
|
|
|
|
p9_tag_init(clnt);
|
|
p9_tag_init(clnt);
|
|
|
|
|
|
err = parse_opts(options, clnt);
|
|
err = parse_opts(options, clnt);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
- goto error;
|
|
|
|
|
|
+ goto free_client;
|
|
|
|
|
|
if (!clnt->trans_mod)
|
|
if (!clnt->trans_mod)
|
|
clnt->trans_mod = v9fs_get_default_trans();
|
|
clnt->trans_mod = v9fs_get_default_trans();
|
|
@@ -687,7 +690,14 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
|
err = -EPROTONOSUPPORT;
|
|
err = -EPROTONOSUPPORT;
|
|
P9_DPRINTK(P9_DEBUG_ERROR,
|
|
P9_DPRINTK(P9_DEBUG_ERROR,
|
|
"No transport defined or default transport\n");
|
|
"No transport defined or default transport\n");
|
|
- goto error;
|
|
|
|
|
|
+ goto free_client;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ clnt->fidpool = p9_idpool_create();
|
|
|
|
+ if (IS_ERR(clnt->fidpool)) {
|
|
|
|
+ err = PTR_ERR(clnt->fidpool);
|
|
|
|
+ clnt->fidpool = NULL;
|
|
|
|
+ goto put_trans;
|
|
}
|
|
}
|
|
|
|
|
|
P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
|
|
P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n",
|
|
@@ -695,19 +705,25 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
|
|
|
|
|
err = clnt->trans_mod->create(clnt, dev_name, options);
|
|
err = clnt->trans_mod->create(clnt, dev_name, options);
|
|
if (err)
|
|
if (err)
|
|
- goto error;
|
|
|
|
|
|
+ goto destroy_fidpool;
|
|
|
|
|
|
if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
|
|
if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize)
|
|
clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
|
|
clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ;
|
|
|
|
|
|
err = p9_client_version(clnt);
|
|
err = p9_client_version(clnt);
|
|
if (err)
|
|
if (err)
|
|
- goto error;
|
|
|
|
|
|
+ goto close_trans;
|
|
|
|
|
|
return clnt;
|
|
return clnt;
|
|
|
|
|
|
-error:
|
|
|
|
- p9_client_destroy(clnt);
|
|
|
|
|
|
+close_trans:
|
|
|
|
+ clnt->trans_mod->close(clnt);
|
|
|
|
+destroy_fidpool:
|
|
|
|
+ p9_idpool_destroy(clnt->fidpool);
|
|
|
|
+put_trans:
|
|
|
|
+ v9fs_put_trans(clnt->trans_mod);
|
|
|
|
+free_client:
|
|
|
|
+ kfree(clnt);
|
|
return ERR_PTR(err);
|
|
return ERR_PTR(err);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(p9_client_create);
|
|
EXPORT_SYMBOL(p9_client_create);
|
|
@@ -1214,10 +1230,11 @@ static int p9_client_statsize(struct p9_wstat *wst, int optional)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
+ /* NOTE: size shouldn't include its own length */
|
|
/* size[2] type[2] dev[4] qid[13] */
|
|
/* size[2] type[2] dev[4] qid[13] */
|
|
/* mode[4] atime[4] mtime[4] length[8]*/
|
|
/* mode[4] atime[4] mtime[4] length[8]*/
|
|
/* name[s] uid[s] gid[s] muid[s] */
|
|
/* name[s] uid[s] gid[s] muid[s] */
|
|
- ret = 2+2+4+13+4+4+4+8+2+2+2+2;
|
|
|
|
|
|
+ ret = 2+4+13+4+4+4+8+2+2+2+2;
|
|
|
|
|
|
if (wst->name)
|
|
if (wst->name)
|
|
ret += strlen(wst->name);
|
|
ret += strlen(wst->name);
|
|
@@ -1258,7 +1275,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
|
|
wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
|
|
wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
|
|
wst->n_uid, wst->n_gid, wst->n_muid);
|
|
wst->n_uid, wst->n_gid, wst->n_muid);
|
|
|
|
|
|
- req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst);
|
|
|
|
|
|
+ req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst);
|
|
if (IS_ERR(req)) {
|
|
if (IS_ERR(req)) {
|
|
err = PTR_ERR(req);
|
|
err = PTR_ERR(req);
|
|
goto error;
|
|
goto error;
|