diff options
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 4 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 3 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.h | 8 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 20 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf_item.c | 44 | ||||
| -rw-r--r-- | fs/xfs/xfs_dfrag.c | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 94 | ||||
| -rw-r--r-- | fs/xfs/xfs_log.c | 67 | ||||
| -rw-r--r-- | fs/xfs/xfs_log_priv.h | 1 | ||||
| -rw-r--r-- | fs/xfs/xfs_vnodeops.c | 26 |
10 files changed, 135 insertions, 141 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index f42f80a3b1fa..a44d68eb50b5 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
| @@ -1338,6 +1338,10 @@ __xfs_get_blocks( | |||
| 1338 | offset = (xfs_off_t)iblock << inode->i_blkbits; | 1338 | offset = (xfs_off_t)iblock << inode->i_blkbits; |
| 1339 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); | 1339 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); |
| 1340 | size = bh_result->b_size; | 1340 | size = bh_result->b_size; |
| 1341 | |||
| 1342 | if (!create && direct && offset >= i_size_read(inode)) | ||
| 1343 | return 0; | ||
| 1344 | |||
| 1341 | error = xfs_iomap(XFS_I(inode), offset, size, | 1345 | error = xfs_iomap(XFS_I(inode), offset, size, |
| 1342 | create ? flags : BMAPI_READ, &iomap, &niomap); | 1346 | create ? flags : BMAPI_READ, &iomap, &niomap); |
| 1343 | if (error) | 1347 | if (error) |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 986061ae1b9b..36d5fcd3f593 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
| @@ -1001,12 +1001,13 @@ xfs_buf_iodone_work( | |||
| 1001 | * We can get an EOPNOTSUPP to ordered writes. Here we clear the | 1001 | * We can get an EOPNOTSUPP to ordered writes. Here we clear the |
| 1002 | * ordered flag and reissue them. Because we can't tell the higher | 1002 | * ordered flag and reissue them. Because we can't tell the higher |
| 1003 | * layers directly that they should not issue ordered I/O anymore, they | 1003 | * layers directly that they should not issue ordered I/O anymore, they |
| 1004 | * need to check if the ordered flag was cleared during I/O completion. | 1004 | * need to check if the _XFS_BARRIER_FAILED flag was set during I/O completion. |
| 1005 | */ | 1005 | */ |
| 1006 | if ((bp->b_error == EOPNOTSUPP) && | 1006 | if ((bp->b_error == EOPNOTSUPP) && |
| 1007 | (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) { | 1007 | (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) { |
| 1008 | XB_TRACE(bp, "ordered_retry", bp->b_iodone); | 1008 | XB_TRACE(bp, "ordered_retry", bp->b_iodone); |
| 1009 | bp->b_flags &= ~XBF_ORDERED; | 1009 | bp->b_flags &= ~XBF_ORDERED; |
| 1010 | bp->b_flags |= _XFS_BARRIER_FAILED; | ||
| 1010 | xfs_buf_iorequest(bp); | 1011 | xfs_buf_iorequest(bp); |
| 1011 | } else if (bp->b_iodone) | 1012 | } else if (bp->b_iodone) |
| 1012 | (*(bp->b_iodone))(bp); | 1013 | (*(bp->b_iodone))(bp); |
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index fe0109956656..456519a088c7 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h | |||
| @@ -85,6 +85,14 @@ typedef enum { | |||
| 85 | * modifications being lost. | 85 | * modifications being lost. |
| 86 | */ | 86 | */ |
| 87 | _XBF_PAGE_LOCKED = (1 << 22), | 87 | _XBF_PAGE_LOCKED = (1 << 22), |
| 88 | |||
| 89 | /* | ||
| 90 | * If we try a barrier write, but it fails we have to communicate | ||
| 91 | * this to the upper layers. Unfortunately b_error gets overwritten | ||
| 92 | * when the buffer is re-issued so we have to add another flag to | ||
| 93 | * keep this information. | ||
| 94 | */ | ||
| 95 | _XFS_BARRIER_FAILED = (1 << 23), | ||
| 88 | } xfs_buf_flags_t; | 96 | } xfs_buf_flags_t; |
| 89 | 97 | ||
| 90 | typedef enum { | 98 | typedef enum { |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 73c65f19e549..18d3c8487835 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
| @@ -1302,9 +1302,29 @@ xfs_fs_remount( | |||
| 1302 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 1302 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
| 1303 | break; | 1303 | break; |
| 1304 | default: | 1304 | default: |
| 1305 | /* | ||
| 1306 | * Logically we would return an error here to prevent | ||
| 1307 | * users from believing they might have changed | ||
| 1308 | * mount options using remount which can't be changed. | ||
| 1309 | * | ||
| 1310 | * But unfortunately mount(8) adds all options from | ||
| 1311 | * mtab and fstab to the mount arguments in some cases | ||
| 1312 | * so we can't blindly reject options, but have to | ||
| 1313 | * check for each specified option if it actually | ||
| 1314 | * differs from the currently set option and only | ||
| 1315 | * reject it if that's the case. | ||
| 1316 | * | ||
| 1317 | * Until that is implemented we return success for | ||
| 1318 | * every remount request, and silently ignore all | ||
| 1319 | * options that we can't actually change. | ||
| 1320 | */ | ||
| 1321 | #if 0 | ||
| 1305 | printk(KERN_INFO | 1322 | printk(KERN_INFO |
| 1306 | "XFS: mount option \"%s\" not supported for remount\n", p); | 1323 | "XFS: mount option \"%s\" not supported for remount\n", p); |
| 1307 | return -EINVAL; | 1324 | return -EINVAL; |
| 1325 | #else | ||
| 1326 | return 0; | ||
| 1327 | #endif | ||
| 1308 | } | 1328 | } |
| 1309 | } | 1329 | } |
| 1310 | 1330 | ||
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 608c30c3f76b..002fc2617c8e 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
| @@ -732,6 +732,7 @@ xfs_buf_item_init( | |||
| 732 | bip->bli_item.li_ops = &xfs_buf_item_ops; | 732 | bip->bli_item.li_ops = &xfs_buf_item_ops; |
| 733 | bip->bli_item.li_mountp = mp; | 733 | bip->bli_item.li_mountp = mp; |
| 734 | bip->bli_buf = bp; | 734 | bip->bli_buf = bp; |
| 735 | xfs_buf_hold(bp); | ||
| 735 | bip->bli_format.blf_type = XFS_LI_BUF; | 736 | bip->bli_format.blf_type = XFS_LI_BUF; |
| 736 | bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp); | 737 | bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp); |
| 737 | bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp)); | 738 | bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp)); |
| @@ -867,6 +868,21 @@ xfs_buf_item_dirty( | |||
| 867 | return (bip->bli_flags & XFS_BLI_DIRTY); | 868 | return (bip->bli_flags & XFS_BLI_DIRTY); |
| 868 | } | 869 | } |
| 869 | 870 | ||
| 871 | STATIC void | ||
| 872 | xfs_buf_item_free( | ||
| 873 | xfs_buf_log_item_t *bip) | ||
| 874 | { | ||
| 875 | #ifdef XFS_TRANS_DEBUG | ||
| 876 | kmem_free(bip->bli_orig); | ||
| 877 | kmem_free(bip->bli_logged); | ||
| 878 | #endif /* XFS_TRANS_DEBUG */ | ||
| 879 | |||
| 880 | #ifdef XFS_BLI_TRACE | ||
| 881 | ktrace_free(bip->bli_trace); | ||
| 882 | #endif | ||
| 883 | kmem_zone_free(xfs_buf_item_zone, bip); | ||
| 884 | } | ||
| 885 | |||
| 870 | /* | 886 | /* |
| 871 | * This is called when the buf log item is no longer needed. It should | 887 | * This is called when the buf log item is no longer needed. It should |
| 872 | * free the buf log item associated with the given buffer and clear | 888 | * free the buf log item associated with the given buffer and clear |
| @@ -887,18 +903,8 @@ xfs_buf_item_relse( | |||
| 887 | (XFS_BUF_IODONE_FUNC(bp) != NULL)) { | 903 | (XFS_BUF_IODONE_FUNC(bp) != NULL)) { |
| 888 | XFS_BUF_CLR_IODONE_FUNC(bp); | 904 | XFS_BUF_CLR_IODONE_FUNC(bp); |
| 889 | } | 905 | } |
| 890 | 906 | xfs_buf_rele(bp); | |
| 891 | #ifdef XFS_TRANS_DEBUG | 907 | xfs_buf_item_free(bip); |
| 892 | kmem_free(bip->bli_orig); | ||
| 893 | bip->bli_orig = NULL; | ||
| 894 | kmem_free(bip->bli_logged); | ||
| 895 | bip->bli_logged = NULL; | ||
| 896 | #endif /* XFS_TRANS_DEBUG */ | ||
| 897 | |||
| 898 | #ifdef XFS_BLI_TRACE | ||
| 899 | ktrace_free(bip->bli_trace); | ||
| 900 | #endif | ||
| 901 | kmem_zone_free(xfs_buf_item_zone, bip); | ||
| 902 | } | 908 | } |
| 903 | 909 | ||
| 904 | 910 | ||
| @@ -1120,6 +1126,7 @@ xfs_buf_iodone( | |||
| 1120 | 1126 | ||
| 1121 | ASSERT(bip->bli_buf == bp); | 1127 | ASSERT(bip->bli_buf == bp); |
| 1122 | 1128 | ||
| 1129 | xfs_buf_rele(bp); | ||
| 1123 | mp = bip->bli_item.li_mountp; | 1130 | mp = bip->bli_item.li_mountp; |
| 1124 | 1131 | ||
| 1125 | /* | 1132 | /* |
| @@ -1136,18 +1143,7 @@ xfs_buf_iodone( | |||
| 1136 | * xfs_trans_delete_ail() drops the AIL lock. | 1143 | * xfs_trans_delete_ail() drops the AIL lock. |
| 1137 | */ | 1144 | */ |
| 1138 | xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip); | 1145 | xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip); |
| 1139 | 1146 | xfs_buf_item_free(bip); | |
| 1140 | #ifdef XFS_TRANS_DEBUG | ||
| 1141 | kmem_free(bip->bli_orig); | ||
| 1142 | bip->bli_orig = NULL; | ||
| 1143 | kmem_free(bip->bli_logged); | ||
| 1144 | bip->bli_logged = NULL; | ||
| 1145 | #endif /* XFS_TRANS_DEBUG */ | ||
| 1146 | |||
| 1147 | #ifdef XFS_BLI_TRACE | ||
| 1148 | ktrace_free(bip->bli_trace); | ||
| 1149 | #endif | ||
| 1150 | kmem_zone_free(xfs_buf_item_zone, bip); | ||
| 1151 | } | 1147 | } |
| 1152 | 1148 | ||
| 1153 | #if defined(XFS_BLI_TRACE) | 1149 | #if defined(XFS_BLI_TRACE) |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 760f4c5b5160..75b0cd4da0ea 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
| @@ -149,7 +149,14 @@ xfs_swap_extents( | |||
| 149 | 149 | ||
| 150 | sbp = &sxp->sx_stat; | 150 | sbp = &sxp->sx_stat; |
| 151 | 151 | ||
| 152 | xfs_lock_two_inodes(ip, tip, lock_flags); | 152 | /* |
| 153 | * we have to do two separate lock calls here to keep lockdep | ||
| 154 | * happy. If we try to get all the locks in one call, lock will | ||
| 155 | * report false positives when we drop the ILOCK and regain them | ||
| 156 | * below. | ||
| 157 | */ | ||
| 158 | xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); | ||
| 159 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); | ||
| 153 | locked = 1; | 160 | locked = 1; |
| 154 | 161 | ||
| 155 | /* Verify that both files have the same format */ | 162 | /* Verify that both files have the same format */ |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 00e80df9dd9d..dbd9cef852ec 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -4118,7 +4118,7 @@ xfs_iext_indirect_to_direct( | |||
| 4118 | ASSERT(nextents <= XFS_LINEAR_EXTS); | 4118 | ASSERT(nextents <= XFS_LINEAR_EXTS); |
| 4119 | size = nextents * sizeof(xfs_bmbt_rec_t); | 4119 | size = nextents * sizeof(xfs_bmbt_rec_t); |
| 4120 | 4120 | ||
| 4121 | xfs_iext_irec_compact_full(ifp); | 4121 | xfs_iext_irec_compact_pages(ifp); |
| 4122 | ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); | 4122 | ASSERT(ifp->if_real_bytes == XFS_IEXT_BUFSZ); |
| 4123 | 4123 | ||
| 4124 | ep = ifp->if_u1.if_ext_irec->er_extbuf; | 4124 | ep = ifp->if_u1.if_ext_irec->er_extbuf; |
| @@ -4449,8 +4449,7 @@ xfs_iext_irec_remove( | |||
| 4449 | * compaction policy is as follows: | 4449 | * compaction policy is as follows: |
| 4450 | * | 4450 | * |
| 4451 | * Full Compaction: Extents fit into a single page (or inline buffer) | 4451 | * Full Compaction: Extents fit into a single page (or inline buffer) |
| 4452 | * Full Compaction: Extents occupy less than 10% of allocated space | 4452 | * Partial Compaction: Extents occupy less than 50% of allocated space |
| 4453 | * Partial Compaction: Extents occupy > 10% and < 50% of allocated space | ||
| 4454 | * No Compaction: Extents occupy at least 50% of allocated space | 4453 | * No Compaction: Extents occupy at least 50% of allocated space |
| 4455 | */ | 4454 | */ |
| 4456 | void | 4455 | void |
| @@ -4471,8 +4470,6 @@ xfs_iext_irec_compact( | |||
| 4471 | xfs_iext_direct_to_inline(ifp, nextents); | 4470 | xfs_iext_direct_to_inline(ifp, nextents); |
| 4472 | } else if (nextents <= XFS_LINEAR_EXTS) { | 4471 | } else if (nextents <= XFS_LINEAR_EXTS) { |
| 4473 | xfs_iext_indirect_to_direct(ifp); | 4472 | xfs_iext_indirect_to_direct(ifp); |
| 4474 | } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 3) { | ||
| 4475 | xfs_iext_irec_compact_full(ifp); | ||
| 4476 | } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { | 4473 | } else if (nextents < (nlists * XFS_LINEAR_EXTS) >> 1) { |
| 4477 | xfs_iext_irec_compact_pages(ifp); | 4474 | xfs_iext_irec_compact_pages(ifp); |
| 4478 | } | 4475 | } |
| @@ -4496,7 +4493,7 @@ xfs_iext_irec_compact_pages( | |||
| 4496 | erp_next = erp + 1; | 4493 | erp_next = erp + 1; |
| 4497 | if (erp_next->er_extcount <= | 4494 | if (erp_next->er_extcount <= |
| 4498 | (XFS_LINEAR_EXTS - erp->er_extcount)) { | 4495 | (XFS_LINEAR_EXTS - erp->er_extcount)) { |
| 4499 | memmove(&erp->er_extbuf[erp->er_extcount], | 4496 | memcpy(&erp->er_extbuf[erp->er_extcount], |
| 4500 | erp_next->er_extbuf, erp_next->er_extcount * | 4497 | erp_next->er_extbuf, erp_next->er_extcount * |
| 4501 | sizeof(xfs_bmbt_rec_t)); | 4498 | sizeof(xfs_bmbt_rec_t)); |
| 4502 | erp->er_extcount += erp_next->er_extcount; | 4499 | erp->er_extcount += erp_next->er_extcount; |
| @@ -4516,91 +4513,6 @@ xfs_iext_irec_compact_pages( | |||
| 4516 | } | 4513 | } |
| 4517 | 4514 | ||
| 4518 | /* | 4515 | /* |
| 4519 | * Fully compact the extent records managed by the indirection array. | ||
| 4520 | */ | ||
| 4521 | void | ||
| 4522 | xfs_iext_irec_compact_full( | ||
| 4523 | xfs_ifork_t *ifp) /* inode fork pointer */ | ||
| 4524 | { | ||
| 4525 | xfs_bmbt_rec_host_t *ep, *ep_next; /* extent record pointers */ | ||
| 4526 | xfs_ext_irec_t *erp, *erp_next; /* extent irec pointers */ | ||
| 4527 | int erp_idx = 0; /* extent irec index */ | ||
| 4528 | int ext_avail; /* empty entries in ex list */ | ||
| 4529 | int ext_diff; /* number of exts to add */ | ||
| 4530 | int nlists; /* number of irec's (ex lists) */ | ||
| 4531 | |||
| 4532 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); | ||
| 4533 | |||
| 4534 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | ||
| 4535 | erp = ifp->if_u1.if_ext_irec; | ||
| 4536 | ep = &erp->er_extbuf[erp->er_extcount]; | ||
| 4537 | erp_next = erp + 1; | ||
| 4538 | ep_next = erp_next->er_extbuf; | ||
| 4539 | |||
| 4540 | while (erp_idx < nlists - 1) { | ||
| 4541 | /* | ||
| 4542 | * Check how many extent records are available in this irec. | ||
| 4543 | * If there is none skip the whole exercise. | ||
| 4544 | */ | ||
| 4545 | ext_avail = XFS_LINEAR_EXTS - erp->er_extcount; | ||
| 4546 | if (ext_avail) { | ||
| 4547 | |||
| 4548 | /* | ||
| 4549 | * Copy over as many as possible extent records into | ||
| 4550 | * the previous page. | ||
| 4551 | */ | ||
| 4552 | ext_diff = MIN(ext_avail, erp_next->er_extcount); | ||
| 4553 | memcpy(ep, ep_next, ext_diff * sizeof(xfs_bmbt_rec_t)); | ||
| 4554 | erp->er_extcount += ext_diff; | ||
| 4555 | erp_next->er_extcount -= ext_diff; | ||
| 4556 | |||
| 4557 | /* | ||
| 4558 | * If the next irec is empty now we can simply | ||
| 4559 | * remove it. | ||
| 4560 | */ | ||
| 4561 | if (erp_next->er_extcount == 0) { | ||
| 4562 | /* | ||
| 4563 | * Free page before removing extent record | ||
| 4564 | * so er_extoffs don't get modified in | ||
| 4565 | * xfs_iext_irec_remove. | ||
| 4566 | */ | ||
| 4567 | kmem_free(erp_next->er_extbuf); | ||
| 4568 | erp_next->er_extbuf = NULL; | ||
| 4569 | xfs_iext_irec_remove(ifp, erp_idx + 1); | ||
| 4570 | erp = &ifp->if_u1.if_ext_irec[erp_idx]; | ||
| 4571 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | ||
| 4572 | |||
| 4573 | /* | ||
| 4574 | * If the next irec is not empty move up the content | ||
| 4575 | * that has not been copied to the previous page to | ||
| 4576 | * the beggining of this one. | ||
| 4577 | */ | ||
| 4578 | } else { | ||
| 4579 | memmove(erp_next->er_extbuf, &ep_next[ext_diff], | ||
| 4580 | erp_next->er_extcount * | ||
| 4581 | sizeof(xfs_bmbt_rec_t)); | ||
| 4582 | ep_next = erp_next->er_extbuf; | ||
| 4583 | memset(&ep_next[erp_next->er_extcount], 0, | ||
| 4584 | (XFS_LINEAR_EXTS - | ||
| 4585 | erp_next->er_extcount) * | ||
| 4586 | sizeof(xfs_bmbt_rec_t)); | ||
| 4587 | } | ||
| 4588 | } | ||
| 4589 | |||
| 4590 | if (erp->er_extcount == XFS_LINEAR_EXTS) { | ||
| 4591 | erp_idx++; | ||
| 4592 | if (erp_idx < nlists) | ||
| 4593 | erp = &ifp->if_u1.if_ext_irec[erp_idx]; | ||
| 4594 | else | ||
| 4595 | break; | ||
| 4596 | } | ||
| 4597 | ep = &erp->er_extbuf[erp->er_extcount]; | ||
| 4598 | erp_next = erp + 1; | ||
| 4599 | ep_next = erp_next->er_extbuf; | ||
| 4600 | } | ||
| 4601 | } | ||
| 4602 | |||
| 4603 | /* | ||
| 4604 | * This is called to update the er_extoff field in the indirection | 4516 | * This is called to update the er_extoff field in the indirection |
| 4605 | * array when extents have been added or removed from one of the | 4517 | * array when extents have been added or removed from one of the |
| 4606 | * extent lists. erp_idx contains the irec index to begin updating | 4518 | * extent lists. erp_idx contains the irec index to begin updating |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index ccba14eb9dbe..0b02c6443551 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -124,16 +124,27 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog, | |||
| 124 | STATIC int xlog_iclogs_empty(xlog_t *log); | 124 | STATIC int xlog_iclogs_empty(xlog_t *log); |
| 125 | 125 | ||
| 126 | #if defined(XFS_LOG_TRACE) | 126 | #if defined(XFS_LOG_TRACE) |
| 127 | |||
| 128 | #define XLOG_TRACE_LOGGRANT_SIZE 2048 | ||
| 129 | #define XLOG_TRACE_ICLOG_SIZE 256 | ||
| 130 | |||
| 131 | void | ||
| 132 | xlog_trace_loggrant_alloc(xlog_t *log) | ||
| 133 | { | ||
| 134 | log->l_grant_trace = ktrace_alloc(XLOG_TRACE_LOGGRANT_SIZE, KM_NOFS); | ||
| 135 | } | ||
| 136 | |||
| 137 | void | ||
| 138 | xlog_trace_loggrant_dealloc(xlog_t *log) | ||
| 139 | { | ||
| 140 | ktrace_free(log->l_grant_trace); | ||
| 141 | } | ||
| 142 | |||
| 127 | void | 143 | void |
| 128 | xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) | 144 | xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) |
| 129 | { | 145 | { |
| 130 | unsigned long cnts; | 146 | unsigned long cnts; |
| 131 | 147 | ||
| 132 | if (!log->l_grant_trace) { | ||
| 133 | log->l_grant_trace = ktrace_alloc(2048, KM_NOSLEEP); | ||
| 134 | if (!log->l_grant_trace) | ||
| 135 | return; | ||
| 136 | } | ||
| 137 | /* ticket counts are 1 byte each */ | 148 | /* ticket counts are 1 byte each */ |
| 138 | cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8; | 149 | cnts = ((unsigned long)tic->t_ocnt) | ((unsigned long)tic->t_cnt) << 8; |
| 139 | 150 | ||
| @@ -157,10 +168,20 @@ xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string) | |||
| 157 | } | 168 | } |
| 158 | 169 | ||
| 159 | void | 170 | void |
| 171 | xlog_trace_iclog_alloc(xlog_in_core_t *iclog) | ||
| 172 | { | ||
| 173 | iclog->ic_trace = ktrace_alloc(XLOG_TRACE_ICLOG_SIZE, KM_NOFS); | ||
| 174 | } | ||
| 175 | |||
| 176 | void | ||
| 177 | xlog_trace_iclog_dealloc(xlog_in_core_t *iclog) | ||
| 178 | { | ||
| 179 | ktrace_free(iclog->ic_trace); | ||
| 180 | } | ||
| 181 | |||
| 182 | void | ||
| 160 | xlog_trace_iclog(xlog_in_core_t *iclog, uint state) | 183 | xlog_trace_iclog(xlog_in_core_t *iclog, uint state) |
| 161 | { | 184 | { |
| 162 | if (!iclog->ic_trace) | ||
| 163 | iclog->ic_trace = ktrace_alloc(256, KM_NOFS); | ||
| 164 | ktrace_enter(iclog->ic_trace, | 185 | ktrace_enter(iclog->ic_trace, |
| 165 | (void *)((unsigned long)state), | 186 | (void *)((unsigned long)state), |
| 166 | (void *)((unsigned long)current_pid()), | 187 | (void *)((unsigned long)current_pid()), |
| @@ -170,8 +191,15 @@ xlog_trace_iclog(xlog_in_core_t *iclog, uint state) | |||
| 170 | (void *)NULL, (void *)NULL); | 191 | (void *)NULL, (void *)NULL); |
| 171 | } | 192 | } |
| 172 | #else | 193 | #else |
| 194 | |||
| 195 | #define xlog_trace_loggrant_alloc(log) | ||
| 196 | #define xlog_trace_loggrant_dealloc(log) | ||
| 173 | #define xlog_trace_loggrant(log,tic,string) | 197 | #define xlog_trace_loggrant(log,tic,string) |
| 198 | |||
| 199 | #define xlog_trace_iclog_alloc(iclog) | ||
| 200 | #define xlog_trace_iclog_dealloc(iclog) | ||
| 174 | #define xlog_trace_iclog(iclog,state) | 201 | #define xlog_trace_iclog(iclog,state) |
| 202 | |||
| 175 | #endif /* XFS_LOG_TRACE */ | 203 | #endif /* XFS_LOG_TRACE */ |
| 176 | 204 | ||
| 177 | 205 | ||
| @@ -1005,11 +1033,12 @@ xlog_iodone(xfs_buf_t *bp) | |||
| 1005 | l = iclog->ic_log; | 1033 | l = iclog->ic_log; |
| 1006 | 1034 | ||
| 1007 | /* | 1035 | /* |
| 1008 | * If the ordered flag has been removed by a lower | 1036 | * If the _XFS_BARRIER_FAILED flag was set by a lower |
| 1009 | * layer, it means the underlyin device no longer supports | 1037 | * layer, it means the underlying device no longer supports |
| 1010 | * barrier I/O. Warn loudly and turn off barriers. | 1038 | * barrier I/O. Warn loudly and turn off barriers. |
| 1011 | */ | 1039 | */ |
| 1012 | if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) { | 1040 | if (bp->b_flags & _XFS_BARRIER_FAILED) { |
| 1041 | bp->b_flags &= ~_XFS_BARRIER_FAILED; | ||
| 1013 | l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; | 1042 | l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; |
| 1014 | xfs_fs_cmn_err(CE_WARN, l->l_mp, | 1043 | xfs_fs_cmn_err(CE_WARN, l->l_mp, |
| 1015 | "xlog_iodone: Barriers are no longer supported" | 1044 | "xlog_iodone: Barriers are no longer supported" |
| @@ -1231,6 +1260,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1231 | spin_lock_init(&log->l_grant_lock); | 1260 | spin_lock_init(&log->l_grant_lock); |
| 1232 | sv_init(&log->l_flush_wait, 0, "flush_wait"); | 1261 | sv_init(&log->l_flush_wait, 0, "flush_wait"); |
| 1233 | 1262 | ||
| 1263 | xlog_trace_loggrant_alloc(log); | ||
| 1234 | /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ | 1264 | /* log record size must be multiple of BBSIZE; see xlog_rec_header_t */ |
| 1235 | ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); | 1265 | ASSERT((XFS_BUF_SIZE(bp) & BBMASK) == 0); |
| 1236 | 1266 | ||
| @@ -1285,6 +1315,8 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1285 | sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force"); | 1315 | sv_init(&iclog->ic_force_wait, SV_DEFAULT, "iclog-force"); |
| 1286 | sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write"); | 1316 | sv_init(&iclog->ic_write_wait, SV_DEFAULT, "iclog-write"); |
| 1287 | 1317 | ||
| 1318 | xlog_trace_iclog_alloc(iclog); | ||
| 1319 | |||
| 1288 | iclogp = &iclog->ic_next; | 1320 | iclogp = &iclog->ic_next; |
| 1289 | } | 1321 | } |
| 1290 | *iclogp = log->l_iclog; /* complete ring */ | 1322 | *iclogp = log->l_iclog; /* complete ring */ |
| @@ -1565,11 +1597,7 @@ xlog_dealloc_log(xlog_t *log) | |||
| 1565 | sv_destroy(&iclog->ic_force_wait); | 1597 | sv_destroy(&iclog->ic_force_wait); |
| 1566 | sv_destroy(&iclog->ic_write_wait); | 1598 | sv_destroy(&iclog->ic_write_wait); |
| 1567 | xfs_buf_free(iclog->ic_bp); | 1599 | xfs_buf_free(iclog->ic_bp); |
| 1568 | #ifdef XFS_LOG_TRACE | 1600 | xlog_trace_iclog_dealloc(iclog); |
| 1569 | if (iclog->ic_trace != NULL) { | ||
| 1570 | ktrace_free(iclog->ic_trace); | ||
| 1571 | } | ||
| 1572 | #endif | ||
| 1573 | next_iclog = iclog->ic_next; | 1601 | next_iclog = iclog->ic_next; |
| 1574 | kmem_free(iclog); | 1602 | kmem_free(iclog); |
| 1575 | iclog = next_iclog; | 1603 | iclog = next_iclog; |
| @@ -1578,14 +1606,7 @@ xlog_dealloc_log(xlog_t *log) | |||
| 1578 | spinlock_destroy(&log->l_grant_lock); | 1606 | spinlock_destroy(&log->l_grant_lock); |
| 1579 | 1607 | ||
| 1580 | xfs_buf_free(log->l_xbuf); | 1608 | xfs_buf_free(log->l_xbuf); |
| 1581 | #ifdef XFS_LOG_TRACE | 1609 | xlog_trace_loggrant_dealloc(log); |
| 1582 | if (log->l_trace != NULL) { | ||
| 1583 | ktrace_free(log->l_trace); | ||
| 1584 | } | ||
| 1585 | if (log->l_grant_trace != NULL) { | ||
| 1586 | ktrace_free(log->l_grant_trace); | ||
| 1587 | } | ||
| 1588 | #endif | ||
| 1589 | log->l_mp->m_log = NULL; | 1610 | log->l_mp->m_log = NULL; |
| 1590 | kmem_free(log); | 1611 | kmem_free(log); |
| 1591 | } /* xlog_dealloc_log */ | 1612 | } /* xlog_dealloc_log */ |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index c8a5b22ee3e3..e7d8f84443fa 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
| @@ -448,7 +448,6 @@ typedef struct log { | |||
| 448 | int l_grant_write_bytes; | 448 | int l_grant_write_bytes; |
| 449 | 449 | ||
| 450 | #ifdef XFS_LOG_TRACE | 450 | #ifdef XFS_LOG_TRACE |
| 451 | struct ktrace *l_trace; | ||
| 452 | struct ktrace *l_grant_trace; | 451 | struct ktrace *l_grant_trace; |
| 453 | #endif | 452 | #endif |
| 454 | 453 | ||
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index aa238c8fbd7a..8b6812f66a15 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -1838,6 +1838,12 @@ again: | |||
| 1838 | #endif | 1838 | #endif |
| 1839 | } | 1839 | } |
| 1840 | 1840 | ||
| 1841 | /* | ||
| 1842 | * xfs_lock_two_inodes() can only be used to lock one type of lock | ||
| 1843 | * at a time - the iolock or the ilock, but not both at once. If | ||
| 1844 | * we lock both at once, lockdep will report false positives saying | ||
| 1845 | * we have violated locking orders. | ||
| 1846 | */ | ||
| 1841 | void | 1847 | void |
| 1842 | xfs_lock_two_inodes( | 1848 | xfs_lock_two_inodes( |
| 1843 | xfs_inode_t *ip0, | 1849 | xfs_inode_t *ip0, |
| @@ -1848,6 +1854,8 @@ xfs_lock_two_inodes( | |||
| 1848 | int attempts = 0; | 1854 | int attempts = 0; |
| 1849 | xfs_log_item_t *lp; | 1855 | xfs_log_item_t *lp; |
| 1850 | 1856 | ||
| 1857 | if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) | ||
| 1858 | ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0); | ||
| 1851 | ASSERT(ip0->i_ino != ip1->i_ino); | 1859 | ASSERT(ip0->i_ino != ip1->i_ino); |
| 1852 | 1860 | ||
| 1853 | if (ip0->i_ino > ip1->i_ino) { | 1861 | if (ip0->i_ino > ip1->i_ino) { |
| @@ -3152,6 +3160,13 @@ error1: /* Just cancel transaction */ | |||
| 3152 | /* | 3160 | /* |
| 3153 | * Zero file bytes between startoff and endoff inclusive. | 3161 | * Zero file bytes between startoff and endoff inclusive. |
| 3154 | * The iolock is held exclusive and no blocks are buffered. | 3162 | * The iolock is held exclusive and no blocks are buffered. |
| 3163 | * | ||
| 3164 | * This function is used by xfs_free_file_space() to zero | ||
| 3165 | * partial blocks when the range to free is not block aligned. | ||
| 3166 | * When unreserving space with boundaries that are not block | ||
| 3167 | * aligned we round up the start and round down the end | ||
| 3168 | * boundaries and then use this function to zero the parts of | ||
| 3169 | * the blocks that got dropped during the rounding. | ||
| 3155 | */ | 3170 | */ |
| 3156 | STATIC int | 3171 | STATIC int |
| 3157 | xfs_zero_remaining_bytes( | 3172 | xfs_zero_remaining_bytes( |
| @@ -3168,6 +3183,17 @@ xfs_zero_remaining_bytes( | |||
| 3168 | int nimap; | 3183 | int nimap; |
| 3169 | int error = 0; | 3184 | int error = 0; |
| 3170 | 3185 | ||
| 3186 | /* | ||
| 3187 | * Avoid doing I/O beyond eof - it's not necessary | ||
| 3188 | * since nothing can read beyond eof. The space will | ||
| 3189 | * be zeroed when the file is extended anyway. | ||
| 3190 | */ | ||
| 3191 | if (startoff >= ip->i_size) | ||
| 3192 | return 0; | ||
| 3193 | |||
| 3194 | if (endoff > ip->i_size) | ||
| 3195 | endoff = ip->i_size; | ||
| 3196 | |||
| 3171 | bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize, | 3197 | bp = xfs_buf_get_noaddr(mp->m_sb.sb_blocksize, |
| 3172 | XFS_IS_REALTIME_INODE(ip) ? | 3198 | XFS_IS_REALTIME_INODE(ip) ? |
| 3173 | mp->m_rtdev_targp : mp->m_ddev_targp); | 3199 | mp->m_rtdev_targp : mp->m_ddev_targp); |
