diff options
-rw-r--r-- | fs/xfs/xfs_inode.c | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index fcb1dcc6f036..bedc66163176 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -4532,39 +4532,63 @@ xfs_iext_irec_compact_full( | |||
4532 | int nlists; /* number of irec's (ex lists) */ | 4532 | int nlists; /* number of irec's (ex lists) */ |
4533 | 4533 | ||
4534 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); | 4534 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); |
4535 | |||
4535 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | 4536 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; |
4536 | erp = ifp->if_u1.if_ext_irec; | 4537 | erp = ifp->if_u1.if_ext_irec; |
4537 | ep = &erp->er_extbuf[erp->er_extcount]; | 4538 | ep = &erp->er_extbuf[erp->er_extcount]; |
4538 | erp_next = erp + 1; | 4539 | erp_next = erp + 1; |
4539 | ep_next = erp_next->er_extbuf; | 4540 | ep_next = erp_next->er_extbuf; |
4541 | |||
4540 | while (erp_idx < nlists - 1) { | 4542 | while (erp_idx < nlists - 1) { |
4543 | /* | ||
4544 | * Check how many extent records are available in this irec. | ||
4545 | * If there is none skip the whole exercise. | ||
4546 | */ | ||
4541 | ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; | 4547 | ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; |
4542 | ext_diff = MIN(ext_avail, erp_next->er_extcount); | 4548 | if (ext_avail) { |
4543 | memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); | 4549 | |
4544 | erp->er_extcount += ext_diff; | ||
4545 | erp_next->er_extcount -= ext_diff; | ||
4546 | /* Remove next page */ | ||
4547 | if (erp_next->er_extcount == 0) { | ||
4548 | /* | 4550 | /* |
4549 | * Free page before removing extent record | 4551 | * Copy over as many as possible extent records into |
4550 | * so er_extoffs don't get modified in | 4552 | * the previous page. |
4551 | * xfs_iext_irec_remove. | ||
4552 | */ | 4553 | */ |
4553 | kmem_free(erp_next->er_extbuf); | 4554 | ext_diff = MIN(ext_avail, erp_next->er_extcount); |
4554 | erp_next->er_extbuf = NULL; | 4555 | memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); |
4555 | xfs_iext_irec_remove(ifp, erp_idx + 1); | 4556 | erp->er_extcount += ext_diff; |
4556 | erp = &ifp->if_u1.if_ext_irec[erp_idx]; | 4557 | erp_next->er_extcount -= ext_diff; |
4557 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | 4558 | |
4558 | /* Update next page */ | 4559 | /* |
4559 | } else { | 4560 | * If the next irec is empty now we can simply |
4560 | /* Move rest of page up to become next new page */ | 4561 | * remove it. |
4561 | memmove(erp_next->er_extbuf, ep_next, | 4562 | */ |
4562 | erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); | 4563 | if (erp_next->er_extcount == 0) { |
4563 | ep_next = erp_next->er_extbuf; | 4564 | /* |
4564 | memset(&ep_next[erp_next->er_extcount], 0, | 4565 | * Free page before removing extent record |
4565 | (XFS_LINEAR_EXTS - erp_next->er_extcount) * | 4566 | * so er_extoffs don't get modified in |
4566 | sizeof(xfs_bmbt_rec_t)); | 4567 | * xfs_iext_irec_remove. |
4568 | */ | ||
4569 | kmem_free(erp_next->er_extbuf); | ||
4570 | erp_next->er_extbuf = NULL; | ||
4571 | xfs_iext_irec_remove(ifp, erp_idx + 1); | ||
4572 | erp = &ifp->if_u1.if_ext_irec[erp_idx]; | ||
4573 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | ||
4574 | |||
4575 | /* | ||
4576 | * If the next irec is not empty move up the content | ||
4577 | * that has not been copied to the previous page to | ||
4578 | * the beggining of this one. | ||
4579 | */ | ||
4580 | } else { | ||
4581 | memmove(erp_next->er_extbuf, &ep_next[ext_diff], | ||
4582 | erp_next->er_extcount * | ||
4583 | sizeof(xfs_bmbt_rec_t)); | ||
4584 | ep_next = erp_next->er_extbuf; | ||
4585 | memset(&ep_next[erp_next->er_extcount], 0, | ||
4586 | (XFS_LINEAR_EXTS - | ||
4587 | erp_next->er_extcount) * | ||
4588 | sizeof(xfs_bmbt_rec_t)); | ||
4589 | } | ||
4567 | } | 4590 | } |
4591 | |||
4568 | if (erp->er_extcount == XFS_LINEAR_EXTS) { | 4592 | if (erp->er_extcount == XFS_LINEAR_EXTS) { |
4569 | erp_idx++; | 4593 | erp_idx++; |
4570 | if (erp_idx < nlists) | 4594 | if (erp_idx < nlists) |