aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-11-12 06:53:59 -0500
committerBen Myers <bpm@sgi.com>2012-11-13 17:40:43 -0500
commitfd23683c3b1ab905cba61ea2981c156f4bf52845 (patch)
tree1ea38537f14d0ff537ff15a97cedd244a18890e9 /fs
parentb64f3a390d3477517cbff7d613e551705540769b (diff)
xfs: growfs: use uncached buffers for new headers
When writing the new AG headers to disk, we can't attach write verifiers because they have a dependency on the struct xfs-perag being attached to the buffer to be fully initialised and growfs can't fully initialise them until later in the process. The simplest way to avoid this problem is to use uncached buffers for writing the new headers. These buffers don't have the xfs-perag attached to them, so it's simple to detect in the write verifier and be able to skip the checks that need the xfs-perag. This enables us to attach the appropriate buffer ops to the buffer and hence calculate CRCs on the way to disk. IT also means that the buffer is torn down immediately, and so the first access to the AG headers will re-read the header from disk and perform full verification of the buffer. This way we also can catch corruptions due to problems that went undetected in growfs. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by Rich Johnston <rjohnston@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_fsops.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index a5034af35db7..2196830bf5c0 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -114,6 +114,26 @@ xfs_fs_geometry(
114 return 0; 114 return 0;
115} 115}
116 116
117static struct xfs_buf *
118xfs_growfs_get_hdr_buf(
119 struct xfs_mount *mp,
120 xfs_daddr_t blkno,
121 size_t numblks,
122 int flags)
123{
124 struct xfs_buf *bp;
125
126 bp = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, flags);
127 if (!bp)
128 return NULL;
129
130 xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
131 bp->b_bn = blkno;
132 bp->b_maps[0].bm_bn = blkno;
133
134 return bp;
135}
136
117static int 137static int
118xfs_growfs_data_private( 138xfs_growfs_data_private(
119 xfs_mount_t *mp, /* mount point for filesystem */ 139 xfs_mount_t *mp, /* mount point for filesystem */
@@ -189,15 +209,15 @@ xfs_growfs_data_private(
189 /* 209 /*
190 * AG freelist header block 210 * AG freelist header block
191 */ 211 */
192 bp = xfs_buf_get(mp->m_ddev_targp, 212 bp = xfs_growfs_get_hdr_buf(mp,
193 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), 213 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
194 XFS_FSS_TO_BB(mp, 1), 0); 214 XFS_FSS_TO_BB(mp, 1), 0);
195 if (!bp) { 215 if (!bp) {
196 error = ENOMEM; 216 error = ENOMEM;
197 goto error0; 217 goto error0;
198 } 218 }
219
199 agf = XFS_BUF_TO_AGF(bp); 220 agf = XFS_BUF_TO_AGF(bp);
200 memset(agf, 0, mp->m_sb.sb_sectsize);
201 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); 221 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
202 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); 222 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
203 agf->agf_seqno = cpu_to_be32(agno); 223 agf->agf_seqno = cpu_to_be32(agno);
@@ -226,15 +246,15 @@ xfs_growfs_data_private(
226 /* 246 /*
227 * AG inode header block 247 * AG inode header block
228 */ 248 */
229 bp = xfs_buf_get(mp->m_ddev_targp, 249 bp = xfs_growfs_get_hdr_buf(mp,
230 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), 250 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
231 XFS_FSS_TO_BB(mp, 1), 0); 251 XFS_FSS_TO_BB(mp, 1), 0);
232 if (!bp) { 252 if (!bp) {
233 error = ENOMEM; 253 error = ENOMEM;
234 goto error0; 254 goto error0;
235 } 255 }
256
236 agi = XFS_BUF_TO_AGI(bp); 257 agi = XFS_BUF_TO_AGI(bp);
237 memset(agi, 0, mp->m_sb.sb_sectsize);
238 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); 258 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);
239 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); 259 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);
240 agi->agi_seqno = cpu_to_be32(agno); 260 agi->agi_seqno = cpu_to_be32(agno);
@@ -255,16 +275,16 @@ xfs_growfs_data_private(
255 /* 275 /*
256 * BNO btree root block 276 * BNO btree root block
257 */ 277 */
258 bp = xfs_buf_get(mp->m_ddev_targp, 278 bp = xfs_growfs_get_hdr_buf(mp,
259 XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), 279 XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)),
260 BTOBB(mp->m_sb.sb_blocksize), 0); 280 BTOBB(mp->m_sb.sb_blocksize), 0);
281
261 if (!bp) { 282 if (!bp) {
262 error = ENOMEM; 283 error = ENOMEM;
263 goto error0; 284 goto error0;
264 } 285 }
265 xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
266 xfs_btree_init_block(mp, bp, XFS_ABTB_MAGIC, 0, 1, 0);
267 286
287 xfs_btree_init_block(mp, bp, XFS_ABTB_MAGIC, 0, 1, 0);
268 arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); 288 arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
269 arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); 289 arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
270 arec->ar_blockcount = cpu_to_be32( 290 arec->ar_blockcount = cpu_to_be32(
@@ -278,16 +298,15 @@ xfs_growfs_data_private(
278 /* 298 /*
279 * CNT btree root block 299 * CNT btree root block
280 */ 300 */
281 bp = xfs_buf_get(mp->m_ddev_targp, 301 bp = xfs_growfs_get_hdr_buf(mp,
282 XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), 302 XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)),
283 BTOBB(mp->m_sb.sb_blocksize), 0); 303 BTOBB(mp->m_sb.sb_blocksize), 0);
284 if (!bp) { 304 if (!bp) {
285 error = ENOMEM; 305 error = ENOMEM;
286 goto error0; 306 goto error0;
287 } 307 }
288 xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
289 xfs_btree_init_block(mp, bp, XFS_ABTC_MAGIC, 0, 1, 0);
290 308
309 xfs_btree_init_block(mp, bp, XFS_ABTC_MAGIC, 0, 1, 0);
291 arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); 310 arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
292 arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); 311 arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
293 arec->ar_blockcount = cpu_to_be32( 312 arec->ar_blockcount = cpu_to_be32(
@@ -302,14 +321,14 @@ xfs_growfs_data_private(
302 /* 321 /*
303 * INO btree root block 322 * INO btree root block
304 */ 323 */
305 bp = xfs_buf_get(mp->m_ddev_targp, 324 bp = xfs_growfs_get_hdr_buf(mp,
306 XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), 325 XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)),
307 BTOBB(mp->m_sb.sb_blocksize), 0); 326 BTOBB(mp->m_sb.sb_blocksize), 0);
308 if (!bp) { 327 if (!bp) {
309 error = ENOMEM; 328 error = ENOMEM;
310 goto error0; 329 goto error0;
311 } 330 }
312 xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); 331
313 xfs_btree_init_block(mp, bp, XFS_IBT_MAGIC, 0, 0, 0); 332 xfs_btree_init_block(mp, bp, XFS_IBT_MAGIC, 0, 0, 0);
314 333
315 error = xfs_bwrite(bp); 334 error = xfs_bwrite(bp);