diff options
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 12 | ||||
-rw-r--r-- | fs/xfs/xfs_ialloc.c | 32 |
2 files changed, 33 insertions, 11 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 61f68768ee84..bfc4e0c26fd3 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -310,13 +310,21 @@ xfs_buf_item_format( | |||
310 | 310 | ||
311 | /* | 311 | /* |
312 | * If it is an inode buffer, transfer the in-memory state to the | 312 | * If it is an inode buffer, transfer the in-memory state to the |
313 | * format flags and clear the in-memory state. We do not transfer | 313 | * format flags and clear the in-memory state. |
314 | * | ||
315 | * For buffer based inode allocation, we do not transfer | ||
314 | * this state if the inode buffer allocation has not yet been committed | 316 | * this state if the inode buffer allocation has not yet been committed |
315 | * to the log as setting the XFS_BLI_INODE_BUF flag will prevent | 317 | * to the log as setting the XFS_BLI_INODE_BUF flag will prevent |
316 | * correct replay of the inode allocation. | 318 | * correct replay of the inode allocation. |
319 | * | ||
320 | * For icreate item based inode allocation, the buffers aren't written | ||
321 | * to the journal during allocation, and hence we should always tag the | ||
322 | * buffer as an inode buffer so that the correct unlinked list replay | ||
323 | * occurs during recovery. | ||
317 | */ | 324 | */ |
318 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { | 325 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { |
319 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | 326 | if (xfs_sb_version_hascrc(&lip->li_mountp->m_sb) || |
327 | !((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | ||
320 | xfs_log_item_in_current_chkpt(lip))) | 328 | xfs_log_item_in_current_chkpt(lip))) |
321 | bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF; | 329 | bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF; |
322 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; | 330 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 4411565b718b..7a0c17d7ec09 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "xfs_bmap.h" | 38 | #include "xfs_bmap.h" |
39 | #include "xfs_cksum.h" | 39 | #include "xfs_cksum.h" |
40 | #include "xfs_buf_item.h" | 40 | #include "xfs_buf_item.h" |
41 | #include "xfs_icreate_item.h" | ||
41 | 42 | ||
42 | 43 | ||
43 | /* | 44 | /* |
@@ -155,7 +156,7 @@ xfs_check_agi_freecount( | |||
155 | * than logging them (which in a transaction context puts them into the AIL | 156 | * than logging them (which in a transaction context puts them into the AIL |
156 | * for writeback rather than the xfsbufd queue). | 157 | * for writeback rather than the xfsbufd queue). |
157 | */ | 158 | */ |
158 | STATIC int | 159 | int |
159 | xfs_ialloc_inode_init( | 160 | xfs_ialloc_inode_init( |
160 | struct xfs_mount *mp, | 161 | struct xfs_mount *mp, |
161 | struct xfs_trans *tp, | 162 | struct xfs_trans *tp, |
@@ -212,6 +213,18 @@ xfs_ialloc_inode_init( | |||
212 | version = 3; | 213 | version = 3; |
213 | ino = XFS_AGINO_TO_INO(mp, agno, | 214 | ino = XFS_AGINO_TO_INO(mp, agno, |
214 | XFS_OFFBNO_TO_AGINO(mp, agbno, 0)); | 215 | XFS_OFFBNO_TO_AGINO(mp, agbno, 0)); |
216 | |||
217 | /* | ||
218 | * log the initialisation that is about to take place as an | ||
219 | * logical operation. This means the transaction does not | ||
220 | * need to log the physical changes to the inode buffers as log | ||
221 | * recovery will know what initialisation is actually needed. | ||
222 | * Hence we only need to log the buffers as "ordered" buffers so | ||
223 | * they track in the AIL as if they were physically logged. | ||
224 | */ | ||
225 | if (tp) | ||
226 | xfs_icreate_log(tp, agno, agbno, XFS_IALLOC_INODES(mp), | ||
227 | mp->m_sb.sb_inodesize, length, gen); | ||
215 | } else if (xfs_sb_version_hasnlink(&mp->m_sb)) | 228 | } else if (xfs_sb_version_hasnlink(&mp->m_sb)) |
216 | version = 2; | 229 | version = 2; |
217 | else | 230 | else |
@@ -227,13 +240,8 @@ xfs_ialloc_inode_init( | |||
227 | XBF_UNMAPPED); | 240 | XBF_UNMAPPED); |
228 | if (!fbuf) | 241 | if (!fbuf) |
229 | return ENOMEM; | 242 | return ENOMEM; |
230 | /* | 243 | |
231 | * Initialize all inodes in this buffer and then log them. | 244 | /* Initialize the inode buffers and log them appropriately. */ |
232 | * | ||
233 | * XXX: It would be much better if we had just one transaction | ||
234 | * to log a whole cluster of inodes instead of all the | ||
235 | * individual transactions causing a lot of log traffic. | ||
236 | */ | ||
237 | fbuf->b_ops = &xfs_inode_buf_ops; | 245 | fbuf->b_ops = &xfs_inode_buf_ops; |
238 | xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length)); | 246 | xfs_buf_zero(fbuf, 0, BBTOB(fbuf->b_length)); |
239 | for (i = 0; i < ninodes; i++) { | 247 | for (i = 0; i < ninodes; i++) { |
@@ -269,7 +277,13 @@ xfs_ialloc_inode_init( | |||
269 | */ | 277 | */ |
270 | xfs_trans_inode_alloc_buf(tp, fbuf); | 278 | xfs_trans_inode_alloc_buf(tp, fbuf); |
271 | if (version == 3) { | 279 | if (version == 3) { |
272 | /* need to log the entire buffer */ | 280 | /* |
281 | * Mark the buffer as ordered so that they are | ||
282 | * not physically logged in the transaction but | ||
283 | * still tracked in the AIL as part of the | ||
284 | * transaction and pin the log appropriately. | ||
285 | */ | ||
286 | xfs_trans_ordered_buf(tp, fbuf); | ||
273 | xfs_trans_log_buf(tp, fbuf, 0, | 287 | xfs_trans_log_buf(tp, fbuf, 0, |
274 | BBTOB(fbuf->b_length) - 1); | 288 | BBTOB(fbuf->b_length) - 1); |
275 | } | 289 | } |