mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-08-04 02:15:58 -04:00
direct: use statx when available
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
b28a23a39d
commit
9f6f90a6da
@ -58,7 +58,7 @@ AC_SEARCH_LIBS([dlopen], [dl], [], [AC_MSG_ERROR([unable to find dlopen()])])
|
|||||||
|
|
||||||
AC_FUNC_ERROR_AT_LINE
|
AC_FUNC_ERROR_AT_LINE
|
||||||
AC_FUNC_MALLOC
|
AC_FUNC_MALLOC
|
||||||
AC_CHECK_FUNCS([open_by_handle_at error memset strdup copy_file_range])
|
AC_CHECK_FUNCS([open_by_handle_at error memset strdup copy_file_range statx])
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile lib/Makefile])
|
AC_CONFIG_FILES([Makefile lib/Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
36
direct.c
36
direct.c
@ -75,15 +75,45 @@ direct_getxattr (struct ovl_layer *l, const char *path, const char *name, char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
direct_fstat (struct ovl_layer *l, int fd, const char *path, struct stat *st)
|
direct_fstat (struct ovl_layer *l, int fd, const char *path, unsigned int mask, struct stat *st)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_STATX
|
||||||
|
int ret;
|
||||||
|
struct statx stx;
|
||||||
|
|
||||||
|
ret = statx (fd, "", AT_STATX_DONT_SYNC|AT_EMPTY_PATH, mask, &stx);
|
||||||
|
|
||||||
|
if (ret < 0 && errno == ENOSYS)
|
||||||
|
goto fallback;
|
||||||
|
if (ret == 0)
|
||||||
|
statx_to_stat (&stx, st);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fallback:
|
||||||
return fstat (fd, st);
|
return fstat (fd, st);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
direct_statat (struct ovl_layer *l, const char *path, struct stat *st, int flags)
|
direct_statat (struct ovl_layer *l, const char *path, struct stat *st, int flags, unsigned int mask)
|
||||||
{
|
{
|
||||||
return TEMP_FAILURE_RETRY (fstatat (l->fd, path, st, flags));
|
#ifdef HAVE_STATX
|
||||||
|
int ret;
|
||||||
|
struct statx stx;
|
||||||
|
|
||||||
|
ret = statx (l->fd, path, AT_STATX_DONT_SYNC|flags, mask, &stx);
|
||||||
|
|
||||||
|
if (ret < 0 && errno == ENOSYS)
|
||||||
|
goto fallback;
|
||||||
|
if (ret == 0)
|
||||||
|
statx_to_stat (&stx, st);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
fallback:
|
||||||
|
return fstatat (l->fd, path, st, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dirent *
|
static struct dirent *
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef FUSE_OVERLAYFS_H
|
#ifndef FUSE_OVERLAYFS_H
|
||||||
# define FUSE_OVERLAYFS_H
|
# define FUSE_OVERLAYFS_H
|
||||||
|
# define _GNU_SOURCE
|
||||||
|
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <plugin-manager.h>
|
# include <plugin-manager.h>
|
||||||
@ -121,8 +122,8 @@ struct data_source
|
|||||||
int (*load_data_source)(struct ovl_layer *l, const char *opaque, const char *path);
|
int (*load_data_source)(struct ovl_layer *l, const char *opaque, const char *path);
|
||||||
int (*cleanup)(struct ovl_layer *l);
|
int (*cleanup)(struct ovl_layer *l);
|
||||||
int (*file_exists)(struct ovl_layer *l, const char *pathname);
|
int (*file_exists)(struct ovl_layer *l, const char *pathname);
|
||||||
int (*statat)(struct ovl_layer *l, const char *path, struct stat *st, int flags);
|
int (*statat)(struct ovl_layer *l, const char *path, struct stat *st, int flags, unsigned int mask);
|
||||||
int (*fstat)(struct ovl_layer *l, int fd, const char *path, struct stat *st);
|
int (*fstat)(struct ovl_layer *l, int fd, const char *path, unsigned int mask, struct stat *st);
|
||||||
void *(*opendir)(struct ovl_layer *l, const char *path);
|
void *(*opendir)(struct ovl_layer *l, const char *path);
|
||||||
struct dirent *(*readdir)(void *dirp);
|
struct dirent *(*readdir)(void *dirp);
|
||||||
int (*closedir)(void *dirp);
|
int (*closedir)(void *dirp);
|
||||||
@ -135,4 +136,21 @@ struct data_source
|
|||||||
/* passtrough to the file system. */
|
/* passtrough to the file system. */
|
||||||
struct data_source direct_access_ds;
|
struct data_source direct_access_ds;
|
||||||
|
|
||||||
|
# ifndef HAVE_STATX
|
||||||
|
# define STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */
|
||||||
|
# define STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */
|
||||||
|
# define STATX_NLINK 0x00000004U /* Want/got stx_nlink */
|
||||||
|
# define STATX_UID 0x00000008U /* Want/got stx_uid */
|
||||||
|
# define STATX_GID 0x00000010U /* Want/got stx_gid */
|
||||||
|
# define STATX_ATIME 0x00000020U /* Want/got stx_atime */
|
||||||
|
# define STATX_MTIME 0x00000040U /* Want/got stx_mtime */
|
||||||
|
# define STATX_CTIME 0x00000080U /* Want/got stx_ctime */
|
||||||
|
# define STATX_INO 0x00000100U /* Want/got stx_ino */
|
||||||
|
# define STATX_SIZE 0x00000200U /* Want/got stx_size */
|
||||||
|
# define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
|
||||||
|
# define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
|
||||||
|
# define STATX_BTIME 0x00000800U /* Want/got stx_btime */
|
||||||
|
# define STATX_ALL 0x00000fffU /* All currently supported flags */
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
20
main.c
20
main.c
@ -598,7 +598,7 @@ delete_whiteout (struct ovl_data *lo, int dirfd, struct ovl_node *parent, const
|
|||||||
|
|
||||||
strconcat3 (whiteout_path, PATH_MAX, parent->path, "/", name);
|
strconcat3 (whiteout_path, PATH_MAX, parent->path, "/", name);
|
||||||
|
|
||||||
if (get_upper_layer (lo)->ds->statat (get_upper_layer (lo), whiteout_path, &st, AT_SYMLINK_NOFOLLOW) == 0
|
if (get_upper_layer (lo)->ds->statat (get_upper_layer (lo), whiteout_path, &st, AT_SYMLINK_NOFOLLOW, STATX_MODE|STATX_TYPE) == 0
|
||||||
&& (st.st_mode & S_IFMT) == S_IFCHR
|
&& (st.st_mode & S_IFMT) == S_IFCHR
|
||||||
&& major (st.st_rdev) == 0
|
&& major (st.st_rdev) == 0
|
||||||
&& minor (st.st_rdev) == 0)
|
&& minor (st.st_rdev) == 0)
|
||||||
@ -676,13 +676,13 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc
|
|||||||
if (st_in)
|
if (st_in)
|
||||||
memcpy (st, st_in, sizeof (* st));
|
memcpy (st, st_in, sizeof (* st));
|
||||||
else if (fd >= 0)
|
else if (fd >= 0)
|
||||||
ret = l->ds->fstat (l, fd, path, st);
|
ret = l->ds->fstat (l, fd, path, STATX_BASIC_STATS, st);
|
||||||
else if (path != NULL)
|
else if (path != NULL)
|
||||||
ret = stat (path, st);
|
ret = stat (path, st);
|
||||||
else if (node->hidden)
|
else if (node->hidden)
|
||||||
ret = fstatat (node_dirfd (node), node->path, st, AT_SYMLINK_NOFOLLOW);
|
ret = fstatat (node_dirfd (node), node->path, st, AT_SYMLINK_NOFOLLOW);
|
||||||
else
|
else
|
||||||
ret = l->ds->statat (l, node->path, st, AT_SYMLINK_NOFOLLOW);
|
ret = l->ds->statat (l, node->path, st, AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1204,7 +1204,7 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c
|
|||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
if (errno != EPERM && it->ds->statat (it, npath, &st, AT_SYMLINK_NOFOLLOW) == 0)
|
if (errno != EPERM && it->ds->statat (it, npath, &st, AT_SYMLINK_NOFOLLOW, STATX_TYPE|STATX_MODE|STATX_INO) == 0)
|
||||||
{
|
{
|
||||||
ret->tmp_ino = st.st_ino;
|
ret->tmp_ino = st.st_ino;
|
||||||
ret->tmp_dev = st.st_dev;
|
ret->tmp_dev = st.st_dev;
|
||||||
@ -1215,7 +1215,7 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* It is an open FD, stat the file and read the origin xattrs. */
|
/* It is an open FD, stat the file and read the origin xattrs. */
|
||||||
if (it->ds->fstat (it, fd, npath, &st) == 0)
|
if (it->ds->fstat (it, fd, npath, STATX_TYPE|STATX_MODE|STATX_INO, &st) == 0)
|
||||||
{
|
{
|
||||||
ret->tmp_ino = st.st_ino;
|
ret->tmp_ino = st.st_ino;
|
||||||
ret->tmp_dev = st.st_dev;
|
ret->tmp_dev = st.st_dev;
|
||||||
@ -1250,7 +1250,7 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c
|
|||||||
originfd = open_by_handle_at (AT_FDCWD, fh, O_RDONLY);
|
originfd = open_by_handle_at (AT_FDCWD, fh, O_RDONLY);
|
||||||
if (originfd >= 0)
|
if (originfd >= 0)
|
||||||
{
|
{
|
||||||
if (it->ds->fstat (it, originfd, npath, &st) == 0)
|
if (it->ds->fstat (it, originfd, npath, STATX_TYPE|STATX_MODE|STATX_INO, &st) == 0)
|
||||||
{
|
{
|
||||||
ret->tmp_ino = st.st_ino;
|
ret->tmp_ino = st.st_ino;
|
||||||
ret->tmp_dev = st.st_dev;
|
ret->tmp_dev = st.st_dev;
|
||||||
@ -1444,7 +1444,7 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
|
|||||||
a whiteout file. */
|
a whiteout file. */
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
ret = it->ds->statat (it, node_path, &st, AT_SYMLINK_NOFOLLOW);
|
ret = it->ds->statat (it, node_path, &st, AT_SYMLINK_NOFOLLOW, STATX_TYPE);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
it->ds->closedir (dp);
|
it->ds->closedir (dp);
|
||||||
@ -1678,7 +1678,7 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name)
|
|||||||
|
|
||||||
strconcat3 (path, PATH_MAX, pnode->path, "/", name);
|
strconcat3 (path, PATH_MAX, pnode->path, "/", name);
|
||||||
|
|
||||||
ret = it->ds->statat (it, path, &st, AT_SYMLINK_NOFOLLOW);
|
ret = it->ds->statat (it, path, &st, AT_SYMLINK_NOFOLLOW, STATX_TYPE|STATX_MODE|STATX_INO);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
@ -2493,7 +2493,7 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
|
|||||||
|
|
||||||
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
||||||
|
|
||||||
ret = node->layer->ds->statat (node->layer, node->path, &st, AT_SYMLINK_NOFOLLOW);
|
ret = node->layer->ds->statat (node->layer, node->path, &st, AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -3197,7 +3197,7 @@ ovl_do_open (fuse_req_t req, fuse_ino_t parent, const char *name, int flags, mod
|
|||||||
if (st == NULL)
|
if (st == NULL)
|
||||||
st = &st_tmp;
|
st = &st_tmp;
|
||||||
|
|
||||||
if (get_upper_layer (lo)->ds->fstat (get_upper_layer (lo), fd, path, st) < 0)
|
if (get_upper_layer (lo)->ds->fstat (get_upper_layer (lo), fd, path, STATX_BASIC_STATS, st) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
n = make_ovl_node (lo, path, get_upper_layer (lo), name, st->st_ino, st->st_dev, false, p, lo->fast_ino_check);
|
n = make_ovl_node (lo, path, get_upper_layer (lo), name, st->st_ino, st->st_dev, false, p, lo->fast_ino_check);
|
||||||
|
2
plugin.h
2
plugin.h
@ -20,8 +20,8 @@
|
|||||||
# define PLUGIN_H
|
# define PLUGIN_H
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
|
|
||||||
# include <fuse-overlayfs.h>
|
|
||||||
# include <utils.h>
|
# include <utils.h>
|
||||||
|
# include <fuse-overlayfs.h>
|
||||||
|
|
||||||
typedef struct data_source *(*plugin_load_data_source)(struct ovl_layer *layer, const char *opaque, const char *path);
|
typedef struct data_source *(*plugin_load_data_source)(struct ovl_layer *layer, const char *opaque, const char *path);
|
||||||
typedef int (*plugin_release)(struct ovl_layer *layer);
|
typedef int (*plugin_release)(struct ovl_layer *layer);
|
||||||
|
31
utils.c
31
utils.c
@ -17,18 +17,45 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
#include "utils.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "utils.h"
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
file_exists_at (int dirfd, const char *pathname)
|
file_exists_at (int dirfd, const char *pathname)
|
||||||
{
|
{
|
||||||
return faccessat (dirfd, pathname, F_OK, AT_SYMLINK_NOFOLLOW|AT_EACCESS);
|
return faccessat (dirfd, pathname, F_OK, AT_SYMLINK_NOFOLLOW|AT_EACCESS);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_STATX
|
||||||
|
void
|
||||||
|
copy_statx_to_stat_time (struct statx_timestamp *stx, struct timespec *st)
|
||||||
|
{
|
||||||
|
st->tv_sec = stx->tv_sec;
|
||||||
|
st->tv_nsec = stx->tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
statx_to_stat (struct statx *stx, struct stat *st)
|
||||||
|
{
|
||||||
|
st->st_dev = makedev (stx->stx_dev_major, stx->stx_dev_minor);
|
||||||
|
st->st_ino = stx->stx_ino;
|
||||||
|
st->st_mode = stx->stx_mode;
|
||||||
|
st->st_nlink = stx->stx_nlink;
|
||||||
|
st->st_uid = stx->stx_uid;
|
||||||
|
st->st_gid = stx->stx_gid;
|
||||||
|
st->st_rdev = makedev (stx->stx_rdev_major, stx->stx_rdev_minor);
|
||||||
|
st->st_size = stx->stx_size;
|
||||||
|
st->st_blksize = stx->stx_blksize;
|
||||||
|
st->st_blocks = stx->stx_blocks;
|
||||||
|
copy_statx_to_stat_time (&stx->stx_atime, &st->st_atim);
|
||||||
|
copy_statx_to_stat_time (&stx->stx_ctime, &st->st_ctim);
|
||||||
|
copy_statx_to_stat_time (&stx->stx_mtime, &st->st_mtim);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
strconcat3 (char *dest, size_t size, const char *s1, const char *s2, const char *s3)
|
strconcat3 (char *dest, size_t size, const char *s1, const char *s2, const char *s3)
|
||||||
{
|
{
|
||||||
|
10
utils.h
10
utils.h
@ -18,11 +18,17 @@
|
|||||||
#ifndef UTILS_H
|
#ifndef UTILS_H
|
||||||
# define UTILS_H
|
# define UTILS_H
|
||||||
|
|
||||||
|
# define _GNU_SOURCE
|
||||||
|
|
||||||
|
# include <config.h>
|
||||||
|
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <dirent.h>
|
# include <dirent.h>
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <fcntl.h>
|
||||||
# include "fuse-overlayfs.h"
|
# include "fuse-overlayfs.h"
|
||||||
|
|
||||||
void cleanup_freep (void *p);
|
void cleanup_freep (void *p);
|
||||||
@ -43,4 +49,8 @@ int open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *
|
|||||||
# define LIKELY(x) __builtin_expect((x),1)
|
# define LIKELY(x) __builtin_expect((x),1)
|
||||||
# define UNLIKELY(x) __builtin_expect((x),0)
|
# define UNLIKELY(x) __builtin_expect((x),0)
|
||||||
|
|
||||||
|
# ifdef HAVE_STATX
|
||||||
|
void statx_to_stat (struct statx *stx, struct stat *st);
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user