diff options
Diffstat (limited to 'fs/hfsplus/brec.c')
-rw-r--r-- | fs/hfsplus/brec.c | 57 |
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: | |||
216 | static struct hfs_bnode *hfs_bnode_split(struct hfs_find_data *fd) | 227 | static 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 | ||