Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Sep 1998 21:09:06 +0000 (GMT)
From:      Terry Lambert <tlambert@primenet.com>
To:        dag-erli@ifi.uio.no (Dag-Erling C. =?iso-8859-1?Q?Sm=F8rgrav?=)
Cc:        finrod@ewox.org, current@FreeBSD.ORG
Subject:   Re: Strange CAM panics [LONG]
Message-ID:  <199809202109.OAA01085@usr04.primenet.com>
In-Reply-To: <xzp3e9mc2pn.fsf@gjallarhorn.ifi.uio.no> from "Dag-Erling C. =?iso-8859-1?Q?Sm=F8rgrav?=" at Sep 20, 98 03:51:00 pm

next in thread | previous in thread | raw e-mail | index | archive | help
> > The strange thing is that the panic always occurs in mountd, which I
> > wouldn't think was related.
> 
> Update: I commented out the NFS configuration from my rc.conf.local
> (effectively disabling mountd). Everything works just fine.
> 
> Needless to say, it used to work fine *with* NFS enabled before CAM.
> IIRC, the last time I mounted a CD-ROM was when I copied the entire
> 2.2.2-RELEASE CD-ROM to disk last Thursday (September 10th), a few
> days before my CAM conversion.

The mount code for any FS capable of being NFS exported will call the
vfs_export() function.

The real question  here is whether your CDROM is on the list of FS's
you are exporting or not.


The current mount code does:

---------------------------------------------------------------------
vfs_mountrootfs:
	allocate struct mount for new root
	save "mounted from"
	call FS_mount with NULL path
	put FS in mountlist
end vfs_mountrootfs

mount:
	get arguments
	find vnode to be covered
	compatability cruft
	allocate struct mount
	call FS_mount with path to device name
	put FS in mountlist
end mount

FS_mount:
	if path == NULL
		// is root device
		if SLICE
			inherit rootvp from root_device_vnode
		else
			make up rootvp using bdevvp
		endif
		call FS_mountfs

	else
		// is non-root device
		copy in arguments
		if MNT_UPDATE
			do cruft better implemented by unmount/mount
		endif

		look up device node
		do weenie credential checks
		if MNT_UPDATE
			make sure it's the same guy...
			save "mounted on" information
			call vfs_export
		else
			save "last mounted on"
			save "mounted from"
			call FS_mountfs
		endif

	endif
	call FS_statfs to set up the mount struct contents
end FS_mount

FS_mountfs:
	call vfs_mountedon	// is device busy?  if yes, fail.
	call vcount		// is vnode busy?  if ys, fail (BOGUS).
	call vinvalbuf		// flush cached device data (soft updates)
	call vfs_object_create	// enable vmio
	demonstrate promiscuous knowledge of disklabel code
	read the superblock
	fill out in core copy of superblock & per FS mount structure
	update superblock
end FS_mountfs
---------------------------------------------------------------------


Note the this code has to be repeated in each FS implementation, which
is what has led to the current problem: different implementations
result in different interactions with new code.

Corrected code would:

---------------------------------------------------------------------
vfs_mountany:
	allocate struct mount
	call vfs_mountedon	// is device busy?  if yes, fail.
	call vcount		// is vnode busy?  if ys, fail (BOGUS).
	call vinvalbuf		// flush cached device data (soft updates)
	call vfs_object_create	// enable vmio
	demonstrate promiscuous knowledge of disklabel code
	call FS_mount
	call FS_statfs to set up the mount struct contents
	put FS in mountlist
	return &struct mount
end vfs_mountany

vfs_mountrootfs:
	call vfs_mountany with root device vnode, "mounted from", "/"
	set root mount structure to point at struct mount from vfs_mountany
end vfs_mountrootfs

mount:
	get arguments
	look up device node
	find vnode to be covered
	do weenie credential checks
	if MNT_UPDATE
		make sure it's the same guy...
		unmount
		mount	(recurse)
		return
	endif
	call vfs_mountany with device node
	call FS_setmntinfo with "mounted from", "last mounted on"
	set covered vnode to point to vp from struct mount from vfs_mountany
	call vfs_export
end mount

FS_mount:
	read the superblock
	fill out in core copy of superblock & per FS mount structure
	update superblock
end FS_mount
---------------------------------------------------------------------

In other words, the concept of covering a vnode, what a root FS
actually is, whether it's an update, whether the FS is NFS exported,
and all of the other FS consumer specific crap should go into a
common code layer that gets written once, and is never touched
again.

Then things like the CAM problem you are currently having would
either effect *all* FS's (and get fixed) or *no* FS's (and not
be a problem).

It would also remove a significant amount of code duplication, and
immediately support root mounts of all supported FS types, including
ext2, etc..

Oh well...

In any case, your problem is in the code path that depends from
/sys/isofs/cd9660/cd9660_vfsops.c:

        /*
         * If updating, check whether changing from read-only to
         * read/write; if there is no device name, that's all we do.
         * Disallow clearing MNT_NOCLUSTERR flag, if block device requests.
         */
        if (mp->mnt_flag & MNT_UPDATE) {
                imp = VFSTOISOFS(mp);
                if (bdevsw[major(imp->im_devvp->v_rdev)]->d_flags &
                    D_NOCLUSTERR)
                        mp->mnt_flag |= MNT_NOCLUSTERR;
                if (args.fspec == 0) 
                        return (vfs_export(mp, &imp->im_export, &args.export));
        }

Which you will probably have to fix in an FS dependent way, so that it
works in the current framework (at least until the next time it breaks
for not being implemented the same in all FS's, and someone making a bad
assumption about what FS's depend upon and what they don't).


					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199809202109.OAA01085>