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