aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_iops.c
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2006-03-13 21:33:36 -0500
committerNathan Scott <nathans@sgi.com>2006-03-13 21:33:36 -0500
commit220b5284139be6ecbc39b353fd76f0923eccc3d6 (patch)
tree86ab8c671631a109690d6589a19d9774d8bed18f /fs/xfs/linux-2.6/xfs_iops.c
parent9b94c2eddf407ad8faa5672ffa691e2076167564 (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.c180
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 */
200STATIC void 200STATIC void
201validate_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 */
226STATIC int 226STATIC int
227linvfs_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 */
259STATIC inline int 259STATIC inline int
260has_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
265STATIC inline void 265STATIC inline void
266cleanup_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
708STATIC void 738STATIC void