1 1.18 isaki /* $NetBSD: readufs_lfs.c,v 1.18 2024/01/07 07:58:33 isaki 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.12 itohy * Written in 1999, 2002, 2003 by ITOH Yasufumi. 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 18 1.4 itohy #ifndef USE_UFS1 19 1.4 itohy #error LFS currently requires USE_UFS1 20 1.4 itohy #endif 21 1.1 minoura 22 1.9 dsl static int get_lfs_inode(ino32_t ino, union ufs_dinode *dibuf); 23 1.1 minoura 24 1.17 christos static struct lfs32_dinode ifile_dinode; 25 1.1 minoura 26 1.1 minoura #define fsi (*ufsinfo) 27 1.1 minoura #define fsi_lfs fsi.fs_u.u_lfs 28 1.1 minoura 29 1.1 minoura /* 30 1.1 minoura * Read and check superblock. 31 1.1 minoura * If it is an LFS, save information from the superblock. 32 1.1 minoura */ 33 1.1 minoura int 34 1.11 cegger try_lfs(void) 35 1.1 minoura { 36 1.2 minoura struct ufs_info *ufsinfo = &ufs_info; 37 1.1 minoura struct dlfs sblk, sblk2; 38 1.1 minoura struct dlfs *s = &sblk; 39 1.4 itohy daddr_t sbpos; 40 1.2 minoura int fsbshift; 41 1.1 minoura 42 1.1 minoura #ifdef DEBUG_WITH_STDIO 43 1.1 minoura printf("trying LFS\n"); 44 1.1 minoura #endif 45 1.2 minoura sbpos = btodb(LFS_LABELPAD); 46 1.2 minoura 47 1.1 minoura /* read primary superblock */ 48 1.2 minoura for (;;) { 49 1.2 minoura #ifdef DEBUG_WITH_STDIO 50 1.4 itohy printf("LFS: reading primary sblk at: 0x%x\n", (unsigned)sbpos); 51 1.2 minoura #endif 52 1.2 minoura RAW_READ(&sblk, sbpos, sizeof sblk); 53 1.1 minoura 54 1.1 minoura #ifdef DEBUG_WITH_STDIO 55 1.2 minoura printf("LFS: sblk: magic: 0x%x, version: %d\n", 56 1.2 minoura sblk.dlfs_magic, sblk.dlfs_version); 57 1.1 minoura #endif 58 1.1 minoura 59 1.2 minoura if (sblk.dlfs_magic != LFS_MAGIC) 60 1.2 minoura return 1; 61 1.2 minoura 62 1.2 minoura #ifdef DEBUG_WITH_STDIO 63 1.2 minoura printf("LFS: bsize %d, fsize %d, bshift %d, blktodb %d, fsbtodb %d, inopf %d, inopb %d\n", 64 1.2 minoura sblk.dlfs_bsize, sblk.dlfs_fsize, 65 1.2 minoura sblk.dlfs_bshift, sblk.dlfs_blktodb, sblk.dlfs_fsbtodb, 66 1.2 minoura sblk.dlfs_inopf, sblk.dlfs_inopb); 67 1.2 minoura #endif 68 1.2 minoura if ((fsi_lfs.version = sblk.dlfs_version) == 1) { 69 1.2 minoura fsbshift = 0; 70 1.2 minoura break; 71 1.2 minoura } else { 72 1.3 fvdl daddr_t sbpos1; 73 1.2 minoura #if 0 74 1.2 minoura fsbshift = sblk.dlfs_bshift - sblk.dlfs_blktodb + sblk.dlfs_fsbtodb - DEV_BSHIFT; 75 1.2 minoura #endif 76 1.2 minoura fsbshift = sblk.dlfs_fsbtodb; 77 1.2 minoura sbpos1 = sblk.dlfs_sboffs[0] << fsbshift; 78 1.2 minoura if (sbpos == sbpos1) 79 1.2 minoura break; 80 1.2 minoura #ifdef DEBUG_WITH_STDIO 81 1.2 minoura printf("LFS: correcting primary sblk location\n"); 82 1.2 minoura #endif 83 1.2 minoura sbpos = sbpos1; 84 1.2 minoura } 85 1.2 minoura } 86 1.1 minoura 87 1.1 minoura #ifdef DEBUG_WITH_STDIO 88 1.2 minoura printf("fsbshift: %d\n", fsbshift); 89 1.1 minoura printf("sboff[1]: %d\n", sblk.dlfs_sboffs[1]); 90 1.1 minoura #endif 91 1.1 minoura 92 1.1 minoura if (sblk.dlfs_sboffs[1] > 0) { 93 1.2 minoura #ifdef DEBUG_WITH_STDIO 94 1.2 minoura printf("LFS: reading secondary sblk at: 0x%x\n", 95 1.2 minoura sblk.dlfs_sboffs[1] << fsbshift); 96 1.2 minoura #endif 97 1.1 minoura /* read secondary superblock */ 98 1.4 itohy RAW_READ(&sblk2, (daddr_t) sblk.dlfs_sboffs[1] << fsbshift, 99 1.4 itohy sizeof sblk2); 100 1.1 minoura 101 1.1 minoura #ifdef DEBUG_WITH_STDIO 102 1.1 minoura printf("LFS: sblk2: magic: 0x%x, version: %d\n", 103 1.1 minoura sblk2.dlfs_magic, sblk2.dlfs_version); 104 1.1 minoura #endif 105 1.1 minoura 106 1.2 minoura if (sblk2.dlfs_magic == LFS_MAGIC) { 107 1.2 minoura if (fsi_lfs.version == 1) { 108 1.16 christos if (sblk.dlfs_inopf > sblk2.dlfs_inopf) 109 1.2 minoura s = &sblk2; 110 1.2 minoura } else { 111 1.2 minoura if (sblk.dlfs_serial > sblk2.dlfs_serial) 112 1.2 minoura s = &sblk2; 113 1.2 minoura } 114 1.2 minoura } 115 1.1 minoura } 116 1.1 minoura 117 1.1 minoura /* This partition looks like an LFS. */ 118 1.1 minoura fsi.get_inode = get_lfs_inode; 119 1.2 minoura /* 120 1.2 minoura * version 1: disk addr is in disk sector --- no shifting 121 1.2 minoura * version 2: disk addr is in fragment 122 1.2 minoura */ 123 1.2 minoura fsi.fsbtodb = fsbshift; 124 1.1 minoura 125 1.1 minoura /* Get information from the superblock. */ 126 1.1 minoura fsi.bsize = s->dlfs_bsize; 127 1.1 minoura fsi.nindir = s->dlfs_nindir; 128 1.2 minoura fsi_lfs.idaddr = s->dlfs_idaddr; 129 1.2 minoura #if 0 130 1.2 minoura fsi_lfs.ibsize = (fsi_lfs.version == 1) ? s->dlfs_bsize : s->dlfs_fsize; 131 1.2 minoura #else /* simplify calculation to reduce code size */ 132 1.15 wiz /* use fsi.bsize (larger than needed for v2, but probably no harm) */ 133 1.2 minoura #endif 134 1.1 minoura 135 1.2 minoura /* 136 1.2 minoura * version 1: number of inode per block 137 1.2 minoura * version 2: number of inode per fragment (but in dlfs_inopb) 138 1.2 minoura */ 139 1.1 minoura fsi_lfs.inopb = s->dlfs_inopb; 140 1.2 minoura 141 1.1 minoura fsi_lfs.ifpb = s->dlfs_ifpb; 142 1.2 minoura fsi_lfs.ioffset = s->dlfs_cleansz + s->dlfs_segtabsz; 143 1.1 minoura 144 1.1 minoura /* ifile is always used to look-up other inodes, so keep its inode. */ 145 1.4 itohy if (get_lfs_inode(LFS_IFILE_INUM, (union ufs_dinode *)&ifile_dinode)) 146 1.1 minoura return 1; /* OOPS, failed to find inode of ifile! */ 147 1.1 minoura 148 1.1 minoura fsi.fstype = UFSTYPE_LFS; 149 1.1 minoura 150 1.1 minoura return 0; 151 1.1 minoura } 152 1.1 minoura 153 1.1 minoura /* 154 1.1 minoura * Get inode from disk. 155 1.1 minoura */ 156 1.1 minoura static int 157 1.10 dsl get_lfs_inode(ino32_t ino, union ufs_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.17 christos struct lfs32_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.18 isaki ufs_read((union ufs_dinode *) &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.17 christos : ((IFILE32 *) buf + i)->if_daddr; 180 1.1 minoura } 181 1.1 minoura #ifdef DEBUG_WITH_STDIO 182 1.4 itohy printf("LFS(%d): daddr: %d\n", ino, (int) 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.17 christos di = (struct lfs32_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.5 itohy printf("LFS: dinode(%d): mode 0%o, nlink %d, inumber %d, size %d, uid %d, db[0] %d\n", 210 1.1 minoura ino, di->di_mode, di->di_nlink, di->di_inumber, 211 1.5 itohy (int) di->di_size, di->di_uid, di->di_db[0]); 212 1.4 itohy #endif 213 1.4 itohy 214 1.4 itohy #if 0 /* currently UFS1 only */ 215 1.4 itohy #if defined(USE_UFS1) && defined(USE_UFS2) 216 1.4 itohy /* XXX for DI_SIZE() macro */ 217 1.4 itohy if (ufsinfo->ufstype != UFSTYPE_UFS1) 218 1.4 itohy di->di1.di_size = di->si2.di_size; 219 1.4 itohy #endif 220 1.1 minoura #endif 221 1.1 minoura 222 1.17 christos dibuf->dil32 = *di; 223 1.1 minoura 224 1.1 minoura return 0; 225 1.1 minoura } 226