Home | History | Annotate | Line # | Download | only in boot_ufs
readufs_lfs.c revision 1.4.2.2
      1  1.4.2.1    skrll /*	$NetBSD: readufs_lfs.c,v 1.4.2.2 2004/09/18 14:42:36 skrll Exp $	*/
      2  1.4.2.1    skrll /*	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.4.2.1    skrll  * 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.4    itohy static int get_lfs_inode __P((ino_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.1  minoura 	ino_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.4.2.1    skrll 	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.4.2.1    skrll 		(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