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