aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_fsops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_fsops.c')
-rw-r--r--fs/xfs/xfs_fsops.c69
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);