diff options
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_iops.c')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 192 |
1 files changed, 119 insertions, 73 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index e88f51028086..91bcd979242c 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
| @@ -62,7 +62,7 @@ void | |||
| 62 | xfs_synchronize_atime( | 62 | xfs_synchronize_atime( |
| 63 | xfs_inode_t *ip) | 63 | xfs_inode_t *ip) |
| 64 | { | 64 | { |
| 65 | struct inode *inode = ip->i_vnode; | 65 | struct inode *inode = VFS_I(ip); |
| 66 | 66 | ||
| 67 | if (inode) { | 67 | if (inode) { |
| 68 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; | 68 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; |
| @@ -79,7 +79,7 @@ void | |||
| 79 | xfs_mark_inode_dirty_sync( | 79 | xfs_mark_inode_dirty_sync( |
| 80 | xfs_inode_t *ip) | 80 | xfs_inode_t *ip) |
| 81 | { | 81 | { |
| 82 | struct inode *inode = ip->i_vnode; | 82 | struct inode *inode = VFS_I(ip); |
| 83 | 83 | ||
| 84 | if (inode) | 84 | if (inode) |
| 85 | mark_inode_dirty_sync(inode); | 85 | mark_inode_dirty_sync(inode); |
| @@ -89,36 +89,31 @@ xfs_mark_inode_dirty_sync( | |||
| 89 | * Change the requested timestamp in the given inode. | 89 | * Change the requested timestamp in the given inode. |
| 90 | * We don't lock across timestamp updates, and we don't log them but | 90 | * We don't lock across timestamp updates, and we don't log them but |
| 91 | * we do record the fact that there is dirty information in core. | 91 | * we do record the fact that there is dirty information in core. |
| 92 | * | ||
| 93 | * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG | ||
| 94 | * with XFS_ICHGTIME_ACC to be sure that access time | ||
| 95 | * update will take. Calling first with XFS_ICHGTIME_ACC | ||
| 96 | * and then XFS_ICHGTIME_MOD may fail to modify the access | ||
| 97 | * timestamp if the filesystem is mounted noacctm. | ||
| 98 | */ | 92 | */ |
| 99 | void | 93 | void |
| 100 | xfs_ichgtime( | 94 | xfs_ichgtime( |
| 101 | xfs_inode_t *ip, | 95 | xfs_inode_t *ip, |
| 102 | int flags) | 96 | int flags) |
| 103 | { | 97 | { |
| 104 | struct inode *inode = vn_to_inode(XFS_ITOV(ip)); | 98 | struct inode *inode = VFS_I(ip); |
| 105 | timespec_t tv; | 99 | timespec_t tv; |
| 100 | int sync_it = 0; | ||
| 101 | |||
| 102 | tv = current_fs_time(inode->i_sb); | ||
| 106 | 103 | ||
| 107 | nanotime(&tv); | 104 | if ((flags & XFS_ICHGTIME_MOD) && |
| 108 | if (flags & XFS_ICHGTIME_MOD) { | 105 | !timespec_equal(&inode->i_mtime, &tv)) { |
| 109 | inode->i_mtime = tv; | 106 | inode->i_mtime = tv; |
| 110 | ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; | 107 | ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec; |
| 111 | ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; | 108 | ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec; |
| 109 | sync_it = 1; | ||
| 112 | } | 110 | } |
| 113 | if (flags & XFS_ICHGTIME_ACC) { | 111 | if ((flags & XFS_ICHGTIME_CHG) && |
| 114 | inode->i_atime = tv; | 112 | !timespec_equal(&inode->i_ctime, &tv)) { |
| 115 | ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec; | ||
| 116 | ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec; | ||
| 117 | } | ||
| 118 | if (flags & XFS_ICHGTIME_CHG) { | ||
| 119 | inode->i_ctime = tv; | 113 | inode->i_ctime = tv; |
| 120 | ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; | 114 | ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec; |
| 121 | ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; | 115 | ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec; |
| 116 | sync_it = 1; | ||
| 122 | } | 117 | } |
| 123 | 118 | ||
| 124 | /* | 119 | /* |
| @@ -130,55 +125,11 @@ xfs_ichgtime( | |||
| 130 | * ensure that the compiler does not reorder the update | 125 | * ensure that the compiler does not reorder the update |
| 131 | * of i_update_core above the timestamp updates above. | 126 | * of i_update_core above the timestamp updates above. |
| 132 | */ | 127 | */ |
| 133 | SYNCHRONIZE(); | 128 | if (sync_it) { |
| 134 | ip->i_update_core = 1; | 129 | SYNCHRONIZE(); |
| 135 | if (!(inode->i_state & I_NEW)) | 130 | ip->i_update_core = 1; |
| 136 | mark_inode_dirty_sync(inode); | 131 | mark_inode_dirty_sync(inode); |
| 137 | } | ||
| 138 | |||
| 139 | /* | ||
| 140 | * Variant on the above which avoids querying the system clock | ||
| 141 | * in situations where we know the Linux inode timestamps have | ||
| 142 | * just been updated (and so we can update our inode cheaply). | ||
| 143 | */ | ||
| 144 | void | ||
| 145 | xfs_ichgtime_fast( | ||
| 146 | xfs_inode_t *ip, | ||
| 147 | struct inode *inode, | ||
| 148 | int flags) | ||
| 149 | { | ||
| 150 | timespec_t *tvp; | ||
| 151 | |||
| 152 | /* | ||
| 153 | * Atime updates for read() & friends are handled lazily now, and | ||
| 154 | * explicit updates must go through xfs_ichgtime() | ||
| 155 | */ | ||
| 156 | ASSERT((flags & XFS_ICHGTIME_ACC) == 0); | ||
| 157 | |||
| 158 | if (flags & XFS_ICHGTIME_MOD) { | ||
| 159 | tvp = &inode->i_mtime; | ||
| 160 | ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec; | ||
| 161 | ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec; | ||
| 162 | } | 132 | } |
| 163 | if (flags & XFS_ICHGTIME_CHG) { | ||
| 164 | tvp = &inode->i_ctime; | ||
| 165 | ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec; | ||
| 166 | ip->i_d.di_ctime.t_nsec = (__int32_t)tvp->tv_nsec; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * We update the i_update_core field _after_ changing | ||
| 171 | * the timestamps in order to coordinate properly with | ||
| 172 | * xfs_iflush() so that we don't lose timestamp updates. | ||
| 173 | * This keeps us from having to hold the inode lock | ||
| 174 | * while doing this. We use the SYNCHRONIZE macro to | ||
| 175 | * ensure that the compiler does not reorder the update | ||
| 176 | * of i_update_core above the timestamp updates above. | ||
| 177 | */ | ||
| 178 | SYNCHRONIZE(); | ||
| 179 | ip->i_update_core = 1; | ||
| 180 | if (!(inode->i_state & I_NEW)) | ||
| 181 | mark_inode_dirty_sync(inode); | ||
| 182 | } | 133 | } |
| 183 | 134 | ||
| 184 | /* | 135 | /* |
| @@ -299,7 +250,7 @@ xfs_vn_mknod( | |||
| 299 | if (unlikely(error)) | 250 | if (unlikely(error)) |
| 300 | goto out_free_acl; | 251 | goto out_free_acl; |
| 301 | 252 | ||
| 302 | inode = ip->i_vnode; | 253 | inode = VFS_I(ip); |
| 303 | 254 | ||
| 304 | error = xfs_init_security(inode, dir); | 255 | error = xfs_init_security(inode, dir); |
| 305 | if (unlikely(error)) | 256 | if (unlikely(error)) |
| @@ -366,7 +317,7 @@ xfs_vn_lookup( | |||
| 366 | return NULL; | 317 | return NULL; |
| 367 | } | 318 | } |
| 368 | 319 | ||
| 369 | return d_splice_alias(cip->i_vnode, dentry); | 320 | return d_splice_alias(VFS_I(cip), dentry); |
| 370 | } | 321 | } |
| 371 | 322 | ||
| 372 | STATIC struct dentry * | 323 | STATIC struct dentry * |
| @@ -399,12 +350,12 @@ xfs_vn_ci_lookup( | |||
| 399 | 350 | ||
| 400 | /* if exact match, just splice and exit */ | 351 | /* if exact match, just splice and exit */ |
| 401 | if (!ci_name.name) | 352 | if (!ci_name.name) |
| 402 | return d_splice_alias(ip->i_vnode, dentry); | 353 | return d_splice_alias(VFS_I(ip), dentry); |
| 403 | 354 | ||
| 404 | /* else case-insensitive match... */ | 355 | /* else case-insensitive match... */ |
| 405 | dname.name = ci_name.name; | 356 | dname.name = ci_name.name; |
| 406 | dname.len = ci_name.len; | 357 | dname.len = ci_name.len; |
| 407 | dentry = d_add_ci(ip->i_vnode, dentry, &dname); | 358 | dentry = d_add_ci(VFS_I(ip), dentry, &dname); |
| 408 | kmem_free(ci_name.name); | 359 | kmem_free(ci_name.name); |
| 409 | return dentry; | 360 | return dentry; |
| 410 | } | 361 | } |
| @@ -478,7 +429,7 @@ xfs_vn_symlink( | |||
| 478 | if (unlikely(error)) | 429 | if (unlikely(error)) |
| 479 | goto out; | 430 | goto out; |
| 480 | 431 | ||
| 481 | inode = cip->i_vnode; | 432 | inode = VFS_I(cip); |
| 482 | 433 | ||
| 483 | error = xfs_init_security(inode, dir); | 434 | error = xfs_init_security(inode, dir); |
| 484 | if (unlikely(error)) | 435 | if (unlikely(error)) |
| @@ -710,7 +661,7 @@ out_error: | |||
| 710 | return error; | 661 | return error; |
| 711 | } | 662 | } |
| 712 | 663 | ||
| 713 | const struct inode_operations xfs_inode_operations = { | 664 | static const struct inode_operations xfs_inode_operations = { |
| 714 | .permission = xfs_vn_permission, | 665 | .permission = xfs_vn_permission, |
| 715 | .truncate = xfs_vn_truncate, | 666 | .truncate = xfs_vn_truncate, |
| 716 | .getattr = xfs_vn_getattr, | 667 | .getattr = xfs_vn_getattr, |
| @@ -722,7 +673,7 @@ const struct inode_operations xfs_inode_operations = { | |||
| 722 | .fallocate = xfs_vn_fallocate, | 673 | .fallocate = xfs_vn_fallocate, |
| 723 | }; | 674 | }; |
| 724 | 675 | ||
| 725 | const struct inode_operations xfs_dir_inode_operations = { | 676 | static const struct inode_operations xfs_dir_inode_operations = { |
| 726 | .create = xfs_vn_create, | 677 | .create = xfs_vn_create, |
| 727 | .lookup = xfs_vn_lookup, | 678 | .lookup = xfs_vn_lookup, |
| 728 | .link = xfs_vn_link, | 679 | .link = xfs_vn_link, |
| @@ -747,7 +698,7 @@ const struct inode_operations xfs_dir_inode_operations = { | |||
| 747 | .listxattr = xfs_vn_listxattr, | 698 | .listxattr = xfs_vn_listxattr, |
| 748 | }; | 699 | }; |
| 749 | 700 | ||
| 750 | const struct inode_operations xfs_dir_ci_inode_operations = { | 701 | static const struct inode_operations xfs_dir_ci_inode_operations = { |
| 751 | .create = xfs_vn_create, | 702 | .create = xfs_vn_create, |
| 752 | .lookup = xfs_vn_ci_lookup, | 703 | .lookup = xfs_vn_ci_lookup, |
| 753 | .link = xfs_vn_link, | 704 | .link = xfs_vn_link, |
| @@ -772,7 +723,7 @@ const struct inode_operations xfs_dir_ci_inode_operations = { | |||
| 772 | .listxattr = xfs_vn_listxattr, | 723 | .listxattr = xfs_vn_listxattr, |
| 773 | }; | 724 | }; |
| 774 | 725 | ||
| 775 | const struct inode_operations xfs_symlink_inode_operations = { | 726 | static const struct inode_operations xfs_symlink_inode_operations = { |
| 776 | .readlink = generic_readlink, | 727 | .readlink = generic_readlink, |
| 777 | .follow_link = xfs_vn_follow_link, | 728 | .follow_link = xfs_vn_follow_link, |
| 778 | .put_link = xfs_vn_put_link, | 729 | .put_link = xfs_vn_put_link, |
| @@ -784,3 +735,98 @@ const struct inode_operations xfs_symlink_inode_operations = { | |||
| 784 | .removexattr = generic_removexattr, | 735 | .removexattr = generic_removexattr, |
| 785 | .listxattr = xfs_vn_listxattr, | 736 | .listxattr = xfs_vn_listxattr, |
| 786 | }; | 737 | }; |
| 738 | |||
| 739 | STATIC void | ||
| 740 | xfs_diflags_to_iflags( | ||
| 741 | struct inode *inode, | ||
| 742 | struct xfs_inode *ip) | ||
| 743 | { | ||
| 744 | if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) | ||
| 745 | inode->i_flags |= S_IMMUTABLE; | ||
| 746 | else | ||
| 747 | inode->i_flags &= ~S_IMMUTABLE; | ||
| 748 | if (ip->i_d.di_flags & XFS_DIFLAG_APPEND) | ||
| 749 | inode->i_flags |= S_APPEND; | ||
| 750 | else | ||
| 751 | inode->i_flags &= ~S_APPEND; | ||
| 752 | if (ip->i_d.di_flags & XFS_DIFLAG_SYNC) | ||
| 753 | inode->i_flags |= S_SYNC; | ||
| 754 | else | ||
| 755 | inode->i_flags &= ~S_SYNC; | ||
| 756 | if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME) | ||
| 757 | inode->i_flags |= S_NOATIME; | ||
| 758 | else | ||
| 759 | inode->i_flags &= ~S_NOATIME; | ||
| 760 | } | ||
| 761 | |||
| 762 | /* | ||
| 763 | * Initialize the Linux inode, set up the operation vectors and | ||
| 764 | * unlock the inode. | ||
| 765 | * | ||
| 766 | * When reading existing inodes from disk this is called directly | ||
| 767 | * from xfs_iget, when creating a new inode it is called from | ||
| 768 | * xfs_ialloc after setting up the inode. | ||
| 769 | */ | ||
| 770 | void | ||
| 771 | xfs_setup_inode( | ||
| 772 | struct xfs_inode *ip) | ||
| 773 | { | ||
| 774 | struct inode *inode = ip->i_vnode; | ||
| 775 | |||
| 776 | inode->i_mode = ip->i_d.di_mode; | ||
| 777 | inode->i_nlink = ip->i_d.di_nlink; | ||
| 778 | inode->i_uid = ip->i_d.di_uid; | ||
| 779 | inode->i_gid = ip->i_d.di_gid; | ||
| 780 | |||
| 781 | switch (inode->i_mode & S_IFMT) { | ||
| 782 | case S_IFBLK: | ||
| 783 | case S_IFCHR: | ||
| 784 | inode->i_rdev = | ||
| 785 | MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff, | ||
| 786 | sysv_minor(ip->i_df.if_u2.if_rdev)); | ||
| 787 | break; | ||
| 788 | default: | ||
| 789 | inode->i_rdev = 0; | ||
| 790 | break; | ||
| 791 | } | ||
| 792 | |||
| 793 | inode->i_generation = ip->i_d.di_gen; | ||
| 794 | i_size_write(inode, ip->i_d.di_size); | ||
| 795 | inode->i_atime.tv_sec = ip->i_d.di_atime.t_sec; | ||
| 796 | inode->i_atime.tv_nsec = ip->i_d.di_atime.t_nsec; | ||
| 797 | inode->i_mtime.tv_sec = ip->i_d.di_mtime.t_sec; | ||
| 798 | inode->i_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; | ||
| 799 | inode->i_ctime.tv_sec = ip->i_d.di_ctime.t_sec; | ||
| 800 | inode->i_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec; | ||
| 801 | xfs_diflags_to_iflags(inode, ip); | ||
| 802 | xfs_iflags_clear(ip, XFS_IMODIFIED); | ||
| 803 | |||
| 804 | switch (inode->i_mode & S_IFMT) { | ||
| 805 | case S_IFREG: | ||
| 806 | inode->i_op = &xfs_inode_operations; | ||
| 807 | inode->i_fop = &xfs_file_operations; | ||
| 808 | inode->i_mapping->a_ops = &xfs_address_space_operations; | ||
| 809 | break; | ||
| 810 | case S_IFDIR: | ||
| 811 | if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb)) | ||
| 812 | inode->i_op = &xfs_dir_ci_inode_operations; | ||
| 813 | else | ||
| 814 | inode->i_op = &xfs_dir_inode_operations; | ||
| 815 | inode->i_fop = &xfs_dir_file_operations; | ||
| 816 | break; | ||
| 817 | case S_IFLNK: | ||
| 818 | inode->i_op = &xfs_symlink_inode_operations; | ||
| 819 | if (!(ip->i_df.if_flags & XFS_IFINLINE)) | ||
| 820 | inode->i_mapping->a_ops = &xfs_address_space_operations; | ||
| 821 | break; | ||
| 822 | default: | ||
| 823 | inode->i_op = &xfs_inode_operations; | ||
| 824 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | ||
| 825 | break; | ||
| 826 | } | ||
| 827 | |||
| 828 | xfs_iflags_clear(ip, XFS_INEW); | ||
| 829 | barrier(); | ||
| 830 | |||
| 831 | unlock_new_inode(inode); | ||
| 832 | } | ||
