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) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * This file implements /dev filesystem operations for non-global
28 * instances. Three major entry points:
29 * devname_profile_update()
30 * Update matching rules determining which names to export
31 * prof_readdir()
32 * Return the list of exported names
33 * prof_lookup()
34 * Implements lookup
35 */
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/sysmacros.h>
40 #include <sys/vnode.h>
41 #include <sys/uio.h>
42 #include <sys/dirent.h>
638 }
639
640 /* Walk nvlist and lookup corresponding device in global inst */
641 while (nvp = nvlist_next_nvpair(nvl, nvp)) {
642 int type;
643 rv = nvpair_value_int32(nvp, &type);
644 if (rv != 0) {
645 cmn_err(CE_WARN, sdev_nvp_val_err,
646 rv, nvpair_name(nvp));
647 break;
648 }
649 if (type == PROFILE_TYPE_EXCLUDE)
650 continue;
651 name = nvpair_name(nvp);
652 (void) prof_lookup_globaldev(dir, dir->sdev_origin,
653 name, name);
654 }
655 }
656
657 /*
658 * Build directory vnodes based on the profile and the global
659 * dev instance.
660 */
661 void
662 prof_filldir(struct sdev_node *ddv)
663 {
664 int firsttime = 1;
665 struct sdev_node *gdir = ddv->sdev_origin;
666
667 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
668
669 /*
670 * We need to rebuild the directory content if
671 * - SDEV_BUILD is set
672 * - The device tree generation number has changed
673 * - The corresponding /dev namespace has been updated
674 */
675 check_build:
676 if ((ddv->sdev_flags & SDEV_BUILD) == 0 &&
677 ddv->sdev_devtree_gen == devtree_gen &&
678 (gdir == NULL || ddv->sdev_ldir_gen
679 == gdir->sdev_gdir_gen))
680 return; /* already up to date */
681
682 /* We may have become a zombie (across a try) */
683 if (ddv->sdev_state == SDEV_ZOMBIE)
684 return;
685
686 if (firsttime && rw_tryupgrade(&ddv->sdev_contents) == 0) {
687 rw_exit(&ddv->sdev_contents);
688 firsttime = 0;
689 rw_enter(&ddv->sdev_contents, RW_WRITER);
690 goto check_build;
691 }
692 sdcmn_err10(("devtree_gen (%s): %ld -> %ld\n",
693 ddv->sdev_path, ddv->sdev_devtree_gen, devtree_gen));
694 if (gdir)
695 sdcmn_err10(("sdev_dir_gen (%s): %ld -> %ld\n",
696 ddv->sdev_path, ddv->sdev_ldir_gen,
697 gdir->sdev_gdir_gen));
698
699 /* update flags and generation number so next filldir is quick */
700 ddv->sdev_flags &= ~SDEV_BUILD;
701 ddv->sdev_devtree_gen = devtree_gen;
702 if (gdir)
703 ddv->sdev_ldir_gen = gdir->sdev_gdir_gen;
704
705 prof_make_symlinks(ddv);
706 prof_make_maps(ddv);
707 prof_make_names(ddv);
708 rw_downgrade(&ddv->sdev_contents);
709 }
710
711 /* apply include/exclude pattern to existing directory content */
712 static void
713 apply_dir_pattern(struct sdev_node *dir, char *expr, char *pathleft, int type)
714 {
715 struct sdev_node *dv;
716
717 /* leaf pattern */
718 if (pathleft == NULL) {
719 if (type == PROFILE_TYPE_INCLUDE)
720 return; /* nothing to do for include */
721 (void) sdev_cleandir(dir, expr, SDEV_ENFORCE);
722 return;
|
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 2014 Coraid, Inc.
24 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 /*
28 * This file implements /dev filesystem operations for non-global
29 * instances. Three major entry points:
30 * devname_profile_update()
31 * Update matching rules determining which names to export
32 * prof_readdir()
33 * Return the list of exported names
34 * prof_lookup()
35 * Implements lookup
36 */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/sysmacros.h>
41 #include <sys/vnode.h>
42 #include <sys/uio.h>
43 #include <sys/dirent.h>
639 }
640
641 /* Walk nvlist and lookup corresponding device in global inst */
642 while (nvp = nvlist_next_nvpair(nvl, nvp)) {
643 int type;
644 rv = nvpair_value_int32(nvp, &type);
645 if (rv != 0) {
646 cmn_err(CE_WARN, sdev_nvp_val_err,
647 rv, nvpair_name(nvp));
648 break;
649 }
650 if (type == PROFILE_TYPE_EXCLUDE)
651 continue;
652 name = nvpair_name(nvp);
653 (void) prof_lookup_globaldev(dir, dir->sdev_origin,
654 name, name);
655 }
656 }
657
658 /*
659 * Return True if directory cache is out of date and should be updated.
660 */
661 static boolean_t
662 prof_dev_needupdate(sdev_node_t *ddv)
663 {
664 sdev_node_t *gdir = ddv->sdev_origin;
665
666 /*
667 * Caller can have either reader or writer lock
668 */
669 ASSERT(RW_LOCK_HELD(&ddv->sdev_contents));
670
671 /*
672 * We need to rebuild the directory content if
673 * - ddv is not in a SDEV_ZOMBIE state
674 * - SDEV_BUILD is set OR
675 * - The device tree generation number has changed OR
676 * - The corresponding /dev namespace has been updated
677 */
678 return ((ddv->sdev_state != SDEV_ZOMBIE) &&
679 (((ddv->sdev_flags & SDEV_BUILD) != 0) ||
680 (ddv->sdev_devtree_gen != devtree_gen) ||
681 ((gdir != NULL) &&
682 (ddv->sdev_ldir_gen != gdir->sdev_gdir_gen))));
683 }
684
685 /*
686 * Build directory vnodes based on the profile and the global
687 * dev instance.
688 */
689 void
690 prof_filldir(sdev_node_t *ddv)
691 {
692 sdev_node_t *gdir;
693
694 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
695
696 if (!prof_dev_needupdate(ddv)) {
697 ASSERT(RW_READ_HELD(&ddv->sdev_contents));
698 return;
699 }
700 /*
701 * Upgrade to writer lock
702 */
703 if (rw_tryupgrade(&ddv->sdev_contents) == 0) {
704 /*
705 * We need to drop the read lock and re-acquire it as a
706 * write lock. While we do this the condition may change so we
707 * need to re-check condition.
708 * NOTE: if device becomes a zombie, prof_dev_needupdate returns
709 * false, so nothing we will just return in this case.
710 */
711 rw_exit(&ddv->sdev_contents);
712 rw_enter(&ddv->sdev_contents, RW_WRITER);
713 if (!prof_dev_needupdate(ddv)) {
714 /* Downgrade back to the read lock before returning */
715 rw_downgrade(&ddv->sdev_contents);
716 return;
717 }
718 }
719 /* At this point we should have a write lock */
720 ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
721
722 sdcmn_err10(("devtree_gen (%s): %ld -> %ld\n",
723 ddv->sdev_path, ddv->sdev_devtree_gen, devtree_gen));
724
725 gdir = ddv->sdev_origin;
726
727 if (gdir != NULL)
728 sdcmn_err10(("sdev_dir_gen (%s): %ld -> %ld\n",
729 ddv->sdev_path, ddv->sdev_ldir_gen,
730 gdir->sdev_gdir_gen));
731
732 /* update flags and generation number so next filldir is quick */
733 if ((ddv->sdev_flags & SDEV_BUILD) == SDEV_BUILD) {
734 ddv->sdev_flags &= ~SDEV_BUILD;
735 }
736 ddv->sdev_devtree_gen = devtree_gen;
737 if (gdir != NULL)
738 ddv->sdev_ldir_gen = gdir->sdev_gdir_gen;
739
740 prof_make_symlinks(ddv);
741 prof_make_maps(ddv);
742 prof_make_names(ddv);
743 rw_downgrade(&ddv->sdev_contents);
744 }
745
746 /* apply include/exclude pattern to existing directory content */
747 static void
748 apply_dir_pattern(struct sdev_node *dir, char *expr, char *pathleft, int type)
749 {
750 struct sdev_node *dv;
751
752 /* leaf pattern */
753 if (pathleft == NULL) {
754 if (type == PROFILE_TYPE_INCLUDE)
755 return; /* nothing to do for include */
756 (void) sdev_cleandir(dir, expr, SDEV_ENFORCE);
757 return;
|