4 * Copyright (c) 1997-2009 Erez Zadok
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 The Regents of the University of California.
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgment:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * File: am-utils/amd/amq_subr.c
46 * Auxiliary routines for amq tool
51 #endif /* HAVE_CONFIG_H */
55 /* forward definitions */
56 bool_t
xdr_amq_mount_tree_node(XDR
*xdrs
, amq_mount_tree
*objp
);
57 bool_t
xdr_amq_mount_subtree(XDR
*xdrs
, amq_mount_tree
*objp
);
61 amqproc_null_1_svc(voidp argp
, struct svc_req
*rqstp
)
70 * Return a sub-tree of mounts
73 amqproc_mnttree_1_svc(voidp argp
, struct svc_req
*rqstp
)
77 mp
= find_ap(*(char **) argp
);
78 return (amq_mount_tree_p
*) ((void *)&mp
);
83 * Unmount a single node
86 amqproc_umnt_1_svc(voidp argp
, struct svc_req
*rqstp
)
88 static int res
= AMQ_UMNT_OK
;
89 am_node
*mp
= find_ap(*(char **) argp
);
92 forcibly_timeout_mp(mp
);
99 * Synchronously unmount a single node - parent side.
102 amqproc_sync_umnt_1_svc_parent(voidp argp
, struct svc_req
*rqstp
)
104 amqproc_umnt_1_svc(argp
, rqstp
);
110 * Synchronously unmount a single node - child side.
113 amqproc_sync_umnt_1_svc_child(voidp argp
, struct svc_req
*rqstp
)
115 static amq_sync_umnt rv
;
119 am_node
*mp
= find_ap(*(char **) argp
);
121 memset(&rv
, 0, sizeof(rv
));
122 rv
.au_etype
= AMQ_UMNT_READ
;
123 if (mp
&& mp
->am_fd
[0] >= 0) {
124 n
= read(mp
->am_fd
[0], &buf
, sizeof(buf
));
125 if (n
== sizeof(buf
))
133 * Synchronously unmount a single node - use if we can't fork (asynchronous).
136 amqproc_sync_umnt_1_svc_async(voidp argp
, struct svc_req
*rqstp
)
138 static amq_sync_umnt rv
;
140 memset(&rv
, 0, sizeof(rv
));
141 rv
.au_etype
= AMQ_UMNT_FORK
;
144 amqproc_umnt_1_svc(argp
, rqstp
);
151 * Return global statistics
154 amqproc_stats_1_svc(voidp argp
, struct svc_req
*rqstp
)
156 return (amq_mount_stats
*) ((void *)&amd_stats
);
161 * Return the entire tree of mount nodes
163 amq_mount_tree_list
*
164 amqproc_export_1_svc(voidp argp
, struct svc_req
*rqstp
)
166 static amq_mount_tree_list aml
;
169 mp
= get_exported_ap(0);
170 aml
.amq_mount_tree_list_val
= (amq_mount_tree_p
*) ((void *) &mp
);
171 aml
.amq_mount_tree_list_len
= 1; /* XXX */
178 amqproc_setopt_1_svc(voidp argp
, struct svc_req
*rqstp
)
181 amq_setopt
*opt
= (amq_setopt
*) argp
;
185 switch (opt
->as_opt
) {
188 if (debug_option(opt
->as_str
))
193 if (gopt
.logfile
&& opt
->as_str
194 && STREQ(gopt
.logfile
, opt
->as_str
)) {
195 if (switch_to_logfile(opt
->as_str
, orig_umask
, 0))
203 if (switch_option(opt
->as_str
))
207 case AMOPT_FLUSHMAPC
:
208 if (amd_state
== Run
) {
209 plog(XLOG_INFO
, "amq says flush cache");
211 flush_nfs_fhandle_cache((fserver
*) NULL
);
212 flush_srvr_nfs_cache((fserver
*) NULL
);
221 amq_mount_info_list
*
222 amqproc_getmntfs_1_svc(voidp argp
, struct svc_req
*rqstp
)
224 return (amq_mount_info_list
*) ((void *)&mfhead
); /* XXX */
229 amqproc_getvers_1_svc(voidp argp
, struct svc_req
*rqstp
)
231 static amq_string res
;
233 res
= get_version_string();
238 /* get PID of remote amd */
240 amqproc_getpid_1_svc(voidp argp
, struct svc_req
*rqstp
)
250 * Process PAWD string of remote pawd tool.
252 * We repeat the resolution of the string until the resolved string resolves
253 * to itself. This ensures that we follow path resolutions through all
254 * possible Amd mount points until we reach some sort of convergence. To
255 * prevent possible infinite loops, we break out of this loop if the strings
256 * do not converge after MAX_PAWD_TRIES times.
259 amqproc_pawd_1_svc(voidp argp
, struct svc_req
*rqstp
)
261 static amq_string res
;
262 #define MAX_PAWD_TRIES 10
263 int index
, len
, maxagain
= MAX_PAWD_TRIES
;
266 char *dir
= *(char **) argp
;
267 static char tmp_buf
[MAXPATHLEN
];
268 char prev_buf
[MAXPATHLEN
];
270 tmp_buf
[0] = prev_buf
[0] = '\0'; /* default is empty string: no match */
272 for (mp
= get_first_exported_ap(&index
);
274 mp
= get_next_exported_ap(&index
)) {
275 if (STREQ(mp
->am_mnt
->mf_ops
->fs_type
, "toplvl"))
277 if (STREQ(mp
->am_mnt
->mf_ops
->fs_type
, "auto"))
279 mountpoint
= (mp
->am_link
? mp
->am_link
: mp
->am_mnt
->mf_mount
);
280 len
= strlen(mountpoint
);
283 if (!NSTREQ(mountpoint
, dir
, len
))
285 if (dir
[len
] != '\0' && dir
[len
] != '/')
287 xstrlcpy(tmp_buf
, mp
->am_path
, sizeof(tmp_buf
));
288 xstrlcat(tmp_buf
, &dir
[len
], sizeof(tmp_buf
));
290 } /* end of "for" loop */
291 /* once tmp_buf and prev_buf are equal, break out of "do" loop */
292 if (STREQ(tmp_buf
, prev_buf
))
295 xstrlcpy(prev_buf
, tmp_buf
, sizeof(prev_buf
));
296 } while (--maxagain
);
297 /* check if we couldn't resolve the string after MAX_PAWD_TRIES times */
299 plog(XLOG_WARNING
, "path \"%s\" did not resolve after %d tries",
300 tmp_buf
, MAX_PAWD_TRIES
);
313 xdr_amq_setopt(XDR
*xdrs
, amq_setopt
*objp
)
315 if (!xdr_enum(xdrs
, (enum_t
*) ((voidp
) &objp
->as_opt
))) {
318 if (!xdr_string(xdrs
, &objp
->as_str
, AMQ_STRLEN
)) {
326 * More XDR routines - Should be used for OUTPUT ONLY.
329 xdr_amq_mount_tree_node(XDR
*xdrs
, amq_mount_tree
*objp
)
331 am_node
*mp
= (am_node
*) objp
;
334 if (!xdr_amq_string(xdrs
, &mp
->am_mnt
->mf_info
)) {
337 if (!xdr_amq_string(xdrs
, &mp
->am_path
)) {
340 if (!xdr_amq_string(xdrs
, mp
->am_link
? &mp
->am_link
: &mp
->am_mnt
->mf_mount
)) {
343 if (!xdr_amq_string(xdrs
, &mp
->am_mnt
->mf_ops
->fs_type
)) {
346 mtime
= mp
->am_stats
.s_mtime
;
347 if (!xdr_long(xdrs
, &mtime
)) {
350 if (!xdr_u_short(xdrs
, &mp
->am_stats
.s_uid
)) {
353 if (!xdr_int(xdrs
, &mp
->am_stats
.s_getattr
)) {
356 if (!xdr_int(xdrs
, &mp
->am_stats
.s_lookup
)) {
359 if (!xdr_int(xdrs
, &mp
->am_stats
.s_readdir
)) {
362 if (!xdr_int(xdrs
, &mp
->am_stats
.s_readlink
)) {
365 if (!xdr_int(xdrs
, &mp
->am_stats
.s_statfs
)) {
373 xdr_amq_mount_subtree(XDR
*xdrs
, amq_mount_tree
*objp
)
375 am_node
*mp
= (am_node
*) objp
;
377 if (!xdr_amq_mount_tree_node(xdrs
, objp
)) {
380 if (!xdr_pointer(xdrs
,
381 (char **) ((voidp
) &mp
->am_osib
),
382 sizeof(amq_mount_tree
),
383 (XDRPROC_T_TYPE
) xdr_amq_mount_subtree
)) {
386 if (!xdr_pointer(xdrs
,
387 (char **) ((voidp
) &mp
->am_child
),
388 sizeof(amq_mount_tree
),
389 (XDRPROC_T_TYPE
) xdr_amq_mount_subtree
)) {
397 xdr_amq_mount_tree(XDR
*xdrs
, amq_mount_tree
*objp
)
399 am_node
*mp
= (am_node
*) objp
;
400 am_node
*mnil
= NULL
;
402 if (!xdr_amq_mount_tree_node(xdrs
, objp
)) {
405 if (!xdr_pointer(xdrs
,
406 (char **) ((voidp
) &mnil
),
407 sizeof(amq_mount_tree
),
408 (XDRPROC_T_TYPE
) xdr_amq_mount_subtree
)) {
411 if (!xdr_pointer(xdrs
,
412 (char **) ((voidp
) &mp
->am_child
),
413 sizeof(amq_mount_tree
),
414 (XDRPROC_T_TYPE
) xdr_amq_mount_subtree
)) {
422 xdr_amq_mount_tree_p(XDR
*xdrs
, amq_mount_tree_p
*objp
)
424 if (!xdr_pointer(xdrs
, (char **) objp
, sizeof(amq_mount_tree
), (XDRPROC_T_TYPE
) xdr_amq_mount_tree
)) {
432 xdr_amq_mount_stats(XDR
*xdrs
, amq_mount_stats
*objp
)
434 if (!xdr_int(xdrs
, &objp
->as_drops
)) {
437 if (!xdr_int(xdrs
, &objp
->as_stale
)) {
440 if (!xdr_int(xdrs
, &objp
->as_mok
)) {
443 if (!xdr_int(xdrs
, &objp
->as_merr
)) {
446 if (!xdr_int(xdrs
, &objp
->as_uerr
)) {
455 xdr_amq_mount_tree_list(XDR
*xdrs
, amq_mount_tree_list
*objp
)
458 (char **) ((voidp
) &objp
->amq_mount_tree_list_val
),
459 (u_int
*) &objp
->amq_mount_tree_list_len
,
461 sizeof(amq_mount_tree_p
),
462 (XDRPROC_T_TYPE
) xdr_amq_mount_tree_p
)) {
471 * Compute length of list
474 xdr_amq_mount_info_qelem(XDR
*xdrs
, qelem
*qhead
)
479 for (mf
= AM_LAST(mntfs
, qhead
); mf
!= HEAD(mntfs
, qhead
); mf
= PREV(mntfs
, mf
)) {
480 if (!(mf
->mf_fsflags
& FS_AMQINFO
))
484 xdr_u_int(xdrs
, &len
);
487 * Send individual data items
489 for (mf
= AM_LAST(mntfs
, qhead
); mf
!= HEAD(mntfs
, qhead
); mf
= PREV(mntfs
, mf
)) {
491 if (!(mf
->mf_fsflags
& FS_AMQINFO
))
494 if (!xdr_amq_string(xdrs
, &mf
->mf_ops
->fs_type
)) {
497 if (!xdr_amq_string(xdrs
, &mf
->mf_mount
)) {
500 if (!xdr_amq_string(xdrs
, &mf
->mf_info
)) {
503 if (!xdr_amq_string(xdrs
, &mf
->mf_server
->fs_host
)) {
506 if (!xdr_int(xdrs
, &mf
->mf_error
)) {
509 if (!xdr_int(xdrs
, &mf
->mf_refc
)) {
512 if (FSRV_ERROR(mf
->mf_server
) || FSRV_ISDOWN(mf
->mf_server
))
514 else if (FSRV_ISUP(mf
->mf_server
))
518 if (!xdr_int(xdrs
, &up
)) {
527 xdr_pri_free(XDRPROC_T_TYPE xdr_args
, caddr_t args_ptr
)
532 return ((*xdr_args
) (&xdr
, (caddr_t
*) args_ptr
));