readufs_lfs.c revision 1.3 1 1.2 minoura /* from Id: readufs_lfs.c,v 1.5 2002/01/26 16:26:44 itohy Exp */
2 1.1 minoura
3 1.1 minoura /*
4 1.1 minoura * FS specific support for 4.4BSD Log-structured Filesystem
5 1.1 minoura *
6 1.1 minoura * Written by ITOH, Yasufumi (itohy (at) netbsd.org).
7 1.1 minoura * Public domain.
8 1.1 minoura *
9 1.1 minoura * Intended to be used for boot programs (first stage).
10 1.1 minoura * DON'T ADD ANY FANCY FEATURE. THIS SHALL BE COMPACT.
11 1.1 minoura */
12 1.1 minoura
13 1.1 minoura #include <sys/types.h>
14 1.1 minoura #include <sys/param.h>
15 1.1 minoura #include <sys/mount.h>
16 1.1 minoura #include <ufs/ufs/dinode.h>
17 1.1 minoura #include <ufs/lfs/lfs.h>
18 1.1 minoura
19 1.1 minoura #include "readufs.h"
20 1.1 minoura
21 1.1 minoura static int get_lfs_inode __P((ino_t ino, struct dinode *dibuf));
22 1.1 minoura
23 1.1 minoura static struct dinode ifile_dinode;
24 1.1 minoura
25 1.1 minoura #define fsi (*ufsinfo)
26 1.1 minoura #define fsi_lfs fsi.fs_u.u_lfs
27 1.1 minoura
28 1.1 minoura /*
29 1.1 minoura * Read and check superblock.
30 1.1 minoura * If it is an LFS, save information from the superblock.
31 1.1 minoura */
32 1.1 minoura int
33 1.1 minoura try_lfs()
34 1.1 minoura {
35 1.2 minoura struct ufs_info *ufsinfo = &ufs_info;
36 1.1 minoura struct dlfs sblk, sblk2;
37 1.1 minoura struct dlfs *s = &sblk;
38 1.3 fvdl daddr_t sbpos;
39 1.2 minoura int fsbshift;
40 1.1 minoura
41 1.1 minoura #ifdef DEBUG_WITH_STDIO
42 1.1 minoura printf("trying LFS\n");
43 1.1 minoura #endif
44 1.2 minoura sbpos = btodb(LFS_LABELPAD);
45 1.2 minoura
46 1.1 minoura /* read primary superblock */
47 1.2 minoura for (;;) {
48 1.2 minoura #ifdef DEBUG_WITH_STDIO
49 1.2 minoura printf("LFS: reading primary sblk at: 0x%x\n", sbpos);
50 1.2 minoura #endif
51 1.2 minoura RAW_READ(&sblk, sbpos, sizeof sblk);
52 1.1 minoura
53 1.1 minoura #ifdef DEBUG_WITH_STDIO
54 1.2 minoura printf("LFS: sblk: magic: 0x%x, version: %d\n",
55 1.2 minoura sblk.dlfs_magic, sblk.dlfs_version);
56 1.1 minoura #endif
57 1.1 minoura
58 1.2 minoura if (sblk.dlfs_magic != LFS_MAGIC)
59 1.2 minoura return 1;
60 1.2 minoura
61 1.2 minoura #ifdef DEBUG_WITH_STDIO
62 1.2 minoura printf("LFS: bsize %d, fsize %d, bshift %d, blktodb %d, fsbtodb %d, inopf %d, inopb %d\n",
63 1.2 minoura sblk.dlfs_bsize, sblk.dlfs_fsize,
64 1.2 minoura sblk.dlfs_bshift, sblk.dlfs_blktodb, sblk.dlfs_fsbtodb,
65 1.2 minoura sblk.dlfs_inopf, sblk.dlfs_inopb);
66 1.2 minoura #endif
67 1.2 minoura if ((fsi_lfs.version = sblk.dlfs_version) == 1) {
68 1.2 minoura fsbshift = 0;
69 1.2 minoura break;
70 1.2 minoura } else {
71 1.3 fvdl daddr_t sbpos1;
72 1.2 minoura #if 0
73 1.2 minoura fsbshift = sblk.dlfs_bshift - sblk.dlfs_blktodb + sblk.dlfs_fsbtodb - DEV_BSHIFT;
74 1.2 minoura #endif
75 1.2 minoura fsbshift = sblk.dlfs_fsbtodb;
76 1.2 minoura sbpos1 = sblk.dlfs_sboffs[0] << fsbshift;
77 1.2 minoura if (sbpos == sbpos1)
78 1.2 minoura break;
79 1.2 minoura #ifdef DEBUG_WITH_STDIO
80 1.2 minoura printf("LFS: correcting primary sblk location\n");
81 1.2 minoura #endif
82 1.2 minoura sbpos = sbpos1;
83 1.2 minoura }
84 1.2 minoura }
85 1.1 minoura
86 1.1 minoura #ifdef DEBUG_WITH_STDIO
87 1.2 minoura printf("fsbshift: %d\n", fsbshift);
88 1.1 minoura printf("sboff[1]: %d\n", sblk.dlfs_sboffs[1]);
89 1.1 minoura #endif
90 1.1 minoura
91 1.1 minoura if (sblk.dlfs_sboffs[1] > 0) {
92 1.2 minoura #ifdef DEBUG_WITH_STDIO
93 1.2 minoura printf("LFS: reading secondary sblk at: 0x%x\n",
94 1.2 minoura sblk.dlfs_sboffs[1] << fsbshift);
95 1.2 minoura #endif
96 1.1 minoura /* read secondary superblock */
97 1.2 minoura RAW_READ(&sblk2, sblk.dlfs_sboffs[1] << fsbshift, sizeof sblk2);
98 1.1 minoura
99 1.1 minoura #ifdef DEBUG_WITH_STDIO
100 1.1 minoura printf("LFS: sblk2: magic: 0x%x, version: %d\n",
101 1.1 minoura sblk2.dlfs_magic, sblk2.dlfs_version);
102 1.1 minoura #endif
103 1.1 minoura
104 1.2 minoura if (sblk2.dlfs_magic == LFS_MAGIC) {
105 1.2 minoura if (fsi_lfs.version == 1) {
106 1.2 minoura if (sblk.dlfs_otstamp > sblk2.dlfs_otstamp)
107 1.2 minoura s = &sblk2;
108 1.2 minoura } else {
109 1.2 minoura if (sblk.dlfs_serial > sblk2.dlfs_serial)
110 1.2 minoura s = &sblk2;
111 1.2 minoura }
112 1.2 minoura }
113 1.1 minoura }
114 1.1 minoura
115 1.1 minoura /* This partition looks like an LFS. */
116 1.1 minoura fsi.get_inode = get_lfs_inode;
117 1.2 minoura /*
118 1.2 minoura * version 1: disk addr is in disk sector --- no shifting
119 1.2 minoura * version 2: disk addr is in fragment
120 1.2 minoura */
121 1.2 minoura fsi.fsbtodb = fsbshift;
122 1.1 minoura
123 1.1 minoura /* Get information from the superblock. */
124 1.1 minoura fsi.bsize = s->dlfs_bsize;
125 1.1 minoura fsi.nindir = s->dlfs_nindir;
126 1.2 minoura fsi_lfs.idaddr = s->dlfs_idaddr;
127 1.2 minoura #if 0
128 1.2 minoura fsi_lfs.ibsize = (fsi_lfs.version == 1) ? s->dlfs_bsize : s->dlfs_fsize;
129 1.2 minoura #else /* simplify calculation to reduce code size */
130 1.2 minoura /* use fsi.bsize (larger then needed for v2, but probably no harm) */
131 1.2 minoura #endif
132 1.1 minoura
133 1.2 minoura /*
134 1.2 minoura * version 1: number of inode per block
135 1.2 minoura * version 2: number of inode per fragment (but in dlfs_inopb)
136 1.2 minoura */
137 1.1 minoura fsi_lfs.inopb = s->dlfs_inopb;
138 1.2 minoura
139 1.1 minoura fsi_lfs.ifpb = s->dlfs_ifpb;
140 1.2 minoura fsi_lfs.ioffset = s->dlfs_cleansz + s->dlfs_segtabsz;
141 1.1 minoura
142 1.1 minoura /* ifile is always used to look-up other inodes, so keep its inode. */
143 1.1 minoura if (get_lfs_inode(LFS_IFILE_INUM, &ifile_dinode))
144 1.1 minoura return 1; /* OOPS, failed to find inode of ifile! */
145 1.1 minoura
146 1.1 minoura fsi.fstype = UFSTYPE_LFS;
147 1.1 minoura
148 1.1 minoura return 0;
149 1.1 minoura }
150 1.1 minoura
151 1.1 minoura /*
152 1.1 minoura * Get inode from disk.
153 1.1 minoura */
154 1.1 minoura static int
155 1.1 minoura get_lfs_inode(ino, dibuf)
156 1.1 minoura ino_t ino;
157 1.1 minoura struct dinode *dibuf;
158 1.1 minoura {
159 1.1 minoura struct ufs_info *ufsinfo = &ufs_info;
160 1.3 fvdl daddr_t daddr;
161 1.1 minoura char *buf = alloca(fsi.bsize);
162 1.2 minoura struct dinode *di, *diend;
163 1.2 minoura int i;
164 1.1 minoura
165 1.1 minoura /* Get fs block which contains the specified inode. */
166 1.1 minoura if (ino == LFS_IFILE_INUM)
167 1.1 minoura daddr = fsi_lfs.idaddr;
168 1.1 minoura else {
169 1.1 minoura #ifdef DEBUG_WITH_STDIO
170 1.2 minoura printf("LFS: ino: %d\nifpb: %d, bsize: %d\n",
171 1.2 minoura ino, fsi_lfs.ifpb, fsi.bsize);
172 1.1 minoura #endif
173 1.1 minoura ufs_read(&ifile_dinode, buf,
174 1.2 minoura ino / fsi_lfs.ifpb + fsi_lfs.ioffset,
175 1.1 minoura fsi.bsize);
176 1.2 minoura i = ino % fsi_lfs.ifpb;
177 1.2 minoura daddr = (fsi_lfs.version == 1) ?
178 1.2 minoura ((IFILE_V1 *) buf + i)->if_daddr
179 1.2 minoura : ((IFILE *) buf + i)->if_daddr;
180 1.1 minoura }
181 1.1 minoura #ifdef DEBUG_WITH_STDIO
182 1.3 fvdl printf("LFS(%d): daddr: %lld\n", ino, (long long)daddr);
183 1.1 minoura #endif
184 1.1 minoura
185 1.1 minoura if (daddr == LFS_UNUSED_DADDR)
186 1.1 minoura return 1;
187 1.1 minoura
188 1.1 minoura /* Read the inode block. */
189 1.2 minoura RAW_READ(buf, daddr << fsi.fsbtodb,
190 1.2 minoura #if 0
191 1.2 minoura fsi_lfs.ibsize
192 1.2 minoura #else /* simplify calculation to reduce code size */
193 1.2 minoura fsi.bsize
194 1.2 minoura #endif
195 1.2 minoura );
196 1.1 minoura
197 1.1 minoura /* Search for the inode. */
198 1.2 minoura di = (struct dinode *) buf;
199 1.2 minoura diend = di + fsi_lfs.inopb;
200 1.1 minoura
201 1.2 minoura for ( ; di < diend; di++)
202 1.1 minoura if (di->di_inumber == ino)
203 1.1 minoura goto found;
204 1.1 minoura /* not found */
205 1.1 minoura return 1;
206 1.1 minoura
207 1.1 minoura found:
208 1.1 minoura #ifdef DEBUG_WITH_STDIO
209 1.1 minoura printf("LFS: dinode(%d): mode 0%o, nlink %d, inumber %d, size %d, uid %d, gid %d, db[0] %d\n",
210 1.1 minoura ino, di->di_mode, di->di_nlink, di->di_inumber,
211 1.1 minoura (int)di->di_size, di->di_uid, di->di_gid, di->di_db[0]);
212 1.1 minoura #endif
213 1.1 minoura
214 1.1 minoura *dibuf = *di;
215 1.1 minoura
216 1.1 minoura return 0;
217 1.1 minoura }
218