aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-07-04 11:13:29 -0400
committerBen Myers <bpm@sgi.com>2012-07-29 17:13:09 -0400
commitb373e98daa70d7ddb10f53f81e711c4d17651795 (patch)
tree88efafe921aadda455f842347bf06ff108f0a08e /fs/xfs/xfs_vnodeops.c
parentbe60fe54b216a62403b816d3930a66ad7c51cbc6 (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.c171
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
414STATIC int
415xfs_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
451STATIC int 391STATIC 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: 695out:
696 return VN_INACTIVE_CACHE;
697out_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