Date: Thu, 9 Mar 2006 05:39:18 GMT From: Kip Macy <kmacy@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 93014 for review Message-ID: <200603090539.k295dImG062022@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=93014 Change 93014 by kmacy@kmacy_storage:sun4v_work on 2006/03/09 05:38:25 hacked up loader for booting off of solaris' UFS Affected files ... .. //depot/projects/kmacy_sun4v/src/lib/libstand/ufs.c#3 edit Differences ... ==== //depot/projects/kmacy_sun4v/src/lib/libstand/ufs.c#3 (text+ko) ==== @@ -81,6 +81,7 @@ #include <sys/param.h> #include <sys/disklabel.h> #include <sys/time.h> +#include <sys/stddef.h> #include <ufs/ufs/dinode.h> #include <ufs/ufs/dir.h> #include <ufs/ffs/fs.h> @@ -110,6 +111,134 @@ ufs_readdir }; +typedef int32_t daddr32_t; +typedef int32_t time32_t; +typedef unsigned char uchar_t; +#define MAXCSBUFS 32 +typedef struct _quad { int val[2]; } squad_t; +struct solaris_fs { + uint32_t fs_link; /* linked list of file systems */ + uint32_t fs_rolled; /* logging only: fs fully rolled */ + daddr32_t fs_sblkno; /* addr of super-block in filesys */ + daddr32_t fs_cblkno; /* offset of cyl-block in filesys */ + daddr32_t fs_iblkno; /* offset of inode-blocks in filesys */ + daddr32_t fs_dblkno; /* offset of first data after cg */ + int32_t fs_cgoffset; /* cylinder group offset in cylinder */ + int32_t fs_cgmask; /* used to calc mod fs_ntrak */ + time32_t fs_time; /* last time written */ + int32_t fs_size; /* number of blocks in fs */ + int32_t fs_dsize; /* number of data blocks in fs */ + int32_t fs_ncg; /* number of cylinder groups */ + int32_t fs_bsize; /* size of basic blocks in fs */ + int32_t fs_fsize; /* size of frag blocks in fs */ + int32_t fs_frag; /* number of frags in a block in fs */ +/* these are configuration parameters */ + int32_t fs_minfree; /* minimum percentage of free blocks */ + int32_t fs_rotdelay; /* num of ms for optimal next block */ + int32_t fs_rps; /* disk revolutions per second */ +/* these fields can be computed from the others */ + int32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ + int32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ + int32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ + int32_t fs_fshift; /* ``numfrags'' calc number of frags */ +/* these are configuration parameters */ + int32_t fs_maxcontig; /* max number of contiguous blks */ + int32_t fs_maxbpg; /* max number of blks per cyl group */ +/* these fields can be computed from the others */ + int32_t fs_fragshift; /* block to frag shift */ + int32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ + int32_t fs_sbsize; /* actual size of super block */ + int32_t fs_csmask; /* csum block offset */ + int32_t fs_csshift; /* csum block number */ + int32_t fs_nindir; /* value of NINDIR */ + int32_t fs_inopb; /* value of INOPB */ + int32_t fs_nspf; /* value of NSPF */ +/* yet another configuration parameter */ + int32_t fs_optim; /* optimization preference, see below */ +/* these fields are derived from the hardware */ + /* USL SVR4 compatibility */ +#ifdef _LITTLE_ENDIAN + /* + * USL SVR4 compatibility + * + * There was a significant divergence here between Solaris and + * SVR4 for x86. By swapping these two members in the superblock, + * we get read-only compatibility of SVR4 filesystems. Otherwise + * there would be no compatibility. This change was introduced + * during bootstrapping of Solaris on x86. By making this ifdef'ed + * on byte order, we provide ongoing compatibility across all + * platforms with the same byte order, the highest compatibility + * that can be achieved. + */ + int32_t fs_state; /* file system state time stamp */ +#else + int32_t fs_npsect; /* # sectors/track including spares */ +#endif + int32_t fs_si; /* summary info state - lufs only */ + int32_t fs_trackskew; /* sector 0 skew, per track */ +/* a unique id for this filesystem (currently unused and unmaintained) */ +/* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */ +/* Neither of those fields is used in the Tahoe code right now but */ +/* there could be problems if they are. */ + int32_t fs_id[2]; /* file system id */ +/* sizes determined by number of cylinder groups and their sizes */ + daddr32_t fs_csaddr; /* blk addr of cyl grp summary area */ + int32_t fs_cssize; /* size of cyl grp summary area */ + int32_t fs_cgsize; /* cylinder group size */ +/* these fields are derived from the hardware */ + int32_t fs_ntrak; /* tracks per cylinder */ + int32_t fs_nsect; /* sectors per track */ + int32_t fs_spc; /* sectors per cylinder */ +/* this comes from the disk driver partitioning */ + int32_t fs_ncyl; /* cylinders in file system */ +/* these fields can be computed from the others */ + int32_t fs_cpg; /* cylinders per group */ + int32_t fs_ipg; /* inodes per group */ + int32_t fs_fpg; /* blocks per group * fs_frag */ +/* this data must be re-computed after crashes */ + struct csum fs_cstotal; /* cylinder summary information */ +/* these fields are cleared at mount time */ + char fs_fmod; /* super block modified flag */ + char fs_clean; /* file system state flag */ + char fs_ronly; /* mounted read-only flag */ + char fs_flags; /* largefiles flag, etc. */ + char fs_fsmnt[512]; /* name mounted on */ +/* these fields retain the current block allocation info */ + int32_t fs_cgrotor; /* last cg searched */ + /* + * The following used to be fs_csp[MAXCSBUFS]. It was not + * used anywhere except in old utilities. We removed this + * in 5.6 and expect fs_u.fs_csp to be used instead. + * We no longer limit fs_cssize based on MAXCSBUFS. + */ + union { /* fs_cs (csum) info */ + uint32_t fs_csp_pad[MAXCSBUFS]; + struct csum *fs_csp; + } fs_u; + int32_t fs_cpc; /* cyl per cycle in postbl */ + short fs_opostbl[16*8]; /* old rotation block list head */ + int32_t fs_sparecon[51]; /* reserved for future constants */ + int32_t fs_version; /* minor version of MTB ufs */ + int32_t fs_logbno; /* block # of embedded log */ + int32_t fs_reclaim; /* reclaim open, deleted files */ + int32_t fs_sparecon2; /* reserved for future constant */ +#ifdef _LITTLE_ENDIAN + /* USL SVR4 compatibility */ + int32_t fs_npsect; /* # sectors/track including spares */ +#else + int32_t fs_state; /* file system state time stamp */ +#endif + squad_t fs_qbmask; /* ~fs_bmask - for use with quad size */ + squad_t fs_qfmask; /* ~fs_fmask - for use with quad size */ + int32_t fs_postblformat; /* format of positional layout tables */ + int32_t fs_nrpos; /* number of rotaional positions */ + int32_t fs_postbloff; /* (short) rotation block list head */ + int32_t fs_rotbloff; /* (uchar_t) blocks for each rotation */ + int32_t fs_magic; /* magic number */ + uchar_t fs_space[1]; /* list of blocks for each rotation */ +/* actually longer */ +}; + /* * In-core open file. */ @@ -142,7 +271,49 @@ static int buf_write_file(struct open_file *, char *, size_t *); static int search_directory(char *, struct open_file *, ino_t *); + /* + * Search a directory for a name and return its + * i_number. + */ + +static void hdump(uint8_t *bp, int size) +{ + int i; + int f = 1; + uint8_t tmp[17]; + + tmp[16] = '\0'; + + for (i=0; i<size; i++) { + uint8_t c; + + c = bp[i]; + if (f) { + printf("%04x : ", i); + f=0; + } + printf(" 0x%02x", c); + + if (c<32 || c>126) c='.'; + tmp[i&15] = c; + + if ((i&15)==15) { + printf(" : %s\n", tmp); + f=1; + } + } + if (!f) { + for (i=(i&15); i<16; i++) { + printf(" --"); + tmp[i]=' '; + } + printf(" : %s\n", tmp); + } +} + + +/* * Read a new inode into a file structure. */ static int @@ -159,6 +330,11 @@ if (fs == NULL) panic("fs == NULL"); + printf("read_inode : inumber=0x%llx fsba=0x%llx dba=0x%llx\n", + (uint64_t)inumber, + (uint64_t)ino_to_fsba(fs, inumber), + (uint64_t)fsbtodb(fs, ino_to_fsba(fs, inumber)) ); + /* * Read inode and save it. */ @@ -327,6 +503,7 @@ file_block = lblkno(fs, fp->f_seekp); block_size = sblksize(fs, DIP(fp, di_size), file_block); + rc = block_map(f, file_block, &disk_block); if (rc) return (rc); @@ -393,6 +570,7 @@ struct file *fp = (struct file *)f->f_fsdata; struct fs *fs = fp->f_fs; long off; + size_t file_size; ufs_lbn_t file_block; ufs2_daddr_t disk_block; size_t block_size; @@ -400,8 +578,24 @@ off = blkoff(fs, fp->f_seekp); file_block = lblkno(fs, fp->f_seekp); - block_size = sblksize(fs, DIP(fp, di_size), file_block); + file_size = DIP(fp, di_size); + block_size = sblksize(fs, file_size, file_block); +#if 0 + printf("buf_read_file: fs->f_seekp=0x%llx : off=0x%lx : file_block=0x%lx : block_size=0x%llx\n", + (uint64_t)fp->f_seekp, off, file_block, (uint64_t)block_size); + printf("\tfile_size=0x%llx : fs_bsize=0x%llx\n", (uint64_t)file_size, (uint64_t)fs->fs_bsize); + printf("fragroundup[blkoff[%lld]=%lld]=%lld\n", file_size, blkoff(fs, file_size), + fragroundup(fs, blkoff(fs, file_size))); + printf("fs->fs_qbmask=%llx fs->fs_qfmask=%llx fs->fs_fmask=%lx\n", fs->fs_qbmask, fs->fs_qfmask, fs->fs_fmask); +#endif + if (block_size > 8192) { + block_size=8192; + printf("FORCE ROUND block_size\n"); + } +#if 0 + printf("\tfp->f_buf_blkno = 0x%lx\n", fp->f_buf_blkno); +#endif if (file_block != fp->f_buf_blkno) { if (fp->f_buf == (char *)0) fp->f_buf = malloc(fs->fs_bsize); @@ -409,17 +603,27 @@ rc = block_map(f, file_block, &disk_block); if (rc) return (rc); - +#if 0 + printf("\tblock_map : disk_block = 0x%lx\n", disk_block); +#endif if (disk_block == 0) { bzero(fp->f_buf, block_size); fp->f_buf_size = block_size; } else { twiddle(); +#if 0 + printf("\tcalling dev_strategy for block read fsbtodb[0x%lx]=0x%lx\n", + disk_block, fsbtodb(fs, disk_block)); +#endif rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsbtodb(fs, disk_block), block_size, fp->f_buf, &fp->f_buf_size); if (rc) return (rc); +#if 0 + printf("\treturned from block read with 0x%lx bytes\n", fp->f_buf_size); + hdump(fp->f_buf, fp->f_buf_size); +#endif } fp->f_buf_blkno = file_block; @@ -442,10 +646,35 @@ return (0); } -/* - * Search a directory for a name and return its - * i_number. - */ +static void +test_disk(struct open_file *f) +{ + int i, rc; + char *buf; + uint64_t read_size; + + struct file *fp = (struct file *)f->f_fsdata; + struct fs *fs = fp->f_fs; + + buf = (char *)malloc(512); + + for (i = 0; i < 10; i++) { + rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, + fsbtodb(fs, i), + 512, buf, &read_size); + + + if (rc || read_size != 512) + printf("strategy failed\n"); + printf("%04d\n", i); +#if 0 + hdump(buf, 512); +#endif + + } + +} + static int search_directory(name, f, inumber_p) char *name; @@ -459,18 +688,33 @@ size_t buf_size; int namlen, length; int rc; +#if 0 + test_disk(f); +#endif + length = strlen(name); - length = strlen(name); + printf("search_directory: name=%s\n", name); fp->f_seekp = 0; while (fp->f_seekp < DIP(fp, di_size)) { + int i; rc = buf_read_file(f, &buf, &buf_size); if (rc) return (rc); + printf("scan directory entries: @ 0x%llx (size=0x%llx)\n", + (uint64_t)buf, (uint64_t)buf_size); dp = (struct direct *)buf; edp = (struct direct *)(buf + buf_size); + i = 0; +#if 0 + hdump(buf, buf_size); +#endif while (dp < edp) { +#if 0 + printf("\tdirent# %d (dp=0x%llx edp=0x%llx\n", i, + (uint64_t)dp, (uint64_t)edp); +#endif if (dp->d_ino == (ino_t)0) goto next; #if BYTE_ORDER == LITTLE_ENDIAN @@ -479,6 +723,9 @@ else #endif namlen = dp->d_namlen; +#if 0 + printf("namlen: %d dp->d_name: %s\n", namlen, dp->d_name); +#endif if (namlen == length && !strcmp(name, dp->d_name)) { /* found entry */ @@ -487,6 +734,7 @@ } next: dp = (struct direct *)((char *)dp + dp->d_reclen); + i++; } fp->f_seekp += buf_size; } @@ -494,7 +742,31 @@ } static int sblock_try[] = SBLOCKSEARCH; +#define SOLARIS_SBLOCK_CONVERT 1 +void map_sblock(struct fs *fsp) +{ + struct solaris_fs sfs = *(struct solaris_fs *)fsp; + + printf("fbsd fs_qfmask offset %lx solaris fs_qfmask offset %lx\n", + offsetof(struct fs, fs_qfmask), offsetof(struct solaris_fs, fs_qfmask)); + printf("fbsd fs_qbmask offset %lx solaris fs_qbmask offset %lx\n", + offsetof(struct fs, fs_qbmask), offsetof(struct solaris_fs, fs_qbmask)); + + printf(" fsp->fs_qbmask: %llx = sfs.fs_qbmask %08lx%08lx;\n", + fsp->fs_qbmask, sfs.fs_qbmask.val[0], sfs.fs_qbmask.val[1]); + fsp->fs_qbmask = ((uint64_t)sfs.fs_qbmask.val[0]) << 32 | sfs.fs_qbmask.val[1]; + printf(" fsp->fs_qfmask: %llx = sfs.fs_qfmask %08lx%08lx;\n", + fsp->fs_qfmask, sfs.fs_qfmask.val[0], sfs.fs_qfmask.val[1]); + fsp->fs_qfmask = ((uint64_t)sfs.fs_qfmask.val[0]) << 32 | sfs.fs_qfmask.val[1]; + +} + + + + + + /* * Open a file. */ @@ -533,6 +805,16 @@ (char *)fs, &buf_size); if (rc) goto out; + + + + +#if 0 + printf("fs->fs_magic: %x fs->fs_bsize: %x fs->fs_sblockloc: %lx\n", + fs->fs_magic, fs->fs_bsize, fs->fs_sblockloc); + printf("sblock_try[i]: %x buf_size %lx\n", + sblock_try[i], buf_size); +#endif if ((fs->fs_magic == FS_UFS1_MAGIC || (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_sblockloc == sblock_try[i])) && @@ -545,6 +827,9 @@ rc = EINVAL; goto out; } +#if 1 + map_sblock(fs); +#endif /* * Calculate indirect block levels. */ @@ -560,9 +845,13 @@ } inumber = ROOTINO; - if ((rc = read_inode(inumber, f)) != 0) - goto out; + if ((rc = read_inode(inumber, f)) != 0) { + printf("failed to read root inode \n"); + goto out; + } + printf("read root inode \n"); + cp = path = strdup(upath); if (path == NULL) { rc = ENOMEM; @@ -609,6 +898,8 @@ * symbolic link. */ parent_inumber = inumber; + printf("-- searching %s @ inode = 0x%x - found @ 0x%x\n", + ncp, parent_inumber, inumber); rc = search_directory(ncp, f, &inumber); *cp = c; if (rc)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603090539.k295dImG062022>