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.
27 * Creates and maintains a cache of mount points.
36 #include <sys/types.h>
39 #include <sys/mnttab.h>
42 #include "libdiskmgt.h"
43 #include "disks_private.h"
46 * The list of mount point entries in /etc/mnttab
50 struct mntpnt_list
*next
;
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.
73 inuse_mnt(char *slice
, nvlist_t
*attrs
, int *errp
)
75 struct mntpnt_list
*listp
;
83 (void) mutex_lock(&init_lock
);
85 thread_t mnttab_thread
;
87 /* load the mntpnt cache */
88 *errp
= load_mnttab(B_FALSE
);
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
);
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
);
113 (void) rw_unlock(&mntpoint_lock
);
119 * Return true if the lists are different. Send an event for each different
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
;
130 while (listp
!= NULL
) {
131 if (! in_list(listp
, secondp
)) {
132 /* not in new list, so was mounted and now unmounted */
134 events_new_slice_event(listp
->special
, DM_EV_TCHANGE
);
142 while (listp
!= NULL
) {
143 if (! in_list(listp
, firstp
)) {
144 /* not in orig list, so this is a new mount */
146 events_new_slice_event(listp
->special
, DM_EV_TCHANGE
);
159 * Free the list of metadevices from /etc/mnttab.
162 free_mnttab(struct mntpnt_list
*listp
) {
164 struct mntpnt_list
*nextp
;
166 while (listp
!= NULL
) {
168 free((void *)listp
->special
);
169 free((void *)listp
->mountp
);
176 * Return true if the element is in the list.
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
)) {
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
199 load_mnttab(int send_event
)
202 struct mntpnt_list
*currp
;
204 struct mntpnt_list
*headp
;
206 struct mntpnt_list
*prevp
;
207 struct swaptable
*st
;
208 struct swapent
*swapent
;
215 /* get the mnttab entries */
216 if ((fp
= fopen("/etc/mnttab", "r")) != NULL
) {
220 while (getmntent(fp
, &entry
) == 0) {
223 * Ignore entries that are incomplete or that are not
224 * devices (skips network mounts, automounter entries,
227 if (entry
.mnt_special
== NULL
||
228 entry
.mnt_mountp
== NULL
||
229 strncmp(entry
.mnt_special
, "/dev", 4) != 0) {
233 currp
= (struct mntpnt_list
*)calloc((size_t)1,
234 (size_t)sizeof (struct mntpnt_list
));
238 * out of memory, free what we have and return
253 currp
->special
= strdup(entry
.mnt_special
);
254 if (currp
->special
== NULL
) {
256 * out of memory, free what we have and return
263 currp
->mountp
= strdup(entry
.mnt_mountp
);
264 if (currp
->mountp
== NULL
) {
266 * out of memory, free what we have and return
279 /* get the swap entries */
280 num
= dm_get_swapentries(&st
, &err
);
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
));
293 /* out of memory, free what we have and return */
294 dm_free_swapentries(st
);
307 if (*swapent
->ste_path
!= '/') {
308 (void) snprintf(fullpath
, sizeof (fullpath
), "/dev/%s",
311 (void) strlcpy(fullpath
, swapent
->ste_path
,
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
);
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
);
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 */
348 (void) rw_unlock(&mntpoint_lock
);
349 /* no change that we care about, so keep the current list */
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.
363 struct pollfd fds
[1];
366 if ((fds
[0].fd
= open("/etc/mnttab", O_RDONLY
)) != -1) {
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)) {
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
);