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 | ||