]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/devfs/devfs_vfsops.c
Introduce support for Mandatory Access Control and extensible
[FreeBSD/FreeBSD.git] / sys / fs / devfs / devfs_vfsops.c
1 /*
2  * Copyright (c) 1992, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 2000
5  *      Poul-Henning Kamp.  All rights reserved.
6  *
7  * This code is derived from software donated to Berkeley by
8  * Jan-Simon Pendry.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *      @(#)kernfs_vfsops.c     8.10 (Berkeley) 5/14/95
32  * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vfsops.c 1.36
33  *
34  * $FreeBSD$
35  */
36
37 #include "opt_devfs.h"
38 #include "opt_mac.h"
39 #ifndef NODEVFS
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/mac.h>
46 #include <sys/malloc.h>
47 #include <sys/mount.h>
48 #include <sys/proc.h>
49 #include <sys/vnode.h>
50
51 #include <fs/devfs/devfs.h>
52
53 MALLOC_DEFINE(M_DEVFS, "DEVFS", "DEVFS data");
54
55 static int      devfs_mount(struct mount *mp, struct nameidata *ndp,
56                                   struct thread *td);
57 static int      devfs_unmount(struct mount *mp, int mntflags,
58                                   struct thread *td);
59 static int      devfs_root(struct mount *mp, struct vnode **vpp);
60 static int      devfs_statfs(struct mount *mp, struct statfs *sbp,
61                                    struct thread *td);
62
63 /*
64  * Mount the filesystem
65  */
66 static int
67 devfs_mount(mp, ndp, td)
68         struct mount *mp;
69         struct nameidata *ndp;
70         struct thread *td;
71 {
72         int error;
73         struct devfs_mount *fmp;
74         struct vnode *rvp;
75
76         error = 0;
77         /*
78          * XXX: flag changes.
79          */
80         if (mp->mnt_flag & MNT_UPDATE)
81                 return (EOPNOTSUPP);
82
83         MALLOC(fmp, struct devfs_mount *, sizeof(struct devfs_mount),
84             M_DEVFS, M_WAITOK | M_ZERO);
85         lockinit(&fmp->dm_lock, PVFS, "devfs", 0, LK_NOPAUSE);
86
87         mp->mnt_flag |= MNT_LOCAL;
88 #ifdef MAC
89         mp->mnt_flag |= MNT_MULTILABEL;
90 #endif
91         mp->mnt_data = (qaddr_t) fmp;
92         vfs_getnewfsid(mp);
93
94         fmp->dm_inode = DEVFSINOMOUNT;
95
96         fmp->dm_rootdir = devfs_vmkdir("(root)", 6, NULL);
97         fmp->dm_rootdir->de_inode = 2;
98 #ifdef MAC
99         mac_create_devfs_directory("", 0, fmp->dm_rootdir);
100 #endif
101         fmp->dm_basedir = fmp->dm_rootdir;
102         devfs_rules_newmount(fmp, td);
103
104         error = devfs_root(mp, &rvp);
105         if (error) {
106                 lockdestroy(&fmp->dm_lock);
107                 FREE(fmp, M_DEVFS);
108                 return (error);
109         }
110         VOP_UNLOCK(rvp, 0, td);
111
112         bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
113         bcopy("devfs", mp->mnt_stat.f_mntfromname, sizeof("devfs"));
114         (void)devfs_statfs(mp, &mp->mnt_stat, td);
115
116         return (0);
117 }
118
119 static int
120 devfs_unmount(mp, mntflags, td)
121         struct mount *mp;
122         int mntflags;
123         struct thread *td;
124 {
125         int error;
126         int flags = 0;
127         struct devfs_mount *fmp;
128
129         fmp = VFSTODEVFS(mp);
130         if (mntflags & MNT_FORCE)
131                 flags |= FORCECLOSE;
132         /* There is 1 extra root vnode reference from devfs_mount(). */
133         error = vflush(mp, 1, flags);
134         if (error)
135                 return (error);
136         devfs_purge(fmp->dm_rootdir);
137         mp->mnt_data = 0;
138         lockdestroy(&fmp->dm_lock);
139         free(fmp, M_DEVFS);
140         return 0;
141 }
142
143 /* Return locked reference to root.  */
144
145 static int
146 devfs_root(mp, vpp)
147         struct mount *mp;
148         struct vnode **vpp;
149 {
150         int error;
151         struct thread *td;
152         struct vnode *vp;
153         struct devfs_mount *dmp;
154
155         td = curthread;                                 /* XXX */
156         dmp = VFSTODEVFS(mp);
157         error = devfs_allocv(dmp->dm_rootdir, mp, &vp, td);
158         if (error)
159                 return (error);
160         vp->v_flag |= VROOT;
161         *vpp = vp;
162         return (0);
163 }
164
165 static int
166 devfs_statfs(mp, sbp, td)
167         struct mount *mp;
168         struct statfs *sbp;
169         struct thread *td;
170 {
171
172         sbp->f_flags = 0;
173         sbp->f_bsize = DEV_BSIZE;
174         sbp->f_iosize = DEV_BSIZE;
175         sbp->f_blocks = 2;              /* 1K to keep df happy */
176         sbp->f_bfree = 0;
177         sbp->f_bavail = 0;
178         sbp->f_files = 0;
179         sbp->f_ffree = 0;
180         if (sbp != &mp->mnt_stat) {
181                 sbp->f_type = mp->mnt_vfc->vfc_typenum;
182                 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
183                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
184                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
185         }
186         return (0);
187 }
188
189 static struct vfsops devfs_vfsops = {
190         NULL,
191         vfs_stdstart,
192         devfs_unmount,
193         devfs_root,
194         vfs_stdquotactl,
195         devfs_statfs,
196         vfs_stdsync,
197         vfs_stdvget,
198         vfs_stdfhtovp,
199         vfs_stdcheckexp,
200         vfs_stdvptofh,
201         vfs_stdinit,
202         vfs_stduninit,
203         vfs_stdextattrctl,
204         devfs_mount,
205 };
206
207 VFS_SET(devfs_vfsops, devfs, VFCF_SYNTHETIC);
208 #endif