NFS mounts - hard versus soft - info. wanted
Richard Tobin
richard at aiai.ed.ac.uk
Tue Aug 21 23:23:40 AEST 1990
In article <1990Aug20.204546.15101 at anduin.cs.liverpool.ac.uk> dave8 at anduin.cs.liverpool.ac.uk writes:
>However, we are frustrated by situations where a cluster server goes down,
>and the workstations on another cluster server hang because the PATH
>environment variable on these includes a directory residing on a
>partition being exported from the machine that has gone down.
One way to deal with this is to mount the filesystems in some
obscure place, and make symbolic links to them. You can then remove
the links when the server goes down.
Of course, this doesn't work if you don't have symbolic links.
You should also mount filesystems from different machines in different
directories, so that "pwd" doesn't hang.
You can have a program maintain the links automatically - here's one
I use. It may need changing for HPs.
-- Richard
/*
* nfslink [-i interval] [-t timeout] host name mountpt [name mountpt ...]
*
* maintain links to mounted file systems, removing them if the
* remote machine isn't responding.
*
* Copyright Richard Tobin / AIAI 1989
*
* May be freely redistributed if this whole notice remains intact.
*/
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#include <rpc/rpc.h>
#include <rpc/clnt.h>
#include <nfs/nfs.h>
#include <setjmp.h>
#include <sys/stat.h>
#include <netdb.h>
#include <sys/socket.h>
main(argc, argv)
int argc;
char **argv;
{
int c, interval = 20, timeout = 5, firsttime = 1;
extern char *optarg;
extern int optind, opterr;
while((c = getopt(argc, argv, "i:t:")) != EOF)
switch(c)
{
case 'i':
interval = atoi(optarg);
break;
case 't':
timeout = atoi(optarg);
break;
case '?':
usage();
break;
}
if((argc - optind) < 3 || ((argc - optind) & 1) == 0)
usage();
while(1)
{
if(nfscheck(argv[optind], timeout) == 0)
makelinks(&argv[optind+1], firsttime);
else
removelinks(&argv[optind+1], firsttime);
firsttime = 0;
sleep(interval);
}
}
void dodate()
{
char *tim;
long *clk;
time(&clk);
tim = ctime(&clk);
tim[24] = '\0'; /* lose the linefeed */
printf("nfslink: %s: ", tim);
}
makelinks(links, verbose)
char **links;
int verbose;
{
struct stat namestat;
while(*links)
{
char *name = *links++;
char *mountpt = *links++;
if(lstat(name, &namestat) == -1)
{
if(errno == ENOENT)
{
if(symlink(mountpt, name) == -1)
{
perror("nfslink: symlink");
fatal("can't link %s to %s\n", name, mountpt);
}
dodate();
printf("linked %s to %s\n", name, mountpt);
fflush(stdout);
continue;
}
else
{
perror("nfslink: lstat");
fatal("can't lstat %s\n", name, 0);
}
}
if((namestat.st_mode & S_IFMT) == S_IFLNK)
{
if(pointsto(name, mountpt))
{
if(verbose)
{
dodate();
printf("%s is already linked to %s\n",
name, mountpt);
fflush(stdout);
}
}
else
{
fatal("%s is a link, but not to %s\n", name, mountpt);
}
}
else
{
fatal("%s exists, but is not a symbolic link\n", name, 0);
}
}
}
removelinks(links, verbose)
char **links;
int verbose;
{
struct stat namestat;
while(*links)
{
char *name = *links++;
char *mountpt = *links++;
if(lstat(name, &namestat) == -1)
{
if(errno == ENOENT)
{
if(verbose)
{
dodate();
printf("link from %s to %s is already removed\n",
name, mountpt);
fflush(stdout);
}
continue;
}
else
{
perror("nfslink: lstat");
fatal("can't lstat %s\n", name, 0);
}
}
if((namestat.st_mode & S_IFMT) == S_IFLNK)
{
if(pointsto(name, mountpt))
{
if(unlink(name) == -1)
{
perror("nfslink: unlink");
fatal("can't remove link from %s to %s\n",
name, mountpt);
}
dodate();
printf("removed link from %s to %s\n",
name, mountpt);
fflush(stdout);
}
else
{
fatal("%s is a link, but not to %s\n", name, mountpt);
}
}
else
{
fatal("%s exists, but is not a symbolic link\n", name, 0);
}
}
}
int pointsto(name, target)
char *name, *target;
{
/* We don't use stat lest it hang, so it's not quite right */
char buf[200];
int len;
len = readlink(name, buf, sizeof(buf)-1);
if(len == -1)
{
perror("nfslink: readlink");
fatal("can't read link %s\n", name, 0);
}
buf[len] = '\0';
return strcmp(buf, target) == 0;
}
fatal(fmt, arg1, arg2)
char *fmt, *arg1, *arg2;
{
fprintf(stderr, "nfslink: fatal error: ");
fprintf(stderr, fmt, arg1, arg2);
exit(1);
}
usage()
{
fprintf(stderr, "usage: nfslink [-i interval] [-t timeout] host name mountpt [name mountpt ...]\n");
exit(2);
}
int nfscheck(host, timeout)
char *host;
int timeout;
{
int stat, sock= RPC_ANYSOCK;
struct hostent *server;
struct sockaddr_in sin;
CLIENT *client;
struct timeval try, total;
server = gethostbyname(host);
if(!server)
{
fprintf(stderr, "nfslink: unknown host %s\n", host);
return -1;
}
bcopy(server->h_addr, &sin.sin_addr, server->h_length);
sin.sin_family = AF_INET;
sin.sin_port = 2049; /* avoid calling portmapper */
try.tv_sec = 1;
try.tv_usec = 0;
client = clntudp_create(&sin, NFS_PROGRAM, NFS_VERSION,
try, &sock);
if(!client)
return -1;
total.tv_sec = timeout;
total.tv_usec = 0;
stat = clnt_call(client, RFS_NULL, xdr_void, 0, xdr_void, 0, total);
clnt_destroy(client);
if(stat != RPC_SUCCESS)
return -1;
return 0;
}
--
Richard Tobin, JANET: R.Tobin at uk.ac.ed
AI Applications Institute, ARPA: R.Tobin%uk.ac.ed at nsfnet-relay.ac.uk
Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
More information about the Comp.unix.questions
mailing list