aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c63
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
816xfs_create( 835xfs_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