Subject: Disklabels arrive for 2.11BSD (#264 part 15 of 18)
Index:	sys,bin,usr.lib,(many more)/<many> 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 15 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/sys/sys/sys_inode.c
/usr/src/sys/sys/init_main.c
/usr/src/sys/sys/ufs_mount.c
/usr/src/sys/sys/ufs_disksubr.c

	ufs_disksubr.c is a new file added by unpacking the shar file
	included below.  The disklabel read, write and ioctl code is 
	contained in this file.

	Other changes include a new calling convention to device driver
	open and close entry points.  Three arguments are now passed
	rather than two.  The third argument is the type of device
	(S_IFBLK or S_IFCHR) and is used by disk drivers to keep track
	of which partitions are open on a drive.

	init_main.c was modifed to check the filesystem type of the swap
	partition.  If the driver for the swap device supports labels then
	the partition used for swapping *must* be of type 'swap'.  This is
	aimed at protecting data partitions by not allowing the kernel
	to swap on a live (type "2.11BSD") filesystem.

	Cut where indicated and save to a file (/tmp/264).  Then:

		cd /tmp
		sh 264
		sh sys.shar
		patch -p0 < sys.patch
		rm 264 sys.shar sys.patch

---------------------------cut here--------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	sys.shar
#	sys.patch
# This archive created: Tue Jun 27 22:29:34 1995
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'sys.shar'
then
	echo shar: "will not over-write existing file 'sys.shar'"
else
sed 's/^0//' << \SHAR_EOF > 'sys.shar'
0#! /bin/sh
0# This is a shell archive, meaning:
0# 1. Remove everything above the #! /bin/sh line.
0# 2. Save the resulting text in a file.
0# 3. Execute the file with /bin/sh (not csh) to create:
0#	/sys/sys/ufs_disksubr.c
0# This archive created: Mon Jun 19 21:24:38 1995
0export PATH; PATH=/bin:/usr/bin:$PATH
0if test -f '/sys/sys/ufs_disksubr.c'
0then
0	echo shar: "will not over-write existing file '/sys/sys/ufs_disksubr.c'"
0else
0sed 's/^X//' << \SHAR_EOF > '/sys/sys/ufs_disksubr.c'
0X/*
0X * Copyright (c) 1982, 1986, 1988, 1993
0X *	The Regents of the University of California.  All rights reserved.
0X * (c) UNIX System Laboratories, Inc.
0X * All or some portions of this file are derived from material licensed
0X * to the University of California by American Telephone and Telegraph
0X * Co. or Unix System Laboratories, Inc. and are reproduced herein with
0X * the permission of UNIX System Laboratories, Inc.
0X *
0X * Redistribution and use in source and binary forms, with or without
0X * modification, are permitted provided that the following conditions
0X * are met:
0X * 1. Redistributions of source code must retain the above copyright
0X *    notice, this list of conditions and the following disclaimer.
0X * 2. Redistributions in binary form must reproduce the above copyright
0X *    notice, this list of conditions and the following disclaimer in the
0X *    documentation and/or other materials provided with the distribution.
0X * 3. All advertising materials mentioning features or use of this software
0X *    must display the following acknowledgement:
0X *	This product includes software developed by the University of
0X *	California, Berkeley and its contributors.
0X * 4. Neither the name of the University nor the names of its contributors
0X *    may be used to endorse or promote products derived from this software
0X *    without specific prior written permission.
0X *
0X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
0X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
0X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0X * SUCH DAMAGE.
0X *
0X *	@(#)ufs_disksubr.c	8.5.3 (2.11BSD GTE) 1995/06/16
0X */
0X
0X#include <errno.h>
0X#include <syslog.h>
0X#include <sys/param.h>
0X#include <sys/user.h>
0X#include <sys/systm.h>
0X#include <sys/buf.h>
0X#include <sys/file.h>
0X#include <sys/ioctl.h>
0X#include <sys/disklabel.h>
0X#include <sys/disk.h>
0X
0X/*
0X * Attempt to read a disk label from a device using the indicated stategy
0X * routine.  The label must be partly set up before this: secpercyl and
0X * anything required in the strategy routine (e.g., sector size) must be
0X * filled in before calling us.  Returns NULL on success and an error
0X * string on failure.
0X */
0Xchar *
0Xreaddisklabel(dev, strat, lp)
0X	dev_t dev;
0X	int (*strat)();
0X	register struct disklabel *lp;
0X	{
0X	register struct buf *bp;
0X	struct disklabel *dlp;
0X	char *msg = NULL;
0X
0X	if	(lp->d_secperunit == 0)
0X		lp->d_secperunit = 0x1fffffffL;
0X	lp->d_npartitions = 1;
0X	if	(lp->d_partitions[0].p_size == 0)
0X		lp->d_partitions[0].p_size = 0x1fffffffL;
0X	lp->d_partitions[0].p_offset = 0;
0X
0X	bp = geteblk();
0X	bp->b_dev = dev;
0X	bp->b_blkno = LABELSECTOR;
0X	bp->b_bcount = lp->d_secsize;	/* Probably should wire this to 512 */
0X	bp->b_flags = B_BUSY | B_READ;
0X	bp->b_cylin = LABELSECTOR / lp->d_secpercyl;
0X	(*strat)(bp);
0X	biowait(bp);
0X	if	(u.u_error)
0X		msg = "I/O error";
0X	else
0X		{
0X		dlp = (struct disklabel *)mapin(bp);
0X		if	(dlp->d_magic != DISKMAGIC || 
0X				dlp->d_magic2 != DISKMAGIC)
0X			{
0X			if	(msg == NULL)
0X				msg = "no disk label";
0X			}
0X		else if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp))
0X			msg = "disk label corrupted";
0X		else
0X			bcopy(dlp, lp, sizeof (struct disklabel));
0X		mapout(bp);
0X		}
0X	bp->b_flags = B_INVAL | B_AGE;
0X	brelse(bp);
0X	return(msg);
0X	}
0X
0X/*
0X * Check new disk label for sensibility before setting it.  'olp' must point
0X * to a kernel resident (or mapped in) label.  'nlp' points to the new label
0X * usually present on the stack (having been passed in via ioctl from an
0X * application).
0X */
0Xint
0Xsetdisklabel(olp, nlp, openmask)
0X	struct disklabel *olp;
0X	register struct disklabel *nlp;
0X	u_short openmask;
0X{
0X	int i;
0X	register struct partition *opp, *npp;
0X
0X	if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
0X	    dkcksum(nlp) != 0)
0X		return (EINVAL);
0X	while ((i = ffs((long)openmask)) != 0) {
0X		i--;
0X		openmask &= ~(1 << i);
0X		if (nlp->d_npartitions <= i)
0X			return (EBUSY);
0X		opp = &olp->d_partitions[i];
0X		npp = &nlp->d_partitions[i];
0X		if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
0X			return (EBUSY);
0X		/*
0X		 * Copy internally-set partition information
0X		 * if new label doesn't include it.		XXX
0X		 */
0X		if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
0X			npp->p_fstype = opp->p_fstype;
0X			npp->p_fsize = opp->p_fsize;
0X			npp->p_frag = opp->p_frag;
0X		}
0X	}
0X 	nlp->d_checksum = 0;
0X 	nlp->d_checksum = dkcksum(nlp);
0X	bcopy(nlp, olp, sizeof (struct disklabel));
0X	return (0);
0X}
0X
0X/*
0X * Write disk label back to device after modification.
0X */
0Xint
0Xwritedisklabel(dev, strat, lp)
0X	dev_t dev;
0X	int (*strat)();
0X	register struct disklabel *lp;
0X{
0X	struct buf *bp;
0X	struct disklabel *dlp;
0X	int labelpart;
0X	int error = 0;
0X
0X	labelpart = dkpart(dev);
0X	if (lp->d_partitions[labelpart].p_offset != 0) {
0X		if (lp->d_partitions[0].p_offset != 0)
0X			return (EXDEV);			/* not quite right */
0X		labelpart = 0;
0X	}
0X	bp = geteblk();
0X	bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
0X	bp->b_blkno = LABELSECTOR;
0X	bp->b_bcount = lp->d_secsize;	/* probably should wire to 512 */
0X	bp->b_flags = B_READ;
0X	(*strat)(bp);
0X	biowait(bp);
0X	if (u.u_error)
0X		goto done;
0X	dlp = (struct disklabel *)mapin(bp);
0X	if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
0X	    dkcksum(dlp) == 0) {
0X		bcopy(lp, dlp, sizeof (struct disklabel));
0X		mapout(bp);
0X		bp->b_flags = B_WRITE;
0X		(*strat)(bp);
0X		biowait(bp);
0X		error = u.u_error;
0X	} else {
0X		error = ESRCH;
0X		mapout(bp);
0X	}
0Xdone:
0X	brelse(bp);
0X	return(error);
0X}
0X
0X/*
0X * Compute checksum for disk label.
0X */
0Xdkcksum(lp)
0X	struct disklabel *lp;
0X{
0X	register u_short *start, *end;
0X	register u_short sum = 0;
0X
0X	start = (u_short *)lp;
0X	end = (u_short *)&lp->d_partitions[lp->d_npartitions];
0X	while (start < end)
0X		sum ^= *start++;
0X	return (sum);
0X}
0X
0X/*
0X * This is new for 2.11BSD.  It is a common routine that checks for
0X * opening a partition that overlaps other currently open partitions.
0X *
0X * NOTE: if 'c' is not the entire drive (as is the case with the old, 
0X * nonstandard, haphazard and overlapping partition tables) the warning 
0X * message will be erroneously issued in some valid situations.
0X*/
0X
0X#define	RAWPART	2	/* 'c' */  /* XXX */
0X
0Xdkoverlapchk(openmask, dev, label, name)
0X	int	openmask;
0X	dev_t	dev;
0X	memaddr	label;
0X	char	*name;
0X	{
0X	int	unit = dkunit(dev);
0X	int	part = dkpart(dev);
0X	int	partmask = 1 << part;
0X	int	i;
0X	daddr_t	start, end;
0X	register struct disklabel *lp = (struct disklabel *)SEG5;
0X	register struct partition *pp;
0X
0X	if	((openmask & partmask) == 0 && part != RAWPART)
0X		{
0X		mapseg5(label, LABELDESC);
0X		pp = &lp->d_partitions[part];
0X		start = pp->p_offset;
0X		end = pp->p_offset + pp->p_size;
0X		i = 0;
0X		for	(pp = lp->d_partitions; i < lp->d_npartitions; pp++,i++)
0X			{
0X			if	(pp->p_offset + pp->p_size <= start ||
0X				 pp->p_offset >= end || i == RAWPART)
0X				continue;
0X			if	(openmask & (1 << i))
0X				log(LOG_WARNING,
0X					"%s%d%c: overlaps open part (%c)\n",
0X					name, unit, part + 'a', i + 'a');
0X			}
0X		normalseg5();
0X		}
0X	return(0);
0X	}
0X
0X/*
0X * It was noticed that the ioctl processing of disklabels was the same
0X * for every disk driver.  Disk drivers should call this routine after
0X * handling ioctls (if any) particular to themselves.
0X*/
0X
0Xioctldisklabel(dev, cmd, data, flag, disk, strat)
0X	dev_t	dev;
0X	int	cmd;
0X	register caddr_t	data;
0X	int	flag;
0X	register struct	dkdevice *disk;
0X	int	(*strat)();
0X	{
0X	struct	disklabel label;
0X	register struct	disklabel *lp = &label;
0X	int	error;
0X	int	flags;
0X
0X/*
0X * Copy in mapped out label to the local copy on the stack.  We're in the
0X * high kernel at this point so saving the mapping is not necessary.
0X*/
0X	mapseg5(disk->dk_label, LABELDESC);
0X	bcopy((struct disklabel *)SEG5, lp, sizeof (*lp));
0X	normalseg5();
0X
0X	switch	(cmd)
0X		{
0X		case	DIOCGDINFO:
0X			bcopy(lp, (struct disklabel *)data, sizeof (*lp));
0X			return(0);
0X/*
0X * Used internally by the kernel in init_main to verify that 'swapdev'
0X * is indeed a FS_SWAP partition.
0X *
0X * NOTE: the label address is the external click address!
0X*/
0X		case	DIOCGPART:
0X			((struct partinfo *)data)->disklab = 
0X					(struct disklabel *)disk->dk_label;
0X			((struct partinfo *)data)->part = 
0X						&disk->dk_parts[dkpart(dev)];
0X			return(0);
0X		case	DIOCWLABEL:
0X			if	((flag & FWRITE) == 0)
0X				return(EBADF);
0X			if	(*(int *)data)
0X				disk->dk_flags |= DKF_WLABEL;
0X			else
0X				disk->dk_flags &= ~DKF_WLABEL;
0X			return(0);
0X		case	DIOCSDINFO:
0X			if	((flag & FWRITE) == 0)
0X				return(EBADF);
0X			error = setdisklabel(lp, (struct disklabel *)data,
0X					disk->dk_flags & DKF_WLABEL ? 0
0X					: disk->dk_openmask);
0X/*
0X * If no error was encountered setting the disklabel then we must copy
0X * out the new label from the local copy to the mapped out label.   Also
0X * update the partition tables (which are resident in the kernel).
0X*/
0X			if	(error == 0)
0X				{
0X				mapseg5(disk->dk_label, LABELDESC);
0X				bcopy(lp,(struct disklabel *)SEG5,sizeof (*lp));
0X				normalseg5();
0X				bcopy(&lp->d_partitions, &disk->dk_parts, 
0X					sizeof (lp->d_partitions));
0X				}
0X			return(error);
0X		case	DIOCWDINFO:
0X			if	((flag & FWRITE) == 0)
0X				return(EBADF);
0X			error = setdisklabel(lp, (struct disklabel *)data,
0X					disk->dk_flags & DKF_WLABEL ? 0
0X					: disk->dk_openmask);
0X			if	(error)
0X				return(error);
0X/*
0X * Copy to external label.  Ah - need to also update the kernel resident
0X * partition tables!
0X*/
0X			mapseg5(disk->dk_label, LABELDESC);
0X			bcopy(lp,(struct disklabel *)SEG5,sizeof (*lp));
0X			normalseg5();
0X			bcopy(&lp->d_partitions, &disk->dk_parts, 
0X				sizeof (lp->d_partitions));
0X
0X/*
0X * We use the 'a' partition to write the label.  This probably shouldn't
0X * be wired in here but it's not worth creating another macro for.  Is it?
0X * The flags are faked to write enable the label area and that the drive is
0X * alive - it better be at this point or there is a problem in the open routine.
0X*/
0X			flags = disk->dk_flags;
0X			disk->dk_flags |= (DKF_ALIVE | DKF_WLABEL);
0X			error = writedisklabel(dev & ~7, strat, lp);
0X			disk->dk_flags = flags;
0X			return(error);
0X		}
0X	return(EINVAL);
0X	}
0SHAR_EOF
0fi
0exit 0
0#	End of shell archive
SHAR_EOF
fi
if test -f 'sys.patch'
then
	echo shar: "will not over-write existing file 'sys.patch'"
else
sed 's/^0//' << \SHAR_EOF > 'sys.patch'
0*** /usr/src/sys/sys/sys_inode.c.old	Fri Jan  6 23:36:24 1995
0--- /usr/src/sys/sys/sys_inode.c	Sun May 21 17:04:37 1995
0***************
0*** 3,9 ****
0   * All rights reserved.  The Berkeley software License Agreement
0   * specifies the terms and conditions for redistribution.
0   *
0!  *	@(#)sys_inode.c	1.3 (2.11BSD GTE) 1/6/95
0   */
0  
0  #include "param.h"
0--- 3,9 ----
0   * All rights reserved.  The Berkeley software License Agreement
0   * specifies the terms and conditions for redistribution.
0   *
0!  *	@(#)sys_inode.c	1.5 (2.11BSD GTE) 1995/05/21
0   */
0  
0  #include "param.h"
0***************
0*** 486,492 ****
0  			u.u_error = EINTR;	/* ??? */
0  		return;
0  	}
0! 	(*cfunc)(dev, flag);
0  }
0  
0  /*
0--- 486,492 ----
0  			u.u_error = EINTR;	/* ??? */
0  		return;
0  	}
0! 	(*cfunc)(dev, flag, mode);
0  }
0  
0  /*
0***************
0*** 640,646 ****
0  					return(EPERM);
0  			}
0  		}
0! 		return ((*cdevsw[maj].d_open)(dev, mode));
0  
0  	case IFBLK:
0  		if ((u_int)maj >= nblkdev)
0--- 640,646 ----
0  					return(EPERM);
0  			}
0  		}
0! 		return ((*cdevsw[maj].d_open)(dev, mode, S_IFCHR));
0  
0  	case IFBLK:
0  		if ((u_int)maj >= nblkdev)
0***************
0*** 667,673 ****
0  		if (securelevel > 0 && (error = ufs_mountedon(dev)))
0  			return(error);
0  #endif
0! 		return ((*bdevsw[maj].d_open)(dev, mode));
0  	}
0  	return (0);
0  }
0--- 667,673 ----
0  		if (securelevel > 0 && (error = ufs_mountedon(dev)))
0  			return(error);
0  #endif
0! 		return ((*bdevsw[maj].d_open)(dev, mode, S_IFBLK));
0  	}
0  	return (0);
0  }
0*** /usr/src/sys/sys/init_main.c.old	Fri Jan  6 21:58:25 1995
0--- /usr/src/sys/sys/init_main.c	Mon May 22 20:20:55 1995
0***************
0*** 3,9 ****
0   * All rights reserved.  The Berkeley software License Agreement
0   * specifies the terms and conditions for redistribution.
0   *
0!  *	@(#)init_main.c	1.7 (2.11BSD GTE) 1/6/95
0   */
0  
0  #include "param.h"
0--- 3,9 ----
0   * All rights reserved.  The Berkeley software License Agreement
0   * specifies the terms and conditions for redistribution.
0   *
0!  *	@(#)init_main.c	1.9 (2.11BSD GTE) 1995/05/22
0   */
0  
0  #include "param.h"
0***************
0*** 14,22 ****
0--- 14,24 ----
0  #include "mount.h"
0  #include "map.h"
0  #include "proc.h"
0+ #include "ioctl.h"
0  #include "inode.h"
0  #include "conf.h"
0  #include "buf.h"
0+ #include "fcntl.h"
0  #include "vm.h"
0  #include "clist.h"
0  #include "uba.h"
0***************
0*** 24,29 ****
0--- 26,33 ----
0  #include "systm.h"
0  #include "kernel.h"
0  #include "namei.h"
0+ #include "disklabel.h"
0+ #include "stat.h"
0  #ifdef QUOTA
0  #include "quota.h"
0  #endif
0***************
0*** 57,62 ****
0--- 61,68 ----
0  	register struct fs *fs;
0  	time_t  toytime, toyclk();
0  	daddr_t swsize;
0+ 	int	(*ioctl)();
0+ 	struct	partinfo dpart;
0  
0  	startup();
0  
0***************
0*** 147,156 ****
0   * 'swplo' was a hack which has _finally_ gone away!  It was never anything
0   * but 0 and caused a number of double word adds in the kernel.
0  */
0! 	(*bdevsw[major(swapdev)].d_open)(swapdev, B_READ|B_WRITE);
0  	swsize = (*bdevsw[major(swapdev)].d_psize)(swapdev);
0! 	if	(swsize < 0)
0! 		panic("swsize");	/* don't want to panic, but what ? */
0  	if	(swsize > (daddr_t)65535)
0  		swsize = 65535;
0  	nswap = swsize;
0--- 153,176 ----
0   * 'swplo' was a hack which has _finally_ gone away!  It was never anything
0   * but 0 and caused a number of double word adds in the kernel.
0  */
0! 	(*bdevsw[major(swapdev)].d_open)(swapdev, FREAD|FWRITE, S_IFBLK);
0  	swsize = (*bdevsw[major(swapdev)].d_psize)(swapdev);
0! 	if	(swsize <= 0)
0! 		panic("swsiz");		/* don't want to panic, but what ? */
0! 
0! /*
0!  * Next we make sure that we do not swap on a partition unless it is of
0!  * type FS_SWAP.  If the driver does not have an ioctl entry point or if
0!  * retrieving the partition information fails then the driver does not 
0!  * support labels and we proceed normally, otherwise the partition must be
0!  * a swap partition (so that we do not swap on top of a filesystem by mistake).
0! */
0! 	ioctl = cdevsw[major(swapdev)].d_ioctl;
0! 	if	(ioctl && !(*ioctl)(swapdev, DIOCGPART, (caddr_t)&dpart, FREAD))
0! 		{
0! 		if	(dpart.part->p_fstype != FS_SWAP)
0! 			panic("swtyp");
0! 		}
0  	if	(swsize > (daddr_t)65535)
0  		swsize = 65535;
0  	nswap = swsize;
0***************
0*** 180,186 ****
0  
0  #ifdef INET
0  	if (netoff = netinit())
0! 		printf("Network init failed\n");
0  	else
0  		NETSTART();
0  #endif
0--- 200,206 ----
0  
0  #ifdef INET
0  	if (netoff = netinit())
0! 		printf("netinit failed\n");
0  	else
0  		NETSTART();
0  #endif
0*** /usr/src/sys/sys/ufs_mount.c.old	Fri Jan  6 21:20:24 1995
0--- /usr/src/sys/sys/ufs_mount.c	Sun May 21 17:18:30 1995
0***************
0*** 3,9 ****
0   * All rights reserved.  The Berkeley software License Agreement
0   * specifies the terms and conditions for redistribution.
0   *
0!  *	@(#)ufs_mount.c	1.3 (2.11BSD GTE) 1/6/95
0   */
0  
0  #include "param.h"
0--- 3,9 ----
0   * All rights reserved.  The Berkeley software License Agreement
0   * specifies the terms and conditions for redistribution.
0   *
0!  *	@(#)ufs_mount.c	1.5 (2.11BSD GTE) 1995/05/21
0   */
0  
0  #include "param.h"
0***************
0*** 18,23 ****
0--- 18,24 ----
0  #include "file.h"
0  #include "namei.h"
0  #include "conf.h"
0+ #include "stat.h"
0  #ifdef QUOTA
0  #include "quota.h"
0  #endif
0***************
0*** 81,87 ****
0  	int needclose = 0;
0  
0  	error =
0! 	    (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE);
0  	if (error)
0  		goto out;
0  	needclose = 1;
0--- 82,88 ----
0  	int needclose = 0;
0  
0  	error =
0! 	    (*bdevsw[major(dev)].d_open)(dev, ronly ? FREAD : FREAD|FWRITE, S_IFBLK);
0  	if (error)
0  		goto out;
0  	needclose = 1;
0***************
0*** 133,139 ****
0  	if (tp)
0  		brelse(tp);
0  	if (needclose) {
0! 		(*bdevsw[major(dev)].d_close)(dev, ronly? FREAD : FREAD|FWRITE);
0  		binval(dev);
0  	}
0  	u.u_error = error;
0--- 134,141 ----
0  	if (tp)
0  		brelse(tp);
0  	if (needclose) {
0! 		(*bdevsw[major(dev)].d_close)(dev, 
0! 			ronly? FREAD : FREAD|FWRITE, S_IFBLK);
0  		binval(dev);
0  	}
0  	u.u_error = error;
0***************
0*** 189,195 ****
0  	irele(ip);
0  	mp->m_inodp = 0;
0  	mp->m_dev = 0;
0! 	(*bdevsw[major(dev)].d_close)(dev, 0);
0  	binval(dev);
0  	return (0);
0  }
0--- 191,197 ----
0  	irele(ip);
0  	mp->m_inodp = 0;
0  	mp->m_dev = 0;
0! 	(*bdevsw[major(dev)].d_close)(dev, 0, S_IFBLK);
0  	binval(dev);
0  	return (0);
0  }
SHAR_EOF
fi
exit 0
#	End of shell archive
