spec_vnops.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /* $OpenBSD: spec_vnops.c,v 1.83 2015/02/10 21:56:09 miod Exp $ */
  2. /* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */
  3. /*
  4. * Copyright (c) 1989, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. 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. * @(#)spec_vnops.c 8.8 (Berkeley) 11/21/94
  32. */
  33. #include <sys/param.h>
  34. #include <sys/proc.h>
  35. #include <sys/systm.h>
  36. #include <sys/kernel.h>
  37. #include <sys/conf.h>
  38. #include <sys/buf.h>
  39. #include <sys/mount.h>
  40. #include <sys/namei.h>
  41. #include <sys/vnode.h>
  42. #include <sys/lock.h>
  43. #include <sys/stat.h>
  44. #include <sys/errno.h>
  45. #include <sys/ioctl.h>
  46. #include <sys/file.h>
  47. #include <sys/disklabel.h>
  48. #include <sys/lockf.h>
  49. #include <sys/poll.h>
  50. #include <sys/dkio.h>
  51. #include <sys/malloc.h>
  52. #include <sys/specdev.h>
  53. #include <sys/unistd.h>
  54. #include <uvm/uvm_extern.h>
  55. #define v_lastr v_specinfo->si_lastr
  56. int spec_open_clone(struct vop_open_args *);
  57. int spec_close_clone(struct vop_close_args *);
  58. struct vnode *speclisth[SPECHSZ];
  59. struct vops spec_vops = {
  60. .vop_lookup = vop_generic_lookup,
  61. .vop_create = spec_badop,
  62. .vop_mknod = spec_badop,
  63. .vop_open = spec_open,
  64. .vop_close = spec_close,
  65. .vop_access = spec_access,
  66. .vop_getattr = spec_getattr,
  67. .vop_setattr = spec_setattr,
  68. .vop_read = spec_read,
  69. .vop_write = spec_write,
  70. .vop_ioctl = spec_ioctl,
  71. .vop_poll = spec_poll,
  72. .vop_kqfilter = spec_kqfilter,
  73. .vop_revoke = vop_generic_revoke,
  74. .vop_fsync = spec_fsync,
  75. .vop_remove = spec_badop,
  76. .vop_link = spec_badop,
  77. .vop_rename = spec_badop,
  78. .vop_mkdir = spec_badop,
  79. .vop_rmdir = spec_badop,
  80. .vop_symlink = spec_badop,
  81. .vop_readdir = spec_badop,
  82. .vop_readlink = spec_badop,
  83. .vop_abortop = spec_badop,
  84. .vop_inactive = spec_inactive,
  85. .vop_reclaim = nullop,
  86. .vop_lock = vop_generic_lock,
  87. .vop_unlock = vop_generic_unlock,
  88. .vop_islocked = vop_generic_islocked,
  89. .vop_bmap = vop_generic_bmap,
  90. .vop_strategy = spec_strategy,
  91. .vop_print = spec_print,
  92. .vop_pathconf = spec_pathconf,
  93. .vop_advlock = spec_advlock,
  94. .vop_bwrite = vop_generic_bwrite,
  95. };
  96. /*
  97. * Open a special file.
  98. */
  99. int
  100. spec_open(void *v)
  101. {
  102. struct vop_open_args *ap = v;
  103. struct proc *p = ap->a_p;
  104. struct vnode *vp = ap->a_vp;
  105. struct vnode *bvp;
  106. dev_t bdev;
  107. dev_t dev = (dev_t)vp->v_rdev;
  108. int maj = major(dev);
  109. int error;
  110. /*
  111. * Don't allow open if fs is mounted -nodev.
  112. */
  113. if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
  114. return (ENXIO);
  115. switch (vp->v_type) {
  116. case VCHR:
  117. if ((u_int)maj >= nchrdev)
  118. return (ENXIO);
  119. if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {
  120. /*
  121. * When running in very secure mode, do not allow
  122. * opens for writing of any disk character devices.
  123. */
  124. if (securelevel >= 2 && cdevsw[maj].d_type == D_DISK)
  125. return (EPERM);
  126. /*
  127. * When running in secure mode, do not allow opens
  128. * for writing of /dev/mem, /dev/kmem, or character
  129. * devices whose corresponding block devices are
  130. * currently mounted.
  131. */
  132. if (securelevel >= 1) {
  133. if ((bdev = chrtoblk(dev)) != NODEV &&
  134. vfinddev(bdev, VBLK, &bvp) &&
  135. bvp->v_usecount > 0 &&
  136. (error = vfs_mountedon(bvp)))
  137. return (error);
  138. if (iskmemdev(dev))
  139. return (EPERM);
  140. }
  141. }
  142. if (cdevsw[maj].d_type == D_TTY)
  143. vp->v_flag |= VISTTY;
  144. if (cdevsw[maj].d_flags & D_CLONE)
  145. return (spec_open_clone(ap));
  146. VOP_UNLOCK(vp, 0, p);
  147. error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, p);
  148. vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  149. return (error);
  150. case VBLK:
  151. if ((u_int)maj >= nblkdev)
  152. return (ENXIO);
  153. /*
  154. * When running in very secure mode, do not allow
  155. * opens for writing of any disk block devices.
  156. */
  157. if (securelevel >= 2 && ap->a_cred != FSCRED &&
  158. (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK)
  159. return (EPERM);
  160. /*
  161. * Do not allow opens of block devices that are
  162. * currently mounted.
  163. */
  164. if ((error = vfs_mountedon(vp)) != 0)
  165. return (error);
  166. return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, p));
  167. case VNON:
  168. case VLNK:
  169. case VDIR:
  170. case VREG:
  171. case VBAD:
  172. case VFIFO:
  173. case VSOCK:
  174. break;
  175. }
  176. return (0);
  177. }
  178. /*
  179. * Vnode op for read
  180. */
  181. int
  182. spec_read(void *v)
  183. {
  184. struct vop_read_args *ap = v;
  185. struct vnode *vp = ap->a_vp;
  186. struct uio *uio = ap->a_uio;
  187. struct proc *p = uio->uio_procp;
  188. struct buf *bp;
  189. daddr_t bn, nextbn, bscale;
  190. int bsize;
  191. struct partinfo dpart;
  192. int n, on, majordev;
  193. int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *);
  194. int error = 0;
  195. #ifdef DIAGNOSTIC
  196. if (uio->uio_rw != UIO_READ)
  197. panic("spec_read mode");
  198. if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
  199. panic("spec_read proc");
  200. #endif
  201. if (uio->uio_resid == 0)
  202. return (0);
  203. switch (vp->v_type) {
  204. case VCHR:
  205. VOP_UNLOCK(vp, 0, p);
  206. error = (*cdevsw[major(vp->v_rdev)].d_read)
  207. (vp->v_rdev, uio, ap->a_ioflag);
  208. vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  209. return (error);
  210. case VBLK:
  211. if (uio->uio_offset < 0)
  212. return (EINVAL);
  213. bsize = BLKDEV_IOSIZE;
  214. if ((majordev = major(vp->v_rdev)) < nblkdev &&
  215. (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
  216. (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
  217. u_int32_t frag =
  218. DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock);
  219. u_int32_t fsize =
  220. DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock);
  221. if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 &&
  222. fsize != 0)
  223. bsize = frag * fsize;
  224. }
  225. bscale = btodb(bsize);
  226. do {
  227. bn = btodb(uio->uio_offset) & ~(bscale - 1);
  228. on = uio->uio_offset % bsize;
  229. n = min((bsize - on), uio->uio_resid);
  230. if (vp->v_lastr + bscale == bn) {
  231. nextbn = bn + bscale;
  232. error = breadn(vp, bn, bsize, &nextbn, &bsize,
  233. 1, &bp);
  234. } else
  235. error = bread(vp, bn, bsize, &bp);
  236. vp->v_lastr = bn;
  237. n = min(n, bsize - bp->b_resid);
  238. if (error) {
  239. brelse(bp);
  240. return (error);
  241. }
  242. error = uiomovei((char *)bp->b_data + on, n, uio);
  243. brelse(bp);
  244. } while (error == 0 && uio->uio_resid > 0 && n != 0);
  245. return (error);
  246. default:
  247. panic("spec_read type");
  248. }
  249. /* NOTREACHED */
  250. }
  251. int
  252. spec_inactive(void *v)
  253. {
  254. struct vop_inactive_args *ap = v;
  255. VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
  256. return (0);
  257. }
  258. /*
  259. * Vnode op for write
  260. */
  261. int
  262. spec_write(void *v)
  263. {
  264. struct vop_write_args *ap = v;
  265. struct vnode *vp = ap->a_vp;
  266. struct uio *uio = ap->a_uio;
  267. struct proc *p = uio->uio_procp;
  268. struct buf *bp;
  269. daddr_t bn, bscale;
  270. int bsize;
  271. struct partinfo dpart;
  272. int n, on, majordev;
  273. int (*ioctl)(dev_t, u_long, caddr_t, int, struct proc *);
  274. int error = 0;
  275. #ifdef DIAGNOSTIC
  276. if (uio->uio_rw != UIO_WRITE)
  277. panic("spec_write mode");
  278. if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
  279. panic("spec_write proc");
  280. #endif
  281. switch (vp->v_type) {
  282. case VCHR:
  283. VOP_UNLOCK(vp, 0, p);
  284. error = (*cdevsw[major(vp->v_rdev)].d_write)
  285. (vp->v_rdev, uio, ap->a_ioflag);
  286. vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  287. return (error);
  288. case VBLK:
  289. if (uio->uio_resid == 0)
  290. return (0);
  291. if (uio->uio_offset < 0)
  292. return (EINVAL);
  293. bsize = BLKDEV_IOSIZE;
  294. if ((majordev = major(vp->v_rdev)) < nblkdev &&
  295. (ioctl = bdevsw[majordev].d_ioctl) != NULL &&
  296. (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {
  297. u_int32_t frag =
  298. DISKLABELV1_FFS_FRAG(dpart.part->p_fragblock);
  299. u_int32_t fsize =
  300. DISKLABELV1_FFS_FSIZE(dpart.part->p_fragblock);
  301. if (dpart.part->p_fstype == FS_BSDFFS && frag != 0 &&
  302. fsize != 0)
  303. bsize = frag * fsize;
  304. }
  305. bscale = btodb(bsize);
  306. do {
  307. bn = btodb(uio->uio_offset) & ~(bscale - 1);
  308. on = uio->uio_offset % bsize;
  309. n = min((bsize - on), uio->uio_resid);
  310. error = bread(vp, bn, bsize, &bp);
  311. n = min(n, bsize - bp->b_resid);
  312. if (error) {
  313. brelse(bp);
  314. return (error);
  315. }
  316. error = uiomovei((char *)bp->b_data + on, n, uio);
  317. if (n + on == bsize)
  318. bawrite(bp);
  319. else
  320. bdwrite(bp);
  321. } while (error == 0 && uio->uio_resid > 0 && n != 0);
  322. return (error);
  323. default:
  324. panic("spec_write type");
  325. }
  326. /* NOTREACHED */
  327. }
  328. /*
  329. * Device ioctl operation.
  330. */
  331. int
  332. spec_ioctl(void *v)
  333. {
  334. struct vop_ioctl_args *ap = v;
  335. dev_t dev = ap->a_vp->v_rdev;
  336. int maj = major(dev);
  337. switch (ap->a_vp->v_type) {
  338. case VCHR:
  339. return ((*cdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
  340. ap->a_fflag, ap->a_p));
  341. case VBLK:
  342. return ((*bdevsw[maj].d_ioctl)(dev, ap->a_command, ap->a_data,
  343. ap->a_fflag, ap->a_p));
  344. default:
  345. panic("spec_ioctl");
  346. /* NOTREACHED */
  347. }
  348. }
  349. int
  350. spec_poll(void *v)
  351. {
  352. struct vop_poll_args *ap = v;
  353. dev_t dev;
  354. switch (ap->a_vp->v_type) {
  355. default:
  356. return (ap->a_events &
  357. (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
  358. case VCHR:
  359. dev = ap->a_vp->v_rdev;
  360. return (*cdevsw[major(dev)].d_poll)(dev, ap->a_events, ap->a_p);
  361. }
  362. }
  363. int
  364. spec_kqfilter(void *v)
  365. {
  366. struct vop_kqfilter_args *ap = v;
  367. dev_t dev;
  368. dev = ap->a_vp->v_rdev;
  369. if (cdevsw[major(dev)].d_kqfilter)
  370. return (*cdevsw[major(dev)].d_kqfilter)(dev, ap->a_kn);
  371. return (EOPNOTSUPP);
  372. }
  373. /*
  374. * Synch buffers associated with a block device
  375. */
  376. int
  377. spec_fsync(void *v)
  378. {
  379. struct vop_fsync_args *ap = v;
  380. struct vnode *vp = ap->a_vp;
  381. struct buf *bp;
  382. struct buf *nbp;
  383. int s;
  384. if (vp->v_type == VCHR)
  385. return (0);
  386. /*
  387. * Flush all dirty buffers associated with a block device.
  388. */
  389. loop:
  390. s = splbio();
  391. for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
  392. nbp = LIST_NEXT(bp, b_vnbufs);
  393. if ((bp->b_flags & B_BUSY))
  394. continue;
  395. if ((bp->b_flags & B_DELWRI) == 0)
  396. panic("spec_fsync: not dirty");
  397. bremfree(bp);
  398. buf_acquire(bp);
  399. splx(s);
  400. bawrite(bp);
  401. goto loop;
  402. }
  403. if (ap->a_waitfor == MNT_WAIT) {
  404. vwaitforio (vp, 0, "spec_fsync", 0);
  405. #ifdef DIAGNOSTIC
  406. if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
  407. splx(s);
  408. vprint("spec_fsync: dirty", vp);
  409. goto loop;
  410. }
  411. #endif
  412. }
  413. splx(s);
  414. return (0);
  415. }
  416. int
  417. spec_strategy(void *v)
  418. {
  419. struct vop_strategy_args *ap = v;
  420. struct buf *bp = ap->a_bp;
  421. int maj = major(bp->b_dev);
  422. if (LIST_FIRST(&bp->b_dep) != NULL)
  423. buf_start(bp);
  424. (*bdevsw[maj].d_strategy)(bp);
  425. return (0);
  426. }
  427. /*
  428. * Device close routine
  429. */
  430. int
  431. spec_close(void *v)
  432. {
  433. struct vop_close_args *ap = v;
  434. struct proc *p = ap->a_p;
  435. struct vnode *vp = ap->a_vp;
  436. dev_t dev = vp->v_rdev;
  437. int (*devclose)(dev_t, int, int, struct proc *);
  438. int mode, relock, error;
  439. switch (vp->v_type) {
  440. case VCHR:
  441. /*
  442. * Hack: a tty device that is a controlling terminal
  443. * has a reference from the session structure.
  444. * We cannot easily tell that a character device is
  445. * a controlling terminal, unless it is the closing
  446. * process' controlling terminal. In that case,
  447. * if the reference count is 2 (this last descriptor
  448. * plus the session), release the reference from the session.
  449. */
  450. if (vcount(vp) == 2 && p != NULL && p->p_p->ps_pgrp &&
  451. vp == p->p_p->ps_pgrp->pg_session->s_ttyvp) {
  452. vrele(vp);
  453. p->p_p->ps_pgrp->pg_session->s_ttyvp = NULL;
  454. }
  455. if (cdevsw[major(dev)].d_flags & D_CLONE)
  456. return (spec_close_clone(ap));
  457. /*
  458. * If the vnode is locked, then we are in the midst
  459. * of forcably closing the device, otherwise we only
  460. * close on last reference.
  461. */
  462. if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
  463. return (0);
  464. devclose = cdevsw[major(dev)].d_close;
  465. mode = S_IFCHR;
  466. break;
  467. case VBLK:
  468. /*
  469. * On last close of a block device (that isn't mounted)
  470. * we must invalidate any in core blocks, so that
  471. * we can, for instance, change floppy disks. In order to do
  472. * that, we must lock the vnode. If we are coming from
  473. * vclean(), the vnode is already locked.
  474. */
  475. if (!(vp->v_flag & VXLOCK))
  476. vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  477. error = vinvalbuf(vp, V_SAVE, ap->a_cred, p, 0, 0);
  478. if (!(vp->v_flag & VXLOCK))
  479. VOP_UNLOCK(vp, 0, p);
  480. if (error)
  481. return (error);
  482. /*
  483. * We do not want to really close the device if it
  484. * is still in use unless we are trying to close it
  485. * forcibly. Since every use (buffer, vnode, swap, cmap)
  486. * holds a reference to the vnode, and because we mark
  487. * any other vnodes that alias this device, when the
  488. * sum of the reference counts on all the aliased
  489. * vnodes descends to one, we are on last close.
  490. */
  491. if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
  492. return (0);
  493. devclose = bdevsw[major(dev)].d_close;
  494. mode = S_IFBLK;
  495. break;
  496. default:
  497. panic("spec_close: not special");
  498. }
  499. /* release lock if held and this isn't coming from vclean() */
  500. relock = VOP_ISLOCKED(vp) && !(vp->v_flag & VXLOCK);
  501. if (relock)
  502. VOP_UNLOCK(vp, 0, p);
  503. error = (*devclose)(dev, ap->a_fflag, mode, p);
  504. if (relock)
  505. vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  506. return (error);
  507. }
  508. int
  509. spec_getattr(void *v)
  510. {
  511. struct vop_getattr_args *ap = v;
  512. struct vnode *vp = ap->a_vp;
  513. if (!(vp->v_flag & VCLONE))
  514. return (EBADF);
  515. return (VOP_GETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p));
  516. }
  517. int
  518. spec_setattr(void *v)
  519. {
  520. struct vop_getattr_args *ap = v;
  521. struct proc *p = ap->a_p;
  522. struct vnode *vp = ap->a_vp;
  523. int error;
  524. if (!(vp->v_flag & VCLONE))
  525. return (EBADF);
  526. vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY, p);
  527. error = VOP_SETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, p);
  528. VOP_UNLOCK(vp, 0, p);
  529. return (error);
  530. }
  531. int
  532. spec_access(void *v)
  533. {
  534. struct vop_access_args *ap = v;
  535. struct vnode *vp = ap->a_vp;
  536. if (!(vp->v_flag & VCLONE))
  537. return (EBADF);
  538. return (VOP_ACCESS(vp->v_specparent, ap->a_mode, ap->a_cred, ap->a_p));
  539. }
  540. /*
  541. * Print out the contents of a special device vnode.
  542. */
  543. int
  544. spec_print(void *v)
  545. {
  546. struct vop_print_args *ap = v;
  547. printf("tag VT_NON, dev %d, %d\n", major(ap->a_vp->v_rdev),
  548. minor(ap->a_vp->v_rdev));
  549. return 0;
  550. }
  551. /*
  552. * Return POSIX pathconf information applicable to special devices.
  553. */
  554. int
  555. spec_pathconf(void *v)
  556. {
  557. struct vop_pathconf_args *ap = v;
  558. int error = 0;
  559. switch (ap->a_name) {
  560. case _PC_LINK_MAX:
  561. *ap->a_retval = LINK_MAX;
  562. break;
  563. case _PC_MAX_CANON:
  564. *ap->a_retval = MAX_CANON;
  565. break;
  566. case _PC_MAX_INPUT:
  567. *ap->a_retval = MAX_INPUT;
  568. break;
  569. case _PC_CHOWN_RESTRICTED:
  570. *ap->a_retval = 1;
  571. break;
  572. case _PC_VDISABLE:
  573. *ap->a_retval = _POSIX_VDISABLE;
  574. break;
  575. case _PC_TIMESTAMP_RESOLUTION:
  576. *ap->a_retval = 1;
  577. break;
  578. default:
  579. error = EINVAL;
  580. break;
  581. }
  582. return (error);
  583. }
  584. /*
  585. * Special device advisory byte-level locks.
  586. */
  587. int
  588. spec_advlock(void *v)
  589. {
  590. struct vop_advlock_args *ap = v;
  591. struct vnode *vp = ap->a_vp;
  592. return (lf_advlock(&vp->v_speclockf, (off_t)0, ap->a_id,
  593. ap->a_op, ap->a_fl, ap->a_flags));
  594. }
  595. /*
  596. * Special device bad operation
  597. */
  598. /*ARGSUSED*/
  599. int
  600. spec_badop(void *v)
  601. {
  602. panic("spec_badop called");
  603. /* NOTREACHED */
  604. }
  605. /*
  606. * Copyright (c) 2006 Pedro Martelletto <pedro@ambientworks.net>
  607. * Copyright (c) 2006 Thordur Bjornsson <thib@openbsd.org>
  608. *
  609. * Permission to use, copy, modify, and distribute this software for any
  610. * purpose with or without fee is hereby granted, provided that the above
  611. * copyright notice and this permission notice appear in all copies.
  612. *
  613. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  614. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  615. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  616. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  617. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  618. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  619. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  620. */
  621. #ifdef CLONE_DEBUG
  622. #define DNPRINTF(m...) do { printf(m); } while (0)
  623. #else
  624. #define DNPRINTF(m...) /* nothing */
  625. #endif
  626. int
  627. spec_open_clone(struct vop_open_args *ap)
  628. {
  629. struct vnode *cvp, *vp = ap->a_vp;
  630. struct cloneinfo *cip;
  631. int error, i;
  632. DNPRINTF("cloning vnode\n");
  633. if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT))
  634. return (ENXIO);
  635. for (i = 1; i < sizeof(vp->v_specbitmap) * NBBY; i++)
  636. if (isclr(vp->v_specbitmap, i)) {
  637. setbit(vp->v_specbitmap, i);
  638. break;
  639. }
  640. if (i == sizeof(vp->v_specbitmap) * NBBY)
  641. return (EBUSY); /* too many open instances */
  642. error = cdevvp(makedev(major(vp->v_rdev),
  643. (i << CLONE_SHIFT) | minor(vp->v_rdev)), &cvp);
  644. if (error) {
  645. clrbit(vp->v_specbitmap, i);
  646. return (error); /* out of vnodes */
  647. }
  648. VOP_UNLOCK(vp, 0, ap->a_p);
  649. error = cdevsw[major(vp->v_rdev)].d_open(cvp->v_rdev, ap->a_mode,
  650. S_IFCHR, ap->a_p);
  651. vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p);
  652. if (error) {
  653. vput(cvp);
  654. clrbit(vp->v_specbitmap, i);
  655. return (error); /* device open failed */
  656. }
  657. cvp->v_flag |= VCLONE;
  658. cip = malloc(sizeof(struct cloneinfo), M_TEMP, M_WAITOK);
  659. cip->ci_data = vp->v_data;
  660. cip->ci_vp = cvp;
  661. cvp->v_specparent = vp;
  662. vp->v_flag |= VCLONED;
  663. vp->v_data = cip;
  664. DNPRINTF("clone of vnode %p is vnode %p\n", vp, cvp);
  665. return (0); /* device cloned */
  666. }
  667. int
  668. spec_close_clone(struct vop_close_args *ap)
  669. {
  670. struct vnode *pvp, *vp = ap->a_vp;
  671. int error;
  672. error = cdevsw[major(vp->v_rdev)].d_close(vp->v_rdev, ap->a_fflag,
  673. S_IFCHR, ap->a_p);
  674. if (error)
  675. return (error); /* device close failed */
  676. pvp = vp->v_specparent; /* get parent device */
  677. clrbit(pvp->v_specbitmap, minor(vp->v_rdev) >> CLONE_SHIFT);
  678. vrele(pvp);
  679. return (0); /* clone closed */
  680. }