]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/fs/devfs/devfs_vnops.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / sys / fs / devfs / devfs_vnops.c
1 /*-
2  * Copyright (c) 2000-2004
3  *      Poul-Henning Kamp.  All rights reserved.
4  * Copyright (c) 1989, 1992-1993, 1995
5  *      The Regents of the University of California.  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_vnops.c      8.15 (Berkeley) 5/21/95
32  * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vnops.c 1.43
33  *
34  * $FreeBSD$
35  */
36
37 /*
38  * TODO:
39  *      remove empty directories
40  *      mkdir: want it ?
41  */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/conf.h>
46 #include <sys/dirent.h>
47 #include <sys/fcntl.h>
48 #include <sys/file.h>
49 #include <sys/filedesc.h>
50 #include <sys/filio.h>
51 #include <sys/jail.h>
52 #include <sys/kernel.h>
53 #include <sys/lock.h>
54 #include <sys/malloc.h>
55 #include <sys/mount.h>
56 #include <sys/namei.h>
57 #include <sys/priv.h>
58 #include <sys/proc.h>
59 #include <sys/stat.h>
60 #include <sys/sx.h>
61 #include <sys/time.h>
62 #include <sys/ttycom.h>
63 #include <sys/unistd.h>
64 #include <sys/vnode.h>
65
66 static struct vop_vector devfs_vnodeops;
67 static struct vop_vector devfs_specops;
68 static struct fileops devfs_ops_f;
69
70 #include <fs/devfs/devfs.h>
71 #include <fs/devfs/devfs_int.h>
72
73 #include <security/mac/mac_framework.h>
74
75 static MALLOC_DEFINE(M_CDEVPDATA, "DEVFSP", "Metainfo for cdev-fp data");
76
77 struct mtx      devfs_de_interlock;
78 MTX_SYSINIT(devfs_de_interlock, &devfs_de_interlock, "devfs interlock", MTX_DEF);
79 struct sx       clone_drain_lock;
80 SX_SYSINIT(clone_drain_lock, &clone_drain_lock, "clone events drain lock");
81 struct mtx      cdevpriv_mtx;
82 MTX_SYSINIT(cdevpriv_mtx, &cdevpriv_mtx, "cdevpriv lock", MTX_DEF);
83
84 static int
85 devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp,
86     int *ref)
87 {
88
89         *dswp = devvn_refthread(fp->f_vnode, devp, ref);
90         if (*devp != fp->f_data) {
91                 if (*dswp != NULL)
92                         dev_relthread(*devp, *ref);
93                 return (ENXIO);
94         }
95         KASSERT((*devp)->si_refcount > 0,
96             ("devfs: un-referenced struct cdev *(%s)", devtoname(*devp)));
97         if (*dswp == NULL)
98                 return (ENXIO);
99         curthread->td_fpop = fp;
100         return (0);
101 }
102
103 int
104 devfs_get_cdevpriv(void **datap)
105 {
106         struct file *fp;
107         struct cdev_privdata *p;
108         int error;
109
110         fp = curthread->td_fpop;
111         if (fp == NULL)
112                 return (EBADF);
113         p = fp->f_cdevpriv;
114         if (p != NULL) {
115                 error = 0;
116                 *datap = p->cdpd_data;
117         } else
118                 error = ENOENT;
119         return (error);
120 }
121
122 int
123 devfs_set_cdevpriv(void *priv, cdevpriv_dtr_t priv_dtr)
124 {
125         struct file *fp;
126         struct cdev_priv *cdp;
127         struct cdev_privdata *p;
128         int error;
129
130         fp = curthread->td_fpop;
131         if (fp == NULL)
132                 return (ENOENT);
133         cdp = cdev2priv((struct cdev *)fp->f_data);
134         p = malloc(sizeof(struct cdev_privdata), M_CDEVPDATA, M_WAITOK);
135         p->cdpd_data = priv;
136         p->cdpd_dtr = priv_dtr;
137         p->cdpd_fp = fp;
138         mtx_lock(&cdevpriv_mtx);
139         if (fp->f_cdevpriv == NULL) {
140                 LIST_INSERT_HEAD(&cdp->cdp_fdpriv, p, cdpd_list);
141                 fp->f_cdevpriv = p;
142                 mtx_unlock(&cdevpriv_mtx);
143                 error = 0;
144         } else {
145                 mtx_unlock(&cdevpriv_mtx);
146                 free(p, M_CDEVPDATA);
147                 error = EBUSY;
148         }
149         return (error);
150 }
151
152 void
153 devfs_destroy_cdevpriv(struct cdev_privdata *p)
154 {
155
156         mtx_assert(&cdevpriv_mtx, MA_OWNED);
157         p->cdpd_fp->f_cdevpriv = NULL;
158         LIST_REMOVE(p, cdpd_list);
159         mtx_unlock(&cdevpriv_mtx);
160         (p->cdpd_dtr)(p->cdpd_data);
161         free(p, M_CDEVPDATA);
162 }
163
164 void
165 devfs_fpdrop(struct file *fp)
166 {
167         struct cdev_privdata *p;
168
169         mtx_lock(&cdevpriv_mtx);
170         if ((p = fp->f_cdevpriv) == NULL) {
171                 mtx_unlock(&cdevpriv_mtx);
172                 return;
173         }
174         devfs_destroy_cdevpriv(p);
175 }
176
177 void
178 devfs_clear_cdevpriv(void)
179 {
180         struct file *fp;
181
182         fp = curthread->td_fpop;
183         if (fp == NULL)
184                 return;
185         devfs_fpdrop(fp);
186 }
187
188 static int
189 devfs_vptocnp(struct vop_vptocnp_args *ap)
190 {
191         struct vnode *vp = ap->a_vp;
192         struct vnode **dvp = ap->a_vpp;
193         struct devfs_mount *dmp;
194         char *buf = ap->a_buf;
195         int *buflen = ap->a_buflen;
196         struct devfs_dirent *dd, *de;
197         int i, error;
198
199         dmp = VFSTODEVFS(vp->v_mount);
200         i = *buflen;
201         dd = vp->v_data;
202         error = 0;
203
204         sx_xlock(&dmp->dm_lock);
205
206         if (vp->v_type == VCHR) {
207                 i -= strlen(dd->de_cdp->cdp_c.si_name);
208                 if (i < 0) {
209                         error = ENOMEM;
210                         goto finished;
211                 }
212                 bcopy(dd->de_cdp->cdp_c.si_name, buf + i,
213                     strlen(dd->de_cdp->cdp_c.si_name));
214                 de = dd->de_dir;
215         } else if (vp->v_type == VDIR) {
216                 if (dd == dmp->dm_rootdir) {
217                         *dvp = vp;
218                         vhold(*dvp);
219                         goto finished;
220                 }
221                 i -= dd->de_dirent->d_namlen;
222                 if (i < 0) {
223                         error = ENOMEM;
224                         goto finished;
225                 }
226                 bcopy(dd->de_dirent->d_name, buf + i,
227                     dd->de_dirent->d_namlen);
228                 de = dd;
229         } else {
230                 error = ENOENT;
231                 goto finished;
232         }
233         *buflen = i;
234         de = devfs_parent_dirent(de);
235         if (de == NULL) {
236                 error = ENOENT;
237                 goto finished;
238         }
239         mtx_lock(&devfs_de_interlock);
240         *dvp = de->de_vnode;
241         if (*dvp != NULL) {
242                 VI_LOCK(*dvp);
243                 mtx_unlock(&devfs_de_interlock);
244                 vholdl(*dvp);
245                 VI_UNLOCK(*dvp);
246         } else {
247                 mtx_unlock(&devfs_de_interlock);
248                 error = ENOENT;
249         }
250 finished:
251         sx_xunlock(&dmp->dm_lock);
252         return (error);
253 }
254
255 /*
256  * Construct the fully qualified path name relative to the mountpoint
257  */
258 static char *
259 devfs_fqpn(char *buf, struct vnode *dvp, struct componentname *cnp)
260 {
261         int i;
262         struct devfs_dirent *de, *dd;
263         struct devfs_mount *dmp;
264
265         dmp = VFSTODEVFS(dvp->v_mount);
266         dd = dvp->v_data;
267         i = SPECNAMELEN;
268         buf[i] = '\0';
269         i -= cnp->cn_namelen;
270         if (i < 0)
271                  return (NULL);
272         bcopy(cnp->cn_nameptr, buf + i, cnp->cn_namelen);
273         de = dd;
274         while (de != dmp->dm_rootdir) {
275                 i--;
276                 if (i < 0)
277                          return (NULL);
278                 buf[i] = '/';
279                 i -= de->de_dirent->d_namlen;
280                 if (i < 0)
281                          return (NULL);
282                 bcopy(de->de_dirent->d_name, buf + i,
283                     de->de_dirent->d_namlen);
284                 de = devfs_parent_dirent(de);
285                 if (de == NULL)
286                         return (NULL);
287         }
288         return (buf + i);
289 }
290
291 static int
292 devfs_allocv_drop_refs(int drop_dm_lock, struct devfs_mount *dmp,
293         struct devfs_dirent *de)
294 {
295         int not_found;
296
297         not_found = 0;
298         if (de->de_flags & DE_DOOMED)
299                 not_found = 1;
300         if (DEVFS_DE_DROP(de)) {
301                 KASSERT(not_found == 1, ("DEVFS de dropped but not doomed"));
302                 devfs_dirent_free(de);
303         }
304         if (DEVFS_DMP_DROP(dmp)) {
305                 KASSERT(not_found == 1,
306                         ("DEVFS mount struct freed before dirent"));
307                 not_found = 2;
308                 sx_xunlock(&dmp->dm_lock);
309                 devfs_unmount_final(dmp);
310         }
311         if (not_found == 1 || (drop_dm_lock && not_found != 2))
312                 sx_unlock(&dmp->dm_lock);
313         return (not_found);
314 }
315
316 static void
317 devfs_insmntque_dtr(struct vnode *vp, void *arg)
318 {
319         struct devfs_dirent *de;
320
321         de = (struct devfs_dirent *)arg;
322         mtx_lock(&devfs_de_interlock);
323         vp->v_data = NULL;
324         de->de_vnode = NULL;
325         mtx_unlock(&devfs_de_interlock);
326         vgone(vp);
327         vput(vp);
328 }
329
330 /*
331  * devfs_allocv shall be entered with dmp->dm_lock held, and it drops
332  * it on return.
333  */
334 int
335 devfs_allocv(struct devfs_dirent *de, struct mount *mp, int lockmode,
336     struct vnode **vpp)
337 {
338         int error;
339         struct vnode *vp;
340         struct cdev *dev;
341         struct devfs_mount *dmp;
342         struct cdevsw *dsw;
343
344         dmp = VFSTODEVFS(mp);
345         if (de->de_flags & DE_DOOMED) {
346                 sx_xunlock(&dmp->dm_lock);
347                 return (ENOENT);
348         }
349         DEVFS_DE_HOLD(de);
350         DEVFS_DMP_HOLD(dmp);
351         mtx_lock(&devfs_de_interlock);
352         vp = de->de_vnode;
353         if (vp != NULL) {
354                 VI_LOCK(vp);
355                 mtx_unlock(&devfs_de_interlock);
356                 sx_xunlock(&dmp->dm_lock);
357                 error = vget(vp, lockmode | LK_INTERLOCK, curthread);
358                 sx_xlock(&dmp->dm_lock);
359                 if (devfs_allocv_drop_refs(0, dmp, de)) {
360                         if (error == 0)
361                                 vput(vp);
362                         return (ENOENT);
363                 }
364                 else if (error) {
365                         sx_xunlock(&dmp->dm_lock);
366                         return (error);
367                 }
368                 sx_xunlock(&dmp->dm_lock);
369                 *vpp = vp;
370                 return (0);
371         }
372         mtx_unlock(&devfs_de_interlock);
373         if (de->de_dirent->d_type == DT_CHR) {
374                 if (!(de->de_cdp->cdp_flags & CDP_ACTIVE)) {
375                         devfs_allocv_drop_refs(1, dmp, de);
376                         return (ENOENT);
377                 }
378                 dev = &de->de_cdp->cdp_c;
379         } else {
380                 dev = NULL;
381         }
382         error = getnewvnode("devfs", mp, &devfs_vnodeops, &vp);
383         if (error != 0) {
384                 devfs_allocv_drop_refs(1, dmp, de);
385                 printf("devfs_allocv: failed to allocate new vnode\n");
386                 return (error);
387         }
388
389         if (de->de_dirent->d_type == DT_CHR) {
390                 vp->v_type = VCHR;
391                 VI_LOCK(vp);
392                 dev_lock();
393                 dev_refl(dev);
394                 /* XXX: v_rdev should be protect by vnode lock */
395                 vp->v_rdev = dev;
396                 KASSERT(vp->v_usecount == 1,
397                     ("%s %d (%d)\n", __func__, __LINE__, vp->v_usecount));
398                 dev->si_usecount += vp->v_usecount;
399                 /* Special casing of ttys for deadfs.  Probably redundant. */
400                 dsw = dev->si_devsw;
401                 if (dsw != NULL && (dsw->d_flags & D_TTY) != 0)
402                         vp->v_vflag |= VV_ISTTY;
403                 dev_unlock();
404                 VI_UNLOCK(vp);
405                 if ((dev->si_flags & SI_ETERNAL) != 0)
406                         vp->v_vflag |= VV_ETERNALDEV;
407                 vp->v_op = &devfs_specops;
408         } else if (de->de_dirent->d_type == DT_DIR) {
409                 vp->v_type = VDIR;
410         } else if (de->de_dirent->d_type == DT_LNK) {
411                 vp->v_type = VLNK;
412         } else {
413                 vp->v_type = VBAD;
414         }
415         VN_LOCK_ASHARE(vp);
416         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_NOWITNESS);
417         mtx_lock(&devfs_de_interlock);
418         vp->v_data = de;
419         de->de_vnode = vp;
420         mtx_unlock(&devfs_de_interlock);
421         error = insmntque1(vp, mp, devfs_insmntque_dtr, de);
422         if (error != 0) {
423                 (void) devfs_allocv_drop_refs(1, dmp, de);
424                 return (error);
425         }
426         if (devfs_allocv_drop_refs(0, dmp, de)) {
427                 vput(vp);
428                 return (ENOENT);
429         }
430 #ifdef MAC
431         mac_devfs_vnode_associate(mp, de, vp);
432 #endif
433         sx_xunlock(&dmp->dm_lock);
434         *vpp = vp;
435         return (0);
436 }
437
438 static int
439 devfs_access(struct vop_access_args *ap)
440 {
441         struct vnode *vp = ap->a_vp;
442         struct devfs_dirent *de;
443         int error;
444
445         de = vp->v_data;
446         if (vp->v_type == VDIR)
447                 de = de->de_dir;
448
449         error = vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid,
450             ap->a_accmode, ap->a_cred, NULL);
451         if (!error)
452                 return (error);
453         if (error != EACCES)
454                 return (error);
455         /* We do, however, allow access to the controlling terminal */
456         if (!(ap->a_td->td_proc->p_flag & P_CONTROLT))
457                 return (error);
458         if (ap->a_td->td_proc->p_session->s_ttyvp == de->de_vnode)
459                 return (0);
460         return (error);
461 }
462
463 /* ARGSUSED */
464 static int
465 devfs_close(struct vop_close_args *ap)
466 {
467         struct vnode *vp = ap->a_vp, *oldvp;
468         struct thread *td = ap->a_td;
469         struct cdev *dev = vp->v_rdev;
470         struct cdevsw *dsw;
471         int vp_locked, error, ref;
472
473         /*
474          * XXX: Don't call d_close() if we were called because of
475          * XXX: insmntque1() failure.
476          */
477         if (vp->v_data == NULL)
478                 return (0);
479
480         /*
481          * Hack: a tty device that is a controlling terminal
482          * has a reference from the session structure.
483          * We cannot easily tell that a character device is
484          * a controlling terminal, unless it is the closing
485          * process' controlling terminal.  In that case,
486          * if the reference count is 2 (this last descriptor
487          * plus the session), release the reference from the session.
488          */
489         oldvp = NULL;
490         sx_xlock(&proctree_lock);
491         if (td && vp == td->td_proc->p_session->s_ttyvp) {
492                 SESS_LOCK(td->td_proc->p_session);
493                 VI_LOCK(vp);
494                 if (count_dev(dev) == 2 && (vp->v_iflag & VI_DOOMED) == 0) {
495                         td->td_proc->p_session->s_ttyvp = NULL;
496                         oldvp = vp;
497                 }
498                 VI_UNLOCK(vp);
499                 SESS_UNLOCK(td->td_proc->p_session);
500         }
501         sx_xunlock(&proctree_lock);
502         if (oldvp != NULL)
503                 vrele(oldvp);
504         /*
505          * We do not want to really close the device if it
506          * is still in use unless we are trying to close it
507          * forcibly. Since every use (buffer, vnode, swap, cmap)
508          * holds a reference to the vnode, and because we mark
509          * any other vnodes that alias this device, when the
510          * sum of the reference counts on all the aliased
511          * vnodes descends to one, we are on last close.
512          */
513         dsw = dev_refthread(dev, &ref);
514         if (dsw == NULL)
515                 return (ENXIO);
516         VI_LOCK(vp);
517         if (vp->v_iflag & VI_DOOMED) {
518                 /* Forced close. */
519         } else if (dsw->d_flags & D_TRACKCLOSE) {
520                 /* Keep device updated on status. */
521         } else if (count_dev(dev) > 1) {
522                 VI_UNLOCK(vp);
523                 dev_relthread(dev, ref);
524                 return (0);
525         }
526         vholdl(vp);
527         VI_UNLOCK(vp);
528         vp_locked = VOP_ISLOCKED(vp);
529         VOP_UNLOCK(vp, 0);
530         KASSERT(dev->si_refcount > 0,
531             ("devfs_close() on un-referenced struct cdev *(%s)", devtoname(dev)));
532         error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
533         dev_relthread(dev, ref);
534         vn_lock(vp, vp_locked | LK_RETRY);
535         vdrop(vp);
536         return (error);
537 }
538
539 static int
540 devfs_close_f(struct file *fp, struct thread *td)
541 {
542         int error;
543         struct file *fpop;
544
545         fpop = td->td_fpop;
546         td->td_fpop = fp;
547         error = vnops.fo_close(fp, td);
548         td->td_fpop = fpop;
549         return (error);
550 }
551
552 static int
553 devfs_fsync(struct vop_fsync_args *ap)
554 {
555         int error;
556         struct bufobj *bo;
557         struct devfs_dirent *de;
558
559         if (!vn_isdisk(ap->a_vp, &error)) {
560                 bo = &ap->a_vp->v_bufobj;
561                 de = ap->a_vp->v_data;
562                 if (error == ENXIO && bo->bo_dirty.bv_cnt > 0) {
563                         printf("Device %s went missing before all of the data "
564                             "could be written to it; expect data loss.\n",
565                             de->de_dirent->d_name);
566
567                         error = vop_stdfsync(ap);
568                         if (bo->bo_dirty.bv_cnt != 0 || error != 0)
569                                 panic("devfs_fsync: vop_stdfsync failed.");
570                 }
571
572                 return (0);
573         }
574
575         return (vop_stdfsync(ap));
576 }
577
578 static int
579 devfs_getattr(struct vop_getattr_args *ap)
580 {
581         struct vnode *vp = ap->a_vp;
582         struct vattr *vap = ap->a_vap;
583         int error = 0;
584         struct devfs_dirent *de;
585         struct cdev *dev;
586
587         de = vp->v_data;
588         KASSERT(de != NULL, ("Null dirent in devfs_getattr vp=%p", vp));
589         if (vp->v_type == VDIR) {
590                 de = de->de_dir;
591                 KASSERT(de != NULL,
592                     ("Null dir dirent in devfs_getattr vp=%p", vp));
593         }
594         vap->va_uid = de->de_uid;
595         vap->va_gid = de->de_gid;
596         vap->va_mode = de->de_mode;
597         if (vp->v_type == VLNK)
598                 vap->va_size = strlen(de->de_symlink);
599         else if (vp->v_type == VDIR)
600                 vap->va_size = vap->va_bytes = DEV_BSIZE;
601         else
602                 vap->va_size = 0;
603         if (vp->v_type != VDIR)
604                 vap->va_bytes = 0;
605         vap->va_blocksize = DEV_BSIZE;
606         vap->va_type = vp->v_type;
607
608 #define fix(aa)                                                 \
609         do {                                                    \
610                 if ((aa).tv_sec <= 3600) {                      \
611                         (aa).tv_sec = boottime.tv_sec;          \
612                         (aa).tv_nsec = boottime.tv_usec * 1000; \
613                 }                                               \
614         } while (0)
615
616         if (vp->v_type != VCHR)  {
617                 fix(de->de_atime);
618                 vap->va_atime = de->de_atime;
619                 fix(de->de_mtime);
620                 vap->va_mtime = de->de_mtime;
621                 fix(de->de_ctime);
622                 vap->va_ctime = de->de_ctime;
623         } else {
624                 dev = vp->v_rdev;
625                 fix(dev->si_atime);
626                 vap->va_atime = dev->si_atime;
627                 fix(dev->si_mtime);
628                 vap->va_mtime = dev->si_mtime;
629                 fix(dev->si_ctime);
630                 vap->va_ctime = dev->si_ctime;
631
632                 vap->va_rdev = cdev2priv(dev)->cdp_inode;
633         }
634         vap->va_gen = 0;
635         vap->va_flags = 0;
636         vap->va_filerev = 0;
637         vap->va_nlink = de->de_links;
638         vap->va_fileid = de->de_inode;
639
640         return (error);
641 }
642
643 /* ARGSUSED */
644 static int
645 devfs_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred, struct thread *td)
646 {
647         struct cdev *dev;
648         struct cdevsw *dsw;
649         struct vnode *vp;
650         struct vnode *vpold;
651         int error, i, ref;
652         const char *p;
653         struct fiodgname_arg *fgn;
654         struct file *fpop;
655
656         fpop = td->td_fpop;
657         error = devfs_fp_check(fp, &dev, &dsw, &ref);
658         if (error)
659                 return (error);
660
661         if (com == FIODTYPE) {
662                 *(int *)data = dsw->d_flags & D_TYPEMASK;
663                 td->td_fpop = fpop;
664                 dev_relthread(dev, ref);
665                 return (0);
666         } else if (com == FIODGNAME) {
667                 fgn = data;
668                 p = devtoname(dev);
669                 i = strlen(p) + 1;
670                 if (i > fgn->len)
671                         error = EINVAL;
672                 else
673                         error = copyout(p, fgn->buf, i);
674                 td->td_fpop = fpop;
675                 dev_relthread(dev, ref);
676                 return (error);
677         }
678         error = dsw->d_ioctl(dev, com, data, fp->f_flag, td);
679         td->td_fpop = NULL;
680         dev_relthread(dev, ref);
681         if (error == ENOIOCTL)
682                 error = ENOTTY;
683         if (error == 0 && com == TIOCSCTTY) {
684                 vp = fp->f_vnode;
685
686                 /* Do nothing if reassigning same control tty */
687                 sx_slock(&proctree_lock);
688                 if (td->td_proc->p_session->s_ttyvp == vp) {
689                         sx_sunlock(&proctree_lock);
690                         return (0);
691                 }
692
693                 vpold = td->td_proc->p_session->s_ttyvp;
694                 VREF(vp);
695                 SESS_LOCK(td->td_proc->p_session);
696                 td->td_proc->p_session->s_ttyvp = vp;
697                 SESS_UNLOCK(td->td_proc->p_session);
698
699                 sx_sunlock(&proctree_lock);
700
701                 /* Get rid of reference to old control tty */
702                 if (vpold)
703                         vrele(vpold);
704         }
705         return (error);
706 }
707
708 /* ARGSUSED */
709 static int
710 devfs_kqfilter_f(struct file *fp, struct knote *kn)
711 {
712         struct cdev *dev;
713         struct cdevsw *dsw;
714         int error, ref;
715         struct file *fpop;
716         struct thread *td;
717
718         td = curthread;
719         fpop = td->td_fpop;
720         error = devfs_fp_check(fp, &dev, &dsw, &ref);
721         if (error)
722                 return (error);
723         error = dsw->d_kqfilter(dev, kn);
724         td->td_fpop = fpop;
725         dev_relthread(dev, ref);
726         return (error);
727 }
728
729 static inline int
730 devfs_prison_check(struct devfs_dirent *de, struct ucred *tcr)
731 {
732         struct cdev_priv *cdp;
733         struct ucred *dcr;
734
735         cdp = de->de_cdp;
736         if (cdp == NULL)
737                 return (0);
738         dcr = cdp->cdp_c.si_cred;
739         if (dcr == NULL)
740                 return (0);
741
742         return (prison_check(tcr, dcr));
743 }
744
745 static int
746 devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)
747 {
748         struct componentname *cnp;
749         struct vnode *dvp, **vpp;
750         struct thread *td;
751         struct devfs_dirent *de, *dd;
752         struct devfs_dirent **dde;
753         struct devfs_mount *dmp;
754         struct cdev *cdev;
755         int error, flags, nameiop, dvplocked;
756         char specname[SPECNAMELEN + 1], *pname;
757
758         cnp = ap->a_cnp;
759         vpp = ap->a_vpp;
760         dvp = ap->a_dvp;
761         pname = cnp->cn_nameptr;
762         td = cnp->cn_thread;
763         flags = cnp->cn_flags;
764         nameiop = cnp->cn_nameiop;
765         dmp = VFSTODEVFS(dvp->v_mount);
766         dd = dvp->v_data;
767         *vpp = NULLVP;
768
769         if ((flags & ISLASTCN) && nameiop == RENAME)
770                 return (EOPNOTSUPP);
771
772         if (dvp->v_type != VDIR)
773                 return (ENOTDIR);
774
775         if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT))
776                 return (EIO);
777
778         error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td);
779         if (error)
780                 return (error);
781
782         if (cnp->cn_namelen == 1 && *pname == '.') {
783                 if ((flags & ISLASTCN) && nameiop != LOOKUP)
784                         return (EINVAL);
785                 *vpp = dvp;
786                 VREF(dvp);
787                 return (0);
788         }
789
790         if (flags & ISDOTDOT) {
791                 if ((flags & ISLASTCN) && nameiop != LOOKUP)
792                         return (EINVAL);
793                 de = devfs_parent_dirent(dd);
794                 if (de == NULL)
795                         return (ENOENT);
796                 dvplocked = VOP_ISLOCKED(dvp);
797                 VOP_UNLOCK(dvp, 0);
798                 error = devfs_allocv(de, dvp->v_mount,
799                     cnp->cn_lkflags & LK_TYPE_MASK, vpp);
800                 *dm_unlock = 0;
801                 vn_lock(dvp, dvplocked | LK_RETRY);
802                 return (error);
803         }
804
805         DEVFS_DMP_HOLD(dmp);
806         devfs_populate(dmp);
807         if (DEVFS_DMP_DROP(dmp)) {
808                 *dm_unlock = 0;
809                 sx_xunlock(&dmp->dm_lock);
810                 devfs_unmount_final(dmp);
811                 return (ENOENT);
812         }
813         dd = dvp->v_data;
814         de = devfs_find(dd, cnp->cn_nameptr, cnp->cn_namelen);
815         while (de == NULL) {    /* While(...) so we can use break */
816
817                 if (nameiop == DELETE)
818                         return (ENOENT);
819
820                 /*
821                  * OK, we didn't have an entry for the name we were asked for
822                  * so we try to see if anybody can create it on demand.
823                  */
824                 pname = devfs_fqpn(specname, dvp, cnp);
825                 if (pname == NULL)
826                         break;
827
828                 cdev = NULL;
829                 DEVFS_DMP_HOLD(dmp);
830                 sx_xunlock(&dmp->dm_lock);
831                 sx_slock(&clone_drain_lock);
832                 EVENTHANDLER_INVOKE(dev_clone,
833                     td->td_ucred, pname, strlen(pname), &cdev);
834                 sx_sunlock(&clone_drain_lock);
835                 sx_xlock(&dmp->dm_lock);
836                 if (DEVFS_DMP_DROP(dmp)) {
837                         *dm_unlock = 0;
838                         sx_xunlock(&dmp->dm_lock);
839                         devfs_unmount_final(dmp);
840                         if (cdev != NULL)
841                                 dev_rel(cdev);
842                         return (ENOENT);
843                 }
844                 if (cdev == NULL)
845                         break;
846
847                 DEVFS_DMP_HOLD(dmp);
848                 devfs_populate(dmp);
849                 if (DEVFS_DMP_DROP(dmp)) {
850                         *dm_unlock = 0;
851                         sx_xunlock(&dmp->dm_lock);
852                         devfs_unmount_final(dmp);
853                         dev_rel(cdev);
854                         return (ENOENT);
855                 }
856
857                 dev_lock();
858                 dde = &cdev2priv(cdev)->cdp_dirents[dmp->dm_idx];
859                 if (dde != NULL && *dde != NULL)
860                         de = *dde;
861                 dev_unlock();
862                 dev_rel(cdev);
863                 break;
864         }
865
866         if (de == NULL || de->de_flags & DE_WHITEOUT) {
867                 if ((nameiop == CREATE || nameiop == RENAME) &&
868                     (flags & (LOCKPARENT | WANTPARENT)) && (flags & ISLASTCN)) {
869                         cnp->cn_flags |= SAVENAME;
870                         return (EJUSTRETURN);
871                 }
872                 return (ENOENT);
873         }
874
875         if (devfs_prison_check(de, td->td_ucred))
876                 return (ENOENT);
877
878         if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) {
879                 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
880                 if (error)
881                         return (error);
882                 if (*vpp == dvp) {
883                         VREF(dvp);
884                         *vpp = dvp;
885                         return (0);
886                 }
887         }
888         error = devfs_allocv(de, dvp->v_mount, cnp->cn_lkflags & LK_TYPE_MASK,
889             vpp);
890         *dm_unlock = 0;
891         return (error);
892 }
893
894 static int
895 devfs_lookup(struct vop_lookup_args *ap)
896 {
897         int j;
898         struct devfs_mount *dmp;
899         int dm_unlock;
900
901         dmp = VFSTODEVFS(ap->a_dvp->v_mount);
902         dm_unlock = 1;
903         sx_xlock(&dmp->dm_lock);
904         j = devfs_lookupx(ap, &dm_unlock);
905         if (dm_unlock == 1)
906                 sx_xunlock(&dmp->dm_lock);
907         return (j);
908 }
909
910 static int
911 devfs_mknod(struct vop_mknod_args *ap)
912 {
913         struct componentname *cnp;
914         struct vnode *dvp, **vpp;
915         struct devfs_dirent *dd, *de;
916         struct devfs_mount *dmp;
917         int error;
918
919         /*
920          * The only type of node we should be creating here is a
921          * character device, for anything else return EOPNOTSUPP.
922          */
923         if (ap->a_vap->va_type != VCHR)
924                 return (EOPNOTSUPP);
925         dvp = ap->a_dvp;
926         dmp = VFSTODEVFS(dvp->v_mount);
927
928         cnp = ap->a_cnp;
929         vpp = ap->a_vpp;
930         dd = dvp->v_data;
931
932         error = ENOENT;
933         sx_xlock(&dmp->dm_lock);
934         TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
935                 if (cnp->cn_namelen != de->de_dirent->d_namlen)
936                         continue;
937                 if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name,
938                     de->de_dirent->d_namlen) != 0)
939                         continue;
940                 if (de->de_flags & DE_WHITEOUT)
941                         break;
942                 goto notfound;
943         }
944         if (de == NULL)
945                 goto notfound;
946         de->de_flags &= ~DE_WHITEOUT;
947         error = devfs_allocv(de, dvp->v_mount, LK_EXCLUSIVE, vpp);
948         return (error);
949 notfound:
950         sx_xunlock(&dmp->dm_lock);
951         return (error);
952 }
953
954 /* ARGSUSED */
955 static int
956 devfs_open(struct vop_open_args *ap)
957 {
958         struct thread *td = ap->a_td;
959         struct vnode *vp = ap->a_vp;
960         struct cdev *dev = vp->v_rdev;
961         struct file *fp = ap->a_fp;
962         int error, ref, vlocked;
963         struct cdevsw *dsw;
964         struct file *fpop;
965
966         if (vp->v_type == VBLK)
967                 return (ENXIO);
968
969         if (dev == NULL)
970                 return (ENXIO);
971
972         /* Make this field valid before any I/O in d_open. */
973         if (dev->si_iosize_max == 0)
974                 dev->si_iosize_max = DFLTPHYS;
975
976         dsw = dev_refthread(dev, &ref);
977         if (dsw == NULL)
978                 return (ENXIO);
979
980         vlocked = VOP_ISLOCKED(vp);
981         VOP_UNLOCK(vp, 0);
982
983         fpop = td->td_fpop;
984         td->td_fpop = fp;
985         if (fp != NULL) {
986                 fp->f_data = dev;
987                 fp->f_vnode = vp;
988         }
989         if (dsw->d_fdopen != NULL)
990                 error = dsw->d_fdopen(dev, ap->a_mode, td, fp);
991         else
992                 error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
993         td->td_fpop = fpop;
994
995         vn_lock(vp, vlocked | LK_RETRY);
996         dev_relthread(dev, ref);
997         if (error)
998                 return (error);
999
1000 #if 0   /* /dev/console */
1001         KASSERT(fp != NULL, ("Could not vnode bypass device on NULL fp"));
1002 #else
1003         if (fp == NULL)
1004                 return (error);
1005 #endif
1006         if (fp->f_ops == &badfileops)
1007                 finit(fp, fp->f_flag, DTYPE_VNODE, dev, &devfs_ops_f);
1008         return (error);
1009 }
1010
1011 static int
1012 devfs_pathconf(struct vop_pathconf_args *ap)
1013 {
1014
1015         switch (ap->a_name) {
1016         case _PC_MAC_PRESENT:
1017 #ifdef MAC
1018                 /*
1019                  * If MAC is enabled, devfs automatically supports
1020                  * trivial non-persistant label storage.
1021                  */
1022                 *ap->a_retval = 1;
1023 #else
1024                 *ap->a_retval = 0;
1025 #endif
1026                 return (0);
1027         default:
1028                 return (vop_stdpathconf(ap));
1029         }
1030         /* NOTREACHED */
1031 }
1032
1033 /* ARGSUSED */
1034 static int
1035 devfs_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td)
1036 {
1037         struct cdev *dev;
1038         struct cdevsw *dsw;
1039         int error, ref;
1040         struct file *fpop;
1041
1042         fpop = td->td_fpop;
1043         error = devfs_fp_check(fp, &dev, &dsw, &ref);
1044         if (error)
1045                 return (poll_no_poll(events));
1046         error = dsw->d_poll(dev, events, td);
1047         td->td_fpop = fpop;
1048         dev_relthread(dev, ref);
1049         return(error);
1050 }
1051
1052 /*
1053  * Print out the contents of a special device vnode.
1054  */
1055 static int
1056 devfs_print(struct vop_print_args *ap)
1057 {
1058
1059         printf("\tdev %s\n", devtoname(ap->a_vp->v_rdev));
1060         return (0);
1061 }
1062
1063 /* ARGSUSED */
1064 static int
1065 devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
1066 {
1067         struct cdev *dev;
1068         int ioflag, error, ref, resid;
1069         struct cdevsw *dsw;
1070         struct file *fpop;
1071
1072         fpop = td->td_fpop;
1073         error = devfs_fp_check(fp, &dev, &dsw, &ref);
1074         if (error)
1075                 return (error);
1076         resid = uio->uio_resid;
1077         ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT);
1078         if (ioflag & O_DIRECT)
1079                 ioflag |= IO_DIRECT;
1080
1081         if ((flags & FOF_OFFSET) == 0)
1082                 uio->uio_offset = fp->f_offset;
1083
1084         error = dsw->d_read(dev, uio, ioflag);
1085         if (uio->uio_resid != resid || (error == 0 && resid != 0))
1086                 vfs_timestamp(&dev->si_atime);
1087         td->td_fpop = fpop;
1088         dev_relthread(dev, ref);
1089
1090         if ((flags & FOF_OFFSET) == 0)
1091                 fp->f_offset = uio->uio_offset;
1092         fp->f_nextoff = uio->uio_offset;
1093         return (error);
1094 }
1095
1096 static int
1097 devfs_readdir(struct vop_readdir_args *ap)
1098 {
1099         int error;
1100         struct uio *uio;
1101         struct dirent *dp;
1102         struct devfs_dirent *dd;
1103         struct devfs_dirent *de;
1104         struct devfs_mount *dmp;
1105         off_t off;
1106         int *tmp_ncookies = NULL;
1107
1108         if (ap->a_vp->v_type != VDIR)
1109                 return (ENOTDIR);
1110
1111         uio = ap->a_uio;
1112         if (uio->uio_offset < 0)
1113                 return (EINVAL);
1114
1115         /*
1116          * XXX: This is a temporary hack to get around this filesystem not
1117          * supporting cookies. We store the location of the ncookies pointer
1118          * in a temporary variable before calling vfs_subr.c:vfs_read_dirent()
1119          * and set the number of cookies to 0. We then set the pointer to
1120          * NULL so that vfs_read_dirent doesn't try to call realloc() on 
1121          * ap->a_cookies. Later in this function, we restore the ap->a_ncookies
1122          * pointer to its original location before returning to the caller.
1123          */
1124         if (ap->a_ncookies != NULL) {
1125                 tmp_ncookies = ap->a_ncookies;
1126                 *ap->a_ncookies = 0;
1127                 ap->a_ncookies = NULL;
1128         }
1129
1130         dmp = VFSTODEVFS(ap->a_vp->v_mount);
1131         sx_xlock(&dmp->dm_lock);
1132         DEVFS_DMP_HOLD(dmp);
1133         devfs_populate(dmp);
1134         if (DEVFS_DMP_DROP(dmp)) {
1135                 sx_xunlock(&dmp->dm_lock);
1136                 devfs_unmount_final(dmp);
1137                 if (tmp_ncookies != NULL)
1138                         ap->a_ncookies = tmp_ncookies;
1139                 return (EIO);
1140         }
1141         error = 0;
1142         de = ap->a_vp->v_data;
1143         off = 0;
1144         TAILQ_FOREACH(dd, &de->de_dlist, de_list) {
1145                 KASSERT(dd->de_cdp != (void *)0xdeadc0de, ("%s %d\n", __func__, __LINE__));
1146                 if (dd->de_flags & DE_WHITEOUT)
1147                         continue;
1148                 if (devfs_prison_check(dd, ap->a_cred))
1149                         continue;
1150                 if (dd->de_dirent->d_type == DT_DIR)
1151                         de = dd->de_dir;
1152                 else
1153                         de = dd;
1154                 dp = dd->de_dirent;
1155                 if (dp->d_reclen > uio->uio_resid)
1156                         break;
1157                 dp->d_fileno = de->de_inode;
1158                 if (off >= uio->uio_offset) {
1159                         error = vfs_read_dirent(ap, dp, off);
1160                         if (error)
1161                                 break;
1162                 }
1163                 off += dp->d_reclen;
1164         }
1165         sx_xunlock(&dmp->dm_lock);
1166         uio->uio_offset = off;
1167
1168         /*
1169          * Restore ap->a_ncookies if it wasn't originally NULL in the first
1170          * place.
1171          */
1172         if (tmp_ncookies != NULL)
1173                 ap->a_ncookies = tmp_ncookies;
1174
1175         return (error);
1176 }
1177
1178 static int
1179 devfs_readlink(struct vop_readlink_args *ap)
1180 {
1181         struct devfs_dirent *de;
1182
1183         de = ap->a_vp->v_data;
1184         return (uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio));
1185 }
1186
1187 static int
1188 devfs_reclaim(struct vop_reclaim_args *ap)
1189 {
1190         struct vnode *vp = ap->a_vp;
1191         struct devfs_dirent *de;
1192         struct cdev *dev;
1193
1194         mtx_lock(&devfs_de_interlock);
1195         de = vp->v_data;
1196         if (de != NULL) {
1197                 de->de_vnode = NULL;
1198                 vp->v_data = NULL;
1199         }
1200         mtx_unlock(&devfs_de_interlock);
1201
1202         vnode_destroy_vobject(vp);
1203
1204         VI_LOCK(vp);
1205         dev_lock();
1206         dev = vp->v_rdev;
1207         vp->v_rdev = NULL;
1208
1209         if (dev == NULL) {
1210                 dev_unlock();
1211                 VI_UNLOCK(vp);
1212                 return (0);
1213         }
1214
1215         dev->si_usecount -= vp->v_usecount;
1216         dev_unlock();
1217         VI_UNLOCK(vp);
1218         dev_rel(dev);
1219         return (0);
1220 }
1221
1222 static int
1223 devfs_remove(struct vop_remove_args *ap)
1224 {
1225         struct vnode *vp = ap->a_vp;
1226         struct devfs_dirent *dd;
1227         struct devfs_dirent *de;
1228         struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount);
1229
1230         sx_xlock(&dmp->dm_lock);
1231         dd = ap->a_dvp->v_data;
1232         de = vp->v_data;
1233         if (de->de_cdp == NULL) {
1234                 TAILQ_REMOVE(&dd->de_dlist, de, de_list);
1235                 devfs_delete(dmp, de, 1);
1236         } else {
1237                 de->de_flags |= DE_WHITEOUT;
1238         }
1239         sx_xunlock(&dmp->dm_lock);
1240         return (0);
1241 }
1242
1243 /*
1244  * Revoke is called on a tty when a terminal session ends.  The vnode
1245  * is orphaned by setting v_op to deadfs so we need to let go of it
1246  * as well so that we create a new one next time around.
1247  *
1248  */
1249 static int
1250 devfs_revoke(struct vop_revoke_args *ap)
1251 {
1252         struct vnode *vp = ap->a_vp, *vp2;
1253         struct cdev *dev;
1254         struct cdev_priv *cdp;
1255         struct devfs_dirent *de;
1256         int i;
1257
1258         KASSERT((ap->a_flags & REVOKEALL) != 0, ("devfs_revoke !REVOKEALL"));
1259
1260         dev = vp->v_rdev;
1261         cdp = cdev2priv(dev);
1262  
1263         dev_lock();
1264         cdp->cdp_inuse++;
1265         dev_unlock();
1266
1267         vhold(vp);
1268         vgone(vp);
1269         vdrop(vp);
1270
1271         VOP_UNLOCK(vp,0);
1272  loop:
1273         for (;;) {
1274                 mtx_lock(&devfs_de_interlock);
1275                 dev_lock();
1276                 vp2 = NULL;
1277                 for (i = 0; i <= cdp->cdp_maxdirent; i++) {
1278                         de = cdp->cdp_dirents[i];
1279                         if (de == NULL)
1280                                 continue;
1281
1282                         vp2 = de->de_vnode;
1283                         if (vp2 != NULL) {
1284                                 dev_unlock();
1285                                 VI_LOCK(vp2);
1286                                 mtx_unlock(&devfs_de_interlock);
1287                                 if (vget(vp2, LK_EXCLUSIVE | LK_INTERLOCK,
1288                                     curthread))
1289                                         goto loop;
1290                                 vhold(vp2);
1291                                 vgone(vp2);
1292                                 vdrop(vp2);
1293                                 vput(vp2);
1294                                 break;
1295                         } 
1296                 }
1297                 if (vp2 != NULL) {
1298                         continue;
1299                 }
1300                 dev_unlock();
1301                 mtx_unlock(&devfs_de_interlock);
1302                 break;
1303         }
1304         dev_lock();
1305         cdp->cdp_inuse--;
1306         if (!(cdp->cdp_flags & CDP_ACTIVE) && cdp->cdp_inuse == 0) {
1307                 TAILQ_REMOVE(&cdevp_list, cdp, cdp_list);
1308                 dev_unlock();
1309                 dev_rel(&cdp->cdp_c);
1310         } else
1311                 dev_unlock();
1312
1313         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1314         return (0);
1315 }
1316
1317 static int
1318 devfs_rioctl(struct vop_ioctl_args *ap)
1319 {
1320         struct vnode *vp;
1321         struct devfs_mount *dmp;
1322         int error;
1323
1324         vp = ap->a_vp;
1325         vn_lock(vp, LK_SHARED | LK_RETRY);
1326         if (vp->v_iflag & VI_DOOMED) {
1327                 VOP_UNLOCK(vp, 0);
1328                 return (EBADF);
1329         }
1330         dmp = VFSTODEVFS(vp->v_mount);
1331         sx_xlock(&dmp->dm_lock);
1332         VOP_UNLOCK(vp, 0);
1333         DEVFS_DMP_HOLD(dmp);
1334         devfs_populate(dmp);
1335         if (DEVFS_DMP_DROP(dmp)) {
1336                 sx_xunlock(&dmp->dm_lock);
1337                 devfs_unmount_final(dmp);
1338                 return (ENOENT);
1339         }
1340         error = devfs_rules_ioctl(dmp, ap->a_command, ap->a_data, ap->a_td);
1341         sx_xunlock(&dmp->dm_lock);
1342         return (error);
1343 }
1344
1345 static int
1346 devfs_rread(struct vop_read_args *ap)
1347 {
1348
1349         if (ap->a_vp->v_type != VDIR)
1350                 return (EINVAL);
1351         return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL));
1352 }
1353
1354 static int
1355 devfs_setattr(struct vop_setattr_args *ap)
1356 {
1357         struct devfs_dirent *de;
1358         struct vattr *vap;
1359         struct vnode *vp;
1360         struct thread *td;
1361         int c, error;
1362         uid_t uid;
1363         gid_t gid;
1364
1365         vap = ap->a_vap;
1366         vp = ap->a_vp;
1367         td = curthread;
1368         if ((vap->va_type != VNON) ||
1369             (vap->va_nlink != VNOVAL) ||
1370             (vap->va_fsid != VNOVAL) ||
1371             (vap->va_fileid != VNOVAL) ||
1372             (vap->va_blocksize != VNOVAL) ||
1373             (vap->va_flags != VNOVAL && vap->va_flags != 0) ||
1374             (vap->va_rdev != VNOVAL) ||
1375             ((int)vap->va_bytes != VNOVAL) ||
1376             (vap->va_gen != VNOVAL)) {
1377                 return (EINVAL);
1378         }
1379
1380         de = vp->v_data;
1381         if (vp->v_type == VDIR)
1382                 de = de->de_dir;
1383
1384         error = c = 0;
1385         if (vap->va_uid == (uid_t)VNOVAL)
1386                 uid = de->de_uid;
1387         else
1388                 uid = vap->va_uid;
1389         if (vap->va_gid == (gid_t)VNOVAL)
1390                 gid = de->de_gid;
1391         else
1392                 gid = vap->va_gid;
1393         if (uid != de->de_uid || gid != de->de_gid) {
1394                 if ((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid ||
1395                     (gid != de->de_gid && !groupmember(gid, ap->a_cred))) {
1396                         error = priv_check(td, PRIV_VFS_CHOWN);
1397                         if (error)
1398                                 return (error);
1399                 }
1400                 de->de_uid = uid;
1401                 de->de_gid = gid;
1402                 c = 1;
1403         }
1404
1405         if (vap->va_mode != (mode_t)VNOVAL) {
1406                 if (ap->a_cred->cr_uid != de->de_uid) {
1407                         error = priv_check(td, PRIV_VFS_ADMIN);
1408                         if (error)
1409                                 return (error);
1410                 }
1411                 de->de_mode = vap->va_mode;
1412                 c = 1;
1413         }
1414
1415         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
1416                 /* See the comment in ufs_vnops::ufs_setattr(). */
1417                 if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, td)) &&
1418                     ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
1419                     (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, td))))
1420                         return (error);
1421                 if (vap->va_atime.tv_sec != VNOVAL) {
1422                         if (vp->v_type == VCHR)
1423                                 vp->v_rdev->si_atime = vap->va_atime;
1424                         else
1425                                 de->de_atime = vap->va_atime;
1426                 }
1427                 if (vap->va_mtime.tv_sec != VNOVAL) {
1428                         if (vp->v_type == VCHR)
1429                                 vp->v_rdev->si_mtime = vap->va_mtime;
1430                         else
1431                                 de->de_mtime = vap->va_mtime;
1432                 }
1433                 c = 1;
1434         }
1435
1436         if (c) {
1437                 if (vp->v_type == VCHR)
1438                         vfs_timestamp(&vp->v_rdev->si_ctime);
1439                 else
1440                         vfs_timestamp(&de->de_mtime);
1441         }
1442         return (0);
1443 }
1444
1445 #ifdef MAC
1446 static int
1447 devfs_setlabel(struct vop_setlabel_args *ap)
1448 {
1449         struct vnode *vp;
1450         struct devfs_dirent *de;
1451
1452         vp = ap->a_vp;
1453         de = vp->v_data;
1454
1455         mac_vnode_relabel(ap->a_cred, vp, ap->a_label);
1456         mac_devfs_update(vp->v_mount, de, vp);
1457
1458         return (0);
1459 }
1460 #endif
1461
1462 static int
1463 devfs_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td)
1464 {
1465
1466         return (vnops.fo_stat(fp, sb, cred, td));
1467 }
1468
1469 static int
1470 devfs_symlink(struct vop_symlink_args *ap)
1471 {
1472         int i, error;
1473         struct devfs_dirent *dd;
1474         struct devfs_dirent *de;
1475         struct devfs_mount *dmp;
1476
1477         error = priv_check(curthread, PRIV_DEVFS_SYMLINK);
1478         if (error)
1479                 return(error);
1480         dmp = VFSTODEVFS(ap->a_dvp->v_mount);
1481         dd = ap->a_dvp->v_data;
1482         de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen);
1483         de->de_uid = 0;
1484         de->de_gid = 0;
1485         de->de_mode = 0755;
1486         de->de_inode = alloc_unr(devfs_inos);
1487         de->de_dirent->d_type = DT_LNK;
1488         i = strlen(ap->a_target) + 1;
1489         de->de_symlink = malloc(i, M_DEVFS, M_WAITOK);
1490         bcopy(ap->a_target, de->de_symlink, i);
1491         sx_xlock(&dmp->dm_lock);
1492 #ifdef MAC
1493         mac_devfs_create_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de);
1494 #endif
1495         TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
1496         return (devfs_allocv(de, ap->a_dvp->v_mount, LK_EXCLUSIVE, ap->a_vpp));
1497 }
1498
1499 static int
1500 devfs_truncate_f(struct file *fp, off_t length, struct ucred *cred, struct thread *td)
1501 {
1502
1503         return (vnops.fo_truncate(fp, length, cred, td));
1504 }
1505
1506 /* ARGSUSED */
1507 static int
1508 devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
1509 {
1510         struct cdev *dev;
1511         int error, ioflag, ref, resid;
1512         struct cdevsw *dsw;
1513         struct file *fpop;
1514
1515         fpop = td->td_fpop;
1516         error = devfs_fp_check(fp, &dev, &dsw, &ref);
1517         if (error)
1518                 return (error);
1519         KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td));
1520         ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT | O_FSYNC);
1521         if (ioflag & O_DIRECT)
1522                 ioflag |= IO_DIRECT;
1523         if ((flags & FOF_OFFSET) == 0)
1524                 uio->uio_offset = fp->f_offset;
1525
1526         resid = uio->uio_resid;
1527
1528         error = dsw->d_write(dev, uio, ioflag);
1529         if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
1530                 vfs_timestamp(&dev->si_ctime);
1531                 dev->si_mtime = dev->si_ctime;
1532         }
1533         td->td_fpop = fpop;
1534         dev_relthread(dev, ref);
1535
1536         if ((flags & FOF_OFFSET) == 0)
1537                 fp->f_offset = uio->uio_offset;
1538         fp->f_nextoff = uio->uio_offset;
1539         return (error);
1540 }
1541
1542 dev_t
1543 dev2udev(struct cdev *x)
1544 {
1545         if (x == NULL)
1546                 return (NODEV);
1547         return (cdev2priv(x)->cdp_inode);
1548 }
1549
1550 static struct fileops devfs_ops_f = {
1551         .fo_read =      devfs_read_f,
1552         .fo_write =     devfs_write_f,
1553         .fo_truncate =  devfs_truncate_f,
1554         .fo_ioctl =     devfs_ioctl_f,
1555         .fo_poll =      devfs_poll_f,
1556         .fo_kqfilter =  devfs_kqfilter_f,
1557         .fo_stat =      devfs_stat_f,
1558         .fo_close =     devfs_close_f,
1559         .fo_flags =     DFLAG_PASSABLE | DFLAG_SEEKABLE
1560 };
1561
1562 static struct vop_vector devfs_vnodeops = {
1563         .vop_default =          &default_vnodeops,
1564
1565         .vop_access =           devfs_access,
1566         .vop_getattr =          devfs_getattr,
1567         .vop_ioctl =            devfs_rioctl,
1568         .vop_lookup =           devfs_lookup,
1569         .vop_mknod =            devfs_mknod,
1570         .vop_pathconf =         devfs_pathconf,
1571         .vop_read =             devfs_rread,
1572         .vop_readdir =          devfs_readdir,
1573         .vop_readlink =         devfs_readlink,
1574         .vop_reclaim =          devfs_reclaim,
1575         .vop_remove =           devfs_remove,
1576         .vop_revoke =           devfs_revoke,
1577         .vop_setattr =          devfs_setattr,
1578 #ifdef MAC
1579         .vop_setlabel =         devfs_setlabel,
1580 #endif
1581         .vop_symlink =          devfs_symlink,
1582         .vop_vptocnp =          devfs_vptocnp,
1583 };
1584
1585 static struct vop_vector devfs_specops = {
1586         .vop_default =          &default_vnodeops,
1587
1588         .vop_access =           devfs_access,
1589         .vop_bmap =             VOP_PANIC,
1590         .vop_close =            devfs_close,
1591         .vop_create =           VOP_PANIC,
1592         .vop_fsync =            devfs_fsync,
1593         .vop_getattr =          devfs_getattr,
1594         .vop_link =             VOP_PANIC,
1595         .vop_mkdir =            VOP_PANIC,
1596         .vop_mknod =            VOP_PANIC,
1597         .vop_open =             devfs_open,
1598         .vop_pathconf =         devfs_pathconf,
1599         .vop_print =            devfs_print,
1600         .vop_read =             VOP_PANIC,
1601         .vop_readdir =          VOP_PANIC,
1602         .vop_readlink =         VOP_PANIC,
1603         .vop_reallocblks =      VOP_PANIC,
1604         .vop_reclaim =          devfs_reclaim,
1605         .vop_remove =           devfs_remove,
1606         .vop_rename =           VOP_PANIC,
1607         .vop_revoke =           devfs_revoke,
1608         .vop_rmdir =            VOP_PANIC,
1609         .vop_setattr =          devfs_setattr,
1610 #ifdef MAC
1611         .vop_setlabel =         devfs_setlabel,
1612 #endif
1613         .vop_strategy =         VOP_PANIC,
1614         .vop_symlink =          VOP_PANIC,
1615         .vop_vptocnp =          devfs_vptocnp,
1616         .vop_write =            VOP_PANIC,
1617 };
1618
1619 /*
1620  * Our calling convention to the device drivers used to be that we passed
1621  * vnode.h IO_* flags to read()/write(), but we're moving to fcntl.h O_ 
1622  * flags instead since that's what open(), close() and ioctl() takes and
1623  * we don't really want vnode.h in device drivers.
1624  * We solved the source compatibility by redefining some vnode flags to
1625  * be the same as the fcntl ones and by sending down the bitwise OR of
1626  * the respective fcntl/vnode flags.  These CTASSERTS make sure nobody
1627  * pulls the rug out under this.
1628  */
1629 CTASSERT(O_NONBLOCK == IO_NDELAY);
1630 CTASSERT(O_FSYNC == IO_SYNC);