Skip to content

Commit

Permalink
direct: use statx when available
Browse files Browse the repository at this point in the history
Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Sep 16, 2019
1 parent 5b64df4 commit c8f8c47
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 18 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ AC_SEARCH_LIBS([dlopen], [dl], [], [AC_MSG_ERROR([unable to find dlopen()])])

AC_FUNC_ERROR_AT_LINE
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_OUTPUT
36 changes: 33 additions & 3 deletions direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,45 @@ direct_getxattr (struct ovl_layer *l, const char *path, const char *name, char *
}

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

}

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 *
Expand Down
22 changes: 20 additions & 2 deletions fuse-overlayfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
#ifndef FUSE_OVERLAYFS_H
# define FUSE_OVERLAYFS_H
# define _GNU_SOURCE

# include <sys/stat.h>
# include <plugin-manager.h>
Expand Down Expand Up @@ -119,8 +120,8 @@ struct data_source
int (*load_data_source)(struct ovl_layer *l, const char *opaque, const char *path);
int (*cleanup)(struct ovl_layer *l);
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 (*fstat)(struct ovl_layer *l, int fd, const char *path, struct stat *st);
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, unsigned int mask, struct stat *st);
void *(*opendir)(struct ovl_layer *l, const char *path);
struct dirent *(*readdir)(void *dirp);
int (*closedir)(void *dirp);
Expand All @@ -133,4 +134,21 @@ struct data_source
/* passtrough to the file system. */
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
20 changes: 10 additions & 10 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ delete_whiteout (struct ovl_data *lo, int dirfd, struct ovl_node *parent, const

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
&& major (st.st_rdev) == 0
&& minor (st.st_rdev) == 0)
Expand Down Expand Up @@ -661,13 +661,13 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc
if (st_in)
memcpy (st, st_in, sizeof (* st));
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)
ret = stat (path, st);
else if (node->hidden)
ret = fstatat (node_dirfd (node), node->path, st, AT_SYMLINK_NOFOLLOW);
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)
return ret;
Expand Down Expand Up @@ -1190,7 +1190,7 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c

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_dev = st.st_dev;
Expand All @@ -1201,7 +1201,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. */
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_dev = st.st_dev;
Expand Down Expand Up @@ -1236,7 +1236,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);
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_dev = st.st_dev;
Expand Down Expand Up @@ -1430,7 +1430,7 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
a whiteout file. */
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)
{
it->ds->closedir (dp);
Expand Down Expand Up @@ -1664,7 +1664,7 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *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)
{
int saved_errno = errno;
Expand Down Expand Up @@ -2464,7 +2464,7 @@ copyup (struct ovl_data *lo, struct ovl_node *node)

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)
return ret;

Expand Down Expand Up @@ -3156,7 +3156,7 @@ ovl_do_open (fuse_req_t req, fuse_ino_t parent, const char *name, int flags, mod
if (st == NULL)
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;

n = make_ovl_node (lo, path, get_upper_layer (lo), name, st->st_ino, st->st_dev, false, p, lo->fast_ino_check);
Expand Down
2 changes: 1 addition & 1 deletion plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
# define PLUGIN_H
# include <config.h>

# include <fuse-overlayfs.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 int (*plugin_release)(struct ovl_layer *layer);
Expand Down
29 changes: 28 additions & 1 deletion utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,44 @@
*/

#include <config.h>
#include "utils.h"
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include "utils.h"
#include <sys/sysmacros.h>

int
file_exists_at (int dirfd, const char *pathname)
{
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
strconcat3 (char *dest, size_t size, const char *s1, const char *s2, const char *s3)
Expand Down
10 changes: 10 additions & 0 deletions utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@
#ifndef UTILS_H
# define UTILS_H

# define _GNU_SOURCE

# include <config.h>

# include <unistd.h>
# include <stdio.h>
# include <sys/types.h>
# include <dirent.h>
# include <stdlib.h>
# include <sys/types.h>
# include <fcntl.h>
# include "fuse-overlayfs.h"

void cleanup_freep (void *p);
Expand All @@ -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 UNLIKELY(x) __builtin_expect((x),0)

# ifdef HAVE_STATX
void statx_to_stat (struct statx *stx, struct stat *st);
# endif

#endif

0 comments on commit c8f8c47

Please sign in to comment.