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 2012 DEY Storage Systems, Inc. All rights reserved.
24 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 * Copyright 2016 Toomas Soome <tsoome@me.com>
27 */
28
29 /*
30 * This module provides support for labeling operations for target
31 * drivers.
32 */
33
34 #include <sys/scsi/scsi.h>
35 #include <sys/sunddi.h>
36 #include <sys/dklabel.h>
37 #include <sys/dkio.h>
38 #include <sys/vtoc.h>
39 #include <sys/dktp/fdisk.h>
40 #include <sys/vtrace.h>
41 #include <sys/efi_partition.h>
42 #include <sys/cmlb.h>
43 #include <sys/cmlb_impl.h>
44 #if defined(__i386) || defined(__amd64)
45 #include <sys/fs/dv_node.h>
663 * If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC
664 * for the architecture).
665 *
666 * For removable devices, default label type is assumed to be VTOC
667 * type. Create minor nodes based on a default label type.
668 * Label on the media is not validated.
669 * minor number consists of:
670 * if _SUNOS_VTOC_8 is defined
671 * lowest 3 bits is taken as partition number
672 * the rest is instance number
673 * if _SUNOS_VTOC_16 is defined
674 * lowest 6 bits is taken as partition number
675 * the rest is instance number
676 *
677 *
678 * Return values:
679 * 0 Success
680 * ENXIO creating minor nodes failed.
681 * EINVAL invalid arg, unsupported tg_ops version
682 */
683 int
684 cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type,
685 boolean_t is_removable, boolean_t is_hotpluggable, char *node_type,
686 int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie)
687 {
688
689 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
690 diskaddr_t cap;
691 int status;
692
693 ASSERT(VALID_BOOLEAN(is_removable));
694 ASSERT(VALID_BOOLEAN(is_hotpluggable));
695
696 if (tgopsp->tg_version < TG_DK_OPS_VERSION_1)
697 return (EINVAL);
698
699 mutex_enter(CMLB_MUTEX(cl));
700
701 CMLB_DEVINFO(cl) = devi;
702 cl->cmlb_tg_ops = tgopsp;
703 cl->cl_device_type = device_type;
704 cl->cl_is_removable = is_removable;
705 cl->cl_is_hotpluggable = is_hotpluggable;
706 cl->cl_node_type = node_type;
707 cl->cl_sys_blocksize = DEV_BSIZE;
708 cl->cl_f_geometry_is_valid = B_FALSE;
709 cl->cl_def_labeltype = CMLB_LABEL_VTOC;
710 cl->cl_alter_behavior = alter_behavior;
711 cl->cl_reserved = -1;
712 cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN;
713 #if defined(__i386) || defined(__amd64)
714 cl->cl_logical_drive_count = 0;
715 #endif
716
717 if (!is_removable) {
718 mutex_exit(CMLB_MUTEX(cl));
719 status = DK_TG_GETCAP(cl, &cap, tg_cookie);
720 mutex_enter(CMLB_MUTEX(cl));
721 if (status == 0 && cap > CMLB_EXTVTOC_LIMIT) {
722 /* set default EFI if > 2TB */
723 cl->cl_def_labeltype = CMLB_LABEL_EFI;
724 }
725 }
726
727 /* create minor nodes based on default label type */
728 cl->cl_last_labeltype = CMLB_LABEL_UNDEF;
729 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
730
731 if (cmlb_create_minor_nodes(cl) != 0) {
732 mutex_exit(CMLB_MUTEX(cl));
733 return (ENXIO);
734 }
735
736 /* Define the dynamic properties for devinfo spapshots. */
737 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn);
738
739 cl->cl_state = CMLB_ATTACHED;
740
741 mutex_exit(CMLB_MUTEX(cl));
742 return (0);
743 }
744
745 /*
746 * cmlb_detach:
753 *
754 * tg_cookie cookie from target driver to be passed back to target
755 * driver when we call back to it through tg_ops.
756 *
757 */
758 /*ARGSUSED1*/
759 void
760 cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie)
761 {
762 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
763
764 mutex_enter(CMLB_MUTEX(cl));
765 cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
766 cl->cl_f_geometry_is_valid = B_FALSE;
767 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
768 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL);
769 cl->cl_state = CMLB_INITED;
770 mutex_exit(CMLB_MUTEX(cl));
771 }
772
773 /*
774 * cmlb_validate:
775 *
776 * Validates label.
777 *
778 * Arguments
779 * cmlbhandle cmlb handle associated with device.
780 *
781 * flags operation flags. used for verbosity control
782 *
783 * tg_cookie cookie from target driver to be passed back to target
784 * driver when we call back to it through tg_ops.
785 *
786 *
787 * Notes:
788 * If new label type is different from the current, adjust minor nodes
789 * accordingly.
790 *
791 * Return values:
792 * 0 success
|
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 2012 DEY Storage Systems, Inc. All rights reserved.
24 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 * Copyright 2016 Toomas Soome <tsoome@me.com>
28 */
29
30 /*
31 * This module provides support for labeling operations for target
32 * drivers.
33 */
34
35 #include <sys/scsi/scsi.h>
36 #include <sys/sunddi.h>
37 #include <sys/dklabel.h>
38 #include <sys/dkio.h>
39 #include <sys/vtoc.h>
40 #include <sys/dktp/fdisk.h>
41 #include <sys/vtrace.h>
42 #include <sys/efi_partition.h>
43 #include <sys/cmlb.h>
44 #include <sys/cmlb_impl.h>
45 #if defined(__i386) || defined(__amd64)
46 #include <sys/fs/dv_node.h>
664 * If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC
665 * for the architecture).
666 *
667 * For removable devices, default label type is assumed to be VTOC
668 * type. Create minor nodes based on a default label type.
669 * Label on the media is not validated.
670 * minor number consists of:
671 * if _SUNOS_VTOC_8 is defined
672 * lowest 3 bits is taken as partition number
673 * the rest is instance number
674 * if _SUNOS_VTOC_16 is defined
675 * lowest 6 bits is taken as partition number
676 * the rest is instance number
677 *
678 *
679 * Return values:
680 * 0 Success
681 * ENXIO creating minor nodes failed.
682 * EINVAL invalid arg, unsupported tg_ops version
683 */
684 /*ARGSUSED8*/
685 int
686 cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type,
687 boolean_t is_removable, boolean_t is_hotpluggable, char *node_type,
688 int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie)
689 {
690
691 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
692
693 ASSERT(VALID_BOOLEAN(is_removable));
694 ASSERT(VALID_BOOLEAN(is_hotpluggable));
695
696 if (tgopsp->tg_version < TG_DK_OPS_VERSION_1)
697 return (EINVAL);
698
699 mutex_enter(CMLB_MUTEX(cl));
700
701 CMLB_DEVINFO(cl) = devi;
702 cl->cmlb_tg_ops = tgopsp;
703 cl->cl_device_type = device_type;
704 cl->cl_is_removable = is_removable;
705 cl->cl_is_hotpluggable = is_hotpluggable;
706 cl->cl_node_type = node_type;
707 cl->cl_sys_blocksize = DEV_BSIZE;
708 cl->cl_f_geometry_is_valid = B_FALSE;
709 cl->cl_def_labeltype = CMLB_LABEL_VTOC;
710 cl->cl_alter_behavior = alter_behavior;
711 cl->cl_reserved = -1;
712 cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN;
713 #if defined(__i386) || defined(__amd64)
714 cl->cl_logical_drive_count = 0;
715 #endif
716
717 /* create minor nodes based on default label type */
718 cl->cl_last_labeltype = CMLB_LABEL_UNDEF;
719 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
720
721 if (cmlb_create_minor_nodes(cl) != 0) {
722 mutex_exit(CMLB_MUTEX(cl));
723 return (ENXIO);
724 }
725
726 /* Define the dynamic properties for devinfo spapshots. */
727 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn);
728
729 cl->cl_state = CMLB_ATTACHED;
730
731 mutex_exit(CMLB_MUTEX(cl));
732 return (0);
733 }
734
735 /*
736 * cmlb_detach:
743 *
744 * tg_cookie cookie from target driver to be passed back to target
745 * driver when we call back to it through tg_ops.
746 *
747 */
748 /*ARGSUSED1*/
749 void
750 cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie)
751 {
752 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
753
754 mutex_enter(CMLB_MUTEX(cl));
755 cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
756 cl->cl_f_geometry_is_valid = B_FALSE;
757 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
758 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL);
759 cl->cl_state = CMLB_INITED;
760 mutex_exit(CMLB_MUTEX(cl));
761 }
762
763 /*
764 * cmlb_workaround_off_by_one:
765 *
766 * Enables the workaround for the ancient off-by-one bug in sd.
767 * See comment preceding cmlb_attach().
768 *
769 * Arguments
770 * cmlbhandle cmlb handle associated with device.
771 *
772 *
773 * Notes:
774 * This should only be called by sd_unit_attach(), and only before
775 * validating the label for the first time.
776 *
777 * Return values:
778 * None.
779 */
780
781 void
782 cmlb_workaround_off_by_one(cmlb_handle_t cmlbhandle)
783 {
784 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
785
786 cl->cl_alter_behavior |= CMLB_OFF_BY_ONE;
787 }
788
789 /*
790 * cmlb_validate:
791 *
792 * Validates label.
793 *
794 * Arguments
795 * cmlbhandle cmlb handle associated with device.
796 *
797 * flags operation flags. used for verbosity control
798 *
799 * tg_cookie cookie from target driver to be passed back to target
800 * driver when we call back to it through tg_ops.
801 *
802 *
803 * Notes:
804 * If new label type is different from the current, adjust minor nodes
805 * accordingly.
806 *
807 * Return values:
808 * 0 success
|