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