diff options
Diffstat (limited to 'fs/xfs/xfs_rw.c')
-rw-r--r-- | fs/xfs/xfs_rw.c | 124 |
1 files changed, 105 insertions, 19 deletions
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index a59c102cf214..defb2febaaf5 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -92,6 +90,90 @@ xfs_write_clear_setuid( | |||
92 | } | 90 | } |
93 | 91 | ||
94 | /* | 92 | /* |
93 | * Handle logging requirements of various synchronous types of write. | ||
94 | */ | ||
95 | int | ||
96 | xfs_write_sync_logforce( | ||
97 | xfs_mount_t *mp, | ||
98 | xfs_inode_t *ip) | ||
99 | { | ||
100 | int error = 0; | ||
101 | |||
102 | /* | ||
103 | * If we're treating this as O_DSYNC and we have not updated the | ||
104 | * size, force the log. | ||
105 | */ | ||
106 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
107 | !(ip->i_update_size)) { | ||
108 | xfs_inode_log_item_t *iip = ip->i_itemp; | ||
109 | |||
110 | /* | ||
111 | * If an allocation transaction occurred | ||
112 | * without extending the size, then we have to force | ||
113 | * the log up the proper point to ensure that the | ||
114 | * allocation is permanent. We can't count on | ||
115 | * the fact that buffered writes lock out direct I/O | ||
116 | * writes - the direct I/O write could have extended | ||
117 | * the size nontransactionally, then finished before | ||
118 | * we started. xfs_write_file will think that the file | ||
119 | * didn't grow but the update isn't safe unless the | ||
120 | * size change is logged. | ||
121 | * | ||
122 | * Force the log if we've committed a transaction | ||
123 | * against the inode or if someone else has and | ||
124 | * the commit record hasn't gone to disk (e.g. | ||
125 | * the inode is pinned). This guarantees that | ||
126 | * all changes affecting the inode are permanent | ||
127 | * when we return. | ||
128 | */ | ||
129 | if (iip && iip->ili_last_lsn) { | ||
130 | xfs_log_force(mp, iip->ili_last_lsn, | ||
131 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
132 | } else if (xfs_ipincount(ip) > 0) { | ||
133 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
134 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
135 | } | ||
136 | |||
137 | } else { | ||
138 | xfs_trans_t *tp; | ||
139 | |||
140 | /* | ||
141 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
142 | * the same way. | ||
143 | * | ||
144 | * If the write was synchronous then we need to make | ||
145 | * sure that the inode modification time is permanent. | ||
146 | * We'll have updated the timestamp above, so here | ||
147 | * we use a synchronous transaction to log the inode. | ||
148 | * It's not fast, but it's necessary. | ||
149 | * | ||
150 | * If this a dsync write and the size got changed | ||
151 | * non-transactionally, then we need to ensure that | ||
152 | * the size change gets logged in a synchronous | ||
153 | * transaction. | ||
154 | */ | ||
155 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
156 | if ((error = xfs_trans_reserve(tp, 0, | ||
157 | XFS_SWRITE_LOG_RES(mp), | ||
158 | 0, 0, 0))) { | ||
159 | /* Transaction reserve failed */ | ||
160 | xfs_trans_cancel(tp, 0); | ||
161 | } else { | ||
162 | /* Transaction reserve successful */ | ||
163 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
164 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
165 | xfs_trans_ihold(tp, ip); | ||
166 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
167 | xfs_trans_set_sync(tp); | ||
168 | error = xfs_trans_commit(tp, 0, NULL); | ||
169 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | return error; | ||
174 | } | ||
175 | |||
176 | /* | ||
95 | * Force a shutdown of the filesystem instantly while keeping | 177 | * Force a shutdown of the filesystem instantly while keeping |
96 | * the filesystem consistent. We don't do an unmount here; just shutdown | 178 | * the filesystem consistent. We don't do an unmount here; just shutdown |
97 | * the shop, make sure that absolutely nothing persistent happens to | 179 | * the shop, make sure that absolutely nothing persistent happens to |
@@ -109,12 +191,12 @@ xfs_do_force_shutdown( | |||
109 | xfs_mount_t *mp; | 191 | xfs_mount_t *mp; |
110 | 192 | ||
111 | mp = XFS_BHVTOM(bdp); | 193 | mp = XFS_BHVTOM(bdp); |
112 | logerror = flags & XFS_LOG_IO_ERROR; | 194 | logerror = flags & SHUTDOWN_LOG_IO_ERROR; |
113 | 195 | ||
114 | if (!(flags & XFS_FORCE_UMOUNT)) { | 196 | if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
115 | cmn_err(CE_NOTE, | 197 | cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " |
116 | "xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%p", | 198 | "line %d of file %s. Return address = 0x%p", |
117 | mp->m_fsname,flags,lnnum,fname,__return_address); | 199 | mp->m_fsname, flags, lnnum, fname, __return_address); |
118 | } | 200 | } |
119 | /* | 201 | /* |
120 | * No need to duplicate efforts. | 202 | * No need to duplicate efforts. |
@@ -125,33 +207,37 @@ xfs_do_force_shutdown( | |||
125 | /* | 207 | /* |
126 | * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't | 208 | * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't |
127 | * queue up anybody new on the log reservations, and wakes up | 209 | * queue up anybody new on the log reservations, and wakes up |
128 | * everybody who's sleeping on log reservations and tells | 210 | * everybody who's sleeping on log reservations to tell them |
129 | * them the bad news. | 211 | * the bad news. |
130 | */ | 212 | */ |
131 | if (xfs_log_force_umount(mp, logerror)) | 213 | if (xfs_log_force_umount(mp, logerror)) |
132 | return; | 214 | return; |
133 | 215 | ||
134 | if (flags & XFS_CORRUPT_INCORE) { | 216 | if (flags & SHUTDOWN_CORRUPT_INCORE) { |
135 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, | 217 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, |
136 | "Corruption of in-memory data detected. Shutting down filesystem: %s", | 218 | "Corruption of in-memory data detected. Shutting down filesystem: %s", |
137 | mp->m_fsname); | 219 | mp->m_fsname); |
138 | if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { | 220 | if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { |
139 | xfs_stack_trace(); | 221 | xfs_stack_trace(); |
140 | } | 222 | } |
141 | } else if (!(flags & XFS_FORCE_UMOUNT)) { | 223 | } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
142 | if (logerror) { | 224 | if (logerror) { |
143 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, | 225 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, |
144 | "Log I/O Error Detected. Shutting down filesystem: %s", | 226 | "Log I/O Error Detected. Shutting down filesystem: %s", |
227 | mp->m_fsname); | ||
228 | } else if (flags & SHUTDOWN_DEVICE_REQ) { | ||
229 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, | ||
230 | "All device paths lost. Shutting down filesystem: %s", | ||
145 | mp->m_fsname); | 231 | mp->m_fsname); |
146 | } else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) { | 232 | } else if (!(flags & SHUTDOWN_REMOTE_REQ)) { |
147 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, | 233 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, |
148 | "I/O Error Detected. Shutting down filesystem: %s", | 234 | "I/O Error Detected. Shutting down filesystem: %s", |
149 | mp->m_fsname); | 235 | mp->m_fsname); |
150 | } | 236 | } |
151 | } | 237 | } |
152 | if (!(flags & XFS_FORCE_UMOUNT)) { | 238 | if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
153 | cmn_err(CE_ALERT, | 239 | cmn_err(CE_ALERT, "Please umount the filesystem, " |
154 | "Please umount the filesystem, and rectify the problem(s)"); | 240 | "and rectify the problem(s)"); |
155 | } | 241 | } |
156 | } | 242 | } |
157 | 243 | ||
@@ -335,7 +421,7 @@ xfs_bwrite( | |||
335 | * from bwrite and we could be tracing a buffer that has | 421 | * from bwrite and we could be tracing a buffer that has |
336 | * been reused. | 422 | * been reused. |
337 | */ | 423 | */ |
338 | xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); | 424 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); |
339 | } | 425 | } |
340 | return (error); | 426 | return (error); |
341 | } | 427 | } |