Sync usage with man page.
[netbsd-mini2440.git] / external / cddl / osnet / sys / kern / vfs.c
blob7e05bca68f4c5160fd02b1cb55c67d74f0567015
1 /* $NetBSD: vfs.c,v 1.1 2009/08/07 20:57:57 haad Exp $ */
3 /*-
4 * Copyright (c) 2006-2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 /* __FBSDID("$FreeBSD: src/sys/compat/opensolaris/kern/opensolaris_vfs.c,v 1.7 2007/11/01 08:58:29 pjd Exp $"); */
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/systm.h>
35 #include <sys/mount.h>
36 #include <sys/cred.h>
37 #include <sys/vfs.h>
38 #include <sys/pathname.h>
39 #include <sys/priv.h>
40 #include <lib/libkern/libkern.h>
42 MALLOC_DECLARE(M_MOUNT);
44 int
45 lookupname(char *dirname, enum uio_seg seg, vnode_t **dirvpp, vnode_t **compvpp)
47 struct nameidata nd;
48 int error;
50 error = 0;
52 KASSERT(dirvpp == NULL);
54 error = namei_simple_kernel(dirname, NSM_FOLLOW_NOEMULROOT, compvpp);
56 return error;
60 int
61 lookupnameat(char *dirname, enum uio_seg seg, vnode_t **dirvpp,
62 vnode_t **compvpp, vnode_t *startvp)
65 struct nameidata nd;
66 int error;
68 error = EOPNOTSUPP;
70 /* XXX Disable until I upgrade testing kernel.
71 KASSERT(dirvpp == NULL);
73 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, dirname);
75 if ((error = nameiat(&nd, startvp)) != 0)
76 return error;
78 *compvpp = nd.ni_vp;*/
80 return (error);
84 void
85 vfs_setmntopt(vfs_t *vfsp, const char *name, const char *arg,
86 int flags)
89 if (strcmp("ro", name) == 0)
90 vfsp->mnt_flag |= MNT_RDONLY;
92 if (strcmp("rw", name) == 0)
93 vfsp->mnt_flag &= ~MNT_RDONLY;
95 if (strcmp("nodevices", name) == 0)
96 vfsp->mnt_flag |= MNT_NODEV;
98 if (strcmp("noatime", name) == 0)
99 vfsp->mnt_flag |= MNT_NOATIME;
101 if (strcmp("atime", name) == 0)
102 vfsp->mnt_flag &= ~MNT_NOATIME;
104 if (strcmp("nosuid", name) == 0)
105 vfsp->mnt_flag |= MNT_NOSUID;
107 if (strcmp("suid", name) == 0)
108 vfsp->mnt_flag &= ~MNT_NOSUID;
110 if (strcmp("noexec", name) == 0)
111 vfsp->mnt_flag |= MNT_NOEXEC;
113 if (strcmp("exec", name) == 0)
114 vfsp->mnt_flag &= ~MNT_NOEXEC;
116 vfsp->mnt_flag |= MNT_LOCAL;
119 void
120 vfs_clearmntopt(vfs_t *vfsp, const char *name)
123 if (strcmp("ro", name) == 0)
124 vfsp->mnt_flag |= MNT_RDONLY;
126 if (strcmp("rw", name) == 0)
127 vfsp->mnt_flag &= ~MNT_RDONLY;
129 if (strcmp("nodevices", name) == 0)
130 vfsp->mnt_flag &= ~MNT_NODEV;
132 if (strcmp("noatime", name) == 0)
133 vfsp->mnt_flag &= ~MNT_NOATIME;
135 if (strcmp("atime", name) == 0)
136 vfsp->mnt_flag |= MNT_NOATIME;
138 if (strcmp("nosuid", name) == 0)
139 vfsp->mnt_flag &= ~MNT_NOSUID;
141 if (strcmp("suid", name) == 0)
142 vfsp->mnt_flag |= MNT_NOSUID;
144 if (strcmp("noexec", name) == 0)
145 vfsp->mnt_flag &= ~MNT_NOEXEC;
147 if (strcmp("exec", name) == 0)
148 vfsp->mnt_flag |= MNT_NOEXEC;
152 vfs_optionisset(const vfs_t *vfsp, const char *name, char **argp)
155 if (strcmp("ro", name) == 0)
156 return (vfsp->mnt_flag & MNT_RDONLY) != 0;
158 if (strcmp("rw", name) == 0)
159 return (vfsp->mnt_flag & MNT_RDONLY) == 0;
161 if (strcmp("nodevices", name) == 0)
162 return (vfsp->mnt_flag & MNT_NODEV) != 0;
164 if (strcmp("noatime", name) == 0)
165 return (vfsp->mnt_flag & MNT_NOATIME) != 0;
167 if (strcmp("atime", name) == 0)
168 return (vfsp->mnt_flag & MNT_NOATIME) == 0;
170 if (strcmp("nosuid", name) == 0)
171 return (vfsp->mnt_flag & MNT_NOSUID) != 0;
173 if (strcmp("suid", name) == 0)
174 return (vfsp->mnt_flag & MNT_NOSUID) == 0;
176 if (strcmp("noexec", name) == 0)
177 return (vfsp->mnt_flag & MNT_NOEXEC) != 0;
179 if (strcmp("exec", name) == 0)
180 return (vfsp->mnt_flag & MNT_NOEXEC) == 0;
182 return 0;
185 #ifdef PORT_FREEBSD
187 traverse(vnode_t **cvpp, int lktype)
189 kthread_t *td = curthread;
190 vnode_t *cvp;
191 vnode_t *tvp;
192 vfs_t *vfsp;
193 int error;
195 cvp = *cvpp;
196 tvp = NULL;
199 * If this vnode is mounted on, then we transparently indirect
200 * to the vnode which is the root of the mounted file system.
201 * Before we do this we must check that an unmount is not in
202 * progress on this vnode.
205 for (;;) {
207 * Reached the end of the mount chain?
209 vfsp = vn_mountedvfs(cvp);
210 if (vfsp == NULL)
211 break;
213 * tvp is NULL for *cvpp vnode, which we can't unlock.
215 if (tvp != NULL)
216 vput(cvp);
217 else
218 vrele(cvp);
221 * The read lock must be held across the call to VFS_ROOT() to
222 * prevent a concurrent unmount from destroying the vfs.
224 error = VFS_ROOT(vfsp, &tvp);
225 if (error != 0)
226 return (error);
227 cvp = tvp;
230 *cvpp = cvp;
231 return (0);
235 domount(kthread_t *td, vnode_t *vp, const char *fstype, char *fspath,
236 char *fspec, int fsflags)
238 struct mount *mp;
239 struct vfsconf *vfsp;
240 struct ucred *newcr, *oldcr;
241 int error;
244 * Be ultra-paranoid about making sure the type and fspath
245 * variables will fit in our mp buffers, including the
246 * terminating NUL.
248 if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
249 return (ENAMETOOLONG);
251 vfsp = vfs_byname_kld(fstype, td, &error);
252 if (vfsp == NULL)
253 return (ENODEV);
255 if (vp->v_type != VDIR)
256 return (ENOTDIR);
257 simple_lock(&vp->v_interlock);
258 if ((vp->v_iflag & VI_MOUNT) != 0 ||
259 vp->v_mountedhere != NULL) {
260 simple_unlock(&vp->v_interlock);
261 return (EBUSY);
263 vp->v_iflag |= VI_MOUNT;
264 simple_unlock(&vp->v_interlock);
267 * Allocate and initialize the filesystem.
269 vn_lock(vp, LK_SHARED | LK_RETRY);
270 mp = vfs_mount_alloc(vp, vfsp, fspath, td);
271 VOP_UNLOCK(vp, 0);
273 mp->mnt_optnew = NULL;
274 vfs_setmntopt(mp, "from", fspec, 0);
275 mp->mnt_optnew = mp->mnt_opt;
276 mp->mnt_opt = NULL;
279 * Set the mount level flags.
280 * crdup() can sleep, so do it before acquiring a mutex.
282 newcr = crdup(kcred);
283 MNT_ILOCK(mp);
284 if (fsflags & MNT_RDONLY)
285 mp->mnt_flag |= MNT_RDONLY;
286 mp->mnt_flag &=~ MNT_UPDATEMASK;
287 mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS);
289 * Unprivileged user can trigger mounting a snapshot, but we don't want
290 * him to unmount it, so we switch to privileged credentials.
292 oldcr = mp->mnt_cred;
293 mp->mnt_cred = newcr;
294 mp->mnt_stat.f_owner = mp->mnt_cred->cr_uid;
295 MNT_IUNLOCK(mp);
296 crfree(oldcr);
298 * Mount the filesystem.
299 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
300 * get. No freeing of cn_pnbuf.
302 error = VFS_MOUNT(mp, td);
304 if (!error) {
305 if (mp->mnt_opt != NULL)
306 vfs_freeopts(mp->mnt_opt);
307 mp->mnt_opt = mp->mnt_optnew;
308 (void)VFS_STATFS(mp, &mp->mnt_stat, td);
311 * Prevent external consumers of mount options from reading
312 * mnt_optnew.
314 mp->mnt_optnew = NULL;
315 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
317 * Put the new filesystem on the mount list after root.
319 #ifdef FREEBSD_NAMECACHE
320 cache_purge(vp);
321 #endif
322 if (!error) {
323 vnode_t *mvp;
325 simple_lock(&vp->v_interlock);
326 vp->v_iflag &= ~VI_MOUNT;
327 simple_unlock(&vp->v_interlock);
328 vp->v_mountedhere = mp;
329 mutex_enter(&mountlist_lock);
330 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
331 mutex_exit(&mountlist_lock);
332 vfs_event_signal(NULL, VQ_MOUNT, 0);
333 if (VFS_ROOT(mp, LK_EXCLUSIVE, &mvp, td))
334 panic("mount: lost mount");
335 mountcheckdirs(vp, mvp);
336 vput(mvp);
337 VOP_UNLOCK(vp, 0);
338 if ((mp->mnt_flag & MNT_RDONLY) == 0)
339 error = vfs_allocate_syncvnode(mp);
340 vfs_unbusy(mp, td);
341 if (error)
342 vrele(vp);
343 else
344 vfs_mountedfrom(mp, fspec);
345 } else {
346 simple_lock(&vp->v_interlock);
347 vp->v_iflag &= ~VI_MOUNT;
348 simple_unlock(&vp->v_interlock);
349 VOP_UNLOCK(vp, 0);
350 vfs_unbusy(mp, td);
351 vfs_mount_destroy(mp);
353 return (error);
355 #endif