Subject: Disklabels arrive for 2.11BSD (#255 part 6 of 18) Index: sys,bin,usr.lib,(many more)/ 2.11BSD Description: The moving the partitions tables out of the disk drivers and to a disklabel residing on the media has been on the wish list for many many years. Disklabels have finally arrived for 2.11BSD! Repeat-By: Observation. Also a reading of the setup and installation documentation for previous 2BSD releases (2.9, 2.10, 2.11) all have a paragraph similar to this present: "It is possible to change the partitions by changing the code for the table in the disk driver. Since it's desirable to do this, these tables really should be read off each pack...." Fix: This is part 6 of 18. Gather all parts before doing anything except reading the instructions which are in #250 (part 1). Updated by this part are: /usr/src/etc/restor/restor.c /usr/src/etc/restor/Makefile /usr/src/etc/newfs.c /usr/src/etc/mkfs.c 'newfs' was almost rewritten based on the 4.4-Lite reference model. NOTE: The newfs program no longer installs sector 0 bootblocks. That functionality has been relocated to the 'disklabel' program. When creating a filesystem on a disk for which the device driver does not support labels you must now use the '-T' option to force 'newfs' to scan /etc/disktab. OTHERWISE newfs will only make a filesystem if a label is found on the disk. The newfs man page has been updated to reflect the above changes. 'restor' must always be built split I/D so some minor changes were made to restor.c, nothing major changed. restor/Makefile had some minor work done to him, a 'lint' target was added. 'mkfs' had major changes made to deal with disklabels when being built for standalone use. If no label is found the standalone mkfs program will refuse to write to the disk. WARNING: do not run 'mkfs' manually (when the kernel is running) unless you are absolutely certain you know what you are doing. Use 'newfs' instead. The 'newfs' program has several safety checks and looks for the partition information in the disklabel, etc. Cut where indicated and save to a file (/tmp/255). Then: patch -p0 < /tmp/255 rm /tmp/255 ---------------------------cut here---------------------- *** /usr/src/etc/restor/restor.c.old Sat Apr 13 17:02:58 1991 --- /usr/src/etc/restor/restor.c Fri Jun 9 23:08:29 1995 *************** *** 1,8 **** /* ! * NOTE: This Program is must be loaded 407 ! * to run standalone. Make sure to keep ! * the size under 48K or it will run out ! * of stack space */ #include --- 1,11 ---- /* ! * 1995/06/09 - standalone restor must be loaded split I/D because the ! * disklabel handling increased the size of standalone programs. ! * This is not too much of a problem since the Kernel has been ! * required to be split I/D for several years. ! * ! * Since split I/D is now required the NCACHE parameter is no ! * longer ifdef'd on STANDALONE (and is always 3 instead of 1). */ #include *************** *** 13,23 **** #endif #define BITS 8 #define MAXXTR 60 - #ifndef STANDALONE #define NCACHE 3 - #else - #define NCACHE 1 /* Size reduction as refered to above */ - #endif #define flsht() (bct = NTREC + 1) #ifndef STANDALONE --- 16,22 ---- *** /usr/src/etc/restor/Makefile.old Mon Jan 18 08:46:49 1993 --- /usr/src/etc/restor/Makefile Thu Jun 8 22:38:41 1995 *************** *** 1,12 **** # ! # restor makefile # - # If SEPFLAG is not "-i" then DEFS must include "-DNONSEPARATE" on the - # PDP-11. Ex: - # SEPFLAG= -n - # DEFS= -DNONSEPARATE - SEPFLAG= -i DEFS= CFLAGS= -O -I. ${DEFS} --- 1,7 ---- # ! # restor makefile - SEPFLAG must be -i, restor will not run unless built -i # SEPFLAG= -i DEFS= CFLAGS= -O -I. ${DEFS} *************** *** 28,30 **** --- 23,28 ---- for i in ${SRCS}; do \ ctags -a -f tags $$cwd/$$i; \ done + + lint: + lint -haxcz restor.c *** /usr/src/etc/newfs.c.old Sat Dec 28 21:43:26 1991 --- /usr/src/etc/newfs.c Wed Apr 26 17:46:48 1995 *************** *** 1,3 **** --- 1,5 ---- + #define COMPAT + /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement *************** *** 9,61 **** "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; ! static char sccsid[] = "@(#)newfs.c 6.0 (2.11BSD) 12/28/91"; #endif /* * newfs: friendly front end to mkfs */ #include #include ! #include ! #include main(argc, argv) int argc; char **argv; { ! extern char *optarg; ! extern int optind; ! register struct disktab *dp; register struct partition *pp; ! register char *cp; struct stat st; long fssize; int ch, status, logsec, m; ! int just_looking, copy_boot; ! char *uboot; ! char device[MAXPATHLEN], cmd[BUFSIZ], ! *index(), *rindex(); - just_looking = 0; - copy_boot = 0; m = 0; ! uboot = (char *)0; ! while ((ch = getopt(argc,argv,"NvbB:m:")) != EOF) switch((char)ch) { case 'N': case 'v': ! ++just_looking; break; ! case 'B': ! uboot = optarg; ! /*FALLTHROUGH*/ ! case 'b': ! ++copy_boot; break; case 'm': m = atoi(optarg); break; case '?': default: usage(); --- 11,87 ---- "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; ! static char sccsid[] = "@(#)newfs.c 6.1 (2.11BSD) 4/26/95"; #endif /* * newfs: friendly front end to mkfs + * + * The installation of bootblocks has been moved to 'disklabel(8)'. This + * program expects to find a disklabel present which will contain the + * geometry and partition size information. If 'newfs' is being run on + * a system without disklabels implemented in the kernel you must specify + * "-T diskname" (where 'diskname' is an entry in /etc/disktab). */ + + #include #include #include ! #include ! #include ! #include ! #include + #include + #include + #include + #include + + #ifdef COMPAT + char *disktype; + int unlabeled; + #endif + int Nflag; + struct disklabel *getdisklabel(); + + extern char *optarg, *__progname; + extern long atol(); + extern int optind, errno; + main(argc, argv) int argc; char **argv; { ! register struct disklabel *lp; register struct partition *pp; ! char *cp; struct stat st; long fssize; int ch, status, logsec, m; ! int fsi; ! char device[MAXPATHLEN], cmd[BUFSIZ], *index(), *rindex(); ! char *special; m = 0; ! while ((ch = getopt(argc,argv,"T:Nvm:s:")) != EOF) switch((char)ch) { case 'N': case 'v': ! Nflag = 1; break; ! #ifdef COMPAT ! case 'T': ! disktype = optarg; break; + #endif case 'm': m = atoi(optarg); break; + case 's': + fssize = atol(optarg); + if (fssize <= 0) + fatal("%s: bad file system size", optarg); + break; case '?': default: usage(); *************** *** 63,144 **** argc -= optind; argv += optind; ! if (argc != 2) usage(); /* figure out device name */ ! cp = rindex(argv[0], '/'); ! if (cp) ! ++cp; ! else ! cp = argv[0]; ! if (*cp == 'r' && cp[1] != 'a' && cp[1] != 'b') ! ++cp; ! sprintf(device, "/dev/r%s", cp); ! ! /* see if it exists and of a legal type */ ! if (stat(device, &st)) { ! fprintf(stderr, "newfs: "); ! perror(device); ! exit(1); } - if ((st.st_mode & S_IFMT) != S_IFCHR) { - fprintf(stderr, "newfs: %s: not a character device.\n", device); - exit(1); - } ! /* see if disk is in disktab table */ ! dp = getdiskbyname(argv[1]); ! if (dp == 0) { ! fprintf(stderr, "newfs: %s not in /etc/disktab.\n", argv[1]); ! exit(1); ! } ! /* grab partition letter */ cp = index(argv[0], '\0') - 1; ! if (cp == 0 || *cp < 'a' || *cp > 'h') { ! fprintf(stderr, "newfs: %s: can't figure out file system partition.\n", argv[0]); ! exit(1); ! } ! /* get default partition size */ ! pp = &dp->d_partitions[*cp - 'a']; ! fssize = pp->p_size; ! if (fssize < 0) { ! fprintf(stderr, "newfs: %s: no default size for `%c' partition.\n", argv[1], *cp); ! exit(1); ! } /* * Convert from sectors to logical blocks. Note that sector size * must evenly devide DEV_BSIZE!!!!! */ ! logsec = DEV_BSIZE/dp->d_secsize; fssize /= logsec; /* build command */ if (m <= 0 || m > 31) m = 2; ! sprintf(cmd, "/etc/mkfs %s %ld %d %d", device, fssize, m, ! (dp->d_ntracks * dp->d_nsectors) / logsec); printf("newfs: %s\n", cmd); ! if (just_looking) exit(0); if (status = system(cmd)) exit(status >> 8); ! /* copy boot if requested */ ! if (copy_boot) { ! if (!uboot && !(uboot = dp->d_uboot)) { ! fprintf(stderr, "newfs: no default boot block available for an %s.\n", ! argv[1]); ! exit(1); } ! sprintf(cmd, "/bin/dd if=%s of=%s bs=512 count=1 conv=sync", ! uboot, device); ! if (status = system(cmd)) ! exit(status >> 8); } ! exit(0); } static --- 89,206 ---- argc -= optind; argv += optind; ! if (argc != 2 && argc != 1) usage(); /* figure out device name */ ! special = argv[0]; ! cp = rindex(special, '/'); ! if (cp == 0) { ! /* ! * No path prefix; try /dev/r%s then /dev/%s ! */ ! (void)sprintf(device, "%s/r%s", _PATH_DEV, special); ! if (stat(device, &st) == -1) ! (void)sprintf(device, "%s/%s", _PATH_DEV, special); ! special = device; } ! fsi = open(special, O_RDONLY); ! if (fsi < 0) ! fatal("%s: %s", special, strerror(errno)); ! /* see if it exists and of a legal type */ ! if (fstat(fsi, &st) == -1) ! fatal("%s: %s", special, strerror(errno)); ! if ((st.st_mode & S_IFMT) != S_IFCHR) ! fatal("%s: not a character device", special); cp = index(argv[0], '\0') - 1; ! if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) ! fatal("%s: can't figure out file system partition", argv[0]); ! #ifdef COMPAT ! if (disktype == NULL) ! disktype = argv[1]; ! #endif ! lp = getdisklabel(special, fsi); ! if (isdigit(*cp)) ! pp = &lp->d_partitions[0]; ! else ! pp = &lp->d_partitions[*cp - 'a']; ! if (pp->p_size <= 0) ! fatal("%s: '%c' partition is unavailable", argv[0], *cp); ! #ifdef nothere ! if (pp->p_fstype == FS_BOOT) ! fatal("%s: '%c' partition overlaps boot program",argv[0], *cp); ! #endif ! ! if (fssize == 0) ! fssize = pp->p_size; ! if (fssize > pp->p_size) ! fatal("%s: maximum file system size on '%c' partition is %ld", ! argv[0], *cp, pp->p_size); /* * Convert from sectors to logical blocks. Note that sector size * must evenly devide DEV_BSIZE!!!!! */ ! ! /* ! * getdisklabel(3) forces the sector size to 512 because any other ! * choice would wreck havoc in the disklabel(8) program and result ! * in corrupted/destroyed filesystems. DEV_BSIZE had better be ! * 1024! ! */ ! if (lp->d_secsize != 512) ! fatal("%s: sector size not 512", argv[0]); ! logsec = DEV_BSIZE/lp->d_secsize; fssize /= logsec; /* build command */ if (m <= 0 || m > 31) m = 2; ! sprintf(cmd, "/etc/mkfs %s %ld %d %d", special, fssize, m, ! lp->d_secpercyl / logsec); printf("newfs: %s\n", cmd); ! ! close(fsi); ! ! if (Nflag) exit(0); + if (status = system(cmd)) exit(status >> 8); + exit(0); + } ! #ifdef COMPAT ! char lmsg[] = "%s: can't read disk label; disk type must be specified"; ! #else ! char lmsg[] = "%s: can't read disk label"; ! #endif ! ! struct disklabel * ! getdisklabel(s, fd) ! char *s; ! int fd; ! { ! static struct disklabel lab; ! ! if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { ! #ifdef COMPAT ! if (disktype) { ! struct disklabel *lp, *getdiskbyname(); ! ! unlabeled++; ! lp = getdiskbyname(disktype); ! if (lp == NULL) ! fatal("%s: unknown disk type", disktype); ! return (lp); } ! #endif ! warn("ioctl (GDINFO)"); ! fatal(lmsg, s); } ! return (&lab); } static *************** *** 145,150 **** usage() { ! fputs("usage: newfs [ -N ] [ -b ] [ -B boot-block ] [-m free-list-gap] special-device device-type\n", stderr); exit(1); } --- 207,239 ---- usage() { ! fprintf(stderr,"usage: %s [-N] [-m freelist-gap] [-s filesystem size] ", ! __progname); ! #ifdef COMPAT ! fputs("[-T disk-type] ", stderr); ! #endif ! fputs("special-device\n", stderr); exit(1); + } + + /*VARARGS*/ + void + fatal(fmt, va_alist) + char *fmt; + va_dcl + { + va_list ap; + + va_start(ap); + + if (fcntl(fileno(stderr), F_GETFL) < 0) { + openlog(__progname, LOG_CONS, LOG_DAEMON); + vsyslog(LOG_ERR, fmt, ap); + closelog(); + } else { + vwarnx(fmt, ap); + } + va_end(ap); + exit(1); + /*NOTREACHED*/ } *** /usr/src/etc/mkfs.c.old Thu Jan 6 20:54:41 1994 --- /usr/src/etc/mkfs.c Mon Jun 12 21:47:18 1995 *************** *** 1,7 **** ! char *sccsid = "@(#)mkfs.c 2.7"; /* ! * Make a file system prototype. * usage: mkfs filsys size [ m n ] */ #include --- 1,7 ---- ! char *sccsid = "@(#)mkfs.c 2.8 1995/06/12"; /* ! * Make a file system. Normally run by 'newfs' and not directly by users. * usage: mkfs filsys size [ m n ] */ #include *************** *** 11,25 **** * See /sys/h/localtimes.h and /sys/conf. */ #undef EXTERNALITIMES - #ifndef STANDALONE - #include - #endif #include - #include - #include #include #include #define UMASK 0755 #define NIPB (DEV_BSIZE/sizeof(struct dinode)) --- 11,27 ---- * See /sys/h/localtimes.h and /sys/conf. */ #undef EXTERNALITIMES #include #include #include + #ifndef STANDALONE + #include + #include + #include + #else + #include "saio.h" + #endif #define UMASK 0755 #define NIPB (DEV_BSIZE/sizeof(struct dinode)) *************** *** 30,35 **** --- 32,39 ---- #ifdef STANDALONE int fin; char module[] = "Mkfs"; + extern char *ltoa(); + extern struct iob iob[]; #endif int fsi; *************** *** 47,56 **** } filsys; int f_n = 100; ! int f_m = 5; ! daddr_t alloc(); main(argc,argv) int argc; char **argv; --- 51,62 ---- } filsys; int f_n = 100; ! int f_m = 2; ! daddr_t alloc(); + extern long atol(); + main(argc,argv) int argc; char **argv; *************** *** 58,63 **** --- 64,74 ---- register int f, c; long n; register char *size; + #ifdef STANDALONE + struct disklabel *lp; + struct partition *pp; + struct iob *io; + #endif #ifndef STANDALONE time(&utime); *************** *** 66,71 **** --- 77,90 ---- exit(1); } size = argv[2]; + /* + * NOTE: this will fail if the device is currently mounted and the system + * is at securelevel 1 or higher. + * + * We do not get the partition information because 'newfs' has already + * done so and invoked us. This program should not be run manually unless + * you are absolutely sure you know what you are doing - use 'newfs' instead. + */ fso = creat(argv[1], 0666); if(fso < 0) { printf("%s: cannot create\n", argv[1]); *************** *** 77,82 **** --- 96,106 ---- exit(1); } #else + /* + * Something more modern than January 1, 1970 - the date that the new + * standalone mkfs worked. 1995/06/08 2121. + */ + utime = 802671684L; printf("%s\n",module); do { printf("file system: "); *************** *** 85,97 **** fsi = open(buf, 0); } while (fso < 0 || fsi < 0); ! printf("file sys size: "); size = buf+128; gets(size); printf("interleaving factor (m; %d default): ", f_m); gets(buf); if (buf[0]) f_m = atoi(buf); printf("interleaving modulus (n; %d default): ", f_n); gets(buf); if (buf[0]) --- 109,175 ---- fsi = open(buf, 0); } while (fso < 0 || fsi < 0); ! /* ! * If the underlying driver supports disklabels then do not make a file ! * system unless: there is a valid label present, the specified partition ! * is of type FS_V71K, and the size is not zero. ! * ! * The 'open' above will have already fetched the label if the driver supports ! * labels - the check below will only fail if the driver doesn't do labels ! * or if the drive blew up in the millisecond since the last read. ! */ ! io = &iob[fsi - 3]; ! lp = &io->i_label; ! pp = &lp->d_partitions[io->i_part]; ! ! if (devlabel(io, READLABEL) < 0) ! { ! /* ! * The driver does not implement labels. The 'iob' structure still contains ! * a label structure so initialize the items that will be looked at later. ! */ ! pp->p_size = 0; ! lp->d_secpercyl = 0; ! goto nolabels; ! } ! if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || ! dkcksum(lp)) ! { ! printf("'%s' is either unlabeled or the label is corrupt.\n", ! buf); ! printf("Since the driver for '%s' supports disklabels you\n", ! buf); ! printf("must use the standalone 'disklabel' before making\n"); ! printf("a filesystem on '%s'\n", buf); ! return; ! } ! if (pp->p_fstype != FS_V71K) ! { ! printf("%s is not a 2.11BSD (FS_V71K) partition.", buf); ! return; ! } ! if (pp->p_size == 0) ! { ! printf("%s is a zero length partition.\n", buf); ! return; ! } ! nolabels: ! printf("file sys size [%D]: ", dbtofsb(pp->p_size)); size = buf+128; gets(size); + if (size[0] == '\0') + strcpy(size, ltoa(dbtofsb(pp->p_size))); + if (pp->p_size && atol(size) > pp->p_size) + { + printf("specified size is larger than the disklabel says.\n"); + return; + } printf("interleaving factor (m; %d default): ", f_m); gets(buf); if (buf[0]) f_m = atoi(buf); + if (lp->d_secpercyl) + f_n = dbtofsb(lp->d_secpercyl); printf("interleaving modulus (n; %d default): ", f_n); gets(buf); if (buf[0]) *************** *** 112,117 **** --- 190,200 ---- n = n*10 + (c-'0'); } filsys.fs.fs_fsize = n; + if (!n) + { + printf("Can't make zero length filesystem\n"); + return; + } /* * Minor hack for standalone root and other * small filesystems: reduce ilist size. *************** *** 139,145 **** filsys.fs.fs_cyl = f_n; printf("m/n = %d %d\n", f_m, f_n); if(filsys.fs.fs_isize >= filsys.fs.fs_fsize) { ! printf("%ld/%ld: bad ratio\n", filsys.fs.fs_fsize, filsys.fs.fs_isize-2); exit(1); } filsys.fs.fs_tfree = 0; --- 222,228 ---- filsys.fs.fs_cyl = f_n; printf("m/n = %d %d\n", f_m, f_n); if(filsys.fs.fs_isize >= filsys.fs.fs_fsize) { ! printf("%D/%D: bad ratio\n", filsys.fs.fs_fsize, filsys.fs.fs_isize-2); exit(1); } filsys.fs.fs_tfree = 0;