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++; |
