* Copyright (c) 1990 Jan-Simon Pendry
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
* Copyright (c) 1990 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)mntfs.c 5.3 (Berkeley) 5/12/91
* $Id: mntfs.c,v 5.2.1.7 91/05/07 22:18:11 jsp Alpha $
qelem mfhead
= { &mfhead
, &mfhead
};
* This is the default attributes field which
* is copied into every new node to be created.
* The individual filesystem fs_init() routines
* patch the copy to represent the particular
* details for the relevant filesystem type
static struct fattr gen_fattr
= {
NFSMODE_DIR
| 0555, /* mode */
mf
->mf_flags
&= ~MFF_ERROR
;
static int init_mntfs
P((mntfs
*mf
, am_ops
*ops
, am_opts
*mo
, char *mp
, char *info
, char *auto_opts
, char *mopts
));
static int init_mntfs(mf
, ops
, mo
, mp
, info
, auto_opts
, mopts
)
mf
->mf_mount
= strdup(mp
);
mf
->mf_info
= strdup(info
);
mf
->mf_auto
= strdup(auto_opts
);
mf
->mf_mopts
= strdup(mopts
);
mf
->mf_attr
.status
= NFS_OK
;
mf
->mf_fattr
= gen_fattr
;
mf
->mf_fattr
.atime
.seconds
= clocktime();
mf
->mf_fattr
.atime
.useconds
= 0;
mf
->mf_fattr
.mtime
= mf
->mf_fattr
.ctime
= mf
->mf_fattr
.atime
;
mf
->mf_server
= (*ops
->ffserver
)(mf
);
static mntfs
*alloc_mntfs
P((am_ops
*ops
, am_opts
*mo
, char *mp
, char *info
, char *auto_opts
, char *mopts
));
static mntfs
*alloc_mntfs(ops
, mo
, mp
, info
, auto_opts
, mopts
)
mntfs
*mf
= ALLOC(mntfs
);
init_mntfs(mf
, ops
, mo
, mp
, info
, auto_opts
, mopts
);
ins_que(&mf
->mf_q
, &mfhead
);
mntfs
*find_mntfs
P((am_ops
*ops
, am_opts
*mo
, char *mp
, char *info
, char *auto_opts
, char *mopts
));
mntfs
*find_mntfs(ops
, mo
, mp
, info
, auto_opts
, mopts
)
dlog("Locating mntfs reference to %s", mp
);
ITER(mf
, mntfs
, &mfhead
) {
if (STREQ(mf
->mf_mount
, mp
)) {
* Handle cases where error ops are involved
* If the existing ops are not efs_ops
if (mf
->mf_ops
!= &efs_ops
)
} else /* ops != &efs_ops */ {
* If the existing ops are efs_ops
if (mf
->mf_ops
== &efs_ops
)
if ((mf
->mf_flags
& MFF_RESTART
) && amd_state
== Run
) {
* Restart a previously mounted filesystem.
mntfs
*mf2
= alloc_mntfs(&ifs_ops
, mo
, mp
, info
, auto_opts
, mopts
);
dlog("Restarting filesystem %s", mf
->mf_mount
);
* Remember who we are restarting
mf2
->mf_private
= (voidp
) dup_mntfs(mf
);
mf2
->mf_prfree
= free_mntfs
;
if (!(mf
->mf_flags
& (MFF_MOUNTED
|MFF_MOUNTING
|MFF_UNMOUNTING
))) {
mf
->mf_flags
&= ~MFF_ERROR
;
mf
->mf_auto
= strealloc(mf
->mf_auto
, auto_opts
);
mf
->mf_mopts
= strealloc(mf
->mf_mopts
, mopts
);
mf
->mf_info
= strealloc(mf
->mf_info
, info
);
if (mf
->mf_private
&& mf
->mf_prfree
) {
(*mf
->mf_prfree
)(mf
->mf_private
);
fs
= ops
->ffserver
? (*ops
->ffserver
)(mf
) : (fserver
*) 0;
free_srvr(mf
->mf_server
);
return alloc_mntfs(ops
, mo
, mp
, info
, auto_opts
, mopts
);
return alloc_mntfs(&efs_ops
, (am_opts
*) 0, "//nil//", ".", "", "");
static void uninit_mntfs(mf
, rmd
)
if (mf
->mf_mount
) free((voidp
) mf
->mf_mount
);
if (mf
->mf_auto
) free((voidp
) mf
->mf_auto
);
if (mf
->mf_mopts
) free((voidp
) mf
->mf_mopts
);
if (mf
->mf_info
) free((voidp
) mf
->mf_info
);
if (mf
->mf_private
&& mf
->mf_prfree
)
(*mf
->mf_prfree
)(mf
->mf_private
);
* Clean up any directories that were made
if (rmd
&& (mf
->mf_flags
& MFF_MKMNT
))
* Clean up the file server
free_srvr(mf
->mf_server
);
* Don't do a callback on this mount
static void discard_mntfs(mf
)
mf
= FIRST(mntfs
, &mfhead
);
while (mf
!= HEAD(mntfs
, &mfhead
)) {
if (mf2
->mf_refc
== 0 && mf2
->mf_cid
)
if (--mf
->mf_refc
== 0) {
if (mf
->mf_flags
& MFF_MOUNTED
) {
mf
->mf_flags
&= ~MFF_MOUNTED
;
quoted
= strchr(mf
->mf_info
, ' ') != 0; /* cheap */
plog(XLOG_INFO
, "%s%s%s %sed fstype %s from %s",
mf
->mf_error
? "discard" : "unmount",
mf
->mf_ops
->fs_type
, mf
->mf_mount
);
if (mf
->mf_ops
->fs_flags
& FS_DISCARD
) {
dlog("Immediately discarding mntfs for %s", mf
->mf_mount
);
if (mf
->mf_flags
& MFF_RESTART
) {
dlog("Discarding remount hook for %s", mf
->mf_mount
);
dlog("Discarding last mntfs reference to %s fstype %s",
mf
->mf_mount
, mf
->mf_ops
->fs_type
);
if (mf
->mf_flags
& (MFF_MOUNTED
|MFF_MOUNTING
|MFF_UNMOUNTING
))
dlog("mntfs reference for %s still active", mf
->mf_mount
);
mf
->mf_cid
= timeout(ALLOWED_MOUNT_TIME
, discard_mntfs
, (voidp
) mf
);
mntfs
*realloc_mntfs
P((mntfs
*mf
, am_ops
*ops
, am_opts
*mo
, char *mp
, char *info
, char *auto_opts
, char *mopts
));
mntfs
*realloc_mntfs(mf
, ops
, mo
, mp
, info
, auto_opts
, mopts
)
if (mf
->mf_refc
== 1 && mf
->mf_ops
== &ifs_ops
&& STREQ(mf
->mf_mount
, mp
)) {
* If we are inheriting then just return
* Re-use the existing mntfs if it is mounted.
* This traps a race in nfsx.
if (mf
->mf_ops
!= &efs_ops
&&
(mf
->mf_flags
& MFF_MOUNTED
) &&
!FSRV_ISDOWN(mf
->mf_server
)) {
mf2
= find_mntfs(ops
, mo
, mp
, info
, auto_opts
, mopts
);