aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2006-01-10 23:28:28 -0500
committerNathan Scott <nathans@sgi.com>2006-01-10 23:28:28 -0500
commitdd9f438e32900d67def49fa1b8961b3e19b6fefc (patch)
treea0a51110a13445f3a27b72303e36ef6ef48db0eb /fs/xfs/xfs_vnodeops.c
parent061f7209bdfb0193b306f88b4ff36b2574b001d3 (diff)
[XFS] Implement the di_extsize allocator hint for non-realtime files as
well. Also provides a mechanism for inheriting this property from the parent directory for new files. SGI-PV: 945264 SGI-Modid: xfs-linux-melb:xfs-kern:24367a Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c158
1 files changed, 75 insertions, 83 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 5f6dce3b4fd6..a2b422c984f2 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -541,24 +541,6 @@ xfs_setattr(
541 } 541 }
542 542
543 /* 543 /*
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. 544 * Can't change realtime flag if any extents are allocated.
563 */ 545 */
564 if ((ip->i_d.di_nextents || ip->i_delayed_blks) && 546 if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
@@ -820,13 +802,17 @@ xfs_setattr(
820 di_flags |= XFS_DIFLAG_RTINHERIT; 802 di_flags |= XFS_DIFLAG_RTINHERIT;
821 if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS) 803 if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
822 di_flags |= XFS_DIFLAG_NOSYMLINKS; 804 di_flags |= XFS_DIFLAG_NOSYMLINKS;
823 } else { 805 if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
806 di_flags |= XFS_DIFLAG_EXTSZINHERIT;
807 } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
824 if (vap->va_xflags & XFS_XFLAG_REALTIME) { 808 if (vap->va_xflags & XFS_XFLAG_REALTIME) {
825 di_flags |= XFS_DIFLAG_REALTIME; 809 di_flags |= XFS_DIFLAG_REALTIME;
826 ip->i_iocore.io_flags |= XFS_IOCORE_RT; 810 ip->i_iocore.io_flags |= XFS_IOCORE_RT;
827 } else { 811 } else {
828 ip->i_iocore.io_flags &= ~XFS_IOCORE_RT; 812 ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
829 } 813 }
814 if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
815 di_flags |= XFS_DIFLAG_EXTSIZE;
830 } 816 }
831 ip->i_d.di_flags = di_flags; 817 ip->i_d.di_flags = di_flags;
832 } 818 }
@@ -1568,7 +1554,8 @@ xfs_release(
1568 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && 1554 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
1569 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && 1555 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 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 */
@@ -1644,9 +1631,10 @@ xfs_inactive(
1644 if (ip->i_d.di_nlink != 0) { 1631 if (ip->i_d.di_nlink != 0) {
1645 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && 1632 if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
1646 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) && 1633 ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) &&
1647 (ip->i_df.if_flags & XFS_IFEXTENTS)) && 1634 (ip->i_df.if_flags & XFS_IFEXTENTS) &&
1648 (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) || 1635 (!(ip->i_d.di_flags &
1649 (ip->i_delayed_blks != 0))) { 1636 (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
1637 (ip->i_delayed_blks != 0)))) {
1650 if ((error = xfs_inactive_free_eofblocks(mp, ip))) 1638 if ((error = xfs_inactive_free_eofblocks(mp, ip)))
1651 return (VN_INACTIVE_CACHE); 1639 return (VN_INACTIVE_CACHE);
1652 /* Update linux inode block count after free above */ 1640 /* Update linux inode block count after free above */
@@ -3998,42 +3986,36 @@ xfs_alloc_file_space(
3998 int alloc_type, 3986 int alloc_type,
3999 int attr_flags) 3987 int attr_flags)
4000{ 3988{
3989 xfs_mount_t *mp = ip->i_mount;
3990 xfs_off_t count;
4001 xfs_filblks_t allocated_fsb; 3991 xfs_filblks_t allocated_fsb;
4002 xfs_filblks_t allocatesize_fsb; 3992 xfs_filblks_t allocatesize_fsb;
4003 int committed; 3993 xfs_extlen_t extsz, temp;
4004 xfs_off_t count; 3994 xfs_fileoff_t startoffset_fsb;
4005 xfs_filblks_t datablocks;
4006 int error;
4007 xfs_fsblock_t firstfsb; 3995 xfs_fsblock_t firstfsb;
4008 xfs_bmap_free_t free_list; 3996 int nimaps;
4009 xfs_bmbt_irec_t *imapp; 3997 int bmapi_flag;
4010 xfs_bmbt_irec_t imaps[1]; 3998 int quota_flag;
4011 xfs_mount_t *mp;
4012 int numrtextents;
4013 int reccount;
4014 uint resblks;
4015 int rt; 3999 int rt;
4016 int rtextsize;
4017 xfs_fileoff_t startoffset_fsb;
4018 xfs_trans_t *tp; 4000 xfs_trans_t *tp;
4019 int xfs_bmapi_flags; 4001 xfs_bmbt_irec_t imaps[1], *imapp;
4002 xfs_bmap_free_t free_list;
4003 uint qblocks, resblks, resrtextents;
4004 int committed;
4005 int error;
4020 4006
4021 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); 4007 vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
4022 mp = ip->i_mount;
4023 4008
4024 if (XFS_FORCED_SHUTDOWN(mp)) 4009 if (XFS_FORCED_SHUTDOWN(mp))
4025 return XFS_ERROR(EIO); 4010 return XFS_ERROR(EIO);
4026 4011
4027 /* 4012 rt = XFS_IS_REALTIME_INODE(ip);
4028 * determine if this is a realtime file 4013 if (unlikely(rt)) {
4029 */ 4014 if (!(extsz = ip->i_d.di_extsize))
4030 if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) { 4015 extsz = mp->m_sb.sb_rextsize;
4031 if (ip->i_d.di_extsize) 4016 } else {
4032 rtextsize = ip->i_d.di_extsize; 4017 extsz = ip->i_d.di_extsize;
4033 else 4018 }
4034 rtextsize = mp->m_sb.sb_rextsize;
4035 } else
4036 rtextsize = 0;
4037 4019
4038 if ((error = XFS_QM_DQATTACH(mp, ip, 0))) 4020 if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
4039 return error; 4021 return error;
@@ -4044,8 +4026,8 @@ xfs_alloc_file_space(
4044 count = len; 4026 count = len;
4045 error = 0; 4027 error = 0;
4046 imapp = &imaps[0]; 4028 imapp = &imaps[0];
4047 reccount = 1; 4029 nimaps = 1;
4048 xfs_bmapi_flags = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); 4030 bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
4049 startoffset_fsb = XFS_B_TO_FSBT(mp, offset); 4031 startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
4050 allocatesize_fsb = XFS_B_TO_FSB(mp, count); 4032 allocatesize_fsb = XFS_B_TO_FSB(mp, count);
4051 4033
@@ -4066,43 +4048,51 @@ xfs_alloc_file_space(
4066 } 4048 }
4067 4049
4068 /* 4050 /*
4069 * allocate file space until done or until there is an error 4051 * Allocate file space until done or until there is an error
4070 */ 4052 */
4071retry: 4053retry:
4072 while (allocatesize_fsb && !error) { 4054 while (allocatesize_fsb && !error) {
4055 xfs_fileoff_t s, e;
4056
4073 /* 4057 /*
4074 * determine if reserving space on 4058 * Determine space reservations for data/realtime,
4075 * the data or realtime partition.
4076 */ 4059 */
4077 if (rt) { 4060 if (unlikely(extsz)) {
4078 xfs_fileoff_t s, e;
4079
4080 s = startoffset_fsb; 4061 s = startoffset_fsb;
4081 do_div(s, rtextsize); 4062 do_div(s, extsz);
4082 s *= rtextsize; 4063 s *= extsz;
4083 e = roundup_64(startoffset_fsb + allocatesize_fsb, 4064 e = startoffset_fsb + allocatesize_fsb;
4084 rtextsize); 4065 if ((temp = do_mod(startoffset_fsb, extsz)))
4085 numrtextents = (int)(e - s) / mp->m_sb.sb_rextsize; 4066 e += temp;
4086 datablocks = 0; 4067 if ((temp = do_mod(e, extsz)))
4068 e += extsz - temp;
4069 } else {
4070 s = 0;
4071 e = allocatesize_fsb;
4072 }
4073
4074 if (unlikely(rt)) {
4075 resrtextents = qblocks = (uint)(e - s);
4076 resrtextents /= mp->m_sb.sb_rextsize;
4077 resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
4078 quota_flag = XFS_QMOPT_RES_RTBLKS;
4087 } else { 4079 } else {
4088 datablocks = allocatesize_fsb; 4080 resrtextents = 0;
4089 numrtextents = 0; 4081 resblks = qblocks = \
4082 XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
4083 quota_flag = XFS_QMOPT_RES_REGBLKS;
4090 } 4084 }
4091 4085
4092 /* 4086 /*
4093 * allocate and setup the transaction 4087 * Allocate and setup the transaction.
4094 */ 4088 */
4095 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); 4089 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
4096 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); 4090 error = xfs_trans_reserve(tp, resblks,
4097 error = xfs_trans_reserve(tp, 4091 XFS_WRITE_LOG_RES(mp), resrtextents,
4098 resblks,
4099 XFS_WRITE_LOG_RES(mp),
4100 numrtextents,
4101 XFS_TRANS_PERM_LOG_RES, 4092 XFS_TRANS_PERM_LOG_RES,
4102 XFS_WRITE_LOG_COUNT); 4093 XFS_WRITE_LOG_COUNT);
4103
4104 /* 4094 /*
4105 * check for running out of space 4095 * Check for running out of space
4106 */ 4096 */
4107 if (error) { 4097 if (error) {
4108 /* 4098 /*
@@ -4113,8 +4103,8 @@ retry:
4113 break; 4103 break;
4114 } 4104 }
4115 xfs_ilock(ip, XFS_ILOCK_EXCL); 4105 xfs_ilock(ip, XFS_ILOCK_EXCL);
4116 error = XFS_TRANS_RESERVE_QUOTA(mp, tp, 4106 error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
4117 ip->i_udquot, ip->i_gdquot, resblks, 0, 0); 4107 qblocks, 0, quota_flag);
4118 if (error) 4108 if (error)
4119 goto error1; 4109 goto error1;
4120 4110
@@ -4122,19 +4112,19 @@ retry:
4122 xfs_trans_ihold(tp, ip); 4112 xfs_trans_ihold(tp, ip);
4123 4113
4124 /* 4114 /*
4125 * issue the bmapi() call to allocate the blocks 4115 * Issue the xfs_bmapi() call to allocate the blocks
4126 */ 4116 */
4127 XFS_BMAP_INIT(&free_list, &firstfsb); 4117 XFS_BMAP_INIT(&free_list, &firstfsb);
4128 error = xfs_bmapi(tp, ip, startoffset_fsb, 4118 error = xfs_bmapi(tp, ip, startoffset_fsb,
4129 allocatesize_fsb, xfs_bmapi_flags, 4119 allocatesize_fsb, bmapi_flag,
4130 &firstfsb, 0, imapp, &reccount, 4120 &firstfsb, 0, imapp, &nimaps,
4131 &free_list); 4121 &free_list);
4132 if (error) { 4122 if (error) {
4133 goto error0; 4123 goto error0;
4134 } 4124 }
4135 4125
4136 /* 4126 /*
4137 * complete the transaction 4127 * Complete the transaction
4138 */ 4128 */
4139 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); 4129 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
4140 if (error) { 4130 if (error) {
@@ -4149,7 +4139,7 @@ retry:
4149 4139
4150 allocated_fsb = imapp->br_blockcount; 4140 allocated_fsb = imapp->br_blockcount;
4151 4141
4152 if (reccount == 0) { 4142 if (nimaps == 0) {
4153 error = XFS_ERROR(ENOSPC); 4143 error = XFS_ERROR(ENOSPC);
4154 break; 4144 break;
4155 } 4145 }
@@ -4172,9 +4162,11 @@ dmapi_enospc_check:
4172 4162
4173 return error; 4163 return error;
4174 4164
4175 error0: 4165error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
4176 xfs_bmap_cancel(&free_list); 4166 xfs_bmap_cancel(&free_list);
4177 error1: 4167 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
4168
4169error1: /* Just cancel transaction */
4178 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 4170 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
4179 xfs_iunlock(ip, XFS_ILOCK_EXCL); 4171 xfs_iunlock(ip, XFS_ILOCK_EXCL);
4180 goto dmapi_enospc_check; 4172 goto dmapi_enospc_check;
@@ -4419,8 +4411,8 @@ xfs_free_file_space(
4419 } 4411 }
4420 xfs_ilock(ip, XFS_ILOCK_EXCL); 4412 xfs_ilock(ip, XFS_ILOCK_EXCL);
4421 error = XFS_TRANS_RESERVE_QUOTA(mp, tp, 4413 error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
4422 ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? 4414 ip->i_udquot, ip->i_gdquot, resblks, 0,
4423 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); 4415 XFS_QMOPT_RES_REGBLKS);
4424 if (error) 4416 if (error)
4425 goto error1; 4417 goto error1;
4426 4418