diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_node.c')
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 288 |
1 files changed, 185 insertions, 103 deletions
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 6c7052406605..5980f9b7fa9b 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -55,6 +55,74 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, | |||
55 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, | 55 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, |
56 | xfs_da_state_blk_t *fblk); | 56 | xfs_da_state_blk_t *fblk); |
57 | 57 | ||
58 | static void | ||
59 | xfs_dir2_free_verify( | ||
60 | struct xfs_buf *bp) | ||
61 | { | ||
62 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
63 | struct xfs_dir2_free_hdr *hdr = bp->b_addr; | ||
64 | int block_ok = 0; | ||
65 | |||
66 | block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC); | ||
67 | if (!block_ok) { | ||
68 | XFS_CORRUPTION_ERROR("xfs_dir2_free_verify magic", | ||
69 | XFS_ERRLEVEL_LOW, mp, hdr); | ||
70 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static void | ||
75 | xfs_dir2_free_read_verify( | ||
76 | struct xfs_buf *bp) | ||
77 | { | ||
78 | xfs_dir2_free_verify(bp); | ||
79 | } | ||
80 | |||
81 | static void | ||
82 | xfs_dir2_free_write_verify( | ||
83 | struct xfs_buf *bp) | ||
84 | { | ||
85 | xfs_dir2_free_verify(bp); | ||
86 | } | ||
87 | |||
88 | static const struct xfs_buf_ops xfs_dir2_free_buf_ops = { | ||
89 | .verify_read = xfs_dir2_free_read_verify, | ||
90 | .verify_write = xfs_dir2_free_write_verify, | ||
91 | }; | ||
92 | |||
93 | |||
94 | static int | ||
95 | __xfs_dir2_free_read( | ||
96 | struct xfs_trans *tp, | ||
97 | struct xfs_inode *dp, | ||
98 | xfs_dablk_t fbno, | ||
99 | xfs_daddr_t mappedbno, | ||
100 | struct xfs_buf **bpp) | ||
101 | { | ||
102 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, | ||
103 | XFS_DATA_FORK, &xfs_dir2_free_buf_ops); | ||
104 | } | ||
105 | |||
106 | int | ||
107 | xfs_dir2_free_read( | ||
108 | struct xfs_trans *tp, | ||
109 | struct xfs_inode *dp, | ||
110 | xfs_dablk_t fbno, | ||
111 | struct xfs_buf **bpp) | ||
112 | { | ||
113 | return __xfs_dir2_free_read(tp, dp, fbno, -1, bpp); | ||
114 | } | ||
115 | |||
116 | static int | ||
117 | xfs_dir2_free_try_read( | ||
118 | struct xfs_trans *tp, | ||
119 | struct xfs_inode *dp, | ||
120 | xfs_dablk_t fbno, | ||
121 | struct xfs_buf **bpp) | ||
122 | { | ||
123 | return __xfs_dir2_free_read(tp, dp, fbno, -2, bpp); | ||
124 | } | ||
125 | |||
58 | /* | 126 | /* |
59 | * Log entries from a freespace block. | 127 | * Log entries from a freespace block. |
60 | */ | 128 | */ |
@@ -131,11 +199,12 @@ xfs_dir2_leaf_to_node( | |||
131 | /* | 199 | /* |
132 | * Get the buffer for the new freespace block. | 200 | * Get the buffer for the new freespace block. |
133 | */ | 201 | */ |
134 | if ((error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp, | 202 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp, |
135 | XFS_DATA_FORK))) { | 203 | XFS_DATA_FORK); |
204 | if (error) | ||
136 | return error; | 205 | return error; |
137 | } | 206 | fbp->b_ops = &xfs_dir2_free_buf_ops; |
138 | ASSERT(fbp != NULL); | 207 | |
139 | free = fbp->b_addr; | 208 | free = fbp->b_addr; |
140 | leaf = lbp->b_addr; | 209 | leaf = lbp->b_addr; |
141 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 210 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
@@ -157,7 +226,10 @@ xfs_dir2_leaf_to_node( | |||
157 | *to = cpu_to_be16(off); | 226 | *to = cpu_to_be16(off); |
158 | } | 227 | } |
159 | free->hdr.nused = cpu_to_be32(n); | 228 | free->hdr.nused = cpu_to_be32(n); |
229 | |||
230 | lbp->b_ops = &xfs_dir2_leafn_buf_ops; | ||
160 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); | 231 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); |
232 | |||
161 | /* | 233 | /* |
162 | * Log everything. | 234 | * Log everything. |
163 | */ | 235 | */ |
@@ -394,12 +466,10 @@ xfs_dir2_leafn_lookup_for_addname( | |||
394 | */ | 466 | */ |
395 | if (curbp) | 467 | if (curbp) |
396 | xfs_trans_brelse(tp, curbp); | 468 | xfs_trans_brelse(tp, curbp); |
397 | /* | 469 | |
398 | * Read the free block. | 470 | error = xfs_dir2_free_read(tp, dp, |
399 | */ | ||
400 | error = xfs_da_read_buf(tp, dp, | ||
401 | xfs_dir2_db_to_da(mp, newfdb), | 471 | xfs_dir2_db_to_da(mp, newfdb), |
402 | -1, &curbp, XFS_DATA_FORK); | 472 | &curbp); |
403 | if (error) | 473 | if (error) |
404 | return error; | 474 | return error; |
405 | free = curbp->b_addr; | 475 | free = curbp->b_addr; |
@@ -534,9 +604,9 @@ xfs_dir2_leafn_lookup_for_entry( | |||
534 | ASSERT(state->extravalid); | 604 | ASSERT(state->extravalid); |
535 | curbp = state->extrablk.bp; | 605 | curbp = state->extrablk.bp; |
536 | } else { | 606 | } else { |
537 | error = xfs_da_read_buf(tp, dp, | 607 | error = xfs_dir2_data_read(tp, dp, |
538 | xfs_dir2_db_to_da(mp, newdb), | 608 | xfs_dir2_db_to_da(mp, newdb), |
539 | -1, &curbp, XFS_DATA_FORK); | 609 | -1, &curbp); |
540 | if (error) | 610 | if (error) |
541 | return error; | 611 | return error; |
542 | } | 612 | } |
@@ -568,6 +638,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
568 | state->extrablk.index = (int)((char *)dep - | 638 | state->extrablk.index = (int)((char *)dep - |
569 | (char *)curbp->b_addr); | 639 | (char *)curbp->b_addr); |
570 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; | 640 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; |
641 | curbp->b_ops = &xfs_dir2_data_buf_ops; | ||
571 | if (cmp == XFS_CMP_EXACT) | 642 | if (cmp == XFS_CMP_EXACT) |
572 | return XFS_ERROR(EEXIST); | 643 | return XFS_ERROR(EEXIST); |
573 | } | 644 | } |
@@ -582,6 +653,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
582 | state->extrablk.index = -1; | 653 | state->extrablk.index = -1; |
583 | state->extrablk.blkno = curdb; | 654 | state->extrablk.blkno = curdb; |
584 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; | 655 | state->extrablk.magic = XFS_DIR2_DATA_MAGIC; |
656 | curbp->b_ops = &xfs_dir2_data_buf_ops; | ||
585 | } else { | 657 | } else { |
586 | /* If the curbp is not the CI match block, drop it */ | 658 | /* If the curbp is not the CI match block, drop it */ |
587 | if (state->extrablk.bp != curbp) | 659 | if (state->extrablk.bp != curbp) |
@@ -825,6 +897,77 @@ xfs_dir2_leafn_rebalance( | |||
825 | } | 897 | } |
826 | } | 898 | } |
827 | 899 | ||
900 | static int | ||
901 | xfs_dir2_data_block_free( | ||
902 | xfs_da_args_t *args, | ||
903 | struct xfs_dir2_data_hdr *hdr, | ||
904 | struct xfs_dir2_free *free, | ||
905 | xfs_dir2_db_t fdb, | ||
906 | int findex, | ||
907 | struct xfs_buf *fbp, | ||
908 | int longest) | ||
909 | { | ||
910 | struct xfs_trans *tp = args->trans; | ||
911 | int logfree = 0; | ||
912 | |||
913 | if (!hdr) { | ||
914 | /* One less used entry in the free table. */ | ||
915 | be32_add_cpu(&free->hdr.nused, -1); | ||
916 | xfs_dir2_free_log_header(tp, fbp); | ||
917 | |||
918 | /* | ||
919 | * If this was the last entry in the table, we can trim the | ||
920 | * table size back. There might be other entries at the end | ||
921 | * referring to non-existent data blocks, get those too. | ||
922 | */ | ||
923 | if (findex == be32_to_cpu(free->hdr.nvalid) - 1) { | ||
924 | int i; /* free entry index */ | ||
925 | |||
926 | for (i = findex - 1; i >= 0; i--) { | ||
927 | if (free->bests[i] != cpu_to_be16(NULLDATAOFF)) | ||
928 | break; | ||
929 | } | ||
930 | free->hdr.nvalid = cpu_to_be32(i + 1); | ||
931 | logfree = 0; | ||
932 | } else { | ||
933 | /* Not the last entry, just punch it out. */ | ||
934 | free->bests[findex] = cpu_to_be16(NULLDATAOFF); | ||
935 | logfree = 1; | ||
936 | } | ||
937 | /* | ||
938 | * If there are no useful entries left in the block, | ||
939 | * get rid of the block if we can. | ||
940 | */ | ||
941 | if (!free->hdr.nused) { | ||
942 | int error; | ||
943 | |||
944 | error = xfs_dir2_shrink_inode(args, fdb, fbp); | ||
945 | if (error == 0) { | ||
946 | fbp = NULL; | ||
947 | logfree = 0; | ||
948 | } else if (error != ENOSPC || args->total != 0) | ||
949 | return error; | ||
950 | /* | ||
951 | * It's possible to get ENOSPC if there is no | ||
952 | * space reservation. In this case some one | ||
953 | * else will eventually get rid of this block. | ||
954 | */ | ||
955 | } | ||
956 | } else { | ||
957 | /* | ||
958 | * Data block is not empty, just set the free entry to the new | ||
959 | * value. | ||
960 | */ | ||
961 | free->bests[findex] = cpu_to_be16(longest); | ||
962 | logfree = 1; | ||
963 | } | ||
964 | |||
965 | /* Log the free entry that changed, unless we got rid of it. */ | ||
966 | if (logfree) | ||
967 | xfs_dir2_free_log_bests(tp, fbp, findex, findex); | ||
968 | return 0; | ||
969 | } | ||
970 | |||
828 | /* | 971 | /* |
829 | * Remove an entry from a node directory. | 972 | * Remove an entry from a node directory. |
830 | * This removes the leaf entry and the data entry, | 973 | * This removes the leaf entry and the data entry, |
@@ -908,17 +1051,16 @@ xfs_dir2_leafn_remove( | |||
908 | xfs_dir2_db_t fdb; /* freeblock block number */ | 1051 | xfs_dir2_db_t fdb; /* freeblock block number */ |
909 | int findex; /* index in freeblock entries */ | 1052 | int findex; /* index in freeblock entries */ |
910 | xfs_dir2_free_t *free; /* freeblock structure */ | 1053 | xfs_dir2_free_t *free; /* freeblock structure */ |
911 | int logfree; /* need to log free entry */ | ||
912 | 1054 | ||
913 | /* | 1055 | /* |
914 | * Convert the data block number to a free block, | 1056 | * Convert the data block number to a free block, |
915 | * read in the free block. | 1057 | * read in the free block. |
916 | */ | 1058 | */ |
917 | fdb = xfs_dir2_db_to_fdb(mp, db); | 1059 | fdb = xfs_dir2_db_to_fdb(mp, db); |
918 | if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), | 1060 | error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb), |
919 | -1, &fbp, XFS_DATA_FORK))) { | 1061 | &fbp); |
1062 | if (error) | ||
920 | return error; | 1063 | return error; |
921 | } | ||
922 | free = fbp->b_addr; | 1064 | free = fbp->b_addr; |
923 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 1065 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); |
924 | ASSERT(be32_to_cpu(free->hdr.firstdb) == | 1066 | ASSERT(be32_to_cpu(free->hdr.firstdb) == |
@@ -954,68 +1096,12 @@ xfs_dir2_leafn_remove( | |||
954 | * If we got rid of the data block, we can eliminate that entry | 1096 | * If we got rid of the data block, we can eliminate that entry |
955 | * in the free block. | 1097 | * in the free block. |
956 | */ | 1098 | */ |
957 | if (hdr == NULL) { | 1099 | error = xfs_dir2_data_block_free(args, hdr, free, |
958 | /* | 1100 | fdb, findex, fbp, longest); |
959 | * One less used entry in the free table. | 1101 | if (error) |
960 | */ | 1102 | return error; |
961 | be32_add_cpu(&free->hdr.nused, -1); | ||
962 | xfs_dir2_free_log_header(tp, fbp); | ||
963 | /* | ||
964 | * If this was the last entry in the table, we can | ||
965 | * trim the table size back. There might be other | ||
966 | * entries at the end referring to non-existent | ||
967 | * data blocks, get those too. | ||
968 | */ | ||
969 | if (findex == be32_to_cpu(free->hdr.nvalid) - 1) { | ||
970 | int i; /* free entry index */ | ||
971 | |||
972 | for (i = findex - 1; | ||
973 | i >= 0 && | ||
974 | free->bests[i] == cpu_to_be16(NULLDATAOFF); | ||
975 | i--) | ||
976 | continue; | ||
977 | free->hdr.nvalid = cpu_to_be32(i + 1); | ||
978 | logfree = 0; | ||
979 | } | ||
980 | /* | ||
981 | * Not the last entry, just punch it out. | ||
982 | */ | ||
983 | else { | ||
984 | free->bests[findex] = cpu_to_be16(NULLDATAOFF); | ||
985 | logfree = 1; | ||
986 | } | ||
987 | /* | ||
988 | * If there are no useful entries left in the block, | ||
989 | * get rid of the block if we can. | ||
990 | */ | ||
991 | if (!free->hdr.nused) { | ||
992 | error = xfs_dir2_shrink_inode(args, fdb, fbp); | ||
993 | if (error == 0) { | ||
994 | fbp = NULL; | ||
995 | logfree = 0; | ||
996 | } else if (error != ENOSPC || args->total != 0) | ||
997 | return error; | ||
998 | /* | ||
999 | * It's possible to get ENOSPC if there is no | ||
1000 | * space reservation. In this case some one | ||
1001 | * else will eventually get rid of this block. | ||
1002 | */ | ||
1003 | } | ||
1004 | } | ||
1005 | /* | ||
1006 | * Data block is not empty, just set the free entry to | ||
1007 | * the new value. | ||
1008 | */ | ||
1009 | else { | ||
1010 | free->bests[findex] = cpu_to_be16(longest); | ||
1011 | logfree = 1; | ||
1012 | } | ||
1013 | /* | ||
1014 | * Log the free entry that changed, unless we got rid of it. | ||
1015 | */ | ||
1016 | if (logfree) | ||
1017 | xfs_dir2_free_log_bests(tp, fbp, findex, findex); | ||
1018 | } | 1103 | } |
1104 | |||
1019 | xfs_dir2_leafn_check(dp, bp); | 1105 | xfs_dir2_leafn_check(dp, bp); |
1020 | /* | 1106 | /* |
1021 | * Return indication of whether this leaf block is empty enough | 1107 | * Return indication of whether this leaf block is empty enough |
@@ -1169,12 +1255,11 @@ xfs_dir2_leafn_toosmall( | |||
1169 | /* | 1255 | /* |
1170 | * Read the sibling leaf block. | 1256 | * Read the sibling leaf block. |
1171 | */ | 1257 | */ |
1172 | if ((error = | 1258 | error = xfs_dir2_leafn_read(state->args->trans, state->args->dp, |
1173 | xfs_da_read_buf(state->args->trans, state->args->dp, blkno, | 1259 | blkno, -1, &bp); |
1174 | -1, &bp, XFS_DATA_FORK))) { | 1260 | if (error) |
1175 | return error; | 1261 | return error; |
1176 | } | 1262 | |
1177 | ASSERT(bp != NULL); | ||
1178 | /* | 1263 | /* |
1179 | * Count bytes in the two blocks combined. | 1264 | * Count bytes in the two blocks combined. |
1180 | */ | 1265 | */ |
@@ -1454,14 +1539,13 @@ xfs_dir2_node_addname_int( | |||
1454 | * This should be really rare, so there's no reason | 1539 | * This should be really rare, so there's no reason |
1455 | * to avoid it. | 1540 | * to avoid it. |
1456 | */ | 1541 | */ |
1457 | if ((error = xfs_da_read_buf(tp, dp, | 1542 | error = xfs_dir2_free_try_read(tp, dp, |
1458 | xfs_dir2_db_to_da(mp, fbno), -2, &fbp, | 1543 | xfs_dir2_db_to_da(mp, fbno), |
1459 | XFS_DATA_FORK))) { | 1544 | &fbp); |
1545 | if (error) | ||
1460 | return error; | 1546 | return error; |
1461 | } | 1547 | if (!fbp) |
1462 | if (unlikely(fbp == NULL)) { | ||
1463 | continue; | 1548 | continue; |
1464 | } | ||
1465 | free = fbp->b_addr; | 1549 | free = fbp->b_addr; |
1466 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 1550 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); |
1467 | findex = 0; | 1551 | findex = 0; |
@@ -1520,9 +1604,10 @@ xfs_dir2_node_addname_int( | |||
1520 | * that was just allocated. | 1604 | * that was just allocated. |
1521 | */ | 1605 | */ |
1522 | fbno = xfs_dir2_db_to_fdb(mp, dbno); | 1606 | fbno = xfs_dir2_db_to_fdb(mp, dbno); |
1523 | if (unlikely(error = xfs_da_read_buf(tp, dp, | 1607 | error = xfs_dir2_free_try_read(tp, dp, |
1524 | xfs_dir2_db_to_da(mp, fbno), -2, &fbp, | 1608 | xfs_dir2_db_to_da(mp, fbno), |
1525 | XFS_DATA_FORK))) | 1609 | &fbp); |
1610 | if (error) | ||
1526 | return error; | 1611 | return error; |
1527 | 1612 | ||
1528 | /* | 1613 | /* |
@@ -1561,12 +1646,12 @@ xfs_dir2_node_addname_int( | |||
1561 | /* | 1646 | /* |
1562 | * Get a buffer for the new block. | 1647 | * Get a buffer for the new block. |
1563 | */ | 1648 | */ |
1564 | if ((error = xfs_da_get_buf(tp, dp, | 1649 | error = xfs_da_get_buf(tp, dp, |
1565 | xfs_dir2_db_to_da(mp, fbno), | 1650 | xfs_dir2_db_to_da(mp, fbno), |
1566 | -1, &fbp, XFS_DATA_FORK))) { | 1651 | -1, &fbp, XFS_DATA_FORK); |
1652 | if (error) | ||
1567 | return error; | 1653 | return error; |
1568 | } | 1654 | fbp->b_ops = &xfs_dir2_free_buf_ops; |
1569 | ASSERT(fbp != NULL); | ||
1570 | 1655 | ||
1571 | /* | 1656 | /* |
1572 | * Initialize the new block to be empty, and remember | 1657 | * Initialize the new block to be empty, and remember |
@@ -1630,8 +1715,8 @@ xfs_dir2_node_addname_int( | |||
1630 | /* | 1715 | /* |
1631 | * Read the data block in. | 1716 | * Read the data block in. |
1632 | */ | 1717 | */ |
1633 | error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno), | 1718 | error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno), |
1634 | -1, &dbp, XFS_DATA_FORK); | 1719 | -1, &dbp); |
1635 | if (error) | 1720 | if (error) |
1636 | return error; | 1721 | return error; |
1637 | hdr = dbp->b_addr; | 1722 | hdr = dbp->b_addr; |
@@ -1917,18 +2002,15 @@ xfs_dir2_node_trim_free( | |||
1917 | /* | 2002 | /* |
1918 | * Read the freespace block. | 2003 | * Read the freespace block. |
1919 | */ | 2004 | */ |
1920 | if (unlikely(error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp, | 2005 | error = xfs_dir2_free_try_read(tp, dp, fo, &bp); |
1921 | XFS_DATA_FORK))) { | 2006 | if (error) |
1922 | return error; | 2007 | return error; |
1923 | } | ||
1924 | |||
1925 | /* | 2008 | /* |
1926 | * There can be holes in freespace. If fo is a hole, there's | 2009 | * There can be holes in freespace. If fo is a hole, there's |
1927 | * nothing to do. | 2010 | * nothing to do. |
1928 | */ | 2011 | */ |
1929 | if (bp == NULL) { | 2012 | if (!bp) |
1930 | return 0; | 2013 | return 0; |
1931 | } | ||
1932 | free = bp->b_addr; | 2014 | free = bp->b_addr; |
1933 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 2015 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); |
1934 | /* | 2016 | /* |