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