direct: use statx when available

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2019-09-14 18:20:29 +02:00
parent b28a23a39d
commit 9f6f90a6da
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED
7 changed files with 104 additions and 19 deletions

View File

@ -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

View File

@ -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 *

View File

@ -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
View File

@ -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);

View File

@ -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
View File

@ -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
View File

@ -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