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

+91 -40
+21 -12
fs/9p/v9fs.c
··· 84 85 static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) 86 { 87 - char *options; 88 substring_t args[MAX_OPT_ARGS]; 89 char *p; 90 int option = 0; ··· 102 if (!opts) 103 return 0; 104 105 - options = kstrdup(opts, GFP_KERNEL); 106 - if (!options) 107 goto fail_option_alloc; 108 109 while ((p = strsep(&options, ",")) != NULL) { 110 int token; ··· 162 break; 163 case Opt_cache: 164 s = match_strdup(&args[0]); 165 - if (!s) 166 - goto fail_option_alloc; 167 168 if (strcmp(s, "loose") == 0) 169 v9ses->cache = CACHE_LOOSE; ··· 180 181 case Opt_access: 182 s = match_strdup(&args[0]); 183 - if (!s) 184 - goto fail_option_alloc; 185 186 v9ses->flags &= ~V9FS_ACCESS_MASK; 187 if (strcmp(s, "user") == 0) ··· 205 continue; 206 } 207 } 208 - kfree(options); 209 - return ret; 210 211 fail_option_alloc: 212 - P9_DPRINTK(P9_DEBUG_ERROR, 213 - "failed to allocate copy of option argument\n"); 214 - return -ENOMEM; 215 } 216 217 /**
··· 84 85 static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) 86 { 87 + char *options, *tmp_options; 88 substring_t args[MAX_OPT_ARGS]; 89 char *p; 90 int option = 0; ··· 102 if (!opts) 103 return 0; 104 105 + tmp_options = kstrdup(opts, GFP_KERNEL); 106 + if (!tmp_options) { 107 + ret = -ENOMEM; 108 goto fail_option_alloc; 109 + } 110 + options = tmp_options; 111 112 while ((p = strsep(&options, ",")) != NULL) { 113 int token; ··· 159 break; 160 case Opt_cache: 161 s = match_strdup(&args[0]); 162 + if (!s) { 163 + ret = -ENOMEM; 164 + P9_DPRINTK(P9_DEBUG_ERROR, 165 + "problem allocating copy of cache arg\n"); 166 + goto free_and_return; 167 + } 168 169 if (strcmp(s, "loose") == 0) 170 v9ses->cache = CACHE_LOOSE; ··· 173 174 case Opt_access: 175 s = match_strdup(&args[0]); 176 + if (!s) { 177 + ret = -ENOMEM; 178 + P9_DPRINTK(P9_DEBUG_ERROR, 179 + "problem allocating copy of access arg\n"); 180 + goto free_and_return; 181 + } 182 183 v9ses->flags &= ~V9FS_ACCESS_MASK; 184 if (strcmp(s, "user") == 0) ··· 194 continue; 195 } 196 } 197 198 + free_and_return: 199 + kfree(tmp_options); 200 fail_option_alloc: 201 + return ret; 202 } 203 204 /**
+1
fs/9p/v9fs_vfs.h
··· 60 int v9fs_uflags2omode(int uflags, int extended); 61 62 ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
··· 60 int v9fs_uflags2omode(int uflags, int extended); 61 62 ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); 63 + void v9fs_blank_wstat(struct p9_wstat *wstat);
+19
fs/9p/vfs_file.c
··· 257 return total; 258 } 259 260 static const struct file_operations v9fs_cached_file_operations = { 261 .llseek = generic_file_llseek, 262 .read = do_sync_read, ··· 283 .release = v9fs_dir_release, 284 .lock = v9fs_file_lock, 285 .mmap = generic_file_readonly_mmap, 286 }; 287 288 const struct file_operations v9fs_file_operations = { ··· 294 .release = v9fs_dir_release, 295 .lock = v9fs_file_lock, 296 .mmap = generic_file_readonly_mmap, 297 };
··· 257 return total; 258 } 259 260 + static int v9fs_file_fsync(struct file *filp, struct dentry *dentry, 261 + int datasync) 262 + { 263 + struct p9_fid *fid; 264 + struct p9_wstat wstat; 265 + int retval; 266 + 267 + P9_DPRINTK(P9_DEBUG_VFS, "filp %p dentry %p datasync %x\n", filp, 268 + dentry, datasync); 269 + 270 + fid = filp->private_data; 271 + v9fs_blank_wstat(&wstat); 272 + 273 + retval = p9_client_wstat(fid, &wstat); 274 + return retval; 275 + } 276 + 277 static const struct file_operations v9fs_cached_file_operations = { 278 .llseek = generic_file_llseek, 279 .read = do_sync_read, ··· 266 .release = v9fs_dir_release, 267 .lock = v9fs_file_lock, 268 .mmap = generic_file_readonly_mmap, 269 + .fsync = v9fs_file_fsync, 270 }; 271 272 const struct file_operations v9fs_file_operations = { ··· 276 .release = v9fs_dir_release, 277 .lock = v9fs_file_lock, 278 .mmap = generic_file_readonly_mmap, 279 + .fsync = v9fs_file_fsync, 280 };
+1 -1
fs/9p/vfs_inode.c
··· 176 * 177 */ 178 179 - static void 180 v9fs_blank_wstat(struct p9_wstat *wstat) 181 { 182 wstat->type = ~0;
··· 176 * 177 */ 178 179 + void 180 v9fs_blank_wstat(struct p9_wstat *wstat) 181 { 182 wstat->type = ~0;
+35 -18
net/9p/client.c
··· 69 70 static int parse_opts(char *opts, struct p9_client *clnt) 71 { 72 - char *options; 73 char *p; 74 substring_t args[MAX_OPT_ARGS]; 75 int option; ··· 81 if (!opts) 82 return 0; 83 84 - options = kstrdup(opts, GFP_KERNEL); 85 - if (!options) { 86 P9_DPRINTK(P9_DEBUG_ERROR, 87 "failed to allocate copy of option string\n"); 88 return -ENOMEM; 89 } 90 91 while ((p = strsep(&options, ",")) != NULL) { 92 int token; ··· 109 break; 110 case Opt_trans: 111 clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); 112 break; 113 case Opt_legacy: 114 clnt->dotu = 0; ··· 125 } 126 } 127 128 - kfree(options); 129 return ret; 130 } 131 ··· 676 clnt->trans = NULL; 677 spin_lock_init(&clnt->lock); 678 INIT_LIST_HEAD(&clnt->fidlist); 679 - clnt->fidpool = p9_idpool_create(); 680 - if (IS_ERR(clnt->fidpool)) { 681 - err = PTR_ERR(clnt->fidpool); 682 - clnt->fidpool = NULL; 683 - goto error; 684 - } 685 686 p9_tag_init(clnt); 687 688 err = parse_opts(options, clnt); 689 if (err < 0) 690 - goto error; 691 692 if (!clnt->trans_mod) 693 clnt->trans_mod = v9fs_get_default_trans(); ··· 690 err = -EPROTONOSUPPORT; 691 P9_DPRINTK(P9_DEBUG_ERROR, 692 "No transport defined or default transport\n"); 693 - goto error; 694 } 695 696 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", ··· 705 706 err = clnt->trans_mod->create(clnt, dev_name, options); 707 if (err) 708 - goto error; 709 710 if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) 711 clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; 712 713 err = p9_client_version(clnt); 714 if (err) 715 - goto error; 716 717 return clnt; 718 719 - error: 720 - p9_client_destroy(clnt); 721 return ERR_PTR(err); 722 } 723 EXPORT_SYMBOL(p9_client_create); ··· 1230 { 1231 int ret; 1232 1233 /* size[2] type[2] dev[4] qid[13] */ 1234 /* mode[4] atime[4] mtime[4] length[8]*/ 1235 /* name[s] uid[s] gid[s] muid[s] */ 1236 - ret = 2+2+4+13+4+4+4+8+2+2+2+2; 1237 1238 if (wst->name) 1239 ret += strlen(wst->name); ··· 1275 wst->name, wst->uid, wst->gid, wst->muid, wst->extension, 1276 wst->n_uid, wst->n_gid, wst->n_muid); 1277 1278 - req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst); 1279 if (IS_ERR(req)) { 1280 err = PTR_ERR(req); 1281 goto error;
··· 69 70 static int parse_opts(char *opts, struct p9_client *clnt) 71 { 72 + char *options, *tmp_options; 73 char *p; 74 substring_t args[MAX_OPT_ARGS]; 75 int option; ··· 81 if (!opts) 82 return 0; 83 84 + tmp_options = kstrdup(opts, GFP_KERNEL); 85 + if (!tmp_options) { 86 P9_DPRINTK(P9_DEBUG_ERROR, 87 "failed to allocate copy of option string\n"); 88 return -ENOMEM; 89 } 90 + options = tmp_options; 91 92 while ((p = strsep(&options, ",")) != NULL) { 93 int token; ··· 108 break; 109 case Opt_trans: 110 clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); 111 + if(clnt->trans_mod == NULL) { 112 + P9_DPRINTK(P9_DEBUG_ERROR, 113 + "Could not find request transport: %s\n", 114 + (char *) &args[0]); 115 + ret = -EINVAL; 116 + goto free_and_return; 117 + } 118 break; 119 case Opt_legacy: 120 clnt->dotu = 0; ··· 117 } 118 } 119 120 + free_and_return: 121 + kfree(tmp_options); 122 return ret; 123 } 124 ··· 667 clnt->trans = NULL; 668 spin_lock_init(&clnt->lock); 669 INIT_LIST_HEAD(&clnt->fidlist); 670 671 p9_tag_init(clnt); 672 673 err = parse_opts(options, clnt); 674 if (err < 0) 675 + goto free_client; 676 677 if (!clnt->trans_mod) 678 clnt->trans_mod = v9fs_get_default_trans(); ··· 687 err = -EPROTONOSUPPORT; 688 P9_DPRINTK(P9_DEBUG_ERROR, 689 "No transport defined or default transport\n"); 690 + goto free_client; 691 + } 692 + 693 + clnt->fidpool = p9_idpool_create(); 694 + if (IS_ERR(clnt->fidpool)) { 695 + err = PTR_ERR(clnt->fidpool); 696 + clnt->fidpool = NULL; 697 + goto put_trans; 698 } 699 700 P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", ··· 695 696 err = clnt->trans_mod->create(clnt, dev_name, options); 697 if (err) 698 + goto destroy_fidpool; 699 700 if ((clnt->msize+P9_IOHDRSZ) > clnt->trans_mod->maxsize) 701 clnt->msize = clnt->trans_mod->maxsize-P9_IOHDRSZ; 702 703 err = p9_client_version(clnt); 704 if (err) 705 + goto close_trans; 706 707 return clnt; 708 709 + close_trans: 710 + clnt->trans_mod->close(clnt); 711 + destroy_fidpool: 712 + p9_idpool_destroy(clnt->fidpool); 713 + put_trans: 714 + v9fs_put_trans(clnt->trans_mod); 715 + free_client: 716 + kfree(clnt); 717 return ERR_PTR(err); 718 } 719 EXPORT_SYMBOL(p9_client_create); ··· 1214 { 1215 int ret; 1216 1217 + /* NOTE: size shouldn't include its own length */ 1218 /* size[2] type[2] dev[4] qid[13] */ 1219 /* mode[4] atime[4] mtime[4] length[8]*/ 1220 /* name[s] uid[s] gid[s] muid[s] */ 1221 + ret = 2+4+13+4+4+4+8+2+2+2+2; 1222 1223 if (wst->name) 1224 ret += strlen(wst->name); ··· 1258 wst->name, wst->uid, wst->gid, wst->muid, wst->extension, 1259 wst->n_uid, wst->n_gid, wst->n_muid); 1260 1261 + req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst); 1262 if (IS_ERR(req)) { 1263 err = PTR_ERR(req); 1264 goto error;
+6 -4
net/9p/trans_fd.c
··· 714 char *p; 715 substring_t args[MAX_OPT_ARGS]; 716 int option; 717 - char *options; 718 int ret; 719 720 opts->port = P9_PORT; ··· 724 if (!params) 725 return 0; 726 727 - options = kstrdup(params, GFP_KERNEL); 728 - if (!options) { 729 P9_DPRINTK(P9_DEBUG_ERROR, 730 "failed to allocate copy of option string\n"); 731 return -ENOMEM; 732 } 733 734 while ((p = strsep(&options, ",")) != NULL) { 735 int token; ··· 761 continue; 762 } 763 } 764 - kfree(options); 765 return 0; 766 } 767
··· 714 char *p; 715 substring_t args[MAX_OPT_ARGS]; 716 int option; 717 + char *options, *tmp_options; 718 int ret; 719 720 opts->port = P9_PORT; ··· 724 if (!params) 725 return 0; 726 727 + tmp_options = kstrdup(params, GFP_KERNEL); 728 + if (!tmp_options) { 729 P9_DPRINTK(P9_DEBUG_ERROR, 730 "failed to allocate copy of option string\n"); 731 return -ENOMEM; 732 } 733 + options = tmp_options; 734 735 while ((p = strsep(&options, ",")) != NULL) { 736 int token; ··· 760 continue; 761 } 762 } 763 + 764 + kfree(tmp_options); 765 return 0; 766 } 767
+5 -4
net/9p/trans_rdma.c
··· 166 char *p; 167 substring_t args[MAX_OPT_ARGS]; 168 int option; 169 - char *options; 170 int ret; 171 172 opts->port = P9_PORT; ··· 177 if (!params) 178 return 0; 179 180 - options = kstrdup(params, GFP_KERNEL); 181 - if (!options) { 182 P9_DPRINTK(P9_DEBUG_ERROR, 183 "failed to allocate copy of option string\n"); 184 return -ENOMEM; 185 } 186 187 while ((p = strsep(&options, ",")) != NULL) { 188 int token; ··· 217 } 218 /* RQ must be at least as large as the SQ */ 219 opts->rq_depth = max(opts->rq_depth, opts->sq_depth); 220 - kfree(options); 221 return 0; 222 } 223
··· 166 char *p; 167 substring_t args[MAX_OPT_ARGS]; 168 int option; 169 + char *options, *tmp_options; 170 int ret; 171 172 opts->port = P9_PORT; ··· 177 if (!params) 178 return 0; 179 180 + tmp_options = kstrdup(params, GFP_KERNEL); 181 + if (!tmp_options) { 182 P9_DPRINTK(P9_DEBUG_ERROR, 183 "failed to allocate copy of option string\n"); 184 return -ENOMEM; 185 } 186 + options = tmp_options; 187 188 while ((p = strsep(&options, ",")) != NULL) { 189 int token; ··· 216 } 217 /* RQ must be at least as large as the SQ */ 218 opts->rq_depth = max(opts->rq_depth, opts->sq_depth); 219 + kfree(tmp_options); 220 return 0; 221 } 222
+3 -1
net/9p/trans_virtio.c
··· 102 struct virtio_chan *chan = client->trans; 103 104 mutex_lock(&virtio_9p_lock); 105 - chan->inuse = false; 106 mutex_unlock(&virtio_9p_lock); 107 } 108 ··· 312 } 313 314 client->trans = (void *)chan; 315 chan->client = client; 316 317 return 0;
··· 102 struct virtio_chan *chan = client->trans; 103 104 mutex_lock(&virtio_9p_lock); 105 + if (chan) 106 + chan->inuse = false; 107 mutex_unlock(&virtio_9p_lock); 108 } 109 ··· 311 } 312 313 client->trans = (void *)chan; 314 + client->status = Connected; 315 chan->client = client; 316 317 return 0;