Allow calling puffs_mount(3) before puffs_daemon(3)

puffs_daemon(3) creates a pipe before forking, and the parent process
waits for the child to either complete puffs_mount(3) or fail. If a
user calls puffs_daemon(3) after puffs_mount(3), the function
deadlocks. While this error-reporting functionality is really a nice
thing to have, deadlocking is not great. If the filesystem has already
been mounted, puffs_mount(3) should just daemonize the process and
return.

This became an issue because fuse_daemonize(3) in FUSE API had no such
requirement and some FUSE filesystems in the wild suffered deadlocks.
This commit is contained in:
pho 2022-01-22 07:35:26 +00:00
parent f6ce8c39be
commit 0585557a98
4 changed files with 34 additions and 24 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.26 2016/01/23 21:22:46 christos Exp $
# $NetBSD: Makefile,v 1.27 2022/01/22 07:35:26 pho Exp $
#
.include <bsd.own.mk>
@ -16,7 +16,6 @@ MAN= puffs.3 puffs_cc.3 puffs_cred.3 puffs_flush.3 \
puffs_framebuf.3 puffs_node.3 puffs_ops.3 puffs_path.3
INCS= puffs.h puffsdump.h
INCSDIR= /usr/include
CPPFLAGS+= -D_KERNTYPES
LINTFLAGS+=-S -w
.include <bsd.lib.mk>

View File

@ -1,4 +1,4 @@
.\" $NetBSD: puffs.3,v 1.66 2021/12/03 17:12:17 pho Exp $
.\" $NetBSD: puffs.3,v 1.67 2022/01/22 07:35:26 pho Exp $
.\"
.\" Copyright (c) 2006, 2007, 2008 Antti Kantee. All rights reserved.
.\"
@ -455,11 +455,13 @@ is called
.It Fn puffs_daemon pu nochdir noclose
Detach from the console like
.Fn daemon 3 .
This call synchronizes with
If it is called before
.Fn puffs_mount ,
this call synchronizes with
.Fn puffs_mount
and the foreground process does not exit before the file system mount
call has returned from the kernel.
Since this routine internally calls fork, it has to be called
Since this routine internally calls fork, it is highly recommended to call it
.Em before
.Fn puffs_mount .
.It Fn puffs_mainloop pu flags

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs.c,v 1.127 2021/12/03 17:12:17 pho Exp $ */
/* $NetBSD: puffs.c,v 1.128 2022/01/22 07:35:26 pho Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: puffs.c,v 1.127 2021/12/03 17:12:17 pho Exp $");
__RCSID("$NetBSD: puffs.c,v 1.128 2022/01/22 07:35:26 pho Exp $");
#endif /* !lint */
#include <sys/param.h>
@ -440,9 +440,12 @@ puffs_daemon(struct puffs_usermount *pu, int nochdir, int noclose)
{
long int n;
int parent, value, fd;
bool is_beforemount;
if (pipe(pu->pu_dpipe) == -1)
return -1;
is_beforemount = (puffs_getstate(pu) < PUFFS_STATE_RUNNING);
if (is_beforemount)
if (pipe(pu->pu_dpipe) == -1)
return -1;
switch (fork()) {
case -1:
@ -454,18 +457,21 @@ puffs_daemon(struct puffs_usermount *pu, int nochdir, int noclose)
parent = 1;
break;
}
pu->pu_state |= PU_PUFFSDAEMON;
if (is_beforemount)
PU_SETSFLAG(pu, PU_PUFFSDAEMON);
if (parent) {
close(pu->pu_dpipe[1]);
n = read(pu->pu_dpipe[0], &value, sizeof(int));
if (n == -1)
err(1, "puffs_daemon");
if (n != sizeof(value))
errx(1, "puffs_daemon got %ld bytes", n);
if (value) {
errno = value;
err(1, "puffs_daemon");
if (is_beforemount) {
close(pu->pu_dpipe[1]);
n = read(pu->pu_dpipe[0], &value, sizeof(int));
if (n == -1)
err(1, "puffs_daemon");
if (n != sizeof(value))
errx(1, "puffs_daemon got %ld bytes", n);
if (value) {
errno = value;
err(1, "puffs_daemon");
}
}
exit(0);
} else {
@ -489,8 +495,10 @@ puffs_daemon(struct puffs_usermount *pu, int nochdir, int noclose)
}
fail:
n = write(pu->pu_dpipe[1], &errno, sizeof(int));
assert(n == 4);
if (is_beforemount) {
n = write(pu->pu_dpipe[1], &errno, sizeof(int));
assert(n == 4);
}
return -1;
}
@ -614,7 +622,7 @@ do { \
free(pu->pu_kargp);
pu->pu_kargp = NULL;
if (pu->pu_state & PU_PUFFSDAEMON)
if (PU_GETSFLAG(pu, PU_PUFFSDAEMON))
shutdaemon(pu, sverrno);
errno = sverrno;
@ -706,8 +714,8 @@ puffs_init(struct puffs_ops *pops, const char *mntfromname,
void
puffs_cancel(struct puffs_usermount *pu, int error)
{
assert(puffs_getstate(pu) < PUFFS_STATE_RUNNING);
assert(PU_GETSFLAG(pu, PU_PUFFSDAEMON));
shutdaemon(pu, error);
free(pu);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: puffs_priv.h,v 1.45 2012/04/18 00:57:22 manu Exp $ */
/* $NetBSD: puffs_priv.h,v 1.46 2022/01/22 07:35:26 pho Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
@ -113,6 +113,7 @@ struct puffs_usermount {
#define PU_DONEXIT 0x2000
#define PU_SETSTATE(pu, s) (pu->pu_state = (s) | (pu->pu_state & ~PU_STATEMASK))
#define PU_SETSFLAG(pu, s) (pu->pu_state |= (s))
#define PU_GETSFLAG(pu, s) (pu->pu_state & (s))
#define PU_CLRSFLAG(pu, s) \
(pu->pu_state = ((pu->pu_state & ~(s)) | (pu->pu_state & PU_STATEMASK)))
int pu_dpipe[2];