aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/brec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hfsplus/brec.c')
-rw-r--r--fs/hfsplus/brec.c57
1 files changed, 41 insertions, 16 deletions
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index c88e5d72a402..2312de34bd42 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -39,13 +39,17 @@ u16 hfs_brec_keylen(struct hfs_bnode *node, u16 rec)
39 !(node->tree->attributes & HFS_TREE_VARIDXKEYS)) { 39 !(node->tree->attributes & HFS_TREE_VARIDXKEYS)) {
40 retval = node->tree->max_key_len + 2; 40 retval = node->tree->max_key_len + 2;
41 } else { 41 } else {
42 recoff = hfs_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2); 42 recoff = hfs_bnode_read_u16(node,
43 node->tree->node_size - (rec + 1) * 2);
43 if (!recoff) 44 if (!recoff)
44 return 0; 45 return 0;
45 if (node->tree->attributes & HFS_TREE_BIGKEYS) 46
46 retval = hfs_bnode_read_u16(node, recoff) + 2; 47 retval = hfs_bnode_read_u16(node, recoff) + 2;
47 else 48 if (retval > node->tree->max_key_len + 2) {
48 retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1; 49 printk(KERN_ERR "hfs: keylen %d too large\n",
50 retval);
51 retval = 0;
52 }
49 } 53 }
50 return retval; 54 return retval;
51} 55}
@@ -81,7 +85,8 @@ again:
81 end_rec_off = tree->node_size - (node->num_recs + 1) * 2; 85 end_rec_off = tree->node_size - (node->num_recs + 1) * 2;
82 end_off = hfs_bnode_read_u16(node, end_rec_off); 86 end_off = hfs_bnode_read_u16(node, end_rec_off);
83 end_rec_off -= 2; 87 end_rec_off -= 2;
84 dprint(DBG_BNODE_MOD, "insert_rec: %d, %d, %d, %d\n", rec, size, end_off, end_rec_off); 88 dprint(DBG_BNODE_MOD, "insert_rec: %d, %d, %d, %d\n",
89 rec, size, end_off, end_rec_off);
85 if (size > end_rec_off - end_off) { 90 if (size > end_rec_off - end_off) {
86 if (new_node) 91 if (new_node)
87 panic("not enough room!\n"); 92 panic("not enough room!\n");
@@ -96,7 +101,9 @@ again:
96 } 101 }
97 node->num_recs++; 102 node->num_recs++;
98 /* write new last offset */ 103 /* write new last offset */
99 hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs); 104 hfs_bnode_write_u16(node,
105 offsetof(struct hfs_bnode_desc, num_recs),
106 node->num_recs);
100 hfs_bnode_write_u16(node, end_rec_off, end_off + size); 107 hfs_bnode_write_u16(node, end_rec_off, end_off + size);
101 data_off = end_off; 108 data_off = end_off;
102 data_rec_off = end_rec_off + 2; 109 data_rec_off = end_rec_off + 2;
@@ -148,7 +155,8 @@ skip:
148 if (tree->attributes & HFS_TREE_VARIDXKEYS) 155 if (tree->attributes & HFS_TREE_VARIDXKEYS)
149 key_len = be16_to_cpu(fd->search_key->key_len) + 2; 156 key_len = be16_to_cpu(fd->search_key->key_len) + 2;
150 else { 157 else {
151 fd->search_key->key_len = cpu_to_be16(tree->max_key_len); 158 fd->search_key->key_len =
159 cpu_to_be16(tree->max_key_len);
152 key_len = tree->max_key_len + 2; 160 key_len = tree->max_key_len + 2;
153 } 161 }
154 goto again; 162 goto again;
@@ -177,7 +185,8 @@ again:
177 mark_inode_dirty(tree->inode); 185 mark_inode_dirty(tree->inode);
178 } 186 }
179 hfs_bnode_dump(node); 187 hfs_bnode_dump(node);
180 dprint(DBG_BNODE_MOD, "remove_rec: %d, %d\n", fd->record, fd->keylength + fd->entrylength); 188 dprint(DBG_BNODE_MOD, "remove_rec: %d, %d\n",
189 fd->record, fd->keylength + fd->entrylength);
181 if (!--node->num_recs) { 190 if (!--node->num_recs) {
182 hfs_bnode_unlink(node); 191 hfs_bnode_unlink(node);
183 if (!node->parent) 192 if (!node->parent)
@@ -191,7 +200,9 @@ again:
191 __hfs_brec_find(node, fd); 200 __hfs_brec_find(node, fd);
192 goto again; 201 goto again;
193 } 202 }
194 hfs_bnode_write_u16(node, offsetof(struct hfs_bnode_desc, num_recs), node->num_recs); 203 hfs_bnode_write_u16(node,
204 offsetof(struct hfs_bnode_desc, num_recs),
205 node->num_recs);
195 206
196 if (rec_off == end_off) 207 if (rec_off == end_off)
197 goto skip; 208 goto skip;
@@ -216,7 +227,7 @@ skip:
216static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) 227static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
217{ 228{
218 struct hfs_btree *tree; 229 struct hfs_btree *tree;
219 struct hfs_bnode *node, *new_node; 230 struct hfs_bnode *node, *new_node, *next_node;
220 struct hfs_bnode_desc node_desc; 231 struct hfs_bnode_desc node_desc;
221 int num_recs, new_rec_off, new_off, old_rec_off; 232 int num_recs, new_rec_off, new_off, old_rec_off;
222 int data_start, data_end, size; 233 int data_start, data_end, size;
@@ -235,6 +246,17 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
235 new_node->type = node->type; 246 new_node->type = node->type;
236 new_node->height = node->height; 247 new_node->height = node->height;
237 248
249 if (node->next)
250 next_node = hfs_bnode_find(tree, node->next);
251 else
252 next_node = NULL;
253
254 if (IS_ERR(next_node)) {
255 hfs_bnode_put(node);
256 hfs_bnode_put(new_node);
257 return next_node;
258 }
259
238 size = tree->node_size / 2 - node->num_recs * 2 - 14; 260 size = tree->node_size / 2 - node->num_recs * 2 - 14;
239 old_rec_off = tree->node_size - 4; 261 old_rec_off = tree->node_size - 4;
240 num_recs = 1; 262 num_recs = 1;
@@ -248,6 +270,8 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
248 /* panic? */ 270 /* panic? */
249 hfs_bnode_put(node); 271 hfs_bnode_put(node);
250 hfs_bnode_put(new_node); 272 hfs_bnode_put(new_node);
273 if (next_node)
274 hfs_bnode_put(next_node);
251 return ERR_PTR(-ENOSPC); 275 return ERR_PTR(-ENOSPC);
252 } 276 }
253 277
@@ -302,8 +326,7 @@ static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd)
302 hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc)); 326 hfs_bnode_write(node, &node_desc, 0, sizeof(node_desc));
303 327
304 /* update next bnode header */ 328 /* update next bnode header */
305 if (new_node->next) { 329 if (next_node) {
306 struct hfs_bnode *next_node = hfs_bnode_find(tree, new_node->next);
307 next_node->prev = new_node->this; 330 next_node->prev = new_node->this;
308 hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc)); 331 hfs_bnode_read(next_node, &node_desc, 0, sizeof(node_desc));
309 node_desc.prev = cpu_to_be32(next_node->prev); 332 node_desc.prev = cpu_to_be32(next_node->prev);
@@ -349,7 +372,8 @@ again:
349 newkeylen = hfs_bnode_read_u16(node, 14) + 2; 372 newkeylen = hfs_bnode_read_u16(node, 14) + 2;
350 else 373 else
351 fd->keylength = newkeylen = tree->max_key_len + 2; 374 fd->keylength = newkeylen = tree->max_key_len + 2;
352 dprint(DBG_BNODE_MOD, "update_rec: %d, %d, %d\n", rec, fd->keylength, newkeylen); 375 dprint(DBG_BNODE_MOD, "update_rec: %d, %d, %d\n",
376 rec, fd->keylength, newkeylen);
353 377
354 rec_off = tree->node_size - (rec + 2) * 2; 378 rec_off = tree->node_size - (rec + 2) * 2;
355 end_rec_off = tree->node_size - (parent->num_recs + 1) * 2; 379 end_rec_off = tree->node_size - (parent->num_recs + 1) * 2;
@@ -360,7 +384,7 @@ again:
360 end_off = hfs_bnode_read_u16(parent, end_rec_off); 384 end_off = hfs_bnode_read_u16(parent, end_rec_off);
361 if (end_rec_off - end_off < diff) { 385 if (end_rec_off - end_off < diff) {
362 386
363 printk(KERN_DEBUG "hfs: splitting index node...\n"); 387 dprint(DBG_BNODE_MOD, "hfs: splitting index node.\n");
364 fd->bnode = parent; 388 fd->bnode = parent;
365 new_node = hfs_bnode_split(fd); 389 new_node = hfs_bnode_split(fd);
366 if (IS_ERR(new_node)) 390 if (IS_ERR(new_node))
@@ -368,7 +392,8 @@ again:
368 parent = fd->bnode; 392 parent = fd->bnode;
369 rec = fd->record; 393 rec = fd->record;
370 rec_off = tree->node_size - (rec + 2) * 2; 394 rec_off = tree->node_size - (rec + 2) * 2;
371 end_rec_off = tree->node_size - (parent->num_recs + 1) * 2; 395 end_rec_off = tree->node_size -
396 (parent->num_recs + 1) * 2;
372 } 397 }
373 } 398 }
374 399