blob: 07711c392f8bf1dfa4ea875a188c201ab2b1e4f0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/fs/hpfs/dnode.c
3 *
4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
5 *
6 * handling directory dnode tree - adding, deleteing & searching for dirents
7 */
8
9#include "hpfs_fn.h"
10
11static loff_t get_pos(struct dnode *d, struct hpfs_dirent *fde)
12{
13 struct hpfs_dirent *de;
14 struct hpfs_dirent *de_end = dnode_end_de(d);
15 int i = 1;
16 for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
17 if (de == fde) return ((loff_t) d->self << 4) | (loff_t)i;
18 i++;
19 }
20 printk("HPFS: get_pos: not_found\n");
21 return ((loff_t)d->self << 4) | (loff_t)1;
22}
23
24void hpfs_add_pos(struct inode *inode, loff_t *pos)
25{
26 struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
27 int i = 0;
28 loff_t **ppos;
29
30 if (hpfs_inode->i_rddir_off)
31 for (; hpfs_inode->i_rddir_off[i]; i++)
32 if (hpfs_inode->i_rddir_off[i] == pos) return;
33 if (!(i&0x0f)) {
34 if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) {
35 printk("HPFS: out of memory for position list\n");
36 return;
37 }
38 if (hpfs_inode->i_rddir_off) {
39 memcpy(ppos, hpfs_inode->i_rddir_off, i * sizeof(loff_t));
40 kfree(hpfs_inode->i_rddir_off);
41 }
42 hpfs_inode->i_rddir_off = ppos;
43 }
44 hpfs_inode->i_rddir_off[i] = pos;
45 hpfs_inode->i_rddir_off[i + 1] = NULL;
46}
47
48void hpfs_del_pos(struct inode *inode, loff_t *pos)
49{
50 struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
51 loff_t **i, **j;
52
53 if (!hpfs_inode->i_rddir_off) goto not_f;
54 for (i = hpfs_inode->i_rddir_off; *i; i++) if (*i == pos) goto fnd;
55 goto not_f;
56 fnd:
57 for (j = i + 1; *j; j++) ;
58 *i = *(j - 1);
59 *(j - 1) = NULL;
60 if (j - 1 == hpfs_inode->i_rddir_off) {
61 kfree(hpfs_inode->i_rddir_off);
62 hpfs_inode->i_rddir_off = NULL;
63 }
64 return;
65 not_f:
66 /*printk("HPFS: warning: position pointer %p->%08x not found\n", pos, (int)*pos);*/
67 return;
68}
69
70static void for_all_poss(struct inode *inode, void (*f)(loff_t *, loff_t, loff_t),
71 loff_t p1, loff_t p2)
72{
73 struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
74 loff_t **i;
75
76 if (!hpfs_inode->i_rddir_off) return;
77 for (i = hpfs_inode->i_rddir_off; *i; i++) (*f)(*i, p1, p2);
78 return;
79}
80
81static void hpfs_pos_subst(loff_t *p, loff_t f, loff_t t)
82{
83 if (*p == f) *p = t;
84}
85
86/*void hpfs_hpfs_pos_substd(loff_t *p, loff_t f, loff_t t)
87{
88 if ((*p & ~0x3f) == (f & ~0x3f)) *p = (t & ~0x3f) | (*p & 0x3f);
89}*/
90
91static void hpfs_pos_ins(loff_t *p, loff_t d, loff_t c)
92{
93 if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) {
94 int n = (*p & 0x3f) + c;
95 if (n > 0x3f) printk("HPFS: hpfs_pos_ins: %08x + %d\n", (int)*p, (int)c >> 8);
96 else *p = (*p & ~0x3f) | n;
97 }
98}
99
100static void hpfs_pos_del(loff_t *p, loff_t d, loff_t c)
101{
102 if ((*p & ~0x3f) == (d & ~0x3f) && (*p & 0x3f) >= (d & 0x3f)) {
103 int n = (*p & 0x3f) - c;
104 if (n < 1) printk("HPFS: hpfs_pos_ins: %08x - %d\n", (int)*p, (int)c >> 8);
105 else *p = (*p & ~0x3f) | n;
106 }
107}
108
109static struct hpfs_dirent *dnode_pre_last_de(struct dnode *d)
110{
111 struct hpfs_dirent *de, *de_end, *dee = NULL, *deee = NULL;
112 de_end = dnode_end_de(d);
113 for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
114 deee = dee; dee = de;
115 }
116 return deee;
117}
118
119static struct hpfs_dirent *dnode_last_de(struct dnode *d)
120{
121 struct hpfs_dirent *de, *de_end, *dee = NULL;
122 de_end = dnode_end_de(d);
123 for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
124 dee = de;
125 }
126 return dee;
127}
128
129static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno ptr)
130{
131 struct hpfs_dirent *de;
132 if (!(de = dnode_last_de(d))) {
133 hpfs_error(s, "set_last_pointer: empty dnode %08x", d->self);
134 return;
135 }
136 if (hpfs_sb(s)->sb_chk) {
137 if (de->down) {
138 hpfs_error(s, "set_last_pointer: dnode %08x has already last pointer %08x",
139 d->self, de_down_pointer(de));
140 return;
141 }
142 if (de->length != 32) {
143 hpfs_error(s, "set_last_pointer: bad last dirent in dnode %08x", d->self);
144 return;
145 }
146 }
147 if (ptr) {
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200148 d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + 4);
149 if (le32_to_cpu(d->first_free) > 2048) {
150 hpfs_error(s, "set_last_pointer: too long dnode %08x", d->self);
151 d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 return;
153 }
154 de->length = 36;
155 de->down = 1;
156 *(dnode_secno *)((char *)de + 32) = ptr;
157 }
158}
159
160/* Add an entry to dnode and don't care if it grows over 2048 bytes */
161
Al Viro7e7742e2010-01-31 17:09:29 -0500162struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
163 const unsigned char *name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 unsigned namelen, secno down_ptr)
165{
166 struct hpfs_dirent *de;
167 struct hpfs_dirent *de_end = dnode_end_de(d);
168 unsigned d_size = de_size(namelen, down_ptr);
169 for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
170 int c = hpfs_compare_names(s, name, namelen, de->name, de->namelen, de->last);
171 if (!c) {
172 hpfs_error(s, "name (%c,%d) already exists in dnode %08x", *name, namelen, d->self);
173 return NULL;
174 }
175 if (c < 0) break;
176 }
177 memmove((char *)de + d_size, de, (char *)de_end - (char *)de);
178 memset(de, 0, d_size);
179 if (down_ptr) {
180 *(int *)((char *)de + d_size - 4) = down_ptr;
181 de->down = 1;
182 }
183 de->length = d_size;
184 if (down_ptr) de->down = 1;
185 de->not_8x3 = hpfs_is_name_long(name, namelen);
186 de->namelen = namelen;
187 memcpy(de->name, name, namelen);
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200188 d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) + d_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 return de;
190}
191
192/* Delete dirent and don't care about its subtree */
193
194static void hpfs_delete_de(struct super_block *s, struct dnode *d,
195 struct hpfs_dirent *de)
196{
197 if (de->last) {
198 hpfs_error(s, "attempt to delete last dirent in dnode %08x", d->self);
199 return;
200 }
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200201 d->first_free = cpu_to_le32(le32_to_cpu(d->first_free) - de->length);
202 memmove(de, de_next_de(de), le32_to_cpu(d->first_free) + (char *)d - (char *)de);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203}
204
205static void fix_up_ptrs(struct super_block *s, struct dnode *d)
206{
207 struct hpfs_dirent *de;
208 struct hpfs_dirent *de_end = dnode_end_de(d);
209 dnode_secno dno = d->self;
210 for (de = dnode_first_de(d); de < de_end; de = de_next_de(de))
211 if (de->down) {
212 struct quad_buffer_head qbh;
213 struct dnode *dd;
214 if ((dd = hpfs_map_dnode(s, de_down_pointer(de), &qbh))) {
215 if (dd->up != dno || dd->root_dnode) {
216 dd->up = dno;
217 dd->root_dnode = 0;
218 hpfs_mark_4buffers_dirty(&qbh);
219 }
220 hpfs_brelse4(&qbh);
221 }
222 }
223}
224
225/* Add an entry to dnode and do dnode splitting if required */
226
227static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
Al Viro7e7742e2010-01-31 17:09:29 -0500228 const unsigned char *name, unsigned namelen,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 struct hpfs_dirent *new_de, dnode_secno down_ptr)
230{
231 struct quad_buffer_head qbh, qbh1, qbh2;
232 struct dnode *d, *ad, *rd, *nd = NULL;
233 dnode_secno adno, rdno;
234 struct hpfs_dirent *de;
235 struct hpfs_dirent nde;
Al Viro7e7742e2010-01-31 17:09:29 -0500236 unsigned char *nname;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 int h;
238 int pos;
239 struct buffer_head *bh;
240 struct fnode *fnode;
241 int c1, c2 = 0;
242 if (!(nname = kmalloc(256, GFP_NOFS))) {
243 printk("HPFS: out of memory, can't add to dnode\n");
244 return 1;
245 }
246 go_up:
247 if (namelen >= 256) {
248 hpfs_error(i->i_sb, "hpfs_add_to_dnode: namelen == %d", namelen);
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800249 kfree(nd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 kfree(nname);
251 return 1;
252 }
253 if (!(d = hpfs_map_dnode(i->i_sb, dno, &qbh))) {
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800254 kfree(nd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 kfree(nname);
256 return 1;
257 }
258 go_up_a:
259 if (hpfs_sb(i->i_sb)->sb_chk)
260 if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "hpfs_add_to_dnode")) {
261 hpfs_brelse4(&qbh);
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800262 kfree(nd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 kfree(nname);
264 return 1;
265 }
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200266 if (le32_to_cpu(d->first_free) + de_size(namelen, down_ptr) <= 2048) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 loff_t t;
268 copy_de(de=hpfs_add_de(i->i_sb, d, name, namelen, down_ptr), new_de);
269 t = get_pos(d, de);
270 for_all_poss(i, hpfs_pos_ins, t, 1);
271 for_all_poss(i, hpfs_pos_subst, 4, t);
272 for_all_poss(i, hpfs_pos_subst, 5, t + 1);
273 hpfs_mark_4buffers_dirty(&qbh);
274 hpfs_brelse4(&qbh);
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800275 kfree(nd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 kfree(nname);
277 return 0;
278 }
279 if (!nd) if (!(nd = kmalloc(0x924, GFP_NOFS))) {
280 /* 0x924 is a max size of dnode after adding a dirent with
281 max name length. We alloc this only once. There must
282 not be any error while splitting dnodes, otherwise the
283 whole directory, not only file we're adding, would
284 be lost. */
285 printk("HPFS: out of memory for dnode splitting\n");
286 hpfs_brelse4(&qbh);
287 kfree(nname);
288 return 1;
289 }
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200290 memcpy(nd, d, le32_to_cpu(d->first_free));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 copy_de(de = hpfs_add_de(i->i_sb, nd, name, namelen, down_ptr), new_de);
292 for_all_poss(i, hpfs_pos_ins, get_pos(nd, de), 1);
293 h = ((char *)dnode_last_de(nd) - (char *)nd) / 2 + 10;
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200294 if (!(ad = hpfs_alloc_dnode(i->i_sb, d->up, &adno, &qbh1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");
296 hpfs_brelse4(&qbh);
297 kfree(nd);
298 kfree(nname);
299 return 1;
300 }
301 i->i_size += 2048;
302 i->i_blocks += 4;
303 pos = 1;
304 for (de = dnode_first_de(nd); (char *)de_next_de(de) - (char *)nd < h; de = de_next_de(de)) {
305 copy_de(hpfs_add_de(i->i_sb, ad, de->name, de->namelen, de->down ? de_down_pointer(de) : 0), de);
306 for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | pos, ((loff_t)adno << 4) | pos);
307 pos++;
308 }
309 copy_de(new_de = &nde, de);
Al Viro7e7742e2010-01-31 17:09:29 -0500310 memcpy(nname, de->name, de->namelen);
311 name = nname;
312 namelen = de->namelen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | pos, 4);
314 down_ptr = adno;
315 set_last_pointer(i->i_sb, ad, de->down ? de_down_pointer(de) : 0);
316 de = de_next_de(de);
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200317 memmove((char *)nd + 20, de, le32_to_cpu(nd->first_free) + (char *)nd - (char *)de);
318 nd->first_free = cpu_to_le32(le32_to_cpu(nd->first_free) - (char *)de - (char *)nd - 20);
319 memcpy(d, nd, le32_to_cpu(nd->first_free));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 for_all_poss(i, hpfs_pos_del, (loff_t)dno << 4, pos);
321 fix_up_ptrs(i->i_sb, ad);
322 if (!d->root_dnode) {
323 dno = ad->up = d->up;
324 hpfs_mark_4buffers_dirty(&qbh);
325 hpfs_brelse4(&qbh);
326 hpfs_mark_4buffers_dirty(&qbh1);
327 hpfs_brelse4(&qbh1);
328 goto go_up;
329 }
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200330 if (!(rd = hpfs_alloc_dnode(i->i_sb, d->up, &rdno, &qbh2))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 hpfs_error(i->i_sb, "unable to alloc dnode - dnode tree will be corrupted");
332 hpfs_brelse4(&qbh);
333 hpfs_brelse4(&qbh1);
334 kfree(nd);
335 kfree(nname);
336 return 1;
337 }
338 i->i_size += 2048;
339 i->i_blocks += 4;
340 rd->root_dnode = 1;
341 rd->up = d->up;
342 if (!(fnode = hpfs_map_fnode(i->i_sb, d->up, &bh))) {
343 hpfs_free_dnode(i->i_sb, rdno);
344 hpfs_brelse4(&qbh);
345 hpfs_brelse4(&qbh1);
346 hpfs_brelse4(&qbh2);
347 kfree(nd);
348 kfree(nname);
349 return 1;
350 }
351 fnode->u.external[0].disk_secno = rdno;
352 mark_buffer_dirty(bh);
353 brelse(bh);
354 d->up = ad->up = hpfs_i(i)->i_dno = rdno;
355 d->root_dnode = ad->root_dnode = 0;
356 hpfs_mark_4buffers_dirty(&qbh);
357 hpfs_brelse4(&qbh);
358 hpfs_mark_4buffers_dirty(&qbh1);
359 hpfs_brelse4(&qbh1);
360 qbh = qbh2;
361 set_last_pointer(i->i_sb, rd, dno);
362 dno = rdno;
363 d = rd;
364 goto go_up_a;
365}
366
367/*
368 * Add an entry to directory btree.
369 * I hate such crazy directory structure.
370 * It's easy to read but terrible to write.
371 * I wrote this directory code 4 times.
372 * I hope, now it's finally bug-free.
373 */
374
Al Viro7e7742e2010-01-31 17:09:29 -0500375int hpfs_add_dirent(struct inode *i,
376 const unsigned char *name, unsigned namelen,
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200377 struct hpfs_dirent *new_de)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
379 struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
380 struct dnode *d;
381 struct hpfs_dirent *de, *de_end;
382 struct quad_buffer_head qbh;
383 dnode_secno dno;
384 int c;
385 int c1, c2 = 0;
386 dno = hpfs_inode->i_dno;
387 down:
388 if (hpfs_sb(i->i_sb)->sb_chk)
389 if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "hpfs_add_dirent")) return 1;
390 if (!(d = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 1;
391 de_end = dnode_end_de(d);
392 for (de = dnode_first_de(d); de < de_end; de = de_next_de(de)) {
393 if (!(c = hpfs_compare_names(i->i_sb, name, namelen, de->name, de->namelen, de->last))) {
394 hpfs_brelse4(&qbh);
395 return -1;
396 }
397 if (c < 0) {
398 if (de->down) {
399 dno = de_down_pointer(de);
400 hpfs_brelse4(&qbh);
401 goto down;
402 }
403 break;
404 }
405 }
406 hpfs_brelse4(&qbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_ADD)) {
408 c = 1;
409 goto ret;
410 }
411 i->i_version++;
412 c = hpfs_add_to_dnode(i, dno, name, namelen, new_de, 0);
413 ret:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 return c;
415}
416
417/*
418 * Find dirent with higher name in 'from' subtree and move it to 'to' dnode.
419 * Return the dnode we moved from (to be checked later if it's empty)
420 */
421
422static secno move_to_top(struct inode *i, dnode_secno from, dnode_secno to)
423{
424 dnode_secno dno, ddno;
425 dnode_secno chk_up = to;
426 struct dnode *dnode;
427 struct quad_buffer_head qbh;
428 struct hpfs_dirent *de, *nde;
429 int a;
430 loff_t t;
431 int c1, c2 = 0;
432 dno = from;
433 while (1) {
434 if (hpfs_sb(i->i_sb)->sb_chk)
435 if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "move_to_top"))
436 return 0;
437 if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return 0;
438 if (hpfs_sb(i->i_sb)->sb_chk) {
439 if (dnode->up != chk_up) {
440 hpfs_error(i->i_sb, "move_to_top: up pointer from %08x should be %08x, is %08x",
441 dno, chk_up, dnode->up);
442 hpfs_brelse4(&qbh);
443 return 0;
444 }
445 chk_up = dno;
446 }
447 if (!(de = dnode_last_de(dnode))) {
448 hpfs_error(i->i_sb, "move_to_top: dnode %08x has no last de", dno);
449 hpfs_brelse4(&qbh);
450 return 0;
451 }
452 if (!de->down) break;
453 dno = de_down_pointer(de);
454 hpfs_brelse4(&qbh);
455 }
456 while (!(de = dnode_pre_last_de(dnode))) {
457 dnode_secno up = dnode->up;
458 hpfs_brelse4(&qbh);
459 hpfs_free_dnode(i->i_sb, dno);
460 i->i_size -= 2048;
461 i->i_blocks -= 4;
462 for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, 5);
463 if (up == to) return to;
464 if (!(dnode = hpfs_map_dnode(i->i_sb, up, &qbh))) return 0;
465 if (dnode->root_dnode) {
466 hpfs_error(i->i_sb, "move_to_top: got to root_dnode while moving from %08x to %08x", from, to);
467 hpfs_brelse4(&qbh);
468 return 0;
469 }
470 de = dnode_last_de(dnode);
471 if (!de || !de->down) {
472 hpfs_error(i->i_sb, "move_to_top: dnode %08x doesn't point down to %08x", up, dno);
473 hpfs_brelse4(&qbh);
474 return 0;
475 }
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200476 dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 de->length -= 4;
478 de->down = 0;
479 hpfs_mark_4buffers_dirty(&qbh);
480 dno = up;
481 }
482 t = get_pos(dnode, de);
483 for_all_poss(i, hpfs_pos_subst, t, 4);
484 for_all_poss(i, hpfs_pos_subst, t + 1, 5);
485 if (!(nde = kmalloc(de->length, GFP_NOFS))) {
486 hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted");
487 hpfs_brelse4(&qbh);
488 return 0;
489 }
490 memcpy(nde, de, de->length);
491 ddno = de->down ? de_down_pointer(de) : 0;
492 hpfs_delete_de(i->i_sb, dnode, de);
493 set_last_pointer(i->i_sb, dnode, ddno);
494 hpfs_mark_4buffers_dirty(&qbh);
495 hpfs_brelse4(&qbh);
496 a = hpfs_add_to_dnode(i, to, nde->name, nde->namelen, nde, from);
497 kfree(nde);
498 if (a) return 0;
499 return dno;
500}
501
502/*
503 * Check if a dnode is empty and delete it from the tree
504 * (chkdsk doesn't like empty dnodes)
505 */
506
507static void delete_empty_dnode(struct inode *i, dnode_secno dno)
508{
509 struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
510 struct quad_buffer_head qbh;
511 struct dnode *dnode;
512 dnode_secno down, up, ndown;
513 int p;
514 struct hpfs_dirent *de;
515 int c1, c2 = 0;
516 try_it_again:
517 if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "delete_empty_dnode")) return;
518 if (!(dnode = hpfs_map_dnode(i->i_sb, dno, &qbh))) return;
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200519 if (le32_to_cpu(dnode->first_free) > 56) goto end;
520 if (le32_to_cpu(dnode->first_free) == 52 || le32_to_cpu(dnode->first_free) == 56) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 struct hpfs_dirent *de_end;
522 int root = dnode->root_dnode;
523 up = dnode->up;
524 de = dnode_first_de(dnode);
525 down = de->down ? de_down_pointer(de) : 0;
526 if (hpfs_sb(i->i_sb)->sb_chk) if (root && !down) {
527 hpfs_error(i->i_sb, "delete_empty_dnode: root dnode %08x is empty", dno);
528 goto end;
529 }
530 hpfs_brelse4(&qbh);
531 hpfs_free_dnode(i->i_sb, dno);
532 i->i_size -= 2048;
533 i->i_blocks -= 4;
534 if (root) {
535 struct fnode *fnode;
536 struct buffer_head *bh;
537 struct dnode *d1;
538 struct quad_buffer_head qbh1;
Randy Dunlap18debbb2006-12-06 20:37:05 -0800539 if (hpfs_sb(i->i_sb)->sb_chk)
540 if (up != i->i_ino) {
541 hpfs_error(i->i_sb,
542 "bad pointer to fnode, dnode %08x, pointing to %08x, should be %08lx",
543 dno, up, (unsigned long)i->i_ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 return;
Randy Dunlap18debbb2006-12-06 20:37:05 -0800545 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) {
547 d1->up = up;
548 d1->root_dnode = 1;
549 hpfs_mark_4buffers_dirty(&qbh1);
550 hpfs_brelse4(&qbh1);
551 }
552 if ((fnode = hpfs_map_fnode(i->i_sb, up, &bh))) {
553 fnode->u.external[0].disk_secno = down;
554 mark_buffer_dirty(bh);
555 brelse(bh);
556 }
557 hpfs_inode->i_dno = down;
558 for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, (loff_t) 12);
559 return;
560 }
561 if (!(dnode = hpfs_map_dnode(i->i_sb, up, &qbh))) return;
562 p = 1;
563 de_end = dnode_end_de(dnode);
564 for (de = dnode_first_de(dnode); de < de_end; de = de_next_de(de), p++)
565 if (de->down) if (de_down_pointer(de) == dno) goto fnd;
566 hpfs_error(i->i_sb, "delete_empty_dnode: pointer to dnode %08x not found in dnode %08x", dno, up);
567 goto end;
568 fnd:
569 for_all_poss(i, hpfs_pos_subst, ((loff_t)dno << 4) | 1, ((loff_t)up << 4) | p);
570 if (!down) {
571 de->down = 0;
572 de->length -= 4;
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200573 dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) - 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 memmove(de_next_de(de), (char *)de_next_de(de) + 4,
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200575 (char *)dnode + le32_to_cpu(dnode->first_free) - (char *)de_next_de(de));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 } else {
577 struct dnode *d1;
578 struct quad_buffer_head qbh1;
579 *(dnode_secno *) ((void *) de + de->length - 4) = down;
580 if ((d1 = hpfs_map_dnode(i->i_sb, down, &qbh1))) {
581 d1->up = up;
582 hpfs_mark_4buffers_dirty(&qbh1);
583 hpfs_brelse4(&qbh1);
584 }
585 }
586 } else {
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200587 hpfs_error(i->i_sb, "delete_empty_dnode: dnode %08x, first_free == %03x", dno, le32_to_cpu(dnode->first_free));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 goto end;
589 }
590
591 if (!de->last) {
592 struct hpfs_dirent *de_next = de_next_de(de);
593 struct hpfs_dirent *de_cp;
594 struct dnode *d1;
595 struct quad_buffer_head qbh1;
596 if (!de_next->down) goto endm;
597 ndown = de_down_pointer(de_next);
598 if (!(de_cp = kmalloc(de->length, GFP_NOFS))) {
599 printk("HPFS: out of memory for dtree balancing\n");
600 goto endm;
601 }
602 memcpy(de_cp, de, de->length);
603 hpfs_delete_de(i->i_sb, dnode, de);
604 hpfs_mark_4buffers_dirty(&qbh);
605 hpfs_brelse4(&qbh);
606 for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, 4);
607 for_all_poss(i, hpfs_pos_del, ((loff_t)up << 4) | p, 1);
608 if (de_cp->down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de_cp), &qbh1))) {
609 d1->up = ndown;
610 hpfs_mark_4buffers_dirty(&qbh1);
611 hpfs_brelse4(&qbh1);
612 }
613 hpfs_add_to_dnode(i, ndown, de_cp->name, de_cp->namelen, de_cp, de_cp->down ? de_down_pointer(de_cp) : 0);
614 /*printk("UP-TO-DNODE: %08x (ndown = %08x, down = %08x, dno = %08x)\n", up, ndown, down, dno);*/
615 dno = up;
616 kfree(de_cp);
617 goto try_it_again;
618 } else {
619 struct hpfs_dirent *de_prev = dnode_pre_last_de(dnode);
620 struct hpfs_dirent *de_cp;
621 struct dnode *d1;
622 struct quad_buffer_head qbh1;
623 dnode_secno dlp;
624 if (!de_prev) {
625 hpfs_error(i->i_sb, "delete_empty_dnode: empty dnode %08x", up);
626 hpfs_mark_4buffers_dirty(&qbh);
627 hpfs_brelse4(&qbh);
628 dno = up;
629 goto try_it_again;
630 }
631 if (!de_prev->down) goto endm;
632 ndown = de_down_pointer(de_prev);
633 if ((d1 = hpfs_map_dnode(i->i_sb, ndown, &qbh1))) {
634 struct hpfs_dirent *del = dnode_last_de(d1);
635 dlp = del->down ? de_down_pointer(del) : 0;
636 if (!dlp && down) {
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200637 if (le32_to_cpu(d1->first_free) > 2044) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 if (hpfs_sb(i->i_sb)->sb_chk >= 2) {
639 printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n");
640 printk("HPFS: warning: terminating balancing operation\n");
641 }
642 hpfs_brelse4(&qbh1);
643 goto endm;
644 }
645 if (hpfs_sb(i->i_sb)->sb_chk >= 2) {
646 printk("HPFS: warning: unbalanced dnode tree, see hpfs.txt 4 more info\n");
647 printk("HPFS: warning: goin'on\n");
648 }
649 del->length += 4;
650 del->down = 1;
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200651 d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 }
653 if (dlp && !down) {
654 del->length -= 4;
655 del->down = 0;
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200656 d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 } else if (down)
658 *(dnode_secno *) ((void *) del + del->length - 4) = down;
659 } else goto endm;
660 if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) {
661 printk("HPFS: out of memory for dtree balancing\n");
662 hpfs_brelse4(&qbh1);
663 goto endm;
664 }
665 hpfs_mark_4buffers_dirty(&qbh1);
666 hpfs_brelse4(&qbh1);
667 memcpy(de_cp, de_prev, de_prev->length);
668 hpfs_delete_de(i->i_sb, dnode, de_prev);
669 if (!de_prev->down) {
670 de_prev->length += 4;
671 de_prev->down = 1;
Mikulas Patocka7d23ce32011-05-08 20:43:06 +0200672 dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 }
674 *(dnode_secno *) ((void *) de_prev + de_prev->length - 4) = ndown;
675 hpfs_mark_4buffers_dirty(&qbh);
676 hpfs_brelse4(&qbh);
677 for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4);
678 for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | p, ((loff_t)up << 4) | (p - 1));
679 if (down) if ((d1 = hpfs_map_dnode(i->i_sb, de_down_pointer(de), &qbh1))) {
680 d1->up = ndown;
681 hpfs_mark_4buffers_dirty(&qbh1);
682 hpfs_brelse4(&qbh1);
683 }
684 hpfs_add_to_dnode(i, ndown, de_cp->name, de_cp->namelen, de_cp, dlp);
685 dno = up;
686 kfree(de_cp);
687 goto try_it_again;
688 }
689 endm:
690 hpfs_mark_4buffers_dirty(&qbh);
691 end:
692 hpfs_brelse4(&qbh);
693}
694
695
696/* Delete dirent from directory */
697
698int hpfs_remove_dirent(struct inode *i, dnode_secno dno, struct hpfs_dirent *de,
699 struct quad_buffer_head *qbh, int depth)
700{
701 struct dnode *dnode = qbh->data;
702 dnode_secno down = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 loff_t t;
704 if (de->first || de->last) {
705 hpfs_error(i->i_sb, "hpfs_remove_dirent: attempt to delete first or last dirent in dnode %08x", dno);
706 hpfs_brelse4(qbh);
707 return 1;
708 }
709 if (de->down) down = de_down_pointer(de);
710 if (depth && (de->down || (de == dnode_first_de(dnode) && de_next_de(de)->last))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 if (hpfs_check_free_dnodes(i->i_sb, FREE_DNODES_DEL)) {
712 hpfs_brelse4(qbh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 return 2;
714 }
715 }
716 i->i_version++;
717 for_all_poss(i, hpfs_pos_del, (t = get_pos(dnode, de)) + 1, 1);
718 hpfs_delete_de(i->i_sb, dnode, de);
719 hpfs_mark_4buffers_dirty(qbh);
720 hpfs_brelse4(qbh);
721 if (down) {
722 dnode_secno a = move_to_top(i, down, dno);
723 for_all_poss(i, hpfs_pos_subst, 5, t);
724 if (a) delete_empty_dnode(i, a);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 return !a;
726 }
727 delete_empty_dnode(i, dno);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 return 0;
729}
730
731void hpfs_count_dnodes(struct super_block *s, dnode_secno dno, int *n_dnodes,
732 int *n_subdirs, int *n_items)
733{
734 struct dnode *dnode;
735 struct quad_buffer_head qbh;
736 struct hpfs_dirent *de;
737 dnode_secno ptr, odno = 0;
738 int c1, c2 = 0;
739 int d1, d2 = 0;
740 go_down:
741 if (n_dnodes) (*n_dnodes)++;
742 if (hpfs_sb(s)->sb_chk)
743 if (hpfs_stop_cycles(s, dno, &c1, &c2, "hpfs_count_dnodes #1")) return;
744 ptr = 0;
745 go_up:
746 if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return;
747 if (hpfs_sb(s)->sb_chk) if (odno && odno != -1 && dnode->up != odno)
748 hpfs_error(s, "hpfs_count_dnodes: bad up pointer; dnode %08x, down %08x points to %08x", odno, dno, dnode->up);
749 de = dnode_first_de(dnode);
750 if (ptr) while(1) {
751 if (de->down) if (de_down_pointer(de) == ptr) goto process_de;
752 if (de->last) {
753 hpfs_brelse4(&qbh);
754 hpfs_error(s, "hpfs_count_dnodes: pointer to dnode %08x not found in dnode %08x, got here from %08x",
755 ptr, dno, odno);
756 return;
757 }
758 de = de_next_de(de);
759 }
760 next_de:
761 if (de->down) {
762 odno = dno;
763 dno = de_down_pointer(de);
764 hpfs_brelse4(&qbh);
765 goto go_down;
766 }
767 process_de:
768 if (!de->first && !de->last && de->directory && n_subdirs) (*n_subdirs)++;
769 if (!de->first && !de->last && n_items) (*n_items)++;
770 if ((de = de_next_de(de)) < dnode_end_de(dnode)) goto next_de;
771 ptr = dno;
772 dno = dnode->up;
773 if (dnode->root_dnode) {
774 hpfs_brelse4(&qbh);
775 return;
776 }
777 hpfs_brelse4(&qbh);
778 if (hpfs_sb(s)->sb_chk)
779 if (hpfs_stop_cycles(s, ptr, &d1, &d2, "hpfs_count_dnodes #2")) return;
780 odno = -1;
781 goto go_up;
782}
783
784static struct hpfs_dirent *map_nth_dirent(struct super_block *s, dnode_secno dno, int n,
785 struct quad_buffer_head *qbh, struct dnode **dn)
786{
787 int i;
788 struct hpfs_dirent *de, *de_end;
789 struct dnode *dnode;
790 dnode = hpfs_map_dnode(s, dno, qbh);
791 if (!dnode) return NULL;
792 if (dn) *dn=dnode;
793 de = dnode_first_de(dnode);
794 de_end = dnode_end_de(dnode);
795 for (i = 1; de < de_end; i++, de = de_next_de(de)) {
796 if (i == n) {
797 return de;
798 }
799 if (de->last) break;
800 }
801 hpfs_brelse4(qbh);
802 hpfs_error(s, "map_nth_dirent: n too high; dnode = %08x, requested %08x", dno, n);
803 return NULL;
804}
805
806dnode_secno hpfs_de_as_down_as_possible(struct super_block *s, dnode_secno dno)
807{
808 struct quad_buffer_head qbh;
809 dnode_secno d = dno;
810 dnode_secno up = 0;
811 struct hpfs_dirent *de;
812 int c1, c2 = 0;
813
814 again:
815 if (hpfs_sb(s)->sb_chk)
816 if (hpfs_stop_cycles(s, d, &c1, &c2, "hpfs_de_as_down_as_possible"))
817 return d;
818 if (!(de = map_nth_dirent(s, d, 1, &qbh, NULL))) return dno;
819 if (hpfs_sb(s)->sb_chk)
820 if (up && ((struct dnode *)qbh.data)->up != up)
821 hpfs_error(s, "hpfs_de_as_down_as_possible: bad up pointer; dnode %08x, down %08x points to %08x", up, d, ((struct dnode *)qbh.data)->up);
822 if (!de->down) {
823 hpfs_brelse4(&qbh);
824 return d;
825 }
826 up = d;
827 d = de_down_pointer(de);
828 hpfs_brelse4(&qbh);
829 goto again;
830}
831
832struct hpfs_dirent *map_pos_dirent(struct inode *inode, loff_t *posp,
833 struct quad_buffer_head *qbh)
834{
835 loff_t pos;
836 unsigned c;
837 dnode_secno dno;
838 struct hpfs_dirent *de, *d;
839 struct hpfs_dirent *up_de;
840 struct hpfs_dirent *end_up_de;
841 struct dnode *dnode;
842 struct dnode *up_dnode;
843 struct quad_buffer_head qbh0;
844
845 pos = *posp;
846 dno = pos >> 6 << 2;
847 pos &= 077;
848 if (!(de = map_nth_dirent(inode->i_sb, dno, pos, qbh, &dnode)))
849 goto bail;
850
851 /* Going to the next dirent */
852 if ((d = de_next_de(de)) < dnode_end_de(dnode)) {
853 if (!(++*posp & 077)) {
Randy Dunlap18debbb2006-12-06 20:37:05 -0800854 hpfs_error(inode->i_sb,
855 "map_pos_dirent: pos crossed dnode boundary; pos = %08llx",
856 (unsigned long long)*posp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 goto bail;
858 }
859 /* We're going down the tree */
860 if (d->down) {
861 *posp = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, de_down_pointer(d)) << 4) + 1;
862 }
863
864 return de;
865 }
866
867 /* Going up */
868 if (dnode->root_dnode) goto bail;
869
870 if (!(up_dnode = hpfs_map_dnode(inode->i_sb, dnode->up, &qbh0)))
871 goto bail;
872
873 end_up_de = dnode_end_de(up_dnode);
874 c = 0;
875 for (up_de = dnode_first_de(up_dnode); up_de < end_up_de;
876 up_de = de_next_de(up_de)) {
877 if (!(++c & 077)) hpfs_error(inode->i_sb,
878 "map_pos_dirent: pos crossed dnode boundary; dnode = %08x", dnode->up);
879 if (up_de->down && de_down_pointer(up_de) == dno) {
880 *posp = ((loff_t) dnode->up << 4) + c;
881 hpfs_brelse4(&qbh0);
882 return de;
883 }
884 }
885
886 hpfs_error(inode->i_sb, "map_pos_dirent: pointer to dnode %08x not found in parent dnode %08x",
887 dno, dnode->up);
888 hpfs_brelse4(&qbh0);
889
890 bail:
891 *posp = 12;
892 return de;
893}
894
895/* Find a dirent in tree */
896
Al Viro7e7742e2010-01-31 17:09:29 -0500897struct hpfs_dirent *map_dirent(struct inode *inode, dnode_secno dno,
898 const unsigned char *name, unsigned len,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 dnode_secno *dd, struct quad_buffer_head *qbh)
900{
901 struct dnode *dnode;
902 struct hpfs_dirent *de;
903 struct hpfs_dirent *de_end;
904 int c1, c2 = 0;
905
906 if (!S_ISDIR(inode->i_mode)) hpfs_error(inode->i_sb, "map_dirent: not a directory\n");
907 again:
908 if (hpfs_sb(inode->i_sb)->sb_chk)
909 if (hpfs_stop_cycles(inode->i_sb, dno, &c1, &c2, "map_dirent")) return NULL;
910 if (!(dnode = hpfs_map_dnode(inode->i_sb, dno, qbh))) return NULL;
911
912 de_end = dnode_end_de(dnode);
913 for (de = dnode_first_de(dnode); de < de_end; de = de_next_de(de)) {
914 int t = hpfs_compare_names(inode->i_sb, name, len, de->name, de->namelen, de->last);
915 if (!t) {
916 if (dd) *dd = dno;
917 return de;
918 }
919 if (t < 0) {
920 if (de->down) {
921 dno = de_down_pointer(de);
922 hpfs_brelse4(qbh);
923 goto again;
924 }
925 break;
926 }
927 }
928 hpfs_brelse4(qbh);
929 return NULL;
930}
931
932/*
933 * Remove empty directory. In normal cases it is only one dnode with two
934 * entries, but we must handle also such obscure cases when it's a tree
935 * of empty dnodes.
936 */
937
938void hpfs_remove_dtree(struct super_block *s, dnode_secno dno)
939{
940 struct quad_buffer_head qbh;
941 struct dnode *dnode;
942 struct hpfs_dirent *de;
943 dnode_secno d1, d2, rdno = dno;
944 while (1) {
945 if (!(dnode = hpfs_map_dnode(s, dno, &qbh))) return;
946 de = dnode_first_de(dnode);
947 if (de->last) {
948 if (de->down) d1 = de_down_pointer(de);
949 else goto error;
950 hpfs_brelse4(&qbh);
951 hpfs_free_dnode(s, dno);
952 dno = d1;
953 } else break;
954 }
955 if (!de->first) goto error;
956 d1 = de->down ? de_down_pointer(de) : 0;
957 de = de_next_de(de);
958 if (!de->last) goto error;
959 d2 = de->down ? de_down_pointer(de) : 0;
960 hpfs_brelse4(&qbh);
961 hpfs_free_dnode(s, dno);
962 do {
963 while (d1) {
964 if (!(dnode = hpfs_map_dnode(s, dno = d1, &qbh))) return;
965 de = dnode_first_de(dnode);
966 if (!de->last) goto error;
967 d1 = de->down ? de_down_pointer(de) : 0;
968 hpfs_brelse4(&qbh);
969 hpfs_free_dnode(s, dno);
970 }
971 d1 = d2;
972 d2 = 0;
973 } while (d1);
974 return;
975 error:
976 hpfs_brelse4(&qbh);
977 hpfs_free_dnode(s, dno);
978 hpfs_error(s, "directory %08x is corrupted or not empty", rdno);
979}
980
981/*
982 * Find dirent for specified fnode. Use truncated 15-char name in fnode as
983 * a help for searching.
984 */
985
986struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
987 struct fnode *f, struct quad_buffer_head *qbh)
988{
Al Viro7e7742e2010-01-31 17:09:29 -0500989 unsigned char *name1;
990 unsigned char *name2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 int name1len, name2len;
992 struct dnode *d;
993 dnode_secno dno, downd;
994 struct fnode *upf;
995 struct buffer_head *bh;
996 struct hpfs_dirent *de, *de_end;
997 int c;
998 int c1, c2 = 0;
999 int d1, d2 = 0;
1000 name1 = f->name;
1001 if (!(name2 = kmalloc(256, GFP_NOFS))) {
1002 printk("HPFS: out of memory, can't map dirent\n");
1003 return NULL;
1004 }
1005 if (f->len <= 15)
1006 memcpy(name2, name1, name1len = name2len = f->len);
1007 else {
1008 memcpy(name2, name1, 15);
1009 memset(name2 + 15, 0xff, 256 - 15);
1010 /*name2[15] = 0xff;*/
1011 name1len = 15; name2len = 256;
1012 }
1013 if (!(upf = hpfs_map_fnode(s, f->up, &bh))) {
1014 kfree(name2);
1015 return NULL;
1016 }
1017 if (!upf->dirflag) {
1018 brelse(bh);
1019 hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, f->up);
1020 kfree(name2);
1021 return NULL;
1022 }
1023 dno = upf->u.external[0].disk_secno;
1024 brelse(bh);
1025 go_down:
1026 downd = 0;
1027 go_up:
1028 if (!(d = hpfs_map_dnode(s, dno, qbh))) {
1029 kfree(name2);
1030 return NULL;
1031 }
1032 de_end = dnode_end_de(d);
1033 de = dnode_first_de(d);
1034 if (downd) {
1035 while (de < de_end) {
1036 if (de->down) if (de_down_pointer(de) == downd) goto f;
1037 de = de_next_de(de);
1038 }
1039 hpfs_error(s, "pointer to dnode %08x not found in dnode %08x", downd, dno);
1040 hpfs_brelse4(qbh);
1041 kfree(name2);
1042 return NULL;
1043 }
1044 next_de:
1045 if (de->fnode == fno) {
1046 kfree(name2);
1047 return de;
1048 }
1049 c = hpfs_compare_names(s, name1, name1len, de->name, de->namelen, de->last);
1050 if (c < 0 && de->down) {
1051 dno = de_down_pointer(de);
1052 hpfs_brelse4(qbh);
1053 if (hpfs_sb(s)->sb_chk)
1054 if (hpfs_stop_cycles(s, dno, &c1, &c2, "map_fnode_dirent #1")) {
1055 kfree(name2);
1056 return NULL;
1057 }
1058 goto go_down;
1059 }
1060 f:
1061 if (de->fnode == fno) {
1062 kfree(name2);
1063 return de;
1064 }
1065 c = hpfs_compare_names(s, name2, name2len, de->name, de->namelen, de->last);
1066 if (c < 0 && !de->last) goto not_found;
1067 if ((de = de_next_de(de)) < de_end) goto next_de;
1068 if (d->root_dnode) goto not_found;
1069 downd = dno;
1070 dno = d->up;
1071 hpfs_brelse4(qbh);
1072 if (hpfs_sb(s)->sb_chk)
1073 if (hpfs_stop_cycles(s, downd, &d1, &d2, "map_fnode_dirent #2")) {
1074 kfree(name2);
1075 return NULL;
1076 }
1077 goto go_up;
1078 not_found:
1079 hpfs_brelse4(qbh);
1080 hpfs_error(s, "dirent for fnode %08x not found", fno);
1081 kfree(name2);
1082 return NULL;
1083}