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