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>
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 * Copyright 2018 Nexenta Systems, Inc.
25 */
26
27 /*
28 * miscellaneous routines for the devfs
29 */
30
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/t_lock.h>
34 #include <sys/systm.h>
35 #include <sys/sysmacros.h>
36 #include <sys/user.h>
37 #include <sys/time.h>
38 #include <sys/vfs.h>
39 #include <sys/vnode.h>
40 #include <sys/file.h>
41 #include <sys/fcntl.h>
42 #include <sys/flock.h>
43 #include <sys/kmem.h>
44 #include <sys/uio.h>
388 struct vnode *vp;
389 size_t nmlen;
390
391 dcmn_err4(("dv_mknod: %s\n", nm));
392
393 dv = kmem_cache_alloc(dv_node_cache, KM_SLEEP);
394 nmlen = strlen(nm) + 1;
395 dv->dv_name = kmem_alloc(nmlen, KM_SLEEP);
396 bcopy(nm, dv->dv_name, nmlen);
397 dv->dv_namelen = nmlen - 1; /* no '\0' */
398
399 vp = DVTOV(dv);
400 vn_reinit(vp);
401 vp->v_flag = 0;
402 vp->v_vfsp = DVTOV(ddv)->v_vfsp;
403 vp->v_type = dmd->ddm_spec_type == S_IFCHR ? VCHR : VBLK;
404 vp->v_rdev = dmd->ddm_dev;
405 vn_setops(vp, vn_getops(DVTOV(ddv)));
406 vn_exists(vp);
407
408 ASSERT(DEVI_BUSY_OWNED(devi));
409 ndi_hold_devi(devi);
410
411 dv->dv_devi = devi;
412 dv->dv_ino = dv_mkino(devi, vp->v_type, vp->v_rdev);
413 dv->dv_nlink = 0; /* updated on insert */
414 dv->dv_dotdot = ddv;
415 dv->dv_attrvp = NULLVP;
416 dv->dv_attr = NULL;
417 dv->dv_flags = 0;
418
419 if (dmd->type == DDM_INTERNAL_PATH)
420 dv->dv_flags |= DV_INTERNAL;
421 if (dmd->ddm_flags & DM_NO_FSPERM)
422 dv->dv_flags |= DV_NO_FSPERM;
423
424 dv->dv_priv = dmd->ddm_node_priv;
425 if (dv->dv_priv)
426 dphold(dv->dv_priv);
427
428 /*
429 * Minors created with ddi_create_priv_minor_node can specify
430 * a default mode permission other than the devfs default.
431 */
1427 mutex_exit(&vp->v_lock);
1428 rw_exit(&dv->dv_contents);
1429 goto set_busy;
1430 }
1431
1432 /*
1433 * Mark referenced directory stale so that DR
1434 * will succeed even if a shell has
1435 * /devices/xxx as current directory (causing
1436 * VN_HOLD reference to an empty directory).
1437 */
1438 ASSERT(!DV_STALE(dv));
1439 ndi_rele_devi(dv->dv_devi);
1440 dv->dv_devi = NULL; /* mark DV_STALE */
1441 }
1442 } else {
1443 ASSERT((vp->v_type == VCHR) || (vp->v_type == VBLK));
1444 ASSERT(dv->dv_nlink == 1); /* no hard links */
1445 mutex_enter(&vp->v_lock);
1446 if (vp->v_count > 0) {
1447 /*
1448 * The file still has references to it. If
1449 * DEVI_GONE is *not* set on the devi referenced
1450 * file is considered busy.
1451 */
1452 if (!DEVI_IS_GONE(dv->dv_devi)) {
1453 mutex_exit(&vp->v_lock);
1454 goto set_busy;
1455 }
1456
1457 /*
1458 * Mark referenced file stale so that DR will
1459 * succeed even if there are userland opens.
1460 */
1461 ASSERT(!DV_STALE(dv));
1462 ndi_rele_devi(dv->dv_devi);
1463 dv->dv_devi = NULL;
1464 }
1465 }
1466
1467 /* unlink from directory */
1468 dv_unlink(ddv, dv);
1469
1470 /* drop locks */
1471 mutex_exit(&vp->v_lock);
1472 if (vp->v_type == VDIR)
1473 rw_exit(&dv->dv_contents);
1474
1475 /* destroy vnode if ref count is zero */
1476 if (vp->v_count == 0)
1477 dv_destroy(dv, flags);
1478
1479 continue;
1480
1481 /*
1482 * If devnm is not NULL we return immediately on busy,
1483 * otherwise we continue destroying unused dv_node's.
1484 */
1485 set_busy: busy++;
|