diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-08-13 07:08:47 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-13 07:08:47 -0400 |
commit | a12e61df4fa1cfae7a6b76976fa65a6fcb048e3f (patch) | |
tree | 957c915298b299902aa80afa7c78e94c71b3dc25 /fs/xfs/xfs_inode.c | |
parent | 7b27718bdb1b70166383dec91391df5534d449ee (diff) | |
parent | 30a2f3c60a84092c8084dfe788b710f8d0768cd4 (diff) |
Merge commit 'v2.6.27-rc3' into x86/urgent
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 165 |
1 files changed, 62 insertions, 103 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e569bf5d6cf0..bedc66163176 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1763,67 +1763,6 @@ xfs_itruncate_finish( | |||
1763 | return 0; | 1763 | return 0; |
1764 | } | 1764 | } |
1765 | 1765 | ||
1766 | |||
1767 | /* | ||
1768 | * xfs_igrow_start | ||
1769 | * | ||
1770 | * Do the first part of growing a file: zero any data in the last | ||
1771 | * block that is beyond the old EOF. We need to do this before | ||
1772 | * the inode is joined to the transaction to modify the i_size. | ||
1773 | * That way we can drop the inode lock and call into the buffer | ||
1774 | * cache to get the buffer mapping the EOF. | ||
1775 | */ | ||
1776 | int | ||
1777 | xfs_igrow_start( | ||
1778 | xfs_inode_t *ip, | ||
1779 | xfs_fsize_t new_size, | ||
1780 | cred_t *credp) | ||
1781 | { | ||
1782 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); | ||
1783 | ASSERT(new_size > ip->i_size); | ||
1784 | |||
1785 | /* | ||
1786 | * Zero any pages that may have been created by | ||
1787 | * xfs_write_file() beyond the end of the file | ||
1788 | * and any blocks between the old and new file sizes. | ||
1789 | */ | ||
1790 | return xfs_zero_eof(ip, new_size, ip->i_size); | ||
1791 | } | ||
1792 | |||
1793 | /* | ||
1794 | * xfs_igrow_finish | ||
1795 | * | ||
1796 | * This routine is called to extend the size of a file. | ||
1797 | * The inode must have both the iolock and the ilock locked | ||
1798 | * for update and it must be a part of the current transaction. | ||
1799 | * The xfs_igrow_start() function must have been called previously. | ||
1800 | * If the change_flag is not zero, the inode change timestamp will | ||
1801 | * be updated. | ||
1802 | */ | ||
1803 | void | ||
1804 | xfs_igrow_finish( | ||
1805 | xfs_trans_t *tp, | ||
1806 | xfs_inode_t *ip, | ||
1807 | xfs_fsize_t new_size, | ||
1808 | int change_flag) | ||
1809 | { | ||
1810 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); | ||
1811 | ASSERT(ip->i_transp == tp); | ||
1812 | ASSERT(new_size > ip->i_size); | ||
1813 | |||
1814 | /* | ||
1815 | * Update the file size. Update the inode change timestamp | ||
1816 | * if change_flag set. | ||
1817 | */ | ||
1818 | ip->i_d.di_size = new_size; | ||
1819 | ip->i_size = new_size; | ||
1820 | if (change_flag) | ||
1821 | xfs_ichgtime(ip, XFS_ICHGTIME_CHG); | ||
1822 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
1823 | |||
1824 | } | ||
1825 | |||
1826 | |||
1827 | /* | 1766 | /* |
1828 | * This is called when the inode's link count goes to 0. | 1767 | * This is called when the inode's link count goes to 0. |
1829 | * We place the on-disk inode on a list in the AGI. It | 1768 | * We place the on-disk inode on a list in the AGI. It |
@@ -2258,7 +2197,7 @@ xfs_ifree_cluster( | |||
2258 | xfs_trans_binval(tp, bp); | 2197 | xfs_trans_binval(tp, bp); |
2259 | } | 2198 | } |
2260 | 2199 | ||
2261 | kmem_free(ip_found, ninodes * sizeof(xfs_inode_t *)); | 2200 | kmem_free(ip_found); |
2262 | xfs_put_perag(mp, pag); | 2201 | xfs_put_perag(mp, pag); |
2263 | } | 2202 | } |
2264 | 2203 | ||
@@ -2470,7 +2409,7 @@ xfs_iroot_realloc( | |||
2470 | (int)new_size); | 2409 | (int)new_size); |
2471 | memcpy(np, op, new_max * (uint)sizeof(xfs_dfsbno_t)); | 2410 | memcpy(np, op, new_max * (uint)sizeof(xfs_dfsbno_t)); |
2472 | } | 2411 | } |
2473 | kmem_free(ifp->if_broot, ifp->if_broot_bytes); | 2412 | kmem_free(ifp->if_broot); |
2474 | ifp->if_broot = new_broot; | 2413 | ifp->if_broot = new_broot; |
2475 | ifp->if_broot_bytes = (int)new_size; | 2414 | ifp->if_broot_bytes = (int)new_size; |
2476 | ASSERT(ifp->if_broot_bytes <= | 2415 | ASSERT(ifp->if_broot_bytes <= |
@@ -2514,7 +2453,7 @@ xfs_idata_realloc( | |||
2514 | 2453 | ||
2515 | if (new_size == 0) { | 2454 | if (new_size == 0) { |
2516 | if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { | 2455 | if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { |
2517 | kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes); | 2456 | kmem_free(ifp->if_u1.if_data); |
2518 | } | 2457 | } |
2519 | ifp->if_u1.if_data = NULL; | 2458 | ifp->if_u1.if_data = NULL; |
2520 | real_size = 0; | 2459 | real_size = 0; |
@@ -2529,7 +2468,7 @@ xfs_idata_realloc( | |||
2529 | ASSERT(ifp->if_real_bytes != 0); | 2468 | ASSERT(ifp->if_real_bytes != 0); |
2530 | memcpy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data, | 2469 | memcpy(ifp->if_u2.if_inline_data, ifp->if_u1.if_data, |
2531 | new_size); | 2470 | new_size); |
2532 | kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes); | 2471 | kmem_free(ifp->if_u1.if_data); |
2533 | ifp->if_u1.if_data = ifp->if_u2.if_inline_data; | 2472 | ifp->if_u1.if_data = ifp->if_u2.if_inline_data; |
2534 | } | 2473 | } |
2535 | real_size = 0; | 2474 | real_size = 0; |
@@ -2636,7 +2575,7 @@ xfs_idestroy_fork( | |||
2636 | 2575 | ||
2637 | ifp = XFS_IFORK_PTR(ip, whichfork); | 2576 | ifp = XFS_IFORK_PTR(ip, whichfork); |
2638 | if (ifp->if_broot != NULL) { | 2577 | if (ifp->if_broot != NULL) { |
2639 | kmem_free(ifp->if_broot, ifp->if_broot_bytes); | 2578 | kmem_free(ifp->if_broot); |
2640 | ifp->if_broot = NULL; | 2579 | ifp->if_broot = NULL; |
2641 | } | 2580 | } |
2642 | 2581 | ||
@@ -2650,7 +2589,7 @@ xfs_idestroy_fork( | |||
2650 | if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) && | 2589 | if ((ifp->if_u1.if_data != ifp->if_u2.if_inline_data) && |
2651 | (ifp->if_u1.if_data != NULL)) { | 2590 | (ifp->if_u1.if_data != NULL)) { |
2652 | ASSERT(ifp->if_real_bytes != 0); | 2591 | ASSERT(ifp->if_real_bytes != 0); |
2653 | kmem_free(ifp->if_u1.if_data, ifp->if_real_bytes); | 2592 | kmem_free(ifp->if_u1.if_data); |
2654 | ifp->if_u1.if_data = NULL; | 2593 | ifp->if_u1.if_data = NULL; |
2655 | ifp->if_real_bytes = 0; | 2594 | ifp->if_real_bytes = 0; |
2656 | } | 2595 | } |
@@ -3058,7 +2997,7 @@ xfs_iflush_cluster( | |||
3058 | 2997 | ||
3059 | out_free: | 2998 | out_free: |
3060 | read_unlock(&pag->pag_ici_lock); | 2999 | read_unlock(&pag->pag_ici_lock); |
3061 | kmem_free(ilist, ilist_size); | 3000 | kmem_free(ilist); |
3062 | return 0; | 3001 | return 0; |
3063 | 3002 | ||
3064 | 3003 | ||
@@ -3102,7 +3041,7 @@ cluster_corrupt_out: | |||
3102 | * Unlocks the flush lock | 3041 | * Unlocks the flush lock |
3103 | */ | 3042 | */ |
3104 | xfs_iflush_abort(iq); | 3043 | xfs_iflush_abort(iq); |
3105 | kmem_free(ilist, ilist_size); | 3044 | kmem_free(ilist); |
3106 | return XFS_ERROR(EFSCORRUPTED); | 3045 | return XFS_ERROR(EFSCORRUPTED); |
3107 | } | 3046 | } |
3108 | 3047 | ||
@@ -3143,8 +3082,6 @@ xfs_iflush( | |||
3143 | * flush lock and do nothing. | 3082 | * flush lock and do nothing. |
3144 | */ | 3083 | */ |
3145 | if (xfs_inode_clean(ip)) { | 3084 | if (xfs_inode_clean(ip)) { |
3146 | ASSERT((iip != NULL) ? | ||
3147 | !(iip->ili_item.li_flags & XFS_LI_IN_AIL) : 1); | ||
3148 | xfs_ifunlock(ip); | 3085 | xfs_ifunlock(ip); |
3149 | return 0; | 3086 | return 0; |
3150 | } | 3087 | } |
@@ -3836,7 +3773,7 @@ xfs_iext_add_indirect_multi( | |||
3836 | erp = xfs_iext_irec_new(ifp, erp_idx); | 3773 | erp = xfs_iext_irec_new(ifp, erp_idx); |
3837 | } | 3774 | } |
3838 | memmove(&erp->er_extbuf[i], nex2_ep, byte_diff); | 3775 | memmove(&erp->er_extbuf[i], nex2_ep, byte_diff); |
3839 | kmem_free(nex2_ep, byte_diff); | 3776 | kmem_free(nex2_ep); |
3840 | erp->er_extcount += nex2; | 3777 | erp->er_extcount += nex2; |
3841 | xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, nex2); | 3778 | xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, nex2); |
3842 | } | 3779 | } |
@@ -4112,7 +4049,7 @@ xfs_iext_direct_to_inline( | |||
4112 | */ | 4049 | */ |
4113 | memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, | 4050 | memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, |
4114 | nextents * sizeof(xfs_bmbt_rec_t)); | 4051 | nextents * sizeof(xfs_bmbt_rec_t)); |
4115 | kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); | 4052 | kmem_free(ifp->if_u1.if_extents); |
4116 | ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; | 4053 | ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; |
4117 | ifp->if_real_bytes = 0; | 4054 | ifp->if_real_bytes = 0; |
4118 | } | 4055 | } |
@@ -4186,7 +4123,7 @@ xfs_iext_indirect_to_direct( | |||
4186 | ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); | 4123 | ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); |
4187 | 4124 | ||
4188 | ep = ifp->if_u1.if_ext_irec->er_extbuf; | 4125 | ep = ifp->if_u1.if_ext_irec->er_extbuf; |
4189 | kmem_free(ifp->if_u1.if_ext_irec, sizeof(xfs_ext_irec_t)); | 4126 | kmem_free(ifp->if_u1.if_ext_irec); |
4190 | ifp->if_flags &= ~XFS_IFEXTIREC; | 4127 | ifp->if_flags &= ~XFS_IFEXTIREC; |
4191 | ifp->if_u1.if_extents = ep; | 4128 | ifp->if_u1.if_extents = ep; |
4192 | ifp->if_bytes = size; | 4129 | ifp->if_bytes = size; |
@@ -4212,7 +4149,7 @@ xfs_iext_destroy( | |||
4212 | } | 4149 | } |
4213 | ifp->if_flags &= ~XFS_IFEXTIREC; | 4150 | ifp->if_flags &= ~XFS_IFEXTIREC; |
4214 | } else if (ifp->if_real_bytes) { | 4151 | } else if (ifp->if_real_bytes) { |
4215 | kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); | 4152 | kmem_free(ifp->if_u1.if_extents); |
4216 | } else if (ifp->if_bytes) { | 4153 | } else if (ifp->if_bytes) { |
4217 | memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS * | 4154 | memset(ifp->if_u2.if_inline_ext, 0, XFS_INLINE_EXTS * |
4218 | sizeof(xfs_bmbt_rec_t)); | 4155 | sizeof(xfs_bmbt_rec_t)); |
@@ -4483,7 +4420,7 @@ xfs_iext_irec_remove( | |||
4483 | if (erp->er_extbuf) { | 4420 | if (erp->er_extbuf) { |
4484 | xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, | 4421 | xfs_iext_irec_update_extoffs(ifp, erp_idx + 1, |
4485 | -erp->er_extcount); | 4422 | -erp->er_extcount); |
4486 | kmem_free(erp->er_extbuf, XFS_IEXT_BUFSZ); | 4423 | kmem_free(erp->er_extbuf); |
4487 | } | 4424 | } |
4488 | /* Compact extent records */ | 4425 | /* Compact extent records */ |
4489 | erp = ifp->if_u1.if_ext_irec; | 4426 | erp = ifp->if_u1.if_ext_irec; |
@@ -4501,8 +4438,7 @@ xfs_iext_irec_remove( | |||
4501 | xfs_iext_realloc_indirect(ifp, | 4438 | xfs_iext_realloc_indirect(ifp, |
4502 | nlists * sizeof(xfs_ext_irec_t)); | 4439 | nlists * sizeof(xfs_ext_irec_t)); |
4503 | } else { | 4440 | } else { |
4504 | kmem_free(ifp->if_u1.if_ext_irec, | 4441 | kmem_free(ifp->if_u1.if_ext_irec); |
4505 | sizeof(xfs_ext_irec_t)); | ||
4506 | } | 4442 | } |
4507 | ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; | 4443 | ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ; |
4508 | } | 4444 | } |
@@ -4571,7 +4507,7 @@ xfs_iext_irec_compact_pages( | |||
4571 | * so er_extoffs don't get modified in | 4507 | * so er_extoffs don't get modified in |
4572 | * xfs_iext_irec_remove. | 4508 | * xfs_iext_irec_remove. |
4573 | */ | 4509 | */ |
4574 | kmem_free(erp_next->er_extbuf, XFS_IEXT_BUFSZ); | 4510 | kmem_free(erp_next->er_extbuf); |
4575 | erp_next->er_extbuf = NULL; | 4511 | erp_next->er_extbuf = NULL; |
4576 | xfs_iext_irec_remove(ifp, erp_idx + 1); | 4512 | xfs_iext_irec_remove(ifp, erp_idx + 1); |
4577 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | 4513 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; |
@@ -4596,40 +4532,63 @@ xfs_iext_irec_compact_full( | |||
4596 | int nlists; /* number of irec's (ex lists) */ | 4532 | int nlists; /* number of irec's (ex lists) */ |
4597 | 4533 | ||
4598 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); | 4534 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); |
4535 | |||
4599 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | 4536 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; |
4600 | erp = ifp->if_u1.if_ext_irec; | 4537 | erp = ifp->if_u1.if_ext_irec; |
4601 | ep = &erp->er_extbuf[erp->er_extcount]; | 4538 | ep = &erp->er_extbuf[erp->er_extcount]; |
4602 | erp_next = erp + 1; | 4539 | erp_next = erp + 1; |
4603 | ep_next = erp_next->er_extbuf; | 4540 | ep_next = erp_next->er_extbuf; |
4541 | |||
4604 | 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 | */ | ||
4605 | ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; | 4547 | ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; |
4606 | ext_diff = MIN(ext_avail, erp_next->er_extcount); | 4548 | if (ext_avail) { |
4607 | memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); | 4549 | |
4608 | erp->er_extcount += ext_diff; | ||
4609 | erp_next->er_extcount -= ext_diff; | ||
4610 | /* Remove next page */ | ||
4611 | if (erp_next->er_extcount == 0) { | ||
4612 | /* | 4550 | /* |
4613 | * Free page before removing extent record | 4551 | * Copy over as many as possible extent records into |
4614 | * so er_extoffs don't get modified in | 4552 | * the previous page. |
4615 | * xfs_iext_irec_remove. | ||
4616 | */ | 4553 | */ |
4617 | kmem_free(erp_next->er_extbuf, | 4554 | ext_diff = MIN(ext_avail, erp_next->er_extcount); |
4618 | erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); | 4555 | memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); |
4619 | erp_next->er_extbuf = NULL; | 4556 | erp->er_extcount += ext_diff; |
4620 | xfs_iext_irec_remove(ifp, erp_idx + 1); | 4557 | erp_next->er_extcount -= ext_diff; |
4621 | erp = &ifp->if_u1.if_ext_irec[erp_idx]; | 4558 | |
4622 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | 4559 | /* |
4623 | /* Update next page */ | 4560 | * If the next irec is empty now we can simply |
4624 | } else { | 4561 | * remove it. |
4625 | /* Move rest of page up to become next new page */ | 4562 | */ |
4626 | memmove(erp_next->er_extbuf, ep_next, | 4563 | if (erp_next->er_extcount == 0) { |
4627 | erp_next->er_extcount * sizeof(xfs_bmbt_rec_t)); | 4564 | /* |
4628 | ep_next = erp_next->er_extbuf; | 4565 | * Free page before removing extent record |
4629 | memset(&ep_next[erp_next->er_extcount], 0, | 4566 | * so er_extoffs don't get modified in |
4630 | (XFS_LINEAR_EXTS - erp_next->er_extcount) * | 4567 | * xfs_iext_irec_remove. |
4631 | sizeof(xfs_bmbt_rec_t)); | 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 | } | ||
4632 | } | 4590 | } |
4591 | |||
4633 | if (erp->er_extcount == XFS_LINEAR_EXTS) { | 4592 | if (erp->er_extcount == XFS_LINEAR_EXTS) { |
4634 | erp_idx++; | 4593 | erp_idx++; |
4635 | if (erp_idx < nlists) | 4594 | if (erp_idx < nlists) |