VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/Etherboot-src/filo/fs/fsys_reiserfs.c@ 566

Last change on this file since 566 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.7 KB
Line 
1/* fsys_reiserfs.c - an implementation for the ReiserFS filesystem */
2/*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2000, 2001 Free Software Foundation, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#ifdef FSYS_REISERFS
22#include "shared.h"
23#include "filesys.h"
24#include <lib.h>
25#include "string.h"
26
27#undef REISERDEBUG
28
29/* Some parts of this code (mainly the structures and defines) are
30 * from the original reiser fs code, as found in the linux kernel.
31 */
32
33/* include/asm-i386/types.h */
34typedef __signed__ char __s8;
35typedef unsigned char __u8;
36typedef __signed__ short __s16;
37typedef unsigned short __u16;
38typedef __signed__ int __s32;
39typedef unsigned int __u32;
40typedef unsigned long long __u64;
41
42/* linux/posix_type.h */
43typedef long linux_off_t;
44
45/* linux/little_endian.h */
46#define __cpu_to_le64(x) ((__u64) (x))
47#define __le64_to_cpu(x) ((__u64) (x))
48#define __cpu_to_le32(x) ((__u32) (x))
49#define __le32_to_cpu(x) ((__u32) (x))
50#define __cpu_to_le16(x) ((__u16) (x))
51#define __le16_to_cpu(x) ((__u16) (x))
52
53/* include/linux/reiser_fs.h */
54/* This is the new super block of a journaling reiserfs system */
55struct reiserfs_super_block
56{
57 __u32 s_block_count; /* blocks count */
58 __u32 s_free_blocks; /* free blocks count */
59 __u32 s_root_block; /* root block number */
60 __u32 s_journal_block; /* journal block number */
61 __u32 s_journal_dev; /* journal device number */
62 __u32 s_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */
63 __u32 s_journal_trans_max; /* max number of blocks in a transaction. */
64 __u32 s_journal_magic; /* random value made on fs creation */
65 __u32 s_journal_max_batch; /* max number of blocks to batch into a trans */
66 __u32 s_journal_max_commit_age; /* in seconds, how old can an async commit be */
67 __u32 s_journal_max_trans_age; /* in seconds, how old can a transaction be */
68 __u16 s_blocksize; /* block size */
69 __u16 s_oid_maxsize; /* max size of object id array */
70 __u16 s_oid_cursize; /* current size of object id array */
71 __u16 s_state; /* valid or error */
72 char s_magic[16]; /* reiserfs magic string indicates that file system is reiserfs */
73 __u16 s_tree_height; /* height of disk tree */
74 __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */
75 __u16 s_version;
76 char s_unused[128]; /* zero filled by mkreiserfs */
77};
78
79#define REISERFS_MAX_SUPPORTED_VERSION 2
80#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
81#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
82
83#define MAX_HEIGHT 7
84
85/* must be correct to keep the desc and commit structs at 4k */
86#define JOURNAL_TRANS_HALF 1018
87
88/* first block written in a commit. */
89struct reiserfs_journal_desc {
90 __u32 j_trans_id; /* id of commit */
91 __u32 j_len; /* length of commit. len +1 is the commit block */
92 __u32 j_mount_id; /* mount id of this trans*/
93 __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */
94 char j_magic[12];
95};
96
97/* last block written in a commit */
98struct reiserfs_journal_commit {
99 __u32 j_trans_id; /* must match j_trans_id from the desc block */
100 __u32 j_len; /* ditto */
101 __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */
102 char j_digest[16]; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
103};
104
105/* this header block gets written whenever a transaction is considered
106 fully flushed, and is more recent than the last fully flushed
107 transaction.
108 fully flushed means all the log blocks and all the real blocks are
109 on disk, and this transaction does not need to be replayed.
110*/
111struct reiserfs_journal_header {
112 /* id of last fully flushed transaction */
113 __u32 j_last_flush_trans_id;
114 /* offset in the log of where to start replay after a crash */
115 __u32 j_first_unflushed_offset;
116 /* mount id to detect very old transactions */
117 __u32 j_mount_id;
118};
119
120/* magic string to find desc blocks in the journal */
121#define JOURNAL_DESC_MAGIC "ReIsErLB"
122
123
124/*
125 * directories use this key as well as old files
126 */
127struct offset_v1
128{
129 /*
130 * for regular files this is the offset to the first byte of the
131 * body, contained in the object-item, as measured from the start of
132 * the entire body of the object.
133 *
134 * for directory entries, k_offset consists of hash derived from
135 * hashing the name and using few bits (23 or more) of the resulting
136 * hash, and generation number that allows distinguishing names with
137 * hash collisions. If number of collisions overflows generation
138 * number, we return EEXIST. High order bit is 0 always
139 */
140 __u32 k_offset;
141 __u32 k_uniqueness;
142};
143
144struct offset_v2
145{
146 /*
147 * for regular files this is the offset to the first byte of the
148 * body, contained in the object-item, as measured from the start of
149 * the entire body of the object.
150 *
151 * for directory entries, k_offset consists of hash derived from
152 * hashing the name and using few bits (23 or more) of the resulting
153 * hash, and generation number that allows distinguishing names with
154 * hash collisions. If number of collisions overflows generation
155 * number, we return EEXIST. High order bit is 0 always
156 */
157 __u64 k_offset:60;
158 __u64 k_type: 4;
159};
160
161
162struct key
163{
164 /* packing locality: by default parent directory object id */
165 __u32 k_dir_id;
166 /* object identifier */
167 __u32 k_objectid;
168 /* the offset and node type (old and new form) */
169 union
170 {
171 struct offset_v1 v1;
172 struct offset_v2 v2;
173 }
174 u;
175};
176
177#define KEY_SIZE (sizeof (struct key))
178
179/* Header of a disk block. More precisely, header of a formatted leaf
180 or internal node, and not the header of an unformatted node. */
181struct block_head
182{
183 __u16 blk_level; /* Level of a block in the tree. */
184 __u16 blk_nr_item; /* Number of keys/items in a block. */
185 __u16 blk_free_space; /* Block free space in bytes. */
186 struct key blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
187 only) */
188};
189#define BLKH_SIZE (sizeof (struct block_head))
190#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */
191
192struct item_head
193{
194 struct key ih_key; /* Everything in the tree is found by searching for it based on its key.*/
195
196 union
197 {
198 __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this
199 is an indirect item. This equals 0xFFFF iff this is a direct item or
200 stat data item. Note that the key, not this field, is used to determine
201 the item type, and thus which field this union contains. */
202 __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory
203 entries in the directory item. */
204 }
205 u;
206 __u16 ih_item_len; /* total size of the item body */
207 __u16 ih_item_location; /* an offset to the item body within the block */
208 __u16 ih_version; /* ITEM_VERSION_1 for all old items,
209 ITEM_VERSION_2 for new ones.
210 Highest bit is set by fsck
211 temporary, cleaned after all done */
212};
213/* size of item header */
214#define IH_SIZE (sizeof (struct item_head))
215
216#define ITEM_VERSION_1 0
217#define ITEM_VERSION_2 1
218#define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \
219 ? (ih)->ih_key.u.v1.k_offset \
220 : (ih)->ih_key.u.v2.k_offset)
221
222#define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \
223 ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \
224 : (ih)->ih_key.u.v2.k_type == V2_##type)
225
226struct disk_child
227{
228 unsigned long dc_block_number; /* Disk child's block number. */
229 unsigned short dc_size; /* Disk child's used space. */
230};
231
232#define DC_SIZE (sizeof (struct disk_child))
233
234/* Stat Data on disk.
235 *
236 * Note that reiserfs has two different forms of stat data. Luckily
237 * the fields needed by grub are at the same position.
238 */
239struct stat_data
240{
241 __u16 sd_mode; /* file type, permissions */
242 __u16 sd_notused1[3]; /* fields not needed by reiserfs */
243 __u32 sd_size; /* file size */
244 __u32 sd_size_hi; /* file size high 32 bits (since version 2) */
245};
246
247struct reiserfs_de_head
248{
249 __u32 deh_offset; /* third component of the directory entry key */
250 __u32 deh_dir_id; /* objectid of the parent directory of the
251 object, that is referenced by directory entry */
252 __u32 deh_objectid;/* objectid of the object, that is referenced by
253 directory entry */
254 __u16 deh_location;/* offset of name in the whole item */
255 __u16 deh_state; /* whether 1) entry contains stat data (for
256 future), and 2) whether entry is hidden
257 (unlinked) */
258};
259
260#define DEH_SIZE (sizeof (struct reiserfs_de_head))
261
262#define DEH_Statdata (1 << 0) /* not used now */
263#define DEH_Visible (1 << 2)
264
265#define SD_OFFSET 0
266#define SD_UNIQUENESS 0
267#define DOT_OFFSET 1
268#define DOT_DOT_OFFSET 2
269#define DIRENTRY_UNIQUENESS 500
270
271#define V1_TYPE_STAT_DATA 0x0
272#define V1_TYPE_DIRECT 0xffffffff
273#define V1_TYPE_INDIRECT 0xfffffffe
274#define V1_TYPE_DIRECTORY_MAX 0xfffffffd
275#define V2_TYPE_STAT_DATA 0
276#define V2_TYPE_INDIRECT 1
277#define V2_TYPE_DIRECT 2
278#define V2_TYPE_DIRENTRY 3
279
280#define REISERFS_ROOT_OBJECTID 2
281#define REISERFS_ROOT_PARENT_OBJECTID 1
282#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
283/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
284#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
285#define REISERFS_OLD_BLOCKSIZE 4096
286
287#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
288#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
289#define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
290
291#define PATH_MAX 1024 /* include/linux/limits.h */
292#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
293
294/* The size of the node cache */
295#define FSYSREISER_CACHE_SIZE 24*1024
296#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
297#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
298
299/* Info about currently opened file */
300struct fsys_reiser_fileinfo
301{
302 __u32 k_dir_id;
303 __u32 k_objectid;
304};
305
306/* In memory info about the currently mounted filesystem */
307struct fsys_reiser_info
308{
309 /* The last read item head */
310 struct item_head *current_ih;
311 /* The last read item */
312 char *current_item;
313 /* The information for the currently opened file */
314 struct fsys_reiser_fileinfo fileinfo;
315 /* The start of the journal */
316 __u32 journal_block;
317 /* The size of the journal */
318 __u32 journal_block_count;
319 /* The first valid descriptor block in journal
320 (relative to journal_block) */
321 __u32 journal_first_desc;
322
323 /* The ReiserFS version. */
324 __u16 version;
325 /* The current depth of the reiser tree. */
326 __u16 tree_depth;
327 /* SECTOR_SIZE << blocksize_shift == blocksize. */
328 __u8 blocksize_shift;
329 /* 1 << full_blocksize_shift == blocksize. */
330 __u8 fullblocksize_shift;
331 /* The reiserfs block size (must be a power of 2) */
332 __u16 blocksize;
333 /* The number of cached tree nodes */
334 __u16 cached_slots;
335 /* The number of valid transactions in journal */
336 __u16 journal_transactions;
337
338 unsigned int blocks[MAX_HEIGHT];
339 unsigned int next_key_nr[MAX_HEIGHT];
340};
341
342/* The cached s+tree blocks in FSYS_BUF, see below
343 * for a more detailed description.
344 */
345#define ROOT ((char *) ((int) FSYS_BUF))
346#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
347#define LEAF CACHE (DISK_LEAF_NODE_LEVEL)
348
349#define BLOCKHEAD(cache) ((struct block_head *) cache)
350#define ITEMHEAD ((struct item_head *) ((int) LEAF + BLKH_SIZE))
351#define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE))
352#define DC(cache) ((struct disk_child *) \
353 ((int) cache + BLKH_SIZE + KEY_SIZE * nr_item))
354/* The fsys_reiser_info block.
355 */
356#define INFO \
357 ((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE))
358/*
359 * The journal cache. For each transaction it contains the number of
360 * blocks followed by the real block numbers of this transaction.
361 *
362 * If the block numbers of some transaction won't fit in this space,
363 * this list is stopped with a 0xffffffff marker and the remaining
364 * uncommitted transactions aren't cached.
365 */
366#define JOURNAL_START ((__u32 *) (INFO + 1))
367#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
368
369
370static __inline__ unsigned long
371log2 (unsigned long word)
372{
373 __asm__ ("bsfl %1,%0"
374 : "=r" (word)
375 : "r" (word));
376 return word;
377}
378
379static __inline__ int
380is_power_of_two (unsigned long word)
381{
382 return (word & -word) == word;
383}
384
385static int
386journal_read (int block, int len, char *buffer)
387{
388 return devread ((INFO->journal_block + block) << INFO->blocksize_shift,
389 0, len, buffer);
390}
391
392/* Read a block from ReiserFS file system, taking the journal into
393 * account. If the block nr is in the journal, the block from the
394 * journal taken.
395 */
396static int
397block_read (int blockNr, int start, int len, char *buffer)
398{
399 int transactions = INFO->journal_transactions;
400 int desc_block = INFO->journal_first_desc;
401 int journal_mask = INFO->journal_block_count - 1;
402 int translatedNr = blockNr;
403 __u32 *journal_table = JOURNAL_START;
404 while (transactions-- > 0)
405 {
406 int i = 0;
407 int j_len;
408 if (*journal_table != 0xffffffff)
409 {
410 /* Search for the blockNr in cached journal */
411 j_len = *journal_table++;
412 while (i++ < j_len)
413 {
414 if (*journal_table++ == blockNr)
415 {
416 journal_table += j_len - i;
417 goto found;
418 }
419 }
420 }
421 else
422 {
423 /* This is the end of cached journal marker. The remaining
424 * transactions are still on disk.
425 */
426 struct reiserfs_journal_desc desc;
427 struct reiserfs_journal_commit commit;
428
429 if (! journal_read (desc_block, sizeof (desc), (char *) &desc))
430 return 0;
431
432 j_len = desc.j_len;
433 while (i < j_len && i < JOURNAL_TRANS_HALF)
434 if (desc.j_realblock[i++] == blockNr)
435 goto found;
436
437 if (j_len >= JOURNAL_TRANS_HALF)
438 {
439 int commit_block = (desc_block + 1 + j_len) & journal_mask;
440 if (! journal_read (commit_block,
441 sizeof (commit), (char *) &commit))
442 return 0;
443 while (i < j_len)
444 if (commit.j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr)
445 goto found;
446 }
447 }
448 goto not_found;
449
450 found:
451 translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
452#ifdef REISERDEBUG
453 printf ("block_read: block %d is mapped to journal block %d.\n",
454 blockNr, translatedNr - INFO->journal_block);
455#endif
456 /* We must continue the search, as this block may be overwritten
457 * in later transactions.
458 */
459 not_found:
460 desc_block = (desc_block + 2 + j_len) & journal_mask;
461 }
462 return devread (translatedNr << INFO->blocksize_shift, start, len, buffer);
463}
464
465/* Init the journal data structure. We try to cache as much as
466 * possible in the JOURNAL_START-JOURNAL_END space, but if it is full
467 * we can still read the rest from the disk on demand.
468 *
469 * The first number of valid transactions and the descriptor block of the
470 * first valid transaction are held in INFO. The transactions are all
471 * adjacent, but we must take care of the journal wrap around.
472 */
473static int
474journal_init (void)
475{
476 unsigned int block_count = INFO->journal_block_count;
477 unsigned int desc_block;
478 unsigned int commit_block;
479 unsigned int next_trans_id;
480 struct reiserfs_journal_header header;
481 struct reiserfs_journal_desc desc;
482 struct reiserfs_journal_commit commit;
483 __u32 *journal_table = JOURNAL_START;
484
485 journal_read (block_count, sizeof (header), (char *) &header);
486 desc_block = header.j_first_unflushed_offset;
487 if (desc_block >= block_count)
488 return 0;
489
490 INFO->journal_first_desc = desc_block;
491 next_trans_id = header.j_last_flush_trans_id + 1;
492
493#ifdef REISERDEBUG
494 printf ("journal_init: last flushed %d\n",
495 header.j_last_flush_trans_id);
496#endif
497
498 while (1)
499 {
500 journal_read (desc_block, sizeof (desc), (char *) &desc);
501 if (substring (JOURNAL_DESC_MAGIC, desc.j_magic) > 0
502 || desc.j_trans_id != next_trans_id
503 || desc.j_mount_id != header.j_mount_id)
504 /* no more valid transactions */
505 break;
506
507 commit_block = (desc_block + desc.j_len + 1) & (block_count - 1);
508 journal_read (commit_block, sizeof (commit), (char *) &commit);
509 if (desc.j_trans_id != commit.j_trans_id
510 || desc.j_len != commit.j_len)
511 /* no more valid transactions */
512 break;
513
514#ifdef REISERDEBUG
515 printf ("Found valid transaction %d/%d at %d.\n",
516 desc.j_trans_id, desc.j_mount_id, desc_block);
517#endif
518
519 next_trans_id++;
520 if (journal_table < JOURNAL_END)
521 {
522 if ((journal_table + 1 + desc.j_len) >= JOURNAL_END)
523 {
524 /* The table is almost full; mark the end of the cached
525 * journal.*/
526 *journal_table = 0xffffffff;
527 journal_table = JOURNAL_END;
528 }
529 else
530 {
531 int i;
532 /* Cache the length and the realblock numbers in the table.
533 * The block number of descriptor can easily be computed.
534 * and need not to be stored here.
535 */
536 *journal_table++ = desc.j_len;
537 for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++)
538 {
539 *journal_table++ = desc.j_realblock[i];
540#ifdef REISERDEBUG
541 printf ("block %d is in journal %d.\n",
542 desc.j_realblock[i], desc_block);
543#endif
544 }
545 for ( ; i < desc.j_len; i++)
546 {
547 *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
548#ifdef REISERDEBUG
549 printf ("block %d is in journal %d.\n",
550 commit.j_realblock[i-JOURNAL_TRANS_HALF],
551 desc_block);
552#endif
553 }
554 }
555 }
556 desc_block = (commit_block + 1) & (block_count - 1);
557 }
558#ifdef REISERDEBUG
559 printf ("Transaction %d/%d at %d isn't valid.\n",
560 desc.j_trans_id, desc.j_mount_id, desc_block);
561#endif
562
563 INFO->journal_transactions
564 = next_trans_id - header.j_last_flush_trans_id - 1;
565 return errnum == 0;
566}
567
568/* check filesystem types and read superblock into memory buffer */
569int
570reiserfs_mount (void)
571{
572 struct reiserfs_super_block super;
573 int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
574
575 if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
576 || ! devread (superblock, 0, sizeof (struct reiserfs_super_block),
577 (char *) &super)
578 || (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
579 && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
580 || (/* check that this is not a copy inside the journal log */
581 super.s_journal_block * super.s_blocksize
582 <= REISERFS_DISK_OFFSET_IN_BYTES))
583 {
584 /* Try old super block position */
585 superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
586 if (part_length < superblock + (sizeof (super) >> SECTOR_BITS)
587 || ! devread (superblock, 0, sizeof (struct reiserfs_super_block),
588 (char *) &super))
589 return 0;
590
591 if (substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
592 && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
593 {
594 /* pre journaling super block ? */
595 if (substring (REISERFS_SUPER_MAGIC_STRING,
596 (char*) ((int) &super + 20)) > 0)
597 return 0;
598
599 super.s_blocksize = REISERFS_OLD_BLOCKSIZE;
600 super.s_journal_block = 0;
601 super.s_version = 0;
602 }
603 }
604
605 /* check the version number. */
606 if (super.s_version > REISERFS_MAX_SUPPORTED_VERSION)
607 return 0;
608
609 INFO->version = super.s_version;
610 INFO->blocksize = super.s_blocksize;
611 INFO->fullblocksize_shift = log2 (super.s_blocksize);
612 INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
613 INFO->cached_slots =
614 (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
615
616#ifdef REISERDEBUG
617 printf ("reiserfs_mount: version=%d, blocksize=%d\n",
618 INFO->version, INFO->blocksize);
619#endif /* REISERDEBUG */
620
621 /* Clear node cache. */
622 memset (INFO->blocks, 0, sizeof (INFO->blocks));
623
624 if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE
625 || super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE
626 || (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize)
627 return 0;
628
629 /* Initialize journal code. If something fails we end with zero
630 * journal_transactions, so we don't access the journal at all.
631 */
632 INFO->journal_transactions = 0;
633 if (super.s_journal_block != 0 && super.s_journal_dev == 0)
634 {
635 INFO->journal_block = super.s_journal_block;
636 INFO->journal_block_count = super.s_journal_size;
637 if (is_power_of_two (INFO->journal_block_count))
638 journal_init ();
639
640 /* Read in super block again, maybe it is in the journal */
641 block_read (superblock >> INFO->blocksize_shift,
642 0, sizeof (struct reiserfs_super_block), (char *) &super);
643 }
644
645 if (! block_read (super.s_root_block, 0, INFO->blocksize, (char*) ROOT))
646 return 0;
647
648 INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level;
649
650#ifdef REISERDEBUG
651 printf ("root read_in: block=%d, depth=%d\n",
652 super.s_root_block, INFO->tree_depth);
653#endif /* REISERDEBUG */
654
655 if (INFO->tree_depth >= MAX_HEIGHT)
656 return 0;
657 if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL)
658 {
659 /* There is only one node in the whole filesystem,
660 * which is simultanously leaf and root */
661 memcpy (LEAF, ROOT, INFO->blocksize);
662 }
663 return 1;
664}
665
666/***************** TREE ACCESSING METHODS *****************************/
667
668/* I assume you are familiar with the ReiserFS tree, if not go to
669 * http://www.namesys.com/content_table.html
670 *
671 * My tree node cache is organized as following
672 * 0 ROOT node
673 * 1 LEAF node (if the ROOT is also a LEAF it is copied here
674 * 2-n other nodes on current path from bottom to top.
675 * if there is not enough space in the cache, the top most are
676 * omitted.
677 *
678 * I have only two methods to find a key in the tree:
679 * search_stat(dir_id, objectid) searches for the stat entry (always
680 * the first entry) of an object.
681 * next_key() gets the next key in tree order.
682 *
683 * This means, that I can only sequential reads of files are
684 * efficient, but this really doesn't hurt for grub.
685 */
686
687/* Read in the node at the current path and depth into the node cache.
688 * You must set INFO->blocks[depth] before.
689 */
690static char *
691read_tree_node (unsigned int blockNr, int depth)
692{
693 char* cache = CACHE(depth);
694 int num_cached = INFO->cached_slots;
695 if (depth < num_cached)
696 {
697 /* This is the cached part of the path. Check if same block is
698 * needed.
699 */
700 if (blockNr == INFO->blocks[depth])
701 return cache;
702 }
703 else
704 cache = CACHE(num_cached);
705
706#ifdef REISERDEBUG
707 printf (" next read_in: block=%d (depth=%d)\n",
708 blockNr, depth);
709#endif /* REISERDEBUG */
710 if (! block_read (blockNr, 0, INFO->blocksize, cache))
711 return 0;
712 /* Make sure it has the right node level */
713 if (BLOCKHEAD (cache)->blk_level != depth)
714 {
715 errnum = ERR_FSYS_CORRUPT;
716 return 0;
717 }
718
719 INFO->blocks[depth] = blockNr;
720 return cache;
721}
722
723/* Get the next key, i.e. the key following the last retrieved key in
724 * tree order. INFO->current_ih and
725 * INFO->current_info are adapted accordingly. */
726static int
727next_key (void)
728{
729 int depth;
730 struct item_head *ih = INFO->current_ih + 1;
731 char *cache;
732
733#ifdef REISERDEBUG
734 printf ("next_key:\n old ih: key %d:%d:%d:%d version:%d\n",
735 INFO->current_ih->ih_key.k_dir_id,
736 INFO->current_ih->ih_key.k_objectid,
737 INFO->current_ih->ih_key.u.v1.k_offset,
738 INFO->current_ih->ih_key.u.v1.k_uniqueness,
739 INFO->current_ih->ih_version);
740#endif /* REISERDEBUG */
741
742 if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item])
743 {
744 depth = DISK_LEAF_NODE_LEVEL;
745 /* The last item, was the last in the leaf node.
746 * Read in the next block
747 */
748 do
749 {
750 if (depth == INFO->tree_depth)
751 {
752 /* There are no more keys at all.
753 * Return a dummy item with MAX_KEY */
754 ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
755 goto found;
756 }
757 depth++;
758#ifdef REISERDEBUG
759 printf (" depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
760#endif /* REISERDEBUG */
761 }
762 while (INFO->next_key_nr[depth] == 0);
763
764 if (depth == INFO->tree_depth)
765 cache = ROOT;
766 else if (depth <= INFO->cached_slots)
767 cache = CACHE (depth);
768 else
769 {
770 cache = read_tree_node (INFO->blocks[depth], depth);
771 if (! cache)
772 return 0;
773 }
774
775 do
776 {
777 int nr_item = BLOCKHEAD (cache)->blk_nr_item;
778 int key_nr = INFO->next_key_nr[depth]++;
779#ifdef REISERDEBUG
780 printf (" depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
781#endif /* REISERDEBUG */
782 if (key_nr == nr_item)
783 /* This is the last item in this block, set the next_key_nr to 0 */
784 INFO->next_key_nr[depth] = 0;
785
786 cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth);
787 if (! cache)
788 return 0;
789 }
790 while (depth > DISK_LEAF_NODE_LEVEL);
791
792 ih = ITEMHEAD;
793 }
794 found:
795 INFO->current_ih = ih;
796 INFO->current_item = &LEAF[ih->ih_item_location];
797#ifdef REISERDEBUG
798 printf (" new ih: key %d:%d:%d:%d version:%d\n",
799 INFO->current_ih->ih_key.k_dir_id,
800 INFO->current_ih->ih_key.k_objectid,
801 INFO->current_ih->ih_key.u.v1.k_offset,
802 INFO->current_ih->ih_key.u.v1.k_uniqueness,
803 INFO->current_ih->ih_version);
804#endif /* REISERDEBUG */
805 return 1;
806}
807
808/* preconditions: reiserfs_mount already executed, therefore
809 * INFO block is valid
810 * returns: 0 if error (errnum is set),
811 * nonzero iff we were able to find the key successfully.
812 * postconditions: on a nonzero return, the current_ih and
813 * current_item fields describe the key that equals the
814 * searched key. INFO->next_key contains the next key after
815 * the searched key.
816 * side effects: messes around with the cache.
817 */
818static int
819search_stat (__u32 dir_id, __u32 objectid)
820{
821 char *cache;
822 int depth;
823 int nr_item;
824 int i;
825 struct item_head *ih;
826#ifdef REISERDEBUG
827 printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid);
828#endif /* REISERDEBUG */
829
830 depth = INFO->tree_depth;
831 cache = ROOT;
832
833 while (depth > DISK_LEAF_NODE_LEVEL)
834 {
835 struct key *key;
836 nr_item = BLOCKHEAD (cache)->blk_nr_item;
837
838 key = KEY (cache);
839
840 for (i = 0; i < nr_item; i++)
841 {
842 if (key->k_dir_id > dir_id
843 || (key->k_dir_id == dir_id
844 && (key->k_objectid > objectid
845 || (key->k_objectid == objectid
846 && (key->u.v1.k_offset
847 | key->u.v1.k_uniqueness) > 0))))
848 break;
849 key++;
850 }
851
852#ifdef REISERDEBUG
853 printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
854#endif /* REISERDEBUG */
855 INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
856 cache = read_tree_node (DC (cache)[i].dc_block_number, --depth);
857 if (! cache)
858 return 0;
859 }
860
861 /* cache == LEAF */
862 nr_item = BLOCKHEAD (LEAF)->blk_nr_item;
863 ih = ITEMHEAD;
864 for (i = 0; i < nr_item; i++)
865 {
866 if (ih->ih_key.k_dir_id == dir_id
867 && ih->ih_key.k_objectid == objectid
868 && ih->ih_key.u.v1.k_offset == 0
869 && ih->ih_key.u.v1.k_uniqueness == 0)
870 {
871#ifdef REISERDEBUG
872 printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
873#endif /* REISERDEBUG */
874 INFO->current_ih = ih;
875 INFO->current_item = &LEAF[ih->ih_item_location];
876 return 1;
877 }
878 ih++;
879 }
880 errnum = ERR_FSYS_CORRUPT;
881 return 0;
882}
883
884int
885reiserfs_read (char *buf, int len)
886{
887 unsigned int blocksize;
888 unsigned int offset;
889 unsigned int to_read;
890 char *prev_buf = buf;
891
892#ifdef REISERDEBUG
893 printf ("reiserfs_read: filepos=%d len=%d, offset=%x:%x\n",
894 filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);
895#endif /* REISERDEBUG */
896
897 if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
898 || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1)
899 {
900 search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid);
901 goto get_next_key;
902 }
903
904 while (! errnum)
905 {
906 if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid)
907 break;
908
909 offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1;
910 blocksize = INFO->current_ih->ih_item_len;
911
912#ifdef REISERDEBUG
913 printf (" loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
914 filepos, len, offset, blocksize);
915#endif /* REISERDEBUG */
916
917 if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT)
918 && offset < blocksize)
919 {
920#ifdef REISERDEBUG
921 printf ("direct_read: offset=%d, blocksize=%d\n",
922 offset, blocksize);
923#endif /* REISERDEBUG */
924 to_read = blocksize - offset;
925 if (to_read > len)
926 to_read = len;
927
928 if (disk_read_hook != NULL)
929 {
930 disk_read_func = disk_read_hook;
931
932 block_read (INFO->blocks[DISK_LEAF_NODE_LEVEL],
933 (INFO->current_item - LEAF + offset), to_read, buf);
934
935 disk_read_func = NULL;
936 }
937 else
938 memcpy (buf, INFO->current_item + offset, to_read);
939 goto update_buf_len;
940 }
941 else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT))
942 {
943 blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
944#ifdef REISERDEBUG
945 printf ("indirect_read: offset=%d, blocksize=%d\n",
946 offset, blocksize);
947#endif /* REISERDEBUG */
948
949 while (offset < blocksize)
950 {
951 __u32 blocknr = ((__u32 *) INFO->current_item)
952 [offset >> INFO->fullblocksize_shift];
953 int blk_offset = offset & (INFO->blocksize-1);
954
955 to_read = INFO->blocksize - blk_offset;
956 if (to_read > len)
957 to_read = len;
958
959 disk_read_func = disk_read_hook;
960
961 /* Journal is only for meta data. Data blocks can be read
962 * directly without using block_read
963 */
964 devread (blocknr << INFO->blocksize_shift,
965 blk_offset, to_read, buf);
966
967 disk_read_func = NULL;
968 update_buf_len:
969 len -= to_read;
970 buf += to_read;
971 offset += to_read;
972 filepos += to_read;
973 if (len == 0)
974 goto done;
975 }
976 }
977 get_next_key:
978 next_key ();
979 }
980 done:
981 return errnum ? 0 : buf - prev_buf;
982}
983
984
985/* preconditions: reiserfs_mount already executed, therefore
986 * INFO block is valid
987 * returns: 0 if error, nonzero iff we were able to find the file successfully
988 * postconditions: on a nonzero return, INFO->fileinfo contains the info
989 * of the file we were trying to look up, filepos is 0 and filemax is
990 * the size of the file.
991 */
992int
993reiserfs_dir (char *dirname)
994{
995 struct reiserfs_de_head *de_head;
996 char *rest, ch;
997 __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
998#ifndef STAGE1_5
999 int do_possibilities = 0;
1000#endif /* ! STAGE1_5 */
1001 char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
1002 int link_count = 0;
1003 int mode;
1004
1005 dir_id = REISERFS_ROOT_PARENT_OBJECTID;
1006 objectid = REISERFS_ROOT_OBJECTID;
1007
1008 while (1)
1009 {
1010#ifdef REISERDEBUG
1011 printf ("dirname=%s\n", dirname);
1012#endif /* REISERDEBUG */
1013
1014 /* Search for the stat info first. */
1015 if (! search_stat (dir_id, objectid))
1016 return 0;
1017
1018#ifdef REISERDEBUG
1019 printf ("sd_mode=%x sd_size=%d\n",
1020 ((struct stat_data *) INFO->current_item)->sd_mode,
1021 ((struct stat_data *) INFO->current_item)->sd_size);
1022#endif /* REISERDEBUG */
1023
1024 mode = ((struct stat_data *) INFO->current_item)->sd_mode;
1025
1026 /* If we've got a symbolic link, then chase it. */
1027 if (S_ISLNK (mode))
1028 {
1029 int len;
1030 if (++link_count > MAX_LINK_COUNT)
1031 {
1032 errnum = ERR_SYMLINK_LOOP;
1033 return 0;
1034 }
1035
1036 /* Get the symlink size. */
1037 filemax = ((struct stat_data *) INFO->current_item)->sd_size;
1038
1039 /* Find out how long our remaining name is. */
1040 len = 0;
1041 while (dirname[len] && !isspace (dirname[len]))
1042 len++;
1043
1044 if (filemax + len > sizeof (linkbuf) - 1)
1045 {
1046 errnum = ERR_FILELENGTH;
1047 return 0;
1048 }
1049
1050 /* Copy the remaining name to the end of the symlink data.
1051 Note that DIRNAME and LINKBUF may overlap! */
1052 grub_memmove (linkbuf + filemax, dirname, len+1);
1053
1054 INFO->fileinfo.k_dir_id = dir_id;
1055 INFO->fileinfo.k_objectid = objectid;
1056 filepos = 0;
1057 if (! next_key ()
1058 || reiserfs_read (linkbuf, filemax) != filemax)
1059 {
1060 if (! errnum)
1061 errnum = ERR_FSYS_CORRUPT;
1062 return 0;
1063 }
1064
1065#ifdef REISERDEBUG
1066 printf ("symlink=%s\n", linkbuf);
1067#endif /* REISERDEBUG */
1068
1069 dirname = linkbuf;
1070 if (*dirname == '/')
1071 {
1072 /* It's an absolute link, so look it up in root. */
1073 dir_id = REISERFS_ROOT_PARENT_OBJECTID;
1074 objectid = REISERFS_ROOT_OBJECTID;
1075 }
1076 else
1077 {
1078 /* Relative, so look it up in our parent directory. */
1079 dir_id = parent_dir_id;
1080 objectid = parent_objectid;
1081 }
1082
1083 /* Now lookup the new name. */
1084 continue;
1085 }
1086
1087 /* if we have a real file (and we're not just printing possibilities),
1088 then this is where we want to exit */
1089
1090 if (! *dirname || isspace (*dirname))
1091 {
1092 if (! S_ISREG (mode))
1093 {
1094 errnum = ERR_BAD_FILETYPE;
1095 return 0;
1096 }
1097
1098 filepos = 0;
1099 filemax = ((struct stat_data *) INFO->current_item)->sd_size;
1100
1101 /* If this is a new stat data and size is > 4GB set filemax to
1102 * maximum
1103 */
1104 if (INFO->current_ih->ih_version == ITEM_VERSION_2
1105 && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0)
1106 filemax = 0xffffffff;
1107
1108 INFO->fileinfo.k_dir_id = dir_id;
1109 INFO->fileinfo.k_objectid = objectid;
1110 return next_key ();
1111 }
1112
1113 /* continue with the file/directory name interpretation */
1114 while (*dirname == '/')
1115 dirname++;
1116 if (! S_ISDIR (mode))
1117 {
1118 errnum = ERR_BAD_FILETYPE;
1119 return 0;
1120 }
1121 for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
1122 *rest = 0;
1123
1124# ifndef STAGE1_5
1125 if (print_possibilities && ch != '/')
1126 do_possibilities = 1;
1127# endif /* ! STAGE1_5 */
1128
1129 while (1)
1130 {
1131 char *name_end;
1132 int num_entries;
1133
1134 if (! next_key ())
1135 return 0;
1136#ifdef REISERDEBUG
1137 printf ("ih: key %d:%d:%d:%d version:%d\n",
1138 INFO->current_ih->ih_key.k_dir_id,
1139 INFO->current_ih->ih_key.k_objectid,
1140 INFO->current_ih->ih_key.u.v1.k_offset,
1141 INFO->current_ih->ih_key.u.v1.k_uniqueness,
1142 INFO->current_ih->ih_version);
1143#endif /* REISERDEBUG */
1144
1145 if (INFO->current_ih->ih_key.k_objectid != objectid)
1146 break;
1147
1148 name_end = INFO->current_item + INFO->current_ih->ih_item_len;
1149 de_head = (struct reiserfs_de_head *) INFO->current_item;
1150 num_entries = INFO->current_ih->u.ih_entry_count;
1151 while (num_entries > 0)
1152 {
1153 char *filename = INFO->current_item + de_head->deh_location;
1154 char tmp = *name_end;
1155 if ((de_head->deh_state & DEH_Visible))
1156 {
1157 int cmp;
1158 /* Directory names in ReiserFS are not null
1159 * terminated. We write a temporary 0 behind it.
1160 * NOTE: that this may overwrite the first block in
1161 * the tree cache. That doesn't hurt as long as we
1162 * don't call next_key () in between.
1163 */
1164 *name_end = 0;
1165 cmp = substring (dirname, filename);
1166 *name_end = tmp;
1167# ifndef STAGE1_5
1168 if (do_possibilities)
1169 {
1170 if (cmp <= 0)
1171 {
1172 if (print_possibilities > 0)
1173 print_possibilities = -print_possibilities;
1174 *name_end = 0;
1175 print_a_completion (filename);
1176 *name_end = tmp;
1177 }
1178 }
1179 else
1180# endif /* ! STAGE1_5 */
1181 if (cmp == 0)
1182 goto found;
1183 }
1184 /* The beginning of this name marks the end of the next name.
1185 */
1186 name_end = filename;
1187 de_head++;
1188 num_entries--;
1189 }
1190 }
1191
1192# ifndef STAGE1_5
1193 if (print_possibilities < 0)
1194 return 1;
1195# endif /* ! STAGE1_5 */
1196
1197 errnum = ERR_FILE_NOT_FOUND;
1198 *rest = ch;
1199 return 0;
1200
1201 found:
1202
1203 *rest = ch;
1204 dirname = rest;
1205
1206 parent_dir_id = dir_id;
1207 parent_objectid = objectid;
1208 dir_id = de_head->deh_dir_id;
1209 objectid = de_head->deh_objectid;
1210
1211 }
1212
1213 return 1;
1214}
1215
1216int
1217reiserfs_embed (int *start_sector, int needed_sectors)
1218{
1219 struct reiserfs_super_block super;
1220 int num_sectors;
1221
1222 if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0,
1223 sizeof (struct reiserfs_super_block), (char *) &super))
1224 return 0;
1225
1226 *start_sector = 1; /* reserve first sector for stage1 */
1227 if ((substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) <= 0
1228 || substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) <= 0)
1229 && (/* check that this is not a super block copy inside
1230 * the journal log */
1231 super.s_journal_block * super.s_blocksize
1232 > REISERFS_DISK_OFFSET_IN_BYTES))
1233 num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
1234 else
1235 num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
1236
1237 return (needed_sectors <= num_sectors);
1238}
1239#endif /* FSYS_REISERFS */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette