1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * miscellaneous routines for the devfs
27 */
28
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/t_lock.h>
32 #include <sys/systm.h>
33 #include <sys/sysmacros.h>
34 #include <sys/user.h>
35 #include <sys/time.h>
36 #include <sys/vfs.h>
37 #include <sys/vnode.h>
38 #include <sys/file.h>
39 #include <sys/fcntl.h>
40 #include <sys/flock.h>
41 #include <sys/kmem.h>
42 #include <sys/uio.h>
43 #include <sys/errno.h>
44 #include <sys/stat.h>
45 #include <sys/cred.h>
386 struct vnode *vp;
387 size_t nmlen;
388
389 dcmn_err4(("dv_mknod: %s\n", nm));
390
391 dv = kmem_cache_alloc(dv_node_cache, KM_SLEEP);
392 nmlen = strlen(nm) + 1;
393 dv->dv_name = kmem_alloc(nmlen, KM_SLEEP);
394 bcopy(nm, dv->dv_name, nmlen);
395 dv->dv_namelen = nmlen - 1; /* no '\0' */
396
397 vp = DVTOV(dv);
398 vn_reinit(vp);
399 vp->v_flag = 0;
400 vp->v_vfsp = DVTOV(ddv)->v_vfsp;
401 vp->v_type = dmd->ddm_spec_type == S_IFCHR ? VCHR : VBLK;
402 vp->v_rdev = dmd->ddm_dev;
403 vn_setops(vp, vn_getops(DVTOV(ddv)));
404 vn_exists(vp);
405
406 /* increment dev_ref with devi_lock held */
407 ASSERT(DEVI_BUSY_OWNED(devi));
408 mutex_enter(&DEVI(devi)->devi_lock);
409 dv->dv_devi = devi;
410 DEVI(devi)->devi_ref++; /* ndi_hold_devi(dip) */
411 mutex_exit(&DEVI(devi)->devi_lock);
412
413 dv->dv_ino = dv_mkino(devi, vp->v_type, vp->v_rdev);
414 dv->dv_nlink = 0; /* updated on insert */
415 dv->dv_dotdot = ddv;
416 dv->dv_attrvp = NULLVP;
417 dv->dv_attr = NULL;
418 dv->dv_flags = 0;
419
420 if (dmd->type == DDM_INTERNAL_PATH)
421 dv->dv_flags |= DV_INTERNAL;
422 if (dmd->ddm_flags & DM_NO_FSPERM)
423 dv->dv_flags |= DV_NO_FSPERM;
424
425 dv->dv_priv = dmd->ddm_node_priv;
426 if (dv->dv_priv)
427 dphold(dv->dv_priv);
428
429 /*
430 * Minors created with ddi_create_priv_minor_node can specify
431 * a default mode permission other than the devfs default.
432 */
1428 mutex_exit(&vp->v_lock);
1429 rw_exit(&dv->dv_contents);
1430 goto set_busy;
1431 }
1432
1433 /*
1434 * Mark referenced directory stale so that DR
1435 * will succeed even if a shell has
1436 * /devices/xxx as current directory (causing
1437 * VN_HOLD reference to an empty directory).
1438 */
1439 ASSERT(!DV_STALE(dv));
1440 ndi_rele_devi(dv->dv_devi);
1441 dv->dv_devi = NULL; /* mark DV_STALE */
1442 }
1443 } else {
1444 ASSERT((vp->v_type == VCHR) || (vp->v_type == VBLK));
1445 ASSERT(dv->dv_nlink == 1); /* no hard links */
1446 mutex_enter(&vp->v_lock);
1447 if (vp->v_count > 0) {
1448 mutex_exit(&vp->v_lock);
1449 goto set_busy;
1450 }
1451 }
1452
1453 /* unlink from directory */
1454 dv_unlink(ddv, dv);
1455
1456 /* drop locks */
1457 mutex_exit(&vp->v_lock);
1458 if (vp->v_type == VDIR)
1459 rw_exit(&dv->dv_contents);
1460
1461 /* destroy vnode if ref count is zero */
1462 if (vp->v_count == 0)
1463 dv_destroy(dv, flags);
1464
1465 continue;
1466
1467 /*
1468 * If devnm is not NULL we return immediately on busy,
1469 * otherwise we continue destroying unused dv_node's.
1470 */
1471 set_busy: busy++;
|
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright 2018 Nexenta Systems, Inc.
28 */
29
30 /*
31 * miscellaneous routines for the devfs
32 */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/t_lock.h>
37 #include <sys/systm.h>
38 #include <sys/sysmacros.h>
39 #include <sys/user.h>
40 #include <sys/time.h>
41 #include <sys/vfs.h>
42 #include <sys/vnode.h>
43 #include <sys/file.h>
44 #include <sys/fcntl.h>
45 #include <sys/flock.h>
46 #include <sys/kmem.h>
47 #include <sys/uio.h>
48 #include <sys/errno.h>
49 #include <sys/stat.h>
50 #include <sys/cred.h>
391 struct vnode *vp;
392 size_t nmlen;
393
394 dcmn_err4(("dv_mknod: %s\n", nm));
395
396 dv = kmem_cache_alloc(dv_node_cache, KM_SLEEP);
397 nmlen = strlen(nm) + 1;
398 dv->dv_name = kmem_alloc(nmlen, KM_SLEEP);
399 bcopy(nm, dv->dv_name, nmlen);
400 dv->dv_namelen = nmlen - 1; /* no '\0' */
401
402 vp = DVTOV(dv);
403 vn_reinit(vp);
404 vp->v_flag = 0;
405 vp->v_vfsp = DVTOV(ddv)->v_vfsp;
406 vp->v_type = dmd->ddm_spec_type == S_IFCHR ? VCHR : VBLK;
407 vp->v_rdev = dmd->ddm_dev;
408 vn_setops(vp, vn_getops(DVTOV(ddv)));
409 vn_exists(vp);
410
411 ASSERT(DEVI_BUSY_OWNED(devi));
412 ndi_hold_devi(devi);
413
414 dv->dv_devi = devi;
415 dv->dv_ino = dv_mkino(devi, vp->v_type, vp->v_rdev);
416 dv->dv_nlink = 0; /* updated on insert */
417 dv->dv_dotdot = ddv;
418 dv->dv_attrvp = NULLVP;
419 dv->dv_attr = NULL;
420 dv->dv_flags = 0;
421
422 if (dmd->type == DDM_INTERNAL_PATH)
423 dv->dv_flags |= DV_INTERNAL;
424 if (dmd->ddm_flags & DM_NO_FSPERM)
425 dv->dv_flags |= DV_NO_FSPERM;
426
427 dv->dv_priv = dmd->ddm_node_priv;
428 if (dv->dv_priv)
429 dphold(dv->dv_priv);
430
431 /*
432 * Minors created with ddi_create_priv_minor_node can specify
433 * a default mode permission other than the devfs default.
434 */
1430 mutex_exit(&vp->v_lock);
1431 rw_exit(&dv->dv_contents);
1432 goto set_busy;
1433 }
1434
1435 /*
1436 * Mark referenced directory stale so that DR
1437 * will succeed even if a shell has
1438 * /devices/xxx as current directory (causing
1439 * VN_HOLD reference to an empty directory).
1440 */
1441 ASSERT(!DV_STALE(dv));
1442 ndi_rele_devi(dv->dv_devi);
1443 dv->dv_devi = NULL; /* mark DV_STALE */
1444 }
1445 } else {
1446 ASSERT((vp->v_type == VCHR) || (vp->v_type == VBLK));
1447 ASSERT(dv->dv_nlink == 1); /* no hard links */
1448 mutex_enter(&vp->v_lock);
1449 if (vp->v_count > 0) {
1450 /*
1451 * The file still has references to it. If
1452 * DV_DEVI_GONE is *not* specified then a
1453 * referenced file is considered busy.
1454 */
1455 if (!(flags & DV_DEVI_GONE)) {
1456 mutex_exit(&vp->v_lock);
1457 goto set_busy;
1458 }
1459
1460 /*
1461 * Mark referenced file stale so that DR will
1462 * succeed even if there are userland opens.
1463 */
1464 ASSERT(!DV_STALE(dv));
1465 ndi_rele_devi(dv->dv_devi);
1466 DEVI(dv->dv_devi)->devi_gone = 1;
1467 dv->dv_devi = NULL;
1468 }
1469 }
1470
1471 /* unlink from directory */
1472 dv_unlink(ddv, dv);
1473
1474 /* drop locks */
1475 mutex_exit(&vp->v_lock);
1476 if (vp->v_type == VDIR)
1477 rw_exit(&dv->dv_contents);
1478
1479 /* destroy vnode if ref count is zero */
1480 if (vp->v_count == 0)
1481 dv_destroy(dv, flags);
1482
1483 continue;
1484
1485 /*
1486 * If devnm is not NULL we return immediately on busy,
1487 * otherwise we continue destroying unused dv_node's.
1488 */
1489 set_busy: busy++;
|