diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-04-16 16:22:51 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:26 -0400 |
commit | eb872f0c8e5c9801da05d5c2a6e402af8e27160e (patch) | |
tree | b9fb68d0ff9eb920471be0e292766532f250a247 /fs | |
parent | 39967ddf19ff98b6e0d7b43fe60bcbf2c254c478 (diff) |
NFS: Reduce the stack footprint of nfs_proc_create
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/proc.c | 118 |
1 files changed, 66 insertions, 52 deletions
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 0288be80444f..aa61f2c66068 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -224,35 +224,60 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page, | |||
224 | return status; | 224 | return status; |
225 | } | 225 | } |
226 | 226 | ||
227 | struct nfs_createdata { | ||
228 | struct nfs_createargs arg; | ||
229 | struct nfs_diropok res; | ||
230 | struct nfs_fh fhandle; | ||
231 | struct nfs_fattr fattr; | ||
232 | }; | ||
233 | |||
234 | static struct nfs_createdata *nfs_alloc_createdata(struct inode *dir, | ||
235 | struct dentry *dentry, struct iattr *sattr) | ||
236 | { | ||
237 | struct nfs_createdata *data; | ||
238 | |||
239 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
240 | |||
241 | if (data != NULL) { | ||
242 | data->arg.fh = NFS_FH(dir); | ||
243 | data->arg.name = dentry->d_name.name; | ||
244 | data->arg.len = dentry->d_name.len; | ||
245 | data->arg.sattr = sattr; | ||
246 | nfs_fattr_init(&data->fattr); | ||
247 | data->fhandle.size = 0; | ||
248 | data->res.fh = &data->fhandle; | ||
249 | data->res.fattr = &data->fattr; | ||
250 | } | ||
251 | return data; | ||
252 | }; | ||
253 | |||
254 | static void nfs_free_createdata(const struct nfs_createdata *data) | ||
255 | { | ||
256 | kfree(data); | ||
257 | } | ||
258 | |||
227 | static int | 259 | static int |
228 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 260 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
229 | int flags, struct nameidata *nd) | 261 | int flags, struct nameidata *nd) |
230 | { | 262 | { |
231 | struct nfs_fh fhandle; | 263 | struct nfs_createdata *data; |
232 | struct nfs_fattr fattr; | ||
233 | struct nfs_createargs arg = { | ||
234 | .fh = NFS_FH(dir), | ||
235 | .name = dentry->d_name.name, | ||
236 | .len = dentry->d_name.len, | ||
237 | .sattr = sattr | ||
238 | }; | ||
239 | struct nfs_diropok res = { | ||
240 | .fh = &fhandle, | ||
241 | .fattr = &fattr | ||
242 | }; | ||
243 | struct rpc_message msg = { | 264 | struct rpc_message msg = { |
244 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], | 265 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], |
245 | .rpc_argp = &arg, | ||
246 | .rpc_resp = &res, | ||
247 | }; | 266 | }; |
248 | int status; | 267 | int status = -ENOMEM; |
249 | 268 | ||
250 | nfs_fattr_init(&fattr); | ||
251 | dprintk("NFS call create %s\n", dentry->d_name.name); | 269 | dprintk("NFS call create %s\n", dentry->d_name.name); |
270 | data = nfs_alloc_createdata(dir, dentry, sattr); | ||
271 | if (data == NULL) | ||
272 | goto out; | ||
273 | msg.rpc_argp = &data->arg; | ||
274 | msg.rpc_resp = &data->res; | ||
252 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 275 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
253 | nfs_mark_for_revalidate(dir); | 276 | nfs_mark_for_revalidate(dir); |
254 | if (status == 0) | 277 | if (status == 0) |
255 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 278 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
279 | nfs_free_createdata(data); | ||
280 | out: | ||
256 | dprintk("NFS reply create: %d\n", status); | 281 | dprintk("NFS reply create: %d\n", status); |
257 | return status; | 282 | return status; |
258 | } | 283 | } |
@@ -264,24 +289,12 @@ static int | |||
264 | nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 289 | nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
265 | dev_t rdev) | 290 | dev_t rdev) |
266 | { | 291 | { |
267 | struct nfs_fh fhandle; | 292 | struct nfs_createdata *data; |
268 | struct nfs_fattr fattr; | ||
269 | struct nfs_createargs arg = { | ||
270 | .fh = NFS_FH(dir), | ||
271 | .name = dentry->d_name.name, | ||
272 | .len = dentry->d_name.len, | ||
273 | .sattr = sattr | ||
274 | }; | ||
275 | struct nfs_diropok res = { | ||
276 | .fh = &fhandle, | ||
277 | .fattr = &fattr | ||
278 | }; | ||
279 | struct rpc_message msg = { | 293 | struct rpc_message msg = { |
280 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], | 294 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], |
281 | .rpc_argp = &arg, | ||
282 | .rpc_resp = &res, | ||
283 | }; | 295 | }; |
284 | int status, mode; | 296 | umode_t mode; |
297 | int status = -ENOMEM; | ||
285 | 298 | ||
286 | dprintk("NFS call mknod %s\n", dentry->d_name.name); | 299 | dprintk("NFS call mknod %s\n", dentry->d_name.name); |
287 | 300 | ||
@@ -294,17 +307,24 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
294 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ | 307 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ |
295 | } | 308 | } |
296 | 309 | ||
297 | nfs_fattr_init(&fattr); | 310 | data = nfs_alloc_createdata(dir, dentry, sattr); |
311 | if (data == NULL) | ||
312 | goto out; | ||
313 | msg.rpc_argp = &data->arg; | ||
314 | msg.rpc_resp = &data->res; | ||
315 | |||
298 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 316 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
299 | nfs_mark_for_revalidate(dir); | 317 | nfs_mark_for_revalidate(dir); |
300 | 318 | ||
301 | if (status == -EINVAL && S_ISFIFO(mode)) { | 319 | if (status == -EINVAL && S_ISFIFO(mode)) { |
302 | sattr->ia_mode = mode; | 320 | sattr->ia_mode = mode; |
303 | nfs_fattr_init(&fattr); | 321 | nfs_fattr_init(data->res.fattr); |
304 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 322 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
305 | } | 323 | } |
306 | if (status == 0) | 324 | if (status == 0) |
307 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 325 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
326 | nfs_free_createdata(data); | ||
327 | out: | ||
308 | dprintk("NFS reply mknod: %d\n", status); | 328 | dprintk("NFS reply mknod: %d\n", status); |
309 | return status; | 329 | return status; |
310 | } | 330 | } |
@@ -440,31 +460,25 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
440 | static int | 460 | static int |
441 | nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | 461 | nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) |
442 | { | 462 | { |
443 | struct nfs_fh fhandle; | 463 | struct nfs_createdata *data; |
444 | struct nfs_fattr fattr; | ||
445 | struct nfs_createargs arg = { | ||
446 | .fh = NFS_FH(dir), | ||
447 | .name = dentry->d_name.name, | ||
448 | .len = dentry->d_name.len, | ||
449 | .sattr = sattr | ||
450 | }; | ||
451 | struct nfs_diropok res = { | ||
452 | .fh = &fhandle, | ||
453 | .fattr = &fattr | ||
454 | }; | ||
455 | struct rpc_message msg = { | 464 | struct rpc_message msg = { |
456 | .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], | 465 | .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], |
457 | .rpc_argp = &arg, | ||
458 | .rpc_resp = &res, | ||
459 | }; | 466 | }; |
460 | int status; | 467 | int status = -ENOMEM; |
461 | 468 | ||
462 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); | 469 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); |
463 | nfs_fattr_init(&fattr); | 470 | data = nfs_alloc_createdata(dir, dentry, sattr); |
471 | if (data == NULL) | ||
472 | goto out; | ||
473 | msg.rpc_argp = &data->arg; | ||
474 | msg.rpc_resp = &data->res; | ||
475 | |||
464 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 476 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
465 | nfs_mark_for_revalidate(dir); | 477 | nfs_mark_for_revalidate(dir); |
466 | if (status == 0) | 478 | if (status == 0) |
467 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 479 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
480 | nfs_free_createdata(data); | ||
481 | out: | ||
468 | dprintk("NFS reply mkdir: %d\n", status); | 482 | dprintk("NFS reply mkdir: %d\n", status); |
469 | return status; | 483 | return status; |
470 | } | 484 | } |