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
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]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
34 #include <sys/types.h>
35 #include <sys/mnttab.h>
36 #include <sys/mntent.h>
38 #include <nfs/nfs_clnt.h>
39 #include <sys/mkdev.h>
54 static char *mntopts
[] = { MNTOPT_IGNORE
, MNTOPT_DEV
, NULL
};
57 * Private method declarations
60 static int ignore(char *);
61 static int get_kstat_info(nfs_mntlist_t
*, int *);
62 static nfs_mntlist_t
*get_mount_data(fs_mntlist_t
*, int *);
63 static nfs_mntlist_t
*get_nfs_info(fs_mntlist_t
*, int *);
64 static nfs_mntlist_t
*kstat_mount(nfs_mntlist_t
*, kstat_t
*);
65 static int load_kstat_data(kstat_ctl_t
*, nfs_mntlist_t
*, kstat_t
*, int *);
66 static kid_t
safe_kstat_read(kstat_ctl_t
*, kstat_t
*, void *, int *);
73 nfs_free_mntinfo_list(nfs_mntlist_t
*list
)
78 while (list
!= NULL
) {
79 free(list
->nml_resource
);
80 free(list
->nml_mountp
);
81 free(list
->nml_fstype
);
82 free(list
->nml_mntopts
);
84 for (i
= 0; i
< list
->nml_failovercount
; i
++) {
85 free(list
->nml_failoverlist
[i
]);
87 free(list
->nml_failoverlist
);
88 free(list
->nml_securitymode
);
93 } /* nfs_free_mntinfo_list */
96 nfs_get_filtered_mount_list(char *resource
, char *mountp
, char *mntopts
,
97 char *time
, boolean_t find_overlays
, int *errp
) {
99 fs_mntlist_t
*fs_mount_list
;
100 nfs_mntlist_t
*nfs_mount_list
;
102 fs_mount_list
= fs_get_filtered_mount_list(resource
, mountp
,
103 MNTTYPE_NFS
, mntopts
, time
, find_overlays
, errp
);
104 if (fs_mount_list
== NULL
) {
108 if ((nfs_mount_list
= get_nfs_info(fs_mount_list
, errp
)) == NULL
) {
109 fs_free_mount_list(fs_mount_list
);
113 fs_free_mount_list(fs_mount_list
);
114 return (nfs_mount_list
);
115 } /* nfs_get_filtered_mount_list */
118 nfs_get_mounts_by_mntopt(char *mntopt
, boolean_t find_overlays
, int *errp
)
120 fs_mntlist_t
*fs_mount_list
;
121 nfs_mntlist_t
*nfs_mount_list
;
123 fs_mount_list
= fs_get_mounts_by_mntopt(mntopt
, find_overlays
, errp
);
124 if (fs_mount_list
== NULL
) {
128 if ((nfs_mount_list
= get_nfs_info(fs_mount_list
, errp
)) == NULL
) {
129 fs_free_mount_list(fs_mount_list
);
133 fs_free_mount_list(fs_mount_list
);
134 return (nfs_mount_list
);
135 } /* nfs_get_mount_by_mntopt */
138 nfs_get_mount_list(int *errp
)
140 fs_mntlist_t
*fs_mount_list
;
141 nfs_mntlist_t
*nfs_mount_list
;
142 boolean_t find_overlays
= B_TRUE
;
144 if ((fs_mount_list
= fs_get_mount_list(find_overlays
, errp
)) == NULL
) {
145 fprintf(stderr
, "nfs_mntinfo: Can't access mnttab. %s\n",
150 if ((nfs_mount_list
= get_nfs_info(fs_mount_list
, errp
)) == NULL
) {
151 fs_free_mount_list(fs_mount_list
);
155 fs_free_mount_list(fs_mount_list
);
156 return (nfs_mount_list
);
157 } /* nfs_get_mount_list */
164 get_kstat_info(nfs_mntlist_t
*nfs_mntinfo
, int *errp
)
166 kstat_ctl_t
*libkstat_cookie
= NULL
;
170 if ((libkstat_cookie
= kstat_open()) == NULL
) {
173 "nfs_mntinfo: kstat_open(): can't open /dev/kstat.\n");
177 * Each kstat consists of header and data sections that are
178 * connected as a "chain" or linked list of kstat stuctures.
179 * The kc_chain used here is the pointer to the global kstat
180 * chain (or the head of the chain of kstat's).
182 for (ksp
= libkstat_cookie
->kc_chain
; ksp
; ksp
= ksp
->ks_next
) {
183 if ((ksp
->ks_type
== KSTAT_TYPE_RAW
) &&
184 (strcmp(ksp
->ks_module
, "nfs") == 0) &&
185 (strcmp(ksp
->ks_name
, "mntinfo") == 0) &&
186 ((mrp
= kstat_mount(nfs_mntinfo
, ksp
)) != NULL
)) {
187 if (load_kstat_data(libkstat_cookie
, mrp
, ksp
, errp
)
189 nfs_free_mntinfo_list(mrp
);
195 } /* get_kstat_info */
198 load_kstat_data(kstat_ctl_t
*libkstat_cookie
, nfs_mntlist_t
*mrp
,
199 kstat_t
*ksp
, int *errp
)
201 struct mntinfo_kstat mik
;
208 if (safe_kstat_read(libkstat_cookie
, ksp
, &mik
, errp
) == -1) {
212 if (strlcpy(mrp
->nml_proto
, mik
.mik_proto
, KNC_STRSIZE
)
217 if (strlcpy(mrp
->nml_curserver
, mik
.mik_curserver
, SYS_NMLN
)
222 mrp
->nml_vers
= mik
.mik_vers
;
224 * get the secmode name from /etc/nfssec.conf.
226 if (!nfs_getseconfig_bynumber(mik
.mik_secmod
, &nfs_sec
)) {
227 mrp
->nml_securitymode
= strdup(nfs_sec
.sc_name
);
229 mrp
->nml_securitymode
= NULL
;
231 mrp
->nml_curread
= mik
.mik_curread
;
232 mrp
->nml_curwrite
= mik
.mik_curwrite
;
233 mrp
->nml_timeo
= mik
.mik_timeo
;
234 mrp
->nml_retrans
= mik
.mik_retrans
;
235 mrp
->nml_acregmin
= mik
.mik_acregmin
;
236 mrp
->nml_acregmax
= mik
.mik_acregmax
;
237 mrp
->nml_acdirmin
= mik
.mik_acdirmin
;
238 mrp
->nml_acdirmax
= mik
.mik_acdirmax
;
240 ((mik
.mik_flags
& MI_HARD
) ? B_TRUE
: B_FALSE
);
242 ((mik
.mik_flags
& MI_INT
) ? B_TRUE
: B_FALSE
);
244 ((mik
.mik_flags
& MI_NOAC
) ? B_TRUE
: B_FALSE
);
246 ((mik
.mik_flags
& MI_NOCTO
) ? B_TRUE
: B_FALSE
);
248 ((mik
.mik_flags
& MI_GRPID
) ? B_TRUE
: B_FALSE
);
250 ((mik
.mik_flags
& MI_DIRECTIO
) ? B_TRUE
: B_FALSE
);
252 ((mik
.mik_flags
& MI_EXTATTR
) ? B_TRUE
: B_FALSE
);
257 kstat_mount(nfs_mntlist_t
*nfs_mntinfo
, kstat_t
*ksp
) {
260 * MAXMIN is used to retrieve the minor number
261 * which is compared to the kstat instance.
262 * If they are the same then this is an instance
263 * for which mount information is needed.
264 * MAXMIN is the maximum minor number and is
265 * defined in mkdev.h.
268 while ((mrp
!= NULL
) &&
269 ((mrp
->nml_fsid
& MAXMIN
) != ksp
->ks_instance
)) {
275 static nfs_mntlist_t
*
276 get_nfs_info(fs_mntlist_t
*fslist
, int *errp
) {
277 nfs_mntlist_t
*mrp
= NULL
;
278 nfs_mntlist_t
*headptr
= NULL
;
279 nfs_mntlist_t
*tailptr
= NULL
;
280 fs_mntlist_t
*fsmnt_list
;
282 for (fsmnt_list
= fslist
; fsmnt_list
; fsmnt_list
= fsmnt_list
->next
) {
283 /* ignore non "nfs" and the "ignore" entries */
285 if ((strcmp(fsmnt_list
->fstype
, MNTTYPE_NFS
) != 0) ||
286 (ignore(fsmnt_list
->mntopts
))) {
290 if ((mrp
= get_mount_data(fsmnt_list
, errp
)) == NULL
) {
291 nfs_free_mntinfo_list(headptr
);
294 if (tailptr
== NULL
) {
297 tailptr
->next
= NULL
;
301 tailptr
->next
= NULL
;
305 if (get_kstat_info(headptr
, errp
) == -1) {
306 nfs_free_mntinfo_list(mrp
);
314 static nfs_mntlist_t
*
315 get_mount_data(fs_mntlist_t
*fsmnt_list
, int *errp
) {
316 struct replica
*rep_list
; /* defined in replica.h */
318 int i
, server_count
= 0;
319 struct stat stat_buf
;
321 if ((mrp
= malloc(sizeof (nfs_mntlist_t
))) == 0) {
326 if ((stat(fsmnt_list
->mountp
, &stat_buf
) == 0)) {
327 mrp
->nml_fsid
= stat_buf
.st_dev
;
330 nfs_free_mntinfo_list(mrp
);
334 if ((mrp
->nml_resource
= strdup(fsmnt_list
->resource
))
337 nfs_free_mntinfo_list(mrp
);
341 parse_replica(mrp
->nml_resource
, &server_count
)) == NULL
) {
342 nfs_free_mntinfo_list(mrp
);
345 if ((mrp
->nml_failoverlist
=
346 calloc(server_count
, sizeof (char *))) == NULL
) {
347 nfs_free_mntinfo_list(mrp
);
350 for (i
= 0; i
< server_count
; i
++) {
351 mrp
->nml_failoverlist
[i
] =
352 malloc(strlen(rep_list
[i
].host
) + strlen(":") +
353 strlen(rep_list
[i
].path
) + 2);
354 if (!mrp
->nml_failoverlist
[i
]) {
355 nfs_free_mntinfo_list(mrp
);
358 sprintf(mrp
->nml_failoverlist
[i
], "%s%s%s",
359 rep_list
[i
].host
, ":", rep_list
[i
].path
);
362 * If the number of servers is not 1 then resource is
363 * either a failover list or there is an error. In either
364 * case the path can't be determined and curpath is set to
367 if (server_count
== 1) {
368 if (strcmp(rep_list
[0].host
, "nfs") == 0) {
371 path
= strdup(rep_list
[0].path
);
372 if ((path
= (char *)strtok_r(path
, "//",
374 strcpy(mrp
->nml_curpath
,
378 * If NULL is returned this is an
379 * invalid path entry. no path can
382 strcpy(mrp
->nml_curpath
, "unknown");
385 strcpy(mrp
->nml_curpath
,
386 (strchr(mrp
->nml_failoverlist
[0],
391 * more than one server in the failover list
392 * path can't be determined.
394 strcpy(mrp
->nml_curpath
, "unknown");
397 mrp
->nml_failovercount
= server_count
;
399 for (i
= 0; i
< server_count
; i
++) {
400 if (rep_list
[i
].host
) {
401 free(rep_list
[i
].host
);
403 if (rep_list
[i
].path
) {
404 free(rep_list
[i
].path
);
409 if ((mrp
->nml_mountp
= strdup(fsmnt_list
->mountp
)) == NULL
) {
411 nfs_free_mntinfo_list(mrp
);
414 if ((mrp
->nml_fstype
= strdup(fsmnt_list
->fstype
)) == NULL
) {
416 nfs_free_mntinfo_list(mrp
);
419 if ((mrp
->nml_mntopts
= strdup(fsmnt_list
->mntopts
)) == NULL
) {
421 nfs_free_mntinfo_list(mrp
);
424 if ((mrp
->nml_time
= strdup(fsmnt_list
->time
)) == NULL
) {
426 nfs_free_mntinfo_list(mrp
);
429 if (fsmnt_list
->overlayed
) {
430 mrp
->nml_overlayed
= B_TRUE
;
432 mrp
->nml_overlayed
= B_FALSE
;
435 } /* get_mount_data */
439 kstat_ctl_t
*libkstat_cookie
,
445 kid_t kstat_chain_id
= kstat_read(libkstat_cookie
, ksp
, data
);
447 if (kstat_chain_id
== -1) {
451 return (kstat_chain_id
);
452 } /* safe_kstat_read */
456 * ignore - Checks for the ignore mount option in the mount opts string.
457 * Returns 1 if the ignore option is found and 0 if not.
475 if (getsubopt(&s
, mntopts
, &value
) == IGNORE
) {