aboutsummaryrefslogtreecommitdiffstats
path: root/daemon
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>1998-03-27 05:37:41 +0000
committerH. Peter Anvin <hpa@zytor.com>1998-03-27 05:37:41 +0000
commitb85764b115b4cb3601c660613b094b2b042dcb0a (patch)
tree762e7ba86393ad293bf62f7763b22c7e06dcc690 /daemon
parent416c8a6915ad2e45c98fd8a72a0deeb8adb5d1c1 (diff)
downloadautofs3-b85764b115b4cb3601c660613b094b2b042dcb0a.tar.gz
autofs3-b85764b115b4cb3601c660613b094b2b042dcb0a.tar.xz
autofs3-b85764b115b4cb3601c660613b094b2b042dcb0a.zip
Initial integration of rth's mount_autofs.
Diffstat (limited to 'daemon')
-rw-r--r--daemon/automount.c93
1 files changed, 77 insertions, 16 deletions
diff --git a/daemon/automount.c b/daemon/automount.c
index 2fb2c90..a7f9582 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -49,6 +49,7 @@ static char *pid_file = NULL; /* File in which to keep pid */
int kproto_version; /* Kernel protocol version used */
static int mounted = 0;
+static int submount = 0;
struct pending_mount {
pid_t pid; /* Which process is mounting for us */
@@ -73,6 +74,9 @@ volatile struct pending_mount *junk_mounts = NULL;
#define DEFAULT_TIMEOUT (5*60) /* 5 minutes */
#define CHECK_RATIO 4 /* exp_runfreq = exp_timeout/CHECK_RATIO */
+static void cleanup_exit(int exit_code);
+
+
static int umount_ent(char *root, char *name)
{
char path_buf[PATH_MAX];
@@ -132,16 +136,10 @@ static int umount_all(int force)
return left;
}
-static int umount_autofs(int force)
+static int do_umount_autofs(void)
{
int rv;
- if ( !mounted )
- return -1;
-
- if ( umount_all(force) && !force )
- return -1;
-
if (ap.ioctlfd >= 0) {
ioctl(ap.ioctlfd, AUTOFS_IOC_CATATONIC, 0);
close(ap.ioctlfd);
@@ -149,11 +147,63 @@ static int umount_autofs(int force)
if (ap.pipefd >= 0)
close(ap.pipefd);
rv = spawnl(LOG_ERR, _PATH_UMOUNT, _PATH_UMOUNT, ap.path, NULL);
+ if (rv == 0 && submount)
+ rmdir(ap.path);
+
free(ap.path);
mounted = 0;
return rv;
}
+static int umount_autofs(int force)
+{
+ if ( !mounted )
+ return -1;
+ if ( umount_all(force) && !force )
+ return -1;
+ return do_umount_autofs();
+}
+
+static void maybe_umount_autofs_and_exit(void)
+{
+ char path_buf[PATH_MAX];
+ struct stat st;
+ struct dirent *de;
+ DIR *dp;
+ int left;
+
+ /* If we are expiring, wait til next round to exit. */
+ if ( ap.exp_process )
+ return;
+
+ chdir("/");
+
+ dp = opendir(ap.path);
+ if ( !dp ) {
+ syslog(LOG_ERR, "maybe_umount_autofs: opendir: %m");
+ return;
+ }
+
+ left = 0;
+ while ( (de = readdir(dp)) != NULL ) {
+ if ( strcmp(de->d_name,".") && strcmp(de->d_name,"..") ) {
+ sprintf(path_buf, "%s/%s", ap.path, de->d_name);
+ if ( !lstat(path_buf,&st) ) {
+ if ( S_ISDIR(st.st_mode) ) {
+ if ( st.st_dev != ap.dev )
+ left++;
+ }
+ }
+ }
+ }
+ closedir(dp);
+
+ if (!left) {
+ if (do_umount_autofs() == 0)
+ cleanup_exit(0);
+ }
+}
+
static int mount_autofs(char *path)
{
int pipefd[2];
@@ -219,15 +269,20 @@ static int mount_autofs(char *path)
static void run_expire(void)
{
- pid_t f;
struct autofs_packet_expire pkt;
sigset_t s, olds;
+ pid_t f;
if ( ap.exp_process ) /* Another process is already expiring */
return; /* Try again next interval */
- if ( ioctl(ap.ioctlfd, AUTOFS_IOC_EXPIRE, &pkt) )
- return; /* Don't fork if there is nothing do expire */
+ if ( ioctl(ap.ioctlfd, AUTOFS_IOC_EXPIRE, &pkt) ) {
+ /* Don't fork if there is nothing do expire, but if we are a submount,
+ see if maybe we shouldn't exit. */
+ if (submount)
+ maybe_umount_autofs_and_exit();
+ return;
+ }
/* Temporarily block SIGCHLD and SIGALRM between forking and setting
ap.exp_process */
@@ -252,7 +307,7 @@ static void run_expire(void)
close(ap.pipefd);
syslog(LOG_DEBUG, "running expiration on path %s", ap.path);
-
+
do {
if ( pkt.hdr.type == autofs_ptype_expire ) {
if ( !umount_ent(ap.path,pkt.name) )
@@ -415,6 +470,8 @@ static void sig_child(int sig)
while ( (pid = waitpid(-1, &status, WNOHANG)) > 0 ) {
if ( pid == ap.exp_process ) {
ap.exp_process = 0;
+ if (submount)
+ maybe_umount_autofs_and_exit();
} else {
for ( mtp = &ap.mounts ; (mt = *mtp) ; mtp = &mt->next ) {
if ( mt->pid == pid ) {
@@ -465,14 +522,17 @@ static void become_daemon(void)
my_pid = getpid();
- /* Make our own process group for "magic" reason */
-
- if ( setpgrp() ) {
+ /* Make our own process group for "magic" reason: processes that share
+ our pgrp see the raw filesystem behine the magic. So if we are a
+ submount, don't change -- otherwise we won't be able to actually
+ perform the mount. */
+
+ if ( !submount && setpgrp() ) {
syslog(LOG_CRIT, "setpgrp: %m");
exit(1);
}
my_pgrp = getpgrp();
-
+
/* Redirect all our file descriptors to /dev/null */
if ( (nullfd = open("/dev/null", O_RDWR)) < 0 ) {
@@ -548,6 +608,7 @@ int main(int argc, char *argv[])
{"pid-file", 1, 0, 'p'},
{"timeout", 1, 0, 't'},
{"version", 0, 0, 'v'},
+ {"submount", 0, &submount, 1},
{0,0,0,0}
};
@@ -621,7 +682,7 @@ int main(int argc, char *argv[])
syslog(LOG_CRIT, "%s: mount failed!", path);
cleanup_exit(1);
}
-
+
/* The following signals cause a shutdown event to occur */
sa.sa_handler = sig_shutdown;
sigemptyset(&sa.sa_mask);