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