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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Creates and maintains a cache of mount points.
38 #include <sys/types.h>
41 #include <sys/mnttab.h>
44 #include "libdiskmgt.h"
45 #include "disks_private.h"
48 * The list of mount point entries in /etc/mnttab
52 struct mntpnt_list
*next
;
57 static struct mntpnt_list
*mntpoint_listp
= NULL
;
58 static rwlock_t mntpoint_lock
= DEFAULTRWLOCK
;
59 static int initialized
= 0;
60 static mutex_t init_lock
= DEFAULTMUTEX
;
62 static boolean_t
diff_mnttab(int send_event
, struct mntpnt_list
*firstp
,
63 struct mntpnt_list
*secondp
);
64 static void free_mnttab(struct mntpnt_list
*listp
);
65 static boolean_t
in_list(struct mntpnt_list
*elementp
,
66 struct mntpnt_list
*listp
);
67 static int load_mnttab(int send_event
);
68 static void watch_mnttab();
71 * Search the list of devices from /etc/mnttab to find the mount point
72 * for the specified device.
75 inuse_mnt(char *slice
, nvlist_t
*attrs
, int *errp
)
77 struct mntpnt_list
*listp
;
85 (void) mutex_lock(&init_lock
);
87 thread_t mnttab_thread
;
89 /* load the mntpnt cache */
90 *errp
= load_mnttab(B_FALSE
);
93 /* start a thread to monitor the mnttab */
94 *errp
= thr_create(NULL
, NULL
, (void *(*)(void *))watch_mnttab
,
95 NULL
, THR_NEW_LWP
| THR_DAEMON
, &mnttab_thread
);
102 (void) mutex_unlock(&init_lock
);
104 (void) rw_rdlock(&mntpoint_lock
);
105 listp
= mntpoint_listp
;
106 while (listp
!= NULL
) {
107 if (libdiskmgt_str_eq(slice
, listp
->special
)) {
108 libdiskmgt_add_str(attrs
, DM_USED_BY
, DM_USE_MOUNT
, errp
);
109 libdiskmgt_add_str(attrs
, DM_USED_NAME
, listp
->mountp
, errp
);
115 (void) rw_unlock(&mntpoint_lock
);
121 * Return true if the lists are different. Send an event for each different
125 diff_mnttab(int send_event
, struct mntpnt_list
*firstp
,
126 struct mntpnt_list
*secondp
)
128 boolean_t different
= B_FALSE
;
129 struct mntpnt_list
*listp
;
132 while (listp
!= NULL
) {
133 if (! in_list(listp
, secondp
)) {
134 /* not in new list, so was mounted and now unmounted */
136 events_new_slice_event(listp
->special
, DM_EV_TCHANGE
);
144 while (listp
!= NULL
) {
145 if (! in_list(listp
, firstp
)) {
146 /* not in orig list, so this is a new mount */
148 events_new_slice_event(listp
->special
, DM_EV_TCHANGE
);
161 * Free the list of metadevices from /etc/mnttab.
164 free_mnttab(struct mntpnt_list
*listp
) {
166 struct mntpnt_list
*nextp
;
168 while (listp
!= NULL
) {
170 free((void *)listp
->special
);
171 free((void *)listp
->mountp
);
178 * Return true if the element is in the list.
181 in_list(struct mntpnt_list
*elementp
, struct mntpnt_list
*listp
)
183 while (listp
!= NULL
) {
184 if (libdiskmgt_str_eq(elementp
->special
, listp
->special
) &&
185 libdiskmgt_str_eq(elementp
->mountp
, listp
->mountp
)) {
197 * Create a list of devices from /etc/mnttab and swap.
198 * return 1 if the list has changed, 0 if the list is still the same
201 load_mnttab(int send_event
)
204 struct mntpnt_list
*currp
;
206 struct mntpnt_list
*headp
;
208 struct mntpnt_list
*prevp
;
209 struct swaptable
*st
;
210 struct swapent
*swapent
;
217 /* get the mnttab entries */
218 if ((fp
= fopen("/etc/mnttab", "r")) != NULL
) {
222 while (getmntent(fp
, &entry
) == 0) {
225 * Ignore entries that are incomplete or that are not
226 * devices (skips network mounts, automounter entries,
229 if (entry
.mnt_special
== NULL
||
230 entry
.mnt_mountp
== NULL
||
231 strncmp(entry
.mnt_special
, "/dev", 4) != 0) {
235 currp
= (struct mntpnt_list
*)calloc((size_t)1,
236 (size_t)sizeof (struct mntpnt_list
));
240 * out of memory, free what we have and return
255 currp
->special
= strdup(entry
.mnt_special
);
256 if (currp
->special
== NULL
) {
258 * out of memory, free what we have and return
265 currp
->mountp
= strdup(entry
.mnt_mountp
);
266 if (currp
->mountp
== NULL
) {
268 * out of memory, free what we have and return
281 /* get the swap entries */
282 num
= dm_get_swapentries(&st
, &err
);
288 for (i
= 0, swapent
= st
->swt_ent
; i
< num
; i
++, swapent
++) {
289 char fullpath
[MAXPATHLEN
+1];
291 currp
= (struct mntpnt_list
*)
292 calloc((size_t)1, (size_t)sizeof (struct mntpnt_list
));
295 /* out of memory, free what we have and return */
296 dm_free_swapentries(st
);
309 if (*swapent
->ste_path
!= '/') {
310 (void) snprintf(fullpath
, sizeof (fullpath
), "/dev/%s",
313 (void) strlcpy(fullpath
, swapent
->ste_path
,
317 currp
->special
= strdup(fullpath
);
318 if (currp
->special
== NULL
) {
319 /* out of memory, free what we have and return */
320 dm_free_swapentries(st
);
325 currp
->mountp
= strdup("swap");
326 if (currp
->mountp
== NULL
) {
327 /* out of memory, free what we have and return */
328 dm_free_swapentries(st
);
336 dm_free_swapentries(st
);
338 /* note that we unlock the mutex in both paths of this if statement */
339 (void) rw_wrlock(&mntpoint_lock
);
340 if (diff_mnttab(send_event
, mntpoint_listp
, headp
) == B_TRUE
) {
341 struct mntpnt_list
*tmpp
;
343 tmpp
= mntpoint_listp
;
344 mntpoint_listp
= headp
;
345 (void) rw_unlock(&mntpoint_lock
);
347 /* free the old list */
350 (void) rw_unlock(&mntpoint_lock
);
351 /* no change that we care about, so keep the current list */
358 * This is a thread that runs forever, watching for changes in the mnttab
359 * that would cause us to flush and reload the cache of mnt entries. Only
360 * changes to /dev devices will cause the cache to be flushed and reloaded.
365 struct pollfd fds
[1];
368 if ((fds
[0].fd
= open("/etc/mnttab", O_RDONLY
)) != -1) {
372 /* do the initial read so we don't get the event right away */
373 (void) read(fds
[0].fd
, buf
, (size_t)(sizeof (buf
) - 1));
374 (void) lseek(fds
[0].fd
, 0, SEEK_SET
);
376 fds
[0].events
= POLLRDBAND
;
377 while (res
= poll(fds
, (nfds_t
)1, -1)) {
381 (void) load_mnttab(B_TRUE
);
383 (void) read(fds
[0].fd
, buf
, (size_t)(sizeof (buf
) - 1));
384 (void) lseek(fds
[0].fd
, 0, SEEK_SET
);