aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_inode.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-08-13 07:08:47 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-13 07:08:47 -0400
commita12e61df4fa1cfae7a6b76976fa65a6fcb048e3f (patch)
tree957c915298b299902aa80afa7c78e94c71b3dc25 /fs/xfs/xfs_inode.c
parent7b27718bdb1b70166383dec91391df5534d449ee (diff)
parent30a2f3c60a84092c8084dfe788b710f8d0768cd4 (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.c165
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 */
1776int
1777xfs_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 */
1803void
1804xfs_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
3059out_free: 2998out_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)