diff options
Diffstat (limited to 'fs/xfs/xfs_rw.c')
-rw-r--r-- | fs/xfs/xfs_rw.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index d33e4f5808e5..c55e28189aba 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 |
@@ -92,6 +92,90 @@ xfs_write_clear_setuid( | |||
92 | } | 92 | } |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * Handle logging requirements of various synchronous types of write. | ||
96 | */ | ||
97 | int | ||
98 | xfs_write_sync_logforce( | ||
99 | xfs_mount_t *mp, | ||
100 | xfs_inode_t *ip) | ||
101 | { | ||
102 | int error = 0; | ||
103 | |||
104 | /* | ||
105 | * If we're treating this as O_DSYNC and we have not updated the | ||
106 | * size, force the log. | ||
107 | */ | ||
108 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
109 | !(ip->i_update_size)) { | ||
110 | xfs_inode_log_item_t *iip = ip->i_itemp; | ||
111 | |||
112 | /* | ||
113 | * If an allocation transaction occurred | ||
114 | * without extending the size, then we have to force | ||
115 | * the log up the proper point to ensure that the | ||
116 | * allocation is permanent. We can't count on | ||
117 | * the fact that buffered writes lock out direct I/O | ||
118 | * writes - the direct I/O write could have extended | ||
119 | * the size nontransactionally, then finished before | ||
120 | * we started. xfs_write_file will think that the file | ||
121 | * didn't grow but the update isn't safe unless the | ||
122 | * size change is logged. | ||
123 | * | ||
124 | * Force the log if we've committed a transaction | ||
125 | * against the inode or if someone else has and | ||
126 | * the commit record hasn't gone to disk (e.g. | ||
127 | * the inode is pinned). This guarantees that | ||
128 | * all changes affecting the inode are permanent | ||
129 | * when we return. | ||
130 | */ | ||
131 | if (iip && iip->ili_last_lsn) { | ||
132 | xfs_log_force(mp, iip->ili_last_lsn, | ||
133 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
134 | } else if (xfs_ipincount(ip) > 0) { | ||
135 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
136 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
137 | } | ||
138 | |||
139 | } else { | ||
140 | xfs_trans_t *tp; | ||
141 | |||
142 | /* | ||
143 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
144 | * the same way. | ||
145 | * | ||
146 | * If the write was synchronous then we need to make | ||
147 | * sure that the inode modification time is permanent. | ||
148 | * We'll have updated the timestamp above, so here | ||
149 | * we use a synchronous transaction to log the inode. | ||
150 | * It's not fast, but it's necessary. | ||
151 | * | ||
152 | * If this a dsync write and the size got changed | ||
153 | * non-transactionally, then we need to ensure that | ||
154 | * the size change gets logged in a synchronous | ||
155 | * transaction. | ||
156 | */ | ||
157 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
158 | if ((error = xfs_trans_reserve(tp, 0, | ||
159 | XFS_SWRITE_LOG_RES(mp), | ||
160 | 0, 0, 0))) { | ||
161 | /* Transaction reserve failed */ | ||
162 | xfs_trans_cancel(tp, 0); | ||
163 | } else { | ||
164 | /* Transaction reserve successful */ | ||
165 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
166 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
167 | xfs_trans_ihold(tp, ip); | ||
168 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
169 | xfs_trans_set_sync(tp); | ||
170 | error = xfs_trans_commit(tp, 0, NULL); | ||
171 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | return error; | ||
176 | } | ||
177 | |||
178 | /* | ||
95 | * Force a shutdown of the filesystem instantly while keeping | 179 | * Force a shutdown of the filesystem instantly while keeping |
96 | * the filesystem consistent. We don't do an unmount here; just shutdown | 180 | * the filesystem consistent. We don't do an unmount here; just shutdown |
97 | * the shop, make sure that absolutely nothing persistent happens to | 181 | * the shop, make sure that absolutely nothing persistent happens to |