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.c193
1 files changed, 91 insertions, 102 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index e92cacde02f5..8076cc981e11 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -185,8 +185,7 @@ xfs_getattr(
185 break; 185 break;
186 } 186 }
187 187
188 vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec; 188 vn_atime_to_timespec(vp, &vap->va_atime);
189 vap->va_atime.tv_nsec = ip->i_d.di_atime.t_nsec;
190 vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec; 189 vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
191 vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; 190 vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
192 vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec; 191 vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
@@ -544,24 +543,6 @@ xfs_setattr(
544 } 543 }
545 544
546 /* 545 /*
547 * Can't set extent size unless the file is marked, or
548 * about to be marked as a realtime file.
549 *
550 * This check will be removed when fixed size extents
551 * with buffered data writes is implemented.
552 *
553 */
554 if ((mask & XFS_AT_EXTSIZE) &&
555 ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
556 vap->va_extsize) &&
557 (!((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ||
558 ((mask & XFS_AT_XFLAGS) &&
559 (vap->va_xflags & XFS_XFLAG_REALTIME))))) {
560 code = XFS_ERROR(EINVAL);
561 goto error_return;
562 }
563
564 /*
565 * Can't change realtime flag if any extents are allocated. 546 * Can't change realtime flag if any extents are allocated.
566 */ 547 */
567 if ((ip->i_d.di_nextents || ip->i_delayed_blks) && 548 if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
@@ -823,13 +804,17 @@ xfs_setattr(
823 di_flags |= XFS_DIFLAG_RTINHERIT; 804 di_flags |= XFS_DIFLAG_RTINHERIT;
824 if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS) 805 if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
825 di_flags |= XFS_DIFLAG_NOSYMLINKS; 806 di_flags |= XFS_DIFLAG_NOSYMLINKS;
826 } else { 807 if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
808 di_flags |= XFS_DIFLAG_EXTSZINHERIT;
809 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
827 if (vap->va_xflags & XFS_XFLAG_REALTIME) { 810 if (vap->va_xflags & XFS_XFLAG_REALTIME) {
828 di_flags |= XFS_DIFLAG_REALTIME; 811 di_flags |= XFS_DIFLAG_REALTIME;
829 ip->i_iocore.io_flags |= XFS_IOCORE_RT; 812 ip->i_iocore.io_flags |= XFS_IOCORE_RT;
830 } else { 813 } else {
831 ip->i_iocore.io_flags &= ~XFS_IOCORE_RT; 814 ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
832 } 815 }
816 if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
817 di_flags |= XFS_DIFLAG_EXTSIZE;
833 } 818 }
834 ip->i_d.di_flags = di_flags; 819 ip->i_d.di_flags = di_flags;
835 } 820 }
@@ -999,10 +984,6 @@ xfs_readlink(
999 goto error_return; 984 goto error_return;
1000 } 985 }
1001 986
1002 if (!(ioflags & IO_INVIS)) {
1003 xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
1004 }
1005
1006 /* 987 /*
1007 * See if the symlink is stored inline. 988 * See if the symlink is stored inline.
1008 */ 989 */
@@ -1234,7 +1215,8 @@ xfs_inactive_free_eofblocks(
1234 xfs_iunlock(ip, XFS_ILOCK_SHARED); 1215 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1235 1216
1236 if (!error && (nimaps != 0) && 1217 if (!error && (nimaps != 0) &&
1237 (imap.br_startblock != HOLESTARTBLOCK)) { 1218 (imap.br_startblock != HOLESTARTBLOCK ||
1219 ip->i_delayed_blks)) {
1238 /* 1220 /*
1239 * Attach the dquots to the inode up front. 1221 * Attach the dquots to the inode up front.
1240 */ 1222 */
@@ -1569,9 +1551,11 @@ xfs_release(
1569 1551
1570 if (ip->i_d.di_nlink != 0) { 1552 if (ip->i_d.di_nlink != 0) {
1571 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && 1553 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
1572 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && 1554 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
1555 ip->i_delayed_blks > 0)) &&
1573 (ip->i_df.if_flags & XFS_IFEXTENTS)) && 1556 (ip->i_df.if_flags & XFS_IFEXTENTS)) &&
1574 (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) { 1557 (!(ip->i_d.di_flags &
1558 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
1575 if ((error = xfs_inactive_free_eofblocks(mp, ip))) 1559 if ((error = xfs_inactive_free_eofblocks(mp, ip)))
1576 return (error); 1560 return (error);
1577 /* Update linux inode block count after free above */ 1561 /* Update linux inode block count after free above */
@@ -1628,7 +1612,8 @@ xfs_inactive(
1628 * only one with a reference to the inode. 1612 * only one with a reference to the inode.
1629 */ 1613 */
1630 truncate = ((ip->i_d.di_nlink == 0) && 1614 truncate = ((ip->i_d.di_nlink == 0) &&
1631 ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0)) && 1615 ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0) ||
1616 (ip->i_delayed_blks > 0)) &&
1632 ((ip->i_d.di_mode & S_IFMT) == S_IFREG)); 1617 ((ip->i_d.di_mode & S_IFMT) == S_IFREG));
1633 1618
1634 mp = ip->i_mount; 1619 mp = ip->i_mount;
@@ -1646,10 +1631,12 @@ xfs_inactive(
1646 1631
1647 if (ip->i_d.di_nlink != 0) { 1632 if (ip->i_d.di_nlink != 0) {
1648 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && 1633 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
1649 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && 1634 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
1650 (ip->i_df.if_flags & XFS_IFEXTENTS)) && 1635 ip->i_delayed_blks > 0)) &&
1651 (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) || 1636 (ip->i_df.if_flags & XFS_IFEXTENTS) &&
1652 (ip->i_delayed_blks != 0))) { 1637 (!(ip->i_d.di_flags &
1638 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
1639 (ip->i_delayed_blks != 0)))) {
1653 if ((error = xfs_inactive_free_eofblocks(mp, ip))) 1640 if ((error = xfs_inactive_free_eofblocks(mp, ip)))
1654 return (VN_INACTIVE_CACHE); 1641 return (VN_INACTIVE_CACHE);
1655 /* Update linux inode block count after free above */ 1642 /* Update linux inode block count after free above */
@@ -2593,7 +2580,6 @@ xfs_link(
2593 int cancel_flags; 2580 int cancel_flags;
2594 int committed; 2581 int committed;
2595 vnode_t *target_dir_vp; 2582 vnode_t *target_dir_vp;
2596 bhv_desc_t *src_bdp;
2597 int resblks; 2583 int resblks;
2598 char *target_name = VNAME(dentry); 2584 char *target_name = VNAME(dentry);
2599 int target_namelen; 2585 int target_namelen;
@@ -2606,8 +2592,7 @@ xfs_link(
2606 if (VN_ISDIR(src_vp)) 2592 if (VN_ISDIR(src_vp))
2607 return XFS_ERROR(EPERM); 2593 return XFS_ERROR(EPERM);
2608 2594
2609 src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops); 2595 sip = xfs_vtoi(src_vp);
2610 sip = XFS_BHVTOI(src_bdp);
2611 tdp = XFS_BHVTOI(target_dir_bdp); 2596 tdp = XFS_BHVTOI(target_dir_bdp);
2612 mp = tdp->i_mount; 2597 mp = tdp->i_mount;
2613 if (XFS_FORCED_SHUTDOWN(mp)) 2598 if (XFS_FORCED_SHUTDOWN(mp))
@@ -3240,7 +3225,6 @@ xfs_readdir(
3240 xfs_trans_t *tp = NULL; 3225 xfs_trans_t *tp = NULL;
3241 int error = 0; 3226 int error = 0;
3242 uint lock_mode; 3227 uint lock_mode;
3243 xfs_off_t start_offset;
3244 3228
3245 vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__, 3229 vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
3246 (inst_t *)__return_address); 3230 (inst_t *)__return_address);
@@ -3251,11 +3235,7 @@ xfs_readdir(
3251 } 3235 }
3252 3236
3253 lock_mode = xfs_ilock_map_shared(dp); 3237 lock_mode = xfs_ilock_map_shared(dp);
3254 start_offset = uiop->uio_offset;
3255 error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); 3238 error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp);
3256 if (start_offset != uiop->uio_offset) {
3257 xfs_ichgtime(dp, XFS_ICHGTIME_ACC);
3258 }
3259 xfs_iunlock_map_shared(dp, lock_mode); 3239 xfs_iunlock_map_shared(dp, lock_mode);
3260 return error; 3240 return error;
3261} 3241}
@@ -3832,7 +3812,12 @@ xfs_reclaim(
3832 vn_iowait(vp); 3812 vn_iowait(vp);
3833 3813
3834 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); 3814 ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
3835 ASSERT(VN_CACHED(vp) == 0); 3815
3816 /*
3817 * Make sure the atime in the XFS inode is correct before freeing the
3818 * Linux inode.
3819 */
3820 xfs_synchronize_atime(ip);
3836 3821
3837 /* If we have nothing to flush with this inode then complete the 3822 /* If we have nothing to flush with this inode then complete the
3838 * teardown now, otherwise break the link between the xfs inode 3823 * teardown now, otherwise break the link between the xfs inode
@@ -4002,42 +3987,36 @@ xfs_alloc_file_space(
4002 int alloc_type, 3987 int alloc_type,
4003 int attr_flags) 3988 int attr_flags)
4004{ 3989{
3990 xfs_mount_t *mp = ip->i_mount;
3991 xfs_off_t count;
4005 xfs_filblks_t allocated_fsb; 3992 xfs_filblks_t allocated_fsb;
4006 xfs_filblks_t allocatesize_fsb; 3993 xfs_filblks_t allocatesize_fsb;
4007 int committed; 3994 xfs_extlen_t extsz, temp;
4008 xfs_off_t count; 3995 xfs_fileoff_t startoffset_fsb;
4009 xfs_filblks_t datablocks;
4010 int error;
4011 xfs_fsblock_t firstfsb; 3996 xfs_fsblock_t firstfsb;
4012 xfs_bmap_free_t free_list; 3997 int nimaps;
4013 xfs_bmbt_irec_t *imapp; 3998 int bmapi_flag;
4014 xfs_bmbt_irec_t imaps[1]; 3999 int quota_flag;
4015 xfs_mount_t *mp;
4016 int numrtextents;
4017 int reccount;
4018 uint resblks;
4019 int rt; 4000 int rt;
4020 int rtextsize;
4021 xfs_fileoff_t startoffset_fsb;
4022 xfs_trans_t *tp; 4001 xfs_trans_t *tp;
4023 int xfs_bmapi_flags; 4002 xfs_bmbt_irec_t imaps[1], *imapp;
4003 xfs_bmap_free_t free_list;
4004 uint qblocks, resblks, resrtextents;
4005 int committed;
4006 int error;
4024 4007
4025 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); 4008 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
4026 mp = ip->i_mount;
4027 4009
4028 if (XFS_FORCED_SHUTDOWN(mp)) 4010 if (XFS_FORCED_SHUTDOWN(mp))
4029 return XFS_ERROR(EIO); 4011 return XFS_ERROR(EIO);
4030 4012
4031 /* 4013 rt = XFS_IS_REALTIME_INODE(ip);
4032 * determine if this is a realtime file 4014 if (unlikely(rt)) {
4033 */ 4015 if (!(extsz = ip->i_d.di_extsize))
4034 if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) { 4016 extsz = mp->m_sb.sb_rextsize;
4035 if (ip->i_d.di_extsize) 4017 } else {
4036 rtextsize = ip->i_d.di_extsize; 4018 extsz = ip->i_d.di_extsize;
4037 else 4019 }
4038 rtextsize = mp->m_sb.sb_rextsize;
4039 } else
4040 rtextsize = 0;
4041 4020
4042 if ((error = XFS_QM_DQATTACH(mp, ip, 0))) 4021 if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
4043 return error; 4022 return error;
@@ -4048,8 +4027,8 @@ xfs_alloc_file_space(
4048 count = len; 4027 count = len;
4049 error = 0; 4028 error = 0;
4050 imapp = &imaps[0]; 4029 imapp = &imaps[0];
4051 reccount = 1; 4030 nimaps = 1;
4052 xfs_bmapi_flags = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); 4031 bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
4053 startoffset_fsb = XFS_B_TO_FSBT(mp, offset); 4032 startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
4054 allocatesize_fsb = XFS_B_TO_FSB(mp, count); 4033 allocatesize_fsb = XFS_B_TO_FSB(mp, count);
4055 4034
@@ -4070,43 +4049,51 @@ xfs_alloc_file_space(
4070 } 4049 }
4071 4050
4072 /* 4051 /*
4073 * allocate file space until done or until there is an error 4052 * Allocate file space until done or until there is an error
4074 */ 4053 */
4075retry: 4054retry:
4076 while (allocatesize_fsb && !error) { 4055 while (allocatesize_fsb && !error) {
4056 xfs_fileoff_t s, e;
4057
4077 /* 4058 /*
4078 * determine if reserving space on 4059 * Determine space reservations for data/realtime.
4079 * the data or realtime partition.
4080 */ 4060 */
4081 if (rt) { 4061 if (unlikely(extsz)) {
4082 xfs_fileoff_t s, e;
4083
4084 s = startoffset_fsb; 4062 s = startoffset_fsb;
4085 do_div(s, rtextsize); 4063 do_div(s, extsz);
4086 s *= rtextsize; 4064 s *= extsz;
4087 e = roundup_64(startoffset_fsb + allocatesize_fsb, 4065 e = startoffset_fsb + allocatesize_fsb;
4088 rtextsize); 4066 if ((temp = do_mod(startoffset_fsb, extsz)))
4089 numrtextents = (int)(e - s) / mp->m_sb.sb_rextsize; 4067 e += temp;
4090 datablocks = 0; 4068 if ((temp = do_mod(e, extsz)))
4069 e += extsz - temp;
4070 } else {
4071 s = 0;
4072 e = allocatesize_fsb;
4073 }
4074
4075 if (unlikely(rt)) {
4076 resrtextents = qblocks = (uint)(e - s);
4077 resrtextents /= mp->m_sb.sb_rextsize;
4078 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
4079 quota_flag = XFS_QMOPT_RES_RTBLKS;
4091 } else { 4080 } else {
4092 datablocks = allocatesize_fsb; 4081 resrtextents = 0;
4093 numrtextents = 0; 4082 resblks = qblocks = \
4083 XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
4084 quota_flag = XFS_QMOPT_RES_REGBLKS;
4094 } 4085 }
4095 4086
4096 /* 4087 /*
4097 * allocate and setup the transaction 4088 * Allocate and setup the transaction.
4098 */ 4089 */
4099 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); 4090 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
4100 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); 4091 error = xfs_trans_reserve(tp, resblks,
4101 error = xfs_trans_reserve(tp, 4092 XFS_WRITE_LOG_RES(mp), resrtextents,
4102 resblks,
4103 XFS_WRITE_LOG_RES(mp),
4104 numrtextents,
4105 XFS_TRANS_PERM_LOG_RES, 4093 XFS_TRANS_PERM_LOG_RES,
4106 XFS_WRITE_LOG_COUNT); 4094 XFS_WRITE_LOG_COUNT);
4107
4108 /* 4095 /*
4109 * check for running out of space 4096 * Check for running out of space
4110 */ 4097 */
4111 if (error) { 4098 if (error) {
4112 /* 4099 /*
@@ -4117,8 +4104,8 @@ retry:
4117 break; 4104 break;
4118 } 4105 }
4119 xfs_ilock(ip, XFS_ILOCK_EXCL); 4106 xfs_ilock(ip, XFS_ILOCK_EXCL);
4120 error = XFS_TRANS_RESERVE_QUOTA(mp, tp, 4107 error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
4121 ip->i_udquot, ip->i_gdquot, resblks, 0, 0); 4108 qblocks, 0, quota_flag);
4122 if (error) 4109 if (error)
4123 goto error1; 4110 goto error1;
4124 4111
@@ -4126,19 +4113,19 @@ retry:
4126 xfs_trans_ihold(tp, ip); 4113 xfs_trans_ihold(tp, ip);
4127 4114
4128 /* 4115 /*
4129 * issue the bmapi() call to allocate the blocks 4116 * Issue the xfs_bmapi() call to allocate the blocks
4130 */ 4117 */
4131 XFS_BMAP_INIT(&free_list, &firstfsb); 4118 XFS_BMAP_INIT(&free_list, &firstfsb);
4132 error = xfs_bmapi(tp, ip, startoffset_fsb, 4119 error = xfs_bmapi(tp, ip, startoffset_fsb,
4133 allocatesize_fsb, xfs_bmapi_flags, 4120 allocatesize_fsb, bmapi_flag,
4134 &firstfsb, 0, imapp, &reccount, 4121 &firstfsb, 0, imapp, &nimaps,
4135 &free_list); 4122 &free_list);
4136 if (error) { 4123 if (error) {
4137 goto error0; 4124 goto error0;
4138 } 4125 }
4139 4126
4140 /* 4127 /*
4141 * complete the transaction 4128 * Complete the transaction
4142 */ 4129 */
4143 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); 4130 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
4144 if (error) { 4131 if (error) {
@@ -4153,7 +4140,7 @@ retry:
4153 4140
4154 allocated_fsb = imapp->br_blockcount; 4141 allocated_fsb = imapp->br_blockcount;
4155 4142
4156 if (reccount == 0) { 4143 if (nimaps == 0) {
4157 error = XFS_ERROR(ENOSPC); 4144 error = XFS_ERROR(ENOSPC);
4158 break; 4145 break;
4159 } 4146 }
@@ -4176,9 +4163,11 @@ dmapi_enospc_check:
4176 4163
4177 return error; 4164 return error;
4178 4165
4179 error0: 4166error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
4180 xfs_bmap_cancel(&free_list); 4167 xfs_bmap_cancel(&free_list);
4181 error1: 4168 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
4169
4170error1: /* Just cancel transaction */
4182 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 4171 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
4183 xfs_iunlock(ip, XFS_ILOCK_EXCL); 4172 xfs_iunlock(ip, XFS_ILOCK_EXCL);
4184 goto dmapi_enospc_check; 4173 goto dmapi_enospc_check;
@@ -4423,8 +4412,8 @@ xfs_free_file_space(
4423 } 4412 }
4424 xfs_ilock(ip, XFS_ILOCK_EXCL); 4413 xfs_ilock(ip, XFS_ILOCK_EXCL);
4425 error = XFS_TRANS_RESERVE_QUOTA(mp, tp, 4414 error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
4426 ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? 4415 ip->i_udquot, ip->i_gdquot, resblks, 0,
4427 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); 4416 XFS_QMOPT_RES_REGBLKS);
4428 if (error) 4417 if (error)
4429 goto error1; 4418 goto error1;
4430 4419