~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/hpfs/anode.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/hpfs/anode.c
  3  *
  4  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
  5  *
  6  *  handling HPFS anode tree that contains file allocation info
  7  */
  8 
  9 #include "hpfs_fn.h"
 10 
 11 /* Find a sector in allocation tree */
 12 
 13 secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
 14                    struct bplus_header *btree, unsigned sec,
 15                    struct buffer_head *bh)
 16 {
 17         anode_secno a = -1;
 18         struct anode *anode;
 19         int i;
 20         int c1, c2 = 0;
 21         go_down:
 22         if (s->s_hpfs_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1;
 23         if (btree->internal) {
 24                 for (i = 0; i < btree->n_used_nodes; i++)
 25                         if (btree->u.internal[i].file_secno > sec) {
 26                                 a = btree->u.internal[i].down;
 27                                 brelse(bh);
 28                                 if (!(anode = hpfs_map_anode(s, a, &bh))) return -1;
 29                                 btree = &anode->btree;
 30                                 goto go_down;
 31                         }
 32                 hpfs_error(s, "sector %08x not found in internal anode %08x", sec, a);
 33                 brelse(bh);
 34                 return -1;
 35         }
 36         for (i = 0; i < btree->n_used_nodes; i++)
 37                 if (btree->u.external[i].file_secno <= sec &&
 38                     btree->u.external[i].file_secno + btree->u.external[i].length > sec) {
 39                         a = btree->u.external[i].disk_secno + sec - btree->u.external[i].file_secno;
 40                         if (s->s_hpfs_chk) if (hpfs_chk_sectors(s, a, 1, "data")) {
 41                                 brelse(bh);
 42                                 return -1;
 43                         }
 44                         if (inode) {
 45                                 inode->i_hpfs_file_sec = btree->u.external[i].file_secno;
 46                                 inode->i_hpfs_disk_sec = btree->u.external[i].disk_secno;
 47                                 inode->i_hpfs_n_secs = btree->u.external[i].length;
 48                         }
 49                         brelse(bh);
 50                         return a;
 51                 }
 52         hpfs_error(s, "sector %08x not found in external anode %08x", sec, a);
 53         brelse(bh);
 54         return -1;
 55 }
 56 
 57 /* Add a sector to tree */
 58 
 59 secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsigned fsecno)
 60 {
 61         struct bplus_header *btree;
 62         struct anode *anode = NULL, *ranode = NULL;
 63         struct fnode *fnode;
 64         anode_secno a, na = -1, ra, up = -1;
 65         secno se;
 66         struct buffer_head *bh, *bh1, *bh2;
 67         int n;
 68         unsigned fs;
 69         int c1, c2 = 0;
 70         if (fnod) {
 71                 if (!(fnode = hpfs_map_fnode(s, node, &bh))) return -1;
 72                 btree = &fnode->btree;
 73         } else {
 74                 if (!(anode = hpfs_map_anode(s, node, &bh))) return -1;
 75                 btree = &anode->btree;
 76         }
 77         a = node;
 78         go_down:
 79         if ((n = btree->n_used_nodes - 1) < -!!fnod) {
 80                 hpfs_error(s, "anode %08x has no entries", a);
 81                 brelse(bh);
 82                 return -1;
 83         }
 84         if (btree->internal) {
 85                 a = btree->u.internal[n].down;
 86                 btree->u.internal[n].file_secno = -1;
 87                 mark_buffer_dirty(bh);
 88                 brelse(bh);
 89                 if (s->s_hpfs_chk)
 90                         if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_add_sector_to_btree #1")) return -1;
 91                 if (!(anode = hpfs_map_anode(s, a, &bh))) return -1;
 92                 btree = &anode->btree;
 93                 goto go_down;
 94         }
 95         if (n >= 0) {
 96                 if (btree->u.external[n].file_secno + btree->u.external[n].length != fsecno) {
 97                         hpfs_error(s, "allocated size %08x, trying to add sector %08x, %cnode %08x",
 98                                 btree->u.external[n].file_secno + btree->u.external[n].length, fsecno,
 99                                 fnod?'f':'a', node);
100                         brelse(bh);
101                         return -1;
102                 }
103                 if (hpfs_alloc_if_possible(s, se = btree->u.external[n].disk_secno + btree->u.external[n].length)) {
104                         btree->u.external[n].length++;
105                         mark_buffer_dirty(bh);
106                         brelse(bh);
107                         return se;
108                 }
109         } else {
110                 if (fsecno) {
111                         hpfs_error(s, "empty file %08x, trying to add sector %08x", node, fsecno);
112                         brelse(bh);
113                         return -1;
114                 }
115                 se = node;
116         }       
117         if (!(se = hpfs_alloc_sector(s, se, 1, fsecno*ALLOC_M>ALLOC_FWD_MAX ? ALLOC_FWD_MAX : fsecno*ALLOC_M<ALLOC_FWD_MIN ? ALLOC_FWD_MIN : fsecno*ALLOC_M, 1))) {
118                 brelse(bh);
119                 return -1;
120         }
121         fs = n < 0 ? 0 : btree->u.external[n].file_secno + btree->u.external[n].length;
122         if (!btree->n_free_nodes) {
123                 up = a != node ? anode->up : -1;
124                 if (!(anode = hpfs_alloc_anode(s, a, &na, &bh1))) {
125                         brelse(bh);
126                         hpfs_free_sectors(s, se, 1);
127                         return -1;
128                 }
129                 if (a == node && fnod) {
130                         anode->up = node;
131                         anode->btree.fnode_parent = 1;
132                         anode->btree.n_used_nodes = btree->n_used_nodes;
133                         anode->btree.first_free = btree->first_free;
134                         anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes;
135                         memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12);
136                         btree->internal = 1;
137                         btree->n_free_nodes = 11;
138                         btree->n_used_nodes = 1;
139                         btree->first_free = (char *)&(btree->u.internal[1]) - (char *)btree;
140                         btree->u.internal[0].file_secno = -1;
141                         btree->u.internal[0].down = na;
142                         mark_buffer_dirty(bh);
143                 } else if (!(ranode = hpfs_alloc_anode(s, /*a*/0, &ra, &bh2))) {
144                         brelse(bh);
145                         brelse(bh1);
146                         hpfs_free_sectors(s, se, 1);
147                         hpfs_free_sectors(s, na, 1);
148                         return -1;
149                 }
150                 brelse(bh);
151                 bh = bh1;
152                 btree = &anode->btree;
153         }
154         btree->n_free_nodes--; n = btree->n_used_nodes++;
155         btree->first_free += 12;
156         btree->u.external[n].disk_secno = se;
157         btree->u.external[n].file_secno = fs;
158         btree->u.external[n].length = 1;
159         mark_buffer_dirty(bh);
160         brelse(bh);
161         if ((a == node && fnod) || na == -1) return se;
162         c2 = 0;
163         while (up != -1) {
164                 if (s->s_hpfs_chk)
165                         if (hpfs_stop_cycles(s, up, &c1, &c2, "hpfs_add_sector_to_btree #2")) return -1;
166                 if (up != node || !fnod) {
167                         if (!(anode = hpfs_map_anode(s, up, &bh))) return -1;
168                         btree = &anode->btree;
169                 } else {
170                         if (!(fnode = hpfs_map_fnode(s, up, &bh))) return -1;
171                         btree = &fnode->btree;
172                 }
173                 if (btree->n_free_nodes) {
174                         btree->n_free_nodes--; n = btree->n_used_nodes++;
175                         btree->first_free += 8;
176                         btree->u.internal[n].file_secno = -1;
177                         btree->u.internal[n].down = na;
178                         btree->u.internal[n-1].file_secno = fs;
179                         mark_buffer_dirty(bh);
180                         brelse(bh);
181                         brelse(bh2);
182                         hpfs_free_sectors(s, ra, 1);
183                         if ((anode = hpfs_map_anode(s, na, &bh))) {
184                                 anode->up = up;
185                                 anode->btree.fnode_parent = up == node && fnod;
186                                 mark_buffer_dirty(bh);
187                                 brelse(bh);
188                         }
189                         return se;
190                 }
191                 up = up != node ? anode->up : -1;
192                 btree->u.internal[btree->n_used_nodes - 1].file_secno = /*fs*/-1;
193                 if (up == -1) anode->up = ra;
194                 mark_buffer_dirty(bh);
195                 brelse(bh);
196                 a = na;
197                 if ((anode = hpfs_alloc_anode(s, a, &na, &bh))) {
198                         /*anode->up = up != -1 ? up : ra;*/
199                         anode->btree.internal = 1;
200                         anode->btree.n_used_nodes = 1;
201                         anode->btree.n_free_nodes = 59;
202                         anode->btree.first_free = 16;
203                         anode->btree.u.internal[0].down = a;
204                         anode->btree.u.internal[0].file_secno = -1;
205                         mark_buffer_dirty(bh);
206                         brelse(bh);
207                         if ((anode = hpfs_map_anode(s, a, &bh))) {
208                                 anode->up = na;
209                                 mark_buffer_dirty(bh);
210                                 brelse(bh);
211                         }
212                 } else na = a;
213         }
214         if ((anode = hpfs_map_anode(s, na, &bh))) {
215                 anode->up = node;
216                 if (fnod) anode->btree.fnode_parent = 1;
217                 mark_buffer_dirty(bh);
218                 brelse(bh);
219         }
220         if (!fnod) {
221                 if (!(anode = hpfs_map_anode(s, node, &bh))) {
222                         brelse(bh2);
223                         return -1;
224                 }
225                 btree = &anode->btree;
226         } else {
227                 if (!(fnode = hpfs_map_fnode(s, node, &bh))) {
228                         brelse(bh2);
229                         return -1;
230                 }
231                 btree = &fnode->btree;
232         }
233         ranode->up = node;
234         memcpy(&ranode->btree, btree, btree->first_free);
235         if (fnod) ranode->btree.fnode_parent = 1;
236         ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes;
237         if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
238                 struct anode *unode;
239                 if ((unode = hpfs_map_anode(s, ranode->u.internal[n].down, &bh1))) {
240                         unode->up = ra;
241                         unode->btree.fnode_parent = 0;
242                         mark_buffer_dirty(bh1);
243                         brelse(bh1);
244                 }
245         }
246         btree->internal = 1;
247         btree->n_free_nodes = fnod ? 10 : 58;
248         btree->n_used_nodes = 2;
249         btree->first_free = (char *)&btree->u.internal[2] - (char *)btree;
250         btree->u.internal[0].file_secno = fs;
251         btree->u.internal[0].down = ra;
252         btree->u.internal[1].file_secno = -1;
253         btree->u.internal[1].down = na;
254         mark_buffer_dirty(bh);
255         brelse(bh);
256         mark_buffer_dirty(bh2);
257         brelse(bh2);
258         return se;
259 }
260 
261 /*
262  * Remove allocation tree. Recursion would look much nicer but
263  * I want to avoid it because it can cause stack overflow.
264  */
265 
266 void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
267 {
268         struct bplus_header *btree1 = btree;
269         struct anode *anode = NULL;
270         anode_secno ano = 0, oano;
271         struct buffer_head *bh;
272         int level = 0;
273         int pos = 0;
274         int i;
275         int c1, c2 = 0;
276         int d1, d2;
277         go_down:
278         d2 = 0;
279         while (btree1->internal) {
280                 ano = btree1->u.internal[pos].down;
281                 if (level) brelse(bh);
282                 if (s->s_hpfs_chk)
283                         if (hpfs_stop_cycles(s, ano, &d1, &d2, "hpfs_remove_btree #1"))
284                                 return;
285                 anode = hpfs_map_anode(s, ano, &bh);
286                 btree1 = &anode->btree;
287                 level++;
288                 pos = 0;
289         }
290         for (i = 0; i < btree1->n_used_nodes; i++)
291                 hpfs_free_sectors(s, btree1->u.external[i].disk_secno, btree1->u.external[i].length);
292         go_up:
293         if (!level) return;
294         if (s->s_hpfs_chk)
295                 if (hpfs_stop_cycles(s, ano, &c1, &c2, "hpfs_remove_btree #2")) return;
296         brelse(bh);
297         hpfs_free_sectors(s, ano, 1);
298         oano = ano;
299         ano = anode->up;
300         if (--level) {
301                 anode = hpfs_map_anode(s, ano, &bh);
302                 btree1 = &anode->btree;
303         } else btree1 = btree;
304         for (i = 0; i < btree1->n_used_nodes; i++) {
305                 if (btree1->u.internal[i].down == oano) {
306                         if ((pos = i + 1) < btree1->n_used_nodes)
307                                 goto go_down;
308                         else
309                                 goto go_up;
310                 }
311         }
312         hpfs_error(s,
313                    "reference to anode %08x not found in anode %08x "
314                    "(probably bad up pointer)",
315                    oano, level ? ano : -1);
316         if (level)
317                 brelse(bh);
318 }
319 
320 /* Just a wrapper around hpfs_bplus_lookup .. used for reading eas */
321 
322 static secno anode_lookup(struct super_block *s, anode_secno a, unsigned sec)
323 {
324         struct anode *anode;
325         struct buffer_head *bh;
326         if (!(anode = hpfs_map_anode(s, a, &bh))) return -1;
327         return hpfs_bplus_lookup(s, NULL, &anode->btree, sec, bh);
328 }
329 
330 int hpfs_ea_read(struct super_block *s, secno a, int ano, unsigned pos,
331             unsigned len, char *buf)
332 {
333         struct buffer_head *bh;
334         char *data;
335         secno sec;
336         unsigned l;
337         while (len) {
338                 if (ano) {
339                         if ((sec = anode_lookup(s, a, pos >> 9)) == -1)
340                                 return -1;
341                 } else sec = a + (pos >> 9);
342                 if (s->s_hpfs_chk) if (hpfs_chk_sectors(s, sec, 1, "ea #1")) return -1;
343                 if (!(data = hpfs_map_sector(s, sec, &bh, (len - 1) >> 9)))
344                         return -1;
345                 l = 0x200 - (pos & 0x1ff); if (l > len) l = len;
346                 memcpy(buf, data + (pos & 0x1ff), l);
347                 brelse(bh);
348                 buf += l; pos += l; len -= l;
349         }
350         return 0;
351 }
352 
353 int hpfs_ea_write(struct super_block *s, secno a, int ano, unsigned pos,
354              unsigned len, char *buf)
355 {
356         struct buffer_head *bh;
357         char *data;
358         secno sec;
359         unsigned l;
360         while (len) {
361                 if (ano) {
362                         if ((sec = anode_lookup(s, a, pos >> 9)) == -1)
363                                 return -1;
364                 } else sec = a + (pos >> 9);
365                 if (s->s_hpfs_chk) if (hpfs_chk_sectors(s, sec, 1, "ea #2")) return -1;
366                 if (!(data = hpfs_map_sector(s, sec, &bh, (len - 1) >> 9)))
367                         return -1;
368                 l = 0x200 - (pos & 0x1ff); if (l > len) l = len;
369                 memcpy(data + (pos & 0x1ff), buf, l);
370                 mark_buffer_dirty(bh);
371                 brelse(bh);
372                 buf += l; pos += l; len -= l;
373         }
374         return 0;
375 }
376 
377 void hpfs_ea_remove(struct super_block *s, secno a, int ano, unsigned len)
378 {
379         struct anode *anode;
380         struct buffer_head *bh;
381         if (ano) {
382                 if (!(anode = hpfs_map_anode(s, a, &bh))) return;
383                 hpfs_remove_btree(s, &anode->btree);
384                 brelse(bh);
385                 hpfs_free_sectors(s, a, 1);
386         } else hpfs_free_sectors(s, a, (len + 511) >> 9);
387 }
388 
389 /* Truncate allocation tree. Doesn't join anodes - I hope it doesn't matter */
390 
391 void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
392 {
393         struct fnode *fnode;
394         struct anode *anode;
395         struct buffer_head *bh;
396         struct bplus_header *btree;
397         anode_secno node = f;
398         int i, j, nodes;
399         int c1, c2 = 0;
400         if (fno) {
401                 if (!(fnode = hpfs_map_fnode(s, f, &bh))) return;
402                 btree = &fnode->btree;
403         } else {
404                 if (!(anode = hpfs_map_anode(s, f, &bh))) return;
405                 btree = &anode->btree;
406         }
407         if (!secs) {
408                 hpfs_remove_btree(s, btree);
409                 if (fno) {
410                         btree->n_free_nodes = 8;
411                         btree->n_used_nodes = 0;
412                         btree->first_free = 8;
413                         btree->internal = 0;
414                         mark_buffer_dirty(bh);
415                 } else hpfs_free_sectors(s, f, 1);
416                 brelse(bh);
417                 return;
418         }
419         while (btree->internal) {
420                 nodes = btree->n_used_nodes + btree->n_free_nodes;
421                 for (i = 0; i < btree->n_used_nodes; i++)
422                         if (btree->u.internal[i].file_secno >= secs) goto f;
423                 brelse(bh);
424                 hpfs_error(s, "internal btree %08x doesn't end with -1", node);
425                 return;
426                 f:
427                 for (j = i + 1; j < btree->n_used_nodes; j++)
428                         hpfs_ea_remove(s, btree->u.internal[j].down, 1, 0);
429                 btree->n_used_nodes = i + 1;
430                 btree->n_free_nodes = nodes - btree->n_used_nodes;
431                 btree->first_free = 8 + 8 * btree->n_used_nodes;
432                 mark_buffer_dirty(bh);
433                 if (btree->u.internal[i].file_secno == secs) {
434                         brelse(bh);
435                         return;
436                 }
437                 node = btree->u.internal[i].down;
438                 brelse(bh);
439                 if (s->s_hpfs_chk)
440                         if (hpfs_stop_cycles(s, node, &c1, &c2, "hpfs_truncate_btree"))
441                                 return;
442                 if (!(anode = hpfs_map_anode(s, node, &bh))) return;
443                 btree = &anode->btree;
444         }       
445         nodes = btree->n_used_nodes + btree->n_free_nodes;
446         for (i = 0; i < btree->n_used_nodes; i++)
447                 if (btree->u.external[i].file_secno + btree->u.external[i].length >= secs) goto ff;
448         brelse(bh);
449         return;
450         ff:
451         if (secs <= btree->u.external[i].file_secno) {
452                 hpfs_error(s, "there is an allocation error in file %08x, sector %08x", f, secs);
453                 if (i) i--;
454         }
455         else if (btree->u.external[i].file_secno + btree->u.external[i].length > secs) {
456                 hpfs_free_sectors(s, btree->u.external[i].disk_secno + secs -
457                         btree->u.external[i].file_secno, btree->u.external[i].length
458                         - secs + btree->u.external[i].file_secno); /* I hope gcc optimizes this :-) */
459                 btree->u.external[i].length = secs - btree->u.external[i].file_secno;
460         }
461         for (j = i + 1; j < btree->n_used_nodes; j++)
462                 hpfs_free_sectors(s, btree->u.external[j].disk_secno, btree->u.external[j].length);
463         btree->n_used_nodes = i + 1;
464         btree->n_free_nodes = nodes - btree->n_used_nodes;
465         btree->first_free = 8 + 12 * btree->n_used_nodes;
466         mark_buffer_dirty(bh);
467         brelse(bh);
468 }
469 
470 /* Remove file or directory and it's eas - note that directory must
471    be empty when this is called. */
472 
473 void hpfs_remove_fnode(struct super_block *s, fnode_secno fno)
474 {
475         struct buffer_head *bh;
476         struct fnode *fnode;
477         struct extended_attribute *ea;
478         struct extended_attribute *ea_end;
479         if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return;
480         if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree);
481         else hpfs_remove_dtree(s, fnode->u.external[0].disk_secno);
482         ea_end = fnode_end_ea(fnode);
483         for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
484                 if (ea->indirect)
485                         hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
486         hpfs_ea_ext_remove(s, fnode->ea_secno, fnode->ea_anode, fnode->ea_size_l);
487         brelse(bh);
488         hpfs_free_sectors(s, fno, 1);
489 }
490 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.