dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libdiskmgt / common / inuse_lu.c
blob48d2089de5e3b972c1526905ece19479c5a24551
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Creates and maintains a short-term cache of live upgrade slices.
33 #include <dirent.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <synch.h>
38 #include <sys/errno.h>
39 #include <sys/param.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43 #include <sys/types.h>
44 #include <sys/wait.h>
46 #include "libdiskmgt.h"
47 #include "disks_private.h"
49 #define TMPNM_SIZE 25
52 * The list of live upgrade slices in use.
55 struct lu_list {
56 struct lu_list *next;
57 char *slice;
58 char *name;
61 static struct lu_list *lu_listp = NULL;
62 static time_t timestamp = 0;
63 static mutex_t lu_lock = DEFAULTMUTEX;
65 static int add_use_record(char *devname, char *name);
66 static void free_lu(struct lu_list *listp);
67 static int load_lu();
68 static int lustatus(int fd);
69 static int lufslist(int fd);
70 static int run_cmd(char *path, char *cmd, char *arg, int fd);
73 * Search the list of devices under live upgrade for the specified device.
75 int
76 inuse_lu(char *slice, nvlist_t *attrs, int *errp)
78 int found = 0;
79 time_t curr_time;
81 *errp = 0;
83 if (slice == NULL) {
84 return (found);
88 * We don't want to have to re-read the live upgrade config for
89 * every slice, but we can't just cache it since there is no event
90 * when this changes. So, we'll keep the config in memory for
91 * a short time (1 minute) before reloading it.
93 (void) mutex_lock(&lu_lock);
95 curr_time = time(NULL);
96 if (timestamp < curr_time && (curr_time - timestamp) > 60) {
97 free_lu(lu_listp); /* free old entries */
98 lu_listp = NULL;
99 *errp = load_lu(); /* load the cache */
100 timestamp = curr_time;
103 if (*errp == 0) {
104 struct lu_list *listp;
106 listp = lu_listp;
107 while (listp != NULL) {
108 if (strcmp(slice, listp->slice) == 0) {
109 libdiskmgt_add_str(attrs, DM_USED_BY, DM_USE_LU, errp);
110 libdiskmgt_add_str(attrs, DM_USED_NAME, listp->name, errp);
111 found = 1;
112 break;
114 listp = listp->next;
118 (void) mutex_unlock(&lu_lock);
120 return (found);
123 static int
124 add_use_record(char *devname, char *name)
126 struct lu_list *sp;
128 sp = (struct lu_list *)malloc(sizeof (struct lu_list));
129 if (sp == NULL) {
130 return (ENOMEM);
133 if ((sp->slice = strdup(devname)) == NULL) {
134 free(sp);
135 return (ENOMEM);
138 if ((sp->name = strdup(name)) == NULL) {
139 free(sp->slice);
140 free(sp);
141 return (ENOMEM);
144 sp->next = lu_listp;
145 lu_listp = sp;
147 return (0);
151 * Free the list of liveupgrade entries.
153 static void
154 free_lu(struct lu_list *listp) {
156 struct lu_list *nextp;
158 while (listp != NULL) {
159 nextp = listp->next;
160 free((void *)listp->slice);
161 free((void *)listp->name);
162 free((void *)listp);
163 listp = nextp;
168 * Create a list of live upgrade devices.
170 static int
171 load_lu()
173 char tmpname[TMPNM_SIZE];
174 int fd;
175 int status = 0;
177 (void) strlcpy(tmpname, "/var/run/dm_lu_XXXXXX", TMPNM_SIZE);
178 if ((fd = mkstemp(tmpname)) != -1) {
179 (void) unlink(tmpname);
180 if (run_cmd("/usr/sbin/lustatus", "lustatus", NULL, fd)) {
181 status = lustatus(fd);
182 } else {
183 (void) close(fd);
187 return (status);
191 * The XML generated by the live upgrade commands is not parseable by the
192 * standard Solaris XML parser, so we have to do it ourselves.
194 static int
195 lufslist(int fd)
197 FILE *fp;
198 char line[MAXPATHLEN];
199 int status;
201 if ((fp = fdopen(fd, "r")) == NULL) {
202 (void) close(fd);
203 return (0);
206 (void) fseek(fp, 0L, SEEK_SET);
207 while (fgets(line, sizeof (line), fp) == line) {
208 char *devp;
209 char *nmp;
210 char *ep;
212 if (strncmp(line, "<beFsComponent ", 15) != 0) {
213 continue;
216 if ((devp = strstr(line, "fsDevice=\"")) == NULL) {
217 continue;
220 devp = devp + 10;
222 if ((ep = strchr(devp, '"')) == NULL) {
223 continue;
226 *ep = 0;
228 /* try to get the mountpoint name */
229 if ((nmp = strstr(ep + 1, "mountPoint=\"")) != NULL) {
230 nmp = nmp + 12;
232 if ((ep = strchr(nmp, '"')) != NULL) {
233 *ep = 0;
234 } else {
235 nmp = "";
238 } else {
239 nmp = "";
242 if ((status = add_use_record(devp, nmp)) != 0) {
243 break;
247 (void) fclose(fp);
249 return (status);
252 static int
253 lustatus(int fd)
255 FILE *fp;
256 char line[MAXPATHLEN];
257 int status = 0;
259 if ((fp = fdopen(fd, "r")) == NULL) {
260 (void) close(fd);
261 return (0);
264 (void) fseek(fp, 0L, SEEK_SET);
265 while (fgets(line, sizeof (line), fp) == line) {
266 char *sp;
267 char *ep;
268 char tmpname[TMPNM_SIZE];
269 int ffd;
271 if (strncmp(line, "<beStatus ", 10) != 0) {
272 continue;
275 if ((sp = strstr(line, "name=\"")) == NULL) {
276 continue;
279 sp = sp + 6;
281 if ((ep = strchr(sp, '"')) == NULL) {
282 continue;
285 *ep = 0;
287 (void) strlcpy(tmpname, "/var/run/dm_lu_XXXXXX", TMPNM_SIZE);
288 if ((ffd = mkstemp(tmpname)) != -1) {
289 (void) unlink(tmpname);
291 if (run_cmd("/usr/sbin/lufslist", "lufslist", sp, ffd) == 0) {
292 (void) close(ffd);
293 break;
296 if ((status = lufslist(ffd)) != 0) {
297 break;
302 (void) fclose(fp);
304 return (status);
307 static int
308 run_cmd(char *path, char *cmd, char *arg, int fd)
310 pid_t pid;
311 int loc;
313 /* create the server process */
314 switch ((pid = fork1())) {
315 case 0:
316 /* child process */
317 (void) close(1);
318 (void) dup(fd);
319 (void) close(2);
320 (void) dup(fd);
321 closefrom(3);
322 (void) execl(path, cmd, "-X", arg, NULL);
323 _exit(1);
324 break;
326 case -1:
327 return (0);
329 default:
330 /* parent process */
331 break;
334 (void) waitpid(pid, &loc, 0);
336 /* printf("got 0x%x %d %d\n", loc, WIFEXITED(loc), WEXITSTATUS(loc)); */
338 if (WIFEXITED(loc) && WEXITSTATUS(loc) == 0) {
339 return (1);
342 return (0);