1 // SPDX-License-Identifier: GPL-2.0
6 * Brad Boyer (flar@allandria.com)
7 * (C) 2003 Ardis Technologies <roman@ardistech.com>
9 * Handle basic btree node operations
12 #include <linux/pagemap.h>
13 #include <linux/slab.h>
14 #include <linux/swap.h>
18 void hfs_bnode_read(struct hfs_bnode
*node
, void *buf
, int off
, int len
)
25 off
+= node
->page_offset
;
26 pagenum
= off
>> PAGE_SHIFT
;
27 off
&= ~PAGE_MASK
; /* compute page offset for the first page */
29 for (bytes_read
= 0; bytes_read
< len
; bytes_read
+= bytes_to_read
) {
30 if (pagenum
>= node
->tree
->pages_per_bnode
)
32 page
= node
->page
[pagenum
];
33 bytes_to_read
= min_t(int, len
- bytes_read
, PAGE_SIZE
- off
);
35 memcpy_from_page(buf
+ bytes_read
, page
, off
, bytes_to_read
);
38 off
= 0; /* page offset only applies to the first page */
42 u16
hfs_bnode_read_u16(struct hfs_bnode
*node
, int off
)
46 hfs_bnode_read(node
, &data
, off
, 2);
47 return be16_to_cpu(data
);
50 u8
hfs_bnode_read_u8(struct hfs_bnode
*node
, int off
)
54 hfs_bnode_read(node
, &data
, off
, 1);
58 void hfs_bnode_read_key(struct hfs_bnode
*node
, void *key
, int off
)
60 struct hfs_btree
*tree
;
64 if (node
->type
== HFS_NODE_LEAF
||
65 tree
->attributes
& HFS_TREE_VARIDXKEYS
)
66 key_len
= hfs_bnode_read_u8(node
, off
) + 1;
68 key_len
= tree
->max_key_len
+ 1;
70 hfs_bnode_read(node
, key
, off
, key_len
);
73 void hfs_bnode_write(struct hfs_bnode
*node
, void *buf
, int off
, int len
)
77 off
+= node
->page_offset
;
80 memcpy_to_page(page
, off
, buf
, len
);
84 void hfs_bnode_write_u16(struct hfs_bnode
*node
, int off
, u16 data
)
86 __be16 v
= cpu_to_be16(data
);
88 hfs_bnode_write(node
, &v
, off
, 2);
91 void hfs_bnode_write_u8(struct hfs_bnode
*node
, int off
, u8 data
)
94 hfs_bnode_write(node
, &data
, off
, 1);
97 void hfs_bnode_clear(struct hfs_bnode
*node
, int off
, int len
)
101 off
+= node
->page_offset
;
102 page
= node
->page
[0];
104 memzero_page(page
, off
, len
);
105 set_page_dirty(page
);
108 void hfs_bnode_copy(struct hfs_bnode
*dst_node
, int dst
,
109 struct hfs_bnode
*src_node
, int src
, int len
)
111 struct page
*src_page
, *dst_page
;
113 hfs_dbg(BNODE_MOD
, "copybytes: %u,%u,%u\n", dst
, src
, len
);
116 src
+= src_node
->page_offset
;
117 dst
+= dst_node
->page_offset
;
118 src_page
= src_node
->page
[0];
119 dst_page
= dst_node
->page
[0];
121 memcpy_page(dst_page
, dst
, src_page
, src
, len
);
122 set_page_dirty(dst_page
);
125 void hfs_bnode_move(struct hfs_bnode
*node
, int dst
, int src
, int len
)
130 hfs_dbg(BNODE_MOD
, "movebytes: %u,%u,%u\n", dst
, src
, len
);
133 src
+= node
->page_offset
;
134 dst
+= node
->page_offset
;
135 page
= node
->page
[0];
136 ptr
= kmap_local_page(page
);
137 memmove(ptr
+ dst
, ptr
+ src
, len
);
139 set_page_dirty(page
);
142 void hfs_bnode_dump(struct hfs_bnode
*node
)
144 struct hfs_bnode_desc desc
;
148 hfs_dbg(BNODE_MOD
, "bnode: %d\n", node
->this);
149 hfs_bnode_read(node
, &desc
, 0, sizeof(desc
));
150 hfs_dbg(BNODE_MOD
, "%d, %d, %d, %d, %d\n",
151 be32_to_cpu(desc
.next
), be32_to_cpu(desc
.prev
),
152 desc
.type
, desc
.height
, be16_to_cpu(desc
.num_recs
));
154 off
= node
->tree
->node_size
- 2;
155 for (i
= be16_to_cpu(desc
.num_recs
); i
>= 0; off
-= 2, i
--) {
156 key_off
= hfs_bnode_read_u16(node
, off
);
157 hfs_dbg_cont(BNODE_MOD
, " %d", key_off
);
158 if (i
&& node
->type
== HFS_NODE_INDEX
) {
161 if (node
->tree
->attributes
& HFS_TREE_VARIDXKEYS
)
162 tmp
= (hfs_bnode_read_u8(node
, key_off
) | 1) + 1;
164 tmp
= node
->tree
->max_key_len
+ 1;
165 hfs_dbg_cont(BNODE_MOD
, " (%d,%d",
166 tmp
, hfs_bnode_read_u8(node
, key_off
));
167 hfs_bnode_read(node
, &cnid
, key_off
+ tmp
, 4);
168 hfs_dbg_cont(BNODE_MOD
, ",%d)", be32_to_cpu(cnid
));
169 } else if (i
&& node
->type
== HFS_NODE_LEAF
) {
172 tmp
= hfs_bnode_read_u8(node
, key_off
);
173 hfs_dbg_cont(BNODE_MOD
, " (%d)", tmp
);
176 hfs_dbg_cont(BNODE_MOD
, "\n");
179 void hfs_bnode_unlink(struct hfs_bnode
*node
)
181 struct hfs_btree
*tree
;
182 struct hfs_bnode
*tmp
;
187 tmp
= hfs_bnode_find(tree
, node
->prev
);
190 tmp
->next
= node
->next
;
191 cnid
= cpu_to_be32(tmp
->next
);
192 hfs_bnode_write(tmp
, &cnid
, offsetof(struct hfs_bnode_desc
, next
), 4);
194 } else if (node
->type
== HFS_NODE_LEAF
)
195 tree
->leaf_head
= node
->next
;
198 tmp
= hfs_bnode_find(tree
, node
->next
);
201 tmp
->prev
= node
->prev
;
202 cnid
= cpu_to_be32(tmp
->prev
);
203 hfs_bnode_write(tmp
, &cnid
, offsetof(struct hfs_bnode_desc
, prev
), 4);
205 } else if (node
->type
== HFS_NODE_LEAF
)
206 tree
->leaf_tail
= node
->prev
;
209 if (!node
->prev
&& !node
->next
) {
210 printk(KERN_DEBUG
"hfs_btree_del_level\n");
216 set_bit(HFS_BNODE_DELETED
, &node
->flags
);
219 static inline int hfs_bnode_hash(u32 num
)
221 num
= (num
>> 16) + num
;
223 return num
& (NODE_HASH_SIZE
- 1);
226 struct hfs_bnode
*hfs_bnode_findhash(struct hfs_btree
*tree
, u32 cnid
)
228 struct hfs_bnode
*node
;
230 if (cnid
>= tree
->node_count
) {
231 pr_err("request for non-existent node %d in B*Tree\n", cnid
);
235 for (node
= tree
->node_hash
[hfs_bnode_hash(cnid
)];
236 node
; node
= node
->next_hash
) {
237 if (node
->this == cnid
) {
244 static struct hfs_bnode
*__hfs_bnode_create(struct hfs_btree
*tree
, u32 cnid
)
246 struct hfs_bnode
*node
, *node2
;
247 struct address_space
*mapping
;
249 int size
, block
, i
, hash
;
252 if (cnid
>= tree
->node_count
) {
253 pr_err("request for non-existent node %d in B*Tree\n", cnid
);
257 size
= sizeof(struct hfs_bnode
) + tree
->pages_per_bnode
*
258 sizeof(struct page
*);
259 node
= kzalloc(size
, GFP_KERNEL
);
264 set_bit(HFS_BNODE_NEW
, &node
->flags
);
265 atomic_set(&node
->refcnt
, 1);
266 hfs_dbg(BNODE_REFS
, "new_node(%d:%d): 1\n",
267 node
->tree
->cnid
, node
->this);
268 init_waitqueue_head(&node
->lock_wq
);
269 spin_lock(&tree
->hash_lock
);
270 node2
= hfs_bnode_findhash(tree
, cnid
);
272 hash
= hfs_bnode_hash(cnid
);
273 node
->next_hash
= tree
->node_hash
[hash
];
274 tree
->node_hash
[hash
] = node
;
275 tree
->node_hash_cnt
++;
277 hfs_bnode_get(node2
);
278 spin_unlock(&tree
->hash_lock
);
280 wait_event(node2
->lock_wq
, !test_bit(HFS_BNODE_NEW
, &node2
->flags
));
283 spin_unlock(&tree
->hash_lock
);
285 mapping
= tree
->inode
->i_mapping
;
286 off
= (loff_t
)cnid
* tree
->node_size
;
287 block
= off
>> PAGE_SHIFT
;
288 node
->page_offset
= off
& ~PAGE_MASK
;
289 for (i
= 0; i
< tree
->pages_per_bnode
; i
++) {
290 page
= read_mapping_page(mapping
, block
++, NULL
);
293 node
->page
[i
] = page
;
298 set_bit(HFS_BNODE_ERROR
, &node
->flags
);
302 void hfs_bnode_unhash(struct hfs_bnode
*node
)
304 struct hfs_bnode
**p
;
306 hfs_dbg(BNODE_REFS
, "remove_node(%d:%d): %d\n",
307 node
->tree
->cnid
, node
->this, atomic_read(&node
->refcnt
));
308 for (p
= &node
->tree
->node_hash
[hfs_bnode_hash(node
->this)];
309 *p
&& *p
!= node
; p
= &(*p
)->next_hash
)
312 *p
= node
->next_hash
;
313 node
->tree
->node_hash_cnt
--;
316 /* Load a particular node out of a tree */
317 struct hfs_bnode
*hfs_bnode_find(struct hfs_btree
*tree
, u32 num
)
319 struct hfs_bnode
*node
;
320 struct hfs_bnode_desc
*desc
;
321 int i
, rec_off
, off
, next_off
;
322 int entry_size
, key_size
;
324 spin_lock(&tree
->hash_lock
);
325 node
= hfs_bnode_findhash(tree
, num
);
328 spin_unlock(&tree
->hash_lock
);
329 wait_event(node
->lock_wq
, !test_bit(HFS_BNODE_NEW
, &node
->flags
));
330 if (test_bit(HFS_BNODE_ERROR
, &node
->flags
))
334 spin_unlock(&tree
->hash_lock
);
335 node
= __hfs_bnode_create(tree
, num
);
337 return ERR_PTR(-ENOMEM
);
338 if (test_bit(HFS_BNODE_ERROR
, &node
->flags
))
340 if (!test_bit(HFS_BNODE_NEW
, &node
->flags
))
343 desc
= (struct hfs_bnode_desc
*)(kmap_local_page(node
->page
[0]) +
345 node
->prev
= be32_to_cpu(desc
->prev
);
346 node
->next
= be32_to_cpu(desc
->next
);
347 node
->num_recs
= be16_to_cpu(desc
->num_recs
);
348 node
->type
= desc
->type
;
349 node
->height
= desc
->height
;
352 switch (node
->type
) {
353 case HFS_NODE_HEADER
:
355 if (node
->height
!= 0)
359 if (node
->height
!= 1)
363 if (node
->height
<= 1 || node
->height
> tree
->depth
)
370 rec_off
= tree
->node_size
- 2;
371 off
= hfs_bnode_read_u16(node
, rec_off
);
372 if (off
!= sizeof(struct hfs_bnode_desc
))
374 for (i
= 1; i
<= node
->num_recs
; off
= next_off
, i
++) {
376 next_off
= hfs_bnode_read_u16(node
, rec_off
);
377 if (next_off
<= off
||
378 next_off
> tree
->node_size
||
381 entry_size
= next_off
- off
;
382 if (node
->type
!= HFS_NODE_INDEX
&&
383 node
->type
!= HFS_NODE_LEAF
)
385 key_size
= hfs_bnode_read_u8(node
, off
) + 1;
386 if (key_size
>= entry_size
/*|| key_size & 1*/)
389 clear_bit(HFS_BNODE_NEW
, &node
->flags
);
390 wake_up(&node
->lock_wq
);
394 set_bit(HFS_BNODE_ERROR
, &node
->flags
);
395 clear_bit(HFS_BNODE_NEW
, &node
->flags
);
396 wake_up(&node
->lock_wq
);
398 return ERR_PTR(-EIO
);
401 void hfs_bnode_free(struct hfs_bnode
*node
)
405 for (i
= 0; i
< node
->tree
->pages_per_bnode
; i
++)
407 put_page(node
->page
[i
]);
411 struct hfs_bnode
*hfs_bnode_create(struct hfs_btree
*tree
, u32 num
)
413 struct hfs_bnode
*node
;
417 spin_lock(&tree
->hash_lock
);
418 node
= hfs_bnode_findhash(tree
, num
);
419 spin_unlock(&tree
->hash_lock
);
421 pr_crit("new node %u already hashed?\n", num
);
425 node
= __hfs_bnode_create(tree
, num
);
427 return ERR_PTR(-ENOMEM
);
428 if (test_bit(HFS_BNODE_ERROR
, &node
->flags
)) {
430 return ERR_PTR(-EIO
);
434 memzero_page(*pagep
, node
->page_offset
,
435 min((int)PAGE_SIZE
, (int)tree
->node_size
));
436 set_page_dirty(*pagep
);
437 for (i
= 1; i
< tree
->pages_per_bnode
; i
++) {
438 memzero_page(*++pagep
, 0, PAGE_SIZE
);
439 set_page_dirty(*pagep
);
441 clear_bit(HFS_BNODE_NEW
, &node
->flags
);
442 wake_up(&node
->lock_wq
);
447 void hfs_bnode_get(struct hfs_bnode
*node
)
450 atomic_inc(&node
->refcnt
);
451 hfs_dbg(BNODE_REFS
, "get_node(%d:%d): %d\n",
452 node
->tree
->cnid
, node
->this,
453 atomic_read(&node
->refcnt
));
457 /* Dispose of resources used by a node */
458 void hfs_bnode_put(struct hfs_bnode
*node
)
461 struct hfs_btree
*tree
= node
->tree
;
464 hfs_dbg(BNODE_REFS
, "put_node(%d:%d): %d\n",
465 node
->tree
->cnid
, node
->this,
466 atomic_read(&node
->refcnt
));
467 BUG_ON(!atomic_read(&node
->refcnt
));
468 if (!atomic_dec_and_lock(&node
->refcnt
, &tree
->hash_lock
))
470 for (i
= 0; i
< tree
->pages_per_bnode
; i
++) {
473 mark_page_accessed(node
->page
[i
]);
476 if (test_bit(HFS_BNODE_DELETED
, &node
->flags
)) {
477 hfs_bnode_unhash(node
);
478 spin_unlock(&tree
->hash_lock
);
480 hfs_bnode_free(node
);
483 spin_unlock(&tree
->hash_lock
);