Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: 9p: fix p9_client_destroy unconditional calling v9fs_put_trans 9p: fix memory leak in v9fs_parse_options() 9p: Fix the kernel crash on a failed mount 9p: fix option parsing 9p: Include fsync support for 9p client net/9p: fix statsize inside twstat net/9p: fail when user specifies a transport which we can't find net/9p: fix virtio transport to correctly update status on connect
This commit is contained in:
commit
3af9cf11b6
33
fs/9p/v9fs.c
33
fs/9p/v9fs.c
@ -84,7 +84,7 @@ static const match_table_t tokens = {
|
|||||||
|
|
||||||
static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
||||||
{
|
{
|
||||||
char *options;
|
char *options, *tmp_options;
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
char *p;
|
char *p;
|
||||||
int option = 0;
|
int option = 0;
|
||||||
@ -102,9 +102,12 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
|||||||
if (!opts)
|
if (!opts)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
options = kstrdup(opts, GFP_KERNEL);
|
tmp_options = kstrdup(opts, GFP_KERNEL);
|
||||||
if (!options)
|
if (!tmp_options) {
|
||||||
|
ret = -ENOMEM;
|
||||||
goto fail_option_alloc;
|
goto fail_option_alloc;
|
||||||
|
}
|
||||||
|
options = tmp_options;
|
||||||
|
|
||||||
while ((p = strsep(&options, ",")) != NULL) {
|
while ((p = strsep(&options, ",")) != NULL) {
|
||||||
int token;
|
int token;
|
||||||
@ -159,8 +162,12 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
|||||||
break;
|
break;
|
||||||
case Opt_cache:
|
case Opt_cache:
|
||||||
s = match_strdup(&args[0]);
|
s = match_strdup(&args[0]);
|
||||||
if (!s)
|
if (!s) {
|
||||||
goto fail_option_alloc;
|
ret = -ENOMEM;
|
||||||
|
P9_DPRINTK(P9_DEBUG_ERROR,
|
||||||
|
"problem allocating copy of cache arg\n");
|
||||||
|
goto free_and_return;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(s, "loose") == 0)
|
if (strcmp(s, "loose") == 0)
|
||||||
v9ses->cache = CACHE_LOOSE;
|
v9ses->cache = CACHE_LOOSE;
|
||||||
@ -173,8 +180,12 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
|||||||
|
|
||||||
case Opt_access:
|
case Opt_access:
|
||||||
s = match_strdup(&args[0]);
|
s = match_strdup(&args[0]);
|
||||||
if (!s)
|
if (!s) {
|
||||||
goto fail_option_alloc;
|
ret = -ENOMEM;
|
||||||
|
P9_DPRINTK(P9_DEBUG_ERROR,
|
||||||
|
"problem allocating copy of access arg\n");
|
||||||
|
goto free_and_return;
|
||||||
|
}
|
||||||
|
|
||||||
v9ses->flags &= ~V9FS_ACCESS_MASK;
|
v9ses->flags &= ~V9FS_ACCESS_MASK;
|
||||||
if (strcmp(s, "user") == 0)
|
if (strcmp(s, "user") == 0)
|
||||||
@ -194,13 +205,11 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kfree(options);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
|
free_and_return:
|
||||||
|
kfree(tmp_options);
|
||||||
fail_option_alloc:
|
fail_option_alloc:
|
||||||
P9_DPRINTK(P9_DEBUG_ERROR,
|
return ret;
|
||||||
"failed to allocate copy of option argument\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,3 +60,4 @@ void v9fs_dentry_release(struct dentry *);
|
|||||||
int v9fs_uflags2omode(int uflags, int extended);
|
int v9fs_uflags2omode(int uflags, int extended);
|
||||||
|
|
||||||
ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
|
ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
|
||||||
|
void v9fs_blank_wstat(struct p9_wstat *wstat);
|
||||||
|
@ -257,6 +257,23 @@ v9fs_file_write(struct file *filp, const char __user * data,
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int v9fs_file_fsync(struct file *filp, struct dentry *dentry,
|
||||||
|
int datasync)
|
||||||
|
{
|
||||||
|
struct p9_fid *fid;
|
||||||
|
struct p9_wstat wstat;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
P9_DPRINTK(P9_DEBUG_VFS, "filp %p dentry %p datasync %x\n", filp,
|
||||||
|
dentry, datasync);
|
||||||
|
|
||||||
|
fid = filp->private_data;
|
||||||
|
v9fs_blank_wstat(&wstat);
|
||||||
|
|
||||||
|
retval = p9_client_wstat(fid, &wstat);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct file_operations v9fs_cached_file_operations = {
|
static const struct file_operations v9fs_cached_file_operations = {
|
||||||
.llseek = generic_file_llseek,
|
.llseek = generic_file_llseek,
|
||||||
.read = do_sync_read,
|
.read = do_sync_read,
|
||||||
@ -266,6 +283,7 @@ static const struct file_operations v9fs_cached_file_operations = {
|
|||||||
.release = v9fs_dir_release,
|
.release = v9fs_dir_release,
|
||||||
.lock = v9fs_file_lock,
|
.lock = v9fs_file_lock,
|
||||||
.mmap = generic_file_readonly_mmap,
|
.mmap = generic_file_readonly_mmap,
|
||||||
|
.fsync = v9fs_file_fsync,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct file_operations v9fs_file_operations = {
|
const struct file_operations v9fs_file_operations = {
|
||||||
@ -276,4 +294,5 @@ const struct file_operations v9fs_file_operations = {
|
|||||||
.release = v9fs_dir_release,
|
.release = v9fs_dir_release,
|
||||||
.lock = v9fs_file_lock,
|
.lock = v9fs_file_lock,
|
||||||
.mmap = generic_file_readonly_mmap,
|
.mmap = generic_file_readonly_mmap,
|
||||||
|
.fsync = v9fs_file_fsync,
|
||||||
};
|
};
|
||||||
|
@ -176,7 +176,7 @@ int v9fs_uflags2omode(int uflags, int extended)
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
void
|
||||||
v9fs_blank_wstat(struct p9_wstat *wstat)
|
v9fs_blank_wstat(struct p9_wstat *wstat)
|
||||||
{
|
{
|
||||||
wstat->type = ~0;
|
wstat->type = ~0;
|
||||||
|
@ -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);
|
tmp_options = kstrdup(opts, GFP_KERNEL);
|
||||||
if (!options) {
|
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:
|
close_trans:
|
||||||
p9_client_destroy(clnt);
|
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;
|
||||||
|
@ -714,7 +714,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
|
|||||||
char *p;
|
char *p;
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
int option;
|
int option;
|
||||||
char *options;
|
char *options, *tmp_options;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
opts->port = P9_PORT;
|
opts->port = P9_PORT;
|
||||||
@ -724,12 +724,13 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
|
|||||||
if (!params)
|
if (!params)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
options = kstrdup(params, GFP_KERNEL);
|
tmp_options = kstrdup(params, GFP_KERNEL);
|
||||||
if (!options) {
|
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;
|
||||||
@ -760,7 +761,8 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kfree(options);
|
|
||||||
|
kfree(tmp_options);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
|
|||||||
char *p;
|
char *p;
|
||||||
substring_t args[MAX_OPT_ARGS];
|
substring_t args[MAX_OPT_ARGS];
|
||||||
int option;
|
int option;
|
||||||
char *options;
|
char *options, *tmp_options;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
opts->port = P9_PORT;
|
opts->port = P9_PORT;
|
||||||
@ -177,12 +177,13 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
|
|||||||
if (!params)
|
if (!params)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
options = kstrdup(params, GFP_KERNEL);
|
tmp_options = kstrdup(params, GFP_KERNEL);
|
||||||
if (!options) {
|
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;
|
||||||
@ -216,7 +217,7 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts)
|
|||||||
}
|
}
|
||||||
/* RQ must be at least as large as the SQ */
|
/* RQ must be at least as large as the SQ */
|
||||||
opts->rq_depth = max(opts->rq_depth, opts->sq_depth);
|
opts->rq_depth = max(opts->rq_depth, opts->sq_depth);
|
||||||
kfree(options);
|
kfree(tmp_options);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,8 @@ static void p9_virtio_close(struct p9_client *client)
|
|||||||
struct virtio_chan *chan = client->trans;
|
struct virtio_chan *chan = client->trans;
|
||||||
|
|
||||||
mutex_lock(&virtio_9p_lock);
|
mutex_lock(&virtio_9p_lock);
|
||||||
chan->inuse = false;
|
if (chan)
|
||||||
|
chan->inuse = false;
|
||||||
mutex_unlock(&virtio_9p_lock);
|
mutex_unlock(&virtio_9p_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,6 +312,7 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
client->trans = (void *)chan;
|
client->trans = (void *)chan;
|
||||||
|
client->status = Connected;
|
||||||
chan->client = client;
|
chan->client = client;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user