readufs_lfs.c revision 1.1 1 /* $Id: readufs_lfs.c,v 1.1 2001/09/27 10:14:50 minoura Exp $ */
2
3 /*
4 * FS specific support for 4.4BSD Log-structured Filesystem
5 *
6 * Written by ITOH, Yasufumi (itohy (at) netbsd.org).
7 * Public domain.
8 *
9 * Intended to be used for boot programs (first stage).
10 * DON'T ADD ANY FANCY FEATURE. THIS SHALL BE COMPACT.
11 */
12
13 #include <sys/types.h>
14 #include <sys/param.h>
15 #include <sys/mount.h>
16 #include <ufs/ufs/dinode.h>
17 #include <ufs/lfs/lfs.h>
18
19 #include "readufs.h"
20
21 static int get_lfs_inode __P((ino_t ino, struct dinode *dibuf));
22
23 static struct dinode ifile_dinode;
24
25 #define fsi (*ufsinfo)
26 #define fsi_lfs fsi.fs_u.u_lfs
27
28 /*
29 * Read and check superblock.
30 * If it is an LFS, save information from the superblock.
31 */
32 int
33 try_lfs()
34 {
35 struct ufs_info *ufsinfo = &ufs_info;
36 struct dlfs sblk, sblk2;
37 struct dlfs *s = &sblk;
38
39 #ifdef DEBUG_WITH_STDIO
40 printf("trying LFS\n");
41 #endif
42 /* read primary superblock */
43 RAW_READ(&sblk, btodb(LFS_LABELPAD), sizeof sblk);
44
45 #ifdef DEBUG_WITH_STDIO
46 printf("LFS: sblk: magic: 0x%x, version: %d\n",
47 sblk.dlfs_magic, sblk.dlfs_version);
48 #endif
49
50 if (sblk.dlfs_magic != LFS_MAGIC)
51 return 1;
52
53 #ifdef DEBUG_WITH_STDIO
54 printf("sboff[1]: %d\n", sblk.dlfs_sboffs[1]);
55 #endif
56
57 if (sblk.dlfs_sboffs[1] > 0) {
58 /* read secondary superblock */
59 RAW_READ(&sblk2,
60 (unsigned int) sblk.dlfs_sboffs[1], sizeof sblk2);
61
62 #ifdef DEBUG_WITH_STDIO
63 printf("LFS: sblk2: magic: 0x%x, version: %d\n",
64 sblk2.dlfs_magic, sblk2.dlfs_version);
65 #endif
66
67 if (sblk2.dlfs_magic == LFS_MAGIC &&
68 sblk.dlfs_tstamp > sblk2.dlfs_tstamp)
69 s = &sblk2;
70 }
71
72 /* This partition looks like an LFS. */
73 fsi.get_inode = get_lfs_inode;
74 /* Disk addr in inode is in disk sector --- no shifting. */
75 fsi.iblkshift = 0;
76
77 /* Get information from the superblock. */
78 fsi.bsize = s->dlfs_bsize;
79 fsi.fsbtodb = s->dlfs_fsbtodb;
80 fsi.nindir = s->dlfs_nindir;
81
82 fsi_lfs.idaddr = s->dlfs_idaddr;
83 fsi_lfs.inopb = s->dlfs_inopb;
84 fsi_lfs.ifpb = s->dlfs_ifpb;
85 fsi_lfs.cleansz = s->dlfs_cleansz;
86 fsi_lfs.segtabsz = s->dlfs_segtabsz;
87
88 /* ifile is always used to look-up other inodes, so keep its inode. */
89 if (get_lfs_inode(LFS_IFILE_INUM, &ifile_dinode))
90 return 1; /* OOPS, failed to find inode of ifile! */
91
92 fsi.fstype = UFSTYPE_LFS;
93
94 return 0;
95 }
96
97 /*
98 * Get inode from disk.
99 */
100 static int
101 get_lfs_inode(ino, dibuf)
102 ino_t ino;
103 struct dinode *dibuf;
104 {
105 struct ufs_info *ufsinfo = &ufs_info;
106 ufs_daddr_t daddr;
107 char *buf = alloca(fsi.bsize);
108 struct dinode *di;
109 int cnt;
110
111 /* Get fs block which contains the specified inode. */
112 if (ino == LFS_IFILE_INUM)
113 daddr = fsi_lfs.idaddr;
114 else {
115 #ifdef DEBUG_WITH_STDIO
116 printf("LFS: ino: %d\nifpb: %d, cleansz: %d, segtabsz: %d, bsize: %d\n",
117 ino, fsi_lfs.ifpb, fsi_lfs.cleansz, fsi_lfs.segtabsz, fsi.bsize);
118 #endif
119 ufs_read(&ifile_dinode, buf,
120 ino / fsi_lfs.ifpb + fsi_lfs.cleansz +
121 fsi_lfs.segtabsz,
122 fsi.bsize);
123 daddr = ((IFILE *) buf + ino % fsi_lfs.ifpb)->if_daddr;
124 }
125 #ifdef DEBUG_WITH_STDIO
126 printf("LFS(%d): daddr: %d\n", ino, daddr);
127 #endif
128
129 if (daddr == LFS_UNUSED_DADDR)
130 return 1;
131
132 /* Read the inode block. */
133 RAW_READ(buf, (unsigned int) daddr, fsi.bsize);
134
135 /* Search for the inode. */
136 cnt = fsi_lfs.inopb;
137 di = (struct dinode *) buf + (cnt - 1);
138
139 for ( ; cnt--; di--)
140 if (di->di_inumber == ino)
141 goto found;
142 /* not found */
143 return 1;
144
145 found:
146 #ifdef DEBUG_WITH_STDIO
147 printf("LFS: dinode(%d): mode 0%o, nlink %d, inumber %d, size %d, uid %d, gid %d, db[0] %d\n",
148 ino, di->di_mode, di->di_nlink, di->di_inumber,
149 (int)di->di_size, di->di_uid, di->di_gid, di->di_db[0]);
150 #endif
151
152 *dibuf = *di;
153
154 return 0;
155 }
156