Subject: port-next68k/11938: NeXT disklabel support
To: None <gnats-bugs@gnats.netbsd.org>
From: None <perseant@hhhh.org>
List: netbsd-bugs
Date: 01/11/2001 14:24:18
>Number: 11938
>Category: port-next68k
>Synopsis: NeXT disklabel compatibility support
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: port-next68k-maintainer
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu Jan 11 14:24:00 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:
>Release: 20010111
>Organization:
------------------------------------------------------------------------
Konrad Schroder http://www.hitl.washington.edu/people/perseant/
Information Tech & Services Box 352142 -or- 215 Fluke Hall, Mason Road
Human Interface Technology Lab University of Washington
Voice: 206.616.1478 FAX: 206.543.5380 Seattle, WA, 98195, USA
>Environment:
System: NetBSD previous.hitl.washington.edu 1.5O NetBSD 1.5O (PREVIOUS) #24: Wed Jan 10 18:34:24 PST 2001 perseant@hammer:/usr/src/sys/arch/next68k/compile/PREVIOUS next68k
>Description:
The NeXT disklabel code does not currently support reading from a
NextStep-generated disklabel. I've stolen the Ultrix compatibility
code and modified it to the point that (with a trivial tweak to ffs)
I can mount a NeXT "4.3BSD" ffs from disk.
>How-To-Repeat:
disklabel sd0
>Fix:
I'm including the ffs patch for completeness, but it's not really something
that is suitable to go into the tree IMO. (My disk has 512-sectors for real,
but NeXTstep thinks they are 1k sectors, so fs_fsbtodb = 0 instead of 1.
I don't think this is typical.) I think that the disklabel patch is okay,
assuming that it dtrt for 1k sector disks, which I haven't tested.
Index: next68k/disksubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/next68k/next68k/disksubr.c,v
retrieving revision 1.5
diff -u -r1.5 disksubr.c
--- next68k/disksubr.c 2000/11/20 08:24:19 1.5
+++ next68k/disksubr.c 2001/01/11 22:05:01
@@ -40,13 +40,22 @@
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
*/
+/* #include "opt_compat_nextstep.h" */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
+#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/syslog.h>
-#include <sys/disk.h>
+#ifdef COMPAT_NEXTSTEP
+# include <ufs/ufs/dinode.h> /* XXX for fs.h */
+# include <ufs/ffs/fs.h> /* XXX for SBSIZE */
+
+char *compat_label __P((dev_t dev, void (*strat) __P((struct buf *bp)),
+ struct disklabel *lp, struct cpu_disklabel *osdep));
+#endif
#define b_cylinder b_resid
@@ -101,8 +110,137 @@
}
}
brelse(bp);
+#ifdef COMPAT_NEXTSTEP
+ /*
+ * If no NetBSD label was found, check for a NextStep label and
+ * construct tne incore label from the NextStep partition information.
+ */
+ if (msg != NULL) {
+ msg = compat_label(dev, strat, lp, osdep);
+ if (msg == NULL) {
+ printf("WARNING: using NextStep partition information\n");
+ /* set geometry? */
+ }
+ }
+#endif
+ /* XXX If no label of either type found, generate default label here */
+ return (msg);
+}
+
+#ifdef COMPAT_NEXTSTEP
+/*
+ * Given a buffer bp, try and interpret it as an NextStep disk label,
+ * putting the partition info into a native NetBSD label
+ */
+char *
+compat_label(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat) __P((struct buf *bp));
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct cpu_disklabel *cdlp;
+ struct cpu_partition *cpp;
+ struct buf *bp = NULL;
+ char *msg = NULL;
+ int part;
+ int msec;
+
+ bp = geteblk((int)LABELSIZE);
+ bp->b_dev = dev;
+ bp->b_blkno = LABELSECTOR;
+ bp->b_bcount = LABELSIZE;
+ bp->b_flags |= B_READ;
+ bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
+ (*strat)(bp);
+
+ if (biowait(bp)) {
+ msg = "I/O error";
+ goto done;
+ }
+
+ cdlp = (struct cpu_disklabel *)bp->b_data;
+ if (IS_DISKLABEL(cdlp)) {
+ /* XXX KS - check the cksum here */
+#ifdef DEBUG
+ printf("Interpreting NextStep label\n");
+#endif
+ lp->d_magic = cdlp->cd_version;
+ lp->d_npartitions = 0;
+
+#if notyet
+ /* XXX not really, until 1k sectors are really supported */
+ /* XXX and then presumably the disk driver will fix for us */
+ if (cdlp->cd_secsize > lp->d_secsize) {
+ msec = cdlp->cd_secsize / lp->d_secsize;
+ lp->d_secsize = cdlp->cd_secsize;
+ lp->d_nsectors /= msec;
+ lp->d_secpercyl /= msec;
+ lp->d_secperunit /= msec;
+ } else if (cdlp->cd_secsize < lp->d_secsize) {
+ msec = lp->d_secsize / cdlp->cd_secsize;
+ lp->d_secsize = cdlp->cd_secsize;
+ lp->d_nsectors *= msec;
+ lp->d_secpercyl *= msec;
+ lp->d_secperunit *= msec;
+ }
+ msec = 1;
+#else
+ msec = cdlp->cd_secsize / lp->d_secsize;
+#endif
+ /* strncpy(lp->d_packname, cdlp->cd_label, 16); */
+ strncpy(lp->d_packname, "NextStep label", 16);
+ lp->d_rpm = cdlp->cd_rpm;
+ lp->d_interleave = 1;
+ lp->d_flags = 0;
+ lp->d_bbsize = LABELSIZE;
+ lp->d_sbsize = SBSIZE; /* XXX KS */
+ for (part = 0; part < MAXPARTITIONS; part++) {
+ cpp = cdlp->cd_partitions + part;
+ if (cpp->cp_size >= 0 && cpp->cp_offset >= 0) {
+ /* XXX is this the correct use of cd_front? */
+ if (part != RAW_PART && cpp->cp_offset == 0) {
+ cpp->cp_offset = cdlp->cd_front;
+ cpp->cp_size -= cdlp->cd_front;
+ }
+ lp->d_partitions[part].p_size = cpp->cp_size * msec;
+ lp->d_partitions[part].p_offset = cpp->cp_offset * msec;
+ lp->d_partitions[part].p_fsize = cpp->cp_fsize;
+ lp->d_partitions[part].p_frag = cpp->cp_bsize /
+ cpp->cp_fsize;
+ lp->d_partitions[part].p_cpg = cpp->cp_cpg;
+ lp->d_partitions[part].p_fstype =
+ (strncmp(cpp->cp_type, "4.3BSD", 7) == 0) ? FS_BSDFFS : FS_UNUSED;
+#ifdef DEBUG
+ if (cpp->cp_type[0] &&
+ lp->d_partitions[part].p_fstype == FS_UNUSED)
+ printf(" Interpreting type \"%.9s\" as \"unused\"\n",
+ cpp->cp_type);
+#endif
+ } else if (part == RAW_PART) {
+ /* If RAW_PART was empty, make one up */
+ lp->d_partitions[part].p_offset = 0;
+ lp->d_partitions[part].p_size = lp->d_secperunit;
+ lp->d_partitions[part].p_fstype = FS_UNUSED;
+ }
+ lp->d_npartitions++;
+
+#ifdef DEBUG
+ printf(" NextStep label sd%d%c: start %d len %d\n",
+ DISKUNIT(dev), "abcdefgh"[part],
+ lp->d_partitions[part].p_offset,
+ lp->d_partitions[part].p_size);
+#endif
+ }
+ } else {
+ printf("label: %x\n", cdlp->cd_version);
+ msg = ((msg != NULL) ? msg: "no disk label");
+ }
+done:
+ brelse(bp);
return (msg);
}
+#endif /* COMPAT_NEXTSTEP */
/*
* Check new disk label for sensibility before setting it.
Index: include/disklabel.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/next68k/include/disklabel.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 disklabel.h
--- include/disklabel.h 1998/06/09 07:53:05 1.1.1.1
+++ include/disklabel.h 2001/01/11 22:05:02
@@ -55,46 +55,47 @@
/* The disklabel the way it is on the disk */
struct cpu_disklabel {
- int cd_version; /* label version */
- int cd_label_blkno; /* block # of this label */
- int cd_size; /* size of media area (sectors) */
- char cd_label[CPULBLLEN]; /* disk name (label) */
- u_int cd_flags; /* flags */
+ int cd_version; /* 0: label version */
+ int cd_label_blkno; /* 4: block # of this label */
+ int cd_size; /* 8: size of media area (sectors) */
+ char cd_label[CPULBLLEN]; /* 12: disk name (label) */
+ u_int cd_flags; /* 36: flags */
#define CD_UNINIT 0x80000000 /* label is uninitialized */
- u_int cd_tag; /* volume tag */
- char cd_name[MAXDNMLEN]; /* drive (hardware) name */
- char cd_type[MAXTYPLEN]; /* drive type */
- int cd_secsize; /* # of bytes per sector */
- int cd_ntracks; /* # of tracks per cylinder */
- int cd_nsectors; /* # of data sectors per track */
- int cd_ncylinders; /* # of data cylinders per unit */
- int cd_rpm; /* rotational speed */
- short cd_front; /* # of sectors in "front porch" */
- short cd_back; /* # of sectors in "back porch" */
- short cd_ngroups; /* # of alt groups */
- short cd_ag_size; /* alt group size (sectors) */
- short cd_ag_alts; /* alternate sectors / alt group */
- short cd_ag_off; /* sector offset to first alternate */
- int cd_boot_blkno[2]; /* boot program locations */
- char cd_kernel[MAXBFLEN]; /* default kernel name */
- char cd_hostname[MAXHNLEN]; /* host name (usu. where disk was labeled) */
- char cd_rootpartition; /* root partition letter e.g. 'a' */
- char cd_rwpartition; /* r/w partition letter e.g. 'b' */
- struct cpu_partition {
- int cp_offset; /* starting sector */
- int cp_size; /* number of sectors in partition */
- short cp_bsize; /* block size in bytes */
- short cp_fsize; /* filesystem basic fragment size */
- char cp_opt; /* optimization type: 's'pace/'t'ime */
- short cp_cpg; /* filesystem cylinders per group */
- short cp_density; /* bytes per inode density */
- char cp_minfree; /* minfree (%) */
- short cp_reserved; /* no useful data here */
- char cp_mountpt[MAXMPTLEN];/* default/standard mount point */
- char cp_automnt; /* auto-mount when inserted */
- char cp_res2; /* alignment byte */
- char cp_type[MAXFSTLEN]; /* file system type name */
- } cd_partitions[MAXPARTITIONS];
+ u_int cd_tag; /* 40: volume tag */
+ char cd_name[MAXDNMLEN]; /* 44: drive (hardware) name */
+ char cd_type[MAXTYPLEN]; /* 68: drive type */
+ int cd_secsize; /* 92: # of bytes per sector */
+ int cd_ntracks; /* 96: # of tracks per cylinder */
+ int cd_nsectors; /* 100: # of data sectors per track */
+ int cd_ncylinders; /* 104: # of data cylinders per unit */
+ int cd_rpm; /* 108: rotational speed */
+ short cd_front; /* 112: # of sectors in "front porch" */
+ short cd_back; /* 114: # of sectors in "back porch" */
+ short cd_ngroups; /* 116: # of alt groups */
+ short cd_ag_size; /* 118: alt group size (sectors) */
+ short cd_ag_alts; /* 120: alternate sectors / alt group */
+ short cd_ag_off; /* 122: sector offset to first alternate */
+ int cd_boot_blkno[2]; /* 124: boot program locations */
+ char cd_kernel[MAXBFLEN]; /* 132: default kernel name */
+ char cd_hostname[MAXHNLEN]; /* 156: host name (usu. where disk was labeled) */
+ char cd_rootpartition; /* 188: root partition letter e.g. 'a' */
+ char cd_rwpartition; /* 189: r/w partition letter e.g. 'b' */
+ struct cpu_partition { /* 190, 236, ... */
+ int cp_offset; /* 0: starting sector */
+ int cp_size; /* 4: number of sectors in partition */
+ short cp_bsize; /* 8: block size in bytes */
+ short cp_fsize; /* 10: filesystem basic fragment size */
+ char cp_opt; /* 12: optimization type: 's'pace/'t'ime */
+ char cp_reserved_0; /* 13: unused */
+ short cp_cpg; /* 14: filesystem cylinders per group */
+ short cp_density; /* 16: bytes per inode density */
+ char cp_minfree; /* 18: minfree (%) */
+ char cp_reserved_1; /* 19: unused */
+ char cp_mountpt[MAXMPTLEN]; /* 20: default/standard mount point */
+ char cp_automnt; /* 36: auto-mount when inserted */
+ char cp_type[MAXFSTLEN]; /* 37: file system type name */
+ char cp_reserved_2; /* 45: alignment byte */
+ } __attribute__ ((__packed__)) cd_partitions[MAXPARTITIONS];
union {
u_short CD_v3_checksum; /* label version 3 checksum */
@@ -104,6 +105,6 @@
#define cd_v3_checksum cd_un.CD_v3_checksum
#define cd_bad cd_un.CD_bad
u_short cd_checksum; /* label version 1 or 2 checksum */
-};
+} __attribute__ ((__packed__));
#endif /* _MACHINE_DISKLABEL_H_ */
#
# The kludge...
#
Index: ffs_vfsops.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.75
diff -u -r1.75 ffs_vfsops.c
--- ffs_vfsops.c 2000/12/04 09:37:06 1.75
+++ ffs_vfsops.c 2001/01/11 22:06:03
@@ -112,6 +112,9 @@
struct pool ffs_inode_pool;
+static void ffs_sanity_rconv __P((struct fs *));
+static void ffs_sanity_wconv __P((struct fs *));
+
/*
* Called by main() when ffs is going to be mounted as root.
*/
@@ -438,6 +441,8 @@
free(newfs, M_UFSMNT);
return (EIO); /* XXX needs translation */
}
+ ffs_sanity_rconv(newfs);
+
/*
* Copy pointer fields back into superblock before copying in XXX
* new superblock. These should really be in the ufsmount. XXX
@@ -624,6 +629,7 @@
}
#endif
ffs_oldfscompat(fs);
+ ffs_sanity_rconv(fs);
if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
error = EINVAL;
@@ -1271,6 +1277,7 @@
if (mp->um_flags & UFS_NEEDSWAP)
ffs_sb_swap(fs, (struct fs*)bp->b_data, 1);
#endif
+ ffs_sanity_wconv((struct fs *)(bp->b_data));
fs->fs_flags |= saveflag;
fs->fs_nrpos = saved_nrpos; /* XXX */
@@ -1321,4 +1328,33 @@
if (!allerror && error)
allerror = error;
return (allerror);
+}
+
+/*
+ * Check sanity for repairable fields in the superblock. For now, just
+ * check the block size as compared to the fsbtodb constant.
+ */
+void
+ffs_sanity_rconv(fs)
+ struct fs *fs;
+{
+ int msec;
+
+ msec = dbtofsb(fs, fs->fs_fsize) / dbtob(1);
+ fs->fs_devbsize = 0;
+#ifdef DEBUG
+ printf("ffs_sanity_rconv: changing fsbtodb by factor of %d\n", msec);
+#endif
+ while (msec > 1) {
+ msec /= 2;
+ ++fs->fs_fsbtodb;
+ ++fs->fs_devbsize;
+ }
+}
+
+void
+ffs_sanity_wconv(fs)
+ struct fs *fs;
+{
+ fs->fs_fsbtodb -= fs->fs_devbsize;
}
Index: fs.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ffs/fs.h,v
retrieving revision 1.12
diff -u -r1.12 fs.h
--- fs.h 1999/11/15 18:49:14 1.12
+++ fs.h 2001/01/11 22:06:03
@@ -157,7 +157,7 @@
*/
struct fs {
int32_t fs_firstfield; /* historic file system linked list, */
- int32_t fs_unused_1; /* used for incore super blocks */
+ int32_t fs_devbsize; /* original dev_bsize */
ufs_daddr_t fs_sblkno; /* addr of super-block in filesys */
ufs_daddr_t fs_cblkno; /* offset of cyl-block in filesys */
ufs_daddr_t fs_iblkno; /* offset of inode-blocks in filesys */
>Release-Note:
>Audit-Trail:
>Unformatted: