diff options
author | Dave Chinner <dchinner@redhat.com> | 2013-04-24 04:58:55 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-04-27 13:45:01 -0400 |
commit | 517c22207b045993a6529e1f8684095adaae9cf3 (patch) | |
tree | 3ce1f91a7334f878a28ef032f97706a5b15619c0 /fs/xfs/xfs_attr_leaf.c | |
parent | f5ea110044fa858925a880b4fa9f551bfa2dfc38 (diff) |
xfs: add CRCs to attr leaf blocks
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_attr_leaf.c')
-rw-r--r-- | fs/xfs/xfs_attr_leaf.c | 1740 |
1 files changed, 990 insertions, 750 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 54b0dc8cc82c..7f8b6c8a483f 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
3 | * Copyright (c) 2013 Red Hat, Inc. | ||
3 | * All Rights Reserved. | 4 | * All Rights Reserved. |
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -39,6 +40,9 @@ | |||
39 | #include "xfs_attr_leaf.h" | 40 | #include "xfs_attr_leaf.h" |
40 | #include "xfs_error.h" | 41 | #include "xfs_error.h" |
41 | #include "xfs_trace.h" | 42 | #include "xfs_trace.h" |
43 | #include "xfs_buf_item.h" | ||
44 | #include "xfs_cksum.h" | ||
45 | |||
42 | 46 | ||
43 | /* | 47 | /* |
44 | * xfs_attr_leaf.c | 48 | * xfs_attr_leaf.c |
@@ -53,77 +57,213 @@ | |||
53 | /* | 57 | /* |
54 | * Routines used for growing the Btree. | 58 | * Routines used for growing the Btree. |
55 | */ | 59 | */ |
56 | STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block, | 60 | STATIC int xfs_attr3_leaf_create(struct xfs_da_args *args, |
57 | struct xfs_buf **bpp); | 61 | xfs_dablk_t which_block, struct xfs_buf **bpp); |
58 | STATIC int xfs_attr_leaf_add_work(struct xfs_buf *leaf_buffer, | 62 | STATIC int xfs_attr3_leaf_add_work(struct xfs_buf *leaf_buffer, |
59 | xfs_da_args_t *args, int freemap_index); | 63 | struct xfs_attr3_icleaf_hdr *ichdr, |
60 | STATIC void xfs_attr_leaf_compact(struct xfs_da_args *args, | 64 | struct xfs_da_args *args, int freemap_index); |
61 | struct xfs_buf *leaf_buffer); | 65 | STATIC void xfs_attr3_leaf_compact(struct xfs_da_args *args, |
62 | STATIC void xfs_attr_leaf_rebalance(xfs_da_state_t *state, | 66 | struct xfs_attr3_icleaf_hdr *ichdr, |
67 | struct xfs_buf *leaf_buffer); | ||
68 | STATIC void xfs_attr3_leaf_rebalance(xfs_da_state_t *state, | ||
63 | xfs_da_state_blk_t *blk1, | 69 | xfs_da_state_blk_t *blk1, |
64 | xfs_da_state_blk_t *blk2); | 70 | xfs_da_state_blk_t *blk2); |
65 | STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | 71 | STATIC int xfs_attr3_leaf_figure_balance(xfs_da_state_t *state, |
66 | xfs_da_state_blk_t *leaf_blk_1, | 72 | xfs_da_state_blk_t *leaf_blk_1, |
67 | xfs_da_state_blk_t *leaf_blk_2, | 73 | struct xfs_attr3_icleaf_hdr *ichdr1, |
68 | int *number_entries_in_blk1, | 74 | xfs_da_state_blk_t *leaf_blk_2, |
69 | int *number_usedbytes_in_blk1); | 75 | struct xfs_attr3_icleaf_hdr *ichdr2, |
76 | int *number_entries_in_blk1, | ||
77 | int *number_usedbytes_in_blk1); | ||
70 | 78 | ||
71 | /* | 79 | /* |
72 | * Routines used for shrinking the Btree. | 80 | * Routines used for shrinking the Btree. |
73 | */ | 81 | */ |
74 | STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, | 82 | STATIC int xfs_attr3_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, |
75 | struct xfs_buf *bp, int level); | 83 | struct xfs_buf *bp, int level); |
76 | STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, | 84 | STATIC int xfs_attr3_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, |
77 | struct xfs_buf *bp); | 85 | struct xfs_buf *bp); |
78 | STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, | 86 | STATIC int xfs_attr3_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, |
79 | xfs_dablk_t blkno, int blkcnt); | 87 | xfs_dablk_t blkno, int blkcnt); |
80 | 88 | ||
81 | /* | 89 | /* |
82 | * Utility routines. | 90 | * Utility routines. |
83 | */ | 91 | */ |
84 | STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf, | 92 | STATIC void xfs_attr3_leaf_moveents(struct xfs_attr_leafblock *src_leaf, |
85 | int src_start, | 93 | struct xfs_attr3_icleaf_hdr *src_ichdr, int src_start, |
86 | xfs_attr_leafblock_t *dst_leaf, | 94 | struct xfs_attr_leafblock *dst_leaf, |
87 | int dst_start, int move_count, | 95 | struct xfs_attr3_icleaf_hdr *dst_ichdr, int dst_start, |
88 | xfs_mount_t *mp); | 96 | int move_count, struct xfs_mount *mp); |
89 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); | 97 | STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index); |
90 | 98 | ||
91 | static void | 99 | void |
92 | xfs_attr_leaf_verify( | 100 | xfs_attr3_leaf_hdr_from_disk( |
101 | struct xfs_attr3_icleaf_hdr *to, | ||
102 | struct xfs_attr_leafblock *from) | ||
103 | { | ||
104 | int i; | ||
105 | |||
106 | ASSERT(from->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC) || | ||
107 | from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)); | ||
108 | |||
109 | if (from->hdr.info.magic == cpu_to_be16(XFS_ATTR3_LEAF_MAGIC)) { | ||
110 | struct xfs_attr3_leaf_hdr *hdr3 = (struct xfs_attr3_leaf_hdr *)from; | ||
111 | |||
112 | to->forw = be32_to_cpu(hdr3->info.hdr.forw); | ||
113 | to->back = be32_to_cpu(hdr3->info.hdr.back); | ||
114 | to->magic = be16_to_cpu(hdr3->info.hdr.magic); | ||
115 | to->count = be16_to_cpu(hdr3->count); | ||
116 | to->usedbytes = be16_to_cpu(hdr3->usedbytes); | ||
117 | to->firstused = be16_to_cpu(hdr3->firstused); | ||
118 | to->holes = hdr3->holes; | ||
119 | |||
120 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | ||
121 | to->freemap[i].base = be16_to_cpu(hdr3->freemap[i].base); | ||
122 | to->freemap[i].size = be16_to_cpu(hdr3->freemap[i].size); | ||
123 | } | ||
124 | return; | ||
125 | } | ||
126 | to->forw = be32_to_cpu(from->hdr.info.forw); | ||
127 | to->back = be32_to_cpu(from->hdr.info.back); | ||
128 | to->magic = be16_to_cpu(from->hdr.info.magic); | ||
129 | to->count = be16_to_cpu(from->hdr.count); | ||
130 | to->usedbytes = be16_to_cpu(from->hdr.usedbytes); | ||
131 | to->firstused = be16_to_cpu(from->hdr.firstused); | ||
132 | to->holes = from->hdr.holes; | ||
133 | |||
134 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | ||
135 | to->freemap[i].base = be16_to_cpu(from->hdr.freemap[i].base); | ||
136 | to->freemap[i].size = be16_to_cpu(from->hdr.freemap[i].size); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | void | ||
141 | xfs_attr3_leaf_hdr_to_disk( | ||
142 | struct xfs_attr_leafblock *to, | ||
143 | struct xfs_attr3_icleaf_hdr *from) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | ASSERT(from->magic == XFS_ATTR_LEAF_MAGIC || | ||
148 | from->magic == XFS_ATTR3_LEAF_MAGIC); | ||
149 | |||
150 | if (from->magic == XFS_ATTR3_LEAF_MAGIC) { | ||
151 | struct xfs_attr3_leaf_hdr *hdr3 = (struct xfs_attr3_leaf_hdr *)to; | ||
152 | |||
153 | hdr3->info.hdr.forw = cpu_to_be32(from->forw); | ||
154 | hdr3->info.hdr.back = cpu_to_be32(from->back); | ||
155 | hdr3->info.hdr.magic = cpu_to_be16(from->magic); | ||
156 | hdr3->count = cpu_to_be16(from->count); | ||
157 | hdr3->usedbytes = cpu_to_be16(from->usedbytes); | ||
158 | hdr3->firstused = cpu_to_be16(from->firstused); | ||
159 | hdr3->holes = from->holes; | ||
160 | hdr3->pad1 = 0; | ||
161 | |||
162 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | ||
163 | hdr3->freemap[i].base = cpu_to_be16(from->freemap[i].base); | ||
164 | hdr3->freemap[i].size = cpu_to_be16(from->freemap[i].size); | ||
165 | } | ||
166 | return; | ||
167 | } | ||
168 | to->hdr.info.forw = cpu_to_be32(from->forw); | ||
169 | to->hdr.info.back = cpu_to_be32(from->back); | ||
170 | to->hdr.info.magic = cpu_to_be16(from->magic); | ||
171 | to->hdr.count = cpu_to_be16(from->count); | ||
172 | to->hdr.usedbytes = cpu_to_be16(from->usedbytes); | ||
173 | to->hdr.firstused = cpu_to_be16(from->firstused); | ||
174 | to->hdr.holes = from->holes; | ||
175 | to->hdr.pad1 = 0; | ||
176 | |||
177 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { | ||
178 | to->hdr.freemap[i].base = cpu_to_be16(from->freemap[i].base); | ||
179 | to->hdr.freemap[i].size = cpu_to_be16(from->freemap[i].size); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | static bool | ||
184 | xfs_attr3_leaf_verify( | ||
93 | struct xfs_buf *bp) | 185 | struct xfs_buf *bp) |
94 | { | 186 | { |
95 | struct xfs_mount *mp = bp->b_target->bt_mount; | 187 | struct xfs_mount *mp = bp->b_target->bt_mount; |
96 | struct xfs_attr_leaf_hdr *hdr = bp->b_addr; | 188 | struct xfs_attr_leafblock *leaf = bp->b_addr; |
97 | int block_ok = 0; | 189 | struct xfs_attr3_icleaf_hdr ichdr; |
98 | 190 | ||
99 | block_ok = hdr->info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC); | 191 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
100 | if (!block_ok) { | 192 | |
101 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); | 193 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
102 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 194 | struct xfs_da3_node_hdr *hdr3 = bp->b_addr; |
195 | |||
196 | if (ichdr.magic != XFS_ATTR3_LEAF_MAGIC) | ||
197 | return false; | ||
198 | |||
199 | if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_uuid)) | ||
200 | return false; | ||
201 | if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) | ||
202 | return false; | ||
203 | } else { | ||
204 | if (ichdr.magic != XFS_ATTR_LEAF_MAGIC) | ||
205 | return false; | ||
103 | } | 206 | } |
207 | if (ichdr.count == 0) | ||
208 | return false; | ||
209 | |||
210 | /* XXX: need to range check rest of attr header values */ | ||
211 | /* XXX: hash order check? */ | ||
212 | |||
213 | return true; | ||
104 | } | 214 | } |
105 | 215 | ||
106 | static void | 216 | static void |
107 | xfs_attr_leaf_read_verify( | 217 | xfs_attr3_leaf_write_verify( |
108 | struct xfs_buf *bp) | 218 | struct xfs_buf *bp) |
109 | { | 219 | { |
110 | xfs_attr_leaf_verify(bp); | 220 | struct xfs_mount *mp = bp->b_target->bt_mount; |
221 | struct xfs_buf_log_item *bip = bp->b_fspriv; | ||
222 | struct xfs_attr3_leaf_hdr *hdr3 = bp->b_addr; | ||
223 | |||
224 | if (!xfs_attr3_leaf_verify(bp)) { | ||
225 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
226 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
231 | return; | ||
232 | |||
233 | if (bip) | ||
234 | hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
235 | |||
236 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_ATTR3_LEAF_CRC_OFF); | ||
111 | } | 237 | } |
112 | 238 | ||
239 | /* | ||
240 | * leaf/node format detection on trees is sketchy, so a node read can be done on | ||
241 | * leaf level blocks when detection identifies the tree as a node format tree | ||
242 | * incorrectly. In this case, we need to swap the verifier to match the correct | ||
243 | * format of the block being read. | ||
244 | */ | ||
113 | static void | 245 | static void |
114 | xfs_attr_leaf_write_verify( | 246 | xfs_attr3_leaf_read_verify( |
115 | struct xfs_buf *bp) | 247 | struct xfs_buf *bp) |
116 | { | 248 | { |
117 | xfs_attr_leaf_verify(bp); | 249 | struct xfs_mount *mp = bp->b_target->bt_mount; |
250 | |||
251 | if ((xfs_sb_version_hascrc(&mp->m_sb) && | ||
252 | !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
253 | XFS_ATTR3_LEAF_CRC_OFF)) || | ||
254 | !xfs_attr3_leaf_verify(bp)) { | ||
255 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
256 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
257 | } | ||
118 | } | 258 | } |
119 | 259 | ||
120 | const struct xfs_buf_ops xfs_attr_leaf_buf_ops = { | 260 | const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = { |
121 | .verify_read = xfs_attr_leaf_read_verify, | 261 | .verify_read = xfs_attr3_leaf_read_verify, |
122 | .verify_write = xfs_attr_leaf_write_verify, | 262 | .verify_write = xfs_attr3_leaf_write_verify, |
123 | }; | 263 | }; |
124 | 264 | ||
125 | int | 265 | int |
126 | xfs_attr_leaf_read( | 266 | xfs_attr3_leaf_read( |
127 | struct xfs_trans *tp, | 267 | struct xfs_trans *tp, |
128 | struct xfs_inode *dp, | 268 | struct xfs_inode *dp, |
129 | xfs_dablk_t bno, | 269 | xfs_dablk_t bno, |
@@ -131,7 +271,7 @@ xfs_attr_leaf_read( | |||
131 | struct xfs_buf **bpp) | 271 | struct xfs_buf **bpp) |
132 | { | 272 | { |
133 | return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, | 273 | return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, |
134 | XFS_ATTR_FORK, &xfs_attr_leaf_buf_ops); | 274 | XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops); |
135 | } | 275 | } |
136 | 276 | ||
137 | /*======================================================================== | 277 | /*======================================================================== |
@@ -559,7 +699,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) | |||
559 | } | 699 | } |
560 | 700 | ||
561 | ASSERT(blkno == 0); | 701 | ASSERT(blkno == 0); |
562 | error = xfs_attr_leaf_create(args, blkno, &bp); | 702 | error = xfs_attr3_leaf_create(args, blkno, &bp); |
563 | if (error) { | 703 | if (error) { |
564 | error = xfs_da_shrink_inode(args, 0, bp); | 704 | error = xfs_da_shrink_inode(args, 0, bp); |
565 | bp = NULL; | 705 | bp = NULL; |
@@ -588,9 +728,9 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) | |||
588 | nargs.hashval = xfs_da_hashname(sfe->nameval, | 728 | nargs.hashval = xfs_da_hashname(sfe->nameval, |
589 | sfe->namelen); | 729 | sfe->namelen); |
590 | nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags); | 730 | nargs.flags = XFS_ATTR_NSP_ONDISK_TO_ARGS(sfe->flags); |
591 | error = xfs_attr_leaf_lookup_int(bp, &nargs); /* set a->index */ | 731 | error = xfs_attr3_leaf_lookup_int(bp, &nargs); /* set a->index */ |
592 | ASSERT(error == ENOATTR); | 732 | ASSERT(error == ENOATTR); |
593 | error = xfs_attr_leaf_add(bp, &nargs); | 733 | error = xfs_attr3_leaf_add(bp, &nargs); |
594 | ASSERT(error != ENOSPC); | 734 | ASSERT(error != ENOSPC); |
595 | if (error) | 735 | if (error) |
596 | goto out; | 736 | goto out; |
@@ -803,7 +943,7 @@ xfs_attr_shortform_allfit( | |||
803 | continue; /* don't copy partial entries */ | 943 | continue; /* don't copy partial entries */ |
804 | if (!(entry->flags & XFS_ATTR_LOCAL)) | 944 | if (!(entry->flags & XFS_ATTR_LOCAL)) |
805 | return(0); | 945 | return(0); |
806 | name_loc = xfs_attr_leaf_name_local(leaf, i); | 946 | name_loc = xfs_attr3_leaf_name_local(leaf, i); |
807 | if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX) | 947 | if (name_loc->namelen >= XFS_ATTR_SF_ENTSIZE_MAX) |
808 | return(0); | 948 | return(0); |
809 | if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) | 949 | if (be16_to_cpu(name_loc->valuelen) >= XFS_ATTR_SF_ENTSIZE_MAX) |
@@ -823,29 +963,34 @@ xfs_attr_shortform_allfit( | |||
823 | * Convert a leaf attribute list to shortform attribute list | 963 | * Convert a leaf attribute list to shortform attribute list |
824 | */ | 964 | */ |
825 | int | 965 | int |
826 | xfs_attr_leaf_to_shortform( | 966 | xfs_attr3_leaf_to_shortform( |
827 | struct xfs_buf *bp, | 967 | struct xfs_buf *bp, |
828 | xfs_da_args_t *args, | 968 | struct xfs_da_args *args, |
829 | int forkoff) | 969 | int forkoff) |
830 | { | 970 | { |
831 | xfs_attr_leafblock_t *leaf; | 971 | struct xfs_attr_leafblock *leaf; |
832 | xfs_attr_leaf_entry_t *entry; | 972 | struct xfs_attr3_icleaf_hdr ichdr; |
833 | xfs_attr_leaf_name_local_t *name_loc; | 973 | struct xfs_attr_leaf_entry *entry; |
834 | xfs_da_args_t nargs; | 974 | struct xfs_attr_leaf_name_local *name_loc; |
835 | xfs_inode_t *dp; | 975 | struct xfs_da_args nargs; |
836 | char *tmpbuffer; | 976 | struct xfs_inode *dp = args->dp; |
837 | int error, i; | 977 | char *tmpbuffer; |
978 | int error; | ||
979 | int i; | ||
838 | 980 | ||
839 | trace_xfs_attr_leaf_to_sf(args); | 981 | trace_xfs_attr_leaf_to_sf(args); |
840 | 982 | ||
841 | dp = args->dp; | ||
842 | tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP); | 983 | tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP); |
843 | ASSERT(tmpbuffer != NULL); | 984 | if (!tmpbuffer) |
985 | return ENOMEM; | ||
844 | 986 | ||
845 | ASSERT(bp != NULL); | ||
846 | memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(dp->i_mount)); | 987 | memcpy(tmpbuffer, bp->b_addr, XFS_LBSIZE(dp->i_mount)); |
988 | |||
847 | leaf = (xfs_attr_leafblock_t *)tmpbuffer; | 989 | leaf = (xfs_attr_leafblock_t *)tmpbuffer; |
848 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 990 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
991 | entry = xfs_attr3_leaf_entryp(leaf); | ||
992 | |||
993 | /* XXX (dgc): buffer is about to be marked stale - why zero it? */ | ||
849 | memset(bp->b_addr, 0, XFS_LBSIZE(dp->i_mount)); | 994 | memset(bp->b_addr, 0, XFS_LBSIZE(dp->i_mount)); |
850 | 995 | ||
851 | /* | 996 | /* |
@@ -875,14 +1020,14 @@ xfs_attr_leaf_to_shortform( | |||
875 | nargs.whichfork = XFS_ATTR_FORK; | 1020 | nargs.whichfork = XFS_ATTR_FORK; |
876 | nargs.trans = args->trans; | 1021 | nargs.trans = args->trans; |
877 | nargs.op_flags = XFS_DA_OP_OKNOENT; | 1022 | nargs.op_flags = XFS_DA_OP_OKNOENT; |
878 | entry = &leaf->entries[0]; | 1023 | |
879 | for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { | 1024 | for (i = 0; i < ichdr.count; entry++, i++) { |
880 | if (entry->flags & XFS_ATTR_INCOMPLETE) | 1025 | if (entry->flags & XFS_ATTR_INCOMPLETE) |
881 | continue; /* don't copy partial entries */ | 1026 | continue; /* don't copy partial entries */ |
882 | if (!entry->nameidx) | 1027 | if (!entry->nameidx) |
883 | continue; | 1028 | continue; |
884 | ASSERT(entry->flags & XFS_ATTR_LOCAL); | 1029 | ASSERT(entry->flags & XFS_ATTR_LOCAL); |
885 | name_loc = xfs_attr_leaf_name_local(leaf, i); | 1030 | name_loc = xfs_attr3_leaf_name_local(leaf, i); |
886 | nargs.name = name_loc->nameval; | 1031 | nargs.name = name_loc->nameval; |
887 | nargs.namelen = name_loc->namelen; | 1032 | nargs.namelen = name_loc->namelen; |
888 | nargs.value = &name_loc->nameval[nargs.namelen]; | 1033 | nargs.value = &name_loc->nameval[nargs.namelen]; |
@@ -895,43 +1040,50 @@ xfs_attr_leaf_to_shortform( | |||
895 | 1040 | ||
896 | out: | 1041 | out: |
897 | kmem_free(tmpbuffer); | 1042 | kmem_free(tmpbuffer); |
898 | return(error); | 1043 | return error; |
899 | } | 1044 | } |
900 | 1045 | ||
901 | /* | 1046 | /* |
902 | * Convert from using a single leaf to a root node and a leaf. | 1047 | * Convert from using a single leaf to a root node and a leaf. |
903 | */ | 1048 | */ |
904 | int | 1049 | int |
905 | xfs_attr_leaf_to_node(xfs_da_args_t *args) | 1050 | xfs_attr3_leaf_to_node( |
1051 | struct xfs_da_args *args) | ||
906 | { | 1052 | { |
907 | xfs_attr_leafblock_t *leaf; | 1053 | struct xfs_attr_leafblock *leaf; |
908 | xfs_da_intnode_t *node; | 1054 | struct xfs_attr3_icleaf_hdr icleafhdr; |
909 | xfs_inode_t *dp; | 1055 | struct xfs_attr_leaf_entry *entries; |
910 | struct xfs_buf *bp1, *bp2; | ||
911 | xfs_dablk_t blkno; | ||
912 | int error; | ||
913 | struct xfs_da_node_entry *btree; | 1056 | struct xfs_da_node_entry *btree; |
1057 | struct xfs_da3_icnode_hdr icnodehdr; | ||
1058 | struct xfs_da_intnode *node; | ||
1059 | struct xfs_inode *dp = args->dp; | ||
1060 | struct xfs_mount *mp = dp->i_mount; | ||
1061 | struct xfs_buf *bp1 = NULL; | ||
1062 | struct xfs_buf *bp2 = NULL; | ||
1063 | xfs_dablk_t blkno; | ||
1064 | int error; | ||
914 | 1065 | ||
915 | trace_xfs_attr_leaf_to_node(args); | 1066 | trace_xfs_attr_leaf_to_node(args); |
916 | 1067 | ||
917 | dp = args->dp; | ||
918 | bp1 = bp2 = NULL; | ||
919 | error = xfs_da_grow_inode(args, &blkno); | 1068 | error = xfs_da_grow_inode(args, &blkno); |
920 | if (error) | 1069 | if (error) |
921 | goto out; | 1070 | goto out; |
922 | error = xfs_attr_leaf_read(args->trans, args->dp, 0, -1, &bp1); | 1071 | error = xfs_attr3_leaf_read(args->trans, dp, 0, -1, &bp1); |
923 | if (error) | 1072 | if (error) |
924 | goto out; | 1073 | goto out; |
925 | 1074 | ||
926 | bp2 = NULL; | 1075 | error = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp2, XFS_ATTR_FORK); |
927 | error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp2, | ||
928 | XFS_ATTR_FORK); | ||
929 | if (error) | 1076 | if (error) |
930 | goto out; | 1077 | goto out; |
1078 | |||
1079 | /* copy leaf to new buffer, update identifiers */ | ||
931 | bp2->b_ops = bp1->b_ops; | 1080 | bp2->b_ops = bp1->b_ops; |
932 | memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(dp->i_mount)); | 1081 | memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp)); |
933 | bp1 = NULL; | 1082 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
934 | xfs_trans_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1); | 1083 | struct xfs_da3_blkinfo *hdr3 = bp2->b_addr; |
1084 | hdr3->blkno = cpu_to_be64(bp2->b_bn); | ||
1085 | } | ||
1086 | xfs_trans_log_buf(args->trans, bp2, 0, XFS_LBSIZE(mp) - 1); | ||
935 | 1087 | ||
936 | /* | 1088 | /* |
937 | * Set up the new root node. | 1089 | * Set up the new root node. |
@@ -940,17 +1092,22 @@ xfs_attr_leaf_to_node(xfs_da_args_t *args) | |||
940 | if (error) | 1092 | if (error) |
941 | goto out; | 1093 | goto out; |
942 | node = bp1->b_addr; | 1094 | node = bp1->b_addr; |
1095 | xfs_da3_node_hdr_from_disk(&icnodehdr, node); | ||
1096 | btree = xfs_da3_node_tree_p(node); | ||
1097 | |||
943 | leaf = bp2->b_addr; | 1098 | leaf = bp2->b_addr; |
944 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1099 | xfs_attr3_leaf_hdr_from_disk(&icleafhdr, leaf); |
1100 | entries = xfs_attr3_leaf_entryp(leaf); | ||
1101 | |||
945 | /* both on-disk, don't endian-flip twice */ | 1102 | /* both on-disk, don't endian-flip twice */ |
946 | btree = xfs_da3_node_tree_p(node); | 1103 | btree[0].hashval = entries[icleafhdr.count - 1].hashval; |
947 | btree[0].hashval = leaf->entries[be16_to_cpu(leaf->hdr.count)-1 ].hashval; | ||
948 | btree[0].before = cpu_to_be32(blkno); | 1104 | btree[0].before = cpu_to_be32(blkno); |
949 | node->hdr.count = cpu_to_be16(1); | 1105 | icnodehdr.count = 1; |
950 | xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(dp->i_mount) - 1); | 1106 | xfs_da3_node_hdr_to_disk(node, &icnodehdr); |
1107 | xfs_trans_log_buf(args->trans, bp1, 0, XFS_LBSIZE(mp) - 1); | ||
951 | error = 0; | 1108 | error = 0; |
952 | out: | 1109 | out: |
953 | return(error); | 1110 | return error; |
954 | } | 1111 | } |
955 | 1112 | ||
956 | 1113 | ||
@@ -963,52 +1120,62 @@ out: | |||
963 | * or a leaf in a node attribute list. | 1120 | * or a leaf in a node attribute list. |
964 | */ | 1121 | */ |
965 | STATIC int | 1122 | STATIC int |
966 | xfs_attr_leaf_create( | 1123 | xfs_attr3_leaf_create( |
967 | xfs_da_args_t *args, | 1124 | struct xfs_da_args *args, |
968 | xfs_dablk_t blkno, | 1125 | xfs_dablk_t blkno, |
969 | struct xfs_buf **bpp) | 1126 | struct xfs_buf **bpp) |
970 | { | 1127 | { |
971 | xfs_attr_leafblock_t *leaf; | 1128 | struct xfs_attr_leafblock *leaf; |
972 | xfs_attr_leaf_hdr_t *hdr; | 1129 | struct xfs_attr3_icleaf_hdr ichdr; |
973 | xfs_inode_t *dp; | 1130 | struct xfs_inode *dp = args->dp; |
974 | struct xfs_buf *bp; | 1131 | struct xfs_mount *mp = dp->i_mount; |
975 | int error; | 1132 | struct xfs_buf *bp; |
1133 | int error; | ||
976 | 1134 | ||
977 | trace_xfs_attr_leaf_create(args); | 1135 | trace_xfs_attr_leaf_create(args); |
978 | 1136 | ||
979 | dp = args->dp; | ||
980 | ASSERT(dp != NULL); | ||
981 | error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp, | 1137 | error = xfs_da_get_buf(args->trans, args->dp, blkno, -1, &bp, |
982 | XFS_ATTR_FORK); | 1138 | XFS_ATTR_FORK); |
983 | if (error) | 1139 | if (error) |
984 | return(error); | 1140 | return error; |
985 | bp->b_ops = &xfs_attr_leaf_buf_ops; | 1141 | bp->b_ops = &xfs_attr3_leaf_buf_ops; |
986 | leaf = bp->b_addr; | 1142 | leaf = bp->b_addr; |
987 | memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); | 1143 | memset(leaf, 0, XFS_LBSIZE(mp)); |
988 | hdr = &leaf->hdr; | 1144 | |
989 | hdr->info.magic = cpu_to_be16(XFS_ATTR_LEAF_MAGIC); | 1145 | memset(&ichdr, 0, sizeof(ichdr)); |
990 | hdr->firstused = cpu_to_be16(XFS_LBSIZE(dp->i_mount)); | 1146 | ichdr.firstused = XFS_LBSIZE(mp); |
991 | if (!hdr->firstused) { | 1147 | |
992 | hdr->firstused = cpu_to_be16( | 1148 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
993 | XFS_LBSIZE(dp->i_mount) - XFS_ATTR_LEAF_NAME_ALIGN); | 1149 | struct xfs_da3_blkinfo *hdr3 = bp->b_addr; |
994 | } | 1150 | |
1151 | ichdr.magic = XFS_ATTR3_LEAF_MAGIC; | ||
1152 | |||
1153 | hdr3->blkno = cpu_to_be64(bp->b_bn); | ||
1154 | hdr3->owner = cpu_to_be64(dp->i_ino); | ||
1155 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid); | ||
995 | 1156 | ||
996 | hdr->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); | 1157 | ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr); |
997 | hdr->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr->firstused) - | 1158 | } else { |
998 | sizeof(xfs_attr_leaf_hdr_t)); | 1159 | ichdr.magic = XFS_ATTR_LEAF_MAGIC; |
1160 | ichdr.freemap[0].base = sizeof(struct xfs_attr_leaf_hdr); | ||
1161 | } | ||
1162 | ichdr.freemap[0].size = ichdr.firstused - ichdr.freemap[0].base; | ||
999 | 1163 | ||
1000 | xfs_trans_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); | 1164 | xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); |
1165 | xfs_trans_log_buf(args->trans, bp, 0, XFS_LBSIZE(mp) - 1); | ||
1001 | 1166 | ||
1002 | *bpp = bp; | 1167 | *bpp = bp; |
1003 | return(0); | 1168 | return 0; |
1004 | } | 1169 | } |
1005 | 1170 | ||
1006 | /* | 1171 | /* |
1007 | * Split the leaf node, rebalance, then add the new entry. | 1172 | * Split the leaf node, rebalance, then add the new entry. |
1008 | */ | 1173 | */ |
1009 | int | 1174 | int |
1010 | xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | 1175 | xfs_attr3_leaf_split( |
1011 | xfs_da_state_blk_t *newblk) | 1176 | struct xfs_da_state *state, |
1177 | struct xfs_da_state_blk *oldblk, | ||
1178 | struct xfs_da_state_blk *newblk) | ||
1012 | { | 1179 | { |
1013 | xfs_dablk_t blkno; | 1180 | xfs_dablk_t blkno; |
1014 | int error; | 1181 | int error; |
@@ -1022,7 +1189,7 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | |||
1022 | error = xfs_da_grow_inode(state->args, &blkno); | 1189 | error = xfs_da_grow_inode(state->args, &blkno); |
1023 | if (error) | 1190 | if (error) |
1024 | return(error); | 1191 | return(error); |
1025 | error = xfs_attr_leaf_create(state->args, blkno, &newblk->bp); | 1192 | error = xfs_attr3_leaf_create(state->args, blkno, &newblk->bp); |
1026 | if (error) | 1193 | if (error) |
1027 | return(error); | 1194 | return(error); |
1028 | newblk->blkno = blkno; | 1195 | newblk->blkno = blkno; |
@@ -1032,7 +1199,7 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | |||
1032 | * Rebalance the entries across the two leaves. | 1199 | * Rebalance the entries across the two leaves. |
1033 | * NOTE: rebalance() currently depends on the 2nd block being empty. | 1200 | * NOTE: rebalance() currently depends on the 2nd block being empty. |
1034 | */ | 1201 | */ |
1035 | xfs_attr_leaf_rebalance(state, oldblk, newblk); | 1202 | xfs_attr3_leaf_rebalance(state, oldblk, newblk); |
1036 | error = xfs_da3_blk_link(state, oldblk, newblk); | 1203 | error = xfs_da3_blk_link(state, oldblk, newblk); |
1037 | if (error) | 1204 | if (error) |
1038 | return(error); | 1205 | return(error); |
@@ -1046,10 +1213,10 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | |||
1046 | */ | 1213 | */ |
1047 | if (state->inleaf) { | 1214 | if (state->inleaf) { |
1048 | trace_xfs_attr_leaf_add_old(state->args); | 1215 | trace_xfs_attr_leaf_add_old(state->args); |
1049 | error = xfs_attr_leaf_add(oldblk->bp, state->args); | 1216 | error = xfs_attr3_leaf_add(oldblk->bp, state->args); |
1050 | } else { | 1217 | } else { |
1051 | trace_xfs_attr_leaf_add_new(state->args); | 1218 | trace_xfs_attr_leaf_add_new(state->args); |
1052 | error = xfs_attr_leaf_add(newblk->bp, state->args); | 1219 | error = xfs_attr3_leaf_add(newblk->bp, state->args); |
1053 | } | 1220 | } |
1054 | 1221 | ||
1055 | /* | 1222 | /* |
@@ -1064,22 +1231,23 @@ xfs_attr_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | |||
1064 | * Add a name to the leaf attribute list structure. | 1231 | * Add a name to the leaf attribute list structure. |
1065 | */ | 1232 | */ |
1066 | int | 1233 | int |
1067 | xfs_attr_leaf_add( | 1234 | xfs_attr3_leaf_add( |
1068 | struct xfs_buf *bp, | 1235 | struct xfs_buf *bp, |
1069 | struct xfs_da_args *args) | 1236 | struct xfs_da_args *args) |
1070 | { | 1237 | { |
1071 | xfs_attr_leafblock_t *leaf; | 1238 | struct xfs_attr_leafblock *leaf; |
1072 | xfs_attr_leaf_hdr_t *hdr; | 1239 | struct xfs_attr3_icleaf_hdr ichdr; |
1073 | xfs_attr_leaf_map_t *map; | 1240 | int tablesize; |
1074 | int tablesize, entsize, sum, tmp, i; | 1241 | int entsize; |
1242 | int sum; | ||
1243 | int tmp; | ||
1244 | int i; | ||
1075 | 1245 | ||
1076 | trace_xfs_attr_leaf_add(args); | 1246 | trace_xfs_attr_leaf_add(args); |
1077 | 1247 | ||
1078 | leaf = bp->b_addr; | 1248 | leaf = bp->b_addr; |
1079 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1249 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
1080 | ASSERT((args->index >= 0) | 1250 | ASSERT(args->index >= 0 && args->index <= ichdr.count); |
1081 | && (args->index <= be16_to_cpu(leaf->hdr.count))); | ||
1082 | hdr = &leaf->hdr; | ||
1083 | entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen, | 1251 | entsize = xfs_attr_leaf_newentsize(args->namelen, args->valuelen, |
1084 | args->trans->t_mountp->m_sb.sb_blocksize, NULL); | 1252 | args->trans->t_mountp->m_sb.sb_blocksize, NULL); |
1085 | 1253 | ||
@@ -1087,25 +1255,23 @@ xfs_attr_leaf_add( | |||
1087 | * Search through freemap for first-fit on new name length. | 1255 | * Search through freemap for first-fit on new name length. |
1088 | * (may need to figure in size of entry struct too) | 1256 | * (may need to figure in size of entry struct too) |
1089 | */ | 1257 | */ |
1090 | tablesize = (be16_to_cpu(hdr->count) + 1) | 1258 | tablesize = (ichdr.count + 1) * sizeof(xfs_attr_leaf_entry_t) |
1091 | * sizeof(xfs_attr_leaf_entry_t) | 1259 | + xfs_attr3_leaf_hdr_size(leaf); |
1092 | + sizeof(xfs_attr_leaf_hdr_t); | 1260 | for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE - 1; i >= 0; i--) { |
1093 | map = &hdr->freemap[XFS_ATTR_LEAF_MAPSIZE-1]; | 1261 | if (tablesize > ichdr.firstused) { |
1094 | for (sum = 0, i = XFS_ATTR_LEAF_MAPSIZE-1; i >= 0; map--, i--) { | 1262 | sum += ichdr.freemap[i].size; |
1095 | if (tablesize > be16_to_cpu(hdr->firstused)) { | ||
1096 | sum += be16_to_cpu(map->size); | ||
1097 | continue; | 1263 | continue; |
1098 | } | 1264 | } |
1099 | if (!map->size) | 1265 | if (!ichdr.freemap[i].size) |
1100 | continue; /* no space in this map */ | 1266 | continue; /* no space in this map */ |
1101 | tmp = entsize; | 1267 | tmp = entsize; |
1102 | if (be16_to_cpu(map->base) < be16_to_cpu(hdr->firstused)) | 1268 | if (ichdr.freemap[i].base < ichdr.firstused) |
1103 | tmp += sizeof(xfs_attr_leaf_entry_t); | 1269 | tmp += sizeof(xfs_attr_leaf_entry_t); |
1104 | if (be16_to_cpu(map->size) >= tmp) { | 1270 | if (ichdr.freemap[i].size >= tmp) { |
1105 | tmp = xfs_attr_leaf_add_work(bp, args, i); | 1271 | tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, i); |
1106 | return(tmp); | 1272 | goto out_log_hdr; |
1107 | } | 1273 | } |
1108 | sum += be16_to_cpu(map->size); | 1274 | sum += ichdr.freemap[i].size; |
1109 | } | 1275 | } |
1110 | 1276 | ||
1111 | /* | 1277 | /* |
@@ -1113,82 +1279,89 @@ xfs_attr_leaf_add( | |||
1113 | * and we don't have enough freespace, then compaction will do us | 1279 | * and we don't have enough freespace, then compaction will do us |
1114 | * no good and we should just give up. | 1280 | * no good and we should just give up. |
1115 | */ | 1281 | */ |
1116 | if (!hdr->holes && (sum < entsize)) | 1282 | if (!ichdr.holes && sum < entsize) |
1117 | return(XFS_ERROR(ENOSPC)); | 1283 | return XFS_ERROR(ENOSPC); |
1118 | 1284 | ||
1119 | /* | 1285 | /* |
1120 | * Compact the entries to coalesce free space. | 1286 | * Compact the entries to coalesce free space. |
1121 | * This may change the hdr->count via dropping INCOMPLETE entries. | 1287 | * This may change the hdr->count via dropping INCOMPLETE entries. |
1122 | */ | 1288 | */ |
1123 | xfs_attr_leaf_compact(args, bp); | 1289 | xfs_attr3_leaf_compact(args, &ichdr, bp); |
1124 | 1290 | ||
1125 | /* | 1291 | /* |
1126 | * After compaction, the block is guaranteed to have only one | 1292 | * After compaction, the block is guaranteed to have only one |
1127 | * free region, in freemap[0]. If it is not big enough, give up. | 1293 | * free region, in freemap[0]. If it is not big enough, give up. |
1128 | */ | 1294 | */ |
1129 | if (be16_to_cpu(hdr->freemap[0].size) | 1295 | if (ichdr.freemap[0].size < (entsize + sizeof(xfs_attr_leaf_entry_t))) { |
1130 | < (entsize + sizeof(xfs_attr_leaf_entry_t))) | 1296 | tmp = ENOSPC; |
1131 | return(XFS_ERROR(ENOSPC)); | 1297 | goto out_log_hdr; |
1298 | } | ||
1299 | |||
1300 | tmp = xfs_attr3_leaf_add_work(bp, &ichdr, args, 0); | ||
1132 | 1301 | ||
1133 | return(xfs_attr_leaf_add_work(bp, args, 0)); | 1302 | out_log_hdr: |
1303 | xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); | ||
1304 | xfs_trans_log_buf(args->trans, bp, | ||
1305 | XFS_DA_LOGRANGE(leaf, &leaf->hdr, | ||
1306 | xfs_attr3_leaf_hdr_size(leaf))); | ||
1307 | return tmp; | ||
1134 | } | 1308 | } |
1135 | 1309 | ||
1136 | /* | 1310 | /* |
1137 | * Add a name to a leaf attribute list structure. | 1311 | * Add a name to a leaf attribute list structure. |
1138 | */ | 1312 | */ |
1139 | STATIC int | 1313 | STATIC int |
1140 | xfs_attr_leaf_add_work( | 1314 | xfs_attr3_leaf_add_work( |
1141 | struct xfs_buf *bp, | 1315 | struct xfs_buf *bp, |
1142 | xfs_da_args_t *args, | 1316 | struct xfs_attr3_icleaf_hdr *ichdr, |
1143 | int mapindex) | 1317 | struct xfs_da_args *args, |
1318 | int mapindex) | ||
1144 | { | 1319 | { |
1145 | xfs_attr_leafblock_t *leaf; | 1320 | struct xfs_attr_leafblock *leaf; |
1146 | xfs_attr_leaf_hdr_t *hdr; | 1321 | struct xfs_attr_leaf_entry *entry; |
1147 | xfs_attr_leaf_entry_t *entry; | 1322 | struct xfs_attr_leaf_name_local *name_loc; |
1148 | xfs_attr_leaf_name_local_t *name_loc; | 1323 | struct xfs_attr_leaf_name_remote *name_rmt; |
1149 | xfs_attr_leaf_name_remote_t *name_rmt; | 1324 | struct xfs_mount *mp; |
1150 | xfs_attr_leaf_map_t *map; | 1325 | int tmp; |
1151 | xfs_mount_t *mp; | 1326 | int i; |
1152 | int tmp, i; | ||
1153 | 1327 | ||
1154 | trace_xfs_attr_leaf_add_work(args); | 1328 | trace_xfs_attr_leaf_add_work(args); |
1155 | 1329 | ||
1156 | leaf = bp->b_addr; | 1330 | leaf = bp->b_addr; |
1157 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1331 | ASSERT(mapindex >= 0 && mapindex < XFS_ATTR_LEAF_MAPSIZE); |
1158 | hdr = &leaf->hdr; | 1332 | ASSERT(args->index >= 0 && args->index <= ichdr->count); |
1159 | ASSERT((mapindex >= 0) && (mapindex < XFS_ATTR_LEAF_MAPSIZE)); | ||
1160 | ASSERT((args->index >= 0) && (args->index <= be16_to_cpu(hdr->count))); | ||
1161 | 1333 | ||
1162 | /* | 1334 | /* |
1163 | * Force open some space in the entry array and fill it in. | 1335 | * Force open some space in the entry array and fill it in. |
1164 | */ | 1336 | */ |
1165 | entry = &leaf->entries[args->index]; | 1337 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; |
1166 | if (args->index < be16_to_cpu(hdr->count)) { | 1338 | if (args->index < ichdr->count) { |
1167 | tmp = be16_to_cpu(hdr->count) - args->index; | 1339 | tmp = ichdr->count - args->index; |
1168 | tmp *= sizeof(xfs_attr_leaf_entry_t); | 1340 | tmp *= sizeof(xfs_attr_leaf_entry_t); |
1169 | memmove((char *)(entry+1), (char *)entry, tmp); | 1341 | memmove(entry + 1, entry, tmp); |
1170 | xfs_trans_log_buf(args->trans, bp, | 1342 | xfs_trans_log_buf(args->trans, bp, |
1171 | XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); | 1343 | XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); |
1172 | } | 1344 | } |
1173 | be16_add_cpu(&hdr->count, 1); | 1345 | ichdr->count++; |
1174 | 1346 | ||
1175 | /* | 1347 | /* |
1176 | * Allocate space for the new string (at the end of the run). | 1348 | * Allocate space for the new string (at the end of the run). |
1177 | */ | 1349 | */ |
1178 | map = &hdr->freemap[mapindex]; | ||
1179 | mp = args->trans->t_mountp; | 1350 | mp = args->trans->t_mountp; |
1180 | ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); | 1351 | ASSERT(ichdr->freemap[mapindex].base < XFS_LBSIZE(mp)); |
1181 | ASSERT((be16_to_cpu(map->base) & 0x3) == 0); | 1352 | ASSERT((ichdr->freemap[mapindex].base & 0x3) == 0); |
1182 | ASSERT(be16_to_cpu(map->size) >= | 1353 | ASSERT(ichdr->freemap[mapindex].size >= |
1183 | xfs_attr_leaf_newentsize(args->namelen, args->valuelen, | 1354 | xfs_attr_leaf_newentsize(args->namelen, args->valuelen, |
1184 | mp->m_sb.sb_blocksize, NULL)); | 1355 | mp->m_sb.sb_blocksize, NULL)); |
1185 | ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); | 1356 | ASSERT(ichdr->freemap[mapindex].size < XFS_LBSIZE(mp)); |
1186 | ASSERT((be16_to_cpu(map->size) & 0x3) == 0); | 1357 | ASSERT((ichdr->freemap[mapindex].size & 0x3) == 0); |
1187 | be16_add_cpu(&map->size, | 1358 | |
1188 | -xfs_attr_leaf_newentsize(args->namelen, args->valuelen, | 1359 | ichdr->freemap[mapindex].size -= |
1189 | mp->m_sb.sb_blocksize, &tmp)); | 1360 | xfs_attr_leaf_newentsize(args->namelen, args->valuelen, |
1190 | entry->nameidx = cpu_to_be16(be16_to_cpu(map->base) + | 1361 | mp->m_sb.sb_blocksize, &tmp); |
1191 | be16_to_cpu(map->size)); | 1362 | |
1363 | entry->nameidx = cpu_to_be16(ichdr->freemap[mapindex].base + | ||
1364 | ichdr->freemap[mapindex].size); | ||
1192 | entry->hashval = cpu_to_be32(args->hashval); | 1365 | entry->hashval = cpu_to_be32(args->hashval); |
1193 | entry->flags = tmp ? XFS_ATTR_LOCAL : 0; | 1366 | entry->flags = tmp ? XFS_ATTR_LOCAL : 0; |
1194 | entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); | 1367 | entry->flags |= XFS_ATTR_NSP_ARGS_TO_ONDISK(args->flags); |
@@ -1203,7 +1376,7 @@ xfs_attr_leaf_add_work( | |||
1203 | XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); | 1376 | XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); |
1204 | ASSERT((args->index == 0) || | 1377 | ASSERT((args->index == 0) || |
1205 | (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval))); | 1378 | (be32_to_cpu(entry->hashval) >= be32_to_cpu((entry-1)->hashval))); |
1206 | ASSERT((args->index == be16_to_cpu(hdr->count)-1) || | 1379 | ASSERT((args->index == ichdr->count - 1) || |
1207 | (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval))); | 1380 | (be32_to_cpu(entry->hashval) <= be32_to_cpu((entry+1)->hashval))); |
1208 | 1381 | ||
1209 | /* | 1382 | /* |
@@ -1214,14 +1387,14 @@ xfs_attr_leaf_add_work( | |||
1214 | * as part of this transaction (a split operation for example). | 1387 | * as part of this transaction (a split operation for example). |
1215 | */ | 1388 | */ |
1216 | if (entry->flags & XFS_ATTR_LOCAL) { | 1389 | if (entry->flags & XFS_ATTR_LOCAL) { |
1217 | name_loc = xfs_attr_leaf_name_local(leaf, args->index); | 1390 | name_loc = xfs_attr3_leaf_name_local(leaf, args->index); |
1218 | name_loc->namelen = args->namelen; | 1391 | name_loc->namelen = args->namelen; |
1219 | name_loc->valuelen = cpu_to_be16(args->valuelen); | 1392 | name_loc->valuelen = cpu_to_be16(args->valuelen); |
1220 | memcpy((char *)name_loc->nameval, args->name, args->namelen); | 1393 | memcpy((char *)name_loc->nameval, args->name, args->namelen); |
1221 | memcpy((char *)&name_loc->nameval[args->namelen], args->value, | 1394 | memcpy((char *)&name_loc->nameval[args->namelen], args->value, |
1222 | be16_to_cpu(name_loc->valuelen)); | 1395 | be16_to_cpu(name_loc->valuelen)); |
1223 | } else { | 1396 | } else { |
1224 | name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); | 1397 | name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); |
1225 | name_rmt->namelen = args->namelen; | 1398 | name_rmt->namelen = args->namelen; |
1226 | memcpy((char *)name_rmt->name, args->name, args->namelen); | 1399 | memcpy((char *)name_rmt->name, args->name, args->namelen); |
1227 | entry->flags |= XFS_ATTR_INCOMPLETE; | 1400 | entry->flags |= XFS_ATTR_INCOMPLETE; |
@@ -1232,44 +1405,41 @@ xfs_attr_leaf_add_work( | |||
1232 | args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen); | 1405 | args->rmtblkcnt = XFS_B_TO_FSB(mp, args->valuelen); |
1233 | } | 1406 | } |
1234 | xfs_trans_log_buf(args->trans, bp, | 1407 | xfs_trans_log_buf(args->trans, bp, |
1235 | XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index), | 1408 | XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index), |
1236 | xfs_attr_leaf_entsize(leaf, args->index))); | 1409 | xfs_attr_leaf_entsize(leaf, args->index))); |
1237 | 1410 | ||
1238 | /* | 1411 | /* |
1239 | * Update the control info for this leaf node | 1412 | * Update the control info for this leaf node |
1240 | */ | 1413 | */ |
1241 | if (be16_to_cpu(entry->nameidx) < be16_to_cpu(hdr->firstused)) { | 1414 | if (be16_to_cpu(entry->nameidx) < ichdr->firstused) |
1242 | /* both on-disk, don't endian-flip twice */ | 1415 | ichdr->firstused = be16_to_cpu(entry->nameidx); |
1243 | hdr->firstused = entry->nameidx; | 1416 | |
1244 | } | 1417 | ASSERT(ichdr->firstused >= ichdr->count * sizeof(xfs_attr_leaf_entry_t) |
1245 | ASSERT(be16_to_cpu(hdr->firstused) >= | 1418 | + xfs_attr3_leaf_hdr_size(leaf)); |
1246 | ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr))); | 1419 | tmp = (ichdr->count - 1) * sizeof(xfs_attr_leaf_entry_t) |
1247 | tmp = (be16_to_cpu(hdr->count)-1) * sizeof(xfs_attr_leaf_entry_t) | 1420 | + xfs_attr3_leaf_hdr_size(leaf); |
1248 | + sizeof(xfs_attr_leaf_hdr_t); | 1421 | |
1249 | map = &hdr->freemap[0]; | 1422 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { |
1250 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) { | 1423 | if (ichdr->freemap[i].base == tmp) { |
1251 | if (be16_to_cpu(map->base) == tmp) { | 1424 | ichdr->freemap[i].base += sizeof(xfs_attr_leaf_entry_t); |
1252 | be16_add_cpu(&map->base, sizeof(xfs_attr_leaf_entry_t)); | 1425 | ichdr->freemap[i].size -= sizeof(xfs_attr_leaf_entry_t); |
1253 | be16_add_cpu(&map->size, | ||
1254 | -((int)sizeof(xfs_attr_leaf_entry_t))); | ||
1255 | } | 1426 | } |
1256 | } | 1427 | } |
1257 | be16_add_cpu(&hdr->usedbytes, xfs_attr_leaf_entsize(leaf, args->index)); | 1428 | ichdr->usedbytes += xfs_attr_leaf_entsize(leaf, args->index); |
1258 | xfs_trans_log_buf(args->trans, bp, | 1429 | return 0; |
1259 | XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); | ||
1260 | return(0); | ||
1261 | } | 1430 | } |
1262 | 1431 | ||
1263 | /* | 1432 | /* |
1264 | * Garbage collect a leaf attribute list block by copying it to a new buffer. | 1433 | * Garbage collect a leaf attribute list block by copying it to a new buffer. |
1265 | */ | 1434 | */ |
1266 | STATIC void | 1435 | STATIC void |
1267 | xfs_attr_leaf_compact( | 1436 | xfs_attr3_leaf_compact( |
1268 | struct xfs_da_args *args, | 1437 | struct xfs_da_args *args, |
1438 | struct xfs_attr3_icleaf_hdr *ichdr_d, | ||
1269 | struct xfs_buf *bp) | 1439 | struct xfs_buf *bp) |
1270 | { | 1440 | { |
1271 | xfs_attr_leafblock_t *leaf_s, *leaf_d; | 1441 | xfs_attr_leafblock_t *leaf_s, *leaf_d; |
1272 | xfs_attr_leaf_hdr_t *hdr_s, *hdr_d; | 1442 | struct xfs_attr3_icleaf_hdr ichdr_s; |
1273 | struct xfs_trans *trans = args->trans; | 1443 | struct xfs_trans *trans = args->trans; |
1274 | struct xfs_mount *mp = trans->t_mountp; | 1444 | struct xfs_mount *mp = trans->t_mountp; |
1275 | char *tmpbuffer; | 1445 | char *tmpbuffer; |
@@ -1286,34 +1456,69 @@ xfs_attr_leaf_compact( | |||
1286 | */ | 1456 | */ |
1287 | leaf_s = (xfs_attr_leafblock_t *)tmpbuffer; | 1457 | leaf_s = (xfs_attr_leafblock_t *)tmpbuffer; |
1288 | leaf_d = bp->b_addr; | 1458 | leaf_d = bp->b_addr; |
1289 | hdr_s = &leaf_s->hdr; | 1459 | ichdr_s = *ichdr_d; /* struct copy */ |
1290 | hdr_d = &leaf_d->hdr; | 1460 | ichdr_d->firstused = XFS_LBSIZE(mp); |
1291 | hdr_d->info = hdr_s->info; /* struct copy */ | 1461 | ichdr_d->usedbytes = 0; |
1292 | hdr_d->firstused = cpu_to_be16(XFS_LBSIZE(mp)); | 1462 | ichdr_d->count = 0; |
1293 | /* handle truncation gracefully */ | 1463 | ichdr_d->holes = 0; |
1294 | if (!hdr_d->firstused) { | 1464 | ichdr_d->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_s); |
1295 | hdr_d->firstused = cpu_to_be16( | 1465 | ichdr_d->freemap[0].size = ichdr_d->firstused - ichdr_d->freemap[0].base; |
1296 | XFS_LBSIZE(mp) - XFS_ATTR_LEAF_NAME_ALIGN); | ||
1297 | } | ||
1298 | hdr_d->usedbytes = 0; | ||
1299 | hdr_d->count = 0; | ||
1300 | hdr_d->holes = 0; | ||
1301 | hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); | ||
1302 | hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) - | ||
1303 | sizeof(xfs_attr_leaf_hdr_t)); | ||
1304 | 1466 | ||
1305 | /* | 1467 | /* |
1306 | * Copy all entry's in the same (sorted) order, | 1468 | * Copy all entry's in the same (sorted) order, |
1307 | * but allocate name/value pairs packed and in sequence. | 1469 | * but allocate name/value pairs packed and in sequence. |
1308 | */ | 1470 | */ |
1309 | xfs_attr_leaf_moveents(leaf_s, 0, leaf_d, 0, | 1471 | xfs_attr3_leaf_moveents(leaf_s, &ichdr_s, 0, leaf_d, ichdr_d, 0, |
1310 | be16_to_cpu(hdr_s->count), mp); | 1472 | ichdr_s.count, mp); |
1473 | /* | ||
1474 | * this logs the entire buffer, but the caller must write the header | ||
1475 | * back to the buffer when it is finished modifying it. | ||
1476 | */ | ||
1311 | xfs_trans_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); | 1477 | xfs_trans_log_buf(trans, bp, 0, XFS_LBSIZE(mp) - 1); |
1312 | 1478 | ||
1313 | kmem_free(tmpbuffer); | 1479 | kmem_free(tmpbuffer); |
1314 | } | 1480 | } |
1315 | 1481 | ||
1316 | /* | 1482 | /* |
1483 | * Compare two leaf blocks "order". | ||
1484 | * Return 0 unless leaf2 should go before leaf1. | ||
1485 | */ | ||
1486 | static int | ||
1487 | xfs_attr3_leaf_order( | ||
1488 | struct xfs_buf *leaf1_bp, | ||
1489 | struct xfs_attr3_icleaf_hdr *leaf1hdr, | ||
1490 | struct xfs_buf *leaf2_bp, | ||
1491 | struct xfs_attr3_icleaf_hdr *leaf2hdr) | ||
1492 | { | ||
1493 | struct xfs_attr_leaf_entry *entries1; | ||
1494 | struct xfs_attr_leaf_entry *entries2; | ||
1495 | |||
1496 | entries1 = xfs_attr3_leaf_entryp(leaf1_bp->b_addr); | ||
1497 | entries2 = xfs_attr3_leaf_entryp(leaf2_bp->b_addr); | ||
1498 | if (leaf1hdr->count > 0 && leaf2hdr->count > 0 && | ||
1499 | ((be32_to_cpu(entries2[0].hashval) < | ||
1500 | be32_to_cpu(entries1[0].hashval)) || | ||
1501 | (be32_to_cpu(entries2[leaf2hdr->count - 1].hashval) < | ||
1502 | be32_to_cpu(entries1[leaf1hdr->count - 1].hashval)))) { | ||
1503 | return 1; | ||
1504 | } | ||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | int | ||
1509 | xfs_attr_leaf_order( | ||
1510 | struct xfs_buf *leaf1_bp, | ||
1511 | struct xfs_buf *leaf2_bp) | ||
1512 | { | ||
1513 | struct xfs_attr3_icleaf_hdr ichdr1; | ||
1514 | struct xfs_attr3_icleaf_hdr ichdr2; | ||
1515 | |||
1516 | xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1_bp->b_addr); | ||
1517 | xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2_bp->b_addr); | ||
1518 | return xfs_attr3_leaf_order(leaf1_bp, &ichdr1, leaf2_bp, &ichdr2); | ||
1519 | } | ||
1520 | |||
1521 | /* | ||
1317 | * Redistribute the attribute list entries between two leaf nodes, | 1522 | * Redistribute the attribute list entries between two leaf nodes, |
1318 | * taking into account the size of the new entry. | 1523 | * taking into account the size of the new entry. |
1319 | * | 1524 | * |
@@ -1326,14 +1531,23 @@ xfs_attr_leaf_compact( | |||
1326 | * the "new" and "old" values can end up in different blocks. | 1531 | * the "new" and "old" values can end up in different blocks. |
1327 | */ | 1532 | */ |
1328 | STATIC void | 1533 | STATIC void |
1329 | xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | 1534 | xfs_attr3_leaf_rebalance( |
1330 | xfs_da_state_blk_t *blk2) | 1535 | struct xfs_da_state *state, |
1536 | struct xfs_da_state_blk *blk1, | ||
1537 | struct xfs_da_state_blk *blk2) | ||
1331 | { | 1538 | { |
1332 | xfs_da_args_t *args; | 1539 | struct xfs_da_args *args; |
1333 | xfs_da_state_blk_t *tmp_blk; | 1540 | struct xfs_attr_leafblock *leaf1; |
1334 | xfs_attr_leafblock_t *leaf1, *leaf2; | 1541 | struct xfs_attr_leafblock *leaf2; |
1335 | xfs_attr_leaf_hdr_t *hdr1, *hdr2; | 1542 | struct xfs_attr3_icleaf_hdr ichdr1; |
1336 | int count, totallen, max, space, swap; | 1543 | struct xfs_attr3_icleaf_hdr ichdr2; |
1544 | struct xfs_attr_leaf_entry *entries1; | ||
1545 | struct xfs_attr_leaf_entry *entries2; | ||
1546 | int count; | ||
1547 | int totallen; | ||
1548 | int max; | ||
1549 | int space; | ||
1550 | int swap; | ||
1337 | 1551 | ||
1338 | /* | 1552 | /* |
1339 | * Set up environment. | 1553 | * Set up environment. |
@@ -1342,9 +1556,9 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
1342 | ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC); | 1556 | ASSERT(blk2->magic == XFS_ATTR_LEAF_MAGIC); |
1343 | leaf1 = blk1->bp->b_addr; | 1557 | leaf1 = blk1->bp->b_addr; |
1344 | leaf2 = blk2->bp->b_addr; | 1558 | leaf2 = blk2->bp->b_addr; |
1345 | ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1559 | xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1); |
1346 | ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1560 | xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2); |
1347 | ASSERT(leaf2->hdr.count == 0); | 1561 | ASSERT(ichdr2.count == 0); |
1348 | args = state->args; | 1562 | args = state->args; |
1349 | 1563 | ||
1350 | trace_xfs_attr_leaf_rebalance(args); | 1564 | trace_xfs_attr_leaf_rebalance(args); |
@@ -1356,16 +1570,23 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
1356 | * second block, this code should never set "swap". | 1570 | * second block, this code should never set "swap". |
1357 | */ | 1571 | */ |
1358 | swap = 0; | 1572 | swap = 0; |
1359 | if (xfs_attr_leaf_order(blk1->bp, blk2->bp)) { | 1573 | if (xfs_attr3_leaf_order(blk1->bp, &ichdr1, blk2->bp, &ichdr2)) { |
1574 | struct xfs_da_state_blk *tmp_blk; | ||
1575 | struct xfs_attr3_icleaf_hdr tmp_ichdr; | ||
1576 | |||
1360 | tmp_blk = blk1; | 1577 | tmp_blk = blk1; |
1361 | blk1 = blk2; | 1578 | blk1 = blk2; |
1362 | blk2 = tmp_blk; | 1579 | blk2 = tmp_blk; |
1580 | |||
1581 | /* struct copies to swap them rather than reconverting */ | ||
1582 | tmp_ichdr = ichdr1; | ||
1583 | ichdr1 = ichdr2; | ||
1584 | ichdr2 = tmp_ichdr; | ||
1585 | |||
1363 | leaf1 = blk1->bp->b_addr; | 1586 | leaf1 = blk1->bp->b_addr; |
1364 | leaf2 = blk2->bp->b_addr; | 1587 | leaf2 = blk2->bp->b_addr; |
1365 | swap = 1; | 1588 | swap = 1; |
1366 | } | 1589 | } |
1367 | hdr1 = &leaf1->hdr; | ||
1368 | hdr2 = &leaf2->hdr; | ||
1369 | 1590 | ||
1370 | /* | 1591 | /* |
1371 | * Examine entries until we reduce the absolute difference in | 1592 | * Examine entries until we reduce the absolute difference in |
@@ -1375,41 +1596,39 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
1375 | * "inleaf" is true if the new entry should be inserted into blk1. | 1596 | * "inleaf" is true if the new entry should be inserted into blk1. |
1376 | * If "swap" is also true, then reverse the sense of "inleaf". | 1597 | * If "swap" is also true, then reverse the sense of "inleaf". |
1377 | */ | 1598 | */ |
1378 | state->inleaf = xfs_attr_leaf_figure_balance(state, blk1, blk2, | 1599 | state->inleaf = xfs_attr3_leaf_figure_balance(state, blk1, &ichdr1, |
1379 | &count, &totallen); | 1600 | blk2, &ichdr2, |
1601 | &count, &totallen); | ||
1380 | if (swap) | 1602 | if (swap) |
1381 | state->inleaf = !state->inleaf; | 1603 | state->inleaf = !state->inleaf; |
1382 | 1604 | ||
1383 | /* | 1605 | /* |
1384 | * Move any entries required from leaf to leaf: | 1606 | * Move any entries required from leaf to leaf: |
1385 | */ | 1607 | */ |
1386 | if (count < be16_to_cpu(hdr1->count)) { | 1608 | if (count < ichdr1.count) { |
1387 | /* | 1609 | /* |
1388 | * Figure the total bytes to be added to the destination leaf. | 1610 | * Figure the total bytes to be added to the destination leaf. |
1389 | */ | 1611 | */ |
1390 | /* number entries being moved */ | 1612 | /* number entries being moved */ |
1391 | count = be16_to_cpu(hdr1->count) - count; | 1613 | count = ichdr1.count - count; |
1392 | space = be16_to_cpu(hdr1->usedbytes) - totallen; | 1614 | space = ichdr1.usedbytes - totallen; |
1393 | space += count * sizeof(xfs_attr_leaf_entry_t); | 1615 | space += count * sizeof(xfs_attr_leaf_entry_t); |
1394 | 1616 | ||
1395 | /* | 1617 | /* |
1396 | * leaf2 is the destination, compact it if it looks tight. | 1618 | * leaf2 is the destination, compact it if it looks tight. |
1397 | */ | 1619 | */ |
1398 | max = be16_to_cpu(hdr2->firstused) | 1620 | max = ichdr2.firstused - xfs_attr3_leaf_hdr_size(leaf1); |
1399 | - sizeof(xfs_attr_leaf_hdr_t); | 1621 | max -= ichdr2.count * sizeof(xfs_attr_leaf_entry_t); |
1400 | max -= be16_to_cpu(hdr2->count) * sizeof(xfs_attr_leaf_entry_t); | ||
1401 | if (space > max) | 1622 | if (space > max) |
1402 | xfs_attr_leaf_compact(args, blk2->bp); | 1623 | xfs_attr3_leaf_compact(args, &ichdr2, blk2->bp); |
1403 | 1624 | ||
1404 | /* | 1625 | /* |
1405 | * Move high entries from leaf1 to low end of leaf2. | 1626 | * Move high entries from leaf1 to low end of leaf2. |
1406 | */ | 1627 | */ |
1407 | xfs_attr_leaf_moveents(leaf1, be16_to_cpu(hdr1->count) - count, | 1628 | xfs_attr3_leaf_moveents(leaf1, &ichdr1, ichdr1.count - count, |
1408 | leaf2, 0, count, state->mp); | 1629 | leaf2, &ichdr2, 0, count, state->mp); |
1409 | 1630 | ||
1410 | xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); | 1631 | } else if (count > ichdr1.count) { |
1411 | xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); | ||
1412 | } else if (count > be16_to_cpu(hdr1->count)) { | ||
1413 | /* | 1632 | /* |
1414 | * I assert that since all callers pass in an empty | 1633 | * I assert that since all callers pass in an empty |
1415 | * second buffer, this code should never execute. | 1634 | * second buffer, this code should never execute. |
@@ -1420,36 +1639,37 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
1420 | * Figure the total bytes to be added to the destination leaf. | 1639 | * Figure the total bytes to be added to the destination leaf. |
1421 | */ | 1640 | */ |
1422 | /* number entries being moved */ | 1641 | /* number entries being moved */ |
1423 | count -= be16_to_cpu(hdr1->count); | 1642 | count -= ichdr1.count; |
1424 | space = totallen - be16_to_cpu(hdr1->usedbytes); | 1643 | space = totallen - ichdr1.usedbytes; |
1425 | space += count * sizeof(xfs_attr_leaf_entry_t); | 1644 | space += count * sizeof(xfs_attr_leaf_entry_t); |
1426 | 1645 | ||
1427 | /* | 1646 | /* |
1428 | * leaf1 is the destination, compact it if it looks tight. | 1647 | * leaf1 is the destination, compact it if it looks tight. |
1429 | */ | 1648 | */ |
1430 | max = be16_to_cpu(hdr1->firstused) | 1649 | max = ichdr1.firstused - xfs_attr3_leaf_hdr_size(leaf1); |
1431 | - sizeof(xfs_attr_leaf_hdr_t); | 1650 | max -= ichdr1.count * sizeof(xfs_attr_leaf_entry_t); |
1432 | max -= be16_to_cpu(hdr1->count) * sizeof(xfs_attr_leaf_entry_t); | ||
1433 | if (space > max) | 1651 | if (space > max) |
1434 | xfs_attr_leaf_compact(args, blk1->bp); | 1652 | xfs_attr3_leaf_compact(args, &ichdr1, blk1->bp); |
1435 | 1653 | ||
1436 | /* | 1654 | /* |
1437 | * Move low entries from leaf2 to high end of leaf1. | 1655 | * Move low entries from leaf2 to high end of leaf1. |
1438 | */ | 1656 | */ |
1439 | xfs_attr_leaf_moveents(leaf2, 0, leaf1, | 1657 | xfs_attr3_leaf_moveents(leaf2, &ichdr2, 0, leaf1, &ichdr1, |
1440 | be16_to_cpu(hdr1->count), count, state->mp); | 1658 | ichdr1.count, count, state->mp); |
1441 | |||
1442 | xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); | ||
1443 | xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); | ||
1444 | } | 1659 | } |
1445 | 1660 | ||
1661 | xfs_attr3_leaf_hdr_to_disk(leaf1, &ichdr1); | ||
1662 | xfs_attr3_leaf_hdr_to_disk(leaf2, &ichdr2); | ||
1663 | xfs_trans_log_buf(args->trans, blk1->bp, 0, state->blocksize-1); | ||
1664 | xfs_trans_log_buf(args->trans, blk2->bp, 0, state->blocksize-1); | ||
1665 | |||
1446 | /* | 1666 | /* |
1447 | * Copy out last hashval in each block for B-tree code. | 1667 | * Copy out last hashval in each block for B-tree code. |
1448 | */ | 1668 | */ |
1449 | blk1->hashval = be32_to_cpu( | 1669 | entries1 = xfs_attr3_leaf_entryp(leaf1); |
1450 | leaf1->entries[be16_to_cpu(leaf1->hdr.count)-1].hashval); | 1670 | entries2 = xfs_attr3_leaf_entryp(leaf2); |
1451 | blk2->hashval = be32_to_cpu( | 1671 | blk1->hashval = be32_to_cpu(entries1[ichdr1.count - 1].hashval); |
1452 | leaf2->entries[be16_to_cpu(leaf2->hdr.count)-1].hashval); | 1672 | blk2->hashval = be32_to_cpu(entries2[ichdr2.count - 1].hashval); |
1453 | 1673 | ||
1454 | /* | 1674 | /* |
1455 | * Adjust the expected index for insertion. | 1675 | * Adjust the expected index for insertion. |
@@ -1463,12 +1683,12 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
1463 | * inserting. The index/blkno fields refer to the "old" entry, | 1683 | * inserting. The index/blkno fields refer to the "old" entry, |
1464 | * while the index2/blkno2 fields refer to the "new" entry. | 1684 | * while the index2/blkno2 fields refer to the "new" entry. |
1465 | */ | 1685 | */ |
1466 | if (blk1->index > be16_to_cpu(leaf1->hdr.count)) { | 1686 | if (blk1->index > ichdr1.count) { |
1467 | ASSERT(state->inleaf == 0); | 1687 | ASSERT(state->inleaf == 0); |
1468 | blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); | 1688 | blk2->index = blk1->index - ichdr1.count; |
1469 | args->index = args->index2 = blk2->index; | 1689 | args->index = args->index2 = blk2->index; |
1470 | args->blkno = args->blkno2 = blk2->blkno; | 1690 | args->blkno = args->blkno2 = blk2->blkno; |
1471 | } else if (blk1->index == be16_to_cpu(leaf1->hdr.count)) { | 1691 | } else if (blk1->index == ichdr1.count) { |
1472 | if (state->inleaf) { | 1692 | if (state->inleaf) { |
1473 | args->index = blk1->index; | 1693 | args->index = blk1->index; |
1474 | args->blkno = blk1->blkno; | 1694 | args->blkno = blk1->blkno; |
@@ -1480,8 +1700,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
1480 | * is already stored in blkno2/index2, so don't | 1700 | * is already stored in blkno2/index2, so don't |
1481 | * overwrite it overwise we corrupt the tree. | 1701 | * overwrite it overwise we corrupt the tree. |
1482 | */ | 1702 | */ |
1483 | blk2->index = blk1->index | 1703 | blk2->index = blk1->index - ichdr1.count; |
1484 | - be16_to_cpu(leaf1->hdr.count); | ||
1485 | args->index = blk2->index; | 1704 | args->index = blk2->index; |
1486 | args->blkno = blk2->blkno; | 1705 | args->blkno = blk2->blkno; |
1487 | if (!state->extravalid) { | 1706 | if (!state->extravalid) { |
@@ -1509,42 +1728,40 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
1509 | * GROT: Do a double-split for this case? | 1728 | * GROT: Do a double-split for this case? |
1510 | */ | 1729 | */ |
1511 | STATIC int | 1730 | STATIC int |
1512 | xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | 1731 | xfs_attr3_leaf_figure_balance( |
1513 | xfs_da_state_blk_t *blk1, | 1732 | struct xfs_da_state *state, |
1514 | xfs_da_state_blk_t *blk2, | 1733 | struct xfs_da_state_blk *blk1, |
1515 | int *countarg, int *usedbytesarg) | 1734 | struct xfs_attr3_icleaf_hdr *ichdr1, |
1735 | struct xfs_da_state_blk *blk2, | ||
1736 | struct xfs_attr3_icleaf_hdr *ichdr2, | ||
1737 | int *countarg, | ||
1738 | int *usedbytesarg) | ||
1516 | { | 1739 | { |
1517 | xfs_attr_leafblock_t *leaf1, *leaf2; | 1740 | struct xfs_attr_leafblock *leaf1 = blk1->bp->b_addr; |
1518 | xfs_attr_leaf_hdr_t *hdr1, *hdr2; | 1741 | struct xfs_attr_leafblock *leaf2 = blk2->bp->b_addr; |
1519 | xfs_attr_leaf_entry_t *entry; | 1742 | struct xfs_attr_leaf_entry *entry; |
1520 | int count, max, index, totallen, half; | 1743 | int count; |
1521 | int lastdelta, foundit, tmp; | 1744 | int max; |
1522 | 1745 | int index; | |
1523 | /* | 1746 | int totallen = 0; |
1524 | * Set up environment. | 1747 | int half; |
1525 | */ | 1748 | int lastdelta; |
1526 | leaf1 = blk1->bp->b_addr; | 1749 | int foundit = 0; |
1527 | leaf2 = blk2->bp->b_addr; | 1750 | int tmp; |
1528 | hdr1 = &leaf1->hdr; | ||
1529 | hdr2 = &leaf2->hdr; | ||
1530 | foundit = 0; | ||
1531 | totallen = 0; | ||
1532 | 1751 | ||
1533 | /* | 1752 | /* |
1534 | * Examine entries until we reduce the absolute difference in | 1753 | * Examine entries until we reduce the absolute difference in |
1535 | * byte usage between the two blocks to a minimum. | 1754 | * byte usage between the two blocks to a minimum. |
1536 | */ | 1755 | */ |
1537 | max = be16_to_cpu(hdr1->count) + be16_to_cpu(hdr2->count); | 1756 | max = ichdr1->count + ichdr2->count; |
1538 | half = (max+1) * sizeof(*entry); | 1757 | half = (max + 1) * sizeof(*entry); |
1539 | half += be16_to_cpu(hdr1->usedbytes) + | 1758 | half += ichdr1->usedbytes + ichdr2->usedbytes + |
1540 | be16_to_cpu(hdr2->usedbytes) + | 1759 | xfs_attr_leaf_newentsize(state->args->namelen, |
1541 | xfs_attr_leaf_newentsize( | 1760 | state->args->valuelen, |
1542 | state->args->namelen, | 1761 | state->blocksize, NULL); |
1543 | state->args->valuelen, | ||
1544 | state->blocksize, NULL); | ||
1545 | half /= 2; | 1762 | half /= 2; |
1546 | lastdelta = state->blocksize; | 1763 | lastdelta = state->blocksize; |
1547 | entry = &leaf1->entries[0]; | 1764 | entry = xfs_attr3_leaf_entryp(leaf1); |
1548 | for (count = index = 0; count < max; entry++, index++, count++) { | 1765 | for (count = index = 0; count < max; entry++, index++, count++) { |
1549 | 1766 | ||
1550 | #define XFS_ATTR_ABS(A) (((A) < 0) ? -(A) : (A)) | 1767 | #define XFS_ATTR_ABS(A) (((A) < 0) ? -(A) : (A)) |
@@ -1567,9 +1784,9 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | |||
1567 | /* | 1784 | /* |
1568 | * Wrap around into the second block if necessary. | 1785 | * Wrap around into the second block if necessary. |
1569 | */ | 1786 | */ |
1570 | if (count == be16_to_cpu(hdr1->count)) { | 1787 | if (count == ichdr1->count) { |
1571 | leaf1 = leaf2; | 1788 | leaf1 = leaf2; |
1572 | entry = &leaf1->entries[0]; | 1789 | entry = xfs_attr3_leaf_entryp(leaf1); |
1573 | index = 0; | 1790 | index = 0; |
1574 | } | 1791 | } |
1575 | 1792 | ||
@@ -1600,7 +1817,7 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | |||
1600 | 1817 | ||
1601 | *countarg = count; | 1818 | *countarg = count; |
1602 | *usedbytesarg = totallen; | 1819 | *usedbytesarg = totallen; |
1603 | return(foundit); | 1820 | return foundit; |
1604 | } | 1821 | } |
1605 | 1822 | ||
1606 | /*======================================================================== | 1823 | /*======================================================================== |
@@ -1619,14 +1836,20 @@ xfs_attr_leaf_figure_balance(xfs_da_state_t *state, | |||
1619 | * GROT: allow for INCOMPLETE entries in calculation. | 1836 | * GROT: allow for INCOMPLETE entries in calculation. |
1620 | */ | 1837 | */ |
1621 | int | 1838 | int |
1622 | xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) | 1839 | xfs_attr3_leaf_toosmall( |
1840 | struct xfs_da_state *state, | ||
1841 | int *action) | ||
1623 | { | 1842 | { |
1624 | xfs_attr_leafblock_t *leaf; | 1843 | struct xfs_attr_leafblock *leaf; |
1625 | xfs_da_state_blk_t *blk; | 1844 | struct xfs_da_state_blk *blk; |
1626 | xfs_da_blkinfo_t *info; | 1845 | struct xfs_attr3_icleaf_hdr ichdr; |
1627 | int count, bytes, forward, error, retval, i; | 1846 | struct xfs_buf *bp; |
1628 | xfs_dablk_t blkno; | 1847 | xfs_dablk_t blkno; |
1629 | struct xfs_buf *bp; | 1848 | int bytes; |
1849 | int forward; | ||
1850 | int error; | ||
1851 | int retval; | ||
1852 | int i; | ||
1630 | 1853 | ||
1631 | trace_xfs_attr_leaf_toosmall(state->args); | 1854 | trace_xfs_attr_leaf_toosmall(state->args); |
1632 | 1855 | ||
@@ -1636,13 +1859,11 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) | |||
1636 | * to coalesce with a sibling. | 1859 | * to coalesce with a sibling. |
1637 | */ | 1860 | */ |
1638 | blk = &state->path.blk[ state->path.active-1 ]; | 1861 | blk = &state->path.blk[ state->path.active-1 ]; |
1639 | info = blk->bp->b_addr; | 1862 | leaf = blk->bp->b_addr; |
1640 | ASSERT(info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1863 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
1641 | leaf = (xfs_attr_leafblock_t *)info; | 1864 | bytes = xfs_attr3_leaf_hdr_size(leaf) + |
1642 | count = be16_to_cpu(leaf->hdr.count); | 1865 | ichdr.count * sizeof(xfs_attr_leaf_entry_t) + |
1643 | bytes = sizeof(xfs_attr_leaf_hdr_t) + | 1866 | ichdr.usedbytes; |
1644 | count * sizeof(xfs_attr_leaf_entry_t) + | ||
1645 | be16_to_cpu(leaf->hdr.usedbytes); | ||
1646 | if (bytes > (state->blocksize >> 1)) { | 1867 | if (bytes > (state->blocksize >> 1)) { |
1647 | *action = 0; /* blk over 50%, don't try to join */ | 1868 | *action = 0; /* blk over 50%, don't try to join */ |
1648 | return(0); | 1869 | return(0); |
@@ -1654,12 +1875,12 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) | |||
1654 | * coalesce it with a sibling block. We choose (arbitrarily) | 1875 | * coalesce it with a sibling block. We choose (arbitrarily) |
1655 | * to merge with the forward block unless it is NULL. | 1876 | * to merge with the forward block unless it is NULL. |
1656 | */ | 1877 | */ |
1657 | if (count == 0) { | 1878 | if (ichdr.count == 0) { |
1658 | /* | 1879 | /* |
1659 | * Make altpath point to the block we want to keep and | 1880 | * Make altpath point to the block we want to keep and |
1660 | * path point to the block we want to drop (this one). | 1881 | * path point to the block we want to drop (this one). |
1661 | */ | 1882 | */ |
1662 | forward = (info->forw != 0); | 1883 | forward = (ichdr.forw != 0); |
1663 | memcpy(&state->altpath, &state->path, sizeof(state->path)); | 1884 | memcpy(&state->altpath, &state->path, sizeof(state->path)); |
1664 | error = xfs_da3_path_shift(state, &state->altpath, forward, | 1885 | error = xfs_da3_path_shift(state, &state->altpath, forward, |
1665 | 0, &retval); | 1886 | 0, &retval); |
@@ -1670,7 +1891,7 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) | |||
1670 | } else { | 1891 | } else { |
1671 | *action = 2; | 1892 | *action = 2; |
1672 | } | 1893 | } |
1673 | return(0); | 1894 | return 0; |
1674 | } | 1895 | } |
1675 | 1896 | ||
1676 | /* | 1897 | /* |
@@ -1681,28 +1902,28 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) | |||
1681 | * to shrink an attribute list over time. | 1902 | * to shrink an attribute list over time. |
1682 | */ | 1903 | */ |
1683 | /* start with smaller blk num */ | 1904 | /* start with smaller blk num */ |
1684 | forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); | 1905 | forward = ichdr.forw < ichdr.back; |
1685 | for (i = 0; i < 2; forward = !forward, i++) { | 1906 | for (i = 0; i < 2; forward = !forward, i++) { |
1907 | struct xfs_attr3_icleaf_hdr ichdr2; | ||
1686 | if (forward) | 1908 | if (forward) |
1687 | blkno = be32_to_cpu(info->forw); | 1909 | blkno = ichdr.forw; |
1688 | else | 1910 | else |
1689 | blkno = be32_to_cpu(info->back); | 1911 | blkno = ichdr.back; |
1690 | if (blkno == 0) | 1912 | if (blkno == 0) |
1691 | continue; | 1913 | continue; |
1692 | error = xfs_attr_leaf_read(state->args->trans, state->args->dp, | 1914 | error = xfs_attr3_leaf_read(state->args->trans, state->args->dp, |
1693 | blkno, -1, &bp); | 1915 | blkno, -1, &bp); |
1694 | if (error) | 1916 | if (error) |
1695 | return(error); | 1917 | return(error); |
1696 | 1918 | ||
1697 | leaf = (xfs_attr_leafblock_t *)info; | 1919 | xfs_attr3_leaf_hdr_from_disk(&ichdr2, bp->b_addr); |
1698 | count = be16_to_cpu(leaf->hdr.count); | 1920 | |
1699 | bytes = state->blocksize - (state->blocksize>>2); | 1921 | bytes = state->blocksize - (state->blocksize >> 2) - |
1700 | bytes -= be16_to_cpu(leaf->hdr.usedbytes); | 1922 | ichdr.usedbytes - ichdr2.usedbytes - |
1701 | leaf = bp->b_addr; | 1923 | ((ichdr.count + ichdr2.count) * |
1702 | count += be16_to_cpu(leaf->hdr.count); | 1924 | sizeof(xfs_attr_leaf_entry_t)) - |
1703 | bytes -= be16_to_cpu(leaf->hdr.usedbytes); | 1925 | xfs_attr3_leaf_hdr_size(leaf); |
1704 | bytes -= count * sizeof(xfs_attr_leaf_entry_t); | 1926 | |
1705 | bytes -= sizeof(xfs_attr_leaf_hdr_t); | ||
1706 | xfs_trans_brelse(state->args->trans, bp); | 1927 | xfs_trans_brelse(state->args->trans, bp); |
1707 | if (bytes >= 0) | 1928 | if (bytes >= 0) |
1708 | break; /* fits with at least 25% to spare */ | 1929 | break; /* fits with at least 25% to spare */ |
@@ -1741,32 +1962,35 @@ xfs_attr_leaf_toosmall(xfs_da_state_t *state, int *action) | |||
1741 | * If two leaves are 37% full, when combined they will leave 25% free. | 1962 | * If two leaves are 37% full, when combined they will leave 25% free. |
1742 | */ | 1963 | */ |
1743 | int | 1964 | int |
1744 | xfs_attr_leaf_remove( | 1965 | xfs_attr3_leaf_remove( |
1745 | struct xfs_buf *bp, | 1966 | struct xfs_buf *bp, |
1746 | xfs_da_args_t *args) | 1967 | struct xfs_da_args *args) |
1747 | { | 1968 | { |
1748 | xfs_attr_leafblock_t *leaf; | 1969 | struct xfs_attr_leafblock *leaf; |
1749 | xfs_attr_leaf_hdr_t *hdr; | 1970 | struct xfs_attr3_icleaf_hdr ichdr; |
1750 | xfs_attr_leaf_map_t *map; | 1971 | struct xfs_attr_leaf_entry *entry; |
1751 | xfs_attr_leaf_entry_t *entry; | 1972 | struct xfs_mount *mp = args->trans->t_mountp; |
1752 | int before, after, smallest, entsize; | 1973 | int before; |
1753 | int tablesize, tmp, i; | 1974 | int after; |
1754 | xfs_mount_t *mp; | 1975 | int smallest; |
1976 | int entsize; | ||
1977 | int tablesize; | ||
1978 | int tmp; | ||
1979 | int i; | ||
1755 | 1980 | ||
1756 | trace_xfs_attr_leaf_remove(args); | 1981 | trace_xfs_attr_leaf_remove(args); |
1757 | 1982 | ||
1758 | leaf = bp->b_addr; | 1983 | leaf = bp->b_addr; |
1759 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1984 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
1760 | hdr = &leaf->hdr; | 1985 | |
1761 | mp = args->trans->t_mountp; | 1986 | ASSERT(ichdr.count > 0 && ichdr.count < XFS_LBSIZE(mp) / 8); |
1762 | ASSERT((be16_to_cpu(hdr->count) > 0) | 1987 | ASSERT(args->index >= 0 && args->index < ichdr.count); |
1763 | && (be16_to_cpu(hdr->count) < (XFS_LBSIZE(mp)/8))); | 1988 | ASSERT(ichdr.firstused >= ichdr.count * sizeof(*entry) + |
1764 | ASSERT((args->index >= 0) | 1989 | xfs_attr3_leaf_hdr_size(leaf)); |
1765 | && (args->index < be16_to_cpu(hdr->count))); | 1990 | |
1766 | ASSERT(be16_to_cpu(hdr->firstused) >= | 1991 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; |
1767 | ((be16_to_cpu(hdr->count) * sizeof(*entry)) + sizeof(*hdr))); | 1992 | |
1768 | entry = &leaf->entries[args->index]; | 1993 | ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); |
1769 | ASSERT(be16_to_cpu(entry->nameidx) >= be16_to_cpu(hdr->firstused)); | ||
1770 | ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); | 1994 | ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); |
1771 | 1995 | ||
1772 | /* | 1996 | /* |
@@ -1775,30 +1999,28 @@ xfs_attr_leaf_remove( | |||
1775 | * find smallest free region in case we need to replace it, | 1999 | * find smallest free region in case we need to replace it, |
1776 | * adjust any map that borders the entry table, | 2000 | * adjust any map that borders the entry table, |
1777 | */ | 2001 | */ |
1778 | tablesize = be16_to_cpu(hdr->count) * sizeof(xfs_attr_leaf_entry_t) | 2002 | tablesize = ichdr.count * sizeof(xfs_attr_leaf_entry_t) |
1779 | + sizeof(xfs_attr_leaf_hdr_t); | 2003 | + xfs_attr3_leaf_hdr_size(leaf); |
1780 | map = &hdr->freemap[0]; | 2004 | tmp = ichdr.freemap[0].size; |
1781 | tmp = be16_to_cpu(map->size); | ||
1782 | before = after = -1; | 2005 | before = after = -1; |
1783 | smallest = XFS_ATTR_LEAF_MAPSIZE - 1; | 2006 | smallest = XFS_ATTR_LEAF_MAPSIZE - 1; |
1784 | entsize = xfs_attr_leaf_entsize(leaf, args->index); | 2007 | entsize = xfs_attr_leaf_entsize(leaf, args->index); |
1785 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; map++, i++) { | 2008 | for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { |
1786 | ASSERT(be16_to_cpu(map->base) < XFS_LBSIZE(mp)); | 2009 | ASSERT(ichdr.freemap[i].base < XFS_LBSIZE(mp)); |
1787 | ASSERT(be16_to_cpu(map->size) < XFS_LBSIZE(mp)); | 2010 | ASSERT(ichdr.freemap[i].size < XFS_LBSIZE(mp)); |
1788 | if (be16_to_cpu(map->base) == tablesize) { | 2011 | if (ichdr.freemap[i].base == tablesize) { |
1789 | be16_add_cpu(&map->base, | 2012 | ichdr.freemap[i].base -= sizeof(xfs_attr_leaf_entry_t); |
1790 | -((int)sizeof(xfs_attr_leaf_entry_t))); | 2013 | ichdr.freemap[i].size += sizeof(xfs_attr_leaf_entry_t); |
1791 | be16_add_cpu(&map->size, sizeof(xfs_attr_leaf_entry_t)); | ||
1792 | } | 2014 | } |
1793 | 2015 | ||
1794 | if ((be16_to_cpu(map->base) + be16_to_cpu(map->size)) | 2016 | if (ichdr.freemap[i].base + ichdr.freemap[i].size == |
1795 | == be16_to_cpu(entry->nameidx)) { | 2017 | be16_to_cpu(entry->nameidx)) { |
1796 | before = i; | 2018 | before = i; |
1797 | } else if (be16_to_cpu(map->base) | 2019 | } else if (ichdr.freemap[i].base == |
1798 | == (be16_to_cpu(entry->nameidx) + entsize)) { | 2020 | (be16_to_cpu(entry->nameidx) + entsize)) { |
1799 | after = i; | 2021 | after = i; |
1800 | } else if (be16_to_cpu(map->size) < tmp) { | 2022 | } else if (ichdr.freemap[i].size < tmp) { |
1801 | tmp = be16_to_cpu(map->size); | 2023 | tmp = ichdr.freemap[i].size; |
1802 | smallest = i; | 2024 | smallest = i; |
1803 | } | 2025 | } |
1804 | } | 2026 | } |
@@ -1809,36 +2031,30 @@ xfs_attr_leaf_remove( | |||
1809 | */ | 2031 | */ |
1810 | if ((before >= 0) || (after >= 0)) { | 2032 | if ((before >= 0) || (after >= 0)) { |
1811 | if ((before >= 0) && (after >= 0)) { | 2033 | if ((before >= 0) && (after >= 0)) { |
1812 | map = &hdr->freemap[before]; | 2034 | ichdr.freemap[before].size += entsize; |
1813 | be16_add_cpu(&map->size, entsize); | 2035 | ichdr.freemap[before].size += ichdr.freemap[after].size; |
1814 | be16_add_cpu(&map->size, | 2036 | ichdr.freemap[after].base = 0; |
1815 | be16_to_cpu(hdr->freemap[after].size)); | 2037 | ichdr.freemap[after].size = 0; |
1816 | hdr->freemap[after].base = 0; | ||
1817 | hdr->freemap[after].size = 0; | ||
1818 | } else if (before >= 0) { | 2038 | } else if (before >= 0) { |
1819 | map = &hdr->freemap[before]; | 2039 | ichdr.freemap[before].size += entsize; |
1820 | be16_add_cpu(&map->size, entsize); | ||
1821 | } else { | 2040 | } else { |
1822 | map = &hdr->freemap[after]; | 2041 | ichdr.freemap[after].base = be16_to_cpu(entry->nameidx); |
1823 | /* both on-disk, don't endian flip twice */ | 2042 | ichdr.freemap[after].size += entsize; |
1824 | map->base = entry->nameidx; | ||
1825 | be16_add_cpu(&map->size, entsize); | ||
1826 | } | 2043 | } |
1827 | } else { | 2044 | } else { |
1828 | /* | 2045 | /* |
1829 | * Replace smallest region (if it is smaller than free'd entry) | 2046 | * Replace smallest region (if it is smaller than free'd entry) |
1830 | */ | 2047 | */ |
1831 | map = &hdr->freemap[smallest]; | 2048 | if (ichdr.freemap[smallest].size < entsize) { |
1832 | if (be16_to_cpu(map->size) < entsize) { | 2049 | ichdr.freemap[smallest].base = be16_to_cpu(entry->nameidx); |
1833 | map->base = cpu_to_be16(be16_to_cpu(entry->nameidx)); | 2050 | ichdr.freemap[smallest].size = entsize; |
1834 | map->size = cpu_to_be16(entsize); | ||
1835 | } | 2051 | } |
1836 | } | 2052 | } |
1837 | 2053 | ||
1838 | /* | 2054 | /* |
1839 | * Did we remove the first entry? | 2055 | * Did we remove the first entry? |
1840 | */ | 2056 | */ |
1841 | if (be16_to_cpu(entry->nameidx) == be16_to_cpu(hdr->firstused)) | 2057 | if (be16_to_cpu(entry->nameidx) == ichdr.firstused) |
1842 | smallest = 1; | 2058 | smallest = 1; |
1843 | else | 2059 | else |
1844 | smallest = 0; | 2060 | smallest = 0; |
@@ -1846,20 +2062,20 @@ xfs_attr_leaf_remove( | |||
1846 | /* | 2062 | /* |
1847 | * Compress the remaining entries and zero out the removed stuff. | 2063 | * Compress the remaining entries and zero out the removed stuff. |
1848 | */ | 2064 | */ |
1849 | memset(xfs_attr_leaf_name(leaf, args->index), 0, entsize); | 2065 | memset(xfs_attr3_leaf_name(leaf, args->index), 0, entsize); |
1850 | be16_add_cpu(&hdr->usedbytes, -entsize); | 2066 | ichdr.usedbytes -= entsize; |
1851 | xfs_trans_log_buf(args->trans, bp, | 2067 | xfs_trans_log_buf(args->trans, bp, |
1852 | XFS_DA_LOGRANGE(leaf, xfs_attr_leaf_name(leaf, args->index), | 2068 | XFS_DA_LOGRANGE(leaf, xfs_attr3_leaf_name(leaf, args->index), |
1853 | entsize)); | 2069 | entsize)); |
1854 | 2070 | ||
1855 | tmp = (be16_to_cpu(hdr->count) - args->index) | 2071 | tmp = (ichdr.count - args->index) * sizeof(xfs_attr_leaf_entry_t); |
1856 | * sizeof(xfs_attr_leaf_entry_t); | 2072 | memmove(entry, entry + 1, tmp); |
1857 | memmove((char *)entry, (char *)(entry+1), tmp); | 2073 | ichdr.count--; |
1858 | be16_add_cpu(&hdr->count, -1); | ||
1859 | xfs_trans_log_buf(args->trans, bp, | 2074 | xfs_trans_log_buf(args->trans, bp, |
1860 | XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(*entry))); | 2075 | XFS_DA_LOGRANGE(leaf, entry, tmp + sizeof(xfs_attr_leaf_entry_t))); |
1861 | entry = &leaf->entries[be16_to_cpu(hdr->count)]; | 2076 | |
1862 | memset((char *)entry, 0, sizeof(xfs_attr_leaf_entry_t)); | 2077 | entry = &xfs_attr3_leaf_entryp(leaf)[ichdr.count]; |
2078 | memset(entry, 0, sizeof(xfs_attr_leaf_entry_t)); | ||
1863 | 2079 | ||
1864 | /* | 2080 | /* |
1865 | * If we removed the first entry, re-find the first used byte | 2081 | * If we removed the first entry, re-find the first used byte |
@@ -1869,130 +2085,130 @@ xfs_attr_leaf_remove( | |||
1869 | */ | 2085 | */ |
1870 | if (smallest) { | 2086 | if (smallest) { |
1871 | tmp = XFS_LBSIZE(mp); | 2087 | tmp = XFS_LBSIZE(mp); |
1872 | entry = &leaf->entries[0]; | 2088 | entry = xfs_attr3_leaf_entryp(leaf); |
1873 | for (i = be16_to_cpu(hdr->count)-1; i >= 0; entry++, i--) { | 2089 | for (i = ichdr.count - 1; i >= 0; entry++, i--) { |
1874 | ASSERT(be16_to_cpu(entry->nameidx) >= | 2090 | ASSERT(be16_to_cpu(entry->nameidx) >= ichdr.firstused); |
1875 | be16_to_cpu(hdr->firstused)); | ||
1876 | ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); | 2091 | ASSERT(be16_to_cpu(entry->nameidx) < XFS_LBSIZE(mp)); |
1877 | 2092 | ||
1878 | if (be16_to_cpu(entry->nameidx) < tmp) | 2093 | if (be16_to_cpu(entry->nameidx) < tmp) |
1879 | tmp = be16_to_cpu(entry->nameidx); | 2094 | tmp = be16_to_cpu(entry->nameidx); |
1880 | } | 2095 | } |
1881 | hdr->firstused = cpu_to_be16(tmp); | 2096 | ichdr.firstused = tmp; |
1882 | if (!hdr->firstused) { | 2097 | if (!ichdr.firstused) |
1883 | hdr->firstused = cpu_to_be16( | 2098 | ichdr.firstused = tmp - XFS_ATTR_LEAF_NAME_ALIGN; |
1884 | tmp - XFS_ATTR_LEAF_NAME_ALIGN); | ||
1885 | } | ||
1886 | } else { | 2099 | } else { |
1887 | hdr->holes = 1; /* mark as needing compaction */ | 2100 | ichdr.holes = 1; /* mark as needing compaction */ |
1888 | } | 2101 | } |
2102 | xfs_attr3_leaf_hdr_to_disk(leaf, &ichdr); | ||
1889 | xfs_trans_log_buf(args->trans, bp, | 2103 | xfs_trans_log_buf(args->trans, bp, |
1890 | XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); | 2104 | XFS_DA_LOGRANGE(leaf, &leaf->hdr, |
2105 | xfs_attr3_leaf_hdr_size(leaf))); | ||
1891 | 2106 | ||
1892 | /* | 2107 | /* |
1893 | * Check if leaf is less than 50% full, caller may want to | 2108 | * Check if leaf is less than 50% full, caller may want to |
1894 | * "join" the leaf with a sibling if so. | 2109 | * "join" the leaf with a sibling if so. |
1895 | */ | 2110 | */ |
1896 | tmp = sizeof(xfs_attr_leaf_hdr_t); | 2111 | tmp = ichdr.usedbytes + xfs_attr3_leaf_hdr_size(leaf) + |
1897 | tmp += be16_to_cpu(leaf->hdr.count) * sizeof(xfs_attr_leaf_entry_t); | 2112 | ichdr.count * sizeof(xfs_attr_leaf_entry_t); |
1898 | tmp += be16_to_cpu(leaf->hdr.usedbytes); | 2113 | |
1899 | return(tmp < mp->m_attr_magicpct); /* leaf is < 37% full */ | 2114 | return tmp < mp->m_attr_magicpct; /* leaf is < 37% full */ |
1900 | } | 2115 | } |
1901 | 2116 | ||
1902 | /* | 2117 | /* |
1903 | * Move all the attribute list entries from drop_leaf into save_leaf. | 2118 | * Move all the attribute list entries from drop_leaf into save_leaf. |
1904 | */ | 2119 | */ |
1905 | void | 2120 | void |
1906 | xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, | 2121 | xfs_attr3_leaf_unbalance( |
1907 | xfs_da_state_blk_t *save_blk) | 2122 | struct xfs_da_state *state, |
2123 | struct xfs_da_state_blk *drop_blk, | ||
2124 | struct xfs_da_state_blk *save_blk) | ||
1908 | { | 2125 | { |
1909 | xfs_attr_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf; | 2126 | struct xfs_attr_leafblock *drop_leaf = drop_blk->bp->b_addr; |
1910 | xfs_attr_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr; | 2127 | struct xfs_attr_leafblock *save_leaf = save_blk->bp->b_addr; |
1911 | xfs_mount_t *mp; | 2128 | struct xfs_attr3_icleaf_hdr drophdr; |
1912 | char *tmpbuffer; | 2129 | struct xfs_attr3_icleaf_hdr savehdr; |
2130 | struct xfs_attr_leaf_entry *entry; | ||
2131 | struct xfs_mount *mp = state->mp; | ||
1913 | 2132 | ||
1914 | trace_xfs_attr_leaf_unbalance(state->args); | 2133 | trace_xfs_attr_leaf_unbalance(state->args); |
1915 | 2134 | ||
1916 | /* | ||
1917 | * Set up environment. | ||
1918 | */ | ||
1919 | mp = state->mp; | ||
1920 | ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC); | ||
1921 | ASSERT(save_blk->magic == XFS_ATTR_LEAF_MAGIC); | ||
1922 | drop_leaf = drop_blk->bp->b_addr; | 2135 | drop_leaf = drop_blk->bp->b_addr; |
1923 | save_leaf = save_blk->bp->b_addr; | 2136 | save_leaf = save_blk->bp->b_addr; |
1924 | ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2137 | xfs_attr3_leaf_hdr_from_disk(&drophdr, drop_leaf); |
1925 | ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2138 | xfs_attr3_leaf_hdr_from_disk(&savehdr, save_leaf); |
1926 | drop_hdr = &drop_leaf->hdr; | 2139 | entry = xfs_attr3_leaf_entryp(drop_leaf); |
1927 | save_hdr = &save_leaf->hdr; | ||
1928 | 2140 | ||
1929 | /* | 2141 | /* |
1930 | * Save last hashval from dying block for later Btree fixup. | 2142 | * Save last hashval from dying block for later Btree fixup. |
1931 | */ | 2143 | */ |
1932 | drop_blk->hashval = be32_to_cpu( | 2144 | drop_blk->hashval = be32_to_cpu(entry[drophdr.count - 1].hashval); |
1933 | drop_leaf->entries[be16_to_cpu(drop_leaf->hdr.count)-1].hashval); | ||
1934 | 2145 | ||
1935 | /* | 2146 | /* |
1936 | * Check if we need a temp buffer, or can we do it in place. | 2147 | * Check if we need a temp buffer, or can we do it in place. |
1937 | * Note that we don't check "leaf" for holes because we will | 2148 | * Note that we don't check "leaf" for holes because we will |
1938 | * always be dropping it, toosmall() decided that for us already. | 2149 | * always be dropping it, toosmall() decided that for us already. |
1939 | */ | 2150 | */ |
1940 | if (save_hdr->holes == 0) { | 2151 | if (savehdr.holes == 0) { |
1941 | /* | 2152 | /* |
1942 | * dest leaf has no holes, so we add there. May need | 2153 | * dest leaf has no holes, so we add there. May need |
1943 | * to make some room in the entry array. | 2154 | * to make some room in the entry array. |
1944 | */ | 2155 | */ |
1945 | if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) { | 2156 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, |
1946 | xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, 0, | 2157 | drop_blk->bp, &drophdr)) { |
1947 | be16_to_cpu(drop_hdr->count), mp); | 2158 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, |
2159 | save_leaf, &savehdr, 0, | ||
2160 | drophdr.count, mp); | ||
1948 | } else { | 2161 | } else { |
1949 | xfs_attr_leaf_moveents(drop_leaf, 0, save_leaf, | 2162 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, |
1950 | be16_to_cpu(save_hdr->count), | 2163 | save_leaf, &savehdr, |
1951 | be16_to_cpu(drop_hdr->count), mp); | 2164 | savehdr.count, drophdr.count, mp); |
1952 | } | 2165 | } |
1953 | } else { | 2166 | } else { |
1954 | /* | 2167 | /* |
1955 | * Destination has holes, so we make a temporary copy | 2168 | * Destination has holes, so we make a temporary copy |
1956 | * of the leaf and add them both to that. | 2169 | * of the leaf and add them both to that. |
1957 | */ | 2170 | */ |
1958 | tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP); | 2171 | struct xfs_attr_leafblock *tmp_leaf; |
1959 | ASSERT(tmpbuffer != NULL); | 2172 | struct xfs_attr3_icleaf_hdr tmphdr; |
1960 | memset(tmpbuffer, 0, state->blocksize); | 2173 | |
1961 | tmp_leaf = (xfs_attr_leafblock_t *)tmpbuffer; | 2174 | tmp_leaf = kmem_alloc(state->blocksize, KM_SLEEP); |
1962 | tmp_hdr = &tmp_leaf->hdr; | 2175 | memset(tmp_leaf, 0, state->blocksize); |
1963 | tmp_hdr->info = save_hdr->info; /* struct copy */ | 2176 | memset(&tmphdr, 0, sizeof(tmphdr)); |
1964 | tmp_hdr->count = 0; | 2177 | |
1965 | tmp_hdr->firstused = cpu_to_be16(state->blocksize); | 2178 | tmphdr.magic = savehdr.magic; |
1966 | if (!tmp_hdr->firstused) { | 2179 | tmphdr.forw = savehdr.forw; |
1967 | tmp_hdr->firstused = cpu_to_be16( | 2180 | tmphdr.back = savehdr.back; |
1968 | state->blocksize - XFS_ATTR_LEAF_NAME_ALIGN); | 2181 | tmphdr.firstused = state->blocksize; |
1969 | } | 2182 | if (xfs_attr3_leaf_order(save_blk->bp, &savehdr, |
1970 | tmp_hdr->usedbytes = 0; | 2183 | drop_blk->bp, &drophdr)) { |
1971 | if (xfs_attr_leaf_order(save_blk->bp, drop_blk->bp)) { | 2184 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, |
1972 | xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, 0, | 2185 | tmp_leaf, &tmphdr, 0, |
1973 | be16_to_cpu(drop_hdr->count), mp); | 2186 | drophdr.count, mp); |
1974 | xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, | 2187 | xfs_attr3_leaf_moveents(save_leaf, &savehdr, 0, |
1975 | be16_to_cpu(tmp_leaf->hdr.count), | 2188 | tmp_leaf, &tmphdr, tmphdr.count, |
1976 | be16_to_cpu(save_hdr->count), mp); | 2189 | savehdr.count, mp); |
1977 | } else { | 2190 | } else { |
1978 | xfs_attr_leaf_moveents(save_leaf, 0, tmp_leaf, 0, | 2191 | xfs_attr3_leaf_moveents(save_leaf, &savehdr, 0, |
1979 | be16_to_cpu(save_hdr->count), mp); | 2192 | tmp_leaf, &tmphdr, 0, |
1980 | xfs_attr_leaf_moveents(drop_leaf, 0, tmp_leaf, | 2193 | savehdr.count, mp); |
1981 | be16_to_cpu(tmp_leaf->hdr.count), | 2194 | xfs_attr3_leaf_moveents(drop_leaf, &drophdr, 0, |
1982 | be16_to_cpu(drop_hdr->count), mp); | 2195 | tmp_leaf, &tmphdr, tmphdr.count, |
2196 | drophdr.count, mp); | ||
1983 | } | 2197 | } |
1984 | memcpy((char *)save_leaf, (char *)tmp_leaf, state->blocksize); | 2198 | memcpy(save_leaf, tmp_leaf, state->blocksize); |
1985 | kmem_free(tmpbuffer); | 2199 | savehdr = tmphdr; /* struct copy */ |
2200 | kmem_free(tmp_leaf); | ||
1986 | } | 2201 | } |
1987 | 2202 | ||
2203 | xfs_attr3_leaf_hdr_to_disk(save_leaf, &savehdr); | ||
1988 | xfs_trans_log_buf(state->args->trans, save_blk->bp, 0, | 2204 | xfs_trans_log_buf(state->args->trans, save_blk->bp, 0, |
1989 | state->blocksize - 1); | 2205 | state->blocksize - 1); |
1990 | 2206 | ||
1991 | /* | 2207 | /* |
1992 | * Copy out last hashval in each block for B-tree code. | 2208 | * Copy out last hashval in each block for B-tree code. |
1993 | */ | 2209 | */ |
1994 | save_blk->hashval = be32_to_cpu( | 2210 | entry = xfs_attr3_leaf_entryp(save_leaf); |
1995 | save_leaf->entries[be16_to_cpu(save_leaf->hdr.count)-1].hashval); | 2211 | save_blk->hashval = be32_to_cpu(entry[savehdr.count - 1].hashval); |
1996 | } | 2212 | } |
1997 | 2213 | ||
1998 | /*======================================================================== | 2214 | /*======================================================================== |
@@ -2013,31 +2229,33 @@ xfs_attr_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, | |||
2013 | * Don't change the args->value unless we find the attribute. | 2229 | * Don't change the args->value unless we find the attribute. |
2014 | */ | 2230 | */ |
2015 | int | 2231 | int |
2016 | xfs_attr_leaf_lookup_int( | 2232 | xfs_attr3_leaf_lookup_int( |
2017 | struct xfs_buf *bp, | 2233 | struct xfs_buf *bp, |
2018 | xfs_da_args_t *args) | 2234 | struct xfs_da_args *args) |
2019 | { | 2235 | { |
2020 | xfs_attr_leafblock_t *leaf; | 2236 | struct xfs_attr_leafblock *leaf; |
2021 | xfs_attr_leaf_entry_t *entry; | 2237 | struct xfs_attr3_icleaf_hdr ichdr; |
2022 | xfs_attr_leaf_name_local_t *name_loc; | 2238 | struct xfs_attr_leaf_entry *entry; |
2023 | xfs_attr_leaf_name_remote_t *name_rmt; | 2239 | struct xfs_attr_leaf_entry *entries; |
2024 | int probe, span; | 2240 | struct xfs_attr_leaf_name_local *name_loc; |
2025 | xfs_dahash_t hashval; | 2241 | struct xfs_attr_leaf_name_remote *name_rmt; |
2242 | xfs_dahash_t hashval; | ||
2243 | int probe; | ||
2244 | int span; | ||
2026 | 2245 | ||
2027 | trace_xfs_attr_leaf_lookup(args); | 2246 | trace_xfs_attr_leaf_lookup(args); |
2028 | 2247 | ||
2029 | leaf = bp->b_addr; | 2248 | leaf = bp->b_addr; |
2030 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2249 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
2031 | ASSERT(be16_to_cpu(leaf->hdr.count) | 2250 | entries = xfs_attr3_leaf_entryp(leaf); |
2032 | < (XFS_LBSIZE(args->dp->i_mount)/8)); | 2251 | ASSERT(ichdr.count < XFS_LBSIZE(args->dp->i_mount) / 8); |
2033 | 2252 | ||
2034 | /* | 2253 | /* |
2035 | * Binary search. (note: small blocks will skip this loop) | 2254 | * Binary search. (note: small blocks will skip this loop) |
2036 | */ | 2255 | */ |
2037 | hashval = args->hashval; | 2256 | hashval = args->hashval; |
2038 | probe = span = be16_to_cpu(leaf->hdr.count) / 2; | 2257 | probe = span = ichdr.count / 2; |
2039 | for (entry = &leaf->entries[probe]; span > 4; | 2258 | for (entry = &entries[probe]; span > 4; entry = &entries[probe]) { |
2040 | entry = &leaf->entries[probe]) { | ||
2041 | span /= 2; | 2259 | span /= 2; |
2042 | if (be32_to_cpu(entry->hashval) < hashval) | 2260 | if (be32_to_cpu(entry->hashval) < hashval) |
2043 | probe += span; | 2261 | probe += span; |
@@ -2046,35 +2264,31 @@ xfs_attr_leaf_lookup_int( | |||
2046 | else | 2264 | else |
2047 | break; | 2265 | break; |
2048 | } | 2266 | } |
2049 | ASSERT((probe >= 0) && | 2267 | ASSERT(probe >= 0 && (!ichdr.count || probe < ichdr.count)); |
2050 | (!leaf->hdr.count | 2268 | ASSERT(span <= 4 || be32_to_cpu(entry->hashval) == hashval); |
2051 | || (probe < be16_to_cpu(leaf->hdr.count)))); | ||
2052 | ASSERT((span <= 4) || (be32_to_cpu(entry->hashval) == hashval)); | ||
2053 | 2269 | ||
2054 | /* | 2270 | /* |
2055 | * Since we may have duplicate hashval's, find the first matching | 2271 | * Since we may have duplicate hashval's, find the first matching |
2056 | * hashval in the leaf. | 2272 | * hashval in the leaf. |
2057 | */ | 2273 | */ |
2058 | while ((probe > 0) && (be32_to_cpu(entry->hashval) >= hashval)) { | 2274 | while (probe > 0 && be32_to_cpu(entry->hashval) >= hashval) { |
2059 | entry--; | 2275 | entry--; |
2060 | probe--; | 2276 | probe--; |
2061 | } | 2277 | } |
2062 | while ((probe < be16_to_cpu(leaf->hdr.count)) && | 2278 | while (probe < ichdr.count && |
2063 | (be32_to_cpu(entry->hashval) < hashval)) { | 2279 | be32_to_cpu(entry->hashval) < hashval) { |
2064 | entry++; | 2280 | entry++; |
2065 | probe++; | 2281 | probe++; |
2066 | } | 2282 | } |
2067 | if ((probe == be16_to_cpu(leaf->hdr.count)) || | 2283 | if (probe == ichdr.count || be32_to_cpu(entry->hashval) != hashval) { |
2068 | (be32_to_cpu(entry->hashval) != hashval)) { | ||
2069 | args->index = probe; | 2284 | args->index = probe; |
2070 | return(XFS_ERROR(ENOATTR)); | 2285 | return XFS_ERROR(ENOATTR); |
2071 | } | 2286 | } |
2072 | 2287 | ||
2073 | /* | 2288 | /* |
2074 | * Duplicate keys may be present, so search all of them for a match. | 2289 | * Duplicate keys may be present, so search all of them for a match. |
2075 | */ | 2290 | */ |
2076 | for ( ; (probe < be16_to_cpu(leaf->hdr.count)) && | 2291 | for (; probe < ichdr.count && (be32_to_cpu(entry->hashval) == hashval); |
2077 | (be32_to_cpu(entry->hashval) == hashval); | ||
2078 | entry++, probe++) { | 2292 | entry++, probe++) { |
2079 | /* | 2293 | /* |
2080 | * GROT: Add code to remove incomplete entries. | 2294 | * GROT: Add code to remove incomplete entries. |
@@ -2088,21 +2302,22 @@ xfs_attr_leaf_lookup_int( | |||
2088 | continue; | 2302 | continue; |
2089 | } | 2303 | } |
2090 | if (entry->flags & XFS_ATTR_LOCAL) { | 2304 | if (entry->flags & XFS_ATTR_LOCAL) { |
2091 | name_loc = xfs_attr_leaf_name_local(leaf, probe); | 2305 | name_loc = xfs_attr3_leaf_name_local(leaf, probe); |
2092 | if (name_loc->namelen != args->namelen) | 2306 | if (name_loc->namelen != args->namelen) |
2093 | continue; | 2307 | continue; |
2094 | if (memcmp(args->name, (char *)name_loc->nameval, args->namelen) != 0) | 2308 | if (memcmp(args->name, name_loc->nameval, |
2309 | args->namelen) != 0) | ||
2095 | continue; | 2310 | continue; |
2096 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) | 2311 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) |
2097 | continue; | 2312 | continue; |
2098 | args->index = probe; | 2313 | args->index = probe; |
2099 | return(XFS_ERROR(EEXIST)); | 2314 | return XFS_ERROR(EEXIST); |
2100 | } else { | 2315 | } else { |
2101 | name_rmt = xfs_attr_leaf_name_remote(leaf, probe); | 2316 | name_rmt = xfs_attr3_leaf_name_remote(leaf, probe); |
2102 | if (name_rmt->namelen != args->namelen) | 2317 | if (name_rmt->namelen != args->namelen) |
2103 | continue; | 2318 | continue; |
2104 | if (memcmp(args->name, (char *)name_rmt->name, | 2319 | if (memcmp(args->name, name_rmt->name, |
2105 | args->namelen) != 0) | 2320 | args->namelen) != 0) |
2106 | continue; | 2321 | continue; |
2107 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) | 2322 | if (!xfs_attr_namesp_match(args->flags, entry->flags)) |
2108 | continue; | 2323 | continue; |
@@ -2110,11 +2325,11 @@ xfs_attr_leaf_lookup_int( | |||
2110 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); | 2325 | args->rmtblkno = be32_to_cpu(name_rmt->valueblk); |
2111 | args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, | 2326 | args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, |
2112 | be32_to_cpu(name_rmt->valuelen)); | 2327 | be32_to_cpu(name_rmt->valuelen)); |
2113 | return(XFS_ERROR(EEXIST)); | 2328 | return XFS_ERROR(EEXIST); |
2114 | } | 2329 | } |
2115 | } | 2330 | } |
2116 | args->index = probe; | 2331 | args->index = probe; |
2117 | return(XFS_ERROR(ENOATTR)); | 2332 | return XFS_ERROR(ENOATTR); |
2118 | } | 2333 | } |
2119 | 2334 | ||
2120 | /* | 2335 | /* |
@@ -2122,40 +2337,40 @@ xfs_attr_leaf_lookup_int( | |||
2122 | * list structure. | 2337 | * list structure. |
2123 | */ | 2338 | */ |
2124 | int | 2339 | int |
2125 | xfs_attr_leaf_getvalue( | 2340 | xfs_attr3_leaf_getvalue( |
2126 | struct xfs_buf *bp, | 2341 | struct xfs_buf *bp, |
2127 | xfs_da_args_t *args) | 2342 | struct xfs_da_args *args) |
2128 | { | 2343 | { |
2129 | int valuelen; | 2344 | struct xfs_attr_leafblock *leaf; |
2130 | xfs_attr_leafblock_t *leaf; | 2345 | struct xfs_attr3_icleaf_hdr ichdr; |
2131 | xfs_attr_leaf_entry_t *entry; | 2346 | struct xfs_attr_leaf_entry *entry; |
2132 | xfs_attr_leaf_name_local_t *name_loc; | 2347 | struct xfs_attr_leaf_name_local *name_loc; |
2133 | xfs_attr_leaf_name_remote_t *name_rmt; | 2348 | struct xfs_attr_leaf_name_remote *name_rmt; |
2349 | int valuelen; | ||
2134 | 2350 | ||
2135 | leaf = bp->b_addr; | 2351 | leaf = bp->b_addr; |
2136 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2352 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
2137 | ASSERT(be16_to_cpu(leaf->hdr.count) | 2353 | ASSERT(ichdr.count < XFS_LBSIZE(args->dp->i_mount) / 8); |
2138 | < (XFS_LBSIZE(args->dp->i_mount)/8)); | 2354 | ASSERT(args->index < ichdr.count); |
2139 | ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); | ||
2140 | 2355 | ||
2141 | entry = &leaf->entries[args->index]; | 2356 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; |
2142 | if (entry->flags & XFS_ATTR_LOCAL) { | 2357 | if (entry->flags & XFS_ATTR_LOCAL) { |
2143 | name_loc = xfs_attr_leaf_name_local(leaf, args->index); | 2358 | name_loc = xfs_attr3_leaf_name_local(leaf, args->index); |
2144 | ASSERT(name_loc->namelen == args->namelen); | 2359 | ASSERT(name_loc->namelen == args->namelen); |
2145 | ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0); | 2360 | ASSERT(memcmp(args->name, name_loc->nameval, args->namelen) == 0); |
2146 | valuelen = be16_to_cpu(name_loc->valuelen); | 2361 | valuelen = be16_to_cpu(name_loc->valuelen); |
2147 | if (args->flags & ATTR_KERNOVAL) { | 2362 | if (args->flags & ATTR_KERNOVAL) { |
2148 | args->valuelen = valuelen; | 2363 | args->valuelen = valuelen; |
2149 | return(0); | 2364 | return 0; |
2150 | } | 2365 | } |
2151 | if (args->valuelen < valuelen) { | 2366 | if (args->valuelen < valuelen) { |
2152 | args->valuelen = valuelen; | 2367 | args->valuelen = valuelen; |
2153 | return(XFS_ERROR(ERANGE)); | 2368 | return XFS_ERROR(ERANGE); |
2154 | } | 2369 | } |
2155 | args->valuelen = valuelen; | 2370 | args->valuelen = valuelen; |
2156 | memcpy(args->value, &name_loc->nameval[args->namelen], valuelen); | 2371 | memcpy(args->value, &name_loc->nameval[args->namelen], valuelen); |
2157 | } else { | 2372 | } else { |
2158 | name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); | 2373 | name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); |
2159 | ASSERT(name_rmt->namelen == args->namelen); | 2374 | ASSERT(name_rmt->namelen == args->namelen); |
2160 | ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); | 2375 | ASSERT(memcmp(args->name, name_rmt->name, args->namelen) == 0); |
2161 | valuelen = be32_to_cpu(name_rmt->valuelen); | 2376 | valuelen = be32_to_cpu(name_rmt->valuelen); |
@@ -2163,15 +2378,15 @@ xfs_attr_leaf_getvalue( | |||
2163 | args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen); | 2378 | args->rmtblkcnt = XFS_B_TO_FSB(args->dp->i_mount, valuelen); |
2164 | if (args->flags & ATTR_KERNOVAL) { | 2379 | if (args->flags & ATTR_KERNOVAL) { |
2165 | args->valuelen = valuelen; | 2380 | args->valuelen = valuelen; |
2166 | return(0); | 2381 | return 0; |
2167 | } | 2382 | } |
2168 | if (args->valuelen < valuelen) { | 2383 | if (args->valuelen < valuelen) { |
2169 | args->valuelen = valuelen; | 2384 | args->valuelen = valuelen; |
2170 | return(XFS_ERROR(ERANGE)); | 2385 | return XFS_ERROR(ERANGE); |
2171 | } | 2386 | } |
2172 | args->valuelen = valuelen; | 2387 | args->valuelen = valuelen; |
2173 | } | 2388 | } |
2174 | return(0); | 2389 | return 0; |
2175 | } | 2390 | } |
2176 | 2391 | ||
2177 | /*======================================================================== | 2392 | /*======================================================================== |
@@ -2184,13 +2399,21 @@ xfs_attr_leaf_getvalue( | |||
2184 | */ | 2399 | */ |
2185 | /*ARGSUSED*/ | 2400 | /*ARGSUSED*/ |
2186 | STATIC void | 2401 | STATIC void |
2187 | xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, | 2402 | xfs_attr3_leaf_moveents( |
2188 | xfs_attr_leafblock_t *leaf_d, int start_d, | 2403 | struct xfs_attr_leafblock *leaf_s, |
2189 | int count, xfs_mount_t *mp) | 2404 | struct xfs_attr3_icleaf_hdr *ichdr_s, |
2405 | int start_s, | ||
2406 | struct xfs_attr_leafblock *leaf_d, | ||
2407 | struct xfs_attr3_icleaf_hdr *ichdr_d, | ||
2408 | int start_d, | ||
2409 | int count, | ||
2410 | struct xfs_mount *mp) | ||
2190 | { | 2411 | { |
2191 | xfs_attr_leaf_hdr_t *hdr_s, *hdr_d; | 2412 | struct xfs_attr_leaf_entry *entry_s; |
2192 | xfs_attr_leaf_entry_t *entry_s, *entry_d; | 2413 | struct xfs_attr_leaf_entry *entry_d; |
2193 | int desti, tmp, i; | 2414 | int desti; |
2415 | int tmp; | ||
2416 | int i; | ||
2194 | 2417 | ||
2195 | /* | 2418 | /* |
2196 | * Check for nothing to do. | 2419 | * Check for nothing to do. |
@@ -2201,45 +2424,41 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, | |||
2201 | /* | 2424 | /* |
2202 | * Set up environment. | 2425 | * Set up environment. |
2203 | */ | 2426 | */ |
2204 | ASSERT(leaf_s->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2427 | ASSERT(ichdr_s->magic == XFS_ATTR_LEAF_MAGIC || |
2205 | ASSERT(leaf_d->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2428 | ichdr_s->magic == XFS_ATTR3_LEAF_MAGIC); |
2206 | hdr_s = &leaf_s->hdr; | 2429 | ASSERT(ichdr_s->magic == ichdr_d->magic); |
2207 | hdr_d = &leaf_d->hdr; | 2430 | ASSERT(ichdr_s->count > 0 && ichdr_s->count < XFS_LBSIZE(mp) / 8); |
2208 | ASSERT((be16_to_cpu(hdr_s->count) > 0) && | 2431 | ASSERT(ichdr_s->firstused >= (ichdr_s->count * sizeof(*entry_s)) |
2209 | (be16_to_cpu(hdr_s->count) < (XFS_LBSIZE(mp)/8))); | 2432 | + xfs_attr3_leaf_hdr_size(leaf_s)); |
2210 | ASSERT(be16_to_cpu(hdr_s->firstused) >= | 2433 | ASSERT(ichdr_d->count < XFS_LBSIZE(mp) / 8); |
2211 | ((be16_to_cpu(hdr_s->count) | 2434 | ASSERT(ichdr_d->firstused >= (ichdr_d->count * sizeof(*entry_d)) |
2212 | * sizeof(*entry_s))+sizeof(*hdr_s))); | 2435 | + xfs_attr3_leaf_hdr_size(leaf_d)); |
2213 | ASSERT(be16_to_cpu(hdr_d->count) < (XFS_LBSIZE(mp)/8)); | 2436 | |
2214 | ASSERT(be16_to_cpu(hdr_d->firstused) >= | 2437 | ASSERT(start_s < ichdr_s->count); |
2215 | ((be16_to_cpu(hdr_d->count) | 2438 | ASSERT(start_d <= ichdr_d->count); |
2216 | * sizeof(*entry_d))+sizeof(*hdr_d))); | 2439 | ASSERT(count <= ichdr_s->count); |
2217 | 2440 | ||
2218 | ASSERT(start_s < be16_to_cpu(hdr_s->count)); | ||
2219 | ASSERT(start_d <= be16_to_cpu(hdr_d->count)); | ||
2220 | ASSERT(count <= be16_to_cpu(hdr_s->count)); | ||
2221 | 2441 | ||
2222 | /* | 2442 | /* |
2223 | * Move the entries in the destination leaf up to make a hole? | 2443 | * Move the entries in the destination leaf up to make a hole? |
2224 | */ | 2444 | */ |
2225 | if (start_d < be16_to_cpu(hdr_d->count)) { | 2445 | if (start_d < ichdr_d->count) { |
2226 | tmp = be16_to_cpu(hdr_d->count) - start_d; | 2446 | tmp = ichdr_d->count - start_d; |
2227 | tmp *= sizeof(xfs_attr_leaf_entry_t); | 2447 | tmp *= sizeof(xfs_attr_leaf_entry_t); |
2228 | entry_s = &leaf_d->entries[start_d]; | 2448 | entry_s = &xfs_attr3_leaf_entryp(leaf_d)[start_d]; |
2229 | entry_d = &leaf_d->entries[start_d + count]; | 2449 | entry_d = &xfs_attr3_leaf_entryp(leaf_d)[start_d + count]; |
2230 | memmove((char *)entry_d, (char *)entry_s, tmp); | 2450 | memmove(entry_d, entry_s, tmp); |
2231 | } | 2451 | } |
2232 | 2452 | ||
2233 | /* | 2453 | /* |
2234 | * Copy all entry's in the same (sorted) order, | 2454 | * Copy all entry's in the same (sorted) order, |
2235 | * but allocate attribute info packed and in sequence. | 2455 | * but allocate attribute info packed and in sequence. |
2236 | */ | 2456 | */ |
2237 | entry_s = &leaf_s->entries[start_s]; | 2457 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; |
2238 | entry_d = &leaf_d->entries[start_d]; | 2458 | entry_d = &xfs_attr3_leaf_entryp(leaf_d)[start_d]; |
2239 | desti = start_d; | 2459 | desti = start_d; |
2240 | for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) { | 2460 | for (i = 0; i < count; entry_s++, entry_d++, desti++, i++) { |
2241 | ASSERT(be16_to_cpu(entry_s->nameidx) | 2461 | ASSERT(be16_to_cpu(entry_s->nameidx) >= ichdr_s->firstused); |
2242 | >= be16_to_cpu(hdr_s->firstused)); | ||
2243 | tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i); | 2462 | tmp = xfs_attr_leaf_entsize(leaf_s, start_s + i); |
2244 | #ifdef GROT | 2463 | #ifdef GROT |
2245 | /* | 2464 | /* |
@@ -2248,36 +2467,34 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, | |||
2248 | * off for 6.2, should be revisited later. | 2467 | * off for 6.2, should be revisited later. |
2249 | */ | 2468 | */ |
2250 | if (entry_s->flags & XFS_ATTR_INCOMPLETE) { /* skip partials? */ | 2469 | if (entry_s->flags & XFS_ATTR_INCOMPLETE) { /* skip partials? */ |
2251 | memset(xfs_attr_leaf_name(leaf_s, start_s + i), 0, tmp); | 2470 | memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp); |
2252 | be16_add_cpu(&hdr_s->usedbytes, -tmp); | 2471 | ichdr_s->usedbytes -= tmp; |
2253 | be16_add_cpu(&hdr_s->count, -1); | 2472 | ichdr_s->count -= 1; |
2254 | entry_d--; /* to compensate for ++ in loop hdr */ | 2473 | entry_d--; /* to compensate for ++ in loop hdr */ |
2255 | desti--; | 2474 | desti--; |
2256 | if ((start_s + i) < offset) | 2475 | if ((start_s + i) < offset) |
2257 | result++; /* insertion index adjustment */ | 2476 | result++; /* insertion index adjustment */ |
2258 | } else { | 2477 | } else { |
2259 | #endif /* GROT */ | 2478 | #endif /* GROT */ |
2260 | be16_add_cpu(&hdr_d->firstused, -tmp); | 2479 | ichdr_d->firstused -= tmp; |
2261 | /* both on-disk, don't endian flip twice */ | 2480 | /* both on-disk, don't endian flip twice */ |
2262 | entry_d->hashval = entry_s->hashval; | 2481 | entry_d->hashval = entry_s->hashval; |
2263 | /* both on-disk, don't endian flip twice */ | 2482 | entry_d->nameidx = cpu_to_be16(ichdr_d->firstused); |
2264 | entry_d->nameidx = hdr_d->firstused; | ||
2265 | entry_d->flags = entry_s->flags; | 2483 | entry_d->flags = entry_s->flags; |
2266 | ASSERT(be16_to_cpu(entry_d->nameidx) + tmp | 2484 | ASSERT(be16_to_cpu(entry_d->nameidx) + tmp |
2267 | <= XFS_LBSIZE(mp)); | 2485 | <= XFS_LBSIZE(mp)); |
2268 | memmove(xfs_attr_leaf_name(leaf_d, desti), | 2486 | memmove(xfs_attr3_leaf_name(leaf_d, desti), |
2269 | xfs_attr_leaf_name(leaf_s, start_s + i), tmp); | 2487 | xfs_attr3_leaf_name(leaf_s, start_s + i), tmp); |
2270 | ASSERT(be16_to_cpu(entry_s->nameidx) + tmp | 2488 | ASSERT(be16_to_cpu(entry_s->nameidx) + tmp |
2271 | <= XFS_LBSIZE(mp)); | 2489 | <= XFS_LBSIZE(mp)); |
2272 | memset(xfs_attr_leaf_name(leaf_s, start_s + i), 0, tmp); | 2490 | memset(xfs_attr3_leaf_name(leaf_s, start_s + i), 0, tmp); |
2273 | be16_add_cpu(&hdr_s->usedbytes, -tmp); | 2491 | ichdr_s->usedbytes -= tmp; |
2274 | be16_add_cpu(&hdr_d->usedbytes, tmp); | 2492 | ichdr_d->usedbytes += tmp; |
2275 | be16_add_cpu(&hdr_s->count, -1); | 2493 | ichdr_s->count -= 1; |
2276 | be16_add_cpu(&hdr_d->count, 1); | 2494 | ichdr_d->count += 1; |
2277 | tmp = be16_to_cpu(hdr_d->count) | 2495 | tmp = ichdr_d->count * sizeof(xfs_attr_leaf_entry_t) |
2278 | * sizeof(xfs_attr_leaf_entry_t) | 2496 | + xfs_attr3_leaf_hdr_size(leaf_d); |
2279 | + sizeof(xfs_attr_leaf_hdr_t); | 2497 | ASSERT(ichdr_d->firstused >= tmp); |
2280 | ASSERT(be16_to_cpu(hdr_d->firstused) >= tmp); | ||
2281 | #ifdef GROT | 2498 | #ifdef GROT |
2282 | } | 2499 | } |
2283 | #endif /* GROT */ | 2500 | #endif /* GROT */ |
@@ -2286,71 +2503,40 @@ xfs_attr_leaf_moveents(xfs_attr_leafblock_t *leaf_s, int start_s, | |||
2286 | /* | 2503 | /* |
2287 | * Zero out the entries we just copied. | 2504 | * Zero out the entries we just copied. |
2288 | */ | 2505 | */ |
2289 | if (start_s == be16_to_cpu(hdr_s->count)) { | 2506 | if (start_s == ichdr_s->count) { |
2290 | tmp = count * sizeof(xfs_attr_leaf_entry_t); | 2507 | tmp = count * sizeof(xfs_attr_leaf_entry_t); |
2291 | entry_s = &leaf_s->entries[start_s]; | 2508 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; |
2292 | ASSERT(((char *)entry_s + tmp) <= | 2509 | ASSERT(((char *)entry_s + tmp) <= |
2293 | ((char *)leaf_s + XFS_LBSIZE(mp))); | 2510 | ((char *)leaf_s + XFS_LBSIZE(mp))); |
2294 | memset((char *)entry_s, 0, tmp); | 2511 | memset(entry_s, 0, tmp); |
2295 | } else { | 2512 | } else { |
2296 | /* | 2513 | /* |
2297 | * Move the remaining entries down to fill the hole, | 2514 | * Move the remaining entries down to fill the hole, |
2298 | * then zero the entries at the top. | 2515 | * then zero the entries at the top. |
2299 | */ | 2516 | */ |
2300 | tmp = be16_to_cpu(hdr_s->count) - count; | 2517 | tmp = (ichdr_s->count - count) * sizeof(xfs_attr_leaf_entry_t); |
2301 | tmp *= sizeof(xfs_attr_leaf_entry_t); | 2518 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[start_s + count]; |
2302 | entry_s = &leaf_s->entries[start_s + count]; | 2519 | entry_d = &xfs_attr3_leaf_entryp(leaf_s)[start_s]; |
2303 | entry_d = &leaf_s->entries[start_s]; | 2520 | memmove(entry_d, entry_s, tmp); |
2304 | memmove((char *)entry_d, (char *)entry_s, tmp); | ||
2305 | 2521 | ||
2306 | tmp = count * sizeof(xfs_attr_leaf_entry_t); | 2522 | tmp = count * sizeof(xfs_attr_leaf_entry_t); |
2307 | entry_s = &leaf_s->entries[be16_to_cpu(hdr_s->count)]; | 2523 | entry_s = &xfs_attr3_leaf_entryp(leaf_s)[ichdr_s->count]; |
2308 | ASSERT(((char *)entry_s + tmp) <= | 2524 | ASSERT(((char *)entry_s + tmp) <= |
2309 | ((char *)leaf_s + XFS_LBSIZE(mp))); | 2525 | ((char *)leaf_s + XFS_LBSIZE(mp))); |
2310 | memset((char *)entry_s, 0, tmp); | 2526 | memset(entry_s, 0, tmp); |
2311 | } | 2527 | } |
2312 | 2528 | ||
2313 | /* | 2529 | /* |
2314 | * Fill in the freemap information | 2530 | * Fill in the freemap information |
2315 | */ | 2531 | */ |
2316 | hdr_d->freemap[0].base = cpu_to_be16(sizeof(xfs_attr_leaf_hdr_t)); | 2532 | ichdr_d->freemap[0].base = xfs_attr3_leaf_hdr_size(leaf_d); |
2317 | be16_add_cpu(&hdr_d->freemap[0].base, be16_to_cpu(hdr_d->count) * | 2533 | ichdr_d->freemap[0].base += ichdr_d->count * sizeof(xfs_attr_leaf_entry_t); |
2318 | sizeof(xfs_attr_leaf_entry_t)); | 2534 | ichdr_d->freemap[0].size = ichdr_d->firstused - ichdr_d->freemap[0].base; |
2319 | hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused) | 2535 | ichdr_d->freemap[1].base = 0; |
2320 | - be16_to_cpu(hdr_d->freemap[0].base)); | 2536 | ichdr_d->freemap[2].base = 0; |
2321 | hdr_d->freemap[1].base = 0; | 2537 | ichdr_d->freemap[1].size = 0; |
2322 | hdr_d->freemap[2].base = 0; | 2538 | ichdr_d->freemap[2].size = 0; |
2323 | hdr_d->freemap[1].size = 0; | 2539 | ichdr_s->holes = 1; /* leaf may not be compact */ |
2324 | hdr_d->freemap[2].size = 0; | ||
2325 | hdr_s->holes = 1; /* leaf may not be compact */ | ||
2326 | } | ||
2327 | |||
2328 | /* | ||
2329 | * Compare two leaf blocks "order". | ||
2330 | * Return 0 unless leaf2 should go before leaf1. | ||
2331 | */ | ||
2332 | int | ||
2333 | xfs_attr_leaf_order( | ||
2334 | struct xfs_buf *leaf1_bp, | ||
2335 | struct xfs_buf *leaf2_bp) | ||
2336 | { | ||
2337 | xfs_attr_leafblock_t *leaf1, *leaf2; | ||
2338 | |||
2339 | leaf1 = leaf1_bp->b_addr; | ||
2340 | leaf2 = leaf2_bp->b_addr; | ||
2341 | ASSERT((leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) && | ||
2342 | (leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC))); | ||
2343 | if ((be16_to_cpu(leaf1->hdr.count) > 0) && | ||
2344 | (be16_to_cpu(leaf2->hdr.count) > 0) && | ||
2345 | ((be32_to_cpu(leaf2->entries[0].hashval) < | ||
2346 | be32_to_cpu(leaf1->entries[0].hashval)) || | ||
2347 | (be32_to_cpu(leaf2->entries[ | ||
2348 | be16_to_cpu(leaf2->hdr.count)-1].hashval) < | ||
2349 | be32_to_cpu(leaf1->entries[ | ||
2350 | be16_to_cpu(leaf1->hdr.count)-1].hashval)))) { | ||
2351 | return(1); | ||
2352 | } | ||
2353 | return(0); | ||
2354 | } | 2540 | } |
2355 | 2541 | ||
2356 | /* | 2542 | /* |
@@ -2361,15 +2547,16 @@ xfs_attr_leaf_lasthash( | |||
2361 | struct xfs_buf *bp, | 2547 | struct xfs_buf *bp, |
2362 | int *count) | 2548 | int *count) |
2363 | { | 2549 | { |
2364 | xfs_attr_leafblock_t *leaf; | 2550 | struct xfs_attr3_icleaf_hdr ichdr; |
2551 | struct xfs_attr_leaf_entry *entries; | ||
2365 | 2552 | ||
2366 | leaf = bp->b_addr; | 2553 | xfs_attr3_leaf_hdr_from_disk(&ichdr, bp->b_addr); |
2367 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2554 | entries = xfs_attr3_leaf_entryp(bp->b_addr); |
2368 | if (count) | 2555 | if (count) |
2369 | *count = be16_to_cpu(leaf->hdr.count); | 2556 | *count = ichdr.count; |
2370 | if (!leaf->hdr.count) | 2557 | if (!ichdr.count) |
2371 | return(0); | 2558 | return 0; |
2372 | return be32_to_cpu(leaf->entries[be16_to_cpu(leaf->hdr.count)-1].hashval); | 2559 | return be32_to_cpu(entries[ichdr.count - 1].hashval); |
2373 | } | 2560 | } |
2374 | 2561 | ||
2375 | /* | 2562 | /* |
@@ -2379,20 +2566,21 @@ xfs_attr_leaf_lasthash( | |||
2379 | STATIC int | 2566 | STATIC int |
2380 | xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) | 2567 | xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index) |
2381 | { | 2568 | { |
2569 | struct xfs_attr_leaf_entry *entries; | ||
2382 | xfs_attr_leaf_name_local_t *name_loc; | 2570 | xfs_attr_leaf_name_local_t *name_loc; |
2383 | xfs_attr_leaf_name_remote_t *name_rmt; | 2571 | xfs_attr_leaf_name_remote_t *name_rmt; |
2384 | int size; | 2572 | int size; |
2385 | 2573 | ||
2386 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 2574 | entries = xfs_attr3_leaf_entryp(leaf); |
2387 | if (leaf->entries[index].flags & XFS_ATTR_LOCAL) { | 2575 | if (entries[index].flags & XFS_ATTR_LOCAL) { |
2388 | name_loc = xfs_attr_leaf_name_local(leaf, index); | 2576 | name_loc = xfs_attr3_leaf_name_local(leaf, index); |
2389 | size = xfs_attr_leaf_entsize_local(name_loc->namelen, | 2577 | size = xfs_attr_leaf_entsize_local(name_loc->namelen, |
2390 | be16_to_cpu(name_loc->valuelen)); | 2578 | be16_to_cpu(name_loc->valuelen)); |
2391 | } else { | 2579 | } else { |
2392 | name_rmt = xfs_attr_leaf_name_remote(leaf, index); | 2580 | name_rmt = xfs_attr3_leaf_name_remote(leaf, index); |
2393 | size = xfs_attr_leaf_entsize_remote(name_rmt->namelen); | 2581 | size = xfs_attr_leaf_entsize_remote(name_rmt->namelen); |
2394 | } | 2582 | } |
2395 | return(size); | 2583 | return size; |
2396 | } | 2584 | } |
2397 | 2585 | ||
2398 | /* | 2586 | /* |
@@ -2417,35 +2605,40 @@ xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize, int *local) | |||
2417 | *local = 0; | 2605 | *local = 0; |
2418 | } | 2606 | } |
2419 | } | 2607 | } |
2420 | return(size); | 2608 | return size; |
2421 | } | 2609 | } |
2422 | 2610 | ||
2423 | /* | 2611 | /* |
2424 | * Copy out attribute list entries for attr_list(), for leaf attribute lists. | 2612 | * Copy out attribute list entries for attr_list(), for leaf attribute lists. |
2425 | */ | 2613 | */ |
2426 | int | 2614 | int |
2427 | xfs_attr_leaf_list_int( | 2615 | xfs_attr3_leaf_list_int( |
2428 | struct xfs_buf *bp, | 2616 | struct xfs_buf *bp, |
2429 | xfs_attr_list_context_t *context) | 2617 | struct xfs_attr_list_context *context) |
2430 | { | 2618 | { |
2431 | attrlist_cursor_kern_t *cursor; | 2619 | struct attrlist_cursor_kern *cursor; |
2432 | xfs_attr_leafblock_t *leaf; | 2620 | struct xfs_attr_leafblock *leaf; |
2433 | xfs_attr_leaf_entry_t *entry; | 2621 | struct xfs_attr3_icleaf_hdr ichdr; |
2434 | int retval, i; | 2622 | struct xfs_attr_leaf_entry *entries; |
2623 | struct xfs_attr_leaf_entry *entry; | ||
2624 | int retval; | ||
2625 | int i; | ||
2626 | |||
2627 | trace_xfs_attr_list_leaf(context); | ||
2435 | 2628 | ||
2436 | ASSERT(bp != NULL); | ||
2437 | leaf = bp->b_addr; | 2629 | leaf = bp->b_addr; |
2630 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | ||
2631 | entries = xfs_attr3_leaf_entryp(leaf); | ||
2632 | |||
2438 | cursor = context->cursor; | 2633 | cursor = context->cursor; |
2439 | cursor->initted = 1; | 2634 | cursor->initted = 1; |
2440 | 2635 | ||
2441 | trace_xfs_attr_list_leaf(context); | ||
2442 | |||
2443 | /* | 2636 | /* |
2444 | * Re-find our place in the leaf block if this is a new syscall. | 2637 | * Re-find our place in the leaf block if this is a new syscall. |
2445 | */ | 2638 | */ |
2446 | if (context->resynch) { | 2639 | if (context->resynch) { |
2447 | entry = &leaf->entries[0]; | 2640 | entry = &entries[0]; |
2448 | for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { | 2641 | for (i = 0; i < ichdr.count; entry++, i++) { |
2449 | if (be32_to_cpu(entry->hashval) == cursor->hashval) { | 2642 | if (be32_to_cpu(entry->hashval) == cursor->hashval) { |
2450 | if (cursor->offset == context->dupcnt) { | 2643 | if (cursor->offset == context->dupcnt) { |
2451 | context->dupcnt = 0; | 2644 | context->dupcnt = 0; |
@@ -2458,12 +2651,12 @@ xfs_attr_leaf_list_int( | |||
2458 | break; | 2651 | break; |
2459 | } | 2652 | } |
2460 | } | 2653 | } |
2461 | if (i == be16_to_cpu(leaf->hdr.count)) { | 2654 | if (i == ichdr.count) { |
2462 | trace_xfs_attr_list_notfound(context); | 2655 | trace_xfs_attr_list_notfound(context); |
2463 | return(0); | 2656 | return 0; |
2464 | } | 2657 | } |
2465 | } else { | 2658 | } else { |
2466 | entry = &leaf->entries[0]; | 2659 | entry = &entries[0]; |
2467 | i = 0; | 2660 | i = 0; |
2468 | } | 2661 | } |
2469 | context->resynch = 0; | 2662 | context->resynch = 0; |
@@ -2472,7 +2665,7 @@ xfs_attr_leaf_list_int( | |||
2472 | * We have found our place, start copying out the new attributes. | 2665 | * We have found our place, start copying out the new attributes. |
2473 | */ | 2666 | */ |
2474 | retval = 0; | 2667 | retval = 0; |
2475 | for ( ; (i < be16_to_cpu(leaf->hdr.count)); entry++, i++) { | 2668 | for (; i < ichdr.count; entry++, i++) { |
2476 | if (be32_to_cpu(entry->hashval) != cursor->hashval) { | 2669 | if (be32_to_cpu(entry->hashval) != cursor->hashval) { |
2477 | cursor->hashval = be32_to_cpu(entry->hashval); | 2670 | cursor->hashval = be32_to_cpu(entry->hashval); |
2478 | cursor->offset = 0; | 2671 | cursor->offset = 0; |
@@ -2483,7 +2676,7 @@ xfs_attr_leaf_list_int( | |||
2483 | 2676 | ||
2484 | if (entry->flags & XFS_ATTR_LOCAL) { | 2677 | if (entry->flags & XFS_ATTR_LOCAL) { |
2485 | xfs_attr_leaf_name_local_t *name_loc = | 2678 | xfs_attr_leaf_name_local_t *name_loc = |
2486 | xfs_attr_leaf_name_local(leaf, i); | 2679 | xfs_attr3_leaf_name_local(leaf, i); |
2487 | 2680 | ||
2488 | retval = context->put_listent(context, | 2681 | retval = context->put_listent(context, |
2489 | entry->flags, | 2682 | entry->flags, |
@@ -2495,7 +2688,7 @@ xfs_attr_leaf_list_int( | |||
2495 | return retval; | 2688 | return retval; |
2496 | } else { | 2689 | } else { |
2497 | xfs_attr_leaf_name_remote_t *name_rmt = | 2690 | xfs_attr_leaf_name_remote_t *name_rmt = |
2498 | xfs_attr_leaf_name_remote(leaf, i); | 2691 | xfs_attr3_leaf_name_remote(leaf, i); |
2499 | 2692 | ||
2500 | int valuelen = be32_to_cpu(name_rmt->valuelen); | 2693 | int valuelen = be32_to_cpu(name_rmt->valuelen); |
2501 | 2694 | ||
@@ -2535,7 +2728,7 @@ xfs_attr_leaf_list_int( | |||
2535 | cursor->offset++; | 2728 | cursor->offset++; |
2536 | } | 2729 | } |
2537 | trace_xfs_attr_list_leaf_end(context); | 2730 | trace_xfs_attr_list_leaf_end(context); |
2538 | return(retval); | 2731 | return retval; |
2539 | } | 2732 | } |
2540 | 2733 | ||
2541 | 2734 | ||
@@ -2547,14 +2740,16 @@ xfs_attr_leaf_list_int( | |||
2547 | * Clear the INCOMPLETE flag on an entry in a leaf block. | 2740 | * Clear the INCOMPLETE flag on an entry in a leaf block. |
2548 | */ | 2741 | */ |
2549 | int | 2742 | int |
2550 | xfs_attr_leaf_clearflag(xfs_da_args_t *args) | 2743 | xfs_attr3_leaf_clearflag( |
2744 | struct xfs_da_args *args) | ||
2551 | { | 2745 | { |
2552 | xfs_attr_leafblock_t *leaf; | 2746 | struct xfs_attr_leafblock *leaf; |
2553 | xfs_attr_leaf_entry_t *entry; | 2747 | struct xfs_attr_leaf_entry *entry; |
2554 | xfs_attr_leaf_name_remote_t *name_rmt; | 2748 | struct xfs_attr_leaf_name_remote *name_rmt; |
2555 | struct xfs_buf *bp; | 2749 | struct xfs_buf *bp; |
2556 | int error; | 2750 | int error; |
2557 | #ifdef DEBUG | 2751 | #ifdef DEBUG |
2752 | struct xfs_attr3_icleaf_hdr ichdr; | ||
2558 | xfs_attr_leaf_name_local_t *name_loc; | 2753 | xfs_attr_leaf_name_local_t *name_loc; |
2559 | int namelen; | 2754 | int namelen; |
2560 | char *name; | 2755 | char *name; |
@@ -2564,23 +2759,25 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) | |||
2564 | /* | 2759 | /* |
2565 | * Set up the operation. | 2760 | * Set up the operation. |
2566 | */ | 2761 | */ |
2567 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); | 2762 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); |
2568 | if (error) | 2763 | if (error) |
2569 | return(error); | 2764 | return(error); |
2570 | 2765 | ||
2571 | leaf = bp->b_addr; | 2766 | leaf = bp->b_addr; |
2572 | ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); | 2767 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; |
2573 | ASSERT(args->index >= 0); | ||
2574 | entry = &leaf->entries[ args->index ]; | ||
2575 | ASSERT(entry->flags & XFS_ATTR_INCOMPLETE); | 2768 | ASSERT(entry->flags & XFS_ATTR_INCOMPLETE); |
2576 | 2769 | ||
2577 | #ifdef DEBUG | 2770 | #ifdef DEBUG |
2771 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | ||
2772 | ASSERT(args->index < ichdr.count); | ||
2773 | ASSERT(args->index >= 0); | ||
2774 | |||
2578 | if (entry->flags & XFS_ATTR_LOCAL) { | 2775 | if (entry->flags & XFS_ATTR_LOCAL) { |
2579 | name_loc = xfs_attr_leaf_name_local(leaf, args->index); | 2776 | name_loc = xfs_attr3_leaf_name_local(leaf, args->index); |
2580 | namelen = name_loc->namelen; | 2777 | namelen = name_loc->namelen; |
2581 | name = (char *)name_loc->nameval; | 2778 | name = (char *)name_loc->nameval; |
2582 | } else { | 2779 | } else { |
2583 | name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); | 2780 | name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); |
2584 | namelen = name_rmt->namelen; | 2781 | namelen = name_rmt->namelen; |
2585 | name = (char *)name_rmt->name; | 2782 | name = (char *)name_rmt->name; |
2586 | } | 2783 | } |
@@ -2595,7 +2792,7 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) | |||
2595 | 2792 | ||
2596 | if (args->rmtblkno) { | 2793 | if (args->rmtblkno) { |
2597 | ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0); | 2794 | ASSERT((entry->flags & XFS_ATTR_LOCAL) == 0); |
2598 | name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); | 2795 | name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); |
2599 | name_rmt->valueblk = cpu_to_be32(args->rmtblkno); | 2796 | name_rmt->valueblk = cpu_to_be32(args->rmtblkno); |
2600 | name_rmt->valuelen = cpu_to_be32(args->valuelen); | 2797 | name_rmt->valuelen = cpu_to_be32(args->valuelen); |
2601 | xfs_trans_log_buf(args->trans, bp, | 2798 | xfs_trans_log_buf(args->trans, bp, |
@@ -2612,34 +2809,41 @@ xfs_attr_leaf_clearflag(xfs_da_args_t *args) | |||
2612 | * Set the INCOMPLETE flag on an entry in a leaf block. | 2809 | * Set the INCOMPLETE flag on an entry in a leaf block. |
2613 | */ | 2810 | */ |
2614 | int | 2811 | int |
2615 | xfs_attr_leaf_setflag(xfs_da_args_t *args) | 2812 | xfs_attr3_leaf_setflag( |
2813 | struct xfs_da_args *args) | ||
2616 | { | 2814 | { |
2617 | xfs_attr_leafblock_t *leaf; | 2815 | struct xfs_attr_leafblock *leaf; |
2618 | xfs_attr_leaf_entry_t *entry; | 2816 | struct xfs_attr_leaf_entry *entry; |
2619 | xfs_attr_leaf_name_remote_t *name_rmt; | 2817 | struct xfs_attr_leaf_name_remote *name_rmt; |
2620 | struct xfs_buf *bp; | 2818 | struct xfs_buf *bp; |
2621 | int error; | 2819 | int error; |
2820 | #ifdef DEBUG | ||
2821 | struct xfs_attr3_icleaf_hdr ichdr; | ||
2822 | #endif | ||
2622 | 2823 | ||
2623 | trace_xfs_attr_leaf_setflag(args); | 2824 | trace_xfs_attr_leaf_setflag(args); |
2624 | 2825 | ||
2625 | /* | 2826 | /* |
2626 | * Set up the operation. | 2827 | * Set up the operation. |
2627 | */ | 2828 | */ |
2628 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); | 2829 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); |
2629 | if (error) | 2830 | if (error) |
2630 | return(error); | 2831 | return(error); |
2631 | 2832 | ||
2632 | leaf = bp->b_addr; | 2833 | leaf = bp->b_addr; |
2633 | ASSERT(args->index < be16_to_cpu(leaf->hdr.count)); | 2834 | #ifdef DEBUG |
2835 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); | ||
2836 | ASSERT(args->index < ichdr.count); | ||
2634 | ASSERT(args->index >= 0); | 2837 | ASSERT(args->index >= 0); |
2635 | entry = &leaf->entries[ args->index ]; | 2838 | #endif |
2839 | entry = &xfs_attr3_leaf_entryp(leaf)[args->index]; | ||
2636 | 2840 | ||
2637 | ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0); | 2841 | ASSERT((entry->flags & XFS_ATTR_INCOMPLETE) == 0); |
2638 | entry->flags |= XFS_ATTR_INCOMPLETE; | 2842 | entry->flags |= XFS_ATTR_INCOMPLETE; |
2639 | xfs_trans_log_buf(args->trans, bp, | 2843 | xfs_trans_log_buf(args->trans, bp, |
2640 | XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); | 2844 | XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); |
2641 | if ((entry->flags & XFS_ATTR_LOCAL) == 0) { | 2845 | if ((entry->flags & XFS_ATTR_LOCAL) == 0) { |
2642 | name_rmt = xfs_attr_leaf_name_remote(leaf, args->index); | 2846 | name_rmt = xfs_attr3_leaf_name_remote(leaf, args->index); |
2643 | name_rmt->valueblk = 0; | 2847 | name_rmt->valueblk = 0; |
2644 | name_rmt->valuelen = 0; | 2848 | name_rmt->valuelen = 0; |
2645 | xfs_trans_log_buf(args->trans, bp, | 2849 | xfs_trans_log_buf(args->trans, bp, |
@@ -2660,14 +2864,20 @@ xfs_attr_leaf_setflag(xfs_da_args_t *args) | |||
2660 | * Note that they could be in different blocks, or in the same block. | 2864 | * Note that they could be in different blocks, or in the same block. |
2661 | */ | 2865 | */ |
2662 | int | 2866 | int |
2663 | xfs_attr_leaf_flipflags(xfs_da_args_t *args) | 2867 | xfs_attr3_leaf_flipflags( |
2868 | struct xfs_da_args *args) | ||
2664 | { | 2869 | { |
2665 | xfs_attr_leafblock_t *leaf1, *leaf2; | 2870 | struct xfs_attr_leafblock *leaf1; |
2666 | xfs_attr_leaf_entry_t *entry1, *entry2; | 2871 | struct xfs_attr_leafblock *leaf2; |
2667 | xfs_attr_leaf_name_remote_t *name_rmt; | 2872 | struct xfs_attr_leaf_entry *entry1; |
2668 | struct xfs_buf *bp1, *bp2; | 2873 | struct xfs_attr_leaf_entry *entry2; |
2874 | struct xfs_attr_leaf_name_remote *name_rmt; | ||
2875 | struct xfs_buf *bp1; | ||
2876 | struct xfs_buf *bp2; | ||
2669 | int error; | 2877 | int error; |
2670 | #ifdef DEBUG | 2878 | #ifdef DEBUG |
2879 | struct xfs_attr3_icleaf_hdr ichdr1; | ||
2880 | struct xfs_attr3_icleaf_hdr ichdr2; | ||
2671 | xfs_attr_leaf_name_local_t *name_loc; | 2881 | xfs_attr_leaf_name_local_t *name_loc; |
2672 | int namelen1, namelen2; | 2882 | int namelen1, namelen2; |
2673 | char *name1, *name2; | 2883 | char *name1, *name2; |
@@ -2678,7 +2888,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) | |||
2678 | /* | 2888 | /* |
2679 | * Read the block containing the "old" attr | 2889 | * Read the block containing the "old" attr |
2680 | */ | 2890 | */ |
2681 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp1); | 2891 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp1); |
2682 | if (error) | 2892 | if (error) |
2683 | return error; | 2893 | return error; |
2684 | 2894 | ||
@@ -2686,7 +2896,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) | |||
2686 | * Read the block containing the "new" attr, if it is different | 2896 | * Read the block containing the "new" attr, if it is different |
2687 | */ | 2897 | */ |
2688 | if (args->blkno2 != args->blkno) { | 2898 | if (args->blkno2 != args->blkno) { |
2689 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno2, | 2899 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno2, |
2690 | -1, &bp2); | 2900 | -1, &bp2); |
2691 | if (error) | 2901 | if (error) |
2692 | return error; | 2902 | return error; |
@@ -2695,31 +2905,35 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) | |||
2695 | } | 2905 | } |
2696 | 2906 | ||
2697 | leaf1 = bp1->b_addr; | 2907 | leaf1 = bp1->b_addr; |
2698 | ASSERT(args->index < be16_to_cpu(leaf1->hdr.count)); | 2908 | entry1 = &xfs_attr3_leaf_entryp(leaf1)[args->index]; |
2699 | ASSERT(args->index >= 0); | ||
2700 | entry1 = &leaf1->entries[ args->index ]; | ||
2701 | 2909 | ||
2702 | leaf2 = bp2->b_addr; | 2910 | leaf2 = bp2->b_addr; |
2703 | ASSERT(args->index2 < be16_to_cpu(leaf2->hdr.count)); | 2911 | entry2 = &xfs_attr3_leaf_entryp(leaf2)[args->index2]; |
2704 | ASSERT(args->index2 >= 0); | ||
2705 | entry2 = &leaf2->entries[ args->index2 ]; | ||
2706 | 2912 | ||
2707 | #ifdef DEBUG | 2913 | #ifdef DEBUG |
2914 | xfs_attr3_leaf_hdr_from_disk(&ichdr1, leaf1); | ||
2915 | ASSERT(args->index < ichdr1.count); | ||
2916 | ASSERT(args->index >= 0); | ||
2917 | |||
2918 | xfs_attr3_leaf_hdr_from_disk(&ichdr2, leaf2); | ||
2919 | ASSERT(args->index2 < ichdr2.count); | ||
2920 | ASSERT(args->index2 >= 0); | ||
2921 | |||
2708 | if (entry1->flags & XFS_ATTR_LOCAL) { | 2922 | if (entry1->flags & XFS_ATTR_LOCAL) { |
2709 | name_loc = xfs_attr_leaf_name_local(leaf1, args->index); | 2923 | name_loc = xfs_attr3_leaf_name_local(leaf1, args->index); |
2710 | namelen1 = name_loc->namelen; | 2924 | namelen1 = name_loc->namelen; |
2711 | name1 = (char *)name_loc->nameval; | 2925 | name1 = (char *)name_loc->nameval; |
2712 | } else { | 2926 | } else { |
2713 | name_rmt = xfs_attr_leaf_name_remote(leaf1, args->index); | 2927 | name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index); |
2714 | namelen1 = name_rmt->namelen; | 2928 | namelen1 = name_rmt->namelen; |
2715 | name1 = (char *)name_rmt->name; | 2929 | name1 = (char *)name_rmt->name; |
2716 | } | 2930 | } |
2717 | if (entry2->flags & XFS_ATTR_LOCAL) { | 2931 | if (entry2->flags & XFS_ATTR_LOCAL) { |
2718 | name_loc = xfs_attr_leaf_name_local(leaf2, args->index2); | 2932 | name_loc = xfs_attr3_leaf_name_local(leaf2, args->index2); |
2719 | namelen2 = name_loc->namelen; | 2933 | namelen2 = name_loc->namelen; |
2720 | name2 = (char *)name_loc->nameval; | 2934 | name2 = (char *)name_loc->nameval; |
2721 | } else { | 2935 | } else { |
2722 | name_rmt = xfs_attr_leaf_name_remote(leaf2, args->index2); | 2936 | name_rmt = xfs_attr3_leaf_name_remote(leaf2, args->index2); |
2723 | namelen2 = name_rmt->namelen; | 2937 | namelen2 = name_rmt->namelen; |
2724 | name2 = (char *)name_rmt->name; | 2938 | name2 = (char *)name_rmt->name; |
2725 | } | 2939 | } |
@@ -2736,7 +2950,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) | |||
2736 | XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1))); | 2950 | XFS_DA_LOGRANGE(leaf1, entry1, sizeof(*entry1))); |
2737 | if (args->rmtblkno) { | 2951 | if (args->rmtblkno) { |
2738 | ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0); | 2952 | ASSERT((entry1->flags & XFS_ATTR_LOCAL) == 0); |
2739 | name_rmt = xfs_attr_leaf_name_remote(leaf1, args->index); | 2953 | name_rmt = xfs_attr3_leaf_name_remote(leaf1, args->index); |
2740 | name_rmt->valueblk = cpu_to_be32(args->rmtblkno); | 2954 | name_rmt->valueblk = cpu_to_be32(args->rmtblkno); |
2741 | name_rmt->valuelen = cpu_to_be32(args->valuelen); | 2955 | name_rmt->valuelen = cpu_to_be32(args->valuelen); |
2742 | xfs_trans_log_buf(args->trans, bp1, | 2956 | xfs_trans_log_buf(args->trans, bp1, |
@@ -2747,7 +2961,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) | |||
2747 | xfs_trans_log_buf(args->trans, bp2, | 2961 | xfs_trans_log_buf(args->trans, bp2, |
2748 | XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2))); | 2962 | XFS_DA_LOGRANGE(leaf2, entry2, sizeof(*entry2))); |
2749 | if ((entry2->flags & XFS_ATTR_LOCAL) == 0) { | 2963 | if ((entry2->flags & XFS_ATTR_LOCAL) == 0) { |
2750 | name_rmt = xfs_attr_leaf_name_remote(leaf2, args->index2); | 2964 | name_rmt = xfs_attr3_leaf_name_remote(leaf2, args->index2); |
2751 | name_rmt->valueblk = 0; | 2965 | name_rmt->valueblk = 0; |
2752 | name_rmt->valuelen = 0; | 2966 | name_rmt->valuelen = 0; |
2753 | xfs_trans_log_buf(args->trans, bp2, | 2967 | xfs_trans_log_buf(args->trans, bp2, |
@@ -2759,7 +2973,7 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) | |||
2759 | */ | 2973 | */ |
2760 | error = xfs_trans_roll(&args->trans, args->dp); | 2974 | error = xfs_trans_roll(&args->trans, args->dp); |
2761 | 2975 | ||
2762 | return(error); | 2976 | return error; |
2763 | } | 2977 | } |
2764 | 2978 | ||
2765 | /*======================================================================== | 2979 | /*======================================================================== |
@@ -2771,12 +2985,14 @@ xfs_attr_leaf_flipflags(xfs_da_args_t *args) | |||
2771 | * We're doing a depth-first traversal in order to invalidate everything. | 2985 | * We're doing a depth-first traversal in order to invalidate everything. |
2772 | */ | 2986 | */ |
2773 | int | 2987 | int |
2774 | xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) | 2988 | xfs_attr3_root_inactive( |
2989 | struct xfs_trans **trans, | ||
2990 | struct xfs_inode *dp) | ||
2775 | { | 2991 | { |
2776 | xfs_da_blkinfo_t *info; | 2992 | struct xfs_da_blkinfo *info; |
2777 | xfs_daddr_t blkno; | 2993 | struct xfs_buf *bp; |
2778 | struct xfs_buf *bp; | 2994 | xfs_daddr_t blkno; |
2779 | int error; | 2995 | int error; |
2780 | 2996 | ||
2781 | /* | 2997 | /* |
2782 | * Read block 0 to see what we have to work with. | 2998 | * Read block 0 to see what we have to work with. |
@@ -2786,38 +3002,44 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) | |||
2786 | */ | 3002 | */ |
2787 | error = xfs_da3_node_read(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK); | 3003 | error = xfs_da3_node_read(*trans, dp, 0, -1, &bp, XFS_ATTR_FORK); |
2788 | if (error) | 3004 | if (error) |
2789 | return(error); | 3005 | return error; |
2790 | blkno = XFS_BUF_ADDR(bp); | 3006 | blkno = bp->b_bn; |
2791 | 3007 | ||
2792 | /* | 3008 | /* |
2793 | * Invalidate the tree, even if the "tree" is only a single leaf block. | 3009 | * Invalidate the tree, even if the "tree" is only a single leaf block. |
2794 | * This is a depth-first traversal! | 3010 | * This is a depth-first traversal! |
2795 | */ | 3011 | */ |
2796 | info = bp->b_addr; | 3012 | info = bp->b_addr; |
2797 | if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) { | 3013 | switch (info->magic) { |
2798 | error = xfs_attr_node_inactive(trans, dp, bp, 1); | 3014 | case cpu_to_be16(XFS_DA_NODE_MAGIC): |
2799 | } else if (info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) { | 3015 | case cpu_to_be16(XFS_DA3_NODE_MAGIC): |
2800 | error = xfs_attr_leaf_inactive(trans, dp, bp); | 3016 | error = xfs_attr3_node_inactive(trans, dp, bp, 1); |
2801 | } else { | 3017 | break; |
3018 | case cpu_to_be16(XFS_ATTR_LEAF_MAGIC): | ||
3019 | case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): | ||
3020 | error = xfs_attr3_leaf_inactive(trans, dp, bp); | ||
3021 | break; | ||
3022 | default: | ||
2802 | error = XFS_ERROR(EIO); | 3023 | error = XFS_ERROR(EIO); |
2803 | xfs_trans_brelse(*trans, bp); | 3024 | xfs_trans_brelse(*trans, bp); |
3025 | break; | ||
2804 | } | 3026 | } |
2805 | if (error) | 3027 | if (error) |
2806 | return(error); | 3028 | return error; |
2807 | 3029 | ||
2808 | /* | 3030 | /* |
2809 | * Invalidate the incore copy of the root block. | 3031 | * Invalidate the incore copy of the root block. |
2810 | */ | 3032 | */ |
2811 | error = xfs_da_get_buf(*trans, dp, 0, blkno, &bp, XFS_ATTR_FORK); | 3033 | error = xfs_da_get_buf(*trans, dp, 0, blkno, &bp, XFS_ATTR_FORK); |
2812 | if (error) | 3034 | if (error) |
2813 | return(error); | 3035 | return error; |
2814 | xfs_trans_binval(*trans, bp); /* remove from cache */ | 3036 | xfs_trans_binval(*trans, bp); /* remove from cache */ |
2815 | /* | 3037 | /* |
2816 | * Commit the invalidate and start the next transaction. | 3038 | * Commit the invalidate and start the next transaction. |
2817 | */ | 3039 | */ |
2818 | error = xfs_trans_roll(trans, dp); | 3040 | error = xfs_trans_roll(trans, dp); |
2819 | 3041 | ||
2820 | return (error); | 3042 | return error; |
2821 | } | 3043 | } |
2822 | 3044 | ||
2823 | /* | 3045 | /* |
@@ -2825,7 +3047,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp) | |||
2825 | * We're doing a depth-first traversal in order to invalidate everything. | 3047 | * We're doing a depth-first traversal in order to invalidate everything. |
2826 | */ | 3048 | */ |
2827 | STATIC int | 3049 | STATIC int |
2828 | xfs_attr_node_inactive( | 3050 | xfs_attr3_node_inactive( |
2829 | struct xfs_trans **trans, | 3051 | struct xfs_trans **trans, |
2830 | struct xfs_inode *dp, | 3052 | struct xfs_inode *dp, |
2831 | struct xfs_buf *bp, | 3053 | struct xfs_buf *bp, |
@@ -2835,25 +3057,25 @@ xfs_attr_node_inactive( | |||
2835 | xfs_da_intnode_t *node; | 3057 | xfs_da_intnode_t *node; |
2836 | xfs_dablk_t child_fsb; | 3058 | xfs_dablk_t child_fsb; |
2837 | xfs_daddr_t parent_blkno, child_blkno; | 3059 | xfs_daddr_t parent_blkno, child_blkno; |
2838 | int error, count, i; | 3060 | int error, i; |
2839 | struct xfs_buf *child_bp; | 3061 | struct xfs_buf *child_bp; |
2840 | struct xfs_da_node_entry *btree; | 3062 | struct xfs_da_node_entry *btree; |
3063 | struct xfs_da3_icnode_hdr ichdr; | ||
2841 | 3064 | ||
2842 | /* | 3065 | /* |
2843 | * Since this code is recursive (gasp!) we must protect ourselves. | 3066 | * Since this code is recursive (gasp!) we must protect ourselves. |
2844 | */ | 3067 | */ |
2845 | if (level > XFS_DA_NODE_MAXDEPTH) { | 3068 | if (level > XFS_DA_NODE_MAXDEPTH) { |
2846 | xfs_trans_brelse(*trans, bp); /* no locks for later trans */ | 3069 | xfs_trans_brelse(*trans, bp); /* no locks for later trans */ |
2847 | return(XFS_ERROR(EIO)); | 3070 | return XFS_ERROR(EIO); |
2848 | } | 3071 | } |
2849 | 3072 | ||
2850 | node = bp->b_addr; | 3073 | node = bp->b_addr; |
2851 | ASSERT(node->hdr.info.magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); | 3074 | xfs_da3_node_hdr_from_disk(&ichdr, node); |
2852 | parent_blkno = XFS_BUF_ADDR(bp); /* save for re-read later */ | 3075 | parent_blkno = bp->b_bn; |
2853 | count = be16_to_cpu(node->hdr.count); | 3076 | if (!ichdr.count) { |
2854 | if (!count) { | ||
2855 | xfs_trans_brelse(*trans, bp); | 3077 | xfs_trans_brelse(*trans, bp); |
2856 | return(0); | 3078 | return 0; |
2857 | } | 3079 | } |
2858 | btree = xfs_da3_node_tree_p(node); | 3080 | btree = xfs_da3_node_tree_p(node); |
2859 | child_fsb = be32_to_cpu(btree[0].before); | 3081 | child_fsb = be32_to_cpu(btree[0].before); |
@@ -2864,7 +3086,7 @@ xfs_attr_node_inactive( | |||
2864 | * over the leaves removing all of them. If this is higher up | 3086 | * over the leaves removing all of them. If this is higher up |
2865 | * in the tree, recurse downward. | 3087 | * in the tree, recurse downward. |
2866 | */ | 3088 | */ |
2867 | for (i = 0; i < count; i++) { | 3089 | for (i = 0; i < ichdr.count; i++) { |
2868 | /* | 3090 | /* |
2869 | * Read the subsidiary block to see what we have to work with. | 3091 | * Read the subsidiary block to see what we have to work with. |
2870 | * Don't do this in a transaction. This is a depth-first | 3092 | * Don't do this in a transaction. This is a depth-first |
@@ -2883,18 +3105,24 @@ xfs_attr_node_inactive( | |||
2883 | * Invalidate the subtree, however we have to. | 3105 | * Invalidate the subtree, however we have to. |
2884 | */ | 3106 | */ |
2885 | info = child_bp->b_addr; | 3107 | info = child_bp->b_addr; |
2886 | if (info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)) { | 3108 | switch (info->magic) { |
2887 | error = xfs_attr_node_inactive(trans, dp, | 3109 | case cpu_to_be16(XFS_DA_NODE_MAGIC): |
2888 | child_bp, level+1); | 3110 | case cpu_to_be16(XFS_DA3_NODE_MAGIC): |
2889 | } else if (info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) { | 3111 | error = xfs_attr3_node_inactive(trans, dp, |
2890 | error = xfs_attr_leaf_inactive(trans, dp, | 3112 | child_bp, level + 1); |
2891 | child_bp); | 3113 | break; |
2892 | } else { | 3114 | case cpu_to_be16(XFS_ATTR_LEAF_MAGIC): |
3115 | case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): | ||
3116 | error = xfs_attr3_leaf_inactive(trans, dp, | ||
3117 | child_bp); | ||
3118 | break; | ||
3119 | default: | ||
2893 | error = XFS_ERROR(EIO); | 3120 | error = XFS_ERROR(EIO); |
2894 | xfs_trans_brelse(*trans, child_bp); | 3121 | xfs_trans_brelse(*trans, child_bp); |
3122 | break; | ||
2895 | } | 3123 | } |
2896 | if (error) | 3124 | if (error) |
2897 | return(error); | 3125 | return error; |
2898 | 3126 | ||
2899 | /* | 3127 | /* |
2900 | * Remove the subsidiary block from the cache | 3128 | * Remove the subsidiary block from the cache |
@@ -2903,7 +3131,7 @@ xfs_attr_node_inactive( | |||
2903 | error = xfs_da_get_buf(*trans, dp, 0, child_blkno, | 3131 | error = xfs_da_get_buf(*trans, dp, 0, child_blkno, |
2904 | &child_bp, XFS_ATTR_FORK); | 3132 | &child_bp, XFS_ATTR_FORK); |
2905 | if (error) | 3133 | if (error) |
2906 | return(error); | 3134 | return error; |
2907 | xfs_trans_binval(*trans, child_bp); | 3135 | xfs_trans_binval(*trans, child_bp); |
2908 | } | 3136 | } |
2909 | 3137 | ||
@@ -2911,12 +3139,12 @@ xfs_attr_node_inactive( | |||
2911 | * If we're not done, re-read the parent to get the next | 3139 | * If we're not done, re-read the parent to get the next |
2912 | * child block number. | 3140 | * child block number. |
2913 | */ | 3141 | */ |
2914 | if ((i+1) < count) { | 3142 | if (i + 1 < ichdr.count) { |
2915 | error = xfs_da3_node_read(*trans, dp, 0, parent_blkno, | 3143 | error = xfs_da3_node_read(*trans, dp, 0, parent_blkno, |
2916 | &bp, XFS_ATTR_FORK); | 3144 | &bp, XFS_ATTR_FORK); |
2917 | if (error) | 3145 | if (error) |
2918 | return(error); | 3146 | return error; |
2919 | child_fsb = be32_to_cpu(btree[i+1].before); | 3147 | child_fsb = be32_to_cpu(btree[i + 1].before); |
2920 | xfs_trans_brelse(*trans, bp); | 3148 | xfs_trans_brelse(*trans, bp); |
2921 | } | 3149 | } |
2922 | /* | 3150 | /* |
@@ -2924,10 +3152,10 @@ xfs_attr_node_inactive( | |||
2924 | */ | 3152 | */ |
2925 | error = xfs_trans_roll(trans, dp); | 3153 | error = xfs_trans_roll(trans, dp); |
2926 | if (error) | 3154 | if (error) |
2927 | return (error); | 3155 | return error; |
2928 | } | 3156 | } |
2929 | 3157 | ||
2930 | return(0); | 3158 | return 0; |
2931 | } | 3159 | } |
2932 | 3160 | ||
2933 | /* | 3161 | /* |
@@ -2937,29 +3165,35 @@ xfs_attr_node_inactive( | |||
2937 | * caught holding something that the logging code wants to flush to disk. | 3165 | * caught holding something that the logging code wants to flush to disk. |
2938 | */ | 3166 | */ |
2939 | STATIC int | 3167 | STATIC int |
2940 | xfs_attr_leaf_inactive( | 3168 | xfs_attr3_leaf_inactive( |
2941 | struct xfs_trans **trans, | 3169 | struct xfs_trans **trans, |
2942 | struct xfs_inode *dp, | 3170 | struct xfs_inode *dp, |
2943 | struct xfs_buf *bp) | 3171 | struct xfs_buf *bp) |
2944 | { | 3172 | { |
2945 | xfs_attr_leafblock_t *leaf; | 3173 | struct xfs_attr_leafblock *leaf; |
2946 | xfs_attr_leaf_entry_t *entry; | 3174 | struct xfs_attr3_icleaf_hdr ichdr; |
2947 | xfs_attr_leaf_name_remote_t *name_rmt; | 3175 | struct xfs_attr_leaf_entry *entry; |
2948 | xfs_attr_inactive_list_t *list, *lp; | 3176 | struct xfs_attr_leaf_name_remote *name_rmt; |
2949 | int error, count, size, tmp, i; | 3177 | struct xfs_attr_inactive_list *list; |
3178 | struct xfs_attr_inactive_list *lp; | ||
3179 | int error; | ||
3180 | int count; | ||
3181 | int size; | ||
3182 | int tmp; | ||
3183 | int i; | ||
2950 | 3184 | ||
2951 | leaf = bp->b_addr; | 3185 | leaf = bp->b_addr; |
2952 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 3186 | xfs_attr3_leaf_hdr_from_disk(&ichdr, leaf); |
2953 | 3187 | ||
2954 | /* | 3188 | /* |
2955 | * Count the number of "remote" value extents. | 3189 | * Count the number of "remote" value extents. |
2956 | */ | 3190 | */ |
2957 | count = 0; | 3191 | count = 0; |
2958 | entry = &leaf->entries[0]; | 3192 | entry = xfs_attr3_leaf_entryp(leaf); |
2959 | for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { | 3193 | for (i = 0; i < ichdr.count; entry++, i++) { |
2960 | if (be16_to_cpu(entry->nameidx) && | 3194 | if (be16_to_cpu(entry->nameidx) && |
2961 | ((entry->flags & XFS_ATTR_LOCAL) == 0)) { | 3195 | ((entry->flags & XFS_ATTR_LOCAL) == 0)) { |
2962 | name_rmt = xfs_attr_leaf_name_remote(leaf, i); | 3196 | name_rmt = xfs_attr3_leaf_name_remote(leaf, i); |
2963 | if (name_rmt->valueblk) | 3197 | if (name_rmt->valueblk) |
2964 | count++; | 3198 | count++; |
2965 | } | 3199 | } |
@@ -2970,24 +3204,24 @@ xfs_attr_leaf_inactive( | |||
2970 | */ | 3204 | */ |
2971 | if (count == 0) { | 3205 | if (count == 0) { |
2972 | xfs_trans_brelse(*trans, bp); | 3206 | xfs_trans_brelse(*trans, bp); |
2973 | return(0); | 3207 | return 0; |
2974 | } | 3208 | } |
2975 | 3209 | ||
2976 | /* | 3210 | /* |
2977 | * Allocate storage for a list of all the "remote" value extents. | 3211 | * Allocate storage for a list of all the "remote" value extents. |
2978 | */ | 3212 | */ |
2979 | size = count * sizeof(xfs_attr_inactive_list_t); | 3213 | size = count * sizeof(xfs_attr_inactive_list_t); |
2980 | list = (xfs_attr_inactive_list_t *)kmem_alloc(size, KM_SLEEP); | 3214 | list = kmem_alloc(size, KM_SLEEP); |
2981 | 3215 | ||
2982 | /* | 3216 | /* |
2983 | * Identify each of the "remote" value extents. | 3217 | * Identify each of the "remote" value extents. |
2984 | */ | 3218 | */ |
2985 | lp = list; | 3219 | lp = list; |
2986 | entry = &leaf->entries[0]; | 3220 | entry = xfs_attr3_leaf_entryp(leaf); |
2987 | for (i = 0; i < be16_to_cpu(leaf->hdr.count); entry++, i++) { | 3221 | for (i = 0; i < ichdr.count; entry++, i++) { |
2988 | if (be16_to_cpu(entry->nameidx) && | 3222 | if (be16_to_cpu(entry->nameidx) && |
2989 | ((entry->flags & XFS_ATTR_LOCAL) == 0)) { | 3223 | ((entry->flags & XFS_ATTR_LOCAL) == 0)) { |
2990 | name_rmt = xfs_attr_leaf_name_remote(leaf, i); | 3224 | name_rmt = xfs_attr3_leaf_name_remote(leaf, i); |
2991 | if (name_rmt->valueblk) { | 3225 | if (name_rmt->valueblk) { |
2992 | lp->valueblk = be32_to_cpu(name_rmt->valueblk); | 3226 | lp->valueblk = be32_to_cpu(name_rmt->valueblk); |
2993 | lp->valuelen = XFS_B_TO_FSB(dp->i_mount, | 3227 | lp->valuelen = XFS_B_TO_FSB(dp->i_mount, |
@@ -3003,15 +3237,15 @@ xfs_attr_leaf_inactive( | |||
3003 | */ | 3237 | */ |
3004 | error = 0; | 3238 | error = 0; |
3005 | for (lp = list, i = 0; i < count; i++, lp++) { | 3239 | for (lp = list, i = 0; i < count; i++, lp++) { |
3006 | tmp = xfs_attr_leaf_freextent(trans, dp, | 3240 | tmp = xfs_attr3_leaf_freextent(trans, dp, |
3007 | lp->valueblk, lp->valuelen); | 3241 | lp->valueblk, lp->valuelen); |
3008 | 3242 | ||
3009 | if (error == 0) | 3243 | if (error == 0) |
3010 | error = tmp; /* save only the 1st errno */ | 3244 | error = tmp; /* save only the 1st errno */ |
3011 | } | 3245 | } |
3012 | 3246 | ||
3013 | kmem_free((xfs_caddr_t)list); | 3247 | kmem_free(list); |
3014 | return(error); | 3248 | return error; |
3015 | } | 3249 | } |
3016 | 3250 | ||
3017 | /* | 3251 | /* |
@@ -3019,14 +3253,20 @@ xfs_attr_leaf_inactive( | |||
3019 | * invalidate any buffers that are incore/in transactions. | 3253 | * invalidate any buffers that are incore/in transactions. |
3020 | */ | 3254 | */ |
3021 | STATIC int | 3255 | STATIC int |
3022 | xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, | 3256 | xfs_attr3_leaf_freextent( |
3023 | xfs_dablk_t blkno, int blkcnt) | 3257 | struct xfs_trans **trans, |
3258 | struct xfs_inode *dp, | ||
3259 | xfs_dablk_t blkno, | ||
3260 | int blkcnt) | ||
3024 | { | 3261 | { |
3025 | xfs_bmbt_irec_t map; | 3262 | struct xfs_bmbt_irec map; |
3026 | xfs_dablk_t tblkno; | 3263 | struct xfs_buf *bp; |
3027 | int tblkcnt, dblkcnt, nmap, error; | 3264 | xfs_dablk_t tblkno; |
3028 | xfs_daddr_t dblkno; | 3265 | xfs_daddr_t dblkno; |
3029 | xfs_buf_t *bp; | 3266 | int tblkcnt; |
3267 | int dblkcnt; | ||
3268 | int nmap; | ||
3269 | int error; | ||
3030 | 3270 | ||
3031 | /* | 3271 | /* |
3032 | * Roll through the "value", invalidating the attribute value's | 3272 | * Roll through the "value", invalidating the attribute value's |