|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* master.c - master map utility routines.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 2006 Ian Kent <raven@themaw.net>
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8480eb |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8480eb |
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
|
Packit |
8480eb |
* USA; either version 2 of the License, or (at your option) any later
|
|
Packit |
8480eb |
* version.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
8480eb |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8480eb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8480eb |
* GNU General Public License for more details.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* ----------------------------------------------------------------------- */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include <stdlib.h>
|
|
Packit |
8480eb |
#include <string.h>
|
|
Packit |
8480eb |
#include <memory.h>
|
|
Packit |
8480eb |
#include <limits.h>
|
|
Packit |
8480eb |
#include <signal.h>
|
|
Packit |
8480eb |
#include <sys/types.h>
|
|
Packit |
8480eb |
#include <sys/stat.h>
|
|
Packit |
8480eb |
#include <ctype.h>
|
|
Packit |
8480eb |
#include "automount.h"
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* The root of the map entry tree */
|
|
Packit |
8480eb |
struct master *master_list = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
extern const char *global_options;
|
|
Packit |
8480eb |
extern long global_negative_timeout;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Attribute to create a joinable thread */
|
|
Packit |
8480eb |
extern pthread_attr_t th_attr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
extern struct startup_cond suc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct map_source *
|
|
Packit |
8480eb |
__master_find_map_source(struct master_mapent *,
|
|
Packit |
8480eb |
const char *, const char *, int, const char **);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static pthread_mutex_t master_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
8480eb |
static pthread_mutex_t instance_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_mutex_lock(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status = pthread_mutex_lock(&master_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_mutex_unlock(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status = pthread_mutex_unlock(&master_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_mutex_lock_cleanup(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_add_autofs_point(struct master_mapent *entry, unsigned logopt,
|
|
Packit |
8480eb |
unsigned nobind, unsigned ghost, int submount)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = malloc(sizeof(struct autofs_point));
|
|
Packit |
8480eb |
if (!ap)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->state = ST_INIT;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->state_pipe[0] = -1;
|
|
Packit |
8480eb |
ap->state_pipe[1] = -1;
|
|
Packit |
8480eb |
ap->logpri_fifo = -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->path = strdup(entry->path);
|
|
Packit |
8480eb |
if (!ap->path) {
|
|
Packit |
8480eb |
free(ap);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ap->pref = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->entry = entry;
|
|
Packit |
8480eb |
ap->exp_thread = 0;
|
|
Packit |
8480eb |
ap->readmap_thread = 0;
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Program command line option overrides config.
|
|
Packit |
8480eb |
* We can't use 0 negative timeout so use default.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (global_negative_timeout <= 0)
|
|
Packit |
8480eb |
ap->negative_timeout = defaults_get_negative_timeout();
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
ap->negative_timeout = global_negative_timeout;
|
|
Packit |
8480eb |
ap->exp_timeout = defaults_get_timeout();
|
|
Packit |
8480eb |
ap->exp_runfreq = 0;
|
|
Packit |
121cba |
ap->flags = MOUNT_FLAG_IGNORE;
|
|
Packit |
8480eb |
if (ghost)
|
|
Packit |
121cba |
ap->flags |= MOUNT_FLAG_GHOST;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (nobind)
|
|
Packit |
8480eb |
ap->flags |= MOUNT_FLAG_NOBIND;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->path[1] == '-')
|
|
Packit |
8480eb |
ap->type = LKP_DIRECT;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
ap->type = LKP_INDIRECT;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->logopt = logopt;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap->parent = NULL;
|
|
Packit |
8480eb |
ap->thid = 0;
|
|
Packit |
8480eb |
ap->submnt_count = 0;
|
|
Packit |
8480eb |
ap->submount = submount;
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ap->mounts);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ap->submounts);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&ap->amdmounts);
|
|
Packit |
8480eb |
ap->shutdown = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_init(&ap->mounts_mutex, NULL);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
free(ap->path);
|
|
Packit |
8480eb |
free(ap);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
ap->mode = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry->ap = ap;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_free_autofs_point(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!ap)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
head = &ap->amdmounts;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct amd_entry *entry = list_entry(p, struct amd_entry, entries);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
if (!list_empty(&entry->ext_mount))
|
|
Packit |
8480eb |
ext_mount_remove(&entry->ext_mount, entry->fs);
|
|
Packit |
8480eb |
if (!list_empty(&entry->entries))
|
|
Packit |
8480eb |
list_del(&entry->entries);
|
|
Packit |
d47386 |
free_amd_entry(entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_destroy(&ap->mounts_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->pref)
|
|
Packit |
8480eb |
free(ap->pref);
|
|
Packit |
8480eb |
free(ap->path);
|
|
Packit |
8480eb |
free(ap);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct map_source *
|
|
Packit |
8480eb |
master_add_map_source(struct master_mapent *entry,
|
|
Packit |
8480eb |
char *type, char *format, time_t age,
|
|
Packit |
8480eb |
int argc, const char **argv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
char *ntype, *nformat;
|
|
Packit |
8480eb |
const char **tmpargv;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = malloc(sizeof(struct map_source));
|
|
Packit |
8480eb |
if (!source)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
memset(source, 0, sizeof(struct map_source));
|
|
Packit |
8480eb |
source->ref = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type) {
|
|
Packit |
8480eb |
ntype = strdup(type);
|
|
Packit |
8480eb |
if (!ntype) {
|
|
Packit |
8480eb |
master_free_map_source(source, 0);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
source->type = ntype;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (format) {
|
|
Packit |
8480eb |
nformat = strdup(format);
|
|
Packit |
8480eb |
if (!nformat) {
|
|
Packit |
8480eb |
master_free_map_source(source, 0);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
source->format = nformat;
|
|
Packit |
8480eb |
if (!strcmp(nformat, "amd"))
|
|
Packit |
8480eb |
source->flags |= MAP_FLAG_FORMAT_AMD;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source->age = age;
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmpargv = copy_argv(argc, argv);
|
|
Packit |
8480eb |
if (!tmpargv) {
|
|
Packit |
8480eb |
master_free_map_source(source, 0);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
source->argc = argc;
|
|
Packit |
8480eb |
source->argv = tmpargv;
|
|
Packit |
8480eb |
if (source->argv[0])
|
|
Packit |
8480eb |
source->name = strdup(source->argv[0]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_writelock(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!entry->maps) {
|
|
Packit |
8480eb |
source->mc = cache_init(entry->ap, source);
|
|
Packit |
8480eb |
if (!source->mc) {
|
|
Packit |
8480eb |
master_free_map_source(source, 0);
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
entry->maps = source;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
struct map_source *this, *last, *next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Typically there only a few map sources */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = __master_find_map_source(entry, type, format, argc, tmpargv);
|
|
Packit |
8480eb |
if (this) {
|
|
Packit |
8480eb |
debug(entry->ap->logopt,
|
|
Packit |
8480eb |
"map source used without taking reference");
|
|
Packit |
8480eb |
this->age = age;
|
|
Packit |
8480eb |
master_free_map_source(source, 0);
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
return this;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source->mc = cache_init(entry->ap, source);
|
|
Packit |
8480eb |
if (!source->mc) {
|
|
Packit |
8480eb |
master_free_map_source(source, 0);
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
last = NULL;
|
|
Packit |
8480eb |
next = entry->maps;
|
|
Packit |
8480eb |
while (next) {
|
|
Packit |
8480eb |
last = next;
|
|
Packit |
8480eb |
next = next->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (last)
|
|
Packit |
8480eb |
last->next = source;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
entry->maps = source;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return source;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int compare_source_type_and_format(struct map_source *map, const char *type, const char *format)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int res = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type) {
|
|
Packit |
8480eb |
if (!map->type)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strcmp(map->type, type))
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
} else if (map->type)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (format) {
|
|
Packit |
8480eb |
if (!map->format)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strcmp(map->format, format))
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
} else if (map->format)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
res = 1;
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
return res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct map_source *
|
|
Packit |
8480eb |
__master_find_map_source(struct master_mapent *entry,
|
|
Packit |
8480eb |
const char *type, const char *format,
|
|
Packit |
8480eb |
int argc, const char **argv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
struct map_source *source = NULL;
|
|
Packit |
8480eb |
int res;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = entry->maps;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
res = compare_source_type_and_format(map, type, format);
|
|
Packit |
8480eb |
if (!res)
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
res = compare_argv(map->argc, map->argv, argc, argv);
|
|
Packit |
8480eb |
if (!res)
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = map;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return source;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct map_source *master_find_map_source(struct master_mapent *entry,
|
|
Packit |
8480eb |
const char *type, const char *format,
|
|
Packit |
8480eb |
int argc, const char **argv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *source = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_readlock(entry);
|
|
Packit |
8480eb |
source = __master_find_map_source(entry, type, format, argc, argv);
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return source;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct map_source *
|
|
Packit |
8480eb |
master_get_map_source(struct master_mapent *entry,
|
|
Packit |
8480eb |
const char *type, const char *format,
|
|
Packit |
8480eb |
int argc, const char **argv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *source = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_readlock(entry);
|
|
Packit |
8480eb |
source = __master_find_map_source(entry, type, format, argc, argv);
|
|
Packit |
8480eb |
if (source)
|
|
Packit |
8480eb |
source->ref++;
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return source;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
/* instance map sources are not ref counted */
|
|
Packit |
8480eb |
if (source->ref && --source->ref)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
if (source->type)
|
|
Packit |
8480eb |
free(source->type);
|
|
Packit |
8480eb |
if (source->format)
|
|
Packit |
8480eb |
free(source->format);
|
|
Packit |
8480eb |
if (source->name)
|
|
Packit |
8480eb |
free(source->name);
|
|
Packit |
8480eb |
if (free_cache && source->mc)
|
|
Packit |
8480eb |
cache_release(source);
|
|
Packit |
8480eb |
if (source->lookup) {
|
|
Packit |
8480eb |
struct map_source *instance;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance = source->instance;
|
|
Packit |
8480eb |
while (instance) {
|
|
Packit |
8480eb |
if (instance->lookup)
|
|
Packit |
8480eb |
close_lookup(instance->lookup);
|
|
Packit |
8480eb |
instance = instance->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
close_lookup(source->lookup);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (source->argv)
|
|
Packit |
8480eb |
free_argv(source->argc, source->argv);
|
|
Packit |
8480eb |
if (source->instance) {
|
|
Packit |
8480eb |
struct map_source *instance, *next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance = source->instance;
|
|
Packit |
8480eb |
while (instance) {
|
|
Packit |
8480eb |
next = instance->next;
|
|
Packit |
8480eb |
__master_free_map_source(instance, 0);
|
|
Packit |
8480eb |
instance = next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(source);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_free_map_source(struct map_source *source, unsigned int free_cache)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
__master_free_map_source(source, free_cache);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct map_source *master_find_source_instance(struct map_source *source, const char *type, const char *format, int argc, const char **argv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
struct map_source *instance = NULL;
|
|
Packit |
8480eb |
int status, res;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = source->instance;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
res = compare_source_type_and_format(map, type, format);
|
|
Packit |
8480eb |
if (!res)
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!argv) {
|
|
Packit |
8480eb |
instance = map;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
res = compare_argv(map->argc, map->argv, argc, argv);
|
|
Packit |
8480eb |
if (!res)
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance = map;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return instance;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct map_source *
|
|
Packit |
8480eb |
master_add_source_instance(struct map_source *source, const char *type, const char *format, time_t age, int argc, const char **argv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *instance;
|
|
Packit |
8480eb |
struct map_source *new;
|
|
Packit |
8480eb |
char *ntype, *nformat;
|
|
Packit |
8480eb |
const char **tmpargv;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance = master_find_source_instance(source, type, format, argc, argv);
|
|
Packit |
8480eb |
if (instance)
|
|
Packit |
8480eb |
return instance;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new = malloc(sizeof(struct map_source));
|
|
Packit |
8480eb |
if (!new)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
memset(new, 0, sizeof(struct map_source));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type) {
|
|
Packit |
8480eb |
ntype = strdup(type);
|
|
Packit |
8480eb |
if (!ntype) {
|
|
Packit |
8480eb |
master_free_map_source(new, 0);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
new->type = ntype;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (format) {
|
|
Packit |
8480eb |
nformat = strdup(format);
|
|
Packit |
8480eb |
if (!nformat) {
|
|
Packit |
8480eb |
master_free_map_source(new, 0);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
new->format = nformat;
|
|
Packit |
8480eb |
if (!strcmp(nformat, "amd"))
|
|
Packit |
8480eb |
new->flags |= MAP_FLAG_FORMAT_AMD;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
new->age = age;
|
|
Packit |
8480eb |
new->master_line = 0;
|
|
Packit |
8480eb |
new->mc = source->mc;
|
|
Packit |
8480eb |
new->exp_timeout = source->exp_timeout;
|
|
Packit |
8480eb |
new->stale = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmpargv = copy_argv(argc, argv);
|
|
Packit |
8480eb |
if (!tmpargv) {
|
|
Packit |
8480eb |
master_free_map_source(new, 0);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
new->argc = argc;
|
|
Packit |
8480eb |
new->argv = tmpargv;
|
|
Packit |
8480eb |
if (source->name)
|
|
Packit |
8480eb |
new->name = strdup(source->name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!source->instance)
|
|
Packit |
8480eb |
source->instance = new;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* We know there's no other instance of this
|
|
Packit |
8480eb |
* type so just add to head of list
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
new->next = source->instance;
|
|
Packit |
8480eb |
source->instance = new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int check_stale_instances(struct map_source *source)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!source)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = source->instance;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
if (map->stale)
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
if (check_stale_instances(map))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void clear_stale_instances(struct map_source *source)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!source)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = source->instance;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
clear_stale_instances(map);
|
|
Packit |
8480eb |
if (map->stale)
|
|
Packit |
8480eb |
map->stale = 0;
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void send_map_update_request(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
int status, need_update = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = ap->entry->maps;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
if (check_stale_instances(map))
|
|
Packit |
8480eb |
map->stale = 1;
|
|
Packit |
8480eb |
if (map->stale) {
|
|
Packit |
8480eb |
need_update = 1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&instance_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!need_update)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_add_task(ap, ST_READMAP);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_source_writelock(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_rwlock_wrlock(&entry->source_lock);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logmsg("master_mapent source write lock failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_source_readlock(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int retries = 25;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (retries--) {
|
|
Packit |
8480eb |
status = pthread_rwlock_rdlock(&entry->source_lock);
|
|
Packit |
8480eb |
if (status != EAGAIN && status != EBUSY)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
struct timespec t = { 0, 200000000 };
|
|
Packit |
8480eb |
struct timespec r;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (status == EAGAIN)
|
|
Packit |
8480eb |
logmsg("master_mapent source too many readers");
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
logmsg("master_mapent source write lock held");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (nanosleep(&t, &r) == -1 && errno == EINTR)
|
|
Packit |
8480eb |
memcpy(&t, &r, sizeof(struct timespec));
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logmsg("master_mapent source read lock failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_source_unlock(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_rwlock_unlock(&entry->source_lock);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logmsg("master_mapent source unlock failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_source_lock_cleanup(void *arg)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master_mapent *entry = (struct master_mapent *) arg;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_source_current_wait(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_lock(&entry->current_mutex);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logmsg("entry current source lock failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (entry->current != NULL) {
|
|
Packit |
8480eb |
status = pthread_cond_wait(
|
|
Packit |
8480eb |
&entry->current_cond, &entry->current_mutex);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logmsg("entry current source condition wait failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_source_current_signal(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_cond_signal(&entry->current_cond);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logmsg("entry current source condition signal failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_unlock(&entry->current_mutex);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
logmsg("entry current source unlock failed");
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct master_mapent *master_find_mapent(struct master *master, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(entry->path, path))
|
|
Packit |
8480eb |
return entry;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int master_partial_match_mapent(struct master *master, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
size_t path_len = strlen(path);
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
size_t entry_len;
|
|
Packit |
8480eb |
size_t cmp_len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry_len = strlen(entry->path);
|
|
Packit |
8480eb |
cmp_len = min(entry_len, path_len);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strncmp(entry->path, path, cmp_len)) {
|
|
Packit |
8480eb |
/* paths are equal, matching master map entry ? */
|
|
Packit |
8480eb |
if (entry_len == path_len) {
|
|
Packit |
8480eb |
if (entry->maps &&
|
|
Packit |
8480eb |
entry->maps->flags & MAP_FLAG_FORMAT_AMD)
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
ret = -1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* amd mount conflicts with entry mount */
|
|
Packit |
8480eb |
if (entry_len > path_len &&
|
|
Packit |
8480eb |
*(entry->path + path_len) == '/') {
|
|
Packit |
8480eb |
ret = -1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* entry mount conflicts with amd mount */
|
|
Packit |
8480eb |
if (entry_len < path_len &&
|
|
Packit |
8480eb |
*(path + entry_len) == '/') {
|
|
Packit |
8480eb |
ret = -1;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct autofs_point *__master_find_submount(struct autofs_point *ap, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &ap->submounts;
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
struct autofs_point *submount;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
submount = list_entry(p, struct autofs_point, mounts);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(submount->path, path))
|
|
Packit |
8480eb |
return submount;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct autofs_point *master_find_submount(struct autofs_point *ap, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct autofs_point *submount;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
submount = __master_find_submount(ap, path);
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return submount;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct amd_entry *__master_find_amdmount(struct autofs_point *ap, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &ap->amdmounts;
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
struct amd_entry *entry;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = list_entry(p, struct amd_entry, entries);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(entry->path, path))
|
|
Packit |
8480eb |
return entry;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct amd_entry *master_find_amdmount(struct autofs_point *ap, const char *path)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct amd_entry *entry;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
entry = __master_find_amdmount(ap, path);
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return entry;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = malloc(sizeof(struct master_mapent));
|
|
Packit |
8480eb |
if (!entry)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
memset(entry, 0, sizeof(struct master_mapent));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = strdup(path);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
free(entry);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
entry->path = tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry->thid = 0;
|
|
Packit |
8480eb |
entry->age = age;
|
|
Packit |
8480eb |
entry->master = master;
|
|
Packit |
8480eb |
entry->current = NULL;
|
|
Packit |
8480eb |
entry->maps = NULL;
|
|
Packit |
8480eb |
entry->ap = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_rwlock_init(&entry->source_lock, NULL);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_init(&entry->current_mutex, NULL);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_cond_init(&entry->current_cond, NULL);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&entry->list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return entry;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_add_mapent(struct master *master, struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
list_add_tail(&entry->list, &master->mounts);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_remove_mapent(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master *master = entry->master;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->ap->submount)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!list_empty(&entry->list)) {
|
|
Packit |
8480eb |
list_del_init(&entry->list);
|
|
Packit |
8480eb |
list_add(&entry->join, &master->completed);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_free_mapent_sources(struct master_mapent *entry, unsigned int free_cache)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (entry->maps) {
|
|
Packit |
8480eb |
struct map_source *m, *n;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
m = entry->maps;
|
|
Packit |
8480eb |
while (m) {
|
|
Packit |
8480eb |
n = m->next;
|
|
Packit |
8480eb |
master_free_map_source(m, free_cache);
|
|
Packit |
8480eb |
m = n;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
entry->maps = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_free_mapent(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->path)
|
|
Packit |
8480eb |
free(entry->path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_free_autofs_point(entry->ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_rwlock_destroy(&entry->source_lock);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_mutex_destroy(&entry->current_mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_cond_destroy(&entry->current_cond);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
756a1b |
struct master *master_new(const char *name, unsigned int timeout, unsigned int flags)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master *master;
|
|
Packit |
8480eb |
char *tmp;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master = malloc(sizeof(struct master));
|
|
Packit |
8480eb |
if (!master)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!name)
|
|
Packit |
8480eb |
tmp = (char *) defaults_get_master_map();
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
tmp = strdup(name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
free(master);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master->name = tmp;
|
|
Packit |
8480eb |
master->nc = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master->recurse = 0;
|
|
Packit |
8480eb |
master->depth = 0;
|
|
Packit |
8480eb |
master->reading = 0;
|
|
Packit |
8480eb |
master->read_fail = 0;
|
|
Packit |
756a1b |
master->default_ghost = flags & DAEMON_FLAGS_GHOST;
|
|
Packit |
8480eb |
master->default_timeout = timeout;
|
|
Packit |
8480eb |
master->default_logging = defaults_get_logging();
|
|
Packit |
8480eb |
master->logopt = master->default_logging;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&master->mounts);
|
|
Packit |
8480eb |
INIT_LIST_HEAD(&master->completed);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return master;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void master_add_amd_mount_section_mounts(struct master *master, time_t age)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int m_logopt = master->logopt;
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
unsigned int loglevel;
|
|
Packit |
8480eb |
unsigned int logopt;
|
|
Packit |
8480eb |
unsigned int flags;
|
|
Packit |
8480eb |
char *argv[2];
|
|
Packit |
8480eb |
char **paths;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
int i;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
loglevel = conf_amd_get_log_options();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
paths = conf_amd_get_mount_paths();
|
|
Packit |
8480eb |
if (!paths)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
i = 0;
|
|
Packit |
8480eb |
while (paths[i]) {
|
|
Packit |
8480eb |
const char *path = paths[i];
|
|
Packit |
8480eb |
unsigned int ghost = 0;
|
|
Packit |
8480eb |
time_t timeout;
|
|
Packit |
8480eb |
char *type = NULL;
|
|
Packit |
8480eb |
char *map = NULL;
|
|
Packit |
8480eb |
char *opts;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = master_partial_match_mapent(master, path);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
/* If this amd entry is already present in the
|
|
Packit |
8480eb |
* master map it's not a duplicate, don't issue
|
|
Packit |
8480eb |
* an error message.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ret == 1)
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
info(m_logopt,
|
|
Packit |
8480eb |
"amd section mount path conflict, %s ignored",
|
|
Packit |
8480eb |
path);
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = conf_amd_get_map_name(path);
|
|
Packit |
8480eb |
if (!map) {
|
|
Packit |
8480eb |
error(m_logopt,
|
|
Packit |
8480eb |
"failed to get map name for amd section mount %s",
|
|
Packit |
8480eb |
path);
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = master_new_mapent(master, path, age);
|
|
Packit |
8480eb |
if (!entry) {
|
|
Packit |
8480eb |
error(m_logopt,
|
|
Packit |
8480eb |
"failed to allocate new amd section mount %s",
|
|
Packit |
8480eb |
path);
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
logopt = m_logopt;
|
|
Packit |
8480eb |
if (loglevel <= LOG_DEBUG && loglevel > LOG_INFO)
|
|
Packit |
8480eb |
logopt = LOGOPT_DEBUG;
|
|
Packit |
8480eb |
else if (loglevel <= LOG_INFO && loglevel > LOG_ERR)
|
|
Packit |
8480eb |
logopt = LOGOPT_VERBOSE;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* It isn't possible to provide the fullybrowsable amd
|
|
Packit |
8480eb |
* browsing functionality within the autofs framework.
|
|
Packit |
8480eb |
* This flag will not be set if browsable_dirs = full
|
|
Packit |
8480eb |
* in the configuration or fullybrowsable is present as
|
|
Packit |
8480eb |
* an option.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
flags = conf_amd_get_flags(path);
|
|
Packit |
8480eb |
if (flags & CONF_BROWSABLE_DIRS)
|
|
Packit |
8480eb |
ghost = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = master_add_autofs_point(entry, logopt, 0, ghost, 0);
|
|
Packit |
8480eb |
if (!ret) {
|
|
Packit |
8480eb |
error(m_logopt, "failed to add autofs_point");
|
|
Packit |
8480eb |
master_free_mapent(entry);
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
opts = conf_amd_get_map_options(path);
|
|
Packit |
8480eb |
if (opts) {
|
|
Packit |
8480eb |
/* autofs uses the equivalent of cache:=inc,sync
|
|
Packit |
8480eb |
* (except for file maps which use cache:=all,sync)
|
|
Packit |
8480eb |
* but if the map is large then it may be necessary
|
|
Packit |
8480eb |
* to read the whole map at startup even if browsing
|
|
Packit |
8480eb |
* is is not enabled, so look for cache:=all in the
|
|
Packit |
8480eb |
* map_options configuration entry.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (strstr(opts, "cache:=all"))
|
|
Packit |
8480eb |
entry->ap->flags |= MOUNT_FLAG_AMD_CACHE_ALL;
|
|
Packit |
8480eb |
free(opts);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
type = conf_amd_get_map_type(path);
|
|
Packit |
8480eb |
argv[0] = map;
|
|
Packit |
8480eb |
argv[1] = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = master_add_map_source(entry, type, "amd",
|
|
Packit |
8480eb |
age, 1, (const char **) argv);
|
|
Packit |
8480eb |
if (!source) {
|
|
Packit |
8480eb |
error(m_logopt,
|
|
Packit |
8480eb |
"failed to add source for amd section mount %s",
|
|
Packit |
8480eb |
path);
|
|
Packit |
8480eb |
master_free_mapent(entry);
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
timeout = conf_amd_get_dismount_interval(path);
|
|
Packit |
8480eb |
set_exp_timeout(entry->ap, source, timeout);
|
|
Packit |
8480eb |
source->master_line = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry->age = age;
|
|
Packit |
8480eb |
entry->current = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_add_mapent(master, entry);
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
if (type)
|
|
Packit |
8480eb |
free(type);
|
|
Packit |
8480eb |
if (map)
|
|
Packit |
8480eb |
free(map);
|
|
Packit |
8480eb |
i++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
i = 0;
|
|
Packit |
8480eb |
while (paths[i])
|
|
Packit |
8480eb |
free(paths[i++]);
|
|
Packit |
8480eb |
free(paths);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void wait_for_lookups_and_lock(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
again:
|
|
Packit |
8480eb |
master_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct master_mapent *this;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_rwlock_trywrlock(&this->source_lock);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
struct timespec t = { 0, 200000000 };
|
|
Packit |
8480eb |
struct timespec r;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (nanosleep(&t, &r) == -1 && errno == EINTR)
|
|
Packit |
8480eb |
memcpy(&t, &r, sizeof(struct timespec));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
goto again;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
master_source_unlock(this);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_read_master(struct master *master, time_t age, int readall)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int logopt = master->logopt;
|
|
Packit |
8480eb |
struct mapent_cache *nc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* We need to clear and re-populate the null map entry cache
|
|
Packit |
8480eb |
* before alowing anyone else to use it.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
wait_for_lookups_and_lock(master);
|
|
Packit |
8480eb |
if (master->nc) {
|
|
Packit |
8480eb |
cache_writelock(master->nc);
|
|
Packit |
8480eb |
nc = master->nc;
|
|
Packit |
8480eb |
cache_clean_null_cache(nc);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
nc = cache_init_null_cache(master);
|
|
Packit |
8480eb |
if (!nc) {
|
|
Packit |
8480eb |
error(logopt,
|
|
Packit |
8480eb |
"failed to init null map cache for %s",
|
|
Packit |
8480eb |
master->name);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_writelock(nc);
|
|
Packit |
8480eb |
master->nc = nc;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
master_init_scan();
|
|
Packit |
8480eb |
lookup_nss_read_master(master, age);
|
|
Packit |
8480eb |
cache_unlock(nc);
|
|
Packit |
8480eb |
master_add_amd_mount_section_mounts(master, age);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!master->read_fail)
|
|
Packit |
8480eb |
master_mount_mounts(master, age, readall);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
master->read_fail = 0;
|
|
Packit |
8480eb |
/* HUP signal sets readall == 1 only */
|
|
Packit |
8480eb |
if (!readall) {
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
master_mount_mounts(master, age, readall);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (list_empty(&master->mounts))
|
|
Packit |
8480eb |
warn(logopt, "no mounts in table");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_submount_list_empty(struct autofs_point *ap)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int res = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
if (list_empty(&ap->submounts))
|
|
Packit |
8480eb |
res = 1;
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
struct autofs_point *this = NULL;
|
|
Packit |
8480eb |
int ret = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &ap->submounts;
|
|
Packit |
8480eb |
p = head->prev;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
this = list_entry(p, struct autofs_point, mounts);
|
|
Packit |
8480eb |
p = p->prev;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* path not the same */
|
|
Packit |
8480eb |
if (strcmp(this->path, path))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!master_submount_list_empty(this)) {
|
|
Packit |
8480eb |
char *this_path = strdup(this->path);
|
|
Packit |
8480eb |
if (this_path) {
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
master_notify_submount(this, path, state);
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
if (!__master_find_submount(ap, this_path)) {
|
|
Packit |
8480eb |
free(this_path);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(this_path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Now we have found the submount we want to expire */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (this->state == ST_SHUTDOWN) {
|
|
Packit |
8480eb |
this = NULL;
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this->shutdown = ap->shutdown;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
__st_add_task(this, state);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_wait_task(this, state, 0);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
|
|
Packit |
8480eb |
* ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
|
|
Packit |
8480eb |
* to ST_READY.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
st_mutex_lock();
|
|
Packit |
8480eb |
while ((this = __master_find_submount(ap, path))) {
|
|
Packit |
8480eb |
struct timespec t = { 0, 300000000 };
|
|
Packit |
8480eb |
struct timespec r;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (this->state != ST_SHUTDOWN &&
|
|
Packit |
8480eb |
this->state != ST_SHUTDOWN_PENDING &&
|
|
Packit |
8480eb |
this->state != ST_SHUTDOWN_FORCE) {
|
|
Packit |
8480eb |
ret = 0;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
while (nanosleep(&t, &r) == -1 && errno == EINTR)
|
|
Packit |
8480eb |
memcpy(&t, &r, sizeof(struct timespec));
|
|
Packit |
8480eb |
mounts_mutex_lock(ap);
|
|
Packit |
8480eb |
st_mutex_lock();
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mounts_mutex_unlock(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void master_notify_state_change(struct master *master, int sig)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
struct list_head *p;
|
|
Packit |
8480eb |
int cur_state;
|
|
Packit |
8480eb |
unsigned int logopt;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
master_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
list_for_each(p, &master->mounts) {
|
|
Packit |
8480eb |
enum states next = ST_INVAL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
entry = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = entry->ap;
|
|
Packit |
8480eb |
logopt = ap->logopt;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ap->state == ST_SHUTDOWN)
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (sig) {
|
|
Packit |
8480eb |
case SIGTERM:
|
|
Packit |
8480eb |
case SIGINT:
|
|
Packit |
8480eb |
if (ap->state != ST_SHUTDOWN_PENDING &&
|
|
Packit |
8480eb |
ap->state != ST_SHUTDOWN_FORCE) {
|
|
Packit |
8480eb |
next = ST_SHUTDOWN_PENDING;
|
|
Packit |
8480eb |
ap->shutdown = 1;
|
|
Packit |
8480eb |
__st_add_task(ap, next);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
#ifdef ENABLE_FORCED_SHUTDOWN
|
|
Packit |
8480eb |
case SIGUSR2:
|
|
Packit |
8480eb |
if (ap->state != ST_SHUTDOWN_FORCE &&
|
|
Packit |
8480eb |
ap->state != ST_SHUTDOWN_PENDING) {
|
|
Packit |
8480eb |
next = ST_SHUTDOWN_FORCE;
|
|
Packit |
8480eb |
ap->shutdown = 1;
|
|
Packit |
8480eb |
__st_add_task(ap, next);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
case SIGUSR1:
|
|
Packit |
8480eb |
assert(ap->state == ST_READY);
|
|
Packit |
8480eb |
next = ST_PRUNE;
|
|
Packit |
8480eb |
__st_add_task(ap, next);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
if (next != ST_INVAL)
|
|
Packit |
8480eb |
debug(logopt,
|
|
Packit |
8480eb |
"sig %d switching %s from %d to %d",
|
|
Packit |
8480eb |
sig, ap->path, ap->state, next);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int master_do_mount(struct master_mapent *entry)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct startup_cond suc;
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
pthread_t thid;
|
|
Packit |
8480eb |
int status;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = entry->ap;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (handle_mounts_startup_cond_init(&suc)) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"failed to init startup cond for mount %s", entry->path);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
suc.ap = ap;
|
|
Packit |
8480eb |
suc.root = ap->path;
|
|
Packit |
8480eb |
suc.done = 0;
|
|
Packit |
8480eb |
suc.status = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
debug(ap->logopt, "mounting %s", entry->path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
status = pthread_create(&thid, &th_attr, handle_mounts, &suc);
|
|
Packit |
8480eb |
if (status) {
|
|
Packit |
8480eb |
crit(ap->logopt,
|
|
Packit |
8480eb |
"failed to create mount handler thread for %s",
|
|
Packit |
8480eb |
entry->path);
|
|
Packit |
8480eb |
handle_mounts_startup_cond_destroy(&suc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (!suc.done) {
|
|
Packit |
8480eb |
status = pthread_cond_wait(&suc.cond, &suc.mutex);
|
|
Packit |
8480eb |
if (status)
|
|
Packit |
8480eb |
fatal(status);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (suc.status) {
|
|
Packit |
8480eb |
error(ap->logopt, "failed to startup mount");
|
|
Packit |
8480eb |
handle_mounts_startup_cond_destroy(&suc);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
entry->thid = thid;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
handle_mounts_startup_cond_destroy(&suc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void check_update_map_sources(struct master_mapent *entry, int readall)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_source *source, *last;
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
int map_stale = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (readall)
|
|
Packit |
8480eb |
map_stale = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = entry->ap;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_writelock(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
last = NULL;
|
|
Packit |
8480eb |
source = entry->maps;
|
|
Packit |
8480eb |
while (source) {
|
|
Packit |
8480eb |
if (readall)
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If a map source is no longer valid and all it's
|
|
Packit |
8480eb |
* entries have expired away we can get rid of it.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (entry->age > source->age) {
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
cache_readlock(source->mc);
|
|
Packit |
8480eb |
me = cache_lookup_first(source->mc);
|
|
Packit |
8480eb |
if (!me) {
|
|
Packit |
8480eb |
struct map_source *next = source->next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_unlock(source->mc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!last)
|
|
Packit |
8480eb |
entry->maps = next;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
last->next = next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (entry->maps == source)
|
|
Packit |
8480eb |
entry->maps = next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_free_map_source(source, 1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
source->stale = 1;
|
|
Packit |
8480eb |
map_stale = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(source->mc);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
last = source;
|
|
Packit |
8480eb |
source = source->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_source_unlock(entry);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* The map sources have changed */
|
|
Packit |
8480eb |
if (map_stale)
|
|
Packit |
8480eb |
st_add_task(ap, ST_READMAP);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_mount_mounts(struct master *master, time_t age, int readall)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct mapent_cache *nc = master->nc;
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
int cur_state;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct master_mapent *this;
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
struct mapent *ne, *nested;
|
|
Packit |
8480eb |
struct stat st;
|
|
Packit |
8480eb |
int state_pipe, save_errno;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = this->ap;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* A master map entry has gone away */
|
|
Packit |
8480eb |
if (this->age < age) {
|
|
Packit |
8480eb |
st_add_task(ap, ST_SHUTDOWN_PENDING);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_readlock(nc);
|
|
Packit |
8480eb |
ne = cache_lookup_distinct(nc, this->path);
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If this path matched a nulled entry the master map entry
|
|
Packit |
8480eb |
* must be an indirect mount so the master map entry line
|
|
Packit |
8480eb |
* number may be obtained from this->maps.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ne) {
|
|
Packit |
8480eb |
int lineno = ne->age;
|
|
Packit |
8480eb |
cache_unlock(nc);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* null entry appears after map entry */
|
|
Packit |
8480eb |
if (this->maps->master_line < lineno) {
|
|
Packit |
8480eb |
warn(ap->logopt,
|
|
Packit |
8480eb |
"ignoring null entry that appears after "
|
|
Packit |
8480eb |
"existing entry for %s", this->path);
|
|
Packit |
8480eb |
goto cont;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (ap->state != ST_INIT) {
|
|
Packit |
8480eb |
st_add_task(ap, ST_SHUTDOWN_PENDING);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* The map entry hasn't been started yet and we've
|
|
Packit |
8480eb |
* seen a preceeding null map entry for it so just
|
|
Packit |
8480eb |
* delete it from the master map entry list so it
|
|
Packit |
8480eb |
* doesn't get in the road.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
master_free_mapent_sources(ap->entry, 1);
|
|
Packit |
8480eb |
master_free_mapent(ap->entry);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
nested = cache_partial_match(nc, this->path);
|
|
Packit |
8480eb |
if (nested) {
|
|
Packit |
8480eb |
error(ap->logopt,
|
|
Packit |
8480eb |
"removing invalid nested null entry %s",
|
|
Packit |
8480eb |
nested->key);
|
|
Packit |
8480eb |
nested = cache_partial_match(nc, this->path);
|
|
Packit |
8480eb |
if (nested)
|
|
Packit |
8480eb |
cache_delete(nc, nested->key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
cache_unlock(nc);
|
|
Packit |
8480eb |
cont:
|
|
Packit |
8480eb |
st_mutex_lock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
state_pipe = this->ap->state_pipe[1];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* No pipe so mount is needed */
|
|
Packit |
8480eb |
ret = fstat(state_pipe, &st);
|
|
Packit |
8480eb |
save_errno = errno;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
st_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!ret)
|
|
Packit |
8480eb |
check_update_map_sources(this, readall);
|
|
Packit |
8480eb |
else if (ret == -1 && save_errno == EBADF) {
|
|
Packit |
8480eb |
if (!master_do_mount(this)) {
|
|
Packit |
8480eb |
list_del_init(&this->list);
|
|
Packit |
8480eb |
master_free_mapent_sources(ap->entry, 1);
|
|
Packit |
8480eb |
master_free_mapent(ap->entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_setcancelstate(cur_state, NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* The nss source instances end up in reverse order. */
|
|
Packit |
8480eb |
static void list_source_instances(struct map_source *source, struct map_source *instance)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (!source || !instance) {
|
|
Packit |
8480eb |
printf("none");
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (instance->next)
|
|
Packit |
8480eb |
list_source_instances(source, instance->next);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* For convienience we map nss instance type "files" to "file".
|
|
Packit |
8480eb |
* Check for that and report corrected instance type.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (strcmp(instance->type, "file"))
|
|
Packit |
8480eb |
printf("%s ", instance->type);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
if (source->argv && *(source->argv[0]) != '/')
|
|
Packit |
8480eb |
printf("files ");
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
printf("%s ", instance->type);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void print_map_info(struct map_source *source)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int argc = source->argc;
|
|
Packit |
8480eb |
int i, multi, map_num;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
multi = (source->type && !strcmp(source->type, "multi"));
|
|
Packit |
8480eb |
map_num = 1;
|
|
Packit |
8480eb |
for (i = 0; i < argc; i++) {
|
|
Packit |
8480eb |
if (source->argv[i] && *source->argv[i] != '-') {
|
|
Packit |
8480eb |
if (!multi)
|
|
Packit |
8480eb |
printf(" map: %s\n", source->argv[i]);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
printf(" map[%i]: %s\n", map_num, source->argv[i]);
|
|
Packit |
8480eb |
i++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (i >= argc)
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(source->argv[i], "--"))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (source->argv[i]) {
|
|
Packit |
8480eb |
int need_newline = 0;
|
|
Packit |
8480eb |
int j;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!multi)
|
|
Packit |
8480eb |
printf(" arguments:");
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
printf(" arguments[%i]:", map_num);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (j = i; j < source->argc; j++) {
|
|
Packit |
8480eb |
if (!strcmp(source->argv[j], "--"))
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
printf(" %s", source->argv[j]);
|
|
Packit |
8480eb |
i++;
|
|
Packit |
8480eb |
need_newline = 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (need_newline)
|
|
Packit |
8480eb |
printf("\n");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (multi)
|
|
Packit |
8480eb |
map_num++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int match_type(const char *source, const char *type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (!strcmp(source, type))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
/* Sources file and files are synonymous */
|
|
Packit |
8480eb |
if (!strncmp(source, type, 4) && (strlen(source) <= 5))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *get_map_name(const char *string)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *name, *tmp;
|
|
Packit |
8480eb |
char *start, *end, *base;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = strdup(string);
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
printf("error: allocation failure: %s\n", strerror(errno));
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
base = basename(tmp);
|
|
Packit |
8480eb |
end = strchr(base, ',');
|
|
Packit |
8480eb |
if (end)
|
|
Packit |
8480eb |
*end = '\0';
|
|
Packit |
8480eb |
start = strchr(tmp, '=');
|
|
Packit |
8480eb |
if (start)
|
|
Packit |
8480eb |
start++;
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
char *colon = strrchr(base, ':');
|
|
Packit |
8480eb |
if (colon)
|
|
Packit |
8480eb |
start = ++colon;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
start = base;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
name = strdup(start);
|
|
Packit |
8480eb |
if (!name)
|
|
Packit |
8480eb |
printf("error: allocation failure: %s\n", strerror(errno));
|
|
Packit |
8480eb |
free(tmp);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return name;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static int match_name(struct map_source *source, const char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int argc = source->argc;
|
|
Packit |
8480eb |
int ret = 0;
|
|
Packit |
8480eb |
int i;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* This can't work for old style "multi" type sources since
|
|
Packit |
8480eb |
* there's no way to know from which map the cache entry came
|
|
Packit |
8480eb |
* from and duplicate entries are ignored at map read time.
|
|
Packit |
8480eb |
* All we can really do is list all the entries for the given
|
|
Packit |
8480eb |
* multi map if one of its map names matches.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
for (i = 0; i < argc; i++) {
|
|
Packit |
8480eb |
if (i == 0 || !strcmp(source->argv[i], "--")) {
|
|
Packit |
8480eb |
if (i != 0) {
|
|
Packit |
8480eb |
i++;
|
|
Packit |
8480eb |
if (i >= argc)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (source->argv[i] && *source->argv[i] != '-') {
|
|
Packit |
8480eb |
char *map = get_map_name(source->argv[i]);
|
|
Packit |
8480eb |
if (!map)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if (!strcmp(map, name)) {
|
|
Packit |
8480eb |
ret = 1;
|
|
Packit |
8480eb |
free(map);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free(map);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int dump_map(struct master *master, const char *type, const char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (list_empty(&master->mounts)) {
|
|
Packit |
8480eb |
printf("no master map entries found\n");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct master_mapent *this;
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
time_t now = monotonic_time(NULL);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = this->ap;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Ensure we actually read indirect map entries so we can
|
|
Packit |
8480eb |
* list them. The map reads won't read any indirect map
|
|
Packit |
8480eb |
* entries (other than those in a file map) unless the
|
|
Packit |
8480eb |
* browse option is set.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->type == LKP_INDIRECT)
|
|
Packit |
8480eb |
ap->flags |= MOUNT_FLAG_GHOST;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Read the map content into the cache */
|
|
Packit |
8480eb |
if (lookup_nss_read_map(ap, NULL, now))
|
|
Packit |
8480eb |
lookup_prune_cache(ap, now);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
printf("failed to read map\n");
|
|
Packit |
8480eb |
lookup_close_lookup(ap);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!this->maps) {
|
|
Packit |
8480eb |
printf("no map sources found for %s\n", ap->path);
|
|
Packit |
8480eb |
lookup_close_lookup(ap);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = this->maps;
|
|
Packit |
8480eb |
while (source) {
|
|
Packit |
8480eb |
struct map_source *instance;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
instance = NULL;
|
|
Packit |
8480eb |
if (source->type) {
|
|
Packit |
8480eb |
if (!match_type(source->type, type)) {
|
|
Packit |
8480eb |
source = source->next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (!match_name(source, name)) {
|
|
Packit |
8480eb |
source = source->next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
instance = source;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
struct map_source *map;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
map = source->instance;
|
|
Packit |
8480eb |
while (map) {
|
|
Packit |
8480eb |
if (!match_type(map->type, type)) {
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (!match_name(map, name)) {
|
|
Packit |
8480eb |
map = map->next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
instance = map;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!instance) {
|
|
Packit |
8480eb |
source = source->next;
|
|
Packit |
8480eb |
lookup_close_lookup(ap);
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = cache_lookup_first(source->mc);
|
|
Packit |
8480eb |
if (!me)
|
|
Packit |
8480eb |
printf("no keys found in map\n");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
if (me->source == instance)
|
|
Packit |
8480eb |
printf("%s\t%s\n", me->key, me->mapent);
|
|
Packit |
8480eb |
} while ((me = cache_lookup_next(source->mc, me)));
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
lookup_close_lookup(ap);
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
lookup_close_lookup(ap);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_show_mounts(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\nautofs dump map information\n"
|
|
Packit |
8480eb |
"===========================\n\n");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("global options: ");
|
|
Packit |
8480eb |
if (!global_options)
|
|
Packit |
8480eb |
printf("none configured\n");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
printf("%s\n", global_options);
|
|
Packit |
8480eb |
unsigned int append_options = defaults_get_append_options();
|
|
Packit |
8480eb |
const char *append = append_options ? "will" : "will not";
|
|
Packit |
8480eb |
printf("global options %s be appended to map entries\n", append);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (list_empty(&master->mounts)) {
|
|
Packit |
8480eb |
printf("no master map entries found\n\n");
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
struct map_source *source;
|
|
Packit |
8480eb |
struct master_mapent *this;
|
|
Packit |
8480eb |
struct autofs_point *ap;
|
|
Packit |
8480eb |
time_t now = monotonic_time(NULL);
|
|
Packit |
8480eb |
unsigned int count = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ap = this->ap;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\nMount point: %s\n", ap->path);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\nsource(s):\n");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Ensure we actually read indirect map entries so we can
|
|
Packit |
8480eb |
* list them. The map reads won't read any indirect map
|
|
Packit |
8480eb |
* entries (other than those in a file map) unless the
|
|
Packit |
8480eb |
* browse option is set.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (ap->type == LKP_INDIRECT)
|
|
Packit |
8480eb |
ap->flags |= MOUNT_FLAG_GHOST;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Read the map content into the cache */
|
|
Packit |
8480eb |
if (lookup_nss_read_map(ap, NULL, now))
|
|
Packit |
8480eb |
lookup_prune_cache(ap, now);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
printf(" failed to read map\n\n");
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!this->maps) {
|
|
Packit |
8480eb |
printf(" no map sources found\n\n");
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = this->maps;
|
|
Packit |
8480eb |
while (source) {
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (source->type)
|
|
Packit |
8480eb |
printf("\n type: %s\n", source->type);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
printf("\n instance type(s): ");
|
|
Packit |
8480eb |
list_source_instances(source, source->instance);
|
|
Packit |
8480eb |
printf("\n");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (source->argc >= 1) {
|
|
Packit |
8480eb |
print_map_info(source);
|
|
Packit |
8480eb |
if (count && ap->type == LKP_INDIRECT)
|
|
Packit |
8480eb |
printf(" duplicate indirect map entry"
|
|
Packit |
8480eb |
" will be ignored at run time\n");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\n");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = cache_lookup_first(source->mc);
|
|
Packit |
8480eb |
if (!me)
|
|
Packit |
8480eb |
printf(" no keys found in map\n");
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
do {
|
|
Packit |
8480eb |
printf(" %s | %s\n", me->key, me->mapent);
|
|
Packit |
8480eb |
} while ((me = cache_lookup_next(source->mc, me)));
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
count++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
source = source->next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
lookup_close_lookup(ap);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
printf("\n");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_list_empty(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int res = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
master_mutex_lock();
|
|
Packit |
8480eb |
if (list_empty(&master->mounts))
|
|
Packit |
8480eb |
res = 1;
|
|
Packit |
8480eb |
master_mutex_unlock();
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_done(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *head, *p;
|
|
Packit |
8480eb |
struct master_mapent *entry;
|
|
Packit |
8480eb |
int res = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->completed;
|
|
Packit |
8480eb |
p = head->next;
|
|
Packit |
8480eb |
while (p != head) {
|
|
Packit |
8480eb |
entry = list_entry(p, struct master_mapent, join);
|
|
Packit |
8480eb |
p = p->next;
|
|
Packit |
8480eb |
list_del(&entry->join);
|
|
Packit |
8480eb |
pthread_join(entry->thid, NULL);
|
|
Packit |
8480eb |
master_free_mapent_sources(entry, 1);
|
|
Packit |
8480eb |
master_free_mapent(entry);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (list_empty(&master->mounts))
|
|
Packit |
8480eb |
res = 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return res;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int master_get_logopt(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
return master_list ? master_list->logopt : LOGOPT_NONE;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int master_kill(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (!list_empty(&master->mounts))
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (master->name)
|
|
Packit |
8480eb |
free(master->name);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
cache_release_null_cache(master);
|
|
Packit |
8480eb |
free(master);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void dump_master(struct master *master)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct list_head *p, *head;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
head = &master->mounts;
|
|
Packit |
8480eb |
list_for_each(p, head) {
|
|
Packit |
8480eb |
struct master_mapent *this = list_entry(p, struct master_mapent, list);
|
|
Packit |
8480eb |
logmsg("path %s", this->path);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|