4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / sys / ufs / ufs / ufs_vfsops.c
CommitLineData
da7c5cc6 1/*
ad0f93d2
KB
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
da7c5cc6 4 *
b702c21d 5 * %sccs.include.redist.c%
7188ac27 6 *
ad0f93d2 7 * @(#)ufs_vfsops.c 8.1 (Berkeley) %G%
da7c5cc6 8 */
71e4e98b 9
e9fed4d6 10#include <sys/param.h>
9e4a3a4a
KM
11#include <net/radix.h>
12#include <sys/domain.h>
13#include <sys/socket.h>
14#include <sys/mbuf.h>
e9fed4d6
KB
15#include <sys/mount.h>
16#include <sys/proc.h>
17#include <sys/buf.h>
18#include <sys/vnode.h>
cb09ceb4 19#include <sys/malloc.h>
4d7c6b73
JSP
20
21#include <miscfs/specfs/specdev.h>
609e7cfa
MK
22#include "ioctl.h"
23#include "disklabel.h"
24#include "stat.h"
71e4e98b 25
e9fed4d6
KB
26#include <ufs/ufs/quota.h>
27#include <ufs/ufs/inode.h>
28#include <ufs/ufs/ufsmount.h>
29#include <ufs/ufs/ufs_extern.h>
7188ac27 30
d85a9d1b 31/*
e9fed4d6 32 * Flag to permit forcible unmounting.
d85a9d1b
KM
33 */
34int doforce = 1;
35
5bf9d21f
KM
36/*
37 * Make a filesystem operational.
38 * Nothing to do at the moment.
39 */
31593ba7 40/* ARGSUSED */
e9fed4d6 41int
0eb6f54a 42ufs_start(mp, flags, p)
5bf9d21f
KM
43 struct mount *mp;
44 int flags;
0eb6f54a 45 struct proc *p;
5bf9d21f
KM
46{
47
48 return (0);
49}
71e4e98b 50
7188ac27 51/*
ec67a3ce
MK
52 error = closei(dev, IFBLK, fs->fs_ronly? FREAD : FREAD|FWRITE);
53 irele(ip);
54 return (error);
71e4e98b
SL
55}
56
8dc876c1
KM
57/*
58 * Do operations associated with quotas
59 */
e9fed4d6 60int
0eb6f54a 61ufs_quotactl(mp, cmds, uid, arg, p)
8dc876c1
KM
62 struct mount *mp;
63 int cmds;
b18e699d 64 uid_t uid;
8dc876c1 65 caddr_t arg;
0eb6f54a 66 struct proc *p;
8dc876c1 67{
8dc876c1
KM
68 int cmd, type, error;
69
70#ifndef QUOTA
71 return (EOPNOTSUPP);
72#else
73 if (uid == -1)
c6f5111d 74 uid = p->p_cred->p_ruid;
8dc876c1
KM
75 cmd = cmds >> SUBCMDSHIFT;
76
77 switch (cmd) {
78 case Q_GETQUOTA:
79 case Q_SYNC:
c6f5111d 80 if (uid == p->p_cred->p_ruid)
8dc876c1
KM
81 break;
82 /* fall through */
83 default:
c6f5111d 84 if (error = suser(p->p_ucred, &p->p_acflag))
8dc876c1
KM
85 return (error);
86 }
87
88 type = cmd & SUBCMDMASK;
89 if ((u_int)type >= MAXQUOTAS)
90 return (EINVAL);
91
92 switch (cmd) {
93
94 case Q_QUOTAON:
c6f5111d 95 return (quotaon(p, mp, type, arg));
8dc876c1
KM
96
97 case Q_QUOTAOFF:
98 if (vfs_busy(mp))
99 return (0);
70a360ba 100 error = quotaoff(p, mp, type);
8dc876c1
KM
101 vfs_unbusy(mp);
102 return (error);
103
104 case Q_SETQUOTA:
105 return (setquota(mp, uid, type, arg));
106
107 case Q_SETUSE:
108 return (setuse(mp, uid, type, arg));
109
110 case Q_GETQUOTA:
111 return (getquota(mp, uid, type, arg));
112
113 case Q_SYNC:
114 if (vfs_busy(mp))
115 return (0);
116 error = qsync(mp);
117 vfs_unbusy(mp);
118 return (error);
119
120 default:
121 return (EINVAL);
122 }
123 /* NOTREACHED */
124#endif
125}
126
cb09ceb4
KM
127/*
128 * Build hash lists of net addresses and hang them off the mount point.
129 * Called by ufs_mount() to set up the lists of export addresses.
130 */
131ufs_hang_addrlist(mp, argp)
132 struct mount *mp;
133 struct ufs_args *argp;
134{
9e4a3a4a
KM
135 register struct netcred *np;
136 register struct radix_node_head *rnh;
cb09ceb4 137 register int i;
9e4a3a4a 138 struct radix_node *rn;
cb09ceb4 139 struct ufsmount *ump;
9e4a3a4a
KM
140 struct sockaddr *saddr, *smask = 0;
141 struct domain *dom;
cb09ceb4
KM
142 int error;
143
bc1c5014 144 ump = VFSTOUFS(mp);
9e4a3a4a 145 if (argp->slen == 0) {
cb09ceb4
KM
146 if (mp->mnt_flag & MNT_DEFEXPORTED)
147 return (EPERM);
148 np = &ump->um_defexported;
9e4a3a4a
KM
149 np->netc_exflags = argp->exflags;
150 np->netc_anon = argp->anon;
151 np->netc_anon.cr_ref = 1;
cb09ceb4
KM
152 mp->mnt_flag |= MNT_DEFEXPORTED;
153 return (0);
154 }
9e4a3a4a
KM
155 i = sizeof(struct netcred) + argp->slen + argp->msklen;
156 np = (struct netcred *)malloc(i, M_NETADDR, M_WAITOK);
157 bzero((caddr_t)np, i);
158 saddr = (struct sockaddr *)(np + 1);
159 if (error = copyin(argp->saddr, (caddr_t)saddr, argp->slen))
160 goto out;
161 if (saddr->sa_len > argp->slen)
162 saddr->sa_len = argp->slen;
163 if (argp->msklen) {
164 smask = (struct sockaddr *)((caddr_t)saddr + argp->slen);
165 if (error = copyin(argp->saddr, (caddr_t)smask, argp->msklen))
166 goto out;
167 if (smask->sa_len > argp->msklen)
168 smask->sa_len = argp->msklen;
169 }
9e4a3a4a
KM
170 i = saddr->sa_family;
171 if ((rnh = ump->um_rtable[i]) == 0) {
cb09ceb4 172 /*
9e4a3a4a
KM
173 * Seems silly to initialize every AF when most are not
174 * used, do so on demand here
cb09ceb4 175 */
9e4a3a4a
KM
176 for (dom = domains; dom; dom = dom->dom_next)
177 if (dom->dom_family == i && dom->dom_rtattach) {
178 dom->dom_rtattach((void **)&ump->um_rtable[i],
179 dom->dom_rtoffset);
180 break;
cb09ceb4 181 }
9e4a3a4a
KM
182 if ((rnh = ump->um_rtable[i]) == 0) {
183 error = ENOBUFS;
184 goto out;
cb09ceb4
KM
185 }
186 }
e14bb1bd
KS
187 rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh,
188 np->netc_rnodes);
9e4a3a4a
KM
189 if (rn == 0 || np != (struct netcred *)rn) { /* already exists */
190 error = EPERM;
191 goto out;
cb09ceb4 192 }
9e4a3a4a
KM
193 np->netc_exflags = argp->exflags;
194 np->netc_anon = argp->anon;
195 np->netc_anon.cr_ref = 1;
cb09ceb4 196 return (0);
9e4a3a4a
KM
197out:
198 free(np, M_NETADDR);
199 return (error);
200}
201
202/* ARGSUSED */
203static int
204ufs_free_netcred(rn, w)
205 struct radix_node *rn;
206 caddr_t w;
207{
e3b2a8e6
KM
208 register struct radix_node_head *rnh = (struct radix_node_head *)w;
209
210 (*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);
9e4a3a4a 211 free((caddr_t)rn, M_NETADDR);
40ca803d 212 return (0);
cb09ceb4 213}
9e4a3a4a 214
cb09ceb4
KM
215
216/*
217 * Free the net address hash lists that are hanging off the mount points.
218 */
219void
220ufs_free_addrlist(ump)
221 struct ufsmount *ump;
222{
cb09ceb4 223 register int i;
9e4a3a4a 224 register struct radix_node_head *rnh;
cb09ceb4 225
9e4a3a4a
KM
226 for (i = 0; i <= AF_MAX; i++)
227 if (rnh = ump->um_rtable[i]) {
e3b2a8e6
KM
228 (*rnh->rnh_walktree)(rnh, ufs_free_netcred,
229 (caddr_t)rnh);
9e4a3a4a
KM
230 free((caddr_t)rnh, M_RTABLE);
231 ump->um_rtable[i] = 0;
232 }
233}
234
235/*
236 * This is the generic part of fhtovp called after the underlying
237 * filesystem has validated the file handle.
238 *
239 * Verify that a host should have access to a filesystem, and if so
240 * return a vnode for the presented file handle.
241 */
242int
485cf2ee 243ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)
9e4a3a4a 244 register struct mount *mp;
485cf2ee 245 struct ufid *ufhp;
9e4a3a4a
KM
246 struct mbuf *nam;
247 struct vnode **vpp;
248 int *exflagsp;
249 struct ucred **credanonp;
250{
9e4a3a4a
KM
251 register struct inode *ip;
252 register struct netcred *np;
253 register struct ufsmount *ump = VFSTOUFS(mp);
254 register struct radix_node_head *rnh;
255 struct vnode *nvp;
256 struct sockaddr *saddr;
257 int error;
258
259 /*
260 * Get the export permission structure for this <mp, client> tuple.
261 */
262 if ((mp->mnt_flag & MNT_EXPORTED) == 0)
263 return (EACCES);
bc1c5014
KM
264 np = NULL;
265 if (nam != NULL) {
9e4a3a4a
KM
266 saddr = mtod(nam, struct sockaddr *);
267 rnh = ump->um_rtable[saddr->sa_family];
bc1c5014 268 if (rnh != NULL) {
9e4a3a4a 269 np = (struct netcred *)
e14bb1bd 270 (*rnh->rnh_matchaddr)((caddr_t)saddr, rnh);
bc1c5014 271 if (np && np->netc_rnodes->rn_flags & RNF_ROOT)
9e4a3a4a 272 np = NULL;
cb09ceb4
KM
273 }
274 }
9e4a3a4a
KM
275 if (np == NULL) {
276 /*
277 * If no address match, use the default if it exists.
278 */
279 if ((mp->mnt_flag & MNT_DEFEXPORTED) == 0)
280 return (EACCES);
281 np = &ump->um_defexported;
282 }
283 if (error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) {
284 *vpp = NULLVP;
285 return (error);
286 }
287 ip = VTOI(nvp);
288 if (ip->i_mode == 0 || ip->i_gen != ufhp->ufid_gen) {
ad89ded3 289 vput(nvp);
9e4a3a4a
KM
290 *vpp = NULLVP;
291 return (ESTALE);
292 }
293 *vpp = nvp;
294 *exflagsp = np->netc_exflags;
295 *credanonp = &np->netc_anon;
296 return (0);
cb09ceb4 297}