2 static char sfs_c_mntSid[] = "@(#)sfs_c_mnt.c 2.1 97/10/23";
6 * Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
8 * Standard Performance Evaluation Corporation (SPEC)
9 * 6585 Merchant Place, Suite 100
12 * This product contains benchmarks acquired from several sources who
13 * understand and agree with SPEC's goal of creating fair and objective
14 * benchmarks to measure computer performance.
16 * This copyright notice is placed here only to protect SPEC in the
17 * event the source is misused in any manner that is contrary to the
18 * spirit, the goals and the intent of SPEC.
20 * The source code is provided to the user or company under the license
21 * agreement for the SPEC Benchmark Suite for this product.
24 /*****************************************************************
26 * Copyright 1991,1992 Legato Systems, Inc. *
27 * Copyright 1991,1992 Auspex Systems, Inc. *
28 * Copyright 1991,1992 Data General Corporation *
29 * Copyright 1991,1992 Digital Equipment Corporation *
30 * Copyright 1991,1992 Interphase Corporation *
31 * Copyright 1991,1992 Sun Microsystems, Inc. *
33 *****************************************************************/
36 * ---------------------- sfs_c_mnt.c ---------------------
38 * The sfs child. Routines to handle mount points.
41 * void init_mount_point(int, char *, CLIENT *)
44 * int pseudo_mount(char *, int, char *, CLIENT *)
47 * 2-Jul-92 Teelucksingh Added code for OSF/1
48 * use of getmntinfo().
49 * 16-Dec-91 Wittle Created.
54 * ------------------------- Include Files -------------------------
67 #include <sys/types.h>
74 #include "sfs_c_def.h"
76 struct hostent *Server_hostent;
79 * ------------------------- Constants -------------------------
83 * Number of times a load generating process will retry amount.
84 * Each load generating process also picks a client shifted
85 * mount start time, and executes a backoff on retry time on
88 #define NUMBER_MOUNT_RETRIES 10
91 * ------------------------- External Definitions -------------------------
94 /* forward definitions for local routines */
95 CLIENT * lad_getmnt_hand(char *);
96 static int pseudo_mount(char *, int, char *, CLIENT *);
99 * Mounts are retried when an RPC timeout occurs, in the mainline
100 * code. They are not retried by the RPC clnt_call routine, as the
101 * timeout values are set now.
103 static struct timeval Mount_timer = { 10, 0 };
107 * ------------------------- Mount Point Routines -------------------------
112 * mount the testdir 'dirnum' under the parent directory 'parentdir'.
118 CLIENT * mount_client_ptr)
120 char pnt_dir[SFS_MAXPATHLEN]; /* test dir component name */
121 char testdirname[SFS_MAXPATHLEN]; /* test dir component name */
122 char export_fsname[SFS_MAXPATHLEN]; /* "host:path" exported fs */
123 sfs_fh_type file_handle;
127 sfs_fh_data *fh_datap, *Ex_fh_datap;
129 fh_datap= calloc(1,sizeof(sfs_fh_data));
130 (void) memset((char *)fh_datap, 0, sizeof(sfs_fh_data));
131 (void) memset((char *)&file_handle, 0, sizeof(file_handle));
132 file_handle.fh_data = fh_datap;
133 file_handle.dir = &Export_dir;
135 Ex_fh_datap = (sfs_fh_data *) calloc(1,sizeof(sfs_fh_data));
136 Export_dir.fh_data = Ex_fh_datap;
138 (void) strcpy(pnt_dir, parentdir);
140 cp = strchr(pnt_dir, ':');
142 (void) fprintf(stderr, "%s: malformed fsname %s\n",
143 sfs_Myname, parentdir);
145 (void) generic_kill(0, SIGINT);
152 * Now we have the parent directory in the form:
155 * First we get the file handle for parent directory
157 * Verify that the server is running the correct version of
158 * the NFS protocol specification and then proceed to get
159 * the exported fh from the server.
161 (void) strcpy(testdirname, pnt_dir);
162 (void) strcat(testdirname, ":");
163 (void) strcat(testdirname, cp);
164 (void) strcpy(export_fsname, testdirname);
166 if (nfs_version == NFS_VERSION) {
167 (void) memset((char *) &Export_dir.fh2, '\0', sizeof (Export_dir.fh2));
168 fh_ptr = (char *)&Export_dir.fh2;
169 } else if (nfs_version == NFS_V3) {
170 (void) memset((char *) &Export_dir.fh3, '\0', sizeof (Export_dir.fh3));
171 fh_ptr = (char *)&Export_dir.fh3;
174 ret = pseudo_mount(export_fsname, nfs_version,
175 fh_ptr, mount_client_ptr);
178 (void) fprintf(stderr,
179 "%s: NFS Protocol Version %lu verification failed.\n",
180 sfs_Myname, (uint32_t)nfs_version);
183 (void) fprintf(stderr, "%s: can't pseudo mount %s\n",
184 sfs_Myname, export_fsname);
187 (void) generic_kill(0, SIGINT);
192 * Setup initial state of export directory
194 Export_dir.state = Exists;
195 (void) strcpy(Export_dir.file_name, testdirname);
196 Export_dir.dir = &Export_dir;
200 * Check for and create the client directory. Stat it first, if not
201 * there then mkdir, if that fails with EEXIST we lost the race but
205 (void) sprintf(testdirname, "%s", "validatedir");
207 (void) sprintf(testdirname, "CL%d", Client_num);
210 if ((ret = lad_lookup(&file_handle, testdirname)) == -1) {
212 (void) generic_kill(0, SIGINT);
218 * Directory doesn't exist so create it
219 * if it already exists thats OK
221 if ((ret = lad_mkdir(&file_handle, testdirname)) == -1) {
223 (void) generic_kill(0, SIGINT);
227 * If someone else created this out from underneath us simply
228 * lookup the result and continue on.
230 if (ret != 0 && (ret = lad_lookup(&file_handle, testdirname)) == -1) {
232 (void) generic_kill(0, SIGINT);
237 /* testdirname now exists, verify it is a directory and writeable */
238 if (!fh_isdir(&file_handle) ||
239 (check_fh_access(&file_handle) == -1)) {
240 (void) fprintf(stderr,
241 "%s: %s is either not a directory or not accessible\n",
242 sfs_Myname, testdirname);
244 (void) generic_kill(0, SIGINT);
249 * logically chdir into CL directory
251 /* Export_dir = file_handle; Implied bcopy here */
252 (void) memmove(&Export_dir,&file_handle,sizeof(sfs_fh_type));
253 Export_dir.fh_data = Ex_fh_datap;
254 (void ) memmove(Export_dir.fh_data, file_handle.fh_data,
255 sizeof(sfs_fh_data));
256 (void) memset((char *)&file_handle, 0, sizeof(file_handle));
257 (void) memset((char *)fh_datap, 0, sizeof(sfs_fh_data));
258 file_handle.fh_data = fh_datap;
259 file_handle.dir = &Export_dir;
262 * Validation only occurs one directory deep so we can exit early
267 (void) sprintf(testdirname, "testdir%d", dirnum);
269 if ((ret = lad_lookup(&file_handle, testdirname)) == -1) {
270 (void) generic_kill(0, SIGINT);
276 * Directory doesn't exist so create it
278 if (lad_mkdir(&file_handle, testdirname) != 0) {
279 (void) fprintf(stderr, "%s: Unable to create %s\n",
280 sfs_Myname, testdirname);
281 (void) generic_kill(0, SIGINT);
286 /* testdirname now exists, verify it is a directory and writeable */
287 if (!fh_isdir(&file_handle) ||
288 (check_fh_access(&file_handle) == -1)) {
289 (void) fprintf(stderr,
290 "%s: %s is either not a directory or not accessible\n",
291 sfs_Myname, testdirname);
292 (void) generic_kill(0, SIGINT);
297 * logically chdir into testdir directory
299 /* Export_dir = file_handle;*/
300 (void) memmove(&Export_dir, &file_handle, sizeof(struct sfs_fh_type));
301 Export_dir.fh_data = Ex_fh_datap; /* Put pointer back */
302 (void) memmove(Export_dir.fh_data, file_handle.fh_data, sizeof
305 } /* init_mount_point */
308 * Get the filehandle for 'mount_fsname', and return it
309 * Returns NULL for error ... not mounted || no NFS client.
311 * Children should only call this routine 1 time.
317 char mnt_pnt[SFS_MAXPATHLEN]; /* working buffer */
318 char host[SFS_MAXPATHLEN]; /* host with exported fs */
319 static struct hostent hp;
321 CLIENT *mount_client_ptr; /* Mount client handle */
323 int rpc_result; /* rpc call result */
324 uint32_t mount_vers = 0;
327 * If the mount point is of the form host:path just use the explicit
328 * name instead of grovelling through the mount table.
330 (void) strcpy(mnt_pnt, mount_point);
331 cp = strchr(mnt_pnt, ':');
333 (void) fprintf(stderr, "%s: malformed fsname %s\n",
334 sfs_Myname, mount_point);
339 (void) strcpy(host, mnt_pnt);
341 /* Verify NFS Version */
342 rpc_result = callrpc(host,
343 (uint32_t) NFS_PROGRAM,
344 (uint32_t) nfs_version,
345 (uint32_t) NFSPROC_NULL, (xdrproc_t) xdr_void,
346 (char *) NULL, (xdrproc_t) xdr_void, (char *) NULL);
347 if (rpc_result != 0) {
348 clnt_perrno((enum clnt_stat)rpc_result);
349 (void) fprintf(stderr,
350 "\nUnable to contact NFS server %s.\n", host);
351 (void) fprintf(stderr,
352 "Verify NFS server daemon supporting version %u is running and\n",
353 (uint32_t)nfs_version);
354 (void) fprintf(stderr, "registered with the portmapper.\n");
358 /* Get host's address */
359 if ((thp = gethostbyname(host)) == NULL) {
360 /* Failure may be due to yellow pages, try again */
361 if ((thp = gethostbyname(host)) == NULL) {
362 (void) fprintf(stderr, "%s: %s not in hosts database\n",
369 Server_hostent = &hp;
371 if (nfs_version == NFS_VERSION)
372 mount_vers = MOUNTVERS;
373 if (nfs_version == NFS_V3)
374 mount_vers = MOUNTVER3;
376 mount_client_ptr = lad_clnt_create(0, Server_hostent,
377 (uint32_t) MOUNTPROG,
379 RPC_ANYSOCK, &Mount_timer);
382 if (mount_client_ptr == ((CLIENT*) NULL)) {
383 (void) fprintf(stderr,
384 "%s: portmap/mountd %s server not responding",
385 sfs_Myname, mount_point);
389 mount_client_ptr->cl_auth = authunix_create_default();
390 return (mount_client_ptr);
392 } /* lad_getmnt_hand */
396 * Get the filehandle for 'mount_fsname', and return it in 'fh_ptr'.
397 * Returns 0 for OK, -1 for error ... not mounted || no NFS client.
399 * Children should only call this routine 1 time.
406 CLIENT * mount_client_ptr)
408 char * host_ptr; /* host with exported fs */
409 char * path_ptr; /* ptr to path for RPC */
411 struct fhstatus fhs; /* status of mountd call */
413 mountres3 mntres3; /* status of mountd call */
415 enum clnt_stat rpc_stat;
416 int tries = 0; /* Number of retries */
417 /* Space by 200ms intervals. */
418 int pacesleep = Child_num * 200;
420 /* Parse the fsname for host and path strings */
421 cp = strchr(mount_fsname, ':');
424 (void) fprintf(stderr, "%s: malformed fsname %s\n",
425 sfs_Myname, mount_fsname);
430 host_ptr = mount_fsname;
433 /* Check host's address */
434 if (gethostbyname(host_ptr) == NULL) {
435 /* Failure may be due to yellow pages, try again */
436 if (gethostbyname(host_ptr) == NULL) {
437 (void) fprintf(stderr, "%s: %s not in hosts database\n",
438 sfs_Myname, host_ptr);
443 if (DEBUG_CHILD_GENERAL) {
444 (void) fprintf(stderr, "%s: mount clnt_call\n", sfs_Myname);
447 /* get fhandle of remote path from host's mountd */
451 * Many children on many clients hammer a server with
452 * mounts. Crude fix is to pace them. Some run rule interpretations
453 * are to have *many* children on each client. This can
456 (void) msec_sleep(pacesleep);
458 if (version == NFS_VERSION) {
459 (void) memset((char *) &fhs, '\0', sizeof (fhs));
460 rpc_stat = clnt_call(mount_client_ptr, MOUNTPROC_MNT, xdr_path,
461 (char *) &path_ptr,xdr_fhstatus,(char *) &fhs,
463 } else if (version == NFS_V3) {
464 (void) memset((char *) &mntres3, '\0', sizeof (mntres3));
465 rpc_stat = clnt_call(mount_client_ptr, MOUNTPROC_MNT, xdr_dirpath,
466 (char *) &path_ptr, xdr_mntres3, (char *) &mntres3,
469 rpc_stat = RPC_PROGVERSMISMATCH;
472 if (rpc_stat != RPC_SUCCESS) {
478 (void) fprintf(stderr,
479 "%s: mounting %s:%s server not responding: %s (%d)\n",
480 sfs_Myname, host_ptr, path_ptr,
481 strerror(errno), errno);
482 if (tries++ < NUMBER_MOUNT_RETRIES) {
483 /* Randomize the backoff on retry */
484 pacesleep = pacesleep + (sfs_random() % 2000);
490 case RPC_PMAPFAILURE:
491 errno = ENETDOWN; /* reasonable error */
492 (void) fprintf(stderr,
493 "%s: mounting %s portmap call failed: %s (%d)\n",
494 sfs_Myname, host_ptr, strerror(errno), errno);
497 case RPC_PROGNOTREGISTERED:
498 errno = ENETDOWN; /* reasonable error */
499 (void) fprintf(stderr,
500 "%s: mounting %s nfsd not registered: %s (%d)\n",
501 sfs_Myname, host_ptr, strerror(errno), errno);
506 (void) fprintf(stderr,
507 "%s: mounting %s authentication failed: %s (%d)\n",
508 sfs_Myname, host_ptr, strerror(errno), errno);
512 errno = ENETDOWN; /* reasonable error */
513 (void) fprintf(stderr,
514 "%s: mounting %s:%s failed: %s (%d)\n",
515 sfs_Myname, host_ptr, path_ptr,
516 strerror(errno), errno);
520 clnt_perror(mount_client_ptr, "");
523 } /* MOUNTPROC_MNT call failed */
525 if (version == NFS_VERSION) {
526 if (fhs.fhs_status != 0) {
527 if (fhs.fhs_status == EACCES) {
528 (void) fprintf(stderr, "%s: mounting %s:%s - access denied\n",
529 sfs_Myname, host_ptr, path_ptr);
531 (void) fprintf(stderr,
532 "%s: mounting %s:%s - bad fh status %d\n ",
533 sfs_Myname, host_ptr, path_ptr, fhs.fhs_status);
536 } /* bad fhs status */
539 * fill in the caller's file handle
541 (void) memmove(fh_ptr, (char *) &fhs.fhs_fh, NFS_FHSIZE);
543 } else if (version == NFS_V3) {
545 if (mntres3.fhs_status != MNT_OK) {
546 if (mntres3.fhs_status == MNT3ERR_ACCES) {
547 (void) fprintf(stderr, "%s: mounting %s:%s - access denied\n",
548 sfs_Myname, host_ptr, path_ptr);
550 (void) fprintf(stderr,
551 "%s: mounting %s:%s - bad fh status %d\n ",
552 sfs_Myname, host_ptr, path_ptr, mntres3.fhs_status);
555 } /* bad fhs status */
558 * fill in the caller's file handle
559 * space pointed by fhandle3_val is allocated through xdr_mntres3
561 fh_ptr3 = (nfs_fh3 *)fh_ptr;
562 fh_ptr3->fh3_length = mntres3.mntres3_u.mntinfo.fhandle.fhandle3_len;
563 (void) memmove((char *) fh_ptr3->fh3_u.data,
564 (char *) mntres3.mntres3_u.mntinfo.fhandle.fhandle3_val,
565 fh_ptr3->fh3_length);