diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 119 |
1 files changed, 64 insertions, 55 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 70bc82f65311..79b522779aa4 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include "xfs_refcache.h" | 51 | #include "xfs_refcache.h" |
52 | #include "xfs_trans_space.h" | 52 | #include "xfs_trans_space.h" |
53 | #include "xfs_log_priv.h" | 53 | #include "xfs_log_priv.h" |
54 | #include "xfs_filestream.h" | ||
54 | 55 | ||
55 | STATIC int | 56 | STATIC int |
56 | xfs_open( | 57 | xfs_open( |
@@ -77,36 +78,6 @@ xfs_open( | |||
77 | return 0; | 78 | return 0; |
78 | } | 79 | } |
79 | 80 | ||
80 | STATIC int | ||
81 | xfs_close( | ||
82 | bhv_desc_t *bdp, | ||
83 | int flags, | ||
84 | lastclose_t lastclose, | ||
85 | cred_t *credp) | ||
86 | { | ||
87 | bhv_vnode_t *vp = BHV_TO_VNODE(bdp); | ||
88 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
89 | |||
90 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
91 | return XFS_ERROR(EIO); | ||
92 | |||
93 | if (lastclose != L_TRUE || !VN_ISREG(vp)) | ||
94 | return 0; | ||
95 | |||
96 | /* | ||
97 | * If we previously truncated this file and removed old data in | ||
98 | * the process, we want to initiate "early" writeout on the last | ||
99 | * close. This is an attempt to combat the notorious NULL files | ||
100 | * problem which is particularly noticable from a truncate down, | ||
101 | * buffered (re-)write (delalloc), followed by a crash. What we | ||
102 | * are effectively doing here is significantly reducing the time | ||
103 | * window where we'd otherwise be exposed to that problem. | ||
104 | */ | ||
105 | if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0) | ||
106 | return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE); | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /* | 81 | /* |
111 | * xfs_getattr | 82 | * xfs_getattr |
112 | */ | 83 | */ |
@@ -183,9 +154,8 @@ xfs_getattr( | |||
183 | * realtime extent size or the realtime volume's | 154 | * realtime extent size or the realtime volume's |
184 | * extent size. | 155 | * extent size. |
185 | */ | 156 | */ |
186 | vap->va_blocksize = ip->i_d.di_extsize ? | 157 | vap->va_blocksize = |
187 | (ip->i_d.di_extsize << mp->m_sb.sb_blocklog) : | 158 | xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog; |
188 | (mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog); | ||
189 | } | 159 | } |
190 | break; | 160 | break; |
191 | } | 161 | } |
@@ -814,6 +784,8 @@ xfs_setattr( | |||
814 | di_flags |= XFS_DIFLAG_PROJINHERIT; | 784 | di_flags |= XFS_DIFLAG_PROJINHERIT; |
815 | if (vap->va_xflags & XFS_XFLAG_NODEFRAG) | 785 | if (vap->va_xflags & XFS_XFLAG_NODEFRAG) |
816 | di_flags |= XFS_DIFLAG_NODEFRAG; | 786 | di_flags |= XFS_DIFLAG_NODEFRAG; |
787 | if (vap->va_xflags & XFS_XFLAG_FILESTREAM) | ||
788 | di_flags |= XFS_DIFLAG_FILESTREAM; | ||
817 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { | 789 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { |
818 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) | 790 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) |
819 | di_flags |= XFS_DIFLAG_RTINHERIT; | 791 | di_flags |= XFS_DIFLAG_RTINHERIT; |
@@ -1201,13 +1173,15 @@ xfs_fsync( | |||
1201 | } | 1173 | } |
1202 | 1174 | ||
1203 | /* | 1175 | /* |
1204 | * This is called by xfs_inactive to free any blocks beyond eof, | 1176 | * This is called by xfs_inactive to free any blocks beyond eof |
1205 | * when the link count isn't zero. | 1177 | * when the link count isn't zero and by xfs_dm_punch_hole() when |
1178 | * punching a hole to EOF. | ||
1206 | */ | 1179 | */ |
1207 | STATIC int | 1180 | int |
1208 | xfs_inactive_free_eofblocks( | 1181 | xfs_free_eofblocks( |
1209 | xfs_mount_t *mp, | 1182 | xfs_mount_t *mp, |
1210 | xfs_inode_t *ip) | 1183 | xfs_inode_t *ip, |
1184 | int flags) | ||
1211 | { | 1185 | { |
1212 | xfs_trans_t *tp; | 1186 | xfs_trans_t *tp; |
1213 | int error; | 1187 | int error; |
@@ -1216,6 +1190,7 @@ xfs_inactive_free_eofblocks( | |||
1216 | xfs_filblks_t map_len; | 1190 | xfs_filblks_t map_len; |
1217 | int nimaps; | 1191 | int nimaps; |
1218 | xfs_bmbt_irec_t imap; | 1192 | xfs_bmbt_irec_t imap; |
1193 | int use_iolock = (flags & XFS_FREE_EOF_LOCK); | ||
1219 | 1194 | ||
1220 | /* | 1195 | /* |
1221 | * Figure out if there are any blocks beyond the end | 1196 | * Figure out if there are any blocks beyond the end |
@@ -1256,11 +1231,14 @@ xfs_inactive_free_eofblocks( | |||
1256 | * cache and we can't | 1231 | * cache and we can't |
1257 | * do that within a transaction. | 1232 | * do that within a transaction. |
1258 | */ | 1233 | */ |
1259 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 1234 | if (use_iolock) |
1235 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
1260 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, | 1236 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, |
1261 | ip->i_size); | 1237 | ip->i_size); |
1262 | if (error) { | 1238 | if (error) { |
1263 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 1239 | xfs_trans_cancel(tp, 0); |
1240 | if (use_iolock) | ||
1241 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
1264 | return error; | 1242 | return error; |
1265 | } | 1243 | } |
1266 | 1244 | ||
@@ -1297,7 +1275,8 @@ xfs_inactive_free_eofblocks( | |||
1297 | error = xfs_trans_commit(tp, | 1275 | error = xfs_trans_commit(tp, |
1298 | XFS_TRANS_RELEASE_LOG_RES); | 1276 | XFS_TRANS_RELEASE_LOG_RES); |
1299 | } | 1277 | } |
1300 | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 1278 | xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL) |
1279 | : XFS_ILOCK_EXCL)); | ||
1301 | } | 1280 | } |
1302 | return error; | 1281 | return error; |
1303 | } | 1282 | } |
@@ -1560,6 +1539,31 @@ xfs_release( | |||
1560 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) | 1539 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) |
1561 | return 0; | 1540 | return 0; |
1562 | 1541 | ||
1542 | if (!XFS_FORCED_SHUTDOWN(mp)) { | ||
1543 | /* | ||
1544 | * If we are using filestreams, and we have an unlinked | ||
1545 | * file that we are processing the last close on, then nothing | ||
1546 | * will be able to reopen and write to this file. Purge this | ||
1547 | * inode from the filestreams cache so that it doesn't delay | ||
1548 | * teardown of the inode. | ||
1549 | */ | ||
1550 | if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip)) | ||
1551 | xfs_filestream_deassociate(ip); | ||
1552 | |||
1553 | /* | ||
1554 | * If we previously truncated this file and removed old data | ||
1555 | * in the process, we want to initiate "early" writeout on | ||
1556 | * the last close. This is an attempt to combat the notorious | ||
1557 | * NULL files problem which is particularly noticable from a | ||
1558 | * truncate down, buffered (re-)write (delalloc), followed by | ||
1559 | * a crash. What we are effectively doing here is | ||
1560 | * significantly reducing the time window where we'd otherwise | ||
1561 | * be exposed to that problem. | ||
1562 | */ | ||
1563 | if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0) | ||
1564 | bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE); | ||
1565 | } | ||
1566 | |||
1563 | #ifdef HAVE_REFCACHE | 1567 | #ifdef HAVE_REFCACHE |
1564 | /* If we are in the NFS reference cache then don't do this now */ | 1568 | /* If we are in the NFS reference cache then don't do this now */ |
1565 | if (ip->i_refcache) | 1569 | if (ip->i_refcache) |
@@ -1573,7 +1577,8 @@ xfs_release( | |||
1573 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && | 1577 | (ip->i_df.if_flags & XFS_IFEXTENTS)) && |
1574 | (!(ip->i_d.di_flags & | 1578 | (!(ip->i_d.di_flags & |
1575 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { | 1579 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) { |
1576 | if ((error = xfs_inactive_free_eofblocks(mp, ip))) | 1580 | error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); |
1581 | if (error) | ||
1577 | return error; | 1582 | return error; |
1578 | /* Update linux inode block count after free above */ | 1583 | /* Update linux inode block count after free above */ |
1579 | vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp, | 1584 | vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp, |
@@ -1654,7 +1659,8 @@ xfs_inactive( | |||
1654 | (!(ip->i_d.di_flags & | 1659 | (!(ip->i_d.di_flags & |
1655 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || | 1660 | (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) || |
1656 | (ip->i_delayed_blks != 0)))) { | 1661 | (ip->i_delayed_blks != 0)))) { |
1657 | if ((error = xfs_inactive_free_eofblocks(mp, ip))) | 1662 | error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK); |
1663 | if (error) | ||
1658 | return VN_INACTIVE_CACHE; | 1664 | return VN_INACTIVE_CACHE; |
1659 | /* Update linux inode block count after free above */ | 1665 | /* Update linux inode block count after free above */ |
1660 | vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp, | 1666 | vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp, |
@@ -1680,6 +1686,7 @@ xfs_inactive( | |||
1680 | 1686 | ||
1681 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0); | 1687 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0); |
1682 | if (error) { | 1688 | if (error) { |
1689 | xfs_trans_cancel(tp, 0); | ||
1683 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 1690 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
1684 | return VN_INACTIVE_CACHE; | 1691 | return VN_INACTIVE_CACHE; |
1685 | } | 1692 | } |
@@ -2217,9 +2224,9 @@ static inline int | |||
2217 | xfs_lock_inumorder(int lock_mode, int subclass) | 2224 | xfs_lock_inumorder(int lock_mode, int subclass) |
2218 | { | 2225 | { |
2219 | if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) | 2226 | if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) |
2220 | lock_mode |= (subclass + XFS_IOLOCK_INUMORDER) << XFS_IOLOCK_SHIFT; | 2227 | lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT; |
2221 | if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) | 2228 | if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) |
2222 | lock_mode |= (subclass + XFS_ILOCK_INUMORDER) << XFS_ILOCK_SHIFT; | 2229 | lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT; |
2223 | 2230 | ||
2224 | return lock_mode; | 2231 | return lock_mode; |
2225 | } | 2232 | } |
@@ -2546,6 +2553,15 @@ xfs_remove( | |||
2546 | */ | 2553 | */ |
2547 | xfs_refcache_purge_ip(ip); | 2554 | xfs_refcache_purge_ip(ip); |
2548 | 2555 | ||
2556 | /* | ||
2557 | * If we are using filestreams, kill the stream association. | ||
2558 | * If the file is still open it may get a new one but that | ||
2559 | * will get killed on last close in xfs_close() so we don't | ||
2560 | * have to worry about that. | ||
2561 | */ | ||
2562 | if (link_zero && xfs_inode_is_filestream(ip)) | ||
2563 | xfs_filestream_deassociate(ip); | ||
2564 | |||
2549 | vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); | 2565 | vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); |
2550 | 2566 | ||
2551 | /* | 2567 | /* |
@@ -4047,22 +4063,16 @@ xfs_alloc_file_space( | |||
4047 | if (XFS_FORCED_SHUTDOWN(mp)) | 4063 | if (XFS_FORCED_SHUTDOWN(mp)) |
4048 | return XFS_ERROR(EIO); | 4064 | return XFS_ERROR(EIO); |
4049 | 4065 | ||
4050 | rt = XFS_IS_REALTIME_INODE(ip); | ||
4051 | if (unlikely(rt)) { | ||
4052 | if (!(extsz = ip->i_d.di_extsize)) | ||
4053 | extsz = mp->m_sb.sb_rextsize; | ||
4054 | } else { | ||
4055 | extsz = ip->i_d.di_extsize; | ||
4056 | } | ||
4057 | |||
4058 | if ((error = XFS_QM_DQATTACH(mp, ip, 0))) | 4066 | if ((error = XFS_QM_DQATTACH(mp, ip, 0))) |
4059 | return error; | 4067 | return error; |
4060 | 4068 | ||
4061 | if (len <= 0) | 4069 | if (len <= 0) |
4062 | return XFS_ERROR(EINVAL); | 4070 | return XFS_ERROR(EINVAL); |
4063 | 4071 | ||
4072 | rt = XFS_IS_REALTIME_INODE(ip); | ||
4073 | extsz = xfs_get_extsz_hint(ip); | ||
4074 | |||
4064 | count = len; | 4075 | count = len; |
4065 | error = 0; | ||
4066 | imapp = &imaps[0]; | 4076 | imapp = &imaps[0]; |
4067 | nimaps = 1; | 4077 | nimaps = 1; |
4068 | bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); | 4078 | bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0); |
@@ -4678,7 +4688,6 @@ xfs_change_file_space( | |||
4678 | bhv_vnodeops_t xfs_vnodeops = { | 4688 | bhv_vnodeops_t xfs_vnodeops = { |
4679 | BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), | 4689 | BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), |
4680 | .vop_open = xfs_open, | 4690 | .vop_open = xfs_open, |
4681 | .vop_close = xfs_close, | ||
4682 | .vop_read = xfs_read, | 4691 | .vop_read = xfs_read, |
4683 | #ifdef HAVE_SPLICE | 4692 | #ifdef HAVE_SPLICE |
4684 | .vop_splice_read = xfs_splice_read, | 4693 | .vop_splice_read = xfs_splice_read, |