]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/miscfs/devfs/devfs_vfsops.c
Use [u]intptr_t instead of [u_]long for casts between pointers and
[FreeBSD/FreeBSD.git] / sys / miscfs / devfs / devfs_vfsops.c
1 /*-
2  * Copyright 1997,1998 Julian Elischer.  All rights reserved.
3  * julian@freebsd.org
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *  1. Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  * 
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED.  IN NO EVENT SHALL THE HOLDER OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  * 
26  *      $Id: devfs_vfsops.c,v 1.30 1998/05/06 05:29:32 msmith Exp $
27  *
28  */
29
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/vnode.h>
35 #include <sys/mount.h>
36 #include <sys/malloc.h>
37
38 #include <miscfs/devfs/devfsdefs.h>
39
40 static MALLOC_DEFINE(M_DEVFSMNT, "DEVFS mount", "DEVFS mount structure");
41
42 static int devfs_statfs( struct mount *mp, struct statfs *sbp, struct proc *p);
43
44 /*-
45  * Called from the generic VFS startups.
46  * This is the second stage of DEVFS initialisation.
47  * The probed devices have already been loaded and the 
48  * basic structure of the DEVFS created.
49  * We take the oportunity to mount the hidden DEVFS layer, so that
50  * devices from devfs get sync'd.
51  */
52 static int
53 devfs_init(struct vfsconf *vfsp)
54 {
55         struct mount *mp = dev_root->dnp->dvm->mount;
56         /*-
57          * fill in the missing members on the "hidden" mount
58          * we could almost use vfs_rootmountalloc() to do this.
59          */
60         lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
61         mp->mnt_op = vfsp->vfc_vfsops;
62         mp->mnt_vfc = vfsp;
63         mp->mnt_stat.f_type = vfsp->vfc_typenum;
64         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
65         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
66         mp->mnt_vnodecovered = NULLVP;
67
68         /* Mark a reference for the "invisible" blueprint mount */
69         mp->mnt_vfc->vfc_refcount++;
70         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
71
72         printf("DEVFS: ready to run\n");
73         return 0; /*XXX*/
74 }
75
76 /*-
77  *  mp   - pointer to 'mount' structure
78  *  path - addr in user space of mount point (ie /usr or whatever)
79  *  data - addr in user space of mount params including the
80  *         name of the block special file to treat as a filesystem.
81  *  ndp  - namei data pointer
82  *  p    - proc pointer
83  * devfs is special in that it doesn't require any device to be mounted..
84  * It makes up its data as it goes along.
85  * it must be mounted during single user.. until it is, only std{in/out/err}
86  * and the root filesystem are available.
87  */
88 /*proto*/
89 int
90 devfs_mount(struct mount *mp, char *path, caddr_t data,
91             struct nameidata *ndp, struct proc *p)
92 {
93         struct devfsmount *devfs_mp_p;  /* devfs specific mount info */
94         int error;
95         u_int size;
96
97 DBPRINT(("mount "));
98
99         /*-
100          *  If they just want to update, we don't need to do anything.
101          */
102         if (mp->mnt_flag & MNT_UPDATE)
103         {
104                 return 0;
105         }
106
107         /*-
108          *  Well, it's not an update, it's a real mount request.
109          *  Time to get dirty.
110          * HERE we should check to see if we are already mounted here.
111          */
112
113         devfs_mp_p = (struct devfsmount *)malloc(sizeof *devfs_mp_p,
114                                                 M_DEVFSMNT, M_WAITOK);
115         if (devfs_mp_p == NULL)
116                 return (ENOMEM);
117         bzero(devfs_mp_p,sizeof(*devfs_mp_p));
118         devfs_mp_p->mount = mp;
119         mp->mnt_data = (void *)devfs_mp_p;
120
121         /*-
122          *  Fill out some fields
123          */
124         mp->mnt_data = (qaddr_t)devfs_mp_p;
125         mp->mnt_stat.f_type = MOUNT_DEVFS;
126         mp->mnt_stat.f_fsid.val[0] = (intptr_t)(void *)devfs_mp_p;
127         mp->mnt_stat.f_fsid.val[1] = MOUNT_DEVFS;
128         mp->mnt_flag |= MNT_LOCAL;
129
130         if(error = dev_dup_plane(devfs_mp_p))
131         {
132                 mp->mnt_data = (qaddr_t)0;
133                 free((caddr_t)devfs_mp_p, M_DEVFSMNT);
134                 return (error);
135         }
136
137         /*-
138          *  Copy in the name of the directory the filesystem
139          *  is to be mounted on.
140          *  And we clear the remainder of the character strings
141          *  to be tidy.
142          *  Then, we try to fill in the filesystem stats structure
143          *  as best we can with whatever we can think of at the time
144          */
145         
146         if(devfs_up_and_going) {
147                 copyinstr(path, (caddr_t)mp->mnt_stat.f_mntonname,
148                         sizeof(mp->mnt_stat.f_mntonname)-1, &size);
149                 bzero(mp->mnt_stat.f_mntonname + size,
150                         sizeof(mp->mnt_stat.f_mntonname) - size);
151         } else {
152                 bcopy("dummy_mount", (caddr_t)mp->mnt_stat.f_mntonname,12);
153         }
154         bzero(mp->mnt_stat.f_mntfromname , MNAMELEN );
155         bcopy("devfs",mp->mnt_stat.f_mntfromname, 5);
156         (void)devfs_statfs(mp, &mp->mnt_stat, p);
157         return 0;
158 }
159
160
161 static int
162 devfs_start(struct mount *mp, int flags, struct proc *p)
163 {
164 DBPRINT(("start "));
165         return 0;
166 }
167
168 /*-
169  *  Unmount the filesystem described by mp.
170  */
171 static int
172 devfs_unmount( struct mount *mp, int mntflags, struct proc *p)
173 {
174         struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data;
175         int flags = 0;
176         int error;
177         
178         if (mntflags & MNT_FORCE) {
179                 flags |= FORCECLOSE;
180         }
181         error = vflush(mp, NULLVP, flags);
182         if (error)
183                 return error;
184
185 DBPRINT(("unmount "));
186         devfs_free_plane(devfs_mp_p);
187         free((caddr_t)devfs_mp_p, M_DEVFSMNT);
188         mp->mnt_data = (qaddr_t)0;
189         mp->mnt_flag &= ~MNT_LOCAL;
190
191         return 0;
192 }
193
194 /* return the address of the root vnode  in *vpp */
195 static int
196 devfs_root(struct mount *mp, struct vnode **vpp)
197 {
198         struct devfsmount *devfs_mp_p = (struct devfsmount *)(mp->mnt_data);
199
200 DBPRINT(("root "));
201         devfs_dntovn(devfs_mp_p->plane_root->dnp,vpp);
202         return 0;
203 }
204
205 static int
206 devfs_quotactl(struct mount *mp, int cmds, uid_t uid, caddr_t arg,
207                struct proc *p)
208 {
209 DBPRINT(("quotactl "));
210         return EOPNOTSUPP;
211 }
212
213 static int
214 devfs_statfs( struct mount *mp, struct statfs *sbp, struct proc *p)
215 {
216         struct devfsmount *devfs_mp_p = (struct devfsmount *)mp->mnt_data;
217
218 /*-
219  *  Fill in the stat block.
220  */
221 DBPRINT(("statfs "));
222         sbp->f_type   = MOUNT_DEVFS;
223         sbp->f_flags  = 0;              /* XXX */
224         sbp->f_bsize  = 128;
225         sbp->f_iosize = 1024;   /* XXX*/
226         sbp->f_blocks = 128;
227         sbp->f_bfree  = 0;
228         sbp->f_bavail = 0;
229         sbp->f_files  = 128;
230         sbp->f_ffree  = 0;              /* what to put in here? */
231         sbp->f_fsid.val[0] = (intptr_t)(void *)devfs_mp_p;
232         sbp->f_fsid.val[1] = MOUNT_DEVFS;
233
234 /*-
235  *  Copy the mounted on and mounted from names into
236  *  the passed in stat block, if it is not the one
237  *  in the mount structure.
238  */
239         if (sbp != &mp->mnt_stat) {
240                 bcopy((caddr_t)mp->mnt_stat.f_mntonname,
241                         (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
242                 bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
243                         (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
244         }
245         return 0;
246 }
247
248 /*-
249  * Go through the disk queues to initiate sandbagged IO;
250  * go through the inodes to write those that have been modified;
251  * initiate the writing of the super block if it has been modified.
252  *
253  * Note: we are always called with the filesystem marked `MPBUSY'.
254  */
255 static int
256 devfs_sync(struct mount *mp, int waitfor,struct ucred *cred,struct proc *p)
257 {
258         register struct vnode *vp, *nvp;
259         struct timeval tv;
260         int error, allerror = 0;
261
262 DBPRINT(("sync "));
263
264         /*-
265          * Write back modified superblock.
266          * Consistency check that the superblock
267          * is still in the buffer cache.
268          */
269         /*-
270          * Write back each (modified) inode.
271          */
272 loop:
273         for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
274                 /*-
275                  * If the vnode that we are about to sync is no longer
276                  * associated with this mount point, start over.
277                  */
278                 if (vp->v_mount != mp)
279                         goto loop;
280                 nvp = vp->v_mntvnodes.le_next;
281                 if (VOP_ISLOCKED(vp))
282                         continue;
283                 if ( vp->v_dirtyblkhd.lh_first == NULL)
284                         continue;
285                 if (vp->v_type == VBLK) {
286                         if (vget(vp, LK_EXCLUSIVE, p))
287                                 goto loop;
288                         error = VOP_FSYNC(vp, cred, waitfor, p);
289                         if (error)
290                                 allerror = error;
291                         vput(vp);
292                 }
293 #ifdef NOTYET
294                 else {
295                         tv = time;
296                         /* VOP_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT); */
297                         VOP_UPDATE(vp, &tv, &tv, 0);
298                 }
299 #endif
300         }
301         /*-
302          * Force stale file system control information to be flushed.
303          *( except that htat makes no sense with devfs
304          */
305         return (allerror);
306 }
307
308 static int
309 devfs_vget(struct mount *mp, ino_t ino,struct vnode **vpp)
310 {
311 DBPRINT(("vget "));
312         return EOPNOTSUPP;
313 }
314
315 /*************************************************************
316  * The concept of exporting a kernel generated devfs is stupid
317  * So don't handle filehandles
318  */
319
320 static int
321 devfs_fhtovp (struct mount *mp, struct fid *fhp, struct sockaddr *nam,
322               struct vnode **vpp, int *exflagsp, struct ucred **credanonp)
323 {
324 DBPRINT(("fhtovp "));
325         return (EINVAL);
326 }
327
328
329 static int
330 devfs_vptofh (struct vnode *vp, struct fid *fhp)
331 {
332 DBPRINT(("vptofh "));
333         return (EINVAL);
334 }
335
336 static struct vfsops devfs_vfsops = {
337         devfs_mount,
338         devfs_start,
339         devfs_unmount,
340         devfs_root,
341         devfs_quotactl,
342         devfs_statfs,
343         devfs_sync,
344         devfs_vget,
345         devfs_fhtovp,
346         devfs_vptofh,
347         devfs_init
348 };
349
350 VFS_SET(devfs_vfsops, devfs, MOUNT_DEVFS, 0);