|
Packit Service |
a4b2a9 |
/* ----------------------------------------------------------------------- *
|
|
Packit Service |
a4b2a9 |
*
|
|
Packit Service |
a4b2a9 |
* mount_nfs.c - Module for Linux automountd to mount an NFS filesystem,
|
|
Packit Service |
a4b2a9 |
* with fallback to symlinking if the path is local
|
|
Packit Service |
a4b2a9 |
*
|
|
Packit Service |
a4b2a9 |
* Copyright 1997 Transmeta Corporation - All Rights Reserved
|
|
Packit Service |
a4b2a9 |
* Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
|
|
Packit Service |
a4b2a9 |
*
|
|
Packit Service |
a4b2a9 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
a4b2a9 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
a4b2a9 |
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
|
Packit Service |
a4b2a9 |
* USA; either version 2 of the License, or (at your option) any later
|
|
Packit Service |
a4b2a9 |
* version; incorporated herein by reference.
|
|
Packit Service |
a4b2a9 |
*
|
|
Packit Service |
a4b2a9 |
* ----------------------------------------------------------------------- */
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
#include <stdio.h>
|
|
Packit Service |
a4b2a9 |
#include <malloc.h>
|
|
Packit Service |
a4b2a9 |
#include <netdb.h>
|
|
Packit Service |
a4b2a9 |
#include <stdlib.h>
|
|
Packit Service |
a4b2a9 |
#include <string.h>
|
|
Packit Service |
a4b2a9 |
#include <sys/param.h>
|
|
Packit Service |
a4b2a9 |
#include <sys/socket.h>
|
|
Packit Service |
a4b2a9 |
#include <sys/types.h>
|
|
Packit Service |
a4b2a9 |
#include <sys/stat.h>
|
|
Packit Service |
a4b2a9 |
#include <sys/vfs.h>
|
|
Packit Service |
a4b2a9 |
#include <netinet/in.h>
|
|
Packit Service |
a4b2a9 |
#include <linux/nfs.h>
|
|
Packit Service |
a4b2a9 |
#include <linux/nfs2.h>
|
|
Packit Service |
a4b2a9 |
#include <ctype.h>
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
#define MODULE_MOUNT
|
|
Packit Service |
a4b2a9 |
#include "automount.h"
|
|
Packit Service |
a4b2a9 |
#include "replicated.h"
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
#define MODPREFIX "mount(nfs): "
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
int mount_version = AUTOFS_MOUNT_VERSION; /* Required by protocol */
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
static struct mount_mod *mount_bind = NULL;
|
|
Packit Service |
a4b2a9 |
static int init_ctr = 0;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
int mount_init(void **context)
|
|
Packit Service |
a4b2a9 |
{
|
|
Packit Service |
a4b2a9 |
/* Make sure we have the local mount method available */
|
|
Packit Service |
a4b2a9 |
if (!mount_bind) {
|
|
Packit Service |
a4b2a9 |
if ((mount_bind = open_mount("bind", MODPREFIX)))
|
|
Packit Service |
a4b2a9 |
init_ctr++;
|
|
Packit Service |
a4b2a9 |
} else
|
|
Packit Service |
a4b2a9 |
init_ctr++;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
seed_random();
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
return !mount_bind;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
int mount_reinit(void **context)
|
|
Packit Service |
a4b2a9 |
{
|
|
Packit Service |
a4b2a9 |
return 0;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
int mount_mount(struct autofs_point *ap, const char *root, const char *name, int name_len,
|
|
Packit Service |
a4b2a9 |
const char *what, const char *fstype, const char *options,
|
|
Packit Service |
a4b2a9 |
void *context)
|
|
Packit Service |
a4b2a9 |
{
|
|
Packit Service |
a4b2a9 |
char fullpath[PATH_MAX];
|
|
Packit Service |
a4b2a9 |
char buf[MAX_ERR_BUF];
|
|
Packit Service |
a4b2a9 |
struct host *this, *hosts = NULL;
|
|
Packit Service |
a4b2a9 |
unsigned int mount_default_proto, vers;
|
|
Packit Service |
a4b2a9 |
char *nfsoptions = NULL;
|
|
Packit Service |
a4b2a9 |
unsigned int flags = ap->flags &
|
|
Packit Service |
a4b2a9 |
(MOUNT_FLAG_RANDOM_SELECT | MOUNT_FLAG_USE_WEIGHT_ONLY);
|
|
Packit Service |
a4b2a9 |
int symlink = (*name != '/' && (ap->flags & MOUNT_FLAG_SYMLINK));
|
|
Packit Service |
a4b2a9 |
int nobind = ap->flags & MOUNT_FLAG_NOBIND;
|
|
Packit Service |
a4b2a9 |
int len, status, err, existed = 1;
|
|
Packit Service |
a4b2a9 |
int nosymlink = 0;
|
|
Packit Service |
a4b2a9 |
int port = -1;
|
|
Packit Service |
a4b2a9 |
int ro = 0; /* Set if mount bind should be read-only */
|
|
Packit Service |
a4b2a9 |
int rdma = 0;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (ap->flags & MOUNT_FLAG_REMOUNT)
|
|
Packit Service |
a4b2a9 |
return 0;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
debug(ap->logopt,
|
|
Packit Service |
a4b2a9 |
MODPREFIX "root=%s name=%s what=%s, fstype=%s, options=%s",
|
|
Packit Service |
a4b2a9 |
root, name, what, fstype, options);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
mount_default_proto = defaults_get_mount_nfs_default_proto();
|
|
Packit Service |
53a4e5 |
vers = NFS_VERS_DEFAULT | NFS_PROTO_DEFAULT;
|
|
Packit Service |
a4b2a9 |
if (strcmp(fstype, "nfs4") == 0)
|
|
Packit Service |
53a4e5 |
vers = NFS4_VERS_DEFAULT | TCP_SUPPORTED;
|
|
Packit Service |
a4b2a9 |
else if (mount_default_proto == 4)
|
|
Packit Service |
53a4e5 |
vers = vers | NFS4_VERS_DEFAULT;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Extract "nosymlink" pseudo-option which stops local filesystems
|
|
Packit Service |
a4b2a9 |
* from being symlinked.
|
|
Packit Service |
a4b2a9 |
*
|
|
Packit Service |
a4b2a9 |
* "nosymlink" is not used anymore. It is left for compatibility
|
|
Packit Service |
a4b2a9 |
* only (so we don't choke on it).
|
|
Packit Service |
a4b2a9 |
*/
|
|
Packit Service |
a4b2a9 |
if (options) {
|
|
Packit Service |
a4b2a9 |
const char *comma;
|
|
Packit Service |
a4b2a9 |
char *nfsp;
|
|
Packit Service |
a4b2a9 |
int o_len = strlen(options) + 1;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
nfsp = nfsoptions = alloca(o_len + 1);
|
|
Packit Service |
a4b2a9 |
if (!nfsoptions)
|
|
Packit Service |
a4b2a9 |
return 1;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
memset(nfsoptions, '\0', o_len + 1);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
for (comma = options; *comma != '\0';) {
|
|
Packit Service |
a4b2a9 |
const char *cp;
|
|
Packit Service |
a4b2a9 |
const char *end;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
while (*comma == ',')
|
|
Packit Service |
a4b2a9 |
comma++;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Skip leading white space */
|
|
Packit Service |
a4b2a9 |
while (*comma == ' ' || *comma == '\t')
|
|
Packit Service |
a4b2a9 |
comma++;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
cp = comma;
|
|
Packit Service |
a4b2a9 |
while (*comma != '\0' && *comma != ',')
|
|
Packit Service |
a4b2a9 |
comma++;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Skip trailing white space */
|
|
Packit Service |
a4b2a9 |
end = comma - 1;
|
|
Packit Service |
a4b2a9 |
while (*comma == ' ' || *comma == '\t')
|
|
Packit Service |
a4b2a9 |
end--;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
o_len = end - cp + 1;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (_strncmp("proto=rdma", cp, o_len) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("rdma", cp, o_len) == 0)
|
|
Packit Service |
a4b2a9 |
rdma = 1;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (_strncmp("nosymlink", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
warn(ap->logopt, MODPREFIX
|
|
Packit Service |
a4b2a9 |
"the \"nosymlink\" option is depricated "
|
|
Packit Service |
a4b2a9 |
"and will soon be removed, "
|
|
Packit Service |
a4b2a9 |
"use the \"nobind\" option instead");
|
|
Packit Service |
a4b2a9 |
nosymlink = 1;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("symlink", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
if (*name != '/')
|
|
Packit Service |
a4b2a9 |
symlink = 1;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("nobind", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
nobind = 1;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("no-use-weight-only", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
flags &= ~MOUNT_FLAG_USE_WEIGHT_ONLY;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("use-weight-only", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
flags |= MOUNT_FLAG_USE_WEIGHT_ONLY;
|
|
Packit Service |
a4b2a9 |
} else {
|
|
Packit Service |
a4b2a9 |
/* Is any version of NFSv4 in the options */
|
|
Packit Service |
a4b2a9 |
if (_strncmp("vers=4", cp, 6) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("nfsvers=4", cp, 9) == 0)
|
|
Packit Service |
a4b2a9 |
vers = NFS4_VERS_MASK | TCP_SUPPORTED;
|
|
Packit Service |
a4b2a9 |
else if (_strncmp("vers=3", cp, o_len) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("nfsvers=3", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK);
|
|
Packit Service |
a4b2a9 |
vers |= NFS3_REQUESTED;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("vers=2", cp, o_len) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("nfsvers=2", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
vers &= ~(NFS4_VERS_MASK | NFS_VERS_MASK);
|
|
Packit Service |
a4b2a9 |
vers |= NFS2_REQUESTED;
|
|
Packit Service |
a4b2a9 |
} else if (strstr(cp, "port=") == cp &&
|
|
Packit Service |
a4b2a9 |
o_len - 5 < 25) {
|
|
Packit Service |
a4b2a9 |
char optport[25];
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
strncpy(optport, cp + 5, o_len - 5);
|
|
Packit Service |
a4b2a9 |
optport[o_len - 5] = '\0';
|
|
Packit Service |
a4b2a9 |
port = atoi(optport);
|
|
Packit Service |
a4b2a9 |
if (port < 0)
|
|
Packit Service |
a4b2a9 |
port = 0;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("proto=udp", cp, o_len) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("udp", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
vers &= ~TCP_SUPPORTED;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("proto=udp6", cp, o_len) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("udp6", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
vers &= ~TCP_SUPPORTED;
|
|
Packit Service |
a4b2a9 |
vers |= UDP6_REQUESTED;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("proto=tcp", cp, o_len) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("tcp", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
vers &= ~UDP_SUPPORTED;
|
|
Packit Service |
a4b2a9 |
} else if (_strncmp("proto=tcp6", cp, o_len) == 0 ||
|
|
Packit Service |
a4b2a9 |
_strncmp("tcp6", cp, o_len) == 0) {
|
|
Packit Service |
a4b2a9 |
vers &= ~UDP_SUPPORTED;
|
|
Packit Service |
a4b2a9 |
vers |= TCP6_REQUESTED;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
/* Check for options that also make sense
|
|
Packit Service |
a4b2a9 |
with bind mounts */
|
|
Packit Service |
a4b2a9 |
else if (_strncmp("ro", cp, o_len) == 0)
|
|
Packit Service |
a4b2a9 |
ro = 1;
|
|
Packit Service |
a4b2a9 |
else if (_strncmp("rw", cp, o_len) == 0)
|
|
Packit Service |
a4b2a9 |
ro = 0;
|
|
Packit Service |
a4b2a9 |
/* and jump over trailing white space */
|
|
Packit Service |
a4b2a9 |
memcpy(nfsp, cp, comma - cp + 1);
|
|
Packit Service |
a4b2a9 |
nfsp += comma - cp + 1;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* In case both tcp and udp options were given */
|
|
Packit Service |
a4b2a9 |
if ((vers & NFS_PROTO_MASK) == 0)
|
|
Packit Service |
a4b2a9 |
vers |= NFS_PROTO_MASK;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
debug(ap->logopt, MODPREFIX
|
|
Packit Service |
a4b2a9 |
"nfs options=\"%s\", nobind=%d, nosymlink=%d, ro=%d",
|
|
Packit Service |
a4b2a9 |
nfsoptions, nobind, nosymlink, ro);
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (!parse_location(ap->logopt, &hosts, what, flags)) {
|
|
Packit Service |
a4b2a9 |
info(ap->logopt, MODPREFIX "no hosts available");
|
|
Packit Service |
a4b2a9 |
return 1;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
/*
|
|
Packit Service |
a4b2a9 |
* We can't probe protocol rdma so leave it to mount.nfs(8)
|
|
Packit Service |
a4b2a9 |
* and and suffer the delay if a server isn't available.
|
|
Packit Service |
a4b2a9 |
*/
|
|
Packit Service |
a4b2a9 |
if (rdma)
|
|
Packit Service |
a4b2a9 |
goto dont_probe;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/*
|
|
Packit Service |
a4b2a9 |
* If this is a singleton mount, and NFSv4 only hasn't been asked
|
|
Packit Service |
a4b2a9 |
* for, and the default NFS protocol is set to v4 in the autofs
|
|
Packit Service |
a4b2a9 |
* configuration only probe NFSv4 and let mount.nfs(8) do fallback
|
|
Packit Service |
a4b2a9 |
* to NFSv3 (if it can). If the NFSv4 probe fails then probe as
|
|
Packit Service |
a4b2a9 |
* normal.
|
|
Packit Service |
a4b2a9 |
*
|
|
Packit Service |
a4b2a9 |
* Note: some NFS servers consider it a protocol violation to use
|
|
Packit Service |
a4b2a9 |
* NFSv4 over UDP so if it has been requested in the mount options
|
|
Packit Service |
a4b2a9 |
* we can't use this at all.
|
|
Packit Service |
a4b2a9 |
*/
|
|
Packit Service |
a4b2a9 |
if ((hosts && !hosts->next) &&
|
|
Packit Service |
a4b2a9 |
mount_default_proto == 4 &&
|
|
Packit Service |
a4b2a9 |
(vers & NFS_VERS_MASK) != 0 &&
|
|
Packit Service |
a4b2a9 |
(vers & NFS4_VERS_MASK) != 0 &&
|
|
Packit Service |
a4b2a9 |
!(vers & UDP6_REQUESTED)) {
|
|
Packit Service |
a4b2a9 |
unsigned int v4_probe_ok = 0;
|
|
Packit Service |
c687e0 |
struct host *tmp = new_host(hosts->name, 0,
|
|
Packit Service |
a4b2a9 |
hosts->addr, hosts->addr_len,
|
|
Packit Service |
a4b2a9 |
hosts->proximity,
|
|
Packit Service |
a4b2a9 |
hosts->weight, hosts->options);
|
|
Packit Service |
a4b2a9 |
if (tmp) {
|
|
Packit Service |
a4b2a9 |
tmp->rr = hosts->rr;
|
|
Packit Service |
a4b2a9 |
prune_host_list(ap->logopt, &tmp,
|
|
Packit Service |
a4b2a9 |
NFS4_VERS_MASK|TCP_SUPPORTED, port);
|
|
Packit Service |
a4b2a9 |
/* If probe succeeds just try the mount with host in hosts */
|
|
Packit Service |
a4b2a9 |
if (tmp) {
|
|
Packit Service |
a4b2a9 |
v4_probe_ok = 1;
|
|
Packit Service |
a4b2a9 |
free_host_list(&tmp);
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
if (!v4_probe_ok)
|
|
Packit Service |
a4b2a9 |
prune_host_list(ap->logopt, &hosts, vers, port);
|
|
Packit Service |
a4b2a9 |
} else {
|
|
Packit Service |
a4b2a9 |
prune_host_list(ap->logopt, &hosts, vers, port);
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
dont_probe:
|
|
Packit Service |
a4b2a9 |
if (!hosts) {
|
|
Packit Service |
a4b2a9 |
info(ap->logopt, MODPREFIX "no hosts available");
|
|
Packit Service |
a4b2a9 |
return 1;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Construct and perhaps create mount point directory */
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Root offset of multi-mount */
|
|
Packit Service |
a4b2a9 |
len = strlen(root);
|
|
Packit Service |
a4b2a9 |
if (root[len - 1] == '/') {
|
|
Packit Service |
a4b2a9 |
len = snprintf(fullpath, len, "%s", root);
|
|
Packit Service |
a4b2a9 |
} else if (*name == '/') {
|
|
Packit Service |
a4b2a9 |
len = sprintf(fullpath, "%s", root);
|
|
Packit Service |
a4b2a9 |
} else {
|
|
Packit Service |
a4b2a9 |
len = sprintf(fullpath, "%s/%s", root, name);
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
fullpath[len] = '\0';
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
debug(ap->logopt, MODPREFIX "calling mkdir_path %s", fullpath);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
15cf98 |
status = mkdir_path(fullpath, mp_mode);
|
|
Packit Service |
a4b2a9 |
if (status && errno != EEXIST) {
|
|
Packit Service |
a4b2a9 |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit Service |
a4b2a9 |
error(ap->logopt,
|
|
Packit Service |
a4b2a9 |
MODPREFIX "mkdir_path %s failed: %s", fullpath, estr);
|
|
Packit Service |
a4b2a9 |
free_host_list(&hosts);
|
|
Packit Service |
a4b2a9 |
return 1;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (!status)
|
|
Packit Service |
a4b2a9 |
existed = 0;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
this = hosts;
|
|
Packit Service |
a4b2a9 |
while (this) {
|
|
Packit Service |
a4b2a9 |
char *loc;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Port option specified, don't try to bind */
|
|
Packit Service |
a4b2a9 |
if (!(nosymlink || nobind) &&
|
|
Packit Service |
a4b2a9 |
this->proximity == PROXIMITY_LOCAL) {
|
|
Packit Service |
a4b2a9 |
/* Local host -- do a "bind" */
|
|
Packit Service |
a4b2a9 |
const char *bind_options;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
debug(ap->logopt,
|
|
Packit Service |
a4b2a9 |
MODPREFIX "%s is local, attempt bind mount",
|
|
Packit Service |
a4b2a9 |
name);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
bind_options = symlink ? "symlink" : ro ? "ro" : "";
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
err = mount_bind->mount_mount(ap, root, name, name_len,
|
|
Packit Service |
a4b2a9 |
this->path, "bind", bind_options,
|
|
Packit Service |
a4b2a9 |
mount_bind->context);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Success - we're done */
|
|
Packit Service |
a4b2a9 |
if (!err) {
|
|
Packit Service |
a4b2a9 |
free_host_list(&hosts);
|
|
Packit Service |
a4b2a9 |
return 0;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Failed to update mtab, don't try any more */
|
|
Packit Service |
a4b2a9 |
if (err == MNT_FORCE_FAIL)
|
|
Packit Service |
a4b2a9 |
goto forced_fail;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* No hostname, can't be NFS */
|
|
Packit Service |
a4b2a9 |
if (!this->name) {
|
|
Packit Service |
a4b2a9 |
this = this->next;
|
|
Packit Service |
a4b2a9 |
continue;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* Not a local host - do an NFS mount */
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (this->rr && this->addr &&
|
|
Packit Service |
a4b2a9 |
!defaults_use_hostname_for_mounts()) {
|
|
Packit Service |
a4b2a9 |
socklen_t len = INET6_ADDRSTRLEN;
|
|
Packit Service |
a4b2a9 |
char n_buf[len + 1];
|
|
Packit Service |
a4b2a9 |
const char *n_addr;
|
|
Packit Service |
6acc18 |
|
|
Packit Service |
a4b2a9 |
n_addr = get_addr_string(this->addr, n_buf, len);
|
|
Packit Service |
6acc18 |
if (!n_addr) {
|
|
Packit Service |
6acc18 |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit Service |
6acc18 |
error(ap->logopt, "get_addr_string: %s", estr);
|
|
Packit Service |
6acc18 |
goto forced_fail;
|
|
Packit Service |
6acc18 |
}
|
|
Packit Service |
a4b2a9 |
loc = malloc(strlen(n_addr) + strlen(this->path) + 4);
|
|
Packit Service |
a4b2a9 |
if (!loc) {
|
|
Packit Service |
a4b2a9 |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit Service |
a4b2a9 |
error(ap->logopt, "malloc: %s", estr);
|
|
Packit Service |
a4b2a9 |
goto forced_fail;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
if (this->addr->sa_family == AF_INET6) {
|
|
Packit Service |
a4b2a9 |
strcpy(loc, "[");
|
|
Packit Service |
a4b2a9 |
strcat(loc, n_addr);
|
|
Packit Service |
a4b2a9 |
strcat(loc, "]");
|
|
Packit Service |
a4b2a9 |
} else
|
|
Packit Service |
a4b2a9 |
strcpy(loc, n_addr);
|
|
Packit Service |
a4b2a9 |
} else {
|
|
Packit Service |
a4b2a9 |
char *host = this->name ? this->name : "localhost";
|
|
Packit Service |
a4b2a9 |
loc = malloc(strlen(host) + strlen(this->path) + 2);
|
|
Packit Service |
a4b2a9 |
if (!loc) {
|
|
Packit Service |
a4b2a9 |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit Service |
a4b2a9 |
error(ap->logopt, "malloc: %s", estr);
|
|
Packit Service |
a4b2a9 |
goto forced_fail;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
strcpy(loc, host);
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
strcat(loc, ":");
|
|
Packit Service |
a4b2a9 |
strcat(loc, this->path);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* If this is a fallback from a bind mount failure
|
|
Packit Service |
a4b2a9 |
* check if the local NFS server is available to try
|
|
Packit Service |
a4b2a9 |
* and prevent lengthy mount failure waits.
|
|
Packit Service |
a4b2a9 |
*/
|
|
Packit Service |
a4b2a9 |
if (this->proximity == PROXIMITY_LOCAL) {
|
|
Packit Service |
a4b2a9 |
char *host = this->name ? this->name : "localhost";
|
|
Packit Service |
a4b2a9 |
int ret;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
ret = rpc_ping(host, port, vers, 2, 0, RPC_CLOSE_DEFAULT);
|
|
Packit Service |
a4b2a9 |
if (ret <= 0)
|
|
Packit Service |
a4b2a9 |
goto next;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (nfsoptions && *nfsoptions) {
|
|
Packit Service |
a4b2a9 |
debug(ap->logopt,
|
|
Packit Service |
a4b2a9 |
MODPREFIX "calling mount -t %s " SLOPPY
|
|
Packit Service |
a4b2a9 |
"-o %s %s %s", fstype, nfsoptions, loc, fullpath);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
err = spawn_mount(ap->logopt,
|
|
Packit Service |
a4b2a9 |
"-t", fstype, SLOPPYOPT "-o",
|
|
Packit Service |
a4b2a9 |
nfsoptions, loc, fullpath, NULL);
|
|
Packit Service |
a4b2a9 |
} else {
|
|
Packit Service |
a4b2a9 |
debug(ap->logopt,
|
|
Packit Service |
a4b2a9 |
MODPREFIX "calling mount -t %s %s %s",
|
|
Packit Service |
a4b2a9 |
fstype, loc, fullpath);
|
|
Packit Service |
a4b2a9 |
err = spawn_mount(ap->logopt,
|
|
Packit Service |
a4b2a9 |
"-t", fstype, loc, fullpath, NULL);
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (!err) {
|
|
Packit Service |
a4b2a9 |
debug(ap->logopt, MODPREFIX "mounted %s on %s", loc, fullpath);
|
|
Packit Service |
a4b2a9 |
free(loc);
|
|
Packit Service |
a4b2a9 |
free_host_list(&hosts);
|
|
Packit Service |
a4b2a9 |
return 0;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
next:
|
|
Packit Service |
a4b2a9 |
free(loc);
|
|
Packit Service |
a4b2a9 |
this = this->next;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
forced_fail:
|
|
Packit Service |
a4b2a9 |
free_host_list(&hosts);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
/* If we get here we've failed to complete the mount */
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
info(ap->logopt, MODPREFIX "nfs: mount failure %s on %s", what, fullpath);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (ap->type != LKP_INDIRECT)
|
|
Packit Service |
a4b2a9 |
return 1;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if ((!(ap->flags & MOUNT_FLAG_GHOST) && name_len) || !existed)
|
|
Packit Service |
a4b2a9 |
rmdir_path(ap, fullpath, ap->dev);
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
return 1;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
int mount_done(void *context)
|
|
Packit Service |
a4b2a9 |
{
|
|
Packit Service |
a4b2a9 |
int rv = 0;
|
|
Packit Service |
a4b2a9 |
|
|
Packit Service |
a4b2a9 |
if (--init_ctr == 0) {
|
|
Packit Service |
a4b2a9 |
rv = close_mount(mount_bind);
|
|
Packit Service |
a4b2a9 |
mount_bind = NULL;
|
|
Packit Service |
a4b2a9 |
}
|
|
Packit Service |
a4b2a9 |
return rv;
|
|
Packit Service |
a4b2a9 |
}
|