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