diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-07-04 11:13:29 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-07-29 17:13:09 -0400 |
commit | b373e98daa70d7ddb10f53f81e711c4d17651795 (patch) | |
tree | 88efafe921aadda455f842347bf06ff108f0a08e /fs/xfs/xfs_vnodeops.c | |
parent | be60fe54b216a62403b816d3930a66ad7c51cbc6 (diff) |
xfs: clean up xfs_inactive
The code to reserve log space and join the inode to the transaction is
common for all cases, so don't duplicate it. Also remove the trivial
xfs_inactive_symlink_local helper which can simply be opencode now.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Rich Johnston <rjohnston@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 171 |
1 files changed, 43 insertions, 128 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index c22f4e0ecac1..f9a515776a9c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -282,23 +282,15 @@ xfs_inactive_symlink_rmt( | |||
282 | * free them all in one bunmapi call. | 282 | * free them all in one bunmapi call. |
283 | */ | 283 | */ |
284 | ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); | 284 | ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); |
285 | if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, | 285 | |
286 | XFS_TRANS_PERM_LOG_RES, XFS_ITRUNCATE_LOG_COUNT))) { | ||
287 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
288 | xfs_trans_cancel(tp, 0); | ||
289 | *tpp = NULL; | ||
290 | return error; | ||
291 | } | ||
292 | /* | 286 | /* |
293 | * Lock the inode, fix the size, and join it to the transaction. | 287 | * Lock the inode, fix the size, and join it to the transaction. |
294 | * Hold it so in the normal path, we still have it locked for | 288 | * Hold it so in the normal path, we still have it locked for |
295 | * the second transaction. In the error paths we need it | 289 | * the second transaction. In the error paths we need it |
296 | * held so the cancel won't rele it, see below. | 290 | * held so the cancel won't rele it, see below. |
297 | */ | 291 | */ |
298 | xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | ||
299 | size = (int)ip->i_d.di_size; | 292 | size = (int)ip->i_d.di_size; |
300 | ip->i_d.di_size = 0; | 293 | ip->i_d.di_size = 0; |
301 | xfs_trans_ijoin(tp, ip, 0); | ||
302 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 294 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
303 | /* | 295 | /* |
304 | * Find the block(s) so we can inval and unmap them. | 296 | * Find the block(s) so we can inval and unmap them. |
@@ -385,67 +377,15 @@ xfs_inactive_symlink_rmt( | |||
385 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | 377 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); |
386 | goto error0; | 378 | goto error0; |
387 | } | 379 | } |
388 | /* | 380 | |
389 | * Return with the inode locked but not joined to the transaction. | 381 | xfs_trans_ijoin(tp, ip, 0); |
390 | */ | ||
391 | *tpp = tp; | 382 | *tpp = tp; |
392 | return 0; | 383 | return 0; |
393 | 384 | ||
394 | error1: | 385 | error1: |
395 | xfs_bmap_cancel(&free_list); | 386 | xfs_bmap_cancel(&free_list); |
396 | error0: | 387 | error0: |
397 | /* | ||
398 | * Have to come here with the inode locked and either | ||
399 | * (held and in the transaction) or (not in the transaction). | ||
400 | * If the inode isn't held then cancel would iput it, but | ||
401 | * that's wrong since this is inactive and the vnode ref | ||
402 | * count is 0 already. | ||
403 | * Cancel won't do anything to the inode if held, but it still | ||
404 | * needs to be locked until the cancel is done, if it was | ||
405 | * joined to the transaction. | ||
406 | */ | ||
407 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
408 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | ||
409 | *tpp = NULL; | ||
410 | return error; | 388 | return error; |
411 | |||
412 | } | ||
413 | |||
414 | STATIC int | ||
415 | xfs_inactive_symlink_local( | ||
416 | xfs_inode_t *ip, | ||
417 | xfs_trans_t **tpp) | ||
418 | { | ||
419 | int error; | ||
420 | |||
421 | ASSERT(ip->i_d.di_size <= XFS_IFORK_DSIZE(ip)); | ||
422 | /* | ||
423 | * We're freeing a symlink which fit into | ||
424 | * the inode. Just free the memory used | ||
425 | * to hold the old symlink. | ||
426 | */ | ||
427 | error = xfs_trans_reserve(*tpp, 0, | ||
428 | XFS_ITRUNCATE_LOG_RES(ip->i_mount), | ||
429 | 0, XFS_TRANS_PERM_LOG_RES, | ||
430 | XFS_ITRUNCATE_LOG_COUNT); | ||
431 | |||
432 | if (error) { | ||
433 | xfs_trans_cancel(*tpp, 0); | ||
434 | *tpp = NULL; | ||
435 | return error; | ||
436 | } | ||
437 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
438 | |||
439 | /* | ||
440 | * Zero length symlinks _can_ exist. | ||
441 | */ | ||
442 | if (ip->i_df.if_bytes > 0) { | ||
443 | xfs_idata_realloc(ip, | ||
444 | -(ip->i_df.if_bytes), | ||
445 | XFS_DATA_FORK); | ||
446 | ASSERT(ip->i_df.if_bytes == 0); | ||
447 | } | ||
448 | return 0; | ||
449 | } | 389 | } |
450 | 390 | ||
451 | STATIC int | 391 | STATIC int |
@@ -604,7 +544,7 @@ xfs_inactive( | |||
604 | xfs_trans_t *tp; | 544 | xfs_trans_t *tp; |
605 | xfs_mount_t *mp; | 545 | xfs_mount_t *mp; |
606 | int error; | 546 | int error; |
607 | int truncate; | 547 | int truncate = 0; |
608 | 548 | ||
609 | /* | 549 | /* |
610 | * If the inode is already free, then there can be nothing | 550 | * If the inode is already free, then there can be nothing |
@@ -616,17 +556,6 @@ xfs_inactive( | |||
616 | return VN_INACTIVE_CACHE; | 556 | return VN_INACTIVE_CACHE; |
617 | } | 557 | } |
618 | 558 | ||
619 | /* | ||
620 | * Only do a truncate if it's a regular file with | ||
621 | * some actual space in it. It's OK to look at the | ||
622 | * inode's fields without the lock because we're the | ||
623 | * only one with a reference to the inode. | ||
624 | */ | ||
625 | truncate = ((ip->i_d.di_nlink == 0) && | ||
626 | ((ip->i_d.di_size != 0) || XFS_ISIZE(ip) != 0 || | ||
627 | (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) && | ||
628 | S_ISREG(ip->i_d.di_mode)); | ||
629 | |||
630 | mp = ip->i_mount; | 559 | mp = ip->i_mount; |
631 | 560 | ||
632 | error = 0; | 561 | error = 0; |
@@ -650,72 +579,54 @@ xfs_inactive( | |||
650 | goto out; | 579 | goto out; |
651 | } | 580 | } |
652 | 581 | ||
653 | ASSERT(ip->i_d.di_nlink == 0); | 582 | if (S_ISREG(ip->i_d.di_mode) && |
583 | (ip->i_d.di_size != 0 || XFS_ISIZE(ip) != 0 || | ||
584 | ip->i_d.di_nextents > 0 || ip->i_delayed_blks > 0)) | ||
585 | truncate = 1; | ||
654 | 586 | ||
655 | error = xfs_qm_dqattach(ip, 0); | 587 | error = xfs_qm_dqattach(ip, 0); |
656 | if (error) | 588 | if (error) |
657 | return VN_INACTIVE_CACHE; | 589 | return VN_INACTIVE_CACHE; |
658 | 590 | ||
659 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | 591 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); |
660 | if (truncate) { | 592 | error = xfs_trans_reserve(tp, 0, |
661 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 593 | (truncate || S_ISLNK(ip->i_d.di_mode)) ? |
662 | 594 | XFS_ITRUNCATE_LOG_RES(mp) : | |
663 | error = xfs_trans_reserve(tp, 0, | 595 | XFS_IFREE_LOG_RES(mp), |
664 | XFS_ITRUNCATE_LOG_RES(mp), | 596 | 0, |
665 | 0, XFS_TRANS_PERM_LOG_RES, | 597 | XFS_TRANS_PERM_LOG_RES, |
666 | XFS_ITRUNCATE_LOG_COUNT); | 598 | XFS_ITRUNCATE_LOG_COUNT); |
667 | if (error) { | 599 | if (error) { |
668 | /* Don't call itruncate_cleanup */ | 600 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); |
669 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | 601 | xfs_trans_cancel(tp, 0); |
670 | xfs_trans_cancel(tp, 0); | 602 | return VN_INACTIVE_CACHE; |
671 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 603 | } |
672 | return VN_INACTIVE_CACHE; | ||
673 | } | ||
674 | 604 | ||
675 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 605 | xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
676 | xfs_trans_ijoin(tp, ip, 0); | 606 | xfs_trans_ijoin(tp, ip, 0); |
677 | 607 | ||
608 | if (S_ISLNK(ip->i_d.di_mode)) { | ||
609 | /* | ||
610 | * Zero length symlinks _can_ exist. | ||
611 | */ | ||
612 | if (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) { | ||
613 | error = xfs_inactive_symlink_rmt(ip, &tp); | ||
614 | if (error) | ||
615 | goto out_cancel; | ||
616 | } else if (ip->i_df.if_bytes > 0) { | ||
617 | xfs_idata_realloc(ip, -(ip->i_df.if_bytes), | ||
618 | XFS_DATA_FORK); | ||
619 | ASSERT(ip->i_df.if_bytes == 0); | ||
620 | } | ||
621 | } else if (truncate) { | ||
678 | ip->i_d.di_size = 0; | 622 | ip->i_d.di_size = 0; |
679 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 623 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
680 | 624 | ||
681 | error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); | 625 | error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); |
682 | if (error) { | 626 | if (error) |
683 | xfs_trans_cancel(tp, | 627 | goto out_cancel; |
684 | XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
685 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | ||
686 | return VN_INACTIVE_CACHE; | ||
687 | } | ||
688 | 628 | ||
689 | ASSERT(ip->i_d.di_nextents == 0); | 629 | ASSERT(ip->i_d.di_nextents == 0); |
690 | } else if (S_ISLNK(ip->i_d.di_mode)) { | ||
691 | |||
692 | /* | ||
693 | * If we get an error while cleaning up a | ||
694 | * symlink we bail out. | ||
695 | */ | ||
696 | error = (ip->i_d.di_size > XFS_IFORK_DSIZE(ip)) ? | ||
697 | xfs_inactive_symlink_rmt(ip, &tp) : | ||
698 | xfs_inactive_symlink_local(ip, &tp); | ||
699 | |||
700 | if (error) { | ||
701 | ASSERT(tp == NULL); | ||
702 | return VN_INACTIVE_CACHE; | ||
703 | } | ||
704 | |||
705 | xfs_trans_ijoin(tp, ip, 0); | ||
706 | } else { | ||
707 | error = xfs_trans_reserve(tp, 0, | ||
708 | XFS_IFREE_LOG_RES(mp), | ||
709 | 0, XFS_TRANS_PERM_LOG_RES, | ||
710 | XFS_INACTIVE_LOG_COUNT); | ||
711 | if (error) { | ||
712 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
713 | xfs_trans_cancel(tp, 0); | ||
714 | return VN_INACTIVE_CACHE; | ||
715 | } | ||
716 | |||
717 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
718 | xfs_trans_ijoin(tp, ip, 0); | ||
719 | } | 630 | } |
720 | 631 | ||
721 | /* | 632 | /* |
@@ -781,7 +692,11 @@ xfs_inactive( | |||
781 | xfs_qm_dqdetach(ip); | 692 | xfs_qm_dqdetach(ip); |
782 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 693 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
783 | 694 | ||
784 | out: | 695 | out: |
696 | return VN_INACTIVE_CACHE; | ||
697 | out_cancel: | ||
698 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
699 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | ||
785 | return VN_INACTIVE_CACHE; | 700 | return VN_INACTIVE_CACHE; |
786 | } | 701 | } |
787 | 702 | ||