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