mknod must do an abortop and return an error;
[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 *
363ac00e 20 * @(#)nfs_vfsops.c 7.6 (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();
363ac00e 56int nfs_statfs();
a2907882
KM
57int nfs_sync();
58int nfs_fhtovp();
59int nfs_vptofh();
363ac00e 60int nfs_init();
a2907882
KM
61
62struct vfsops nfs_vfsops = {
63 nfs_mount,
b3226026 64 nfs_start,
a2907882
KM
65 nfs_unmount,
66 nfs_root,
67 nfs_statfs,
68 nfs_sync,
69 nfs_fhtovp,
70 nfs_vptofh,
363ac00e 71 nfs_init,
a2907882
KM
72};
73
74extern struct nfsreq nfsreqh;
75static long nfs_mntid;
76
77/*
78 * Called by vfs_mountroot when nfs is going to be mounted as root
79 * Not Yet (By a LONG shot)
80 */
81nfs_mountroot()
82{
83 return (ENODEV);
84}
85
86/*
87 * VFS Operations.
88 *
89 * mount system call
90 * It seems a bit dumb to copyinstr() the host and path here and then
91 * bcopy() them in mountnfs(), but I wanted to detect errors before
92 * doing the sockargs() call because sockargs() allocates an mbuf and
93 * an error after that means that I have to release the mbuf.
94 */
95nfs_mount(mp, path, data, ndp)
96 struct mount *mp;
97 char *path;
98 caddr_t data;
99 struct nameidata *ndp;
100{
101 int error;
102 struct nfs_args args;
103 struct mbuf *saddr;
104 char pth[MNAMELEN], hst[MNAMELEN];
105 int len;
106 nfsv2fh_t nfh;
107
108 if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
109 return (error);
110 if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
111 return (error);
112 if (error = copyinstr(path, pth, MNAMELEN-1, &len))
113 return (error);
114 bzero(&pth[len], MNAMELEN-len);
115 if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
116 return (error);
117 bzero(&hst[len], MNAMELEN-len);
118 /* sockargs() call must be after above copyin() calls */
119 if (error = sockargs(&saddr, (caddr_t)args.addr,
120 sizeof (struct sockaddr_in), MT_SONAME))
121 return (error);
122 args.fh = &nfh;
123 error = mountnfs(&args, mp, saddr, pth, hst);
124 return (error);
125}
126
127/*
128 * Common code for mount and mountroot
129 */
130mountnfs(argp, mp, saddr, pth, hst)
131 register struct nfs_args *argp;
132 register struct mount *mp;
133 register struct mbuf *saddr;
134 char *pth, *hst;
135{
136 register struct nfsmount *nmp;
137 struct nfsnode *np;
36c3043b 138#ifdef notdef
a2907882 139 struct statfs statf, *sbp;
36c3043b 140#endif
a2907882
KM
141 int error;
142
143 nmp = (struct nfsmount *)malloc(sizeof (struct nfsmount), M_NFSMNT,
144 M_WAITOK);
145 mp->m_data = (qaddr_t)nmp;
146 mp->m_fsid.val[0] = ++nfs_mntid;
147 mp->m_fsid.val[1] = MOUNT_NFS;
148 nmp->nm_mountp = mp;
149 nmp->nm_flag = argp->flags;
150 nmp->nm_sockaddr = saddr;
151 /* Set up the sockets */
152 if (error = socreate(AF_INET, &nmp->nm_so, SOCK_DGRAM, 0))
153 goto bad;
154 if (error = soconnect(nmp->nm_so, saddr))
155 goto bad;
ffe6f482 156printf("sosnd=0x%x sorcv=0x%x\n",&nmp->nm_so->so_snd,&nmp->nm_so->so_rcv);
a2907882
KM
157 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo >= 1)
158 nmp->nm_timeo = argp->timeo;
159 else
160 nmp->nm_timeo = NFS_TIMEO;
161 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 0)
162 nmp->nm_retrans = argp->retrans;
163 else
164 nmp->nm_retrans = NFS_RETRANS;
165 if ((argp->flags & NFSMNT_WSIZE) &&
166 argp->wsize <= NFS_MAXDATA && argp->wsize > 0 &&
167 (argp->wsize & 0x1ff) == 0)
168 nmp->nm_wsize = argp->wsize;
169 else
170 nmp->nm_wsize = NFS_WSIZE;
171 if ((argp->flags & NFSMNT_RSIZE) &&
172 argp->rsize <= NFS_MAXDATA && argp->rsize > 0 &&
173 (argp->rsize & 0x1ff) == 0)
174 nmp->nm_rsize = argp->rsize;
175 else
176 nmp->nm_rsize = NFS_RSIZE;
177 bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
178 bcopy(pth, nmp->nm_path, MNAMELEN);
179 bcopy(hst, nmp->nm_host, MNAMELEN);
36c3043b 180#ifdef notdef
a2907882
KM
181 sbp = &statf;
182 /*
183 * Kludge City...
184 * To do an interruptable hard mount, turn it into a soft mount
185 * with a retry limit of one and then repeat it so long as it
186 * times out and there is no pending signal for the process.
187 * It is tempting to just let nfs_statfs() sleep at positive
188 * prio, but then you would long jump out without taking the
189 * mount structure back out of the list.
190 * NB: NFSMNT_INT must NEVER be set for nfs_mountroot(), since
191 * the process context is not yet built!!
192 */
193 if ((argp->flags && NFSMNT_INT) && (argp->flags & NFSMNT_SOFT) == 0) {
194 int savretrans;
195
196 nmp->nm_flag |= NFSMNT_SOFT;
197 savretrans = nmp->nm_retrans;
198 nmp->nm_retrans = 1;
199 do {
200 error = nfs_statfs(mp, sbp);
201 } while (error == ETIMEDOUT && (u.u_procp->p_sig &
202 (sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)|
203 sigmask(SIGKILL))) == 0);
204 nmp->nm_retrans = savretrans;
205 nmp->nm_flag &= ~NFSMNT_SOFT;
206 if (error)
207 goto bad;
208 } else if (error = nfs_statfs(mp, sbp))
209 goto bad;
210 mp->m_fsize = sbp->f_fsize;
211
212 /*
213 * If the block size is not an exact multiple of CLBYTES
214 * use CLBYTES so that paging in ZMAGIC executables doesn't
215 * get sick. (It is used by vinitfod())
216 */
217 if (sbp->f_bsize >= CLBYTES && claligned(sbp->f_bsize))
218 mp->m_bsize = sbp->f_bsize;
219 else
220 mp->m_bsize = CLBYTES;
36c3043b
KM
221#else
222 /*
223 * Set to CLBYTES so that vinifod() doesn't get confused.
224 * Actually any exact multiple of CLBYTES will do
225 */
226 mp->m_bsize = mp->m_fsize = CLBYTES;
227#endif
a2907882
KM
228 return (0);
229bad:
230 m_freem(saddr);
231 free((caddr_t)nmp, M_NFSMNT);
232 return (error);
233}
234
235/*
236 * unmount system call
237 */
238nfs_unmount(mp, flags)
239 struct mount *mp;
240 int flags;
241{
242 register struct nfsmount *nmp;
243 register struct nfsreq *rep;
244 struct nfsreq *rep2;
245 int error;
246 int s;
247
248 if (flags & MNT_FORCE)
249 return (EINVAL);
250 nmp = vfs_to_nfs(mp);
9238aa59
RM
251 /*
252 * Clear out the buffer cache
253 */
254 bflush(mp);
255 if (binval(mp))
256 return (EBUSY);
a2907882
KM
257 /*
258 * Goes something like this..
259 * - Call nfs_nflush() to clear out the nfsnode table
260 * - Flush out lookup cache
261 * - Close the socket
262 * - Free up the data structures
263 */
264 if (error = nfs_nflush(mp)) {
265 return (error);
266 }
267 /*
268 * Scan the request list for any requests left hanging about
269 */
270 s = splnet();
271 rep = nfsreqh.r_next;
ffe6f482 272 while (rep && rep != &nfsreqh) {
a2907882
KM
273 if (rep->r_mntp == nmp) {
274 rep->r_prev->r_next = rep2 = rep->r_next;
ffe6f482 275 rep->r_next->r_prev = rep->r_prev;
a2907882
KM
276 m_freem(rep->r_mreq);
277 if (rep->r_mrep != NULL)
278 m_freem(rep->r_mrep);
279 free((caddr_t)rep, M_NFSREQ);
280 rep = rep2;
281 } else
282 rep = rep->r_next;
283 }
284 splx(s);
285 soclose(nmp->nm_so);
286 m_freem(nmp->nm_sockaddr);
287 free((caddr_t)nmp, M_NFSMNT);
288 return (0);
289}
290
291/*
292 * Return root of a filesystem
293 */
294nfs_root(mp, vpp)
295 struct mount *mp;
296 struct vnode **vpp;
297{
298 register struct vnode *vp;
299 struct nfsmount *nmp;
300 struct nfsnode *np;
301 int error;
302
303 nmp = vfs_to_nfs(mp);
304 if (error = nfs_nget(mp, &nmp->nm_fh, &np))
305 return (error);
306 vp = NFSTOV(np);
307 vp->v_type = VDIR;
308 vp->v_flag = VROOT;
309 *vpp = vp;
310 return (0);
311}
312
9238aa59
RM
313extern int syncprt;
314
a2907882 315/*
9238aa59 316 * Flush out the buffer cache
a2907882
KM
317 */
318nfs_sync(mp, waitfor)
319 struct mount *mp;
320 int waitfor;
321{
9238aa59
RM
322 if (syncprt)
323 bufstats();
324 /*
325 * Force stale buffer cache information to be flushed.
326 */
327 bflush(mp);
a2907882
KM
328 return (0);
329}
330
331/*
332 * At this point, this should never happen
333 */
334nfs_fhtovp(mp, fhp, vpp)
335 struct mount *mp;
336 struct fid *fhp;
337 struct vnode **vpp;
338{
339 return (EINVAL);
340}
341
342/*
343 * Vnode pointer to File handle, should never happen either
344 */
345nfs_vptofh(mp, fhp, vpp)
346 struct mount *mp;
347 struct fid *fhp;
348 struct vnode **vpp;
349{
350 return (EINVAL);
351}
9238aa59
RM
352
353/*
354 * Vfs start routine, a no-op.
355 */
356nfs_start(mp, flags)
357 struct mount *mp;
358 int flags;
359{
360 return (0);
361}