dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libdiskmgt / common / inuse_mnt.c
bloba0c921c9a7515040d7b9f543ebc892140b56de81
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Creates and maintains a cache of mount points.
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <synch.h>
34 #include <thread.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <sys/mnttab.h>
40 #include <sys/swap.h>
42 #include "libdiskmgt.h"
43 #include "disks_private.h"
46 * The list of mount point entries in /etc/mnttab
49 struct mntpnt_list {
50 struct mntpnt_list *next;
51 char *special;
52 char *mountp;
55 static struct mntpnt_list *mntpoint_listp = NULL;
56 static rwlock_t mntpoint_lock = DEFAULTRWLOCK;
57 static int initialized = 0;
58 static mutex_t init_lock = DEFAULTMUTEX;
60 static boolean_t diff_mnttab(int send_event, struct mntpnt_list *firstp,
61 struct mntpnt_list *secondp);
62 static void free_mnttab(struct mntpnt_list *listp);
63 static boolean_t in_list(struct mntpnt_list *elementp,
64 struct mntpnt_list *listp);
65 static int load_mnttab(int send_event);
66 static void watch_mnttab();
69 * Search the list of devices from /etc/mnttab to find the mount point
70 * for the specified device.
72 int
73 inuse_mnt(char *slice, nvlist_t *attrs, int *errp)
75 struct mntpnt_list *listp;
76 int found = 0;
78 *errp = 0;
79 if (slice == NULL) {
80 return (found);
83 (void) mutex_lock(&init_lock);
84 if (!initialized) {
85 thread_t mnttab_thread;
87 /* load the mntpnt cache */
88 *errp = load_mnttab(B_FALSE);
90 if (*errp == 0) {
91 /* start a thread to monitor the mnttab */
92 *errp = thr_create(NULL, 0, (void *(*)(void *))watch_mnttab,
93 NULL, THR_NEW_LWP | THR_DAEMON, &mnttab_thread);
96 if (*errp == 0) {
97 initialized = 1;
100 (void) mutex_unlock(&init_lock);
102 (void) rw_rdlock(&mntpoint_lock);
103 listp = mntpoint_listp;
104 while (listp != NULL) {
105 if (libdiskmgt_str_eq(slice, listp->special)) {
106 libdiskmgt_add_str(attrs, DM_USED_BY, DM_USE_MOUNT, errp);
107 libdiskmgt_add_str(attrs, DM_USED_NAME, listp->mountp, errp);
108 found = 1;
109 break;
111 listp = listp->next;
113 (void) rw_unlock(&mntpoint_lock);
115 return (found);
119 * Return true if the lists are different. Send an event for each different
120 * device.
122 static boolean_t
123 diff_mnttab(int send_event, struct mntpnt_list *firstp,
124 struct mntpnt_list *secondp)
126 boolean_t different = B_FALSE;
127 struct mntpnt_list *listp;
129 listp = firstp;
130 while (listp != NULL) {
131 if (! in_list(listp, secondp)) {
132 /* not in new list, so was mounted and now unmounted */
133 if (send_event) {
134 events_new_slice_event(listp->special, DM_EV_TCHANGE);
136 different = B_TRUE;
138 listp = listp->next;
141 listp = secondp;
142 while (listp != NULL) {
143 if (! in_list(listp, firstp)) {
144 /* not in orig list, so this is a new mount */
145 if (send_event) {
146 events_new_slice_event(listp->special, DM_EV_TCHANGE);
148 different = B_TRUE;
150 listp = listp->next;
153 return (different);
157 * free_mnttab()
159 * Free the list of metadevices from /etc/mnttab.
161 static void
162 free_mnttab(struct mntpnt_list *listp) {
164 struct mntpnt_list *nextp;
166 while (listp != NULL) {
167 nextp = listp->next;
168 free((void *)listp->special);
169 free((void *)listp->mountp);
170 free((void *)listp);
171 listp = nextp;
176 * Return true if the element is in the list.
178 static boolean_t
179 in_list(struct mntpnt_list *elementp, struct mntpnt_list *listp)
181 while (listp != NULL) {
182 if (libdiskmgt_str_eq(elementp->special, listp->special) &&
183 libdiskmgt_str_eq(elementp->mountp, listp->mountp)) {
184 return (B_TRUE);
186 listp = listp->next;
189 return (B_FALSE);
193 * load_mnttab()
195 * Create a list of devices from /etc/mnttab and swap.
196 * return 1 if the list has changed, 0 if the list is still the same
198 static int
199 load_mnttab(int send_event)
202 struct mntpnt_list *currp;
203 FILE *fp;
204 struct mntpnt_list *headp;
205 int num;
206 struct mntpnt_list *prevp;
207 struct swaptable *st;
208 struct swapent *swapent;
209 int err;
210 int i;
212 headp = NULL;
213 prevp = NULL;
215 /* get the mnttab entries */
216 if ((fp = fopen("/etc/mnttab", "r")) != NULL) {
218 struct mnttab entry;
220 while (getmntent(fp, &entry) == 0) {
223 * Ignore entries that are incomplete or that are not
224 * devices (skips network mounts, automounter entries,
225 * /proc, etc.).
227 if (entry.mnt_special == NULL ||
228 entry.mnt_mountp == NULL ||
229 strncmp(entry.mnt_special, "/dev", 4) != 0) {
230 continue;
233 currp = (struct mntpnt_list *)calloc((size_t)1,
234 (size_t)sizeof (struct mntpnt_list));
236 if (currp == NULL) {
238 * out of memory, free what we have and return
240 free_mnttab(headp);
241 (void) fclose(fp);
242 return (ENOMEM);
245 if (headp == NULL) {
246 headp = currp;
247 } else {
248 prevp->next = currp;
251 currp->next = NULL;
253 currp->special = strdup(entry.mnt_special);
254 if (currp->special == NULL) {
256 * out of memory, free what we have and return
258 free_mnttab(headp);
259 (void) fclose(fp);
260 return (ENOMEM);
263 currp->mountp = strdup(entry.mnt_mountp);
264 if (currp->mountp == NULL) {
266 * out of memory, free what we have and return
268 free_mnttab(headp);
269 (void) fclose(fp);
270 return (ENOMEM);
273 prevp = currp;
276 (void) fclose(fp);
279 /* get the swap entries */
280 num = dm_get_swapentries(&st, &err);
281 if (num < 0) {
282 free_mnttab(headp);
283 return (ENOMEM);
286 for (i = 0, swapent = st->swt_ent; i < num; i++, swapent++) {
287 char fullpath[MAXPATHLEN+1];
289 currp = (struct mntpnt_list *)
290 calloc((size_t)1, (size_t)sizeof (struct mntpnt_list));
292 if (currp == NULL) {
293 /* out of memory, free what we have and return */
294 dm_free_swapentries(st);
295 free_mnttab(headp);
296 return (ENOMEM);
299 if (headp == NULL) {
300 headp = currp;
301 } else {
302 prevp->next = currp;
305 currp->next = NULL;
307 if (*swapent->ste_path != '/') {
308 (void) snprintf(fullpath, sizeof (fullpath), "/dev/%s",
309 swapent->ste_path);
310 } else {
311 (void) strlcpy(fullpath, swapent->ste_path,
312 sizeof (fullpath));
315 currp->special = strdup(fullpath);
316 if (currp->special == NULL) {
317 /* out of memory, free what we have and return */
318 dm_free_swapentries(st);
319 free_mnttab(headp);
320 return (ENOMEM);
323 currp->mountp = strdup("swap");
324 if (currp->mountp == NULL) {
325 /* out of memory, free what we have and return */
326 dm_free_swapentries(st);
327 free_mnttab(headp);
328 return (ENOMEM);
331 prevp = currp;
333 if (num)
334 dm_free_swapentries(st);
336 /* note that we unlock the mutex in both paths of this if statement */
337 (void) rw_wrlock(&mntpoint_lock);
338 if (diff_mnttab(send_event, mntpoint_listp, headp) == B_TRUE) {
339 struct mntpnt_list *tmpp;
341 tmpp = mntpoint_listp;
342 mntpoint_listp = headp;
343 (void) rw_unlock(&mntpoint_lock);
345 /* free the old list */
346 free_mnttab(tmpp);
347 } else {
348 (void) rw_unlock(&mntpoint_lock);
349 /* no change that we care about, so keep the current list */
350 free_mnttab(headp);
352 return (0);
356 * This is a thread that runs forever, watching for changes in the mnttab
357 * that would cause us to flush and reload the cache of mnt entries. Only
358 * changes to /dev devices will cause the cache to be flushed and reloaded.
360 static void
361 watch_mnttab()
363 struct pollfd fds[1];
364 int res;
366 if ((fds[0].fd = open("/etc/mnttab", O_RDONLY)) != -1) {
368 char buf[81];
370 /* do the initial read so we don't get the event right away */
371 (void) read(fds[0].fd, buf, (size_t)(sizeof (buf) - 1));
372 (void) lseek(fds[0].fd, 0, SEEK_SET);
374 fds[0].events = POLLRDBAND;
375 while (res = poll(fds, (nfds_t)1, -1)) {
376 if (res <= 0)
377 continue;
379 (void) load_mnttab(B_TRUE);
381 (void) read(fds[0].fd, buf, (size_t)(sizeof (buf) - 1));
382 (void) lseek(fds[0].fd, 0, SEEK_SET);