* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)nfs_vfsops.c 7.4 (Berkeley) %G%
#include "../netinet/in.h"
struct vfsops nfs_vfsops
= {
extern struct nfsreq nfsreqh
;
* Called by vfs_mountroot when nfs is going to be mounted as root
* Not Yet (By a LONG shot)
* It seems a bit dumb to copyinstr() the host and path here and then
* bcopy() them in mountnfs(), but I wanted to detect errors before
* doing the sockargs() call because sockargs() allocates an mbuf and
* an error after that means that I have to release the mbuf.
nfs_mount(mp
, path
, data
, ndp
)
char pth
[MNAMELEN
], hst
[MNAMELEN
];
if (error
= copyin(data
, (caddr_t
)&args
, sizeof (struct nfs_args
)))
if (error
=copyin((caddr_t
)args
.fh
, (caddr_t
)&nfh
, sizeof (nfsv2fh_t
)))
if (error
= copyinstr(path
, pth
, MNAMELEN
-1, &len
))
bzero(&pth
[len
], MNAMELEN
-len
);
if (error
= copyinstr(args
.hostname
, hst
, MNAMELEN
-1, &len
))
bzero(&hst
[len
], MNAMELEN
-len
);
/* sockargs() call must be after above copyin() calls */
if (error
= sockargs(&saddr
, (caddr_t
)args
.addr
,
sizeof (struct sockaddr_in
), MT_SONAME
))
error
= mountnfs(&args
, mp
, saddr
, pth
, hst
);
* Common code for mount and mountroot
mountnfs(argp
, mp
, saddr
, pth
, hst
)
register struct nfs_args
*argp
;
register struct mount
*mp
;
register struct mbuf
*saddr
;
register struct nfsmount
*nmp
;
struct statfs statf
, *sbp
;
nmp
= (struct nfsmount
*)malloc(sizeof (struct nfsmount
), M_NFSMNT
,
mp
->m_data
= (qaddr_t
)nmp
;
mp
->m_fsid
.val
[0] = ++nfs_mntid
;
mp
->m_fsid
.val
[1] = MOUNT_NFS
;
nmp
->nm_flag
= argp
->flags
;
nmp
->nm_sockaddr
= saddr
;
if (error
= socreate(AF_INET
, &nmp
->nm_so
, SOCK_DGRAM
, 0))
if (error
= soconnect(nmp
->nm_so
, saddr
))
if ((argp
->flags
& NFSMNT_TIMEO
) && argp
->timeo
>= 1)
nmp
->nm_timeo
= argp
->timeo
;
nmp
->nm_timeo
= NFS_TIMEO
;
if ((argp
->flags
& NFSMNT_RETRANS
) && argp
->retrans
> 0)
nmp
->nm_retrans
= argp
->retrans
;
nmp
->nm_retrans
= NFS_RETRANS
;
if ((argp
->flags
& NFSMNT_WSIZE
) &&
argp
->wsize
<= NFS_MAXDATA
&& argp
->wsize
> 0 &&
(argp
->wsize
& 0x1ff) == 0)
nmp
->nm_wsize
= argp
->wsize
;
nmp
->nm_wsize
= NFS_WSIZE
;
if ((argp
->flags
& NFSMNT_RSIZE
) &&
argp
->rsize
<= NFS_MAXDATA
&& argp
->rsize
> 0 &&
(argp
->rsize
& 0x1ff) == 0)
nmp
->nm_rsize
= argp
->rsize
;
nmp
->nm_rsize
= NFS_RSIZE
;
bcopy((caddr_t
)argp
->fh
, (caddr_t
)&nmp
->nm_fh
, sizeof(nfsv2fh_t
));
bcopy(pth
, nmp
->nm_path
, MNAMELEN
);
bcopy(hst
, nmp
->nm_host
, MNAMELEN
);
* To do an interruptable hard mount, turn it into a soft mount
* with a retry limit of one and then repeat it so long as it
* times out and there is no pending signal for the process.
* It is tempting to just let nfs_statfs() sleep at positive
* prio, but then you would long jump out without taking the
* mount structure back out of the list.
* NB: NFSMNT_INT must NEVER be set for nfs_mountroot(), since
* the process context is not yet built!!
if ((argp
->flags
&& NFSMNT_INT
) && (argp
->flags
& NFSMNT_SOFT
) == 0) {
nmp
->nm_flag
|= NFSMNT_SOFT
;
savretrans
= nmp
->nm_retrans
;
error
= nfs_statfs(mp
, sbp
);
} while (error
== ETIMEDOUT
&& (u
.u_procp
->p_sig
&
(sigmask(SIGINT
)|sigmask(SIGQUIT
)|sigmask(SIGTERM
)|
sigmask(SIGKILL
))) == 0);
nmp
->nm_retrans
= savretrans
;
nmp
->nm_flag
&= ~NFSMNT_SOFT
;
} else if (error
= nfs_statfs(mp
, sbp
))
mp
->m_fsize
= sbp
->f_fsize
;
* If the block size is not an exact multiple of CLBYTES
* use CLBYTES so that paging in ZMAGIC executables doesn't
* get sick. (It is used by vinitfod())
if (sbp
->f_bsize
>= CLBYTES
&& claligned(sbp
->f_bsize
))
mp
->m_bsize
= sbp
->f_bsize
;
* Set to CLBYTES so that vinifod() doesn't get confused.
* Actually any exact multiple of CLBYTES will do
mp
->m_bsize
= mp
->m_fsize
= CLBYTES
;
free((caddr_t
)nmp
, M_NFSMNT
);
register struct nfsmount
*nmp
;
register struct nfsreq
*rep
;
* Clear out the buffer cache
* Goes something like this..
* - Call nfs_nflush() to clear out the nfsnode table
* - Flush out lookup cache
* - Free up the data structures
if (error
= nfs_nflush(mp
)) {
* Scan the request list for any requests left hanging about
if (rep
->r_mntp
== nmp
) {
rep
->r_prev
->r_next
= rep2
= rep
->r_next
;
rep
->r_next
->r_prev
= rep
->r_prev
;
free((caddr_t
)rep
, M_NFSREQ
);
m_freem(nmp
->nm_sockaddr
);
free((caddr_t
)nmp
, M_NFSMNT
);
* Return root of a filesystem
register struct vnode
*vp
;
if (error
= nfs_nget(mp
, &nmp
->nm_fh
, &np
))
* Flush out the buffer cache
* Force stale buffer cache information to be flushed.
* At this point, this should never happen
* Vnode pointer to File handle, should never happen either
* Vfs start routine, a no-op.