diff options
Diffstat (limited to 'fs/xfs/xfs_fsops.c')
-rw-r--r-- | fs/xfs/xfs_fsops.c | 141 |
1 files changed, 94 insertions, 47 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 4beaede43277..94eaeedc5498 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -97,7 +97,9 @@ xfs_fs_geometry( | |||
97 | (xfs_sb_version_haslazysbcount(&mp->m_sb) ? | 97 | (xfs_sb_version_haslazysbcount(&mp->m_sb) ? |
98 | XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) | | 98 | XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) | |
99 | (xfs_sb_version_hasattr2(&mp->m_sb) ? | 99 | (xfs_sb_version_hasattr2(&mp->m_sb) ? |
100 | XFS_FSOP_GEOM_FLAGS_ATTR2 : 0); | 100 | XFS_FSOP_GEOM_FLAGS_ATTR2 : 0) | |
101 | (xfs_sb_version_hasprojid32bit(&mp->m_sb) ? | ||
102 | XFS_FSOP_GEOM_FLAGS_PROJID32 : 0); | ||
101 | geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? | 103 | geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? |
102 | mp->m_sb.sb_logsectsize : BBSIZE; | 104 | mp->m_sb.sb_logsectsize : BBSIZE; |
103 | geo->rtsectsize = mp->m_sb.sb_blocksize; | 105 | geo->rtsectsize = mp->m_sb.sb_blocksize; |
@@ -112,18 +114,40 @@ xfs_fs_geometry( | |||
112 | return 0; | 114 | return 0; |
113 | } | 115 | } |
114 | 116 | ||
117 | static struct xfs_buf * | ||
118 | xfs_growfs_get_hdr_buf( | ||
119 | struct xfs_mount *mp, | ||
120 | xfs_daddr_t blkno, | ||
121 | size_t numblks, | ||
122 | int flags, | ||
123 | const struct xfs_buf_ops *ops) | ||
124 | { | ||
125 | struct xfs_buf *bp; | ||
126 | |||
127 | bp = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, flags); | ||
128 | if (!bp) | ||
129 | return NULL; | ||
130 | |||
131 | xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); | ||
132 | bp->b_bn = blkno; | ||
133 | bp->b_maps[0].bm_bn = blkno; | ||
134 | bp->b_ops = ops; | ||
135 | |||
136 | return bp; | ||
137 | } | ||
138 | |||
115 | static int | 139 | static int |
116 | xfs_growfs_data_private( | 140 | xfs_growfs_data_private( |
117 | xfs_mount_t *mp, /* mount point for filesystem */ | 141 | xfs_mount_t *mp, /* mount point for filesystem */ |
118 | xfs_growfs_data_t *in) /* growfs data input struct */ | 142 | xfs_growfs_data_t *in) /* growfs data input struct */ |
119 | { | 143 | { |
120 | xfs_agf_t *agf; | 144 | xfs_agf_t *agf; |
145 | struct xfs_agfl *agfl; | ||
121 | xfs_agi_t *agi; | 146 | xfs_agi_t *agi; |
122 | xfs_agnumber_t agno; | 147 | xfs_agnumber_t agno; |
123 | xfs_extlen_t agsize; | 148 | xfs_extlen_t agsize; |
124 | xfs_extlen_t tmpsize; | 149 | xfs_extlen_t tmpsize; |
125 | xfs_alloc_rec_t *arec; | 150 | xfs_alloc_rec_t *arec; |
126 | struct xfs_btree_block *block; | ||
127 | xfs_buf_t *bp; | 151 | xfs_buf_t *bp; |
128 | int bucket; | 152 | int bucket; |
129 | int dpct; | 153 | int dpct; |
@@ -146,9 +170,14 @@ xfs_growfs_data_private( | |||
146 | dpct = pct - mp->m_sb.sb_imax_pct; | 170 | dpct = pct - mp->m_sb.sb_imax_pct; |
147 | bp = xfs_buf_read_uncached(mp->m_ddev_targp, | 171 | bp = xfs_buf_read_uncached(mp->m_ddev_targp, |
148 | XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1), | 172 | XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1), |
149 | XFS_FSS_TO_BB(mp, 1), 0); | 173 | XFS_FSS_TO_BB(mp, 1), 0, NULL); |
150 | if (!bp) | 174 | if (!bp) |
151 | return EIO; | 175 | return EIO; |
176 | if (bp->b_error) { | ||
177 | int error = bp->b_error; | ||
178 | xfs_buf_relse(bp); | ||
179 | return error; | ||
180 | } | ||
152 | xfs_buf_relse(bp); | 181 | xfs_buf_relse(bp); |
153 | 182 | ||
154 | new = nb; /* use new as a temporary here */ | 183 | new = nb; /* use new as a temporary here */ |
@@ -186,17 +215,18 @@ xfs_growfs_data_private( | |||
186 | nfree = 0; | 215 | nfree = 0; |
187 | for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) { | 216 | for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) { |
188 | /* | 217 | /* |
189 | * AG freelist header block | 218 | * AG freespace header block |
190 | */ | 219 | */ |
191 | bp = xfs_buf_get(mp->m_ddev_targp, | 220 | bp = xfs_growfs_get_hdr_buf(mp, |
192 | XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), | 221 | XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), |
193 | XFS_FSS_TO_BB(mp, 1), 0); | 222 | XFS_FSS_TO_BB(mp, 1), 0, |
223 | &xfs_agf_buf_ops); | ||
194 | if (!bp) { | 224 | if (!bp) { |
195 | error = ENOMEM; | 225 | error = ENOMEM; |
196 | goto error0; | 226 | goto error0; |
197 | } | 227 | } |
228 | |||
198 | agf = XFS_BUF_TO_AGF(bp); | 229 | agf = XFS_BUF_TO_AGF(bp); |
199 | memset(agf, 0, mp->m_sb.sb_sectsize); | ||
200 | agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); | 230 | agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); |
201 | agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); | 231 | agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); |
202 | agf->agf_seqno = cpu_to_be32(agno); | 232 | agf->agf_seqno = cpu_to_be32(agno); |
@@ -223,17 +253,39 @@ xfs_growfs_data_private( | |||
223 | goto error0; | 253 | goto error0; |
224 | 254 | ||
225 | /* | 255 | /* |
256 | * AG freelist header block | ||
257 | */ | ||
258 | bp = xfs_growfs_get_hdr_buf(mp, | ||
259 | XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), | ||
260 | XFS_FSS_TO_BB(mp, 1), 0, | ||
261 | &xfs_agfl_buf_ops); | ||
262 | if (!bp) { | ||
263 | error = ENOMEM; | ||
264 | goto error0; | ||
265 | } | ||
266 | |||
267 | agfl = XFS_BUF_TO_AGFL(bp); | ||
268 | for (bucket = 0; bucket < XFS_AGFL_SIZE(mp); bucket++) | ||
269 | agfl->agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK); | ||
270 | |||
271 | error = xfs_bwrite(bp); | ||
272 | xfs_buf_relse(bp); | ||
273 | if (error) | ||
274 | goto error0; | ||
275 | |||
276 | /* | ||
226 | * AG inode header block | 277 | * AG inode header block |
227 | */ | 278 | */ |
228 | bp = xfs_buf_get(mp->m_ddev_targp, | 279 | bp = xfs_growfs_get_hdr_buf(mp, |
229 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | 280 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), |
230 | XFS_FSS_TO_BB(mp, 1), 0); | 281 | XFS_FSS_TO_BB(mp, 1), 0, |
282 | &xfs_agi_buf_ops); | ||
231 | if (!bp) { | 283 | if (!bp) { |
232 | error = ENOMEM; | 284 | error = ENOMEM; |
233 | goto error0; | 285 | goto error0; |
234 | } | 286 | } |
287 | |||
235 | agi = XFS_BUF_TO_AGI(bp); | 288 | agi = XFS_BUF_TO_AGI(bp); |
236 | memset(agi, 0, mp->m_sb.sb_sectsize); | ||
237 | agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); | 289 | agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); |
238 | agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); | 290 | agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); |
239 | agi->agi_seqno = cpu_to_be32(agno); | 291 | agi->agi_seqno = cpu_to_be32(agno); |
@@ -254,24 +306,22 @@ xfs_growfs_data_private( | |||
254 | /* | 306 | /* |
255 | * BNO btree root block | 307 | * BNO btree root block |
256 | */ | 308 | */ |
257 | bp = xfs_buf_get(mp->m_ddev_targp, | 309 | bp = xfs_growfs_get_hdr_buf(mp, |
258 | XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), | 310 | XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), |
259 | BTOBB(mp->m_sb.sb_blocksize), 0); | 311 | BTOBB(mp->m_sb.sb_blocksize), 0, |
312 | &xfs_allocbt_buf_ops); | ||
313 | |||
260 | if (!bp) { | 314 | if (!bp) { |
261 | error = ENOMEM; | 315 | error = ENOMEM; |
262 | goto error0; | 316 | goto error0; |
263 | } | 317 | } |
264 | block = XFS_BUF_TO_BLOCK(bp); | 318 | |
265 | memset(block, 0, mp->m_sb.sb_blocksize); | 319 | xfs_btree_init_block(mp, bp, XFS_ABTB_MAGIC, 0, 1, 0); |
266 | block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC); | 320 | arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); |
267 | block->bb_level = 0; | ||
268 | block->bb_numrecs = cpu_to_be16(1); | ||
269 | block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK); | ||
270 | block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK); | ||
271 | arec = XFS_ALLOC_REC_ADDR(mp, block, 1); | ||
272 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); | 321 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); |
273 | arec->ar_blockcount = cpu_to_be32( | 322 | arec->ar_blockcount = cpu_to_be32( |
274 | agsize - be32_to_cpu(arec->ar_startblock)); | 323 | agsize - be32_to_cpu(arec->ar_startblock)); |
324 | |||
275 | error = xfs_bwrite(bp); | 325 | error = xfs_bwrite(bp); |
276 | xfs_buf_relse(bp); | 326 | xfs_buf_relse(bp); |
277 | if (error) | 327 | if (error) |
@@ -280,25 +330,22 @@ xfs_growfs_data_private( | |||
280 | /* | 330 | /* |
281 | * CNT btree root block | 331 | * CNT btree root block |
282 | */ | 332 | */ |
283 | bp = xfs_buf_get(mp->m_ddev_targp, | 333 | bp = xfs_growfs_get_hdr_buf(mp, |
284 | XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), | 334 | XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), |
285 | BTOBB(mp->m_sb.sb_blocksize), 0); | 335 | BTOBB(mp->m_sb.sb_blocksize), 0, |
336 | &xfs_allocbt_buf_ops); | ||
286 | if (!bp) { | 337 | if (!bp) { |
287 | error = ENOMEM; | 338 | error = ENOMEM; |
288 | goto error0; | 339 | goto error0; |
289 | } | 340 | } |
290 | block = XFS_BUF_TO_BLOCK(bp); | 341 | |
291 | memset(block, 0, mp->m_sb.sb_blocksize); | 342 | xfs_btree_init_block(mp, bp, XFS_ABTC_MAGIC, 0, 1, 0); |
292 | block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC); | 343 | arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); |
293 | block->bb_level = 0; | ||
294 | block->bb_numrecs = cpu_to_be16(1); | ||
295 | block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK); | ||
296 | block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK); | ||
297 | arec = XFS_ALLOC_REC_ADDR(mp, block, 1); | ||
298 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); | 344 | arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); |
299 | arec->ar_blockcount = cpu_to_be32( | 345 | arec->ar_blockcount = cpu_to_be32( |
300 | agsize - be32_to_cpu(arec->ar_startblock)); | 346 | agsize - be32_to_cpu(arec->ar_startblock)); |
301 | nfree += be32_to_cpu(arec->ar_blockcount); | 347 | nfree += be32_to_cpu(arec->ar_blockcount); |
348 | |||
302 | error = xfs_bwrite(bp); | 349 | error = xfs_bwrite(bp); |
303 | xfs_buf_relse(bp); | 350 | xfs_buf_relse(bp); |
304 | if (error) | 351 | if (error) |
@@ -307,20 +354,17 @@ xfs_growfs_data_private( | |||
307 | /* | 354 | /* |
308 | * INO btree root block | 355 | * INO btree root block |
309 | */ | 356 | */ |
310 | bp = xfs_buf_get(mp->m_ddev_targp, | 357 | bp = xfs_growfs_get_hdr_buf(mp, |
311 | XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), | 358 | XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), |
312 | BTOBB(mp->m_sb.sb_blocksize), 0); | 359 | BTOBB(mp->m_sb.sb_blocksize), 0, |
360 | &xfs_inobt_buf_ops); | ||
313 | if (!bp) { | 361 | if (!bp) { |
314 | error = ENOMEM; | 362 | error = ENOMEM; |
315 | goto error0; | 363 | goto error0; |
316 | } | 364 | } |
317 | block = XFS_BUF_TO_BLOCK(bp); | 365 | |
318 | memset(block, 0, mp->m_sb.sb_blocksize); | 366 | xfs_btree_init_block(mp, bp, XFS_IBT_MAGIC, 0, 0, 0); |
319 | block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC); | 367 | |
320 | block->bb_level = 0; | ||
321 | block->bb_numrecs = 0; | ||
322 | block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK); | ||
323 | block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK); | ||
324 | error = xfs_bwrite(bp); | 368 | error = xfs_bwrite(bp); |
325 | xfs_buf_relse(bp); | 369 | xfs_buf_relse(bp); |
326 | if (error) | 370 | if (error) |
@@ -408,14 +452,16 @@ xfs_growfs_data_private( | |||
408 | if (agno < oagcount) { | 452 | if (agno < oagcount) { |
409 | error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, | 453 | error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, |
410 | XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), | 454 | XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), |
411 | XFS_FSS_TO_BB(mp, 1), 0, &bp); | 455 | XFS_FSS_TO_BB(mp, 1), 0, &bp, |
456 | &xfs_sb_buf_ops); | ||
412 | } else { | 457 | } else { |
413 | bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, | 458 | bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, |
414 | XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), | 459 | XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), |
415 | XFS_FSS_TO_BB(mp, 1), 0); | 460 | XFS_FSS_TO_BB(mp, 1), 0); |
416 | if (bp) | 461 | if (bp) { |
462 | bp->b_ops = &xfs_sb_buf_ops; | ||
417 | xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); | 463 | xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); |
418 | else | 464 | } else |
419 | error = ENOMEM; | 465 | error = ENOMEM; |
420 | } | 466 | } |
421 | 467 | ||
@@ -426,6 +472,7 @@ xfs_growfs_data_private( | |||
426 | break; | 472 | break; |
427 | } | 473 | } |
428 | xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS); | 474 | xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS); |
475 | |||
429 | /* | 476 | /* |
430 | * If we get an error writing out the alternate superblocks, | 477 | * If we get an error writing out the alternate superblocks, |
431 | * just issue a warning and continue. The real work is | 478 | * just issue a warning and continue. The real work is |