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