first buffer cache implementation; name cache usage; code cleanups
[unix-history] / usr / src / sys / nfs / nfs_vfsops.c
CommitLineData
a2907882
KM
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the University of California, Berkeley. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
9238aa59 20 * @(#)nfs_vfsops.c 7.4 (Berkeley) %G%
a2907882
KM
21 */
22
23#include "param.h"
24#include "signal.h"
25#include "user.h"
26#include "proc.h"
27#include "uio.h"
28#include "ucred.h"
36c3043b 29#include "../ufs/dir.h"
a2907882
KM
30#include "namei.h"
31#include "vnode.h"
32#include "mount.h"
33#include "errno.h"
34#include "malloc.h"
35#include "mbuf.h"
36#undef m_data
37#include "socket.h"
38#include "socketvar.h"
39#include "../netinet/in.h"
40#include "nfsv2.h"
41#include "nfsnode.h"
42#include "nfsmount.h"
43#include "nfs.h"
44
45#ifndef shouldbe
46#include "conf.h"
47#endif
48
49/*
50 * nfs vfs operations.
51 */
52int nfs_mount();
b3226026 53int nfs_start();
a2907882
KM
54int nfs_unmount();
55int nfs_root();
56extern int nfs_statfs();
57int nfs_sync();
58int nfs_fhtovp();
59int nfs_vptofh();
60
61struct vfsops nfs_vfsops = {
62 nfs_mount,
b3226026 63 nfs_start,
a2907882
KM
64 nfs_unmount,
65 nfs_root,
66 nfs_statfs,
67 nfs_sync,
68 nfs_fhtovp,
69 nfs_vptofh,
70};
71
72extern struct nfsreq nfsreqh;
73static long nfs_mntid;
74
75/*
76 * Called by vfs_mountroot when nfs is going to be mounted as root
77 * Not Yet (By a LONG shot)
78 */
79nfs_mountroot()
80{
81 return (ENODEV);
82}
83
84/*
85 * VFS Operations.
86 *
87 * mount system call
88 * It seems a bit dumb to copyinstr() the host and path here and then
89 * bcopy() them in mountnfs(), but I wanted to detect errors before
90 * doing the sockargs() call because sockargs() allocates an mbuf and
91 * an error after that means that I have to release the mbuf.
92 */
93nfs_mount(mp, path, data, ndp)
94 struct mount *mp;
95 char *path;
96 caddr_t data;
97 struct nameidata *ndp;
98{
99 int error;
100 struct nfs_args args;
101 struct mbuf *saddr;
102 char pth[MNAMELEN], hst[MNAMELEN];
103 int len;
104 nfsv2fh_t nfh;
105
106 if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
107 return (error);
108 if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
109 return (error);
110 if (error = copyinstr(path, pth, MNAMELEN-1, &len))
111 return (error);
112 bzero(&pth[len], MNAMELEN-len);
113 if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
114 return (error);
115 bzero(&hst[len], MNAMELEN-len);
116 /* sockargs() call must be after above copyin() calls */
117 if (error = sockargs(&saddr, (caddr_t)args.addr,
118 sizeof (struct sockaddr_in), MT_SONAME))
119 return (error);
120 args.fh = &nfh;
121 error = mountnfs(&args, mp, saddr, pth, hst);
122 return (error);
123}
124
125/*
126 * Common code for mount and mountroot
127 */
128mountnfs(argp, mp, saddr, pth, hst)
129 register struct nfs_args *argp;
130 register struct mount *mp;
131 register struct mbuf *saddr;
132 char *pth, *hst;
133{
134 register struct nfsmount *nmp;
135 struct nfsnode *np;
36c3043b 136#ifdef notdef
a2907882 137 struct statfs statf, *sbp;
36c3043b 138#endif
a2907882
KM
139 int error;
140
141 nmp = (struct nfsmount *)malloc(sizeof (struct nfsmount), M_NFSMNT,
142 M_WAITOK);
143 mp->m_data = (qaddr_t)nmp;
144 mp->m_fsid.val[0] = ++nfs_mntid;
145 mp->m_fsid.val[1] = MOUNT_NFS;
146 nmp->nm_mountp = mp;
147 nmp->nm_flag = argp->flags;
148 nmp->nm_sockaddr = saddr;
149 /* Set up the sockets */
150 if (error = socreate(AF_INET, &nmp->nm_so, SOCK_DGRAM, 0))
151 goto bad;
152 if (error = soconnect(nmp->nm_so, saddr))
153 goto bad;
154 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo >= 1)
155 nmp->nm_timeo = argp->timeo;
156 else
157 nmp->nm_timeo = NFS_TIMEO;
158 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 0)
159 nmp->nm_retrans = argp->retrans;
160 else
161 nmp->nm_retrans = NFS_RETRANS;
162 if ((argp->flags & NFSMNT_WSIZE) &&
163 argp->wsize <= NFS_MAXDATA && argp->wsize > 0 &&
164 (argp->wsize & 0x1ff) == 0)
165 nmp->nm_wsize = argp->wsize;
166 else
167 nmp->nm_wsize = NFS_WSIZE;
168 if ((argp->flags & NFSMNT_RSIZE) &&
169 argp->rsize <= NFS_MAXDATA && argp->rsize > 0 &&
170 (argp->rsize & 0x1ff) == 0)
171 nmp->nm_rsize = argp->rsize;
172 else
173 nmp->nm_rsize = NFS_RSIZE;
174 bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
175 bcopy(pth, nmp->nm_path, MNAMELEN);
176 bcopy(hst, nmp->nm_host, MNAMELEN);
36c3043b 177#ifdef notdef
a2907882
KM
178 sbp = &statf;
179 /*
180 * Kludge City...
181 * To do an interruptable hard mount, turn it into a soft mount
182 * with a retry limit of one and then repeat it so long as it
183 * times out and there is no pending signal for the process.
184 * It is tempting to just let nfs_statfs() sleep at positive
185 * prio, but then you would long jump out without taking the
186 * mount structure back out of the list.
187 * NB: NFSMNT_INT must NEVER be set for nfs_mountroot(), since
188 * the process context is not yet built!!
189 */
190 if ((argp->flags && NFSMNT_INT) && (argp->flags & NFSMNT_SOFT) == 0) {
191 int savretrans;
192
193 nmp->nm_flag |= NFSMNT_SOFT;
194 savretrans = nmp->nm_retrans;
195 nmp->nm_retrans = 1;
196 do {
197 error = nfs_statfs(mp, sbp);
198 } while (error == ETIMEDOUT && (u.u_procp->p_sig &
199 (sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)|
200 sigmask(SIGKILL))) == 0);
201 nmp->nm_retrans = savretrans;
202 nmp->nm_flag &= ~NFSMNT_SOFT;
203 if (error)
204 goto bad;
205 } else if (error = nfs_statfs(mp, sbp))
206 goto bad;
207 mp->m_fsize = sbp->f_fsize;
208
209 /*
210 * If the block size is not an exact multiple of CLBYTES
211 * use CLBYTES so that paging in ZMAGIC executables doesn't
212 * get sick. (It is used by vinitfod())
213 */
214 if (sbp->f_bsize >= CLBYTES && claligned(sbp->f_bsize))
215 mp->m_bsize = sbp->f_bsize;
216 else
217 mp->m_bsize = CLBYTES;
36c3043b
KM
218#else
219 /*
220 * Set to CLBYTES so that vinifod() doesn't get confused.
221 * Actually any exact multiple of CLBYTES will do
222 */
223 mp->m_bsize = mp->m_fsize = CLBYTES;
224#endif
a2907882
KM
225 return (0);
226bad:
227 m_freem(saddr);
228 free((caddr_t)nmp, M_NFSMNT);
229 return (error);
230}
231
232/*
233 * unmount system call
234 */
235nfs_unmount(mp, flags)
236 struct mount *mp;
237 int flags;
238{
239 register struct nfsmount *nmp;
240 register struct nfsreq *rep;
241 struct nfsreq *rep2;
242 int error;
243 int s;
244
245 if (flags & MNT_FORCE)
246 return (EINVAL);
247 nmp = vfs_to_nfs(mp);
9238aa59
RM
248 /*
249 * Clear out the buffer cache
250 */
251 bflush(mp);
252 if (binval(mp))
253 return (EBUSY);
a2907882
KM
254 /*
255 * Goes something like this..
256 * - Call nfs_nflush() to clear out the nfsnode table
257 * - Flush out lookup cache
258 * - Close the socket
259 * - Free up the data structures
260 */
261 if (error = nfs_nflush(mp)) {
262 return (error);
263 }
264 /*
265 * Scan the request list for any requests left hanging about
266 */
267 s = splnet();
268 rep = nfsreqh.r_next;
269 while (rep) {
270 if (rep->r_mntp == nmp) {
271 rep->r_prev->r_next = rep2 = rep->r_next;
272 if (rep->r_next != NULL)
273 rep->r_next->r_prev = rep->r_prev;
274 m_freem(rep->r_mreq);
275 if (rep->r_mrep != NULL)
276 m_freem(rep->r_mrep);
277 free((caddr_t)rep, M_NFSREQ);
278 rep = rep2;
279 } else
280 rep = rep->r_next;
281 }
282 splx(s);
283 soclose(nmp->nm_so);
284 m_freem(nmp->nm_sockaddr);
285 free((caddr_t)nmp, M_NFSMNT);
286 return (0);
287}
288
289/*
290 * Return root of a filesystem
291 */
292nfs_root(mp, vpp)
293 struct mount *mp;
294 struct vnode **vpp;
295{
296 register struct vnode *vp;
297 struct nfsmount *nmp;
298 struct nfsnode *np;
299 int error;
300
301 nmp = vfs_to_nfs(mp);
302 if (error = nfs_nget(mp, &nmp->nm_fh, &np))
303 return (error);
304 vp = NFSTOV(np);
305 vp->v_type = VDIR;
306 vp->v_flag = VROOT;
307 *vpp = vp;
308 return (0);
309}
310
9238aa59
RM
311extern int syncprt;
312
a2907882 313/*
9238aa59 314 * Flush out the buffer cache
a2907882
KM
315 */
316nfs_sync(mp, waitfor)
317 struct mount *mp;
318 int waitfor;
319{
9238aa59
RM
320 if (syncprt)
321 bufstats();
322 /*
323 * Force stale buffer cache information to be flushed.
324 */
325 bflush(mp);
a2907882
KM
326 return (0);
327}
328
329/*
330 * At this point, this should never happen
331 */
332nfs_fhtovp(mp, fhp, vpp)
333 struct mount *mp;
334 struct fid *fhp;
335 struct vnode **vpp;
336{
337 return (EINVAL);
338}
339
340/*
341 * Vnode pointer to File handle, should never happen either
342 */
343nfs_vptofh(mp, fhp, vpp)
344 struct mount *mp;
345 struct fid *fhp;
346 struct vnode **vpp;
347{
348 return (EINVAL);
349}
9238aa59
RM
350
351/*
352 * Vfs start routine, a no-op.
353 */
354nfs_start(mp, flags)
355 struct mount *mp;
356 int flags;
357{
358 return (0);
359}