diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
| -rw-r--r-- | fs/xfs/xfs_vnodeops.c | 144 |
1 files changed, 62 insertions, 82 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 58bfe629b933..7c1f74531463 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -1,40 +1,26 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
| 3 | * All Rights Reserved. | ||
| 3 | * | 4 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or |
| 5 | * under the terms of version 2 of the GNU General Public License as | 6 | * modify it under the terms of the GNU General Public License as |
| 6 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
| 7 | * | 8 | * |
| 8 | * This program is distributed in the hope that it would be useful, but | 9 | * This program is distributed in the hope that it would be useful, |
| 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. | ||
| 11 | * | 13 | * |
| 12 | * Further, this software is distributed without any warranty that it is | 14 | * You should have received a copy of the GNU General Public License |
| 13 | * free of the rightful claim of any third person regarding infringement | 15 | * along with this program; if not, write the Free Software Foundation, |
| 14 | * or the like. Any license provided herein, whether implied or | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 15 | * otherwise, applies only to this software file. Patent licenses, if | ||
| 16 | * any, provided herein do not apply to combinations of this program with | ||
| 17 | * other software, or any other product whatsoever. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | ||
| 21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
| 22 | * | ||
| 23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | ||
| 24 | * Mountain View, CA 94043, or: | ||
| 25 | * | ||
| 26 | * http://www.sgi.com | ||
| 27 | * | ||
| 28 | * For further information regarding this notice, see: | ||
| 29 | * | ||
| 30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | ||
| 31 | */ | 17 | */ |
| 32 | |||
| 33 | #include "xfs.h" | 18 | #include "xfs.h" |
| 34 | #include "xfs_macros.h" | 19 | #include "xfs_fs.h" |
| 35 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
| 36 | #include "xfs_inum.h" | 21 | #include "xfs_bit.h" |
| 37 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
| 23 | #include "xfs_inum.h" | ||
| 38 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
| 39 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
| 40 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
| @@ -42,33 +28,32 @@ | |||
| 42 | #include "xfs_dir2.h" | 28 | #include "xfs_dir2.h" |
| 43 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
| 44 | #include "xfs_mount.h" | 30 | #include "xfs_mount.h" |
| 45 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_da_btree.h" |
| 46 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
| 33 | #include "xfs_alloc_btree.h" | ||
| 47 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
| 48 | #include "xfs_itable.h" | ||
| 49 | #include "xfs_btree.h" | ||
| 50 | #include "xfs_ialloc.h" | ||
| 51 | #include "xfs_alloc.h" | ||
| 52 | #include "xfs_attr_sf.h" | ||
| 53 | #include "xfs_dir_sf.h" | 35 | #include "xfs_dir_sf.h" |
| 54 | #include "xfs_dir2_sf.h" | 36 | #include "xfs_dir2_sf.h" |
| 37 | #include "xfs_attr_sf.h" | ||
| 55 | #include "xfs_dinode.h" | 38 | #include "xfs_dinode.h" |
| 56 | #include "xfs_inode_item.h" | ||
| 57 | #include "xfs_inode.h" | 39 | #include "xfs_inode.h" |
| 40 | #include "xfs_inode_item.h" | ||
| 41 | #include "xfs_dir_leaf.h" | ||
| 42 | #include "xfs_itable.h" | ||
| 43 | #include "xfs_btree.h" | ||
| 44 | #include "xfs_ialloc.h" | ||
| 45 | #include "xfs_alloc.h" | ||
| 58 | #include "xfs_bmap.h" | 46 | #include "xfs_bmap.h" |
| 59 | #include "xfs_da_btree.h" | ||
| 60 | #include "xfs_attr.h" | 47 | #include "xfs_attr.h" |
| 61 | #include "xfs_rw.h" | 48 | #include "xfs_rw.h" |
| 62 | #include "xfs_refcache.h" | ||
| 63 | #include "xfs_error.h" | 49 | #include "xfs_error.h" |
| 64 | #include "xfs_bit.h" | ||
| 65 | #include "xfs_rtalloc.h" | ||
| 66 | #include "xfs_quota.h" | 50 | #include "xfs_quota.h" |
| 67 | #include "xfs_utils.h" | 51 | #include "xfs_utils.h" |
| 52 | #include "xfs_rtalloc.h" | ||
| 53 | #include "xfs_refcache.h" | ||
| 68 | #include "xfs_trans_space.h" | 54 | #include "xfs_trans_space.h" |
| 69 | #include "xfs_dir_leaf.h" | ||
| 70 | #include "xfs_mac.h" | ||
| 71 | #include "xfs_log_priv.h" | 55 | #include "xfs_log_priv.h" |
| 56 | #include "xfs_mac.h" | ||
| 72 | 57 | ||
| 73 | 58 | ||
| 74 | /* | 59 | /* |
| @@ -181,40 +166,7 @@ xfs_getattr( | |||
| 181 | vap->va_rdev = 0; | 166 | vap->va_rdev = 0; |
| 182 | 167 | ||
| 183 | if (!(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) { | 168 | if (!(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) { |
| 184 | 169 | vap->va_blocksize = xfs_preferred_iosize(mp); | |
| 185 | #if 0 | ||
| 186 | /* Large block sizes confuse various | ||
| 187 | * user space programs, so letting the | ||
| 188 | * stripe size through is not a good | ||
| 189 | * idea for now. | ||
| 190 | */ | ||
| 191 | vap->va_blocksize = mp->m_swidth ? | ||
| 192 | /* | ||
| 193 | * If the underlying volume is a stripe, then | ||
| 194 | * return the stripe width in bytes as the | ||
| 195 | * recommended I/O size. | ||
| 196 | */ | ||
| 197 | (mp->m_swidth << mp->m_sb.sb_blocklog) : | ||
| 198 | /* | ||
| 199 | * Return the largest of the preferred buffer | ||
| 200 | * sizes since doing small I/Os into larger | ||
| 201 | * buffers causes buffers to be decommissioned. | ||
| 202 | * The value returned is in bytes. | ||
| 203 | */ | ||
| 204 | (1 << (int)MAX(mp->m_readio_log, | ||
| 205 | mp->m_writeio_log)); | ||
| 206 | |||
| 207 | #else | ||
| 208 | vap->va_blocksize = | ||
| 209 | /* | ||
| 210 | * Return the largest of the preferred buffer | ||
| 211 | * sizes since doing small I/Os into larger | ||
| 212 | * buffers causes buffers to be decommissioned. | ||
| 213 | * The value returned is in bytes. | ||
| 214 | */ | ||
| 215 | 1 << (int)MAX(mp->m_readio_log, | ||
| 216 | mp->m_writeio_log); | ||
| 217 | #endif | ||
| 218 | } else { | 170 | } else { |
| 219 | 171 | ||
| 220 | /* | 172 | /* |
| @@ -581,8 +533,7 @@ xfs_setattr( | |||
| 581 | /* | 533 | /* |
| 582 | * Can't change extent size if any extents are allocated. | 534 | * Can't change extent size if any extents are allocated. |
| 583 | */ | 535 | */ |
| 584 | if ((ip->i_d.di_nextents || ip->i_delayed_blks) && | 536 | if (ip->i_d.di_nextents && (mask & XFS_AT_EXTSIZE) && |
| 585 | (mask & XFS_AT_EXTSIZE) && | ||
| 586 | ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != | 537 | ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) != |
| 587 | vap->va_extsize) ) { | 538 | vap->va_extsize) ) { |
| 588 | code = XFS_ERROR(EINVAL); /* EFBIG? */ | 539 | code = XFS_ERROR(EINVAL); /* EFBIG? */ |
| @@ -610,7 +561,8 @@ xfs_setattr( | |||
| 610 | /* | 561 | /* |
| 611 | * Can't change realtime flag if any extents are allocated. | 562 | * Can't change realtime flag if any extents are allocated. |
| 612 | */ | 563 | */ |
| 613 | if (ip->i_d.di_nextents && (mask & XFS_AT_XFLAGS) && | 564 | if ((ip->i_d.di_nextents || ip->i_delayed_blks) && |
| 565 | (mask & XFS_AT_XFLAGS) && | ||
| 614 | (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != | 566 | (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != |
| 615 | (vap->va_xflags & XFS_XFLAG_REALTIME)) { | 567 | (vap->va_xflags & XFS_XFLAG_REALTIME)) { |
| 616 | code = XFS_ERROR(EINVAL); /* EFBIG? */ | 568 | code = XFS_ERROR(EINVAL); /* EFBIG? */ |
| @@ -674,8 +626,10 @@ xfs_setattr( | |||
| 674 | */ | 626 | */ |
| 675 | if (mask & XFS_AT_SIZE) { | 627 | if (mask & XFS_AT_SIZE) { |
| 676 | code = 0; | 628 | code = 0; |
| 677 | if (vap->va_size > ip->i_d.di_size) | 629 | if ((vap->va_size > ip->i_d.di_size) && |
| 630 | (flags & ATTR_NOSIZETOK) == 0) { | ||
| 678 | code = xfs_igrow_start(ip, vap->va_size, credp); | 631 | code = xfs_igrow_start(ip, vap->va_size, credp); |
| 632 | } | ||
| 679 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 633 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 680 | if (!code) | 634 | if (!code) |
| 681 | code = xfs_itruncate_data(ip, vap->va_size); | 635 | code = xfs_itruncate_data(ip, vap->va_size); |
| @@ -1118,6 +1072,7 @@ xfs_fsync( | |||
| 1118 | xfs_inode_t *ip; | 1072 | xfs_inode_t *ip; |
| 1119 | xfs_trans_t *tp; | 1073 | xfs_trans_t *tp; |
| 1120 | int error; | 1074 | int error; |
| 1075 | int log_flushed = 0, changed = 1; | ||
| 1121 | 1076 | ||
| 1122 | vn_trace_entry(BHV_TO_VNODE(bdp), | 1077 | vn_trace_entry(BHV_TO_VNODE(bdp), |
| 1123 | __FUNCTION__, (inst_t *)__return_address); | 1078 | __FUNCTION__, (inst_t *)__return_address); |
| @@ -1171,10 +1126,18 @@ xfs_fsync( | |||
| 1171 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 1126 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
| 1172 | 1127 | ||
| 1173 | if (xfs_ipincount(ip)) { | 1128 | if (xfs_ipincount(ip)) { |
| 1174 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, | 1129 | _xfs_log_force(ip->i_mount, (xfs_lsn_t)0, |
| 1175 | XFS_LOG_FORCE | | 1130 | XFS_LOG_FORCE | |
| 1176 | ((flag & FSYNC_WAIT) | 1131 | ((flag & FSYNC_WAIT) |
| 1177 | ? XFS_LOG_SYNC : 0)); | 1132 | ? XFS_LOG_SYNC : 0), |
| 1133 | &log_flushed); | ||
| 1134 | } else { | ||
| 1135 | /* | ||
| 1136 | * If the inode is not pinned and nothing | ||
| 1137 | * has changed we don't need to flush the | ||
| 1138 | * cache. | ||
| 1139 | */ | ||
| 1140 | changed = 0; | ||
| 1178 | } | 1141 | } |
| 1179 | error = 0; | 1142 | error = 0; |
| 1180 | } else { | 1143 | } else { |
| @@ -1210,10 +1173,27 @@ xfs_fsync( | |||
| 1210 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 1173 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
| 1211 | if (flag & FSYNC_WAIT) | 1174 | if (flag & FSYNC_WAIT) |
| 1212 | xfs_trans_set_sync(tp); | 1175 | xfs_trans_set_sync(tp); |
| 1213 | error = xfs_trans_commit(tp, 0, NULL); | 1176 | error = _xfs_trans_commit(tp, 0, NULL, &log_flushed); |
| 1214 | 1177 | ||
| 1215 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 1178 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
| 1216 | } | 1179 | } |
| 1180 | |||
| 1181 | if ((ip->i_mount->m_flags & XFS_MOUNT_BARRIER) && changed) { | ||
| 1182 | /* | ||
| 1183 | * If the log write didn't issue an ordered tag we need | ||
| 1184 | * to flush the disk cache for the data device now. | ||
| 1185 | */ | ||
| 1186 | if (!log_flushed) | ||
| 1187 | xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); | ||
| 1188 | |||
| 1189 | /* | ||
| 1190 | * If this inode is on the RT dev we need to flush that | ||
| 1191 | * cache aswell. | ||
| 1192 | */ | ||
| 1193 | if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) | ||
| 1194 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); | ||
| 1195 | } | ||
| 1196 | |||
| 1217 | return error; | 1197 | return error; |
| 1218 | } | 1198 | } |
| 1219 | 1199 | ||
