Add umount2(). umount() is now a macro that just calls umount2() with flags = 0.

This commit is contained in:
Gregory Nutt 2015-03-14 16:48:45 -06:00
parent 9e2587ffe9
commit f932b26db1
11 changed files with 111 additions and 23 deletions

55
TODO
View file

@ -1,4 +1,4 @@
NuttX TODO List (Last updated March 10, 2015)
NuttX TODO List (Last updated March 14, 2015)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@ -18,7 +18,7 @@ nuttx/
(12) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
(11) Libraries (libc/, libm/)
(11) File system/Generic drivers (fs/, drivers/)
(12) File system/Generic drivers (fs/, drivers/)
(9) Graphics subystem (graphics/)
(1) Pascal add-on (pcode/)
(1) Documentation (Documentation/)
@ -1303,6 +1303,57 @@ o File system / Generic drivers (fs/, drivers/)
Status: Open
Priority: Medium
Title: UNMOUNT WITH OPEN FILES
Description: What is the policy for umounting files that have open file
references? Currently, umount() does the unmount
unconditionally and this has been noted to cause crashes in
some subsequent FAT file system operations. umount() is not
a standard OS interface and so have no specification. Here
are some possible behaviors or unmount() with open files:
1. Refuse to unmount() the file system if there are open
references to files on the file system (i.e., the file
system unbind() method returns a failure).
2. The file system knows that it has open references and so
does not unbind() immediately, but defers until the last
file is closed.
3. The file system performs the unbind() immediately, but
returns an error for an any subsequent operations on the
file system using one of the stale file handles.
4. In your application, do not un-mount until you have closed
all references to files or directories in the file system.
This would probably be a good practice anyway.
I lieu of any real specifications, I often just do what Linux
does. Here is now Linux does things:
http://man7.org/linux/man-pages/man2/umount.2.html .
Linux has have a umount2() that takes flags that control these
behaviors. They have a couple of other options as well.
It is not explicitly stated in the manpage, but it looks like
the Linux umount() does the first option: It should return
EBUSY meaning that the "target could not be unmounted because
it is busy." That one is pretty easy to implement within the
filesystem unbind() method.
I now think for an embedded system with mostly removable
storage devices, the option 3 is probably the most usable. For
example, NuttX has a little automounter at nuttx/fs/mount/fs_automount.c
That will automatically mount and unmount SD cards as they are
inserted or removed. I think that is a desire-able feature on
an embedded device. And I think it demands option 3 where the
umount occurs immediately, but then subsequent operations on
the volume fail.
The true lazy umount could also cause issues if the file is
never closed. Of course if the media is gone, I would hope
that the file access also fail in that case. But what if the
media is inserted and removed many times. Seems like the lazy
unmount could cause some problems and won't really buy you
anything anyway (because the file I/O will fail anyway).
Status: Open
Priority: Medium-High
o Graphics subsystem (graphics/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -41,7 +41,7 @@ statfs NXstatfs
system NXsystem
tcgetattr NXtcgetattr
tcsetattr NXtcsetattr
umount NXumount
umount2 NXumount2
unlink NXunlink
usleep NXusleep
vfork NXvfork

View file

@ -38,7 +38,7 @@
ifneq ($(CONFIG_NFILE_DESCRIPTORS),0)
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
CSRCS += fs_mount.c fs_umount.c fs_foreachmountpoint.c
CSRCS += fs_mount.c fs_umount2.c fs_foreachmountpoint.c
ifeq ($(CONFIG_FS_AUTOMOUNTER),y)
CSRCS += fs_automount.c

View file

@ -290,7 +290,7 @@ static int automount_unmount(FAR struct automounter_state_s *priv)
/* Un-mount the volume */
ret = umount(lower->mountpoint);
ret = umount2(lower->mountpoint, MNT_FORCE);
if (ret < 0)
{
int errcode = get_errno();
@ -305,7 +305,7 @@ static int automount_unmount(FAR struct automounter_state_s *priv)
{
fvdbg("WARNING: Volume is busy, try again later\n");
/* Start a timer to retry the umount after a delay */
/* Start a timer to retry the umount2 after a delay */
ret = wd_start(priv->wdog, lower->udelay, automount_timeout, 1,
(uint32_t)((uintptr_t)priv));
@ -323,7 +323,7 @@ static int automount_unmount(FAR struct automounter_state_s *priv)
else
{
fvdbg("ERROR: umount failed: %d\n", errcode);
fvdbg("ERROR: umount2 failed: %d\n", errcode);
return -errcode;
}
}

View file

@ -353,7 +353,7 @@ int mount(FAR const char *source, FAR const char *target,
/* We can release our reference to the blkdrver_inode, if the filesystem
* wants to retain the blockdriver inode (which it should), then it must
* have called inode_addref(). There is one reference on mountpt_inode
* that will persist until umount() is called.
* that will persist until umount2() is called.
*/
#ifdef BDFS_SUPPORT

View file

@ -1,7 +1,7 @@
/****************************************************************************
* fs/mount/fs_umount.c
* fs/mount/fs_umount2.c
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -70,7 +70,7 @@
****************************************************************************/
/****************************************************************************
* Name: umount
* Name: umount2
*
* Description:
* umount() detaches the filesystem mounted at the path specified by
@ -87,7 +87,7 @@
*
****************************************************************************/
int umount(const char *target)
int umount2(FAR const char *target, unsigned int flags)
{
FAR struct inode *mountpt_inode;
FAR struct inode *blkdrvr_inode = NULL;
@ -203,4 +203,3 @@ errout:
set_errno(errcode);
return ERROR;
}

View file

@ -1,7 +1,7 @@
/****************************************************************************
* include/sys/mount.h
*
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -40,6 +40,8 @@
* Included Files
****************************************************************************/
#include <nuttx/compiler.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -48,6 +50,41 @@
#define MS_RDONLY 1 /* Mount file system read-only */
/* Un-mount flags
*
* These flags control the behavior of umount2() when there are open file
* references through the mountpoint. umount2() with no flag bits set is
* equivalent to umount(), i.e., the umount() will fail with EBUSY if there
* are open references on the file.
*
* MNT_FORCE - Force unmount even if busy. This can cause data loss.
* MNT_DETACH - Perform a lazy unmount: make the mount point unavailable
* for new accesses, and actually perform the unmount when the mount
* point ceases to be busy.
* MNT_EXPIRE - Mark the mount point as expired. If a mount point is not
* currently in use, then an initial call to umount2() with this flag
* fails with the error EAGAIN, but marks the mount point as expired. The
* mount point remains expired as long as it isn't accessed by any
* process. A second umount2() call specifying MNT_EXPIRE unmounts an
* expired mount point. This flag cannot be specified with either
* MNT_FORCE or MNT_DETACH.
* UMOUNT_NOFOLLOW (- Don't dereference target if it is a symbolic link.
* For Linux, this flag allows security problems to be avoided in
* set-user-ID-root programs that allow unprivileged users to unmount
* file systems. For NuttX, it is provided only for compatibility
*
* Not all options are supported on all file systems.
*/
#define MNT_FORCE (1 << 0)
#define MNT_DETACH (1 << 1)
#define MNT_EXPIRE (1 << 2)
#define UMOUNT_NOFOLLOW (0)
/* mount() is equivalent to umount2() with flags = 0 */
#define umount(t) umount2(t,0)
/****************************************************************************
* Public Type Definitions
****************************************************************************/
@ -59,15 +96,16 @@
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C" {
extern "C"
{
#else
#define EXTERN extern
#endif
int mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
int umount(const char *target);
int mount(FAR const char *source, FAR const char *target,
FAR const char *filesystemtype, unsigned long mountflags,
FAR const void *data);
int umount2(FAR const char *target, unsigned int flags);
#undef EXTERN
#if defined(__cplusplus)

View file

@ -298,7 +298,7 @@
# define SYS_mount (__SYS_mountpoint+2)
# define SYS_rename (__SYS_mountpoint+3)
# define SYS_rmdir (__SYS_mountpoint+4)
# define SYS_umount (__SYS_mountpoint+5)
# define SYS_umount2 (__SYS_mountpoint+5)
# define SYS_unlink (__SYS_mountpoint+6)
# define __SYS_shm (__SYS_mountpoint+7)
# else

View file

@ -144,7 +144,7 @@
"timer_getoverrun","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t"
"timer_gettime","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t","FAR struct itimerspec*"
"timer_settime","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t","int","FAR const struct itimerspec*","FAR struct itimerspec*"
"umount","sys/mount.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","const char*"
"umount2","sys/mount.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char*","unsigned int"
"unlink","unistd.h","CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char*"
"unsetenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","const char*"
"up_assert","assert.h","","void","FAR const uint8_t*","int"

Can't render this file because it has a wrong number of fields in line 2.

View file

@ -215,7 +215,7 @@ SYSCALL_LOOKUP(up_assert, 2, STUB_up_assert)
SYSCALL_LOOKUP(mount, 5, STUB_mount)
SYSCALL_LOOKUP(rename, 2, STUB_rename)
SYSCALL_LOOKUP(rmdir, 1, STUB_rmdir)
SYSCALL_LOOKUP(umount, 1, STUB_umount)
SYSCALL_LOOKUP(umount2, 2, STUB_umount2)
SYSCALL_LOOKUP(unlink, 1, STUB_unlink)
# endif
#endif

View file

@ -223,7 +223,7 @@ uintptr_t STUB_mount(int nbr, uintptr_t parm1, uintptr_t parm2,
uintptr_t parm3, uintptr_t parm4, uintptr_t parm5);
uintptr_t STUB_rename(int nbr, uintptr_t parm1, uintptr_t parm2);
uintptr_t STUB_rmdir(int nbr, uintptr_t parm1);
uintptr_t STUB_umount(int nbr, uintptr_t parm1);
uintptr_t STUB_umount2(int nbr, uintptr_t parm1, uintptr parm2);
uintptr_t STUB_unlink(int nbr, uintptr_t parm1);
/* Shared memory interfaces */