struct vfsops isofs_vfsops
= {
(void *)enodev
, /* quotactl */
* Called by vfs_mountroot when ufs is going to be mounted as root.
* Name is updated by mount(8) after booting.
#define ROOTNAME "root_device"
register struct mount
*mp
;
extern struct vnode
*rootvp
;
struct proc
*p
= curproc
; /* XXX */
mp
= (struct mount
*)malloc((u_long
)sizeof(struct mount
),
mp
->mnt_op
= &isofs_vfsops
;
mp
->mnt_flag
= MNT_RDONLY
;
error
= iso_mountfs(rootvp
, mp
, p
);
free((caddr_t
)mp
, M_MOUNT
);
if (error
= vfs_lock(mp
)) {
(void)isofs_unmount(mp
, 0, p
);
free((caddr_t
)mp
, M_MOUNT
);
mp
->mnt_vnodecovered
= NULLVP
;
bzero(imp
->im_fsmnt
, sizeof(imp
->im_fsmnt
));
bcopy((caddr_t
)imp
->im_fsmnt
, (caddr_t
)mp
->mnt_stat
.f_mntonname
,
(void) copystr(ROOTNAME
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
(void) isofs_statfs(mp
, &mp
->mnt_stat
, p
);
* Flag to allow forcible unmounting.
isofs_mount(mp
, path
, data
, ndp
, p
)
register struct mount
*mp
;
if (error
= copyin(data
, (caddr_t
)&args
, sizeof (struct ufs_args
)))
if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
* Process export requests.
if ((args
.exflags
& MNT_EXPORTED
) || (mp
->mnt_flag
& MNT_EXPORTED
)) {
if (args
.exflags
& MNT_EXPORTED
)
mp
->mnt_flag
|= MNT_EXPORTED
;
mp
->mnt_flag
&= ~MNT_EXPORTED
;
if (args
.exflags
& MNT_EXRDONLY
)
mp
->mnt_flag
|= MNT_EXRDONLY
;
mp
->mnt_flag
&= ~MNT_EXRDONLY
;
mp
->mnt_exroot
= args
.exroot
;
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
if (mp
->mnt_flag
& MNT_UPDATE
) {
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= args
.fspec
;
if (error
= namei(ndp
, p
))
if (devvp
->v_type
!= VBLK
) {
if (major(devvp
->v_rdev
) >= nblkdev
) {
if ((mp
->mnt_flag
& MNT_UPDATE
) == 0)
error
= iso_mountfs(devvp
, mp
, p
);
if (devvp
!= imp
->im_devvp
)
error
= EINVAL
; /* needs translation */
(void) copyinstr(path
, imp
->im_fsmnt
, sizeof(imp
->im_fsmnt
)-1, &size
);
bzero(imp
->im_fsmnt
+ size
, sizeof(imp
->im_fsmnt
) - size
);
bcopy((caddr_t
)imp
->im_fsmnt
, (caddr_t
)mp
->mnt_stat
.f_mntonname
,
(void) copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
(void) isofs_statfs(mp
, &mp
->mnt_stat
, p
);
* Common code for mount and mountroot
iso_mountfs(devvp
, mp
, p
)
register struct vnode
*devvp
;
register struct iso_mnt
*isomp
= (struct iso_mnt
*)0;
dev_t dev
= devvp
->v_rdev
;
int error
= EINVAL
, i
, size
;
int ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
extern struct vnode
*rootvp
;
struct iso_volume_descriptor
*vdp
;
struct iso_primary_descriptor
*pri
;
struct iso_directory_record
*rootp
;
* Disallow multiple mounts of the same device.
* Disallow mounting of a device that is currently in use
* (except for root, which might share swap device for miniroot).
* Flush out any old buffers remaining from a previous use.
if (error
= iso_mountedon(devvp
))
if (vcount(devvp
) > 1 && devvp
!= rootvp
)
if (error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, NOCRED
, p
))
/* This is the "logical sector size". The standard says this
* should be 2048 or the physical sector size on the device,
* whichever is greater. For now, we'll just use a constant.
for (iso_blknum
= 16; iso_blknum
< 100; iso_blknum
++) {
if (error
= bread (devvp
, iso_blknum
* iso_bsize
/ DEV_BSIZE
,
vdp
= (struct iso_volume_descriptor
*)bp
->b_un
.b_addr
;
if (bcmp (vdp
->id
, ISO_STANDARD_ID
, sizeof vdp
->id
) != 0) {
if (isonum_711 (vdp
->type
) == ISO_VD_END
) {
if (isonum_711 (vdp
->type
) == ISO_VD_PRIMARY
)
if (isonum_711 (vdp
->type
) != ISO_VD_PRIMARY
) {
pri
= (struct iso_primary_descriptor
*)vdp
;
logical_block_size
= isonum_723 (pri
->logical_block_size
);
if (logical_block_size
< DEV_BSIZE
|| logical_block_size
>= MAXBSIZE
|| (logical_block_size
& (logical_block_size
- 1)) != 0) {
rootp
= (struct iso_directory_record
*)pri
->root_directory_record
;
isomp
= (struct iso_mnt
*)malloc(sizeof *isomp
,M_UFSMNT
,M_WAITOK
);
isomp
->logical_block_size
= logical_block_size
;
isomp
->volume_space_size
= isonum_733 (pri
->volume_space_size
);
bcopy (rootp
, isomp
->root
, sizeof isomp
->root
);
isomp
->root_extent
= isonum_733 (rootp
->extent
);
isomp
->root_size
= isonum_733 (rootp
->size
);
isomp
->im_bsize
= logical_block_size
;
isomp
->im_bmask
= ~(isomp
->im_bsize
- 1);
while ((1 << isomp
->im_bshift
) < isomp
->im_bsize
)
mp
->mnt_data
= (qaddr_t
)isomp
;
mp
->mnt_stat
.f_fsid
.val
[0] = (long)dev
;
mp
->mnt_stat
.f_fsid
.val
[1] = MOUNT_ISOFS
;
mp
->mnt_flag
|= MNT_LOCAL
;
devvp
->v_specflags
|= SI_MOUNTEDON
;
(void)VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, NOCRED
, p
);
free((caddr_t
)isomp
, M_UFSMNT
);
mp
->mnt_data
= (qaddr_t
)0;
* Make a filesystem operational.
* Nothing to do at the moment.
isofs_start(mp
, flags
, p
)
isofs_unmount(mp
, mntflags
, p
)
register struct iso_mnt
*isomp
;
int i
, error
, ronly
, flags
= 0;
if (mntflags
& MNT_FORCE
) {
if (!iso_doforce
|| mp
== rootfs
)
if (error
= vflush(mp
, NULLVP
, flags
))
ronly
= !isomp
->im_ronly
;
isomp
->im_devvp
->v_specflags
&= ~SI_MOUNTEDON
;
error
= VOP_CLOSE(isomp
->im_devvp
, ronly
? FREAD
: FREAD
|FWRITE
,
free((caddr_t
)isomp
, M_UFSMNT
);
mp
->mnt_data
= (qaddr_t
)0;
mp
->mnt_flag
&= ~MNT_LOCAL
;
* Check to see if a filesystem is mounted on a block device.
register struct vnode
*vp
;
register struct vnode
*vq
;
if (vp
->v_specflags
& SI_MOUNTEDON
)
if (vp
->v_flag
& VALIASED
) {
for (vq
= *vp
->v_hashchain
; vq
; vq
= vq
->v_specnext
) {
if (vq
->v_rdev
!= vp
->v_rdev
||
vq
->v_type
!= vp
->v_type
)
if (vq
->v_specflags
& SI_MOUNTEDON
)
* Return root of a filesystem
register struct iso_node
*ip
;
struct iso_mnt
*imp
= VFSTOISOFS (mp
);
error
= iso_iget(ip
, imp
->root_extent
, &nip
,
(struct iso_directory_record
*) imp
->root
);
* Get file system statistics.
register struct statfs
*sbp
;
register struct iso_mnt
*isomp
;
sbp
->f_type
= MOUNT_ISOFS
;
sbp
->f_fsize
= isomp
->logical_block_size
;
sbp
->f_bsize
= sbp
->f_fsize
;
sbp
->f_blocks
= isomp
->volume_space_size
;
sbp
->f_bfree
= 0; /* total free blocks */
sbp
->f_bavail
= 0; /* blocks free for non superuser */
sbp
->f_files
= 0; /* total files */
sbp
->f_ffree
= 0; /* free file nodes */
if (sbp
!= &mp
->mnt_stat
) {
bcopy((caddr_t
)mp
->mnt_stat
.f_mntonname
,
(caddr_t
)&sbp
->f_mntonname
[0], MNAMELEN
);
bcopy((caddr_t
)mp
->mnt_stat
.f_mntfromname
,
(caddr_t
)&sbp
->f_mntfromname
[0], MNAMELEN
);
* Have to be really careful about stale file handles:
* - check that the inode number is in range
* - call iget() to get the locked inode
* - check for an unallocated inode (i_mode == 0)
* - check that the generation number matches
isofs_fhtovp(mp
, fhp
, vpp
)
register struct mount
*mp
;
/* here's a guess at what we need here */
ifhp
= (struct ifid
*)fhp
;
if (ifhp
->ifid_lbn
>= imp
->volume_space_size
)
if (ifhp
->ifid_offset
+ sizeof (struct iso_directory_record
)
bread (isomp
->im_devvp
, ifhp
->ifid_lbn
, imp
->im_bsize
, NOCRED
, &bp
);
dirp
= bp
->b_un
.b_addr
+ ifhp
->ifid_offset
;
if (ifhp
->ifid_offset
+ isonum_711 (dirp
) >= imp
->im_bsize
) {
if (error
= iso_iget(ip
, ifhp
->ifid_ino
, &nip
, dirp
)) {
* Vnode pointer to File handle
register struct inode
*ip
= VTOI(vp
);
register struct ufid
*ufhp
;
ufhp
= (struct ufid
*)fhp
;
ufhp
->ufid_len
= sizeof(struct ufid
);
ufhp
->ufid_ino
= ip
->i_number
;
ufhp
->ufid_gen
= ip
->i_gen
;