diff options
-rw-r--r-- | fs/xfs/xfs_inode_item.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 46cc40131d4a..576fdfe81d60 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -198,6 +198,41 @@ xfs_inode_item_size( | |||
198 | } | 198 | } |
199 | 199 | ||
200 | /* | 200 | /* |
201 | * xfs_inode_item_format_extents - convert in-core extents to on-disk form | ||
202 | * | ||
203 | * For either the data or attr fork in extent format, we need to endian convert | ||
204 | * the in-core extent as we place them into the on-disk inode. In this case, we | ||
205 | * need to do this conversion before we write the extents into the log. Because | ||
206 | * we don't have the disk inode to write into here, we allocate a buffer and | ||
207 | * format the extents into it via xfs_iextents_copy(). We free the buffer in | ||
208 | * the unlock routine after the copy for the log has been made. | ||
209 | * | ||
210 | * In the case of the data fork, the in-core and on-disk fork sizes can be | ||
211 | * different due to delayed allocation extents. We only log on-disk extents | ||
212 | * here, so always use the physical fork size to determine the size of the | ||
213 | * buffer we need to allocate. | ||
214 | */ | ||
215 | STATIC void | ||
216 | xfs_inode_item_format_extents( | ||
217 | struct xfs_inode *ip, | ||
218 | struct xfs_log_iovec *vecp, | ||
219 | int whichfork, | ||
220 | int type) | ||
221 | { | ||
222 | xfs_bmbt_rec_t *ext_buffer; | ||
223 | |||
224 | ext_buffer = kmem_alloc(XFS_IFORK_SIZE(ip, whichfork), KM_SLEEP); | ||
225 | if (whichfork == XFS_DATA_FORK) | ||
226 | ip->i_itemp->ili_extents_buf = ext_buffer; | ||
227 | else | ||
228 | ip->i_itemp->ili_aextents_buf = ext_buffer; | ||
229 | |||
230 | vecp->i_addr = ext_buffer; | ||
231 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, whichfork); | ||
232 | vecp->i_type = type; | ||
233 | } | ||
234 | |||
235 | /* | ||
201 | * This is called to fill in the vector of log iovecs for the | 236 | * This is called to fill in the vector of log iovecs for the |
202 | * given inode log item. It fills the first item with an inode | 237 | * given inode log item. It fills the first item with an inode |
203 | * log format structure, the second with the on-disk inode structure, | 238 | * log format structure, the second with the on-disk inode structure, |
@@ -213,7 +248,6 @@ xfs_inode_item_format( | |||
213 | struct xfs_inode *ip = iip->ili_inode; | 248 | struct xfs_inode *ip = iip->ili_inode; |
214 | uint nvecs; | 249 | uint nvecs; |
215 | size_t data_bytes; | 250 | size_t data_bytes; |
216 | xfs_bmbt_rec_t *ext_buffer; | ||
217 | xfs_mount_t *mp; | 251 | xfs_mount_t *mp; |
218 | 252 | ||
219 | vecp->i_addr = &iip->ili_format; | 253 | vecp->i_addr = &iip->ili_format; |
@@ -320,22 +354,8 @@ xfs_inode_item_format( | |||
320 | } else | 354 | } else |
321 | #endif | 355 | #endif |
322 | { | 356 | { |
323 | /* | 357 | xfs_inode_item_format_extents(ip, vecp, |
324 | * There are delayed allocation extents | 358 | XFS_DATA_FORK, XLOG_REG_TYPE_IEXT); |
325 | * in the inode, or we need to convert | ||
326 | * the extents to on disk format. | ||
327 | * Use xfs_iextents_copy() | ||
328 | * to copy only the real extents into | ||
329 | * a separate buffer. We'll free the | ||
330 | * buffer in the unlock routine. | ||
331 | */ | ||
332 | ext_buffer = kmem_alloc(ip->i_df.if_bytes, | ||
333 | KM_SLEEP); | ||
334 | iip->ili_extents_buf = ext_buffer; | ||
335 | vecp->i_addr = ext_buffer; | ||
336 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, | ||
337 | XFS_DATA_FORK); | ||
338 | vecp->i_type = XLOG_REG_TYPE_IEXT; | ||
339 | } | 359 | } |
340 | ASSERT(vecp->i_len <= ip->i_df.if_bytes); | 360 | ASSERT(vecp->i_len <= ip->i_df.if_bytes); |
341 | iip->ili_format.ilf_dsize = vecp->i_len; | 361 | iip->ili_format.ilf_dsize = vecp->i_len; |
@@ -445,19 +465,12 @@ xfs_inode_item_format( | |||
445 | */ | 465 | */ |
446 | vecp->i_addr = ip->i_afp->if_u1.if_extents; | 466 | vecp->i_addr = ip->i_afp->if_u1.if_extents; |
447 | vecp->i_len = ip->i_afp->if_bytes; | 467 | vecp->i_len = ip->i_afp->if_bytes; |
468 | vecp->i_type = XLOG_REG_TYPE_IATTR_EXT; | ||
448 | #else | 469 | #else |
449 | ASSERT(iip->ili_aextents_buf == NULL); | 470 | ASSERT(iip->ili_aextents_buf == NULL); |
450 | /* | 471 | xfs_inode_item_format_extents(ip, vecp, |
451 | * Need to endian flip before logging | 472 | XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT); |
452 | */ | ||
453 | ext_buffer = kmem_alloc(ip->i_afp->if_bytes, | ||
454 | KM_SLEEP); | ||
455 | iip->ili_aextents_buf = ext_buffer; | ||
456 | vecp->i_addr = ext_buffer; | ||
457 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, | ||
458 | XFS_ATTR_FORK); | ||
459 | #endif | 473 | #endif |
460 | vecp->i_type = XLOG_REG_TYPE_IATTR_EXT; | ||
461 | iip->ili_format.ilf_asize = vecp->i_len; | 474 | iip->ili_format.ilf_asize = vecp->i_len; |
462 | vecp++; | 475 | vecp++; |
463 | nvecs++; | 476 | nvecs++; |