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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <assert.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <syslog.h>
35 #include <zone.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <stropts.h>
39 #include <sys/conf.h>
40 #include <pthread.h>
41 #include <unistd.h>
42 #include <wait.h>
43 #include <libcontract.h>
44 #include <libcontract_priv.h>
45 #include <sys/contract/process.h>
46 #include "dlmgmt_impl.h"
47
48 typedef enum dlmgmt_db_op {
49 DLMGMT_DB_OP_WRITE,
50 DLMGMT_DB_OP_DELETE,
51 DLMGMT_DB_OP_READ
52 } dlmgmt_db_op_t;
53
54 typedef struct dlmgmt_db_req_s {
55 struct dlmgmt_db_req_s *ls_next;
56 dlmgmt_db_op_t ls_op;
57 char ls_link[MAXLINKNAMELEN];
58 datalink_id_t ls_linkid;
59 zoneid_t ls_zoneid;
60 uint32_t ls_flags; /* Either DLMGMT_ACTIVE or */
61 /* DLMGMT_PERSIST, not both. */
62 } dlmgmt_db_req_t;
63
64 /*
65 * List of pending db updates (e.g., because of a read-only filesystem).
697 assert(dlmgmt_db_req_head == NULL);
698 dlmgmt_db_req_tail = NULL;
699 }
700 free(req);
701 }
702
703 dlmgmt_table_unlock();
704 return (NULL);
705 }
706
707 static int
708 parse_linkprops(char *buf, dlmgmt_link_t *linkp)
709 {
710 boolean_t found_type = B_FALSE;
711 dladm_datatype_t type = DLADM_TYPE_STR;
712 int i, len;
713 char *curr;
714 char attr_name[MAXLINKATTRLEN];
715 size_t attr_buf_len = 0;
716 void *attr_buf = NULL;
717
718 curr = buf;
719 len = strlen(buf);
720 attr_name[0] = '\0';
721 for (i = 0; i < len; i++) {
722 char c = buf[i];
723 boolean_t match = (c == '=' ||
724 (c == ',' && !found_type) || c == ';');
725
726 /*
727 * Move to the next character if there is no match and
728 * if we have not reached the last character.
729 */
730 if (!match && i != len - 1)
731 continue;
732
733 if (match) {
734 /*
735 * NUL-terminate the string pointed to by 'curr'.
736 */
737 buf[i] = '\0';
738 if (*curr == '\0')
739 goto parse_fail;
740 }
741
742 if (attr_name[0] != '\0' && found_type) {
743 /*
744 * We get here after we have processed the "<prop>="
745 * pattern. The pattern we are now interested in is
751 if (strcmp(attr_name, "linkid") == 0) {
752 if (read_int64(curr, &attr_buf) == 0)
753 goto parse_fail;
754 linkp->ll_linkid =
755 (datalink_class_t)*(int64_t *)attr_buf;
756 } else if (strcmp(attr_name, "name") == 0) {
757 if (read_str(curr, &attr_buf) == 0)
758 goto parse_fail;
759 (void) snprintf(linkp->ll_link,
760 MAXLINKNAMELEN, "%s", attr_buf);
761 } else if (strcmp(attr_name, "class") == 0) {
762 if (read_int64(curr, &attr_buf) == 0)
763 goto parse_fail;
764 linkp->ll_class =
765 (datalink_class_t)*(int64_t *)attr_buf;
766 } else if (strcmp(attr_name, "media") == 0) {
767 if (read_int64(curr, &attr_buf) == 0)
768 goto parse_fail;
769 linkp->ll_media =
770 (uint32_t)*(int64_t *)attr_buf;
771 } else {
772 attr_buf_len = translators[type].read_func(curr,
773 &attr_buf);
774 if (attr_buf_len == 0)
775 goto parse_fail;
776
777 if (linkattr_set(&(linkp->ll_head), attr_name,
778 attr_buf, attr_buf_len, type) != 0) {
779 free(attr_buf);
780 goto parse_fail;
781 }
782 }
783
784 free(attr_buf);
785 attr_name[0] = '\0';
786 found_type = B_FALSE;
787 } else if (attr_name[0] != '\0') {
788 /*
789 * Non-zero length attr_name and found_type of false
790 * indicates that we have not found the type for this
794 for (type = 0; type < ntranslators; type++) {
795 if (strcmp(curr,
796 translators[type].type_name) == 0) {
797 found_type = B_TRUE;
798 break;
799 }
800 }
801
802 if (!found_type)
803 goto parse_fail;
804 } else {
805 /*
806 * A zero length attr_name indicates we are looking
807 * at the beginning of a link attribute.
808 */
809 if (c != '=')
810 goto parse_fail;
811
812 (void) snprintf(attr_name, MAXLINKATTRLEN, "%s", curr);
813 }
814 curr = buf + i + 1;
815 }
816
817 /* Correct any erroneous IPTUN datalink class constant in the file */
818 if (linkp->ll_class == 0x60) {
819 linkp->ll_class = DATALINK_CLASS_IPTUN;
820 rewrite_needed = B_TRUE;
821 }
822
823 return (0);
824
825 parse_fail:
826 /*
827 * Free linkp->ll_head (link attribute list)
828 */
829 linkattr_destroy(linkp);
830 return (-1);
831 }
832
833 static boolean_t
1205
1206 return (err);
1207 }
1208
1209 /*
1210 * Generate an entry in the link database.
1211 * Each entry has this format:
1212 * <link name> <prop0>=<type>,<val>;...;<propn>=<type>,<val>;
1213 */
1214 static void
1215 generate_link_line(dlmgmt_link_t *linkp, boolean_t persist, char *buf)
1216 {
1217 char tmpbuf[MAXLINELEN];
1218 char *ptr = tmpbuf;
1219 char *lim = tmpbuf + MAXLINELEN;
1220 dlmgmt_linkattr_t *cur_p = NULL;
1221 uint64_t u64;
1222
1223 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", linkp->ll_link);
1224 if (!persist) {
1225 /*
1226 * We store the linkid in the active database so that dlmgmtd
1227 * can recover in the event that it is restarted.
1228 */
1229 u64 = linkp->ll_linkid;
1230 ptr += write_uint64(ptr, BUFLEN(lim, ptr), "linkid", &u64);
1231 }
1232 u64 = linkp->ll_class;
1233 ptr += write_uint64(ptr, BUFLEN(lim, ptr), "class", &u64);
1234 u64 = linkp->ll_media;
1235 ptr += write_uint64(ptr, BUFLEN(lim, ptr), "media", &u64);
1236
1237 /*
1238 * The daemon does not keep any active link attribute. Only store the
1239 * attributes if this request is for persistent configuration,
1240 */
1241 if (persist) {
1242 for (cur_p = linkp->ll_head; cur_p != NULL;
1243 cur_p = cur_p->lp_next) {
1244 ptr += translators[cur_p->lp_type].write_func(ptr,
1245 BUFLEN(lim, ptr), cur_p->lp_name, cur_p->lp_val);
1246 }
1247 }
1248
1249 if (ptr <= lim)
1250 (void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
1251 }
1365 static void
1366 dlmgmt_db_phys_activate(dlmgmt_link_t *linkp)
1367 {
1368 linkp->ll_flags |= DLMGMT_ACTIVE;
1369 (void) dlmgmt_write_db_entry(linkp->ll_link, linkp, DLMGMT_ACTIVE);
1370 }
1371
1372 static void
1373 dlmgmt_db_walk(zoneid_t zoneid, datalink_class_t class, db_walk_func_t *func)
1374 {
1375 dlmgmt_link_t *linkp;
1376
1377 for (linkp = avl_first(&dlmgmt_id_avl); linkp != NULL;
1378 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp)) {
1379 if (linkp->ll_zoneid == zoneid && (linkp->ll_class & class))
1380 func(linkp);
1381 }
1382 }
1383
1384 /*
1385 * Initialize the datalink <link name, linkid> mapping and the link's
1386 * attributes list based on the configuration file /etc/dladm/datalink.conf
1387 * and the active configuration cache file
1388 * /etc/svc/volatile/dladm/datalink-management:default.cache.
1389 */
1390 int
1391 dlmgmt_db_init(zoneid_t zoneid)
1392 {
1393 dlmgmt_db_req_t *req;
1394 int err;
1395 boolean_t boot = B_FALSE;
1396
1397 if ((req = dlmgmt_db_req_alloc(DLMGMT_DB_OP_READ, NULL,
1398 DATALINK_INVALID_LINKID, zoneid, DLMGMT_ACTIVE, &err)) == NULL)
1399 return (err);
1400
1401 if ((err = dlmgmt_process_db_req(req)) != 0) {
1402 /*
1403 * If we get back ENOENT, that means that the active
1404 * configuration file doesn't exist yet, and is not an error.
1405 * We'll create it down below after we've loaded the
1406 * persistent configuration.
1407 */
1408 if (err != ENOENT)
1409 goto done;
1410 boot = B_TRUE;
1411 }
1412
1413 req->ls_flags = DLMGMT_PERSIST;
1414 err = dlmgmt_process_db_req(req);
1415 if (err != 0 && err != ENOENT)
1416 goto done;
1417 err = 0;
1418 if (rewrite_needed) {
1419 /*
1420 * First update links in memory, then dump the entire db to
1421 * disk.
1422 */
1423 dlmgmt_db_walk(zoneid, DATALINK_CLASS_ALL, dlmgmt_db_upgrade);
1424 req->ls_op = DLMGMT_DB_OP_WRITE;
1425 req->ls_linkid = DATALINK_ALL_LINKID;
1426 if ((err = dlmgmt_process_db_req(req)) != 0 &&
1427 err != EINPROGRESS)
1428 goto done;
1429 }
1430 if (boot) {
1431 dlmgmt_db_walk(zoneid, DATALINK_CLASS_PHYS,
1432 dlmgmt_db_phys_activate);
1433 }
1434
1435 done:
1436 if (err == EINPROGRESS)
1437 err = 0;
1438 else
1439 free(req);
1440 return (err);
1441 }
1442
1443 /*
1444 * Remove all links in the given zoneid.
1445 */
1446 void
1447 dlmgmt_db_fini(zoneid_t zoneid)
1448 {
1449 dlmgmt_link_t *linkp = avl_first(&dlmgmt_name_avl), *next_linkp;
1450
1451 while (linkp != NULL) {
1452 next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp);
1453 if (linkp->ll_zoneid == zoneid) {
1454 (void) dlmgmt_destroy_common(linkp,
1455 DLMGMT_ACTIVE | DLMGMT_PERSIST);
1456 }
1457 linkp = next_linkp;
1458 }
1459 }
|
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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2015, Joyent Inc.
25 */
26
27 #include <assert.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <syslog.h>
36 #include <zone.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <stropts.h>
40 #include <sys/conf.h>
41 #include <pthread.h>
42 #include <unistd.h>
43 #include <wait.h>
44 #include <libcontract.h>
45 #include <libcontract_priv.h>
46 #include <sys/contract/process.h>
47 #include <sys/vnic.h>
48 #include <zone.h>
49 #include "dlmgmt_impl.h"
50
51 typedef enum dlmgmt_db_op {
52 DLMGMT_DB_OP_WRITE,
53 DLMGMT_DB_OP_DELETE,
54 DLMGMT_DB_OP_READ
55 } dlmgmt_db_op_t;
56
57 typedef struct dlmgmt_db_req_s {
58 struct dlmgmt_db_req_s *ls_next;
59 dlmgmt_db_op_t ls_op;
60 char ls_link[MAXLINKNAMELEN];
61 datalink_id_t ls_linkid;
62 zoneid_t ls_zoneid;
63 uint32_t ls_flags; /* Either DLMGMT_ACTIVE or */
64 /* DLMGMT_PERSIST, not both. */
65 } dlmgmt_db_req_t;
66
67 /*
68 * List of pending db updates (e.g., because of a read-only filesystem).
700 assert(dlmgmt_db_req_head == NULL);
701 dlmgmt_db_req_tail = NULL;
702 }
703 free(req);
704 }
705
706 dlmgmt_table_unlock();
707 return (NULL);
708 }
709
710 static int
711 parse_linkprops(char *buf, dlmgmt_link_t *linkp)
712 {
713 boolean_t found_type = B_FALSE;
714 dladm_datatype_t type = DLADM_TYPE_STR;
715 int i, len;
716 char *curr;
717 char attr_name[MAXLINKATTRLEN];
718 size_t attr_buf_len = 0;
719 void *attr_buf = NULL;
720 boolean_t rename;
721
722 curr = buf;
723 len = strlen(buf);
724 attr_name[0] = '\0';
725 for (i = 0; i < len; i++) {
726 char c = buf[i];
727 boolean_t match = (c == '=' ||
728 (c == ',' && !found_type) || c == ';');
729
730 rename = B_FALSE;
731 /*
732 * Move to the next character if there is no match and
733 * if we have not reached the last character.
734 */
735 if (!match && i != len - 1)
736 continue;
737
738 if (match) {
739 /*
740 * NUL-terminate the string pointed to by 'curr'.
741 */
742 buf[i] = '\0';
743 if (*curr == '\0')
744 goto parse_fail;
745 }
746
747 if (attr_name[0] != '\0' && found_type) {
748 /*
749 * We get here after we have processed the "<prop>="
750 * pattern. The pattern we are now interested in is
756 if (strcmp(attr_name, "linkid") == 0) {
757 if (read_int64(curr, &attr_buf) == 0)
758 goto parse_fail;
759 linkp->ll_linkid =
760 (datalink_class_t)*(int64_t *)attr_buf;
761 } else if (strcmp(attr_name, "name") == 0) {
762 if (read_str(curr, &attr_buf) == 0)
763 goto parse_fail;
764 (void) snprintf(linkp->ll_link,
765 MAXLINKNAMELEN, "%s", attr_buf);
766 } else if (strcmp(attr_name, "class") == 0) {
767 if (read_int64(curr, &attr_buf) == 0)
768 goto parse_fail;
769 linkp->ll_class =
770 (datalink_class_t)*(int64_t *)attr_buf;
771 } else if (strcmp(attr_name, "media") == 0) {
772 if (read_int64(curr, &attr_buf) == 0)
773 goto parse_fail;
774 linkp->ll_media =
775 (uint32_t)*(int64_t *)attr_buf;
776 } else if (strcmp(attr_name, "zone") == 0) {
777 if (read_str(curr, &attr_buf) == 0)
778 goto parse_fail;
779 linkp->ll_zoneid = getzoneidbyname(attr_buf);
780 if (linkp->ll_zoneid == -1) {
781 if (errno == EFAULT)
782 abort();
783 /*
784 * If we can't find the zone, assign the
785 * link to the GZ and mark it for being
786 * renamed.
787 */
788 linkp->ll_zoneid = 0;
789 rename = B_TRUE;
790 }
791 } else {
792 attr_buf_len = translators[type].read_func(curr,
793 &attr_buf);
794 if (attr_buf_len == 0)
795 goto parse_fail;
796
797 if (linkattr_set(&(linkp->ll_head), attr_name,
798 attr_buf, attr_buf_len, type) != 0) {
799 free(attr_buf);
800 goto parse_fail;
801 }
802 }
803
804 free(attr_buf);
805 attr_name[0] = '\0';
806 found_type = B_FALSE;
807 } else if (attr_name[0] != '\0') {
808 /*
809 * Non-zero length attr_name and found_type of false
810 * indicates that we have not found the type for this
814 for (type = 0; type < ntranslators; type++) {
815 if (strcmp(curr,
816 translators[type].type_name) == 0) {
817 found_type = B_TRUE;
818 break;
819 }
820 }
821
822 if (!found_type)
823 goto parse_fail;
824 } else {
825 /*
826 * A zero length attr_name indicates we are looking
827 * at the beginning of a link attribute.
828 */
829 if (c != '=')
830 goto parse_fail;
831
832 (void) snprintf(attr_name, MAXLINKATTRLEN, "%s", curr);
833 }
834
835 /*
836 * The zone that this link belongs to has died, we are
837 * reparenting it to the GZ and renaming it to avoid name
838 * collisions.
839 */
840 if (rename == B_TRUE) {
841 (void) snprintf(linkp->ll_link, MAXLINKNAMELEN,
842 "SUNWorphan%u", (uint16_t)(gethrtime() / 1000));
843 }
844 curr = buf + i + 1;
845 }
846
847 /* Correct any erroneous IPTUN datalink class constant in the file */
848 if (linkp->ll_class == 0x60) {
849 linkp->ll_class = DATALINK_CLASS_IPTUN;
850 rewrite_needed = B_TRUE;
851 }
852
853 return (0);
854
855 parse_fail:
856 /*
857 * Free linkp->ll_head (link attribute list)
858 */
859 linkattr_destroy(linkp);
860 return (-1);
861 }
862
863 static boolean_t
1235
1236 return (err);
1237 }
1238
1239 /*
1240 * Generate an entry in the link database.
1241 * Each entry has this format:
1242 * <link name> <prop0>=<type>,<val>;...;<propn>=<type>,<val>;
1243 */
1244 static void
1245 generate_link_line(dlmgmt_link_t *linkp, boolean_t persist, char *buf)
1246 {
1247 char tmpbuf[MAXLINELEN];
1248 char *ptr = tmpbuf;
1249 char *lim = tmpbuf + MAXLINELEN;
1250 dlmgmt_linkattr_t *cur_p = NULL;
1251 uint64_t u64;
1252
1253 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", linkp->ll_link);
1254 if (!persist) {
1255 char zname[ZONENAME_MAX];
1256 /*
1257 * We store the linkid and the zone name in the active database
1258 * so that dlmgmtd can recover in the event that it is
1259 * restarted.
1260 */
1261 u64 = linkp->ll_linkid;
1262 ptr += write_uint64(ptr, BUFLEN(lim, ptr), "linkid", &u64);
1263
1264 if (getzonenamebyid(linkp->ll_zoneid, zname,
1265 sizeof (zname)) != -1) {
1266 ptr += write_str(ptr, BUFLEN(lim, ptr), "zone", zname);
1267 }
1268 }
1269 u64 = linkp->ll_class;
1270 ptr += write_uint64(ptr, BUFLEN(lim, ptr), "class", &u64);
1271 u64 = linkp->ll_media;
1272 ptr += write_uint64(ptr, BUFLEN(lim, ptr), "media", &u64);
1273
1274 /*
1275 * The daemon does not keep any active link attribute. Only store the
1276 * attributes if this request is for persistent configuration,
1277 */
1278 if (persist) {
1279 for (cur_p = linkp->ll_head; cur_p != NULL;
1280 cur_p = cur_p->lp_next) {
1281 ptr += translators[cur_p->lp_type].write_func(ptr,
1282 BUFLEN(lim, ptr), cur_p->lp_name, cur_p->lp_val);
1283 }
1284 }
1285
1286 if (ptr <= lim)
1287 (void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
1288 }
1402 static void
1403 dlmgmt_db_phys_activate(dlmgmt_link_t *linkp)
1404 {
1405 linkp->ll_flags |= DLMGMT_ACTIVE;
1406 (void) dlmgmt_write_db_entry(linkp->ll_link, linkp, DLMGMT_ACTIVE);
1407 }
1408
1409 static void
1410 dlmgmt_db_walk(zoneid_t zoneid, datalink_class_t class, db_walk_func_t *func)
1411 {
1412 dlmgmt_link_t *linkp;
1413
1414 for (linkp = avl_first(&dlmgmt_id_avl); linkp != NULL;
1415 linkp = AVL_NEXT(&dlmgmt_id_avl, linkp)) {
1416 if (linkp->ll_zoneid == zoneid && (linkp->ll_class & class))
1417 func(linkp);
1418 }
1419 }
1420
1421 /*
1422 * Attempt to mitigate one of the deadlocks in the dlmgmtd architecture.
1423 *
1424 * dlmgmt_db_init() calls dlmgmt_process_db_req() which eventually gets to
1425 * dlmgmt_zfop() which tries to fork, enter the zone and read the file.
1426 * Because of the upcall architecture of dlmgmtd this can lead to deadlock
1427 * with the following scenario:
1428 * a) the thread preparing to fork will have acquired the malloc locks
1429 * then attempt to suspend every thread in preparation to fork.
1430 * b) all of the upcalls will be blocked in door_ucred() trying to malloc()
1431 * and get the credentials of their caller.
1432 * c) we can't suspend the in-kernel thread making the upcall.
1433 *
1434 * Thus, we cannot serve door requests because we're blocked in malloc()
1435 * which fork() owns, but fork() is in turn blocked on the in-kernel thread
1436 * making the door upcall. This is a fundamental architectural problem with
1437 * any server handling upcalls and also trying to fork().
1438 *
1439 * To minimize the chance of this deadlock occuring, we check ahead of time to
1440 * see if the file we want to read actually exists in the zone (which it almost
1441 * never does), so we don't need fork in that case (i.e. rarely to never).
1442 */
1443 static boolean_t
1444 zone_file_exists(char *zoneroot, char *filename)
1445 {
1446 struct stat sb;
1447 char fname[MAXPATHLEN];
1448
1449 (void) snprintf(fname, sizeof (fname), "%s/%s", zoneroot, filename);
1450
1451 if (stat(fname, &sb) == -1)
1452 return (B_FALSE);
1453
1454 return (B_TRUE);
1455 }
1456
1457 /*
1458 * Initialize the datalink <link name, linkid> mapping and the link's
1459 * attributes list based on the configuration file /etc/dladm/datalink.conf
1460 * and the active configuration cache file
1461 * /etc/svc/volatile/dladm/datalink-management:default.cache.
1462 */
1463 int
1464 dlmgmt_db_init(zoneid_t zoneid, char *zoneroot)
1465 {
1466 dlmgmt_db_req_t *req;
1467 int err;
1468 boolean_t boot = B_FALSE;
1469 char tdir[MAXPATHLEN];
1470 char *path = cachefile;
1471
1472 if ((req = dlmgmt_db_req_alloc(DLMGMT_DB_OP_READ, NULL,
1473 DATALINK_INVALID_LINKID, zoneid, DLMGMT_ACTIVE, &err)) == NULL)
1474 return (err);
1475
1476 /* Handle running in a non-native branded zone (i.e. has /native) */
1477 if (zone_file_exists(zoneroot, "/native" DLMGMT_TMPFS_DIR)) {
1478 (void) snprintf(tdir, sizeof (tdir), "/native%s", cachefile);
1479 path = tdir;
1480 }
1481
1482 if (zone_file_exists(zoneroot, path)) {
1483 if ((err = dlmgmt_process_db_req(req)) != 0) {
1484 /*
1485 * If we get back ENOENT, that means that the active
1486 * configuration file doesn't exist yet, and is not an
1487 * error. We'll create it down below after we've
1488 * loaded the persistent configuration.
1489 */
1490 if (err != ENOENT)
1491 goto done;
1492 boot = B_TRUE;
1493 }
1494 } else {
1495 boot = B_TRUE;
1496 }
1497
1498 req->ls_flags = DLMGMT_PERSIST;
1499 err = dlmgmt_process_db_req(req);
1500 if (err != 0 && err != ENOENT)
1501 goto done;
1502 err = 0;
1503 if (rewrite_needed) {
1504 /*
1505 * First update links in memory, then dump the entire db to
1506 * disk.
1507 */
1508 dlmgmt_db_walk(zoneid, DATALINK_CLASS_ALL, dlmgmt_db_upgrade);
1509 req->ls_op = DLMGMT_DB_OP_WRITE;
1510 req->ls_linkid = DATALINK_ALL_LINKID;
1511 if ((err = dlmgmt_process_db_req(req)) != 0 &&
1512 err != EINPROGRESS)
1513 goto done;
1514 }
1515 if (boot) {
1516 dlmgmt_db_walk(zoneid, DATALINK_CLASS_PHYS,
1517 dlmgmt_db_phys_activate);
1518 }
1519
1520 done:
1521 if (err == EINPROGRESS)
1522 err = 0;
1523 else
1524 free(req);
1525 return (err);
1526 }
1527
1528 /*
1529 * Remove all links in the given zoneid.
1530 *
1531 * We do this work in two different passes. In the first pass, we remove any
1532 * entry that hasn't been loaned and mark every entry that has been loaned as
1533 * something that is going to be tombstomed. In the second pass, we drop the
1534 * table lock for every entry and remove the tombstombed entry for our zone.
1535 */
1536 void
1537 dlmgmt_db_fini(zoneid_t zoneid)
1538 {
1539 dlmgmt_link_t *linkp = avl_first(&dlmgmt_name_avl), *next_linkp;
1540
1541 while (linkp != NULL) {
1542 next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp);
1543 if (linkp->ll_zoneid == zoneid) {
1544 boolean_t onloan = linkp->ll_onloan;
1545
1546 /*
1547 * Cleanup any VNICs that were loaned to the zone
1548 * before the zone goes away and we can no longer
1549 * refer to the VNIC by the name/zoneid.
1550 */
1551 if (onloan) {
1552 (void) dlmgmt_delete_db_entry(linkp,
1553 DLMGMT_ACTIVE);
1554 linkp->ll_tomb = B_TRUE;
1555 } else {
1556 (void) dlmgmt_destroy_common(linkp,
1557 DLMGMT_ACTIVE | DLMGMT_PERSIST);
1558 }
1559 }
1560 linkp = next_linkp;
1561 }
1562
1563 again:
1564 linkp = avl_first(&dlmgmt_name_avl);
1565 while (linkp != NULL) {
1566 vnic_ioc_delete_t ioc;
1567
1568 next_linkp = AVL_NEXT(&dlmgmt_name_avl, linkp);
1569
1570 if (linkp->ll_zoneid != zoneid) {
1571 linkp = next_linkp;
1572 continue;
1573 }
1574 ioc.vd_vnic_id = linkp->ll_linkid;
1575 if (linkp->ll_tomb != B_TRUE)
1576 abort();
1577
1578 /*
1579 * We have to drop the table lock while going up into the
1580 * kernel. If we hold the table lock while deleting a vnic, we
1581 * may get blocked on the mac perimeter and the holder of it may
1582 * want something from dlmgmtd.
1583 */
1584 dlmgmt_table_unlock();
1585
1586 if (ioctl(dladm_dld_fd(dld_handle),
1587 VNIC_IOC_DELETE, &ioc) < 0)
1588 dlmgmt_log(LOG_WARNING, "dlmgmt_db_fini "
1589 "delete VNIC ioctl failed %d %d",
1590 ioc.vd_vnic_id, errno);
1591
1592 /*
1593 * Even though we've dropped the lock, we know that nothing else
1594 * could have removed us. Therefore, it should be safe to go
1595 * through and delete ourselves, but do nothing else. We'll have
1596 * to restart iteration from the beginning. This can be painful.
1597 */
1598 dlmgmt_table_lock(B_TRUE);
1599
1600 (void) dlmgmt_destroy_common(linkp,
1601 DLMGMT_ACTIVE | DLMGMT_PERSIST);
1602 goto again;
1603 }
1604
1605 }
|