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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <strings.h> 28 #include <unistd.h> 29 #include <stdarg.h> 30 #include <fcntl.h> 31 #include <stdlib.h> 32 #include <libnvpair.h> 33 #include <libdevinfo.h> 34 #include <syslog.h> 35 #include <sys/param.h> 36 #include <errno.h> 37 #include <assert.h> 38 #include <sys/systeminfo.h> 39 #include <sys/modctl.h> 40 #include <sys/fs/sdev_impl.h> 41 42 /* 43 * Private interfaces for non-global /dev profile 44 */ 45 46 /* 47 * Allocate opaque data structure for passing profile to the kernel for 48 * the given mount point. 49 * 50 * Note that this interface returns an empty, initialized, profile. 51 * It does not return what may have been previously committed. 52 */ 53 int 54 di_prof_init(const char *mountpt, di_prof_t *profp) 55 { 56 nvlist_t *nvl; 57 58 if (nvlist_alloc(&nvl, 0, 0)) 59 return (-1); 60 61 if (nvlist_add_string(nvl, SDEV_NVNAME_MOUNTPT, mountpt)) { 62 nvlist_free(nvl); 63 return (-1); 64 } 65 66 *profp = (di_prof_t)nvl; 67 return (0); 68 } 69 70 /* 71 * Free space allocated by di_prof_init(). 72 */ 73 void 74 di_prof_fini(di_prof_t prof) 75 { 76 nvlist_free((nvlist_t *)prof); 77 } 78 79 /* 80 * Sends profile to the kernel. 81 */ 82 int 83 di_prof_commit(di_prof_t prof) 84 { 85 char *buf = NULL; 86 size_t buflen = 0; 87 int rv; 88 89 if (nvlist_pack((nvlist_t *)prof, &buf, &buflen, NV_ENCODE_NATIVE, 0)) 90 return (-1); 91 rv = modctl(MODDEVNAME, MODDEVNAME_PROFILE, buf, buflen); 92 free(buf); 93 return (rv); 94 } 95 96 /* 97 * Add a device or directory to profile's include list. 98 * 99 * Note that there is no arbitration between conflicting 100 * include and exclude profile entries, most recent 101 * is the winner. 102 */ 103 int 104 di_prof_add_dev(di_prof_t prof, const char *dev) 105 { 106 if (nvlist_add_string((nvlist_t *)prof, SDEV_NVNAME_INCLUDE, dev)) 107 return (-1); 108 return (0); 109 } 110 111 /* 112 * Add a device or directory to profile's exclude list. 113 * This can effectively remove a previously committed device. 114 */ 115 int 116 di_prof_add_exclude(di_prof_t prof, const char *dev) 117 { 118 if (nvlist_add_string((nvlist_t *)prof, SDEV_NVNAME_EXCLUDE, dev)) 119 return (-1); 120 return (0); 121 } 122 123 /* 124 * Add a symlink to profile. 125 */ 126 int 127 di_prof_add_symlink(di_prof_t prof, const char *linkname, const char *target) 128 { 129 nvlist_t *nvl = (nvlist_t *)prof; 130 char *syml[2]; 131 132 syml[0] = (char *)linkname; /* 1st entry must be the symlink */ 133 syml[1] = (char *)target; /* 2nd entry must be the target */ 134 if (nvlist_add_string_array(nvl, SDEV_NVNAME_SYMLINK, syml, 2)) 135 return (-1); 136 return (0); 137 } 138 139 /* 140 * Add a name mapping to profile. 141 */ 142 int 143 di_prof_add_map(di_prof_t prof, const char *source, const char *target) 144 { 145 nvlist_t *nvl = (nvlist_t *)prof; 146 char *map[2]; 147 148 map[0] = (char *)source; /* 1st entry must be the source */ 149 map[1] = (char *)target; /* 2nd entry must be the target */ 150 if (nvlist_add_string_array(nvl, SDEV_NVNAME_MAP, map, 2)) 151 return (-1); 152 return (0); 153 } 154