aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_rw.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_rw.c')
-rw-r--r--fs/xfs/xfs_rw.c124
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 */
95int
96xfs_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}