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