aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_ialloc.c
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2013-06-27 02:04:55 -0400
committerBen Myers <bpm@sgi.com>2013-06-27 15:26:21 -0400
commit28c8e41af693e4b5cd2d68218f144cf40ce15781 (patch)
tree79bea3212f87c81509af8acbf92b004f91e4a3eb /fs/xfs/xfs_ialloc.c
parentb8402b4729495ac719a3f532c2e33ac653b222a8 (diff)
xfs: Inode create item recovery
When we find a icreate transaction, we need to get and initialise the buffers in the range that has been passed. Extract and verify the information in the item record, then loop over the range initialising and issuing the buffer writes delayed. Support an arbitrary size range to initialise so that in future when we allocate inodes in much larger chunks all kernels that understand this transaction can still recover them. Signed-off-by: Dave Chinner <david@fromorbit.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_ialloc.c')
-rw-r--r--fs/xfs/xfs_ialloc.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 4345c53c729c..4411565b718b 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -150,12 +150,16 @@ xfs_check_agi_freecount(
150#endif 150#endif
151 151
152/* 152/*
153 * Initialise a new set of inodes. 153 * Initialise a new set of inodes. When called without a transaction context
154 * (e.g. from recovery) we initiate a delayed write of the inode buffers rather
155 * than logging them (which in a transaction context puts them into the AIL
156 * for writeback rather than the xfsbufd queue).
154 */ 157 */
155STATIC int 158STATIC int
156xfs_ialloc_inode_init( 159xfs_ialloc_inode_init(
157 struct xfs_mount *mp, 160 struct xfs_mount *mp,
158 struct xfs_trans *tp, 161 struct xfs_trans *tp,
162 struct list_head *buffer_list,
159 xfs_agnumber_t agno, 163 xfs_agnumber_t agno,
160 xfs_agblock_t agbno, 164 xfs_agblock_t agbno,
161 xfs_agblock_t length, 165 xfs_agblock_t length,
@@ -247,18 +251,33 @@ xfs_ialloc_inode_init(
247 ino++; 251 ino++;
248 uuid_copy(&free->di_uuid, &mp->m_sb.sb_uuid); 252 uuid_copy(&free->di_uuid, &mp->m_sb.sb_uuid);
249 xfs_dinode_calc_crc(mp, free); 253 xfs_dinode_calc_crc(mp, free);
250 } else { 254 } else if (tp) {
251 /* just log the inode core */ 255 /* just log the inode core */
252 xfs_trans_log_buf(tp, fbuf, ioffset, 256 xfs_trans_log_buf(tp, fbuf, ioffset,
253 ioffset + isize - 1); 257 ioffset + isize - 1);
254 } 258 }
255 } 259 }
256 if (version == 3) { 260
257 /* need to log the entire buffer */ 261 if (tp) {
258 xfs_trans_log_buf(tp, fbuf, 0, 262 /*
259 BBTOB(fbuf->b_length) - 1); 263 * Mark the buffer as an inode allocation buffer so it
264 * sticks in AIL at the point of this allocation
265 * transaction. This ensures the they are on disk before
266 * the tail of the log can be moved past this
267 * transaction (i.e. by preventing relogging from moving
268 * it forward in the log).
269 */
270 xfs_trans_inode_alloc_buf(tp, fbuf);
271 if (version == 3) {
272 /* need to log the entire buffer */
273 xfs_trans_log_buf(tp, fbuf, 0,
274 BBTOB(fbuf->b_length) - 1);
275 }
276 } else {
277 fbuf->b_flags |= XBF_DONE;
278 xfs_buf_delwri_queue(fbuf, buffer_list);
279 xfs_buf_relse(fbuf);
260 } 280 }
261 xfs_trans_inode_alloc_buf(tp, fbuf);
262 } 281 }
263 return 0; 282 return 0;
264} 283}
@@ -303,7 +322,7 @@ xfs_ialloc_ag_alloc(
303 * First try to allocate inodes contiguous with the last-allocated 322 * First try to allocate inodes contiguous with the last-allocated
304 * chunk of inodes. If the filesystem is striped, this will fill 323 * chunk of inodes. If the filesystem is striped, this will fill
305 * an entire stripe unit with inodes. 324 * an entire stripe unit with inodes.
306 */ 325 */
307 agi = XFS_BUF_TO_AGI(agbp); 326 agi = XFS_BUF_TO_AGI(agbp);
308 newino = be32_to_cpu(agi->agi_newino); 327 newino = be32_to_cpu(agi->agi_newino);
309 agno = be32_to_cpu(agi->agi_seqno); 328 agno = be32_to_cpu(agi->agi_seqno);
@@ -402,7 +421,7 @@ xfs_ialloc_ag_alloc(
402 * rather than a linear progression to prevent the next generation 421 * rather than a linear progression to prevent the next generation
403 * number from being easily guessable. 422 * number from being easily guessable.
404 */ 423 */
405 error = xfs_ialloc_inode_init(args.mp, tp, agno, args.agbno, 424 error = xfs_ialloc_inode_init(args.mp, tp, NULL, agno, args.agbno,
406 args.len, prandom_u32()); 425 args.len, prandom_u32());
407 426
408 if (error) 427 if (error)