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