diff options
author | Nathan Scott <nathans@sgi.com> | 2006-03-13 21:33:36 -0500 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2006-03-13 21:33:36 -0500 |
commit | 220b5284139be6ecbc39b353fd76f0923eccc3d6 (patch) | |
tree | 86ab8c671631a109690d6589a19d9774d8bed18f /fs/xfs/linux-2.6/xfs_iops.c | |
parent | 9b94c2eddf407ad8faa5672ffa691e2076167564 (diff) |
[XFS] Dynamically allocate vattr in places it makes sense to do so, to
reduce stack use. Also re-use vattr in some places so that multiple
copies are not held on-stack.
SGI-PV: 947312
SGI-Modid: xfs-linux-melb:xfs-kern:25369a
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 180 |
1 files changed, 105 insertions, 75 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index d7f6f2d8ac8e..b1219195c6e2 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -198,22 +198,22 @@ xfs_ichgtime_fast( | |||
198 | * Pull the link count and size up from the xfs inode to the linux inode | 198 | * Pull the link count and size up from the xfs inode to the linux inode |
199 | */ | 199 | */ |
200 | STATIC void | 200 | STATIC void |
201 | validate_fields( | 201 | __linvfs_validate_fields( |
202 | struct inode *ip) | 202 | struct inode *ip, |
203 | struct vattr *vattr) | ||
203 | { | 204 | { |
204 | vnode_t *vp = LINVFS_GET_VP(ip); | 205 | vnode_t *vp = LINVFS_GET_VP(ip); |
205 | vattr_t va; | ||
206 | int error; | 206 | int error; |
207 | 207 | ||
208 | va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; | 208 | vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; |
209 | VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error); | 209 | VOP_GETATTR(vp, vattr, ATTR_LAZY, NULL, error); |
210 | if (likely(!error)) { | 210 | if (likely(!error)) { |
211 | ip->i_nlink = va.va_nlink; | 211 | ip->i_nlink = vattr->va_nlink; |
212 | ip->i_blocks = va.va_nblocks; | 212 | ip->i_blocks = vattr->va_nblocks; |
213 | 213 | ||
214 | /* we're under i_mutex so i_size can't change under us */ | 214 | /* we're under i_sem so i_size can't change under us */ |
215 | if (i_size_read(ip) != va.va_size) | 215 | if (i_size_read(ip) != vattr->va_size) |
216 | i_size_write(ip, va.va_size); | 216 | i_size_write(ip, vattr->va_size); |
217 | } | 217 | } |
218 | } | 218 | } |
219 | 219 | ||
@@ -224,7 +224,7 @@ validate_fields( | |||
224 | * inode, of course, such that log replay can't cause these to be lost). | 224 | * inode, of course, such that log replay can't cause these to be lost). |
225 | */ | 225 | */ |
226 | STATIC int | 226 | STATIC int |
227 | linvfs_init_security( | 227 | __linvfs_init_security( |
228 | struct vnode *vp, | 228 | struct vnode *vp, |
229 | struct inode *dir) | 229 | struct inode *dir) |
230 | { | 230 | { |
@@ -257,23 +257,23 @@ linvfs_init_security( | |||
257 | * XXX(hch): nfsd is broken, better fix it instead. | 257 | * XXX(hch): nfsd is broken, better fix it instead. |
258 | */ | 258 | */ |
259 | STATIC inline int | 259 | STATIC inline int |
260 | has_fs_struct(struct task_struct *task) | 260 | __linvfs_has_fs_struct(struct task_struct *task) |
261 | { | 261 | { |
262 | return (task->fs != init_task.fs); | 262 | return (task->fs != init_task.fs); |
263 | } | 263 | } |
264 | 264 | ||
265 | STATIC inline void | 265 | STATIC inline void |
266 | cleanup_inode( | 266 | __linvfs_cleanup_inode( |
267 | vnode_t *dvp, | 267 | vnode_t *dvp, |
268 | vnode_t *vp, | 268 | vnode_t *vp, |
269 | struct dentry *dentry, | 269 | struct dentry *dentry, |
270 | int mode) | 270 | int mode) |
271 | { | 271 | { |
272 | struct dentry teardown = {}; | 272 | struct dentry teardown = {}; |
273 | int err2; | 273 | int error; |
274 | 274 | ||
275 | /* Oh, the horror. | 275 | /* Oh, the horror. |
276 | * If we can't add the ACL or we fail in | 276 | * If we can't add the ACL or we fail in |
277 | * linvfs_init_security we must back out. | 277 | * linvfs_init_security we must back out. |
278 | * ENOSPC can hit here, among other things. | 278 | * ENOSPC can hit here, among other things. |
279 | */ | 279 | */ |
@@ -281,9 +281,9 @@ cleanup_inode( | |||
281 | teardown.d_name = dentry->d_name; | 281 | teardown.d_name = dentry->d_name; |
282 | 282 | ||
283 | if (S_ISDIR(mode)) | 283 | if (S_ISDIR(mode)) |
284 | VOP_RMDIR(dvp, &teardown, NULL, err2); | 284 | VOP_RMDIR(dvp, &teardown, NULL, error); |
285 | else | 285 | else |
286 | VOP_REMOVE(dvp, &teardown, NULL, err2); | 286 | VOP_REMOVE(dvp, &teardown, NULL, error); |
287 | VN_RELE(vp); | 287 | VN_RELE(vp); |
288 | } | 288 | } |
289 | 289 | ||
@@ -295,7 +295,7 @@ linvfs_mknod( | |||
295 | dev_t rdev) | 295 | dev_t rdev) |
296 | { | 296 | { |
297 | struct inode *ip; | 297 | struct inode *ip; |
298 | vattr_t va; | 298 | vattr_t *vattr; |
299 | vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); | 299 | vnode_t *vp = NULL, *dvp = LINVFS_GET_VP(dir); |
300 | xfs_acl_t *default_acl = NULL; | 300 | xfs_acl_t *default_acl = NULL; |
301 | attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; | 301 | attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; |
@@ -305,70 +305,76 @@ linvfs_mknod( | |||
305 | * Irix uses Missed'em'V split, but doesn't want to see | 305 | * Irix uses Missed'em'V split, but doesn't want to see |
306 | * the upper 5 bits of (14bit) major. | 306 | * the upper 5 bits of (14bit) major. |
307 | */ | 307 | */ |
308 | if (!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff) | 308 | if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)) |
309 | return -EINVAL; | 309 | return -EINVAL; |
310 | 310 | ||
311 | if (test_default_acl && test_default_acl(dvp)) { | 311 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
312 | if (!_ACL_ALLOC(default_acl)) | 312 | if (unlikely(!vattr)) |
313 | return -ENOMEM; | ||
314 | |||
315 | if (unlikely(test_default_acl && test_default_acl(dvp))) { | ||
316 | if (!_ACL_ALLOC(default_acl)) { | ||
317 | kfree(vattr); | ||
313 | return -ENOMEM; | 318 | return -ENOMEM; |
319 | } | ||
314 | if (!_ACL_GET_DEFAULT(dvp, default_acl)) { | 320 | if (!_ACL_GET_DEFAULT(dvp, default_acl)) { |
315 | _ACL_FREE(default_acl); | 321 | _ACL_FREE(default_acl); |
316 | default_acl = NULL; | 322 | default_acl = NULL; |
317 | } | 323 | } |
318 | } | 324 | } |
319 | 325 | ||
320 | if (IS_POSIXACL(dir) && !default_acl && has_fs_struct(current)) | 326 | if (IS_POSIXACL(dir) && !default_acl && __linvfs_has_fs_struct(current)) |
321 | mode &= ~current->fs->umask; | 327 | mode &= ~current->fs->umask; |
322 | 328 | ||
323 | memset(&va, 0, sizeof(va)); | 329 | memset(vattr, 0, sizeof(*vattr)); |
324 | va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; | 330 | vattr->va_mask = XFS_AT_TYPE|XFS_AT_MODE; |
325 | va.va_mode = mode; | 331 | vattr->va_mode = mode; |
326 | 332 | ||
327 | switch (mode & S_IFMT) { | 333 | switch (mode & S_IFMT) { |
328 | case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: | 334 | case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: |
329 | va.va_rdev = sysv_encode_dev(rdev); | 335 | vattr->va_rdev = sysv_encode_dev(rdev); |
330 | va.va_mask |= XFS_AT_RDEV; | 336 | vattr->va_mask |= XFS_AT_RDEV; |
331 | /*FALLTHROUGH*/ | 337 | /*FALLTHROUGH*/ |
332 | case S_IFREG: | 338 | case S_IFREG: |
333 | VOP_CREATE(dvp, dentry, &va, &vp, NULL, error); | 339 | VOP_CREATE(dvp, dentry, vattr, &vp, NULL, error); |
334 | break; | 340 | break; |
335 | case S_IFDIR: | 341 | case S_IFDIR: |
336 | VOP_MKDIR(dvp, dentry, &va, &vp, NULL, error); | 342 | VOP_MKDIR(dvp, dentry, vattr, &vp, NULL, error); |
337 | break; | 343 | break; |
338 | default: | 344 | default: |
339 | error = EINVAL; | 345 | error = EINVAL; |
340 | break; | 346 | break; |
341 | } | 347 | } |
342 | 348 | ||
343 | if (!error) | 349 | if (unlikely(!error)) { |
344 | { | 350 | error = __linvfs_init_security(vp, dir); |
345 | error = linvfs_init_security(vp, dir); | ||
346 | if (error) | 351 | if (error) |
347 | cleanup_inode(dvp, vp, dentry, mode); | 352 | __linvfs_cleanup_inode(dvp, vp, dentry, mode); |
348 | } | 353 | } |
349 | 354 | ||
350 | if (default_acl) { | 355 | if (unlikely(default_acl)) { |
351 | if (!error) { | 356 | if (!error) { |
352 | error = _ACL_INHERIT(vp, &va, default_acl); | 357 | error = _ACL_INHERIT(vp, vattr, default_acl); |
353 | if (!error) | 358 | if (!error) |
354 | VMODIFY(vp); | 359 | VMODIFY(vp); |
355 | else | 360 | else |
356 | cleanup_inode(dvp, vp, dentry, mode); | 361 | __linvfs_cleanup_inode(dvp, vp, dentry, mode); |
357 | } | 362 | } |
358 | _ACL_FREE(default_acl); | 363 | _ACL_FREE(default_acl); |
359 | } | 364 | } |
360 | 365 | ||
361 | if (!error) { | 366 | if (likely(!error)) { |
362 | ASSERT(vp); | 367 | ASSERT(vp); |
363 | ip = LINVFS_GET_IP(vp); | 368 | ip = LINVFS_GET_IP(vp); |
364 | 369 | ||
365 | if (S_ISCHR(mode) || S_ISBLK(mode)) | 370 | if (S_ISCHR(mode) || S_ISBLK(mode)) |
366 | ip->i_rdev = rdev; | 371 | ip->i_rdev = rdev; |
367 | else if (S_ISDIR(mode)) | 372 | else if (S_ISDIR(mode)) |
368 | validate_fields(ip); | 373 | __linvfs_validate_fields(ip, vattr); |
369 | d_instantiate(dentry, ip); | 374 | d_instantiate(dentry, ip); |
370 | validate_fields(dir); | 375 | __linvfs_validate_fields(dir, vattr); |
371 | } | 376 | } |
377 | kfree(vattr); | ||
372 | return -error; | 378 | return -error; |
373 | } | 379 | } |
374 | 380 | ||
@@ -423,22 +429,28 @@ linvfs_link( | |||
423 | struct inode *ip; /* inode of guy being linked to */ | 429 | struct inode *ip; /* inode of guy being linked to */ |
424 | vnode_t *tdvp; /* target directory for new name/link */ | 430 | vnode_t *tdvp; /* target directory for new name/link */ |
425 | vnode_t *vp; /* vp of name being linked */ | 431 | vnode_t *vp; /* vp of name being linked */ |
432 | vattr_t *vattr; | ||
426 | int error; | 433 | int error; |
427 | 434 | ||
428 | ip = old_dentry->d_inode; /* inode being linked to */ | 435 | ip = old_dentry->d_inode; /* inode being linked to */ |
429 | if (S_ISDIR(ip->i_mode)) | 436 | if (S_ISDIR(ip->i_mode)) |
430 | return -EPERM; | 437 | return -EPERM; |
431 | 438 | ||
439 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); | ||
440 | if (unlikely(!vattr)) | ||
441 | return -ENOMEM; | ||
442 | |||
432 | tdvp = LINVFS_GET_VP(dir); | 443 | tdvp = LINVFS_GET_VP(dir); |
433 | vp = LINVFS_GET_VP(ip); | 444 | vp = LINVFS_GET_VP(ip); |
434 | 445 | ||
435 | VOP_LINK(tdvp, vp, dentry, NULL, error); | 446 | VOP_LINK(tdvp, vp, dentry, NULL, error); |
436 | if (!error) { | 447 | if (likely(!error)) { |
437 | VMODIFY(tdvp); | 448 | VMODIFY(tdvp); |
438 | VN_HOLD(vp); | 449 | VN_HOLD(vp); |
439 | validate_fields(ip); | 450 | __linvfs_validate_fields(ip, vattr); |
440 | d_instantiate(dentry, ip); | 451 | d_instantiate(dentry, ip); |
441 | } | 452 | } |
453 | kfree(vattr); | ||
442 | return -error; | 454 | return -error; |
443 | } | 455 | } |
444 | 456 | ||
@@ -449,17 +461,22 @@ linvfs_unlink( | |||
449 | { | 461 | { |
450 | struct inode *inode; | 462 | struct inode *inode; |
451 | vnode_t *dvp; /* directory containing name to remove */ | 463 | vnode_t *dvp; /* directory containing name to remove */ |
464 | vattr_t *vattr; | ||
452 | int error; | 465 | int error; |
453 | 466 | ||
467 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); | ||
468 | if (unlikely(!vattr)) | ||
469 | return -ENOMEM; | ||
470 | |||
454 | inode = dentry->d_inode; | 471 | inode = dentry->d_inode; |
455 | dvp = LINVFS_GET_VP(dir); | 472 | dvp = LINVFS_GET_VP(dir); |
456 | 473 | ||
457 | VOP_REMOVE(dvp, dentry, NULL, error); | 474 | VOP_REMOVE(dvp, dentry, NULL, error); |
458 | if (!error) { | 475 | if (likely(!error)) { |
459 | validate_fields(dir); /* For size only */ | 476 | __linvfs_validate_fields(dir, vattr); /* size needs update */ |
460 | validate_fields(inode); | 477 | __linvfs_validate_fields(inode, vattr); |
461 | } | 478 | } |
462 | 479 | kfree(vattr); | |
463 | return -error; | 480 | return -error; |
464 | } | 481 | } |
465 | 482 | ||
@@ -470,7 +487,7 @@ linvfs_symlink( | |||
470 | const char *symname) | 487 | const char *symname) |
471 | { | 488 | { |
472 | struct inode *ip; | 489 | struct inode *ip; |
473 | vattr_t va; | 490 | vattr_t *vattr; |
474 | vnode_t *dvp; /* directory containing name of symlink */ | 491 | vnode_t *dvp; /* directory containing name of symlink */ |
475 | vnode_t *cvp; /* used to lookup symlink to put in dentry */ | 492 | vnode_t *cvp; /* used to lookup symlink to put in dentry */ |
476 | int error; | 493 | int error; |
@@ -478,22 +495,27 @@ linvfs_symlink( | |||
478 | dvp = LINVFS_GET_VP(dir); | 495 | dvp = LINVFS_GET_VP(dir); |
479 | cvp = NULL; | 496 | cvp = NULL; |
480 | 497 | ||
481 | memset(&va, 0, sizeof(va)); | 498 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); |
482 | va.va_mode = S_IFLNK | | 499 | if (unlikely(!vattr)) |
500 | return -ENOMEM; | ||
501 | |||
502 | memset(vattr, 0, sizeof(*vattr)); | ||
503 | vattr->va_mode = S_IFLNK | | ||
483 | (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); | 504 | (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); |
484 | va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; | 505 | vattr->va_mask = XFS_AT_TYPE|XFS_AT_MODE; |
485 | 506 | ||
486 | error = 0; | 507 | error = 0; |
487 | VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error); | 508 | VOP_SYMLINK(dvp, dentry, vattr, (char *)symname, &cvp, NULL, error); |
488 | if (likely(!error && cvp)) { | 509 | if (likely(!error && cvp)) { |
489 | error = linvfs_init_security(cvp, dir); | 510 | error = __linvfs_init_security(cvp, dir); |
490 | if (likely(!error)) { | 511 | if (likely(!error)) { |
491 | ip = LINVFS_GET_IP(cvp); | 512 | ip = LINVFS_GET_IP(cvp); |
492 | d_instantiate(dentry, ip); | 513 | d_instantiate(dentry, ip); |
493 | validate_fields(dir); | 514 | __linvfs_validate_fields(dir, vattr); |
494 | validate_fields(ip); | 515 | __linvfs_validate_fields(ip, vattr); |
495 | } | 516 | } |
496 | } | 517 | } |
518 | kfree(vattr); | ||
497 | return -error; | 519 | return -error; |
498 | } | 520 | } |
499 | 521 | ||
@@ -504,13 +526,19 @@ linvfs_rmdir( | |||
504 | { | 526 | { |
505 | struct inode *inode = dentry->d_inode; | 527 | struct inode *inode = dentry->d_inode; |
506 | vnode_t *dvp = LINVFS_GET_VP(dir); | 528 | vnode_t *dvp = LINVFS_GET_VP(dir); |
529 | vattr_t *vattr; | ||
507 | int error; | 530 | int error; |
508 | 531 | ||
532 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); | ||
533 | if (unlikely(!vattr)) | ||
534 | return -ENOMEM; | ||
535 | |||
509 | VOP_RMDIR(dvp, dentry, NULL, error); | 536 | VOP_RMDIR(dvp, dentry, NULL, error); |
510 | if (!error) { | 537 | if (likely(!error)) { |
511 | validate_fields(inode); | 538 | __linvfs_validate_fields(inode, vattr); |
512 | validate_fields(dir); | 539 | __linvfs_validate_fields(dir, vattr); |
513 | } | 540 | } |
541 | kfree(vattr); | ||
514 | return -error; | 542 | return -error; |
515 | } | 543 | } |
516 | 544 | ||
@@ -524,22 +552,26 @@ linvfs_rename( | |||
524 | struct inode *new_inode = ndentry->d_inode; | 552 | struct inode *new_inode = ndentry->d_inode; |
525 | vnode_t *fvp; /* from directory */ | 553 | vnode_t *fvp; /* from directory */ |
526 | vnode_t *tvp; /* target directory */ | 554 | vnode_t *tvp; /* target directory */ |
555 | vattr_t *vattr; | ||
527 | int error; | 556 | int error; |
528 | 557 | ||
558 | vattr = kmalloc(sizeof(*vattr), GFP_KERNEL); | ||
559 | if (unlikely(!vattr)) | ||
560 | return -ENOMEM; | ||
561 | |||
529 | fvp = LINVFS_GET_VP(odir); | 562 | fvp = LINVFS_GET_VP(odir); |
530 | tvp = LINVFS_GET_VP(ndir); | 563 | tvp = LINVFS_GET_VP(ndir); |
531 | 564 | ||
532 | VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); | 565 | VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); |
533 | if (error) | 566 | if (likely(!error)) { |
534 | return -error; | 567 | if (new_inode) |
535 | 568 | __linvfs_validate_fields(new_inode, vattr); | |
536 | if (new_inode) | 569 | __linvfs_validate_fields(odir, vattr); |
537 | validate_fields(new_inode); | 570 | if (ndir != odir) |
538 | 571 | __linvfs_validate_fields(ndir, vattr); | |
539 | validate_fields(odir); | 572 | } |
540 | if (ndir != odir) | 573 | kfree(vattr); |
541 | validate_fields(ndir); | 574 | return -error; |
542 | return 0; | ||
543 | } | 575 | } |
544 | 576 | ||
545 | /* | 577 | /* |
@@ -653,11 +685,10 @@ linvfs_setattr( | |||
653 | struct inode *inode = dentry->d_inode; | 685 | struct inode *inode = dentry->d_inode; |
654 | unsigned int ia_valid = attr->ia_valid; | 686 | unsigned int ia_valid = attr->ia_valid; |
655 | vnode_t *vp = LINVFS_GET_VP(inode); | 687 | vnode_t *vp = LINVFS_GET_VP(inode); |
656 | vattr_t vattr; | 688 | vattr_t vattr = { 0 }; |
657 | int flags = 0; | 689 | int flags = 0; |
658 | int error; | 690 | int error; |
659 | 691 | ||
660 | memset(&vattr, 0, sizeof(vattr_t)); | ||
661 | if (ia_valid & ATTR_UID) { | 692 | if (ia_valid & ATTR_UID) { |
662 | vattr.va_mask |= XFS_AT_UID; | 693 | vattr.va_mask |= XFS_AT_UID; |
663 | vattr.va_uid = attr->ia_uid; | 694 | vattr.va_uid = attr->ia_uid; |
@@ -699,10 +730,9 @@ linvfs_setattr( | |||
699 | #endif | 730 | #endif |
700 | 731 | ||
701 | VOP_SETATTR(vp, &vattr, flags, NULL, error); | 732 | VOP_SETATTR(vp, &vattr, flags, NULL, error); |
702 | if (error) | 733 | if (likely(!error)) |
703 | return -error; | 734 | __vn_revalidate(vp, &vattr); |
704 | vn_revalidate(vp); | 735 | return -error; |
705 | return error; | ||
706 | } | 736 | } |
707 | 737 | ||
708 | STATIC void | 738 | STATIC void |