Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
bnode.c
Go to the documentation of this file.
1 /*
2  * linux/fs/hfs/bnode.c
3  *
4  * Copyright (C) 2001
5  * Brad Boyer ([email protected])
6  * (C) 2003 Ardis Technologies <[email protected]>
7  *
8  * Handle basic btree node operations
9  */
10 
11 #include <linux/pagemap.h>
12 #include <linux/slab.h>
13 #include <linux/swap.h>
14 
15 #include "btree.h"
16 
17 void hfs_bnode_read(struct hfs_bnode *node, void *buf,
18  int off, int len)
19 {
20  struct page *page;
21 
22  off += node->page_offset;
23  page = node->page[0];
24 
25  memcpy(buf, kmap(page) + off, len);
26  kunmap(page);
27 }
28 
30 {
31  __be16 data;
32  // optimize later...
33  hfs_bnode_read(node, &data, off, 2);
34  return be16_to_cpu(data);
35 }
36 
38 {
39  u8 data;
40  // optimize later...
41  hfs_bnode_read(node, &data, off, 1);
42  return data;
43 }
44 
45 void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off)
46 {
47  struct hfs_btree *tree;
48  int key_len;
49 
50  tree = node->tree;
51  if (node->type == HFS_NODE_LEAF ||
53  key_len = hfs_bnode_read_u8(node, off) + 1;
54  else
55  key_len = tree->max_key_len + 1;
56 
57  hfs_bnode_read(node, key, off, key_len);
58 }
59 
60 void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
61 {
62  struct page *page;
63 
64  off += node->page_offset;
65  page = node->page[0];
66 
67  memcpy(kmap(page) + off, buf, len);
68  kunmap(page);
69  set_page_dirty(page);
70 }
71 
72 void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
73 {
74  __be16 v = cpu_to_be16(data);
75  // optimize later...
76  hfs_bnode_write(node, &v, off, 2);
77 }
78 
79 void hfs_bnode_write_u8(struct hfs_bnode *node, int off, u8 data)
80 {
81  // optimize later...
82  hfs_bnode_write(node, &data, off, 1);
83 }
84 
85 void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
86 {
87  struct page *page;
88 
89  off += node->page_offset;
90  page = node->page[0];
91 
92  memset(kmap(page) + off, 0, len);
93  kunmap(page);
94  set_page_dirty(page);
95 }
96 
97 void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
98  struct hfs_bnode *src_node, int src, int len)
99 {
100  struct hfs_btree *tree;
101  struct page *src_page, *dst_page;
102 
103  dprint(DBG_BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len);
104  if (!len)
105  return;
106  tree = src_node->tree;
107  src += src_node->page_offset;
108  dst += dst_node->page_offset;
109  src_page = src_node->page[0];
110  dst_page = dst_node->page[0];
111 
112  memcpy(kmap(dst_page) + dst, kmap(src_page) + src, len);
113  kunmap(src_page);
114  kunmap(dst_page);
115  set_page_dirty(dst_page);
116 }
117 
118 void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
119 {
120  struct page *page;
121  void *ptr;
122 
123  dprint(DBG_BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len);
124  if (!len)
125  return;
126  src += node->page_offset;
127  dst += node->page_offset;
128  page = node->page[0];
129  ptr = kmap(page);
130  memmove(ptr + dst, ptr + src, len);
131  kunmap(page);
132  set_page_dirty(page);
133 }
134 
136 {
137  struct hfs_bnode_desc desc;
138  __be32 cnid;
139  int i, off, key_off;
140 
141  dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
142  hfs_bnode_read(node, &desc, 0, sizeof(desc));
143  dprint(DBG_BNODE_MOD, "%d, %d, %d, %d, %d\n",
144  be32_to_cpu(desc.next), be32_to_cpu(desc.prev),
145  desc.type, desc.height, be16_to_cpu(desc.num_recs));
146 
147  off = node->tree->node_size - 2;
148  for (i = be16_to_cpu(desc.num_recs); i >= 0; off -= 2, i--) {
149  key_off = hfs_bnode_read_u16(node, off);
150  dprint(DBG_BNODE_MOD, " %d", key_off);
151  if (i && node->type == HFS_NODE_INDEX) {
152  int tmp;
153 
154  if (node->tree->attributes & HFS_TREE_VARIDXKEYS)
155  tmp = (hfs_bnode_read_u8(node, key_off) | 1) + 1;
156  else
157  tmp = node->tree->max_key_len + 1;
158  dprint(DBG_BNODE_MOD, " (%d,%d", tmp, hfs_bnode_read_u8(node, key_off));
159  hfs_bnode_read(node, &cnid, key_off + tmp, 4);
160  dprint(DBG_BNODE_MOD, ",%d)", be32_to_cpu(cnid));
161  } else if (i && node->type == HFS_NODE_LEAF) {
162  int tmp;
163 
164  tmp = hfs_bnode_read_u8(node, key_off);
165  dprint(DBG_BNODE_MOD, " (%d)", tmp);
166  }
167  }
168  dprint(DBG_BNODE_MOD, "\n");
169 }
170 
172 {
173  struct hfs_btree *tree;
174  struct hfs_bnode *tmp;
175  __be32 cnid;
176 
177  tree = node->tree;
178  if (node->prev) {
179  tmp = hfs_bnode_find(tree, node->prev);
180  if (IS_ERR(tmp))
181  return;
182  tmp->next = node->next;
183  cnid = cpu_to_be32(tmp->next);
184  hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, next), 4);
185  hfs_bnode_put(tmp);
186  } else if (node->type == HFS_NODE_LEAF)
187  tree->leaf_head = node->next;
188 
189  if (node->next) {
190  tmp = hfs_bnode_find(tree, node->next);
191  if (IS_ERR(tmp))
192  return;
193  tmp->prev = node->prev;
194  cnid = cpu_to_be32(tmp->prev);
195  hfs_bnode_write(tmp, &cnid, offsetof(struct hfs_bnode_desc, prev), 4);
196  hfs_bnode_put(tmp);
197  } else if (node->type == HFS_NODE_LEAF)
198  tree->leaf_tail = node->prev;
199 
200  // move down?
201  if (!node->prev && !node->next) {
202  printk(KERN_DEBUG "hfs_btree_del_level\n");
203  }
204  if (!node->parent) {
205  tree->root = 0;
206  tree->depth = 0;
207  }
209 }
210 
211 static inline int hfs_bnode_hash(u32 num)
212 {
213  num = (num >> 16) + num;
214  num += num >> 8;
215  return num & (NODE_HASH_SIZE - 1);
216 }
217 
219 {
220  struct hfs_bnode *node;
221 
222  if (cnid >= tree->node_count) {
223  printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
224  return NULL;
225  }
226 
227  for (node = tree->node_hash[hfs_bnode_hash(cnid)];
228  node; node = node->next_hash) {
229  if (node->this == cnid) {
230  return node;
231  }
232  }
233  return NULL;
234 }
235 
236 static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
237 {
238  struct super_block *sb;
239  struct hfs_bnode *node, *node2;
240  struct address_space *mapping;
241  struct page *page;
242  int size, block, i, hash;
243  loff_t off;
244 
245  if (cnid >= tree->node_count) {
246  printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
247  return NULL;
248  }
249 
250  sb = tree->inode->i_sb;
251  size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
252  sizeof(struct page *);
253  node = kzalloc(size, GFP_KERNEL);
254  if (!node)
255  return NULL;
256  node->tree = tree;
257  node->this = cnid;
258  set_bit(HFS_BNODE_NEW, &node->flags);
259  atomic_set(&node->refcnt, 1);
260  dprint(DBG_BNODE_REFS, "new_node(%d:%d): 1\n",
261  node->tree->cnid, node->this);
263  spin_lock(&tree->hash_lock);
264  node2 = hfs_bnode_findhash(tree, cnid);
265  if (!node2) {
266  hash = hfs_bnode_hash(cnid);
267  node->next_hash = tree->node_hash[hash];
268  tree->node_hash[hash] = node;
269  tree->node_hash_cnt++;
270  } else {
271  spin_unlock(&tree->hash_lock);
272  kfree(node);
273  wait_event(node2->lock_wq, !test_bit(HFS_BNODE_NEW, &node2->flags));
274  return node2;
275  }
276  spin_unlock(&tree->hash_lock);
277 
278  mapping = tree->inode->i_mapping;
279  off = (loff_t)cnid * tree->node_size;
280  block = off >> PAGE_CACHE_SHIFT;
281  node->page_offset = off & ~PAGE_CACHE_MASK;
282  for (i = 0; i < tree->pages_per_bnode; i++) {
283  page = read_mapping_page(mapping, block++, NULL);
284  if (IS_ERR(page))
285  goto fail;
286  if (PageError(page)) {
287  page_cache_release(page);
288  goto fail;
289  }
290  page_cache_release(page);
291  node->page[i] = page;
292  }
293 
294  return node;
295 fail:
296  set_bit(HFS_BNODE_ERROR, &node->flags);
297  return node;
298 }
299 
300 void hfs_bnode_unhash(struct hfs_bnode *node)
301 {
302  struct hfs_bnode **p;
303 
304  dprint(DBG_BNODE_REFS, "remove_node(%d:%d): %d\n",
305  node->tree->cnid, node->this, atomic_read(&node->refcnt));
306  for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
307  *p && *p != node; p = &(*p)->next_hash)
308  ;
309  BUG_ON(!*p);
310  *p = node->next_hash;
311  node->tree->node_hash_cnt--;
312 }
313 
314 /* Load a particular node out of a tree */
315 struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
316 {
317  struct hfs_bnode *node;
318  struct hfs_bnode_desc *desc;
319  int i, rec_off, off, next_off;
320  int entry_size, key_size;
321 
322  spin_lock(&tree->hash_lock);
323  node = hfs_bnode_findhash(tree, num);
324  if (node) {
325  hfs_bnode_get(node);
326  spin_unlock(&tree->hash_lock);
327  wait_event(node->lock_wq, !test_bit(HFS_BNODE_NEW, &node->flags));
328  if (test_bit(HFS_BNODE_ERROR, &node->flags))
329  goto node_error;
330  return node;
331  }
332  spin_unlock(&tree->hash_lock);
333  node = __hfs_bnode_create(tree, num);
334  if (!node)
335  return ERR_PTR(-ENOMEM);
336  if (test_bit(HFS_BNODE_ERROR, &node->flags))
337  goto node_error;
338  if (!test_bit(HFS_BNODE_NEW, &node->flags))
339  return node;
340 
341  desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) + node->page_offset);
342  node->prev = be32_to_cpu(desc->prev);
343  node->next = be32_to_cpu(desc->next);
344  node->num_recs = be16_to_cpu(desc->num_recs);
345  node->type = desc->type;
346  node->height = desc->height;
347  kunmap(node->page[0]);
348 
349  switch (node->type) {
350  case HFS_NODE_HEADER:
351  case HFS_NODE_MAP:
352  if (node->height != 0)
353  goto node_error;
354  break;
355  case HFS_NODE_LEAF:
356  if (node->height != 1)
357  goto node_error;
358  break;
359  case HFS_NODE_INDEX:
360  if (node->height <= 1 || node->height > tree->depth)
361  goto node_error;
362  break;
363  default:
364  goto node_error;
365  }
366 
367  rec_off = tree->node_size - 2;
368  off = hfs_bnode_read_u16(node, rec_off);
369  if (off != sizeof(struct hfs_bnode_desc))
370  goto node_error;
371  for (i = 1; i <= node->num_recs; off = next_off, i++) {
372  rec_off -= 2;
373  next_off = hfs_bnode_read_u16(node, rec_off);
374  if (next_off <= off ||
375  next_off > tree->node_size ||
376  next_off & 1)
377  goto node_error;
378  entry_size = next_off - off;
379  if (node->type != HFS_NODE_INDEX &&
380  node->type != HFS_NODE_LEAF)
381  continue;
382  key_size = hfs_bnode_read_u8(node, off) + 1;
383  if (key_size >= entry_size /*|| key_size & 1*/)
384  goto node_error;
385  }
386  clear_bit(HFS_BNODE_NEW, &node->flags);
387  wake_up(&node->lock_wq);
388  return node;
389 
390 node_error:
391  set_bit(HFS_BNODE_ERROR, &node->flags);
392  clear_bit(HFS_BNODE_NEW, &node->flags);
393  wake_up(&node->lock_wq);
394  hfs_bnode_put(node);
395  return ERR_PTR(-EIO);
396 }
397 
398 void hfs_bnode_free(struct hfs_bnode *node)
399 {
400  //int i;
401 
402  //for (i = 0; i < node->tree->pages_per_bnode; i++)
403  // if (node->page[i])
404  // page_cache_release(node->page[i]);
405  kfree(node);
406 }
407 
408 struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
409 {
410  struct hfs_bnode *node;
411  struct page **pagep;
412  int i;
413 
414  spin_lock(&tree->hash_lock);
415  node = hfs_bnode_findhash(tree, num);
416  spin_unlock(&tree->hash_lock);
417  BUG_ON(node);
418  node = __hfs_bnode_create(tree, num);
419  if (!node)
420  return ERR_PTR(-ENOMEM);
421  if (test_bit(HFS_BNODE_ERROR, &node->flags)) {
422  hfs_bnode_put(node);
423  return ERR_PTR(-EIO);
424  }
425 
426  pagep = node->page;
427  memset(kmap(*pagep) + node->page_offset, 0,
428  min((int)PAGE_CACHE_SIZE, (int)tree->node_size));
429  set_page_dirty(*pagep);
430  kunmap(*pagep);
431  for (i = 1; i < tree->pages_per_bnode; i++) {
432  memset(kmap(*++pagep), 0, PAGE_CACHE_SIZE);
433  set_page_dirty(*pagep);
434  kunmap(*pagep);
435  }
436  clear_bit(HFS_BNODE_NEW, &node->flags);
437  wake_up(&node->lock_wq);
438 
439  return node;
440 }
441 
442 void hfs_bnode_get(struct hfs_bnode *node)
443 {
444  if (node) {
445  atomic_inc(&node->refcnt);
446  dprint(DBG_BNODE_REFS, "get_node(%d:%d): %d\n",
447  node->tree->cnid, node->this, atomic_read(&node->refcnt));
448  }
449 }
450 
451 /* Dispose of resources used by a node */
452 void hfs_bnode_put(struct hfs_bnode *node)
453 {
454  if (node) {
455  struct hfs_btree *tree = node->tree;
456  int i;
457 
458  dprint(DBG_BNODE_REFS, "put_node(%d:%d): %d\n",
459  node->tree->cnid, node->this, atomic_read(&node->refcnt));
460  BUG_ON(!atomic_read(&node->refcnt));
461  if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
462  return;
463  for (i = 0; i < tree->pages_per_bnode; i++) {
464  if (!node->page[i])
465  continue;
466  mark_page_accessed(node->page[i]);
467  }
468 
469  if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
470  hfs_bnode_unhash(node);
471  spin_unlock(&tree->hash_lock);
472  hfs_bmap_free(node);
473  hfs_bnode_free(node);
474  return;
475  }
476  spin_unlock(&tree->hash_lock);
477  }
478 }