mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-11 08:16:05 -04:00
Merge pull request #214 from giuseppe/mkdir-fix
mkdir: if the destination exists atomically swap them
This commit is contained in:
commit
8b4062db5c
9
NEWS
9
NEWS
@ -1,3 +1,12 @@
|
|||||||
|
* fuse-overlayfs-1.1.0
|
||||||
|
|
||||||
|
- use openat(2) when available.
|
||||||
|
- accept "ro" as mount option.
|
||||||
|
- fix set mtime for a symlink.
|
||||||
|
- fix some issues reported by static analysis.
|
||||||
|
- fix potential infinite loop on a short read.
|
||||||
|
- fix creating a directory if the destination already exists in the upper layer.
|
||||||
|
|
||||||
* fuse-overlayfs-1.0.0
|
* fuse-overlayfs-1.0.0
|
||||||
|
|
||||||
- fix portability issue to 32 bits archs.
|
- fix portability issue to 32 bits archs.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([fuse-overlayfs], [1.0.0], [giuseppe@scrivano.org])
|
AC_INIT([fuse-overlayfs], [1.1.0], [giuseppe@scrivano.org])
|
||||||
AC_CONFIG_SRCDIR([main.c])
|
AC_CONFIG_SRCDIR([main.c])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
|
150
main.c
150
main.c
@ -823,7 +823,7 @@ drop_node_from_ino (Hash_table *inodes, struct ovl_node *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
direct_renameat2 (struct ovl_layer *l, int olddirfd, const char *oldpath,
|
direct_renameat2 (int olddirfd, const char *oldpath,
|
||||||
int newdirfd, const char *newpath, unsigned int flags)
|
int newdirfd, const char *newpath, unsigned int flags)
|
||||||
{
|
{
|
||||||
return syscall (SYS_renameat2, olddirfd, oldpath, newdirfd, newpath, flags);
|
return syscall (SYS_renameat2, olddirfd, oldpath, newdirfd, newpath, flags);
|
||||||
@ -2393,6 +2393,67 @@ copy_xattr (int sfd, int dfd, char *buf, size_t buf_size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
empty_dirfd (int fd)
|
||||||
|
{
|
||||||
|
cleanup_dir DIR *dp = NULL;
|
||||||
|
struct dirent *dent;
|
||||||
|
|
||||||
|
dp = fdopendir (fd);
|
||||||
|
if (dp == NULL)
|
||||||
|
{
|
||||||
|
close (fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
dent = readdir (dp);
|
||||||
|
if (dent == NULL)
|
||||||
|
{
|
||||||
|
if (errno)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcmp (dent->d_name, ".") == 0)
|
||||||
|
continue;
|
||||||
|
if (strcmp (dent->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = unlinkat (dirfd (dp), dent->d_name, 0);
|
||||||
|
if (ret < 0 && errno == EISDIR)
|
||||||
|
{
|
||||||
|
ret = unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
|
||||||
|
if (ret < 0 && errno == ENOTEMPTY)
|
||||||
|
{
|
||||||
|
int dfd;
|
||||||
|
|
||||||
|
dfd = safe_openat (dirfd (dp), dent->d_name, O_DIRECTORY, 0);
|
||||||
|
if (dfd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = empty_dirfd (dfd);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int create_node_directory (struct ovl_data *lo, struct ovl_node *src);
|
static int create_node_directory (struct ovl_data *lo, struct ovl_node *src);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2482,6 +2543,24 @@ create_directory (struct ovl_data *lo, int dirfd, const char *name, const struct
|
|||||||
ret = renameat (lo->workdir_fd, wd_tmp_file_name, dirfd, name);
|
ret = renameat (lo->workdir_fd, wd_tmp_file_name, dirfd, name);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
if (errno == EEXIST)
|
||||||
|
{
|
||||||
|
int dfd = -1;
|
||||||
|
|
||||||
|
ret = direct_renameat2 (lo->workdir_fd, wd_tmp_file_name, dirfd, name, RENAME_EXCHANGE);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
dfd = TEMP_FAILURE_RETRY (safe_openat (lo->workdir_fd, wd_tmp_file_name, O_DIRECTORY, 0));
|
||||||
|
if (dfd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = empty_dirfd (dfd);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
return unlinkat (lo->workdir_fd, wd_tmp_file_name, AT_REMOVEDIR);
|
||||||
|
}
|
||||||
if (errno == ENOTDIR)
|
if (errno == ENOTDIR)
|
||||||
unlinkat (dirfd, name, 0);
|
unlinkat (dirfd, name, 0);
|
||||||
if (errno == ENOENT && parent)
|
if (errno == ENOENT && parent)
|
||||||
@ -2816,67 +2895,6 @@ update_paths (struct ovl_node *node)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
empty_dirfd (int fd)
|
|
||||||
{
|
|
||||||
cleanup_dir DIR *dp = NULL;
|
|
||||||
struct dirent *dent;
|
|
||||||
|
|
||||||
dp = fdopendir (fd);
|
|
||||||
if (dp == NULL)
|
|
||||||
{
|
|
||||||
close (fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
dent = readdir (dp);
|
|
||||||
if (dent == NULL)
|
|
||||||
{
|
|
||||||
if (errno)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (strcmp (dent->d_name, ".") == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp (dent->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ret = unlinkat (dirfd (dp), dent->d_name, 0);
|
|
||||||
if (ret < 0 && errno == EISDIR)
|
|
||||||
{
|
|
||||||
ret = unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
|
|
||||||
if (ret < 0 && errno == ENOTEMPTY)
|
|
||||||
{
|
|
||||||
int dfd;
|
|
||||||
|
|
||||||
dfd = safe_openat (dirfd (dp), dent->d_name, O_DIRECTORY, 0);
|
|
||||||
if (dfd < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = empty_dirfd (dfd);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ret = unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
empty_dir (struct ovl_layer *l, const char *path)
|
empty_dir (struct ovl_layer *l, const char *path)
|
||||||
{
|
{
|
||||||
@ -4006,7 +4024,7 @@ ovl_rename_exchange (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
||||||
ret = direct_renameat2 (node->layer, srcfd, name, destfd, newname, flags);
|
ret = direct_renameat2 (srcfd, name, destfd, newname, flags);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -4179,7 +4197,7 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
so that with one operation we get both the rename and the whiteout created. */
|
so that with one operation we get both the rename and the whiteout created. */
|
||||||
if (destnode_is_whiteout)
|
if (destnode_is_whiteout)
|
||||||
{
|
{
|
||||||
ret = direct_renameat2 (get_upper_layer (lo), srcfd, name, destfd, newname, flags|RENAME_EXCHANGE);
|
ret = direct_renameat2 (srcfd, name, destfd, newname, flags|RENAME_EXCHANGE);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -4199,11 +4217,11 @@ ovl_rename_direct (fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||||||
|
|
||||||
/* Try to create the whiteout atomically, if it fails do the
|
/* Try to create the whiteout atomically, if it fails do the
|
||||||
rename+mknod separately. */
|
rename+mknod separately. */
|
||||||
ret = direct_renameat2 (get_upper_layer (lo), srcfd, name, destfd,
|
ret = direct_renameat2 (srcfd, name, destfd,
|
||||||
newname, flags|RENAME_WHITEOUT);
|
newname, flags|RENAME_WHITEOUT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ret = direct_renameat2 (get_upper_layer (lo), srcfd, name, destfd,
|
ret = direct_renameat2 (srcfd, name, destfd,
|
||||||
newname, flags);
|
newname, flags);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user