diff options
Diffstat (limited to 'fs/xfs/xfs_fsops.c')
-rw-r--r-- | fs/xfs/xfs_fsops.c | 69 |
1 files changed, 37 insertions, 32 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 2d0b3e1da9e6..37a6f62c57b6 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include "xfs_rtalloc.h" | 45 | #include "xfs_rtalloc.h" |
46 | #include "xfs_rw.h" | 46 | #include "xfs_rw.h" |
47 | #include "xfs_filestream.h" | 47 | #include "xfs_filestream.h" |
48 | #include "xfs_trace.h" | ||
48 | 49 | ||
49 | /* | 50 | /* |
50 | * File system operations | 51 | * File system operations |
@@ -166,27 +167,14 @@ xfs_growfs_data_private( | |||
166 | } | 167 | } |
167 | new = nb - mp->m_sb.sb_dblocks; | 168 | new = nb - mp->m_sb.sb_dblocks; |
168 | oagcount = mp->m_sb.sb_agcount; | 169 | oagcount = mp->m_sb.sb_agcount; |
169 | if (nagcount > oagcount) { | ||
170 | void *new_perag, *old_perag; | ||
171 | |||
172 | xfs_filestream_flush(mp); | ||
173 | |||
174 | new_perag = kmem_zalloc(sizeof(xfs_perag_t) * nagcount, | ||
175 | KM_MAYFAIL); | ||
176 | if (!new_perag) | ||
177 | return XFS_ERROR(ENOMEM); | ||
178 | |||
179 | down_write(&mp->m_peraglock); | ||
180 | memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount); | ||
181 | old_perag = mp->m_perag; | ||
182 | mp->m_perag = new_perag; | ||
183 | |||
184 | mp->m_flags |= XFS_MOUNT_32BITINODES; | ||
185 | nagimax = xfs_initialize_perag(mp, nagcount); | ||
186 | up_write(&mp->m_peraglock); | ||
187 | 170 | ||
188 | kmem_free(old_perag); | 171 | /* allocate the new per-ag structures */ |
172 | if (nagcount > oagcount) { | ||
173 | error = xfs_initialize_perag(mp, nagcount, &nagimax); | ||
174 | if (error) | ||
175 | return error; | ||
189 | } | 176 | } |
177 | |||
190 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); | 178 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS); |
191 | tp->t_flags |= XFS_TRANS_RESERVE; | 179 | tp->t_flags |= XFS_TRANS_RESERVE; |
192 | if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp), | 180 | if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp), |
@@ -195,14 +183,19 @@ xfs_growfs_data_private( | |||
195 | return error; | 183 | return error; |
196 | } | 184 | } |
197 | 185 | ||
186 | /* | ||
187 | * Write new AG headers to disk. Non-transactional, but written | ||
188 | * synchronously so they are completed prior to the growfs transaction | ||
189 | * being logged. | ||
190 | */ | ||
198 | nfree = 0; | 191 | nfree = 0; |
199 | for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) { | 192 | for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) { |
200 | /* | 193 | /* |
201 | * AG freelist header block | 194 | * AG freelist header block |
202 | */ | 195 | */ |
203 | bp = xfs_buf_get(mp->m_ddev_targp, | 196 | bp = xfs_buf_get(mp->m_ddev_targp, |
204 | XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), | 197 | XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), |
205 | XFS_FSS_TO_BB(mp, 1), 0); | 198 | XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); |
206 | agf = XFS_BUF_TO_AGF(bp); | 199 | agf = XFS_BUF_TO_AGF(bp); |
207 | memset(agf, 0, mp->m_sb.sb_sectsize); | 200 | memset(agf, 0, mp->m_sb.sb_sectsize); |
208 | agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); | 201 | agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); |
@@ -233,8 +226,8 @@ xfs_growfs_data_private( | |||
233 | * AG inode header block | 226 | * AG inode header block |
234 | */ | 227 | */ |
235 | bp = xfs_buf_get(mp->m_ddev_targp, | 228 | bp = xfs_buf_get(mp->m_ddev_targp, |
236 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), | 229 | XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), |
237 | XFS_FSS_TO_BB(mp, 1), 0); | 230 | XFS_FSS_TO_BB(mp, 1), XBF_LOCK | XBF_MAPPED); |
238 | agi = XFS_BUF_TO_AGI(bp); | 231 | agi = XFS_BUF_TO_AGI(bp); |
239 | memset(agi, 0, mp->m_sb.sb_sectsize); | 232 | memset(agi, 0, mp->m_sb.sb_sectsize); |
240 | agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); | 233 | agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); |
@@ -257,8 +250,9 @@ xfs_growfs_data_private( | |||
257 | * BNO btree root block | 250 | * BNO btree root block |
258 | */ | 251 | */ |
259 | bp = xfs_buf_get(mp->m_ddev_targp, | 252 | bp = xfs_buf_get(mp->m_ddev_targp, |
260 | XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), | 253 | XFS_AGB_TO_DADDR(mp, agno, XFS_BNO_BLOCK(mp)), |
261 | BTOBB(mp->m_sb.sb_blocksize), 0); | 254 | BTOBB(mp->m_sb.sb_blocksize), |
255 | XBF_LOCK | XBF_MAPPED); | ||
262 | block = XFS_BUF_TO_BLOCK(bp); | 256 | block = XFS_BUF_TO_BLOCK(bp); |
263 | memset(block, 0, mp->m_sb.sb_blocksize); | 257 | memset(block, 0, mp->m_sb.sb_blocksize); |
264 | block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC); | 258 | block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC); |
@@ -278,8 +272,9 @@ xfs_growfs_data_private( | |||
278 | * CNT btree root block | 272 | * CNT btree root block |
279 | */ | 273 | */ |
280 | bp = xfs_buf_get(mp->m_ddev_targp, | 274 | bp = xfs_buf_get(mp->m_ddev_targp, |
281 | XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), | 275 | XFS_AGB_TO_DADDR(mp, agno, XFS_CNT_BLOCK(mp)), |
282 | BTOBB(mp->m_sb.sb_blocksize), 0); | 276 | BTOBB(mp->m_sb.sb_blocksize), |
277 | XBF_LOCK | XBF_MAPPED); | ||
283 | block = XFS_BUF_TO_BLOCK(bp); | 278 | block = XFS_BUF_TO_BLOCK(bp); |
284 | memset(block, 0, mp->m_sb.sb_blocksize); | 279 | memset(block, 0, mp->m_sb.sb_blocksize); |
285 | block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC); | 280 | block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC); |
@@ -300,8 +295,9 @@ xfs_growfs_data_private( | |||
300 | * INO btree root block | 295 | * INO btree root block |
301 | */ | 296 | */ |
302 | bp = xfs_buf_get(mp->m_ddev_targp, | 297 | bp = xfs_buf_get(mp->m_ddev_targp, |
303 | XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), | 298 | XFS_AGB_TO_DADDR(mp, agno, XFS_IBT_BLOCK(mp)), |
304 | BTOBB(mp->m_sb.sb_blocksize), 0); | 299 | BTOBB(mp->m_sb.sb_blocksize), |
300 | XBF_LOCK | XBF_MAPPED); | ||
305 | block = XFS_BUF_TO_BLOCK(bp); | 301 | block = XFS_BUF_TO_BLOCK(bp); |
306 | memset(block, 0, mp->m_sb.sb_blocksize); | 302 | memset(block, 0, mp->m_sb.sb_blocksize); |
307 | block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC); | 303 | block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC); |
@@ -344,6 +340,7 @@ xfs_growfs_data_private( | |||
344 | be32_add_cpu(&agf->agf_length, new); | 340 | be32_add_cpu(&agf->agf_length, new); |
345 | ASSERT(be32_to_cpu(agf->agf_length) == | 341 | ASSERT(be32_to_cpu(agf->agf_length) == |
346 | be32_to_cpu(agi->agi_length)); | 342 | be32_to_cpu(agi->agi_length)); |
343 | |||
347 | xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH); | 344 | xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH); |
348 | /* | 345 | /* |
349 | * Free the new space. | 346 | * Free the new space. |
@@ -354,6 +351,12 @@ xfs_growfs_data_private( | |||
354 | goto error0; | 351 | goto error0; |
355 | } | 352 | } |
356 | } | 353 | } |
354 | |||
355 | /* | ||
356 | * Update changed superblock fields transactionally. These are not | ||
357 | * seen by the rest of the world until the transaction commit applies | ||
358 | * them atomically to the superblock. | ||
359 | */ | ||
357 | if (nagcount > oagcount) | 360 | if (nagcount > oagcount) |
358 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount); | 361 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount); |
359 | if (nb > mp->m_sb.sb_dblocks) | 362 | if (nb > mp->m_sb.sb_dblocks) |
@@ -364,9 +367,9 @@ xfs_growfs_data_private( | |||
364 | if (dpct) | 367 | if (dpct) |
365 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct); | 368 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct); |
366 | error = xfs_trans_commit(tp, 0); | 369 | error = xfs_trans_commit(tp, 0); |
367 | if (error) { | 370 | if (error) |
368 | return error; | 371 | return error; |
369 | } | 372 | |
370 | /* New allocation groups fully initialized, so update mount struct */ | 373 | /* New allocation groups fully initialized, so update mount struct */ |
371 | if (nagimax) | 374 | if (nagimax) |
372 | mp->m_maxagi = nagimax; | 375 | mp->m_maxagi = nagimax; |
@@ -376,6 +379,8 @@ xfs_growfs_data_private( | |||
376 | mp->m_maxicount = icount << mp->m_sb.sb_inopblog; | 379 | mp->m_maxicount = icount << mp->m_sb.sb_inopblog; |
377 | } else | 380 | } else |
378 | mp->m_maxicount = 0; | 381 | mp->m_maxicount = 0; |
382 | |||
383 | /* update secondary superblocks. */ | ||
379 | for (agno = 1; agno < nagcount; agno++) { | 384 | for (agno = 1; agno < nagcount; agno++) { |
380 | error = xfs_read_buf(mp, mp->m_ddev_targp, | 385 | error = xfs_read_buf(mp, mp->m_ddev_targp, |
381 | XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), | 386 | XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), |
@@ -611,7 +616,7 @@ xfs_fs_log_dummy( | |||
611 | xfs_inode_t *ip; | 616 | xfs_inode_t *ip; |
612 | int error; | 617 | int error; |
613 | 618 | ||
614 | tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); | 619 | tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP); |
615 | error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); | 620 | error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); |
616 | if (error) { | 621 | if (error) { |
617 | xfs_trans_cancel(tp, 0); | 622 | xfs_trans_cancel(tp, 0); |