diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
| -rw-r--r-- | fs/xfs/xfs_vnodeops.c | 120 |
1 files changed, 6 insertions, 114 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 6f268756bf36..9d376be0ea38 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -256,7 +256,7 @@ xfs_setattr( | |||
| 256 | iattr->ia_size > ip->i_d.di_size) { | 256 | iattr->ia_size > ip->i_d.di_size) { |
| 257 | code = xfs_flush_pages(ip, | 257 | code = xfs_flush_pages(ip, |
| 258 | ip->i_d.di_size, iattr->ia_size, | 258 | ip->i_d.di_size, iattr->ia_size, |
| 259 | XFS_B_ASYNC, FI_NONE); | 259 | XBF_ASYNC, FI_NONE); |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | /* wait for all I/O to complete */ | 262 | /* wait for all I/O to complete */ |
| @@ -584,116 +584,6 @@ xfs_readlink( | |||
| 584 | } | 584 | } |
| 585 | 585 | ||
| 586 | /* | 586 | /* |
| 587 | * xfs_fsync | ||
| 588 | * | ||
| 589 | * This is called to sync the inode and its data out to disk. We need to hold | ||
| 590 | * the I/O lock while flushing the data, and the inode lock while flushing the | ||
| 591 | * inode. The inode lock CANNOT be held while flushing the data, so acquire | ||
| 592 | * after we're done with that. | ||
| 593 | */ | ||
| 594 | int | ||
| 595 | xfs_fsync( | ||
| 596 | xfs_inode_t *ip) | ||
| 597 | { | ||
| 598 | xfs_trans_t *tp; | ||
| 599 | int error = 0; | ||
| 600 | int log_flushed = 0, changed = 1; | ||
| 601 | |||
| 602 | xfs_itrace_entry(ip); | ||
| 603 | |||
| 604 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
| 605 | return XFS_ERROR(EIO); | ||
| 606 | |||
| 607 | /* | ||
| 608 | * We always need to make sure that the required inode state is safe on | ||
| 609 | * disk. The inode might be clean but we still might need to force the | ||
| 610 | * log because of committed transactions that haven't hit the disk yet. | ||
| 611 | * Likewise, there could be unflushed non-transactional changes to the | ||
| 612 | * inode core that have to go to disk and this requires us to issue | ||
| 613 | * a synchronous transaction to capture these changes correctly. | ||
| 614 | * | ||
| 615 | * This code relies on the assumption that if the update_* fields | ||
| 616 | * of the inode are clear and the inode is unpinned then it is clean | ||
| 617 | * and no action is required. | ||
| 618 | */ | ||
| 619 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
| 620 | |||
| 621 | if (!ip->i_update_core) { | ||
| 622 | /* | ||
| 623 | * Timestamps/size haven't changed since last inode flush or | ||
| 624 | * inode transaction commit. That means either nothing got | ||
| 625 | * written or a transaction committed which caught the updates. | ||
| 626 | * If the latter happened and the transaction hasn't hit the | ||
| 627 | * disk yet, the inode will be still be pinned. If it is, | ||
| 628 | * force the log. | ||
| 629 | */ | ||
| 630 | |||
| 631 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
| 632 | |||
| 633 | if (xfs_ipincount(ip)) { | ||
| 634 | error = _xfs_log_force(ip->i_mount, (xfs_lsn_t)0, | ||
| 635 | XFS_LOG_FORCE | XFS_LOG_SYNC, | ||
| 636 | &log_flushed); | ||
| 637 | } else { | ||
| 638 | /* | ||
| 639 | * If the inode is not pinned and nothing has changed | ||
| 640 | * we don't need to flush the cache. | ||
| 641 | */ | ||
| 642 | changed = 0; | ||
| 643 | } | ||
| 644 | } else { | ||
| 645 | /* | ||
| 646 | * Kick off a transaction to log the inode core to get the | ||
| 647 | * updates. The sync transaction will also force the log. | ||
| 648 | */ | ||
| 649 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
| 650 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS); | ||
| 651 | error = xfs_trans_reserve(tp, 0, | ||
| 652 | XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0); | ||
| 653 | if (error) { | ||
| 654 | xfs_trans_cancel(tp, 0); | ||
| 655 | return error; | ||
| 656 | } | ||
| 657 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 658 | |||
| 659 | /* | ||
| 660 | * Note - it's possible that we might have pushed ourselves out | ||
| 661 | * of the way during trans_reserve which would flush the inode. | ||
| 662 | * But there's no guarantee that the inode buffer has actually | ||
| 663 | * gone out yet (it's delwri). Plus the buffer could be pinned | ||
| 664 | * anyway if it's part of an inode in another recent | ||
| 665 | * transaction. So we play it safe and fire off the | ||
| 666 | * transaction anyway. | ||
| 667 | */ | ||
| 668 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
| 669 | xfs_trans_ihold(tp, ip); | ||
| 670 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
| 671 | xfs_trans_set_sync(tp); | ||
| 672 | error = _xfs_trans_commit(tp, 0, &log_flushed); | ||
| 673 | |||
| 674 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 675 | } | ||
| 676 | |||
| 677 | if ((ip->i_mount->m_flags & XFS_MOUNT_BARRIER) && changed) { | ||
| 678 | /* | ||
| 679 | * If the log write didn't issue an ordered tag we need | ||
| 680 | * to flush the disk cache for the data device now. | ||
| 681 | */ | ||
| 682 | if (!log_flushed) | ||
| 683 | xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); | ||
| 684 | |||
| 685 | /* | ||
| 686 | * If this inode is on the RT dev we need to flush that | ||
| 687 | * cache as well. | ||
| 688 | */ | ||
| 689 | if (XFS_IS_REALTIME_INODE(ip)) | ||
| 690 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); | ||
| 691 | } | ||
| 692 | |||
| 693 | return error; | ||
| 694 | } | ||
| 695 | |||
| 696 | /* | ||
| 697 | * Flags for xfs_free_eofblocks | 587 | * Flags for xfs_free_eofblocks |
| 698 | */ | 588 | */ |
| 699 | #define XFS_FREE_EOF_TRYLOCK (1<<0) | 589 | #define XFS_FREE_EOF_TRYLOCK (1<<0) |
| @@ -1096,7 +986,7 @@ xfs_release( | |||
| 1096 | */ | 986 | */ |
| 1097 | truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); | 987 | truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); |
| 1098 | if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) | 988 | if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) |
| 1099 | xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE); | 989 | xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE); |
| 1100 | } | 990 | } |
| 1101 | 991 | ||
| 1102 | if (ip->i_d.di_nlink != 0) { | 992 | if (ip->i_d.di_nlink != 0) { |
| @@ -2199,7 +2089,8 @@ xfs_symlink( | |||
| 2199 | if (DM_EVENT_ENABLED(dp, DM_EVENT_SYMLINK)) { | 2089 | if (DM_EVENT_ENABLED(dp, DM_EVENT_SYMLINK)) { |
| 2200 | error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dp, | 2090 | error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dp, |
| 2201 | DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, | 2091 | DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, |
| 2202 | link_name->name, target_path, 0, 0, 0); | 2092 | link_name->name, |
| 2093 | (unsigned char *)target_path, 0, 0, 0); | ||
| 2203 | if (error) | 2094 | if (error) |
| 2204 | return error; | 2095 | return error; |
| 2205 | } | 2096 | } |
| @@ -2395,7 +2286,8 @@ std_return: | |||
| 2395 | dp, DM_RIGHT_NULL, | 2286 | dp, DM_RIGHT_NULL, |
| 2396 | error ? NULL : ip, | 2287 | error ? NULL : ip, |
| 2397 | DM_RIGHT_NULL, link_name->name, | 2288 | DM_RIGHT_NULL, link_name->name, |
| 2398 | target_path, 0, error, 0); | 2289 | (unsigned char *)target_path, |
| 2290 | 0, error, 0); | ||
| 2399 | } | 2291 | } |
| 2400 | 2292 | ||
| 2401 | if (!error) | 2293 | if (!error) |
