various fixes
diff --git a/ChangeLog b/ChangeLog
index 61d8293..e8d2cac 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2004-11-23 Miklos Szeredi <miklos@szeredi.hu>
+
+ * More cleanups in the kernel
+
+ * The 10,229 charater device number has been assigned for FUSE
+
+ * Version file checking fix (reported by Christian Magnusson)
+
+ * fusermount: opening the fuse device now doesn't need /sys.
+
+ * Optimize reading by controlling the maximum readahead based on
+ the 'max_read' mount option
+
+ * fixes for UCLIBC (Christian Magnusson)
+
2004-11-19 Miklos Szeredi <miklos@szeredi.hu>
* Cleaned up kernel in preparation for merge into mainline:
diff --git a/kernel/dev.c b/kernel/dev.c
index 7261770..da41e59 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -8,6 +8,7 @@
#include "fuse_i.h"
+#include <linux/init.h>
#include <linux/module.h>
#include <linux/poll.h>
#ifdef KERNEL_2_6
@@ -261,7 +262,6 @@
else if (!list_empty(&fc->pending)) {
req = list_entry(fc->pending.next, struct fuse_req, list);
list_del_init(&req->list);
- req->locked = 1;
}
spin_unlock(&fuse_lock);
if (!fc)
@@ -275,12 +275,9 @@
if (ret < 0) {
req->out.h.error = -EPROTO;
req->finished = 1;
- } else {
+ } else
list_add_tail(&req->list, &fc->processing);
- req->sent = 1;
- }
- req->locked = 0;
- if (ret < 0 || req->interrupted)
+ if (ret < 0)
/* Unlocks fuse_lock: */
request_end(fc, req);
else
@@ -471,10 +468,8 @@
spin_lock(&fuse_lock);
req = request_find(fc, oh.unique);
- if (req != NULL) {
+ if (req != NULL)
list_del_init(&req->list);
- req->locked = 1;
- }
spin_unlock(&fuse_lock);
if (!req)
return -ENOENT;
@@ -491,7 +486,6 @@
process_getdir(req);
}
req->finished = 1;
- req->locked = 0;
/* Unlocks fuse_lock: */
request_end(fc, req);
@@ -565,7 +559,6 @@
};
#ifdef KERNEL_2_6
-#define FUSE_MINOR MISC_DYNAMIC_MINOR
#ifndef FUSE_MAINLINE
static decl_subsys(fs, NULL, NULL);
diff --git a/kernel/dir.c b/kernel/dir.c
index 124bf86..fe8e803 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -111,6 +111,7 @@
int generation, struct fuse_attr *attr, int version)
{
struct inode *inode;
+ struct fuse_conn *fc = SB_FC(sb);
inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
if (!inode)
@@ -118,6 +119,7 @@
if ((inode->i_state & I_NEW)) {
inode->i_generation = generation;
+ inode->i_data.backing_dev_info = &fc->bdi;
fuse_init_inode(inode, attr);
unlock_new_inode(inode);
} else if (inode->i_generation != generation)
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index e454fd0..c5b8e23 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -42,6 +42,10 @@
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/spinlock.h>
+#ifdef KERNEL_2_6
+#include <linux/mm.h>
+#include <linux/backing-dev.h>
+#endif
#include <asm/semaphore.h>
#ifndef BUG_ON
@@ -152,15 +156,6 @@
/** True if the request has reply */
unsigned int isreply:1;
- /** The request is locked */
- unsigned int locked:1;
-
- /** The request has been interrupted while it was locked */
- unsigned int interrupted:1;
-
- /* The request has been sent to the client */
- unsigned int sent:1;
-
/* The request is preallocated */
unsigned int preallocated:1;
@@ -264,6 +259,11 @@
/** Is removexattr not implemented by fs? */
unsigned int no_removexattr : 1;
+
+#ifdef KERNEL_2_6
+ /** Backing dev info */
+ struct backing_dev_info bdi;
+#endif
};
struct fuse_getdir_out_i {
@@ -283,7 +283,16 @@
extern struct file_operations fuse_dev_operations;
/**
- * The lock to protect fuses structures
+ * This is the single global spinlock which protects FUSE's structures
+ *
+ * The following data is protected by this lock:
+ *
+ * - the private_data field of the device file
+ * - the s_fs_info field of the super block
+ * - unused_list, pending, processing lists in fuse_conn
+ * - the unique request ID counter reqctr in fuse_conn
+ * - the sb (super_block) field in fuse_conn
+ * - the file (device file) field in fuse_conn
*/
extern spinlock_t fuse_lock;
@@ -336,7 +345,6 @@
*/
void fuse_fs_cleanup(void);
-
/**
* Allocate a request
*/
diff --git a/kernel/inode.c b/kernel/inode.c
index 55a283b..8cae834 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -178,7 +178,9 @@
OPT_ALLOW_OTHER,
OPT_ALLOW_ROOT,
OPT_KERNEL_CACHE,
+#ifndef FUSE_MAINLINE
OPT_LARGE_READ,
+#endif
OPT_DIRECT_IO,
OPT_MAX_READ,
OPT_ERR
@@ -192,7 +194,9 @@
{OPT_ALLOW_OTHER, "allow_other"},
{OPT_ALLOW_ROOT, "allow_root"},
{OPT_KERNEL_CACHE, "kernel_cache"},
+#ifndef FUSE_MAINLINE
{OPT_LARGE_READ, "large_read"},
+#endif
{OPT_DIRECT_IO, "direct_io"},
{OPT_MAX_READ, "max_read=%u"},
{OPT_ERR, NULL}
@@ -247,7 +251,8 @@
case OPT_KERNEL_CACHE:
d->flags |= FUSE_KERNEL_CACHE;
break;
-
+
+#ifndef FUSE_MAINLINE
case OPT_LARGE_READ:
#ifndef KERNEL_2_6
d->flags |= FUSE_LARGE_READ;
@@ -261,7 +266,7 @@
}
#endif
break;
-
+#endif
case OPT_DIRECT_IO:
d->flags |= FUSE_DIRECT_IO;
break;
@@ -351,6 +356,10 @@
req->preallocated = 1;
list_add(&req->list, &fc->unused_list);
}
+#ifdef KERNEL_2_6
+ fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
+ fc->bdi.unplug_io_fn = default_unplug_io_fn;
+#endif
fc->reqctr = 1;
}
return fc;
@@ -502,6 +511,10 @@
fc->flags = d.flags;
fc->uid = d.uid;
fc->max_read = d.max_read;
+#ifdef KERNEL_2_6
+ if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
+ fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
+#endif
fc->max_write = FUSE_MAX_IN / 2;
SB_FC(sb) = fc;
diff --git a/kernel/linux/fuse.h b/kernel/linux/fuse.h
index f5f7405..ea640e9 100644
--- a/kernel/linux/fuse.h
+++ b/kernel/linux/fuse.h
@@ -17,6 +17,12 @@
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
+/** The major number of the fuse character device */
+#define FUSE_MAJOR 10
+
+/** The minor number of the fuse character device */
+#define FUSE_MINOR 229
+
/** Opening this will yield a new control file */
#define FUSE_DEV "/dev/fuse"
diff --git a/lib/fuse.c b/lib/fuse.c
index b29db9d..59f8b45 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -17,6 +17,9 @@
#include <errno.h>
#include <sys/param.h>
+#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
+#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
+
#define FUSE_MAX_PATH 4096
#define PARAM(inarg) (((char *)(inarg)) + sizeof(*inarg))
@@ -1722,12 +1725,18 @@
const char *version_file = FUSE_VERSION_FILE;
FILE *vf = fopen(version_file, "r");
if (vf == NULL) {
- version_file = "/sys/fs/fuse/version";
+ version_file = FUSE_VERSION_FILE_OLD;
vf = fopen(version_file, "r");
if (vf == NULL) {
- fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n",
- FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
- return -1;
+ struct stat tmp;
+ if (stat(FUSE_DEV_OLD, &tmp) != -1) {
+ fprintf(stderr, "fuse: kernel interface too old, need >= %i.%i\n",
+ FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
+ return -1;
+ } else {
+ fprintf(stderr, "fuse: warning: version of kernel interface unknown\n");
+ return 0;
+ }
}
}
res = fscanf(vf, "%i.%i", &f->majorver, &f->minorver);
@@ -1817,7 +1826,17 @@
if (f->id_table == NULL)
goto out_free_name_table;
- pthread_mutex_init(&f->lock, NULL);
+#ifndef USE_UCLIBC
+ pthread_mutex_init(&f->lock, NULL);
+#else
+ {
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
+ pthread_mutex_init(&f->lock, &attr);
+ pthread_mutexattr_destroy(&attr);
+ }
+#endif
f->numworker = 0;
f->numavail = 0;
f->op = *op;
diff --git a/lib/mount.c b/lib/mount.c
index 05dcb59..a84dbee 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -91,7 +91,11 @@
return -1;
}
+#ifndef USE_UCLIBC
pid = fork();
+#else
+ pid = vfork();
+#endif
if(pid == -1) {
perror("fuse: fork() failed");
close(fds[0]);
diff --git a/util/fusermount.c b/util/fusermount.c
index 98a705b..a7d26ed 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -38,8 +38,8 @@
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
-#define FUSE_DEV_NEW "/dev/fuse"
#define FUSE_SYS_DEV "/sys/class/misc/fuse/dev"
+#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"
const char *progname;
@@ -54,6 +54,94 @@
}
}
+#ifndef USE_UCLIBC
+/* Until there is a nice interface for capabilities in _libc_, this will
+remain here. I don't think it is fair to expect users to compile libcap
+for this program. And anyway what's all this fuss about versioning the
+kernel interface? It is quite good as is. */
+#define _LINUX_CAPABILITY_VERSION 0x19980330
+
+typedef struct __user_cap_header_struct {
+ unsigned int version;
+ int pid;
+} *cap_user_header_t;
+
+typedef struct __user_cap_data_struct {
+ unsigned int effective;
+ unsigned int permitted;
+ unsigned int inheritable;
+} *cap_user_data_t;
+
+int capget(cap_user_header_t header, cap_user_data_t data);
+int capset(cap_user_header_t header, cap_user_data_t data);
+
+#define CAP_SYS_ADMIN 21
+
+static uid_t oldfsuid;
+static gid_t oldfsgid;
+static struct __user_cap_data_struct oldcaps;
+
+static int drop_privs(void)
+{
+ int res;
+ struct __user_cap_header_struct head;
+ struct __user_cap_data_struct newcaps;
+
+ head.version = _LINUX_CAPABILITY_VERSION;
+ head.pid = 0;
+ res = capget(&head, &oldcaps);
+ if (res == -1) {
+ fprintf(stderr, "%s: failed to get capabilities: %s\n", progname,
+ strerror(errno));
+ return -1;
+ }
+
+ oldfsuid = setfsuid(getuid());
+ oldfsgid = setfsgid(getgid());
+ newcaps = oldcaps;
+ /* Keep CAP_SYS_ADMIN for mount */
+ newcaps.effective &= (1 << CAP_SYS_ADMIN);
+
+ head.version = _LINUX_CAPABILITY_VERSION;
+ head.pid = 0;
+ res = capset(&head, &newcaps);
+ if (res == -1) {
+ setfsuid(oldfsuid);
+ setfsgid(oldfsgid);
+ fprintf(stderr, "%s: failed to set capabilities: %s\n", progname,
+ strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static void restore_privs(void)
+{
+ struct __user_cap_header_struct head;
+ int res;
+
+ head.version = _LINUX_CAPABILITY_VERSION;
+ head.pid = 0;
+ res = capset(&head, &oldcaps);
+ if (res == -1)
+ fprintf(stderr, "%s: failed to restore capabilities: %s\n", progname,
+ strerror(errno));
+
+ setfsuid(oldfsuid);
+ setfsgid(oldfsgid);
+}
+#else /* USE_UCLIBC */
+static int drop_privs(void)
+{
+ return 0;
+}
+static void restore_privs(void)
+{
+}
+#endif /* USE_UCLIBC */
+
+
+#ifndef USE_UCLIBC
/* use a lock file so that multiple fusermount processes don't try and
modify the mtab file at once! */
static int lock_mtab()
@@ -113,88 +201,10 @@
return 0;
}
-
-/* Until there is a nice interface for capabilities in _libc_, this will
-remain here. I don't think it is fair to expect users to compile libcap
-for this program. And anyway what's all this fuss about versioning the
-kernel interface? It is quite good as is. */
-#define _LINUX_CAPABILITY_VERSION 0x19980330
-
-typedef struct __user_cap_header_struct {
- unsigned int version;
- int pid;
-} *cap_user_header_t;
-
-typedef struct __user_cap_data_struct {
- unsigned int effective;
- unsigned int permitted;
- unsigned int inheritable;
-} *cap_user_data_t;
-
-int capget(cap_user_header_t header, cap_user_data_t data);
-int capset(cap_user_header_t header, cap_user_data_t data);
-
-#define CAP_SYS_ADMIN 21
-
-static uid_t oldfsuid;
-static gid_t oldfsgid;
-static struct __user_cap_data_struct oldcaps;
-
-static int drop_privs()
+static int remove_mount(const char *mnt, int quiet, const char *mtab,
+ const char *mtab_new)
{
int res;
- struct __user_cap_header_struct head;
- struct __user_cap_data_struct newcaps;
-
- head.version = _LINUX_CAPABILITY_VERSION;
- head.pid = 0;
- res = capget(&head, &oldcaps);
- if (res == -1) {
- fprintf(stderr, "%s: failed to get capabilities: %s\n", progname,
- strerror(errno));
- return -1;
- }
-
- oldfsuid = setfsuid(getuid());
- oldfsgid = setfsgid(getgid());
- newcaps = oldcaps;
- /* Keep CAP_SYS_ADMIN for mount */
- newcaps.effective &= (1 << CAP_SYS_ADMIN);
-
- head.version = _LINUX_CAPABILITY_VERSION;
- head.pid = 0;
- res = capset(&head, &newcaps);
- if (res == -1) {
- setfsuid(oldfsuid);
- setfsgid(oldfsgid);
- fprintf(stderr, "%s: failed to set capabilities: %s\n", progname,
- strerror(errno));
- return -1;
- }
- return 0;
-}
-
-static void restore_privs()
-{
- struct __user_cap_header_struct head;
- int res;
-
- head.version = _LINUX_CAPABILITY_VERSION;
- head.pid = 0;
- res = capset(&head, &oldcaps);
- if (res == -1)
- fprintf(stderr, "%s: failed to restore capabilities: %s\n", progname,
- strerror(errno));
-
- setfsuid(oldfsuid);
- setfsgid(oldfsgid);
-}
-
-static int remove_mount(const char *mnt, int quiet, int lazy)
-{
- int res;
- const char *mtab = _PATH_MOUNTED;
- const char *mtab_new = _PATH_MOUNTED "~fuse~";
struct mntent *entp;
FILE *fp;
FILE *newfp;
@@ -248,37 +258,9 @@
endmntent(fp);
endmntent(newfp);
-
- if (found) {
- if (getuid() != 0) {
- res = drop_privs();
- if (res == -1) {
- unlink(mtab_new);
- return -1;
- }
- }
- res = umount2(mnt, lazy ? 2 : 0);
- if (res == -1) {
- if (!quiet)
- fprintf(stderr, "%s: failed to unmount %s: %s\n",
- progname, mnt,strerror(errno));
- found = -1;
- }
- if (getuid() != 0)
- restore_privs();
- }
-
- if (found == 1) {
- res = rename(mtab_new, mtab);
- if (res == -1) {
- fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname,
- mtab_new, mtab, strerror(errno));
- return -1;
- }
- }
- else {
- if (!found && !quiet)
+ if (!found) {
+ if (!quiet)
fprintf(stderr, "%s: entry for %s not found in %s\n", progname,
mnt, mtab);
unlink(mtab_new);
@@ -288,6 +270,55 @@
return 0;
}
+
+static int do_unmount(const char *mnt, int quiet, int lazy, const char *mtab,
+ const char *mtab_new)
+{
+ int res;
+
+ if (getuid() != 0) {
+ res = drop_privs();
+ if (res == -1)
+ return -1;
+ }
+ res = umount2(mnt, lazy ? 2 : 0);
+ if (res == -1) {
+ if (!quiet)
+ fprintf(stderr, "%s: failed to unmount %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+ if (getuid() != 0)
+ restore_privs();
+
+ res = rename(mtab_new, mtab);
+ if (res == -1) {
+ fprintf(stderr, "%s: failed to rename %s to %s: %s\n", progname,
+ mtab_new, mtab, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static int unmount_fuse(const char *mnt, int quiet, int lazy)
+{
+ int res;
+ const char *mtab = _PATH_MOUNTED;
+ const char *mtab_new = _PATH_MOUNTED "~fuse~";
+
+ res = remove_mount(mnt, quiet, mtab, mtab_new);
+ if (res == -1)
+ return -1;
+
+ res = do_unmount(mnt, quiet, lazy, mtab, mtab_new);
+ if (res == -1) {
+ unlink(mtab_new);
+ return -1;
+ }
+ return 0;
+}
+#endif /* USE_UCLIBC */
+
static int begins_with(const char *s, const char *beg)
{
if (strncmp(s, beg, strlen(beg)) == 0)
@@ -475,20 +506,32 @@
return res;
}
-static int check_version(void)
+static int check_version(const char *dev)
{
int res;
int majorver;
int minorver;
- const char *version_file = FUSE_VERSION_FILE;
- FILE *vf = fopen(version_file, "r");
+ const char *version_file;
+ int isold = 0;
+ FILE *vf;
+
+ if (strcmp(dev, FUSE_DEV_OLD) == 0)
+ isold = 1;
+
+ if (isold)
+ version_file = FUSE_VERSION_FILE_OLD;
+ else
+ version_file = FUSE_VERSION_FILE;
+
+ vf = fopen(version_file, "r");
if (vf == NULL) {
- version_file = "/sys/fs/fuse/version";
- vf = fopen(version_file, "r");
- if (vf == NULL) {
+ if (isold) {
fprintf(stderr, "%s: kernel interface too old\n", progname);
return -1;
- }
+ } else
+ /* If /sys/fs/fuse/version doesn't exist, just skip
+ version checking */
+ return 0;
}
res = fscanf(vf, "%i.%i", &majorver, &minorver);
fclose(vf);
@@ -606,7 +649,7 @@
return fd;
}
-static int try_open_new(char **devp)
+static int try_open_new(char **devp, int final)
{
const char *dev;
unsigned minor;
@@ -616,8 +659,18 @@
unsigned devnum;
char buf[256];
int fd = open(FUSE_SYS_DEV, O_RDONLY);
- if (fd == -1)
- return -2;
+ if (fd == -1) {
+ if (!final)
+ return -2;
+ fd = try_open(FUSE_DEV, devp, 0);
+ if (fd != -1)
+ return fd;
+ if (errno == ENODEV)
+ return -2;
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname,
+ FUSE_DEV, strerror(errno));
+ return -1;
+ }
res = read(fd, buf, sizeof(buf)-1);
close(fd);
@@ -635,10 +688,17 @@
}
devnum = (major << 8) + (minor & 0xff) + ((minor & 0xff00) << 12);
- dev = FUSE_DEV_NEW;
+ dev = FUSE_DEV;
res = stat(dev, &stbuf);
- if (res == -1)
- return try_open_new_temp(devnum, devp);
+ if (res == -1) {
+ if (major == FUSE_MAJOR && minor == FUSE_MINOR)
+ return try_open_new_temp(devnum, devp);
+ else {
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname,
+ dev, strerror(errno));
+ return -1;
+ }
+ }
if ((stbuf.st_mode & S_IFMT) != S_IFCHR || stbuf.st_rdev != devnum) {
fprintf(stderr, "%s: %s exists but has wrong attributes\n", progname,
@@ -652,21 +712,27 @@
{
int fd;
- fd = try_open_new(devp);
- if (fd != -2)
- return fd;
-
- fd = try_open(FUSE_DEV_OLD, devp, 1);
- if (fd != -1)
- return fd;
-
if (1
#ifndef AUTO_MODPROBE
&& getuid() == 0
#endif
) {
int status;
- pid_t pid = fork();
+ pid_t pid;
+
+ fd = try_open(FUSE_DEV_OLD, devp, 1);
+ if (fd != -1)
+ return fd;
+
+ fd = try_open_new(devp, 0);
+ if (fd != -2)
+ return fd;
+
+#ifndef USE_UCLIBC
+ pid = fork();
+#else
+ pid = vfork();
+#endif
if (pid == 0) {
setuid(0);
execl("/sbin/modprobe", "/sbin/modprobe", "fuse", NULL);
@@ -674,17 +740,16 @@
}
if (pid != -1)
waitpid(pid, &status, 0);
-
- fd = try_open_new(devp);
- if (fd != -2)
- return fd;
-
- fd = try_open(FUSE_DEV_OLD, devp, 1);
- if (fd != -1)
- return fd;
-
}
+ fd = try_open(FUSE_DEV_OLD, devp, 1);
+ if (fd != -1)
+ return fd;
+
+ fd = try_open_new(devp, 1);
+ if (fd != -2)
+ return fd;
+
fprintf(stderr, "fuse device not found, try 'modprobe fuse' first\n");
return -1;
}
@@ -697,7 +762,6 @@
char *dev;
const char *type = "fuse";
struct stat stbuf;
- int mtablock;
char *fsname;
char *mnt_opts;
const char *real_mnt = mnt;
@@ -713,7 +777,7 @@
return -1;
}
- res = check_version();
+ res = check_version(dev);
if (res != -1) {
res = check_perm(&real_mnt, &stbuf, &currdir_fd);
if (res != -1)
@@ -731,9 +795,10 @@
fchdir(currdir_fd);
close(currdir_fd);
}
-
+
+#ifndef USE_UCLIBC
if (geteuid() == 0) {
- mtablock = lock_mtab();
+ int mtablock = lock_mtab();
res = add_mount(fsname, mnt, type, mnt_opts);
unlock_mtab(mtablock);
if (res == -1) {
@@ -741,6 +806,8 @@
return -1;
}
}
+#endif
+
free(fsname);
free(mnt_opts);
free(dev);
@@ -928,11 +995,14 @@
restore_privs();
if (unmount) {
+#ifndef USE_UCLIBC
if (geteuid() == 0) {
int mtablock = lock_mtab();
- res = remove_mount(mnt, quiet, lazy);
+ res = unmount_fuse(mnt, quiet, lazy);
unlock_mtab(mtablock);
- } else {
+ } else
+#endif
+ {
res = umount2(mnt, lazy ? 2 : 0);
if (res == -1) {
if (!quiet)