diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 63 |
1 files changed, 41 insertions, 22 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 4ecf2a549060..ebdb88840a47 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -112,7 +112,7 @@ xfs_readlink( | |||
112 | char *link) | 112 | char *link) |
113 | { | 113 | { |
114 | xfs_mount_t *mp = ip->i_mount; | 114 | xfs_mount_t *mp = ip->i_mount; |
115 | int pathlen; | 115 | xfs_fsize_t pathlen; |
116 | int error = 0; | 116 | int error = 0; |
117 | 117 | ||
118 | trace_xfs_readlink(ip); | 118 | trace_xfs_readlink(ip); |
@@ -122,13 +122,20 @@ xfs_readlink( | |||
122 | 122 | ||
123 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 123 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
124 | 124 | ||
125 | ASSERT(S_ISLNK(ip->i_d.di_mode)); | ||
126 | ASSERT(ip->i_d.di_size <= MAXPATHLEN); | ||
127 | |||
128 | pathlen = ip->i_d.di_size; | 125 | pathlen = ip->i_d.di_size; |
129 | if (!pathlen) | 126 | if (!pathlen) |
130 | goto out; | 127 | goto out; |
131 | 128 | ||
129 | if (pathlen < 0 || pathlen > MAXPATHLEN) { | ||
130 | xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)", | ||
131 | __func__, (unsigned long long) ip->i_ino, | ||
132 | (long long) pathlen); | ||
133 | ASSERT(0); | ||
134 | error = XFS_ERROR(EFSCORRUPTED); | ||
135 | goto out; | ||
136 | } | ||
137 | |||
138 | |||
132 | if (ip->i_df.if_flags & XFS_IFINLINE) { | 139 | if (ip->i_df.if_flags & XFS_IFINLINE) { |
133 | memcpy(link, ip->i_df.if_u1.if_data, pathlen); | 140 | memcpy(link, ip->i_df.if_u1.if_data, pathlen); |
134 | link[pathlen] = '\0'; | 141 | link[pathlen] = '\0'; |
@@ -169,7 +176,7 @@ xfs_free_eofblocks( | |||
169 | * Figure out if there are any blocks beyond the end | 176 | * Figure out if there are any blocks beyond the end |
170 | * of the file. If not, then there is nothing to do. | 177 | * of the file. If not, then there is nothing to do. |
171 | */ | 178 | */ |
172 | end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_size)); | 179 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip)); |
173 | last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); | 180 | last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); |
174 | if (last_fsb <= end_fsb) | 181 | if (last_fsb <= end_fsb) |
175 | return 0; | 182 | return 0; |
@@ -220,7 +227,14 @@ xfs_free_eofblocks( | |||
220 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 227 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
221 | xfs_trans_ijoin(tp, ip, 0); | 228 | xfs_trans_ijoin(tp, ip, 0); |
222 | 229 | ||
223 | error = xfs_itruncate_data(&tp, ip, ip->i_size); | 230 | /* |
231 | * Do not update the on-disk file size. If we update the | ||
232 | * on-disk file size and then the system crashes before the | ||
233 | * contents of the file are flushed to disk then the files | ||
234 | * may be full of holes (ie NULL files bug). | ||
235 | */ | ||
236 | error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, | ||
237 | XFS_ISIZE(ip)); | ||
224 | if (error) { | 238 | if (error) { |
225 | /* | 239 | /* |
226 | * If we get an error at this point we simply don't | 240 | * If we get an error at this point we simply don't |
@@ -534,8 +548,8 @@ xfs_release( | |||
534 | return 0; | 548 | return 0; |
535 | 549 | ||
536 | if ((S_ISREG(ip->i_d.di_mode) && | 550 | if ((S_ISREG(ip->i_d.di_mode) && |
537 | ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 || | 551 | (VFS_I(ip)->i_size > 0 || |
538 | ip->i_delayed_blks > 0)) && | 552 | (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) && |
539 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && | 553 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && |
540 | (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { | 554 | (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { |
541 | 555 | ||
@@ -612,7 +626,7 @@ xfs_inactive( | |||
612 | * only one with a reference to the inode. | 626 | * only one with a reference to the inode. |
613 | */ | 627 | */ |
614 | truncate = ((ip->i_d.di_nlink == 0) && | 628 | truncate = ((ip->i_d.di_nlink == 0) && |
615 | ((ip->i_d.di_size != 0) || (ip->i_size != 0) || | 629 | ((ip->i_d.di_size != 0) || XFS_ISIZE(ip) != 0 || |
616 | (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) && | 630 | (ip->i_d.di_nextents > 0) || (ip->i_delayed_blks > 0)) && |
617 | S_ISREG(ip->i_d.di_mode)); | 631 | S_ISREG(ip->i_d.di_mode)); |
618 | 632 | ||
@@ -626,12 +640,12 @@ xfs_inactive( | |||
626 | 640 | ||
627 | if (ip->i_d.di_nlink != 0) { | 641 | if (ip->i_d.di_nlink != 0) { |
628 | if ((S_ISREG(ip->i_d.di_mode) && | 642 | if ((S_ISREG(ip->i_d.di_mode) && |
629 | ((ip->i_size > 0) || (VN_CACHED(VFS_I(ip)) > 0 || | 643 | (VFS_I(ip)->i_size > 0 || |
630 | ip->i_delayed_blks > 0)) && | 644 | (VN_CACHED(VFS_I(ip)) > 0 || ip->i_delayed_blks > 0)) && |
631 | (ip->i_df.if_flags & XFS_IFEXTENTS) && | 645 | (ip->i_df.if_flags & XFS_IFEXTENTS) && |
632 | (!(ip->i_d.di_flags & | 646 | (!(ip->i_d.di_flags & |
633 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || | 647 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || |
634 | (ip->i_delayed_blks != 0)))) { | 648 | ip->i_delayed_blks != 0))) { |
635 | error = xfs_free_eofblocks(mp, ip, 0); | 649 | error = xfs_free_eofblocks(mp, ip, 0); |
636 | if (error) | 650 | if (error) |
637 | return VN_INACTIVE_CACHE; | 651 | return VN_INACTIVE_CACHE; |
@@ -664,13 +678,18 @@ xfs_inactive( | |||
664 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 678 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
665 | xfs_trans_ijoin(tp, ip, 0); | 679 | xfs_trans_ijoin(tp, ip, 0); |
666 | 680 | ||
667 | error = xfs_itruncate_data(&tp, ip, 0); | 681 | ip->i_d.di_size = 0; |
682 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
683 | |||
684 | error = xfs_itruncate_extents(&tp, ip, XFS_DATA_FORK, 0); | ||
668 | if (error) { | 685 | if (error) { |
669 | xfs_trans_cancel(tp, | 686 | xfs_trans_cancel(tp, |
670 | XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | 687 | XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); |
671 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 688 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
672 | return VN_INACTIVE_CACHE; | 689 | return VN_INACTIVE_CACHE; |
673 | } | 690 | } |
691 | |||
692 | ASSERT(ip->i_d.di_nextents == 0); | ||
674 | } else if (S_ISLNK(ip->i_d.di_mode)) { | 693 | } else if (S_ISLNK(ip->i_d.di_mode)) { |
675 | 694 | ||
676 | /* | 695 | /* |
@@ -816,7 +835,7 @@ int | |||
816 | xfs_create( | 835 | xfs_create( |
817 | xfs_inode_t *dp, | 836 | xfs_inode_t *dp, |
818 | struct xfs_name *name, | 837 | struct xfs_name *name, |
819 | mode_t mode, | 838 | umode_t mode, |
820 | xfs_dev_t rdev, | 839 | xfs_dev_t rdev, |
821 | xfs_inode_t **ipp) | 840 | xfs_inode_t **ipp) |
822 | { | 841 | { |
@@ -1475,7 +1494,7 @@ xfs_symlink( | |||
1475 | xfs_inode_t *dp, | 1494 | xfs_inode_t *dp, |
1476 | struct xfs_name *link_name, | 1495 | struct xfs_name *link_name, |
1477 | const char *target_path, | 1496 | const char *target_path, |
1478 | mode_t mode, | 1497 | umode_t mode, |
1479 | xfs_inode_t **ipp) | 1498 | xfs_inode_t **ipp) |
1480 | { | 1499 | { |
1481 | xfs_mount_t *mp = dp->i_mount; | 1500 | xfs_mount_t *mp = dp->i_mount; |
@@ -1955,11 +1974,11 @@ xfs_zero_remaining_bytes( | |||
1955 | * since nothing can read beyond eof. The space will | 1974 | * since nothing can read beyond eof. The space will |
1956 | * be zeroed when the file is extended anyway. | 1975 | * be zeroed when the file is extended anyway. |
1957 | */ | 1976 | */ |
1958 | if (startoff >= ip->i_size) | 1977 | if (startoff >= XFS_ISIZE(ip)) |
1959 | return 0; | 1978 | return 0; |
1960 | 1979 | ||
1961 | if (endoff > ip->i_size) | 1980 | if (endoff > XFS_ISIZE(ip)) |
1962 | endoff = ip->i_size; | 1981 | endoff = XFS_ISIZE(ip); |
1963 | 1982 | ||
1964 | bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ? | 1983 | bp = xfs_buf_get_uncached(XFS_IS_REALTIME_INODE(ip) ? |
1965 | mp->m_rtdev_targp : mp->m_ddev_targp, | 1984 | mp->m_rtdev_targp : mp->m_ddev_targp, |
@@ -2254,7 +2273,7 @@ xfs_change_file_space( | |||
2254 | bf->l_start += offset; | 2273 | bf->l_start += offset; |
2255 | break; | 2274 | break; |
2256 | case 2: /*SEEK_END*/ | 2275 | case 2: /*SEEK_END*/ |
2257 | bf->l_start += ip->i_size; | 2276 | bf->l_start += XFS_ISIZE(ip); |
2258 | break; | 2277 | break; |
2259 | default: | 2278 | default: |
2260 | return XFS_ERROR(EINVAL); | 2279 | return XFS_ERROR(EINVAL); |
@@ -2271,7 +2290,7 @@ xfs_change_file_space( | |||
2271 | bf->l_whence = 0; | 2290 | bf->l_whence = 0; |
2272 | 2291 | ||
2273 | startoffset = bf->l_start; | 2292 | startoffset = bf->l_start; |
2274 | fsize = ip->i_size; | 2293 | fsize = XFS_ISIZE(ip); |
2275 | 2294 | ||
2276 | /* | 2295 | /* |
2277 | * XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve | 2296 | * XFS_IOC_RESVSP and XFS_IOC_UNRESVSP will reserve or unreserve |