]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/miscfs/devfs/devfs_vnops.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / sys / miscfs / devfs / devfs_vnops.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  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/buf.h>
32 #include <sys/namei.h>
33 #include <sys/kernel.h>
34 #include <sys/fcntl.h>
35 #include <sys/conf.h>
36 #include <sys/lock.h>
37 #include <sys/stat.h>
38 #include <sys/mount.h>
39 #include <sys/proc.h>
40 #include <sys/time.h>
41 #include <sys/vnode.h>
42 #include <sys/dirent.h>
43 #include <miscfs/devfs/devfsdefs.h>
44 #include <sys/vmmeter.h>                                                        
45
46 #include <vm/vm.h>
47 #include <vm/vm_object.h>
48 #include <vm/vm_page.h>
49 #include <vm/vm_pager.h>
50
51
52 /*
53  * Insert description here
54  */
55
56
57 /*
58  * Convert a component of a pathname into a pointer to a locked node.
59  * This is a very central and rather complicated routine.
60  * If the file system is not maintained in a strict tree hierarchy,
61  * this can result in a deadlock situation (see comments in code below).
62  *
63  * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
64  * whether the name is to be looked up, created, renamed, or deleted.
65  * When CREATE, RENAME, or DELETE is specified, information usable in
66  * creating, renaming, or deleting a directory entry may be calculated.
67  * If flag has LOCKPARENT or'ed into it and the target of the pathname
68  * exists, lookup returns both the target and its parent directory locked.
69  * When creating or renaming and LOCKPARENT is specified, the target may
70  * not be ".".  When deleting and LOCKPARENT is specified, the target may
71  * be "."., but the caller must check to ensure it does an vrele and DNUNLOCK
72  * instead of two DNUNLOCKs.
73  *
74  * Overall outline of devfs_lookup:
75  *
76  *      check accessibility of directory
77  *      null terminate the component (lookup leaves the whole string alone)
78  *      look for name in cache, if found, then if at end of path
79  *        and deleting or creating, drop it, else return name
80  *      search for name in directory, to found or notfound
81  * notfound:
82  *      if creating, return locked directory,
83  *      else return error
84  * found:
85  *      if at end of path and deleting, return information to allow delete
86  *      if at end of path and rewriting (RENAME and LOCKPARENT), lock target
87  *        node and return info to allow rewrite
88  *      if not at end, add name to cache; if at end and neither creating
89  *        nor deleting, add name to cache
90  * On return to lookup, remove the null termination we put in at the start.
91  *
92  * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent node unlocked.
93  */
94 static int
95 devfs_lookup(struct vop_lookup_args *ap)
96         /*struct vop_lookup_args {
97                 struct vnode * a_dvp; directory vnode ptr
98                 struct vnode ** a_vpp; where to put the result
99                 struct componentname * a_cnp; the name we want
100         };*/
101 {
102         struct componentname *cnp = ap->a_cnp;
103         struct vnode *dir_vnode = ap->a_dvp;
104         struct vnode **result_vnode = ap->a_vpp;
105         dn_p   dir_node;       /* the directory we are searching */
106         dn_p   new_node;       /* the node we are searching for */
107         devnm_p new_nodename;
108         int flags = cnp->cn_flags;
109         int op = cnp->cn_nameiop;       /* LOOKUP, CREATE, RENAME, or DELETE */
110         int lockparent = flags & LOCKPARENT;
111         int wantparent = flags & (LOCKPARENT|WANTPARENT);
112         int error = 0;
113         struct proc *p = cnp->cn_proc;
114         char    heldchar;       /* the char at the end of the name componet */
115
116         *result_vnode = NULL; /* safe not sorry */ /*XXX*/
117
118 DBPRINT(("lookup\n"));
119
120         if (dir_vnode->v_usecount == 0)
121             printf("dir had no refs ");
122         if (devfs_vntodn(dir_vnode,&dir_node))
123         {
124                 printf("vnode has changed?\n");
125                 vprint("=",dir_vnode);
126                 return(EINVAL);
127         }
128
129         /*
130          * Check accessiblity of directory.
131          */
132         if (dir_node->type != DEV_DIR) /* XXX or symlink? */
133         {
134                 return (ENOTDIR);
135         }
136         if ((error = VOP_ACCESS(dir_vnode, VEXEC, cnp->cn_cred, p)) != 0)
137         {
138                 return (error);
139         }
140
141         /*
142          * We now have a segment name to search for, and a directory to search.
143          *
144          */
145
146 /***********************************************************************\
147 * SEARCH FOR NAME                                                       *
148 * while making sure the component is null terminated for the strcmp     *
149 \***********************************************************************/
150
151         heldchar = cnp->cn_nameptr[cnp->cn_namelen];
152         cnp->cn_nameptr[cnp->cn_namelen] = '\0';
153         new_nodename = dev_findname(dir_node,cnp->cn_nameptr);
154         cnp->cn_nameptr[cnp->cn_namelen] = heldchar;
155         if(!new_nodename) {
156                 /*******************************************************\
157                 * Failed to find it.. (That may be good)                *
158                 \*******************************************************/
159                 new_node = NULL; /* to be safe */
160                 /*
161                  * If creating, and at end of pathname
162                  * then can consider
163                  * allowing file to be created.
164                  */
165                 if (!(flags & ISLASTCN) || !(op == CREATE || op == RENAME)) {
166                         return ENOENT;
167                 }
168                 /*
169                  * Access for write is interpreted as allowing
170                  * creation of files in the directory.
171                  */
172                 if ((error = VOP_ACCESS(dir_vnode, VWRITE,
173                                 cnp->cn_cred, p)) != 0)
174                 {
175 DBPRINT(("MKACCESS "));
176                         return (error);
177                 }
178                 /*
179                  * We return with the directory locked, so that
180                  * the parameters we set up above will still be
181                  * valid if we actually decide to add a new entry.
182                  * We return ni_vp == NULL to indicate that the entry
183                  * does not currently exist; we leave a pointer to
184                  * the (locked) directory vnode in namei_data->ni_dvp.
185                  * The pathname buffer is saved so that the name
186                  * can be obtained later.
187                  *
188                  * NB - if the directory is unlocked, then this
189                  * information cannot be used.
190                  */
191                 cnp->cn_flags |= SAVENAME; /*XXX why? */
192                 if (!lockparent)
193                         VOP_UNLOCK(dir_vnode, 0, p);
194                 return (EJUSTRETURN);
195         }
196
197         /***************************************************************\
198         * Found it.. this is not always a good thing..                  *
199         \***************************************************************/
200         new_node = new_nodename->dnp;
201         new_node->last_lookup = new_nodename; /* for unlink */
202         /*
203          * If deleting, and at end of pathname, return
204          * parameters which can be used to remove file.
205          * If the wantparent flag isn't set, we return only
206          * the directory (in namei_data->ni_dvp), otherwise we go
207          * on and lock the node, being careful with ".".
208          */
209         if (op == DELETE && (flags & ISLASTCN)) {
210                 /*
211                  * Write access to directory required to delete files.
212                  */
213                 if ((error = VOP_ACCESS(dir_vnode, VWRITE,
214                                 cnp->cn_cred, p)) != 0)
215                         return (error);
216                 /*
217                  * we are trying to delete '.'.  What does this mean? XXX
218                  */
219                 if (dir_node == new_node) {
220                         VREF(dir_vnode);
221                         *result_vnode = dir_vnode;
222                         return (0);
223                 }
224                 /*
225                  * If directory is "sticky", then user must own
226                  * the directory, or the file in it, else she
227                  * may not delete it (unless she's root). This
228                  * implements append-only directories.
229                  */
230                 devfs_dntovn(new_node,result_vnode);
231 #ifdef NOTYET
232                 if ((dir_node->mode & ISVTX) &&
233                     cnp->cn_cred->cr_uid != 0 &&
234                     cnp->cn_cred->cr_uid != dir_node->uid &&
235                     cnp->cn_cred->cr_uid != new_node->uid) {
236                         VOP_UNLOCK(*result_vnode, 0, p);
237                         return (EPERM);
238                 }
239 #endif
240                 if (!lockparent)
241                         VOP_UNLOCK(dir_vnode, 0, p);
242                 return (0);
243         }
244
245         /*
246          * If rewriting (RENAME), return the vnode and the
247          * information required to rewrite the present directory
248          * Must get node of directory entry to verify it's a
249          * regular file, or empty directory.
250          */
251         if (op == RENAME && wantparent && (flags & ISLASTCN)) {
252                 /*
253                  * Are we allowed to change the holding directory?
254                  */
255                 if ((error = VOP_ACCESS(dir_vnode, VWRITE,
256                                 cnp->cn_cred, p)) != 0)
257                         return (error);
258                 /*
259                  * Careful about locking second node.
260                  * This can only occur if the target is ".".
261                  */
262                 if (dir_node == new_node)
263                         return (EISDIR);
264                 devfs_dntovn(new_node,result_vnode);
265                 /* hmm save the 'from' name (we need to delete it) */
266                 cnp->cn_flags |= SAVENAME;
267                 if (!lockparent)
268                         VOP_UNLOCK(dir_vnode, 0, p);
269                 return (0);
270         }
271
272         /*
273          * Step through the translation in the name.  We do not unlock the
274          * directory because we may need it again if a symbolic link
275          * is relative to the current directory.  Instead we save it
276          * unlocked as "saved_dir_node" XXX.  We must get the target
277          * node before unlocking
278          * the directory to insure that the node will not be removed
279          * before we get it.  We prevent deadlock by always fetching
280          * nodes from the root, moving down the directory tree. Thus
281          * when following backward pointers ".." we must unlock the
282          * parent directory before getting the requested directory.
283          * There is a potential race condition here if both the current
284          * and parent directories are removed before the lock for the
285          * node associated with ".." returns.  We hope that this occurs
286          * infrequently since we cannot avoid this race condition without
287          * implementing a sophisticated deadlock detection algorithm.
288          * Note also that this simple deadlock detection scheme will not
289          * work if the file system has any hard links other than ".."
290          * that point backwards in the directory structure.
291          */
292         if (flags & ISDOTDOT) {
293                 VOP_UNLOCK(dir_vnode, 0, p);    /* race to get the node */
294                 devfs_dntovn(new_node,result_vnode);
295                 if (lockparent && (flags & ISLASTCN))
296                         vn_lock(dir_vnode, LK_EXCLUSIVE | LK_RETRY, p);
297         } else if (dir_node == new_node) {
298                 VREF(dir_vnode);        /* we want ourself, ie "." */
299                 *result_vnode = dir_vnode;
300         } else {
301                 devfs_dntovn(new_node,result_vnode);
302                 if (!lockparent || (flags & ISLASTCN))
303                         VOP_UNLOCK(dir_vnode, 0, p);
304         }
305
306 DBPRINT(("GOT\n"));
307         return (0);
308 }
309
310 /*
311  */
312
313 static int
314 devfs_access(struct vop_access_args *ap)
315         /*struct vop_access_args  {
316                 struct vnode *a_vp;
317                 int  a_mode;
318                 struct ucred *a_cred;
319                 struct proc *a_p;
320         } */ 
321 {
322         /*
323          *  mode is filled with a combination of VREAD, VWRITE,
324          *  and/or VEXEC bits turned on.  In an octal number these
325          *  are the Y in 0Y00.
326          */
327         struct vnode *vp = ap->a_vp;
328         int mode = ap->a_mode;
329         struct ucred *cred = ap->a_cred;
330         dn_p    dnp;
331         int     error;
332         gid_t   *gp;
333         int     i;
334
335 DBPRINT(("access\n"));
336         if ((error = devfs_vntodn(vp,&dnp)) != 0)
337         {
338                 printf("devfs_vntodn returned %d ",error);
339                 return error;
340         }
341
342         /* 
343          * if we are not running as a process, we are in the 
344          * kernel and we DO have permission
345          */
346         if (ap->a_p == NULL)
347                 return 0;
348
349         /*
350          * Access check is based on only one of owner, group, public.
351          * If not owner, then check group. If not a member of the
352          * group, then check public access.
353          */
354         if (cred->cr_uid != dnp->uid)
355         {
356                 /* failing that.. try groups */
357                 mode >>= 3;
358                 gp = cred->cr_groups;
359                 for (i = 0; i < cred->cr_ngroups; i++, gp++)
360                 {
361                         if (dnp->gid == *gp)
362                         {
363                                 goto found;
364                         }
365                 }
366                 /* failing that.. try general access */
367                 mode >>= 3;
368 found:
369                 ;
370         }
371         if ((dnp->mode & mode) == mode)
372                 return (0);
373         /*
374          *  Root gets to do anything.
375          * but only use suser_xxx prives as a last resort
376          * (Use of super powers is recorded in ap->a_p->p_acflag)
377          */
378         if( suser_xxx(cred, ap->a_p, 0) == 0) /* XXX what if no proc? */
379                 return 0;
380         return (EACCES);
381 }
382
383 static int
384 devfs_getattr(struct vop_getattr_args *ap)
385         /*struct vop_getattr_args {
386                 struct vnode *a_vp;
387                 struct vattr *a_vap;
388                 struct ucred *a_cred;
389                 struct proc *a_p;
390         } */ 
391 {
392         struct vnode *vp = ap->a_vp;
393         struct vattr *vap = ap->a_vap;
394         dn_p    dnp;
395         int     error;
396
397 DBPRINT(("getattr\n"));
398         if ((error = devfs_vntodn(vp,&dnp)) != 0)
399         {
400                 printf("devfs_vntodn returned %d ",error);
401                 return error;
402         }
403         vap->va_rdev = 0;/* default value only */
404         vap->va_mode = dnp->mode;
405         switch (dnp->type)
406         {
407         case    DEV_DIR:
408                 vap->va_rdev = (udev_t)dnp->dvm;
409                 vap->va_mode |= (S_IFDIR);
410                 break;
411         case    DEV_CDEV:
412                 vap->va_rdev = dev2udev(vp->v_rdev);
413                 vap->va_mode |= (S_IFCHR);
414                 break;
415 #if nolonger
416         case    DEV_BDEV:
417                 vap->va_rdev = dev2budev(vp->v_rdev);
418                 vap->va_mode |= (S_IFBLK);
419                 break;
420 #endif
421         case    DEV_SLNK:
422                 break;
423         }
424         vap->va_type = vp->v_type;
425         vap->va_nlink = dnp->links;
426         vap->va_uid = dnp->uid;
427         vap->va_gid = dnp->gid;
428         vap->va_fsid = (intptr_t)(void *)dnp->dvm;
429         vap->va_fileid = (intptr_t)(void *)dnp;
430         vap->va_size = dnp->len; /* now a u_quad_t */
431         vap->va_blocksize = 512;
432         /*
433          * XXX If the node times are in  Jan 1, 1970, then
434          * update them to the boot time.
435          * When we made the node, the date/time was not yet known.
436          */
437         if(dnp->ctime.tv_sec < (24 * 3600))
438         {
439                 TIMEVAL_TO_TIMESPEC(&boottime,&(dnp->ctime));
440                 TIMEVAL_TO_TIMESPEC(&boottime,&(dnp->mtime));
441                 TIMEVAL_TO_TIMESPEC(&boottime,&(dnp->atime));
442         }
443         if (dnp->flags & IN_ACCESS) {
444                 nanotime(&dnp->atime);
445                 dnp->flags &= ~IN_ACCESS;
446         }
447         vap->va_ctime = dnp->ctime;
448         vap->va_mtime = dnp->mtime;
449         vap->va_atime = dnp->atime;
450         vap->va_gen = 0;
451         vap->va_flags = 0;
452         vap->va_bytes = dnp->len;               /* u_quad_t */
453         vap->va_filerev = 0; /* XXX */          /* u_quad_t */
454         vap->va_vaflags = 0; /* XXX */
455         return 0;
456 }
457
458 static int
459 devfs_setattr(struct vop_setattr_args *ap)
460         /*struct vop_setattr_args  {
461                 struct vnode *a_vp;
462                 struct vattr *a_vap;
463                 struct ucred *a_cred;
464                 struct proc *a_p;
465         } */ 
466 {
467         struct vnode *vp = ap->a_vp;
468         struct vattr *vap = ap->a_vap;
469         struct ucred *cred = ap->a_cred;
470         struct proc *p = ap->a_p;
471         int error = 0;
472         gid_t *gp;
473         int i;
474         dn_p    dnp;
475
476         if (vap->va_flags != VNOVAL)    /* XXX needs to be implemented */
477                 return (EOPNOTSUPP);
478
479         if ((error = devfs_vntodn(vp,&dnp)) != 0)
480         {
481                 printf("devfs_vntodn returned %d ",error);
482                 return error;
483         }
484 DBPRINT(("setattr\n"));
485         if ((vap->va_type != VNON)  ||
486             (vap->va_nlink != VNOVAL)  ||
487             (vap->va_fsid != VNOVAL)  ||
488             (vap->va_fileid != VNOVAL)  ||
489             (vap->va_blocksize != VNOVAL)  ||
490             (vap->va_rdev != VNOVAL)  ||
491             (vap->va_bytes != VNOVAL)  ||
492             (vap->va_gen != VNOVAL ))
493         {
494                 return EINVAL;
495         }
496
497
498         /* 
499          * Anyone can touch the files in such a way that the times are set
500          * to NOW (e.g. run 'touch') if they have write permissions
501          * however only the owner or root can set "un-natural times.
502          * They also don't need write permissions.
503          */
504         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
505 #if 0           /*
506                  * This next test is pointless under devfs for now..
507                  * as there is only one devfs hiding under potentially many
508                  * mountpoints and actual device node are really 'mounted' under
509                  * a FAKE mountpoint inside the kernel only, no matter where it
510                  * APPEARS they are mounted to the outside world..
511                  * A readonly devfs doesn't exist anyway.
512                  */
513                 if (vp->v_mount->mnt_flag & MNT_RDONLY)
514                         return (EROFS);
515 #endif
516                 if (((vap->va_vaflags & VA_UTIMES_NULL) == 0) &&
517                     (cred->cr_uid != dnp->uid)  &&
518                     suser_xxx(cred, p, 0))
519                         return (EPERM);
520                     if(VOP_ACCESS(vp, VWRITE, cred, p))
521                         return (EACCES);
522                 dnp->atime = vap->va_atime;
523                 dnp->mtime = vap->va_mtime;
524                 nanotime(&dnp->ctime);
525                 return (0);
526         }
527
528         /*
529          * Change the permissions.. must be root or owner to do this.
530          */
531         if (vap->va_mode != (u_short)VNOVAL) {
532                 if ((cred->cr_uid != dnp->uid)
533                  && suser_xxx(cred, p, 0))
534                         return (EPERM);
535                 /* set drwxwxrwx stuff */
536                 dnp->mode &= ~07777;
537                 dnp->mode |= vap->va_mode & 07777;
538         }
539
540         /*
541          * Change the owner.. must be root to do this.
542          */
543         if (vap->va_uid != (uid_t)VNOVAL) {
544                 if (suser_xxx(cred, p, 0))
545                         return (EPERM);
546                 dnp->uid = vap->va_uid;
547         }
548
549         /*
550          * Change the group.. must be root or owner to do this.
551          * If we are the owner, we must be in the target group too.
552          * don't use suser_xxx() unless you have to as it reports
553          * whether you needed suser_xxx powers or not.
554          */
555         if (vap->va_gid != (gid_t)VNOVAL) {
556                 if (cred->cr_uid == dnp->uid){
557                         gp = cred->cr_groups;
558                         for (i = 0; i < cred->cr_ngroups; i++, gp++) {
559                                 if (vap->va_gid == *gp)
560                                         goto cando; 
561                         }
562                 }
563                 /*
564                  * we can't do it with normal privs,
565                  * do we have an ace up our sleeve?
566                  */
567                 if( suser_xxx(cred, p, 0))
568                         return (EPERM);
569 cando:
570                 dnp->gid = vap->va_gid;
571         }
572 #if 0
573         /*
574          * Copied from somewhere else
575          * but only kept as a marker and reminder of the fact that
576          * flags should be handled some day
577          */
578         if (vap->va_flags != VNOVAL) {
579                 if (error = suser_xxx(cred, p, 0))
580                         return error;
581                 if (cred->cr_uid == 0)
582                 ;
583                 else {
584                 }
585         }
586 #endif
587         return error;
588 }
589
590
591 static int
592 devfs_xread(struct vop_read_args *ap)
593         /*struct vop_read_args {
594                 struct vnode *a_vp;
595                 struct uio *a_uio;
596                 int  a_ioflag;
597                 struct ucred *a_cred;
598         } */
599 {
600         int     error = 0;
601         dn_p    dnp;
602         struct vnode *vp = ap->a_vp;
603
604 DBPRINT(("read\n"));
605         if ((error = devfs_vntodn(vp,&dnp)) != 0)
606         {
607                 printf("devfs_vntodn returned %d ",error);
608                 return error;
609         }
610
611
612         switch (vp->v_type) {
613         case VREG:
614                 return(EINVAL);
615         case VDIR:
616                 return VOP_READDIR(vp,ap->a_uio,ap->a_cred,
617                                         NULL,NULL,NULL);
618         case VCHR:
619         case VBLK:
620                 panic("devfs:  vnode methods");
621
622         default:
623                 panic("devfs_read(): bad file type");
624                 break;
625         }
626 }
627
628 /*
629  *  Write data to a file or directory.
630  */
631 static int
632 devfs_xwrite(struct vop_write_args *ap)
633         /*struct vop_write_args  {
634                 struct vnode *a_vp;
635                 struct uio *a_uio;
636                 int  a_ioflag;
637                 struct ucred *a_cred;
638         } */
639 {
640         struct vnode *vp = ap->a_vp;
641
642         switch (vp->v_type) {
643         case VREG:
644                 return(EINVAL);
645         case VDIR:
646                 return(EISDIR);
647         case VCHR:
648         case VBLK:
649                 panic("devfs:  vnode methods");
650         default:
651                 panic("devfs_xwrite(): bad file type");
652         }
653 }
654
655
656 static int
657 devfs_remove(struct vop_remove_args *ap)
658         /*struct vop_remove_args  {
659                 struct vnode *a_dvp;
660                 struct vnode *a_vp;
661                 struct componentname *a_cnp;
662         } */ 
663 {
664         struct vnode *vp = ap->a_vp;
665         struct vnode *dvp = ap->a_dvp;
666         struct componentname *cnp = ap->a_cnp;
667         dn_p  tp, tdp;
668         devnm_p tnp;
669         int doingdirectory = 0;
670         int error = 0;
671         uid_t ouruid = cnp->cn_cred->cr_uid;
672
673
674 DBPRINT(("remove\n"));
675         /*
676          * Lock our directories and get our name pointers
677          * assume that the names are null terminated as they
678          * are the end of the path. Get pointers to all our
679          * devfs structures.
680          */
681         if ((error = devfs_vntodn(dvp, &tdp)) != 0) {
682 abortit:
683                 return (error);
684         }
685         if ((error = devfs_vntodn(vp, &tp)) != 0) goto abortit;
686         /*
687          * Assuming we are atomic, dev_lookup left this for us
688          */
689         tnp = tp->last_lookup;
690         
691
692         /*
693          * Check we are doing legal things WRT the new flags
694          */
695         if ((tp->flags & (IMMUTABLE | APPEND))
696           || (tdp->flags & APPEND) /*XXX eh?*/ ) {
697                 error = EPERM;
698                 goto abortit;
699         }
700
701         /*
702          * Make sure that we don't try do something stupid
703          */
704         if ((tp->type) == DEV_DIR) {
705                 /*
706                  * Avoid ".", "..", and aliases of "." for obvious reasons.
707                  */
708                 if ( (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') 
709                     || (cnp->cn_flags&ISDOTDOT) ) {
710                         error = EINVAL;
711                         goto abortit;
712                 }
713                 doingdirectory++;
714         }
715
716         /***********************************
717          * Start actually doing things.... *
718          ***********************************/
719         getnanotime(&(tdp->mtime));
720
721
722         /*
723          * own the parent directory, or the destination of the rename,
724          * otherwise the destination may not be changed (except by
725          * root). This implements append-only directories.
726          * XXX shoudn't this be in generic code? 
727          */
728         if ((tdp->mode & S_ISTXT)
729           && ouruid != 0
730           && ouruid != tdp->uid
731           && ouruid != tp->uid ) {
732                 error = EPERM;
733                 goto abortit;
734         }
735         /*
736          * Target must be empty if a directory and have no links
737          * to it. Also, ensure source and target are compatible
738          * (both directories, or both not directories).
739          */
740         if (( doingdirectory) && (tp->links > 2)) {
741                         printf("nlink = %d\n",tp->links); /*XXX*/
742                         error = ENOTEMPTY;
743                         goto abortit;
744         }
745         dev_free_name(tnp);
746         tp = NULL;
747         return (error);
748 }
749
750 /*
751  */
752 static int
753 devfs_link(struct vop_link_args *ap)
754         /*struct vop_link_args  {
755                 struct vnode *a_tdvp;
756                 struct vnode *a_vp;
757                 struct componentname *a_cnp;
758         } */ 
759 {
760         struct vnode *vp = ap->a_vp;
761         struct vnode *tdvp = ap->a_tdvp;
762         struct componentname *cnp = ap->a_cnp;
763         dn_p  fp, tdp;
764         devnm_p tnp;
765         int error = 0;
766
767 DBPRINT(("link\n"));
768         /*
769          * First catch an arbitrary restriction for this FS
770          */
771         if(cnp->cn_namelen > DEVMAXNAMESIZE) {
772                 error = ENAMETOOLONG;
773                 goto abortit;
774         }
775
776         /*
777          * Lock our directories and get our name pointers
778          * assume that the names are null terminated as they
779          * are the end of the path. Get pointers to all our
780          * devfs structures.
781          */
782         if ((error = devfs_vntodn(tdvp,&tdp)) != 0) goto abortit;
783         if ((error = devfs_vntodn(vp,&fp)) != 0) goto abortit;
784         
785         /*
786          * trying to move it out of devfs? (v_tag == VT_DEVFS)
787          */
788         if ( (vp->v_tag != VT_DEVFS)
789          || (vp->v_tag != tdvp->v_tag) ) {
790                 error = EXDEV;
791 abortit:
792                 goto out;
793         }
794
795         /*
796          * Check we are doing legal things WRT the new flags
797          */
798         if (fp->flags & (IMMUTABLE | APPEND)) {
799                 error = EPERM;
800                 goto abortit;
801         }
802
803         /***********************************
804          * Start actually doing things.... *
805          ***********************************/
806         getnanotime(&(tdp->atime));
807         error = dev_add_name(cnp->cn_nameptr,
808                         tdp,
809                         NULL,
810                         fp,
811                         &tnp);
812 out:
813         return (error);
814
815 }
816
817 /*
818  * Rename system call. Seems overly complicated to me...
819  *      rename("foo", "bar");
820  * is essentially
821  *      unlink("bar");
822  *      link("foo", "bar");
823  *      unlink("foo");
824  * but ``atomically''.
825  *
826  * When the target exists, both the directory
827  * and target vnodes are locked.
828  * the source and source-parent vnodes are referenced
829  *
830  *
831  * Basic algorithm is:
832  *
833  * 1) Bump link count on source while we're linking it to the
834  *    target.  This also ensure the inode won't be deleted out
835  *    from underneath us while we work (it may be truncated by
836  *    a concurrent `trunc' or `open' for creation).
837  * 2) Link source to destination.  If destination already exists,
838  *    delete it first.
839  * 3) Unlink source reference to node if still around. If a
840  *    directory was moved and the parent of the destination
841  *    is different from the source, patch the ".." entry in the
842  *    directory.
843  */
844 static int
845 devfs_rename(struct vop_rename_args *ap)
846         /*struct vop_rename_args  {
847                 struct vnode *a_fdvp;
848                 struct vnode *a_fvp;
849                 struct componentname *a_fcnp;
850                 struct vnode *a_tdvp;
851                 struct vnode *a_tvp;
852                 struct componentname *a_tcnp;
853         } */
854 {
855         struct vnode *tvp = ap->a_tvp;
856         struct vnode *tdvp = ap->a_tdvp;
857         struct vnode *fvp = ap->a_fvp;
858         struct vnode *fdvp = ap->a_fdvp;
859         struct componentname *tcnp = ap->a_tcnp;
860         struct componentname *fcnp = ap->a_fcnp;
861         struct proc *p = fcnp->cn_proc;
862         dn_p fp, fdp, tp, tdp;
863         devnm_p fnp,tnp;
864         int doingdirectory = 0;
865         int error = 0;
866
867         /*
868          * First catch an arbitrary restriction for this FS
869          */
870         if(tcnp->cn_namelen > DEVMAXNAMESIZE) {
871                 error = ENAMETOOLONG;
872                 goto abortit;
873         }
874
875         /*
876          * Lock our directories and get our name pointers
877          * assume that the names are null terminated as they
878          * are the end of the path. Get pointers to all our
879          * devfs structures.
880          */
881         if ((error = devfs_vntodn(tdvp,&tdp)) != 0) goto abortit;
882         if ((error = devfs_vntodn(fdvp,&fdp)) != 0) goto abortit;
883         if ((error = devfs_vntodn(fvp,&fp)) != 0) goto abortit;
884         fnp = fp->last_lookup;
885         if (tvp) {
886                 if ((error = devfs_vntodn(tvp,&tp)) != 0) goto abortit;
887                 tnp = tp->last_lookup;
888         } else {
889                 tp = NULL;
890                 tnp = NULL;
891         }
892         
893         /*
894          * trying to move it out of devfs? (v_tag == VT_DEVFS)
895          * if we move a dir across mnt points. we need to fix all
896          * the mountpoint pointers! XXX
897          * so for now keep dirs within the same mount
898          */
899         if ( (fvp->v_tag != VT_DEVFS)
900          || (fvp->v_tag != tdvp->v_tag)
901          || (tvp && (fvp->v_tag != tvp->v_tag))
902          || ((fp->type == DEV_DIR) && (fp->dvm != tdp->dvm ))) {
903                 error = EXDEV;
904 abortit:
905                 if (tdvp == tvp) /* eh? */
906                         vrele(tdvp);
907                 else
908                         vput(tdvp);
909                 if (tvp)
910                         vput(tvp);
911                 vrele(fdvp);
912                 vrele(fvp);
913                 return (error);
914         }
915
916         /*
917          * Check we are doing legal things WRT the new flags
918          */
919         if ((tp && (tp->flags & (IMMUTABLE | APPEND)))
920           || (fp->flags & (IMMUTABLE | APPEND))
921           || (fdp->flags & APPEND)) {
922                 error = EPERM;
923                 goto abortit;
924         }
925
926         /*
927          * Make sure that we don't try do something stupid
928          */
929         if ((fp->type) == DEV_DIR) {
930                 /*
931                  * Avoid ".", "..", and aliases of "." for obvious reasons.
932                  */
933                 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') 
934                     || (fcnp->cn_flags&ISDOTDOT) 
935                     || (tcnp->cn_namelen == 1 && tcnp->cn_nameptr[0] == '.') 
936                     || (tcnp->cn_flags&ISDOTDOT) 
937                     || (tdp == fp )) {
938                         error = EINVAL;
939                         goto abortit;
940                 }
941                 doingdirectory++;
942         }
943
944         /*
945          * If ".." must be changed (ie the directory gets a new
946          * parent) then the source directory must not be in the
947          * directory heirarchy above the target, as this would
948          * orphan everything below the source directory. Also
949          * the user must have write permission in the source so
950          * as to be able to change "..". 
951          */
952         if (doingdirectory && (tdp != fdp)) {
953                 dn_p tmp,ntmp;
954                 error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
955                 tmp = tdp;
956                 do {
957                         if(tmp == fp) {
958                                 /* XXX unlock stuff here probably */
959                                 error = EINVAL;
960                                 goto out;
961                         }
962                         ntmp = tmp;
963                 } while ((tmp = tmp->by.Dir.parent) != ntmp);
964         }
965
966         /***********************************
967          * Start actually doing things.... *
968          ***********************************/
969         getnanotime(&(fp->atime));
970         /*
971          * Check if just deleting a link name.
972          */
973         if (fvp == tvp) {
974                 if (fvp->v_type == VDIR) {
975                         error = EINVAL;
976                         goto abortit;
977                 }
978
979                 /* Release destination completely. */
980                 vput(tdvp);
981                 vput(tvp);
982
983                 /* Delete source. */
984                 vrele(fdvp);
985                 vrele(fvp);
986                 dev_free_name(fnp);
987                 return 0;
988         }
989
990
991         /*
992          * 1) Bump link count while we're moving stuff
993          *    around.  If we crash somewhere before
994          *    completing our work,  too bad :)
995          */
996         fp->links++;
997         /*
998          * If the target exists zap it (unless it's a non-empty directory)
999          * We could do that as well but won't
1000          */
1001         if (tp) {
1002                 int ouruid = tcnp->cn_cred->cr_uid;
1003                 /*
1004                  * If the parent directory is "sticky", then the user must
1005                  * own the parent directory, or the destination of the rename,
1006                  * otherwise the destination may not be changed (except by
1007                  * root). This implements append-only directories.
1008                  * XXX shoudn't this be in generic code? 
1009                  */
1010                 if ((tdp->mode & S_ISTXT)
1011                   && ouruid != 0
1012                   && ouruid != tdp->uid
1013                   && ouruid != tp->uid ) {
1014                         error = EPERM;
1015                         goto bad;
1016                 }
1017                 /*
1018                  * Target must be empty if a directory and have no links
1019                  * to it. Also, ensure source and target are compatible
1020                  * (both directories, or both not directories).
1021                  */
1022                 if (( doingdirectory) && (tp->links > 2)) {
1023                                 printf("nlink = %d\n",tp->links); /*XXX*/
1024                                 error = ENOTEMPTY;
1025                                 goto bad;
1026                 }
1027                 dev_free_name(tnp);
1028                 tp = NULL;
1029         }
1030         dev_add_name(tcnp->cn_nameptr,tdp,fnp->as.front.realthing,fp,&tnp);
1031         fnp->dnp = NULL;
1032         fp->links--; /* one less link to it.. */
1033         dev_free_name(fnp);
1034         fp->links--; /* we added one earlier*/
1035         if (tdp)
1036                 vput(tdvp);
1037         if (tp)
1038                 vput(fvp);
1039         vrele(ap->a_fvp);
1040         return (error);
1041
1042 bad:
1043         if (tp)
1044                 vput(tvp);
1045         vput(tdvp);
1046 out:
1047         if (vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p) == 0) {
1048                 fp->links--; /* we added one earlier*/
1049                 vput(fvp);
1050         } else
1051                 vrele(fvp);
1052         return (error);
1053 }
1054
1055 static int
1056 devfs_symlink(struct vop_symlink_args *ap)
1057         /*struct vop_symlink_args {
1058                 struct vnode *a_dvp;
1059                 struct vnode **a_vpp;
1060                 struct componentname *a_cnp;
1061                 struct vattr *a_vap;
1062                 char *a_target;
1063         } */
1064 {
1065         int error;
1066         dn_p dnp;
1067         union typeinfo by;
1068         devnm_p nm_p;
1069
1070 DBPRINT(("symlink\n"));
1071         if((error = devfs_vntodn(ap->a_dvp, &dnp)) != 0) {
1072                 return (error);
1073         }
1074                 
1075         by.Slnk.name = ap->a_target;
1076         by.Slnk.namelen = strlen(ap->a_target);
1077         dev_add_entry(ap->a_cnp->cn_nameptr, dnp, DEV_SLNK, &by,
1078                 NULL, NULL, &nm_p);
1079         if((error = devfs_dntovn(nm_p->dnp, ap->a_vpp)) != 0) {
1080                 return (error);
1081         }
1082         VOP_SETATTR(*ap->a_vpp, ap->a_vap, ap->a_cnp->cn_cred,
1083                 ap->a_cnp->cn_proc);
1084         return 0;
1085 }
1086
1087 /*
1088  * Vnode op for readdir
1089  */
1090 static int
1091 devfs_readdir(struct vop_readdir_args *ap)
1092         /*struct vop_readdir_args {
1093                 struct vnode *a_vp;
1094                 struct uio *a_uio;
1095                 struct ucred *a_cred;
1096                 int *eofflag;
1097                 int *ncookies;
1098                 u_int **cookies;
1099         } */
1100 {
1101         struct vnode *vp = ap->a_vp;
1102         struct uio *uio = ap->a_uio;
1103         struct dirent dirent;
1104         dn_p dir_node;
1105         devnm_p name_node;
1106         char    *name;
1107         int error = 0;
1108         int reclen;
1109         int nodenumber;
1110         int     startpos,pos;
1111
1112 DBPRINT(("readdir\n"));
1113
1114 /*  set up refs to dir */
1115         if ((error = devfs_vntodn(vp,&dir_node)) != 0)
1116                 return error;
1117         if(dir_node->type != DEV_DIR)
1118                 return(ENOTDIR);
1119
1120         pos = 0;
1121         startpos = uio->uio_offset;
1122         name_node = dir_node->by.Dir.dirlist;
1123         nodenumber = 0;
1124         getnanotime(&(dir_node->atime));
1125
1126         while ((name_node || (nodenumber < 2)) && (uio->uio_resid > 0))
1127         {
1128                 switch(nodenumber)
1129                 {
1130                 case    0:
1131                         dirent.d_fileno = (uintptr_t)(void *)dir_node;
1132                         name = ".";
1133                         dirent.d_namlen = 1;
1134                         dirent.d_type = DT_DIR;
1135                         break;
1136                 case    1:
1137                         if(dir_node->by.Dir.parent)
1138                                 dirent.d_fileno
1139                                  = (uintptr_t)(void *)dir_node->by.Dir.parent;
1140                         else
1141                                 dirent.d_fileno = (uintptr_t)(void *)dir_node;
1142                         name = "..";
1143                         dirent.d_namlen = 2;
1144                         dirent.d_type = DT_DIR;
1145                         break;
1146                 default:
1147                         dirent.d_fileno = (uintptr_t)(void *)name_node->dnp;
1148                         dirent.d_namlen = strlen(name_node->name);
1149                         name = name_node->name;
1150                         switch(name_node->dnp->type) {
1151                         case DEV_BDEV:
1152                                 dirent.d_type = DT_BLK;
1153                                 break;
1154                         case DEV_CDEV:
1155                                 dirent.d_type = DT_CHR;
1156                                 break;
1157                         case DEV_DDEV:
1158                                 dirent.d_type = DT_SOCK; /*XXX*/
1159                                 break;
1160                         case DEV_DIR:
1161                                 dirent.d_type = DT_DIR;
1162                                 break;
1163                         case DEV_SLNK:
1164                                 dirent.d_type = DT_LNK;
1165                                 break;
1166                         default:
1167                                 dirent.d_type = DT_UNKNOWN;
1168                         }
1169                 }
1170
1171                 reclen = dirent.d_reclen = GENERIC_DIRSIZ(&dirent);
1172
1173                 if(pos >= startpos)     /* made it to the offset yet? */
1174                 {
1175                         if (uio->uio_resid < reclen) /* will it fit? */
1176                                 break;
1177                         strcpy( dirent.d_name,name);
1178                         if ((error = uiomove ((caddr_t)&dirent,
1179                                         dirent.d_reclen, uio)) != 0)
1180                                 break;
1181                 }
1182                 pos += reclen;
1183                 if((nodenumber >1) && name_node)
1184                         name_node = name_node->next;
1185                 nodenumber++;
1186         }
1187         uio->uio_offset = pos;
1188
1189         return (error);
1190 }
1191
1192
1193 /*
1194  */
1195 static int
1196 devfs_readlink(struct vop_readlink_args *ap)
1197         /*struct vop_readlink_args {
1198                 struct vnode *a_vp;
1199                 struct uio *a_uio;
1200                 struct ucred *a_cred;
1201         } */
1202 {
1203         struct vnode *vp = ap->a_vp;
1204         struct uio *uio = ap->a_uio;
1205         dn_p lnk_node;
1206         int error = 0;
1207
1208
1209 DBPRINT(("readlink\n"));
1210 /*  set up refs to dir */
1211         if ((error = devfs_vntodn(vp,&lnk_node)) != 0)
1212                 return error;
1213         if(lnk_node->type != DEV_SLNK)
1214                 return(EINVAL);
1215         if ((error = VOP_ACCESS(vp, VREAD, ap->a_cred, NULL)) != 0) { /* XXX */
1216                 return error;
1217         }
1218         error = uiomove(lnk_node->by.Slnk.name, lnk_node->by.Slnk.namelen, uio);
1219         return error;
1220 }
1221
1222 static int
1223 devfs_reclaim(struct vop_reclaim_args *ap)
1224         /*struct vop_reclaim_args {
1225                 struct vnode *a_vp;
1226         } */
1227 {
1228         dn_p    dnp = NULL;
1229         int     error;
1230         struct vnode *vp = ap->a_vp;
1231
1232 DBPRINT(("reclaim\n"));
1233         if ((error = devfs_vntodn(vp,&dnp)) != 0)
1234         {
1235                 printf("devfs_vntodn returned %d ",error);
1236                 return error;
1237         }
1238
1239         vp->v_data = NULL;
1240         if (dnp) {
1241                 dnp->vn = 0;
1242                 dnp->vn_id = 0;
1243         }
1244         return(0);
1245 }
1246
1247 /*
1248  * Print out the contents of a /devfs vnode.
1249  */
1250 static int
1251 devfs_print(struct vop_print_args *ap)
1252         /*struct vop_print_args {
1253                 struct vnode *a_vp;
1254         } */
1255 {
1256
1257         printf("tag VT_DEVFS, devfs vnode\n");
1258         return (0);
1259 }
1260
1261 /**************************************************************************\
1262 * pseudo ops *
1263 \**************************************************************************/
1264
1265 /*proto*/
1266 void
1267 devfs_dropvnode(dn_p dnp)
1268 {
1269         struct vnode *vn_p;
1270
1271 #ifdef PARANOID
1272         if(!dnp)
1273         {
1274                 printf("devfs: dn count dropped too early\n");
1275         }
1276 #endif
1277         vn_p = dnp->vn;
1278         /*
1279          * check if we have a vnode.......
1280          */
1281         if((vn_p) && ( dnp->vn_id == vn_p->v_id) && (dnp == (dn_p)vn_p->v_data))
1282         {
1283                 VOP_REVOKE(vn_p, REVOKEALL);
1284         }
1285         dnp->vn = NULL; /* be pedantic about this */
1286 }
1287
1288 /* struct vnode *speclisth[SPECHSZ];*/ /* till specfs goes away */
1289
1290 /*
1291  * Open a special file.
1292         struct vop_open_args {
1293                 struct vnode *a_vp;
1294                 int  a_mode;
1295                 struct ucred *a_cred;
1296                 struct proc *a_p;
1297         } *ap;
1298  */
1299 /* ARGSUSED */
1300 static int
1301 devfs_open( struct vop_open_args *ap)
1302 {
1303         struct proc *p = ap->a_p;
1304         struct vnode *vp = ap->a_vp;
1305         int error;
1306         dn_p    dnp;
1307         struct cdevsw *dsw;
1308         dev_t dev = vp->v_rdev;
1309
1310         if ((error = devfs_vntodn(vp,&dnp)) != 0)
1311                 return error;
1312
1313         switch (vp->v_type) {
1314         case VCHR:
1315                 dsw = devsw(dev);
1316                 if ( (dsw == NULL) || (dsw->d_open == NULL))
1317                         return ENXIO;
1318                 if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE) && 
1319                     vn_isdisk(vp, NULL)) {
1320                         /*
1321                          * When running in very secure mode, do not allow
1322                          * opens for writing of any disk devices.
1323                          */
1324                         if (securelevel >= 2)
1325                                 return (EPERM);
1326                         /*
1327                          * When running in secure mode, do not allow opens
1328                          * for writing if the device is mounted.
1329                          */
1330                         if (securelevel >= 1 && vp->v_specmountpoint != NULL)
1331                                 return (EPERM);
1332                 }
1333                 if ((dsw->d_flags & D_TYPEMASK) == D_TTY)
1334                         vp->v_flag |= VISTTY;
1335                 VOP_UNLOCK(vp, 0, p);
1336                 error = (*vp->v_rdev->si_devsw->d_open)(
1337                                         vp->v_rdev,
1338                                         ap->a_mode,
1339                                         S_IFCHR,
1340                                         p);
1341                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
1342                 return (error);
1343                 /* NOT REACHED */
1344         case VBLK:
1345                 dsw = devsw(dev);
1346                 if ( (dsw == NULL) || (dsw->d_open == NULL))
1347                         return ENXIO;
1348                 /*
1349                  * When running in very secure mode, do not allow
1350                  * opens for writing of any disk block devices.
1351                  */
1352                 if (securelevel >= 2 && ap->a_cred != FSCRED &&
1353                     (ap->a_mode & FWRITE) &&
1354                     (dsw->d_flags & D_TYPEMASK) == D_DISK)
1355                         return (EPERM);
1356
1357                 /*
1358                  * Do not allow opens of block devices that are
1359                  * currently mounted.
1360                  */
1361                 error = vfs_mountedon(vp);
1362                 if (error)
1363                         return (error);
1364                 error = (*vp->v_rdev->si_devsw->d_open)(
1365                                         vp->v_rdev,
1366                                         ap->a_mode,
1367                                         S_IFBLK,
1368                                         p);
1369                 break;
1370         default:
1371                 break;
1372         }
1373         return (error);
1374 }
1375
1376 /* ARGSUSED */
1377 static int
1378 devfs_read( struct vop_read_args *ap)
1379 {
1380         int error;
1381
1382         error = VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap);
1383         return (error);
1384 }
1385
1386 /* ARGSUSED */
1387 static int
1388 devfs_write( struct vop_write_args *ap)
1389 {
1390         int error;
1391
1392         error = VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap);
1393         return (error);
1394 }
1395
1396 /*
1397  * Device ioctl operation.
1398         struct vop_ioctl_args {
1399                 struct vnode *a_vp;
1400                 int  a_command;
1401                 caddr_t  a_data;
1402                 int  a_fflag;
1403                 struct ucred *a_cred;
1404                 struct proc *a_p;
1405         }
1406  */
1407 /* ARGSUSED */
1408 static int
1409 devfs_ioctl(struct vop_ioctl_args *ap)
1410 {
1411         dn_p    dnp;
1412         int     error;
1413         struct vnode *vp = ap->a_vp;
1414
1415         if ((error = devfs_vntodn(vp,&dnp)) != 0)
1416                 return error;
1417
1418
1419         switch (vp->v_type) {
1420
1421         case VCHR:
1422                 return ((*vp->v_rdev->si_devsw->d_ioctl)(vp->v_rdev,
1423                                         ap->a_command,
1424                                         ap->a_data,
1425                                         ap->a_fflag,
1426                                         ap->a_p));
1427         case VBLK:
1428                 return ((*vp->v_rdev->si_devsw->d_ioctl)(vp->v_rdev,
1429                                         ap->a_command,
1430                                         ap->a_data,
1431                                         ap->a_fflag,
1432                                         ap->a_p));
1433         default:
1434                 panic("devfs_ioctl");
1435                 /* NOTREACHED */
1436         }
1437 }
1438
1439 /*
1440         struct vop_poll_args {
1441                 struct vnode *a_vp;
1442                 int  a_events;
1443                 struct ucred *a_cred;
1444                 struct proc *a_p;
1445         } *ap;
1446 */
1447 /* ARGSUSED */
1448 static int
1449 devfs_poll(struct vop_poll_args *ap)
1450 {
1451         dn_p    dnp;
1452         int     error;
1453         struct vnode *vp = ap->a_vp;
1454
1455         if ((error = devfs_vntodn(vp,&dnp)) != 0)
1456                 return error;
1457
1458
1459         switch (vp->v_type) {
1460
1461         case VCHR:
1462                 return (*vp->v_rdev->si_devsw->d_poll)(vp->v_rdev,
1463                                         ap->a_events,
1464                                         ap->a_p);
1465         default:
1466                 return (vop_defaultop((struct vop_generic_args *)ap));
1467
1468         }
1469 }
1470 /*
1471  * Synch buffers associated with a block device
1472         struct vop_fsync_args {
1473                 struct vnode *a_vp;
1474                 struct ucred *a_cred;
1475                 int  a_waitfor;
1476                 struct proc *a_p;
1477         } 
1478  */
1479 /* ARGSUSED */
1480 static int
1481 devfs_fsync(struct vop_fsync_args *ap)
1482 {
1483         struct vnode *vp = ap->a_vp;
1484         struct buf *bp;
1485         struct buf *nbp;
1486         int s;
1487         dn_p    dnp;
1488         int     error;
1489
1490         if ((error = devfs_vntodn(vp,&dnp)) != 0)
1491                 return error;
1492
1493
1494         if (vp->v_type == VCHR)
1495                 return (0);
1496         /*
1497          * Flush all dirty buffers associated with a block device.
1498          */
1499 loop:
1500         s = splbio();
1501         for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
1502                 nbp = TAILQ_NEXT(bp, b_vnbufs);
1503                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
1504                         continue;
1505                 if ((bp->b_flags & B_DELWRI) == 0)
1506                         panic("devfs_fsync: not dirty");
1507                 if ((vp->v_flag & VOBJBUF) && (bp->b_flags & B_CLUSTEROK)) {
1508                         BUF_UNLOCK(bp);
1509                         vfs_bio_awrite(bp);
1510                         splx(s);
1511                 } else {
1512                         bremfree(bp);
1513                         splx(s);
1514                         bawrite(bp);
1515                 }
1516                 goto loop;
1517         }
1518         if (ap->a_waitfor == MNT_WAIT) {
1519                 while (vp->v_numoutput) {
1520                         vp->v_flag |= VBWAIT;
1521                         (void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "spfsyn", 0);
1522                 }
1523 #ifdef DIAGNOSTIC
1524                 if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
1525                         vprint("devfs_fsync: dirty", vp);
1526                         splx(s);
1527                         goto loop;
1528                 }
1529 #endif
1530         }
1531         splx(s);
1532         return (0);
1533 }
1534 /*
1535  *
1536  *      struct vop_inactive_args {
1537  *              struct vnode *a_vp;
1538  *              struct proc *a_p;
1539  *      } 
1540  */
1541
1542 static int
1543 devfs_inactive(struct vop_inactive_args *ap)
1544 {
1545
1546         VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
1547         return (0);
1548 }
1549
1550 /*
1551  * Just call the device strategy routine
1552         struct vop_strategy_args {
1553                 struct vnode *a_vp;
1554                 struct buf *a_bp;
1555         }
1556  */
1557 static int
1558 devfs_strategy(struct vop_strategy_args *ap)
1559 {
1560         struct buf *bp = ap->a_bp;
1561         dn_p    dnp;
1562         int     error;
1563         struct vnode *vp = ap->a_vp;
1564
1565         if ((vp->v_type != VCHR)
1566         &&  (vp->v_type != VBLK))
1567                 panic ("devfs_strat:badvnode type");
1568         if ((error = devfs_vntodn(vp,&dnp)) != 0)
1569                 return error;
1570
1571
1572         if ((bp->b_iocmd == BIO_WRITE) &&
1573                 (LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
1574                 (*bioops.io_start)(bp);
1575         switch (vp->v_type) {
1576         case VCHR:
1577                 (*vp->v_rdev->si_devsw->d_strategy)(bp);
1578                 break;
1579         case VBLK:
1580                 (*vp->v_rdev->si_devsw->d_strategy)(bp);
1581                 break;
1582         default:
1583                 /* XXX set error code? */
1584                 break;
1585         }
1586         return (0);
1587 }
1588
1589 /*
1590  * I can't say I'm completely sure what this one is for.
1591  * it's copied from specfs.
1592         struct vop_freeblks_args {
1593                 struct vnode *a_vp;
1594                 daddr_t a_addr;
1595                 daddr_t a_length;
1596         };
1597  */
1598 static int
1599 devfs_freeblks(struct vop_freeblks_args *ap)
1600 {
1601         struct cdevsw *bsw;
1602         struct buf *bp;
1603         struct vnode *vp = ap->a_vp;
1604
1605         bsw = devsw(vp->v_rdev);
1606         if ((bsw->d_flags & D_CANFREE) == 0)
1607                 return (0);
1608         bp = geteblk(ap->a_length);
1609         bp->b_iocmd = BIO_DELETE;
1610         bp->b_dev = vp->v_rdev;
1611         bp->b_blkno = ap->a_addr;
1612         bp->b_offset = dbtob(ap->a_addr);
1613         bp->b_bcount = ap->a_length;
1614         DEV_STRATEGY(bp, 0);
1615         return (0);
1616 }
1617
1618
1619 /*
1620  * This is a noop, simply returning what one has been given.
1621         struct vop_bmap_args  {
1622                 struct vnode *a_vp;
1623                 daddr_t  a_bn;
1624                 struct vnode **a_vpp;
1625                 daddr_t *a_bnp;
1626                 int *a_runp;
1627                 int *a_runb;
1628         }
1629  */
1630 static int
1631 devfs_bmap(struct vop_bmap_args *ap)
1632 {
1633
1634         if (ap->a_vpp != NULL)
1635                 *ap->a_vpp = ap->a_vp;
1636         if (ap->a_bnp != NULL)
1637                 *ap->a_bnp = ap->a_bn;
1638         if (ap->a_runp != NULL)
1639                 *ap->a_runp = 0;
1640         if (ap->a_runb != NULL)
1641                 *ap->a_runb = 0;
1642         return (0);
1643 }
1644
1645 /*
1646  * Device close routine
1647         struct vop_close_args {
1648                 struct vnode *a_vp;
1649                 int  a_fflag;
1650                 struct ucred *a_cred;
1651                 struct proc *a_p;
1652         }
1653  */
1654 /* ARGSUSED */
1655 static int
1656 devfs_close(struct vop_close_args *ap)
1657 {
1658         struct vnode *vp = ap->a_vp;
1659         dn_p dnp;
1660         struct cdevsw *devswp;
1661         dev_t dev;
1662         int mode, error;
1663
1664         if ((error = devfs_vntodn(vp,&dnp)) != 0)
1665                 return error;
1666
1667
1668         switch (vp->v_type) {
1669
1670         case VCHR:
1671                 devswp = vp->v_rdev->si_devsw;
1672                 dev = vp->v_rdev;
1673                 mode = S_IFCHR;
1674                 /*
1675                  * Hack: a tty device that is a controlling terminal
1676                  * has a reference from the session structure.
1677                  * We cannot easily tell that a character device is
1678                  * a controlling terminal, unless it is the closing
1679                  * process' controlling terminal.  In that case,
1680                  * if the reference count is 2 (this last descriptor
1681                  * plus the session), release the reference from the session.
1682                  */
1683                 if (vcount(vp) == 2 && ap->a_p &&
1684                     (vp->v_flag & VXLOCK) == 0 &&
1685                     vp == ap->a_p->p_session->s_ttyvp) {
1686                         vrele(vp);
1687                         ap->a_p->p_session->s_ttyvp = NULL;
1688                 }
1689                 if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
1690                         return (0);
1691
1692                 break;
1693
1694         case VBLK:
1695                 devswp = vp->v_rdev->si_devsw;
1696                 dev = vp->v_rdev;
1697                 mode = S_IFBLK;
1698                 /*
1699                  * On last close of a block device (that isn't mounted)
1700                  * we must invalidate any in core blocks, so that
1701                  * we can, for instance, change floppy disks.
1702                  */
1703                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p);
1704                 error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0);
1705                 VOP_UNLOCK(vp, 0, ap->a_p);
1706                 if (error)
1707                         return (error);
1708
1709                 break;
1710         default:
1711                 panic("devfs_close: not special");
1712         }
1713         /*
1714          * If the vnode is locked, then we are in the midst
1715          * of forcably closing the device, otherwise we would normally
1716          * only close on last reference.
1717          * We do not want to really close the device if it
1718          * is still in use unless we are trying to close it
1719          * forcibly. Since every use (buffer, vnode, swap, cmap)
1720          * holds a reference to the vnode, and because we mark
1721          * any other vnodes that alias this device, when the
1722          * sum of the reference counts on all the aliased
1723          * vnodes descends to one, we are on last close.
1724          * defeat this however if the device wants to be told of every 
1725          * close.
1726          */
1727         if ((vp->v_flag & VXLOCK)
1728         || (devswp->d_flags & D_TRACKCLOSE)
1729         || (vcount(vp) <= 1)) {
1730                 return ((*devswp->d_close)(dev, ap->a_fflag, mode, ap->a_p));
1731         }
1732         return (0);
1733 }
1734
1735 /*
1736  * Special device advisory byte-level locks.
1737         struct vop_advlock_args {
1738                 struct vnode *a_vp;
1739                 caddr_t  a_id;
1740                 int  a_op;
1741                 struct flock *a_fl;
1742                 int  a_flags;
1743         }
1744  */
1745 /* ARGSUSED */
1746 static int
1747 devfs_advlock(struct vop_advlock_args *ap)
1748 {
1749
1750         return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
1751 }
1752
1753 /*
1754  * Special device bad operation
1755  */
1756 static int
1757 devfs_badop(void)
1758 {
1759
1760         panic("devfs_badop called");
1761         /* NOTREACHED */
1762 }
1763
1764 static void
1765 devfs_getpages_iodone(struct buf *bp)
1766 {
1767
1768         bp->b_flags |= B_DONE;
1769         wakeup(bp);
1770 }
1771
1772 static int
1773 devfs_getpages(struct vop_getpages_args *ap)
1774 {
1775         vm_offset_t kva;
1776         int error;
1777         int i, pcount, size, s;
1778         daddr_t blkno;
1779         struct buf *bp;
1780         vm_page_t m;
1781         vm_ooffset_t offset;
1782         int toff, nextoff, nread;
1783         struct vnode *vp = ap->a_vp;
1784         int blksiz;
1785         int gotreqpage;
1786
1787         error = 0;
1788         pcount = round_page(ap->a_count) / PAGE_SIZE;
1789
1790         /*
1791          * Calculate the offset of the transfer and do sanity check.
1792          * FreeBSD currently only supports an 8 TB range due to b_blkno
1793          * being in DEV_BSIZE ( usually 512 ) byte chunks on call to
1794          * VOP_STRATEGY.  XXX
1795          */
1796         offset = IDX_TO_OFF(ap->a_m[0]->pindex) + ap->a_offset;
1797
1798 #define DADDR_T_BIT     (sizeof(daddr_t)*8)
1799 #define OFFSET_MAX      ((1LL << (DADDR_T_BIT + DEV_BSHIFT)) - 1)
1800
1801         if (offset < 0 || offset > OFFSET_MAX) {
1802                 /* XXX still no %q in kernel. */
1803                 printf("devfs_getpages: preposterous offset 0x%x%08x\n",
1804                        (u_int)((u_quad_t)offset >> 32),
1805                        (u_int)(offset & 0xffffffff));
1806                 return (VM_PAGER_ERROR);
1807         }
1808
1809         blkno = btodb(offset);
1810
1811         /*
1812          * Round up physical size for real devices.  We cannot round using
1813          * v_mount's block size data because v_mount has nothing to do with
1814          * the device.  i.e. it's usually '/dev'.  We need the physical block
1815          * size for the device itself.
1816          *
1817          * We can't use v_specmountpoint because it only exists when the
1818          * block device is mounted.  However, we can use v_rdev.
1819          */
1820
1821         if (vp->v_type == VBLK)
1822                 blksiz = vp->v_rdev->si_bsize_phys;
1823         else
1824                 blksiz = DEV_BSIZE;
1825
1826         size = (ap->a_count + blksiz - 1) & ~(blksiz - 1);
1827
1828         bp = getpbuf(NULL);
1829         kva = (vm_offset_t)bp->b_data;
1830
1831         /*
1832          * Map the pages to be read into the kva.
1833          */
1834         pmap_qenter(kva, ap->a_m, pcount);
1835
1836         /* Build a minimal buffer header. */
1837         bp->b_iocmd = BIO_READ;
1838         bp->b_iodone = devfs_getpages_iodone;
1839
1840         /* B_PHYS is not set, but it is nice to fill this in. */
1841         bp->b_rcred = bp->b_wcred = curproc->p_ucred;
1842         if (bp->b_rcred != NOCRED)
1843                 crhold(bp->b_rcred);
1844         if (bp->b_wcred != NOCRED)
1845                 crhold(bp->b_wcred);
1846         bp->b_blkno = blkno;
1847         bp->b_lblkno = blkno;
1848         pbgetvp(vp, bp);
1849         bp->b_bcount = size;
1850         bp->b_bufsize = size;
1851         bp->b_resid = 0;
1852
1853         cnt.v_vnodein++;
1854         cnt.v_vnodepgsin += pcount;
1855
1856         /* Do the input. */
1857         BUF_STRATEGY(bp);
1858
1859         s = splbio();
1860
1861         /* We definitely need to be at splbio here. */
1862         while ((bp->b_flags & B_DONE) == 0)
1863                 tsleep(bp, PVM, "spread", 0);
1864
1865         splx(s);
1866
1867         if ((bp->b_flags & B_ERROR) != 0) {
1868                 if (bp->b_error)
1869                         error = bp->b_error;
1870                 else
1871                         error = EIO;
1872         }
1873
1874         nread = size - bp->b_resid;
1875
1876         if (nread < ap->a_count) {
1877                 bzero((caddr_t)kva + nread,
1878                         ap->a_count - nread);
1879         }
1880         pmap_qremove(kva, pcount);
1881
1882
1883         gotreqpage = 0;
1884         for (i = 0, toff = 0; i < pcount; i++, toff = nextoff) {
1885                 nextoff = toff + PAGE_SIZE;
1886                 m = ap->a_m[i];
1887
1888                 m->flags &= ~PG_ZERO;
1889
1890                 if (nextoff <= nread) {
1891                         m->valid = VM_PAGE_BITS_ALL;
1892                         vm_page_undirty(m);
1893                 } else if (toff < nread) {
1894                         /*
1895                          * Since this is a VM request, we have to supply the
1896                          * unaligned offset to allow vm_page_set_validclean()
1897                          * to zero sub-DEV_BSIZE'd portions of the page.
1898                          */
1899                         vm_page_set_validclean(m, 0, nread - toff);
1900                 } else {
1901                         m->valid = 0;
1902                         vm_page_undirty(m);
1903                 }
1904
1905                 if (i != ap->a_reqpage) {
1906                         /*
1907                          * Just in case someone was asking for this page we
1908                          * now tell them that it is ok to use.
1909                          */
1910                         if (!error || (m->valid == VM_PAGE_BITS_ALL)) {
1911                                 if (m->valid) {
1912                                         if (m->flags & PG_WANTED) {
1913                                                 vm_page_activate(m);
1914                                         } else {
1915                                                 vm_page_deactivate(m);
1916                                         }
1917                                         vm_page_wakeup(m);
1918                                 } else {
1919                                         vm_page_free(m);
1920                                 }
1921                         } else {
1922                                 vm_page_free(m);
1923                         }
1924                 } else if (m->valid) {
1925                         gotreqpage = 1;
1926                         /*
1927                          * Since this is a VM request, we need to make the
1928                          * entire page presentable by zeroing invalid sections.
1929                          */
1930                         if (m->valid != VM_PAGE_BITS_ALL)
1931                                 vm_page_zero_invalid(m, FALSE);
1932                 }
1933         }
1934         if (!gotreqpage) {
1935                 m = ap->a_m[ap->a_reqpage];
1936                 printf("devfs_getpages: I/O read failure: (error code=%d)\n",
1937                                                                 error);
1938                 printf("               size: %d, resid:"
1939                         " %ld, a_count: %d, valid: 0x%x\n",
1940                                 size, bp->b_resid, ap->a_count, m->valid);
1941                 printf("               nread: %d, reqpage:"
1942                         " %d, pindex: %d, pcount: %d\n",
1943                                 nread, ap->a_reqpage, m->pindex, pcount);
1944                 /*
1945                  * Free the buffer header back to the swap buffer pool.
1946                  */
1947                 relpbuf(bp, NULL);
1948                 return VM_PAGER_ERROR;
1949         }
1950         /*
1951          * Free the buffer header back to the swap buffer pool.
1952          */
1953         relpbuf(bp, NULL);
1954         return VM_PAGER_OK;
1955 }
1956
1957
1958
1959 /* These are the operations used by directories etc in a devfs */
1960
1961 vop_t **devfs_vnodeop_p;
1962 static struct vnodeopv_entry_desc devfs_vnodeop_entries[] = {
1963         { &vop_default_desc,            (vop_t *) vop_defaultop },
1964         { &vop_access_desc,             (vop_t *) devfs_access },
1965         { &vop_bmap_desc,               (vop_t *) devfs_badop },
1966         { &vop_getattr_desc,            (vop_t *) devfs_getattr },
1967         { &vop_inactive_desc,           (vop_t *) devfs_inactive },
1968         { &vop_link_desc,               (vop_t *) devfs_link },
1969         { &vop_lookup_desc,             (vop_t *) devfs_lookup },
1970         { &vop_pathconf_desc,           (vop_t *) vop_stdpathconf },
1971         { &vop_print_desc,              (vop_t *) devfs_print },
1972         { &vop_read_desc,               (vop_t *) devfs_xread },
1973         { &vop_readdir_desc,            (vop_t *) devfs_readdir },
1974         { &vop_readlink_desc,           (vop_t *) devfs_readlink },
1975         { &vop_reclaim_desc,            (vop_t *) devfs_reclaim },
1976         { &vop_remove_desc,             (vop_t *) devfs_remove },
1977         { &vop_rename_desc,             (vop_t *) devfs_rename },
1978         { &vop_setattr_desc,            (vop_t *) devfs_setattr },
1979         { &vop_symlink_desc,            (vop_t *) devfs_symlink },
1980         { &vop_write_desc,              (vop_t *) devfs_xwrite },
1981         { NULL, NULL }
1982 };
1983 static struct vnodeopv_desc devfs_vnodeop_opv_desc =
1984         { &devfs_vnodeop_p, devfs_vnodeop_entries };
1985
1986 VNODEOP_SET(devfs_vnodeop_opv_desc);
1987
1988
1989
1990 vop_t **devfs_spec_vnodeop_p;
1991 static struct vnodeopv_entry_desc devfs_spec_vnodeop_entries[] = {
1992         { &vop_default_desc,            (vop_t *) vop_defaultop },
1993         { &vop_access_desc,             (vop_t *) devfs_access },
1994         { &vop_advlock_desc,            (vop_t *) devfs_advlock },
1995         { &vop_bmap_desc,               (vop_t *) devfs_bmap },
1996         { &vop_close_desc,              (vop_t *) devfs_close },
1997         { &vop_create_desc,             (vop_t *) devfs_badop },
1998         { &vop_freeblks_desc,           (vop_t *) devfs_freeblks },
1999         { &vop_fsync_desc,              (vop_t *) devfs_fsync },
2000         { &vop_getattr_desc,            (vop_t *) devfs_getattr },
2001         { &vop_getpages_desc,           (vop_t *) devfs_getpages },
2002         { &vop_inactive_desc,           (vop_t *) devfs_inactive },
2003         { &vop_ioctl_desc,              (vop_t *) devfs_ioctl },
2004         { &vop_lease_desc,              (vop_t *) vop_null },
2005         { &vop_link_desc,               (vop_t *) devfs_badop },
2006         { &vop_lookup_desc,             (vop_t *) devfs_lookup },
2007         { &vop_mkdir_desc,              (vop_t *) devfs_badop },
2008         { &vop_mknod_desc,              (vop_t *) devfs_badop },
2009         { &vop_open_desc,               (vop_t *) devfs_open },
2010         { &vop_pathconf_desc,           (vop_t *) vop_stdpathconf },
2011         { &vop_poll_desc,               (vop_t *) devfs_poll },
2012         { &vop_print_desc,              (vop_t *) devfs_print },
2013         { &vop_read_desc,               (vop_t *) devfs_read },
2014         { &vop_readdir_desc,            (vop_t *) devfs_badop },
2015         { &vop_readlink_desc,           (vop_t *) devfs_badop },
2016         { &vop_reallocblks_desc,        (vop_t *) devfs_badop },
2017         { &vop_reclaim_desc,            (vop_t *) devfs_reclaim },
2018         { &vop_remove_desc,             (vop_t *) devfs_badop },
2019         { &vop_rename_desc,             (vop_t *) devfs_badop },
2020         { &vop_rmdir_desc,              (vop_t *) devfs_badop },
2021         { &vop_setattr_desc,            (vop_t *) devfs_setattr },
2022         { &vop_strategy_desc,           (vop_t *) devfs_strategy },
2023         { &vop_symlink_desc,            (vop_t *) devfs_symlink },
2024         { &vop_write_desc,              (vop_t *) devfs_write },
2025         { NULL, NULL }
2026 };
2027 static struct vnodeopv_desc devfs_spec_vnodeop_opv_desc =
2028         { &devfs_spec_vnodeop_p, devfs_spec_vnodeop_entries };
2029
2030 VNODEOP_SET(devfs_spec_vnodeop_opv_desc);
2031