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