gfapi: new api glfs_statx as linux's statx
Change-Id: I44dd6ceef0954ae7fc13f920e84d81bbd3f6a774 Updates: #389 Signed-off-by: Kinglong Mee <mijinlong@open-fs.com> Signed-off-by: ShyamsundarR <srangana@redhat.com>
This commit is contained in:
parent
f99f51ca87
commit
c31f1c232a
@ -170,6 +170,8 @@ _pub_glfs_h_lease _glfs_h_lease$GFAPI_4.0.0
|
||||
_pub_glfs_upcall_lease_get_object _glfs_upcall_lease_get_object$GFAPI_4.1.6
|
||||
_pub_glfs_upcall_lease_get_lease_type _glfs_upcall_lease_get_lease_type$GFAPI_4.1.6
|
||||
|
||||
_priv_glfs_statx _glfs_statx$GFAPI_future
|
||||
|
||||
_pub_glfs_read_async _glfs_read_async$GFAPI_future
|
||||
_pub_glfs_write_async _glfs_write_async$GFAPI_future
|
||||
_pub_glfs_readv_async _glfs_readv_async$GFAPI_future
|
||||
|
@ -235,6 +235,11 @@ GFAPI_4.1.6 {
|
||||
glfs_upcall_lease_get_lease_type;
|
||||
} GFAPI_4.0.0;
|
||||
|
||||
GFAPI_PRIVATE_future {
|
||||
global:
|
||||
glfs_statx;
|
||||
} GFAPI_4.1.6;
|
||||
|
||||
GFAPI_future {
|
||||
global:
|
||||
glfs_read_async;
|
||||
@ -256,5 +261,5 @@ GFAPI_future {
|
||||
glfs_discard_async;
|
||||
glfs_zerofill_async;
|
||||
glfs_copy_file_range;
|
||||
} GFAPI_4.1.6;
|
||||
} GFAPI_PRIVATE_future;
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <glusterfs/compat-errno.h>
|
||||
#include <limits.h>
|
||||
#include "glusterfs3.h"
|
||||
#include <glusterfs/iatt.h>
|
||||
|
||||
#ifdef NAME_MAX
|
||||
#define GF_NAME_MAX NAME_MAX
|
||||
@ -206,6 +207,90 @@ glfs_iatt_to_stat(struct glfs *fs, struct iatt *iatt, struct stat *stat)
|
||||
stat->st_dev = fs->dev_id;
|
||||
}
|
||||
|
||||
void
|
||||
glfs_iatt_to_statx(struct glfs *fs, struct iatt *iatt, struct glfs_stat *statx)
|
||||
{
|
||||
statx->glfs_st_mask = 0;
|
||||
|
||||
statx->glfs_st_mode = 0;
|
||||
if (IATT_TYPE_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_mode |= st_mode_type_from_ia(iatt->ia_type);
|
||||
statx->glfs_st_mask |= GLFS_STAT_TYPE;
|
||||
}
|
||||
|
||||
if (IATT_MODE_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_mode |= st_mode_prot_from_ia(iatt->ia_prot);
|
||||
statx->glfs_st_mask |= GLFS_STAT_MODE;
|
||||
}
|
||||
|
||||
if (IATT_NLINK_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_nlink = iatt->ia_nlink;
|
||||
statx->glfs_st_mask |= GLFS_STAT_NLINK;
|
||||
}
|
||||
|
||||
if (IATT_UID_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_uid = iatt->ia_uid;
|
||||
statx->glfs_st_mask |= GLFS_STAT_UID;
|
||||
}
|
||||
|
||||
if (IATT_GID_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_gid = iatt->ia_gid;
|
||||
statx->glfs_st_mask |= GLFS_STAT_GID;
|
||||
}
|
||||
|
||||
if (IATT_ATIME_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_atime.tv_sec = iatt->ia_atime;
|
||||
statx->glfs_st_atime.tv_nsec = iatt->ia_atime_nsec;
|
||||
statx->glfs_st_mask |= GLFS_STAT_ATIME;
|
||||
}
|
||||
|
||||
if (IATT_MTIME_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_mtime.tv_sec = iatt->ia_mtime;
|
||||
statx->glfs_st_mtime.tv_nsec = iatt->ia_mtime_nsec;
|
||||
statx->glfs_st_mask |= GLFS_STAT_MTIME;
|
||||
}
|
||||
|
||||
if (IATT_CTIME_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_ctime.tv_sec = iatt->ia_ctime;
|
||||
statx->glfs_st_ctime.tv_nsec = iatt->ia_ctime_nsec;
|
||||
statx->glfs_st_mask |= GLFS_STAT_CTIME;
|
||||
}
|
||||
|
||||
if (IATT_BTIME_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_btime.tv_sec = iatt->ia_btime;
|
||||
statx->glfs_st_btime.tv_nsec = iatt->ia_btime_nsec;
|
||||
statx->glfs_st_mask |= GLFS_STAT_BTIME;
|
||||
}
|
||||
|
||||
if (IATT_INO_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_ino = iatt->ia_ino;
|
||||
statx->glfs_st_mask |= GLFS_STAT_INO;
|
||||
}
|
||||
|
||||
if (IATT_SIZE_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_size = iatt->ia_size;
|
||||
statx->glfs_st_mask |= GLFS_STAT_SIZE;
|
||||
}
|
||||
|
||||
if (IATT_BLOCKS_VALID(iatt->ia_flags)) {
|
||||
statx->glfs_st_blocks = iatt->ia_blocks;
|
||||
statx->glfs_st_mask |= GLFS_STAT_BLOCKS;
|
||||
}
|
||||
|
||||
/* unconditionally present, encode as is */
|
||||
statx->glfs_st_blksize = iatt->ia_blksize;
|
||||
statx->glfs_st_rdev_major = ia_major(iatt->ia_rdev);
|
||||
statx->glfs_st_rdev_minor = ia_minor(iatt->ia_rdev);
|
||||
statx->glfs_st_dev_major = ia_major(fs->dev_id);
|
||||
statx->glfs_st_dev_minor = ia_minor(fs->dev_id);
|
||||
|
||||
/* At present we do not read any localFS attributes and pass them along,
|
||||
* so setting this to 0. As we start supporting file attributes we can
|
||||
* populate the same here as well */
|
||||
statx->glfs_st_attributes = 0;
|
||||
statx->glfs_st_attributes_mask = 0;
|
||||
}
|
||||
|
||||
int
|
||||
glfs_loc_unlink(loc_t *loc)
|
||||
{
|
||||
@ -455,6 +540,61 @@ invalid_fs:
|
||||
|
||||
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_stat, 3.4.0);
|
||||
|
||||
int
|
||||
priv_glfs_statx(struct glfs *fs, const char *path, unsigned int mask,
|
||||
struct glfs_stat *statxbuf)
|
||||
{
|
||||
int ret = -1;
|
||||
xlator_t *subvol = NULL;
|
||||
loc_t loc = {
|
||||
0,
|
||||
};
|
||||
struct iatt iatt = {
|
||||
0,
|
||||
};
|
||||
int reval = 0;
|
||||
|
||||
DECLARE_OLD_THIS;
|
||||
__GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
|
||||
|
||||
if (path == NULL) {
|
||||
ret = -1;
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mask & ~GLFS_STAT_ALL) {
|
||||
ret = -1;
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
subvol = glfs_active_subvol(fs);
|
||||
if (!subvol) {
|
||||
ret = -1;
|
||||
errno = EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
retry:
|
||||
ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
|
||||
ESTALE_RETRY(ret, errno, reval, &loc, retry);
|
||||
|
||||
if (ret == 0 && statxbuf)
|
||||
glfs_iatt_to_statx(fs, &iatt, statxbuf);
|
||||
out:
|
||||
loc_wipe(&loc);
|
||||
|
||||
glfs_subvol_done(fs, subvol);
|
||||
|
||||
__GLFS_EXIT_FS;
|
||||
|
||||
invalid_fs:
|
||||
return ret;
|
||||
}
|
||||
|
||||
GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_statx, future);
|
||||
|
||||
int
|
||||
pub_glfs_fstat(struct glfs_fd *glfd, struct stat *stat)
|
||||
{
|
||||
|
@ -12,7 +12,6 @@
|
||||
#define _GLFS_HANDLES_H
|
||||
|
||||
#include "glfs.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
/* GLFS OBJECT BASED OPERATIONS
|
||||
*
|
||||
|
@ -667,4 +667,32 @@ get_fop_attr_thrd_key(dict_t **fop_attr);
|
||||
|
||||
void
|
||||
unset_fop_attr(dict_t **fop_attr);
|
||||
|
||||
/*
|
||||
SYNOPSIS
|
||||
glfs_statx: Fetch extended file attributes for the given path.
|
||||
|
||||
DESCRIPTION
|
||||
This function fetches extended file attributes for the given path.
|
||||
|
||||
PARAMETERS
|
||||
@fs: The 'virtual mount' object referencing a volume, under which file exists.
|
||||
@path: Path of the file within the virtual mount.
|
||||
@mask: Requested extended file attributes mask, (See mask defines above)
|
||||
|
||||
RETURN VALUES
|
||||
-1 : Failure. @errno will be set with the type of failure.
|
||||
0 : Filled in statxbuf with appropriate masks for valid items in the
|
||||
structure.
|
||||
|
||||
ERRNO VALUES
|
||||
EINVAL: fs is invalid
|
||||
EINVAL: mask has unsupported bits set
|
||||
Other errors as returned by stat(2)
|
||||
*/
|
||||
|
||||
int
|
||||
glfs_statx(struct glfs *fs, const char *path, unsigned int mask,
|
||||
struct glfs_stat *statxbuf) GFAPI_PRIVATE(glfs_statx, future);
|
||||
|
||||
#endif /* !_GLFS_INTERNAL_H */
|
||||
|
@ -40,7 +40,8 @@
|
||||
#include <sys/cdefs.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/*
|
||||
* For off64_t to be defined, we need both
|
||||
@ -403,6 +404,101 @@ glfs_get_volumeid(glfs_t *fs, char *volid, size_t size) __THROW
|
||||
struct glfs_fd;
|
||||
typedef struct glfs_fd glfs_fd_t;
|
||||
|
||||
/*
|
||||
* Mask for request/result items in the struct glfs_stat.
|
||||
*
|
||||
* Query request/result mask for glfs_stat() (family of functions) and
|
||||
* struct glfs_stat::glfs_st_mask.
|
||||
*
|
||||
* These bits should be set in the mask argument of glfs_stat() (family of
|
||||
* functions) to request particular items when calling glfs_stat().
|
||||
*
|
||||
* NOTE: Lower order 32 bits are used to reflect statx(2) bits. For Gluster
|
||||
* specific attrs/extensions, use higher order 32 bits.
|
||||
*
|
||||
*/
|
||||
#define GLFS_STAT_TYPE 0x0000000000000001U /* Want/got stx_mode & S_IFMT */
|
||||
#define GLFS_STAT_MODE 0x0000000000000002U /* Want/got stx_mode & ~S_IFMT */
|
||||
#define GLFS_STAT_NLINK 0x0000000000000004U /* Want/got stx_nlink */
|
||||
#define GLFS_STAT_UID 0x0000000000000008U /* Want/got stx_uid */
|
||||
#define GLFS_STAT_GID 0x0000000000000010U /* Want/got stx_gid */
|
||||
#define GLFS_STAT_ATIME 0x0000000000000020U /* Want/got stx_atime */
|
||||
#define GLFS_STAT_MTIME 0x0000000000000040U /* Want/got stx_mtime */
|
||||
#define GLFS_STAT_CTIME 0x0000000000000080U /* Want/got stx_ctime */
|
||||
#define GLFS_STAT_INO 0x0000000000000100U /* Want/got stx_ino */
|
||||
#define GLFS_STAT_SIZE 0x0000000000000200U /* Want/got stx_size */
|
||||
#define GLFS_STAT_BLOCKS 0x0000000000000400U /* Want/got stx_blocks */
|
||||
#define GLFS_STAT_BASIC_STATS \
|
||||
0x00000000000007ffU /* Items in the normal stat struct */
|
||||
#define GLFS_STAT_BTIME 0x0000000000000800U /* Want/got stx_btime */
|
||||
#define GLFS_STAT_ALL 0x0000000000000fffU /* All currently supported flags */
|
||||
#define GLFS_STAT_RESERVED \
|
||||
0x8000000000000000U /* Reserved to denote future expansion */
|
||||
|
||||
/*
|
||||
* Attributes to be found in glfs_st_attributes and masked in
|
||||
* glfs_st_attributes_mask.
|
||||
*
|
||||
* These give information about the features or the state of a file that might
|
||||
* be of use to programs.
|
||||
*
|
||||
* NOTE: Lower order 32 bits are used to reflect statx(2) attribute bits. For
|
||||
* Gluster specific attrs, use higher order 32 bits.
|
||||
*
|
||||
* NOTE: We do not support any file attributes or state as yet!
|
||||
*/
|
||||
#define GLFS_STAT_ATTR_RESERVED \
|
||||
0x8000000000000000U /* Reserved to denote future expansion */
|
||||
|
||||
/* Extended file attribute structure.
|
||||
*
|
||||
* The caller passes a mask of what they're specifically interested in as a
|
||||
* parameter to glfs_stat(). What glfs_stat() actually got will be indicated
|
||||
* in glfs_st_mask upon return.
|
||||
*
|
||||
* For each bit in the mask argument:
|
||||
*
|
||||
* - if the datum is not supported:
|
||||
*
|
||||
* - the bit will be cleared, and
|
||||
*
|
||||
* - the datum value is undefined
|
||||
*
|
||||
* - otherwise, if explicitly requested:
|
||||
*
|
||||
* - the field will be filled in and the bit will be set;
|
||||
*
|
||||
* - otherwise, if not requested, but available in, it will be filled in
|
||||
* anyway, and the bit will be set upon return;
|
||||
*
|
||||
* - otherwise the field and the bit will be cleared before returning.
|
||||
*
|
||||
*/
|
||||
|
||||
struct glfs_stat {
|
||||
uint64_t glfs_st_mask; /* What results were written [uncond] */
|
||||
uint64_t glfs_st_attributes; /* Flags conveying information about the file
|
||||
[uncond] */
|
||||
uint64_t glfs_st_attributes_mask; /* Mask to show what's supported in
|
||||
st_attributes [ucond] */
|
||||
struct timespec glfs_st_atime; /* Last access time */
|
||||
struct timespec glfs_st_btime; /* File creation time */
|
||||
struct timespec glfs_st_ctime; /* Last attribute change time */
|
||||
struct timespec glfs_st_mtime; /* Last data modification time */
|
||||
ino_t glfs_st_ino; /* Inode number */
|
||||
off_t glfs_st_size; /* File size */
|
||||
blkcnt_t glfs_st_blocks; /* Number of 512-byte blocks allocated */
|
||||
uint32_t glfs_st_rdev_major; /* Device ID of special file [if bdev/cdev] */
|
||||
uint32_t glfs_st_rdev_minor;
|
||||
uint32_t glfs_st_dev_major; /* ID of device containing file [uncond] */
|
||||
uint32_t glfs_st_dev_minor;
|
||||
blksize_t glfs_st_blksize; /* Preferred general I/O size [uncond] */
|
||||
nlink_t glfs_st_nlink; /* Number of hard links */
|
||||
uid_t glfs_st_uid; /* User ID of owner */
|
||||
gid_t glfs_st_gid; /* Group ID of owner */
|
||||
mode_t glfs_st_mode; /* File mode */
|
||||
};
|
||||
|
||||
#define GLFS_LEASE_ID_SIZE 16 /* 128bits */
|
||||
typedef char glfs_leaseid_t[GLFS_LEASE_ID_SIZE];
|
||||
|
||||
|
@ -264,12 +264,10 @@ st_mode_prot_from_ia(ia_prot_t prot)
|
||||
return prot_bit;
|
||||
}
|
||||
|
||||
static inline mode_t
|
||||
st_mode_from_ia(ia_prot_t prot, ia_type_t type)
|
||||
static inline uint32_t
|
||||
st_mode_type_from_ia(ia_type_t type)
|
||||
{
|
||||
mode_t st_mode = 0;
|
||||
uint32_t type_bit = 0;
|
||||
uint32_t prot_bit = 0;
|
||||
|
||||
switch (type) {
|
||||
case IA_IFREG:
|
||||
@ -297,6 +295,17 @@ st_mode_from_ia(ia_prot_t prot, ia_type_t type)
|
||||
break;
|
||||
}
|
||||
|
||||
return type_bit;
|
||||
}
|
||||
|
||||
static inline mode_t
|
||||
st_mode_from_ia(ia_prot_t prot, ia_type_t type)
|
||||
{
|
||||
mode_t st_mode = 0;
|
||||
uint32_t type_bit = 0;
|
||||
uint32_t prot_bit = 0;
|
||||
|
||||
type_bit = st_mode_type_from_ia(type);
|
||||
prot_bit = st_mode_prot_from_ia(prot);
|
||||
|
||||
st_mode = (type_bit | prot_bit);
|
||||
|
184
tests/basic/gfapi/gfapi-statx-basic.c
Normal file
184
tests/basic/gfapi/gfapi-statx-basic.c
Normal file
@ -0,0 +1,184 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <glusterfs/api/glfs.h>
|
||||
|
||||
#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \
|
||||
do { \
|
||||
if (ret < 0) { \
|
||||
fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \
|
||||
strerror(errno)); \
|
||||
goto label; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define GOTO_LABEL_ON_FALSE(compstr, ret, label) \
|
||||
do { \
|
||||
if (ret == false) { \
|
||||
fprintf(stderr, "%s : comparison failed!\n", compstr); \
|
||||
goto label; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WRITE_SIZE 513
|
||||
#define TRUNC_SIZE 4096
|
||||
|
||||
/* Using private function and hence providing a forward declation in sync with
|
||||
code in glfs-internal.h */
|
||||
int
|
||||
glfs_statx(struct glfs *fs, const char *path, unsigned int mask,
|
||||
struct glfs_stat *statxbuf);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ret = -1;
|
||||
int flags = O_RDWR | O_SYNC;
|
||||
glfs_t *fs = NULL;
|
||||
glfs_fd_t *fd1 = NULL;
|
||||
char *volname = NULL;
|
||||
char *logfile = NULL;
|
||||
const char *filename = "file_tmp";
|
||||
const char buff[WRITE_SIZE];
|
||||
struct stat sb;
|
||||
unsigned int mask;
|
||||
struct glfs_stat statx;
|
||||
bool bret;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Invalid argument\n");
|
||||
fprintf(stderr, "Usage: %s <volname> <logfile>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
volname = argv[1];
|
||||
logfile = argv[2];
|
||||
|
||||
fs = glfs_new(volname);
|
||||
if (!fs)
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_new", ret, out);
|
||||
|
||||
ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server", ret, out);
|
||||
|
||||
ret = glfs_set_logging(fs, logfile, 7);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging", ret, out);
|
||||
|
||||
ret = glfs_init(fs);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init", ret, out);
|
||||
|
||||
fd1 = glfs_creat(fs, filename, flags, 0644);
|
||||
if (fd1 == NULL) {
|
||||
ret = -1;
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_creat", ret, out);
|
||||
}
|
||||
|
||||
ret = glfs_truncate(fs, filename, TRUNC_SIZE);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_truncate", ret, out);
|
||||
|
||||
ret = glfs_write(fd1, buff, WRITE_SIZE, flags);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_write", ret, out);
|
||||
|
||||
ret = glfs_fstat(fd1, &sb);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_fstat", ret, out);
|
||||
|
||||
if (sb.st_size != TRUNC_SIZE) {
|
||||
fprintf(stderr, "wrong size %jd should be %jd\n", (intmax_t)sb.st_size,
|
||||
(intmax_t)2048);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
glfs_close(fd1);
|
||||
fd1 = NULL;
|
||||
|
||||
/* TEST 1: Invalid mask to statx */
|
||||
mask = 0xfafadbdb;
|
||||
ret = glfs_statx(fs, filename, mask, NULL);
|
||||
if (ret == 0 || ((ret == -1) && (errno != EINVAL))) {
|
||||
fprintf(stderr,
|
||||
"Invalid args passed, but error returned is"
|
||||
" incorrect (ret - %d, errno - %d)\n",
|
||||
ret, errno);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
/* TEST 2: Call statx and validate fields against prior fstat data */
|
||||
/* NOTE: This fails, as iatt->ia_flags are not carried through the stack,
|
||||
* for example if mdc_to_iatt is invoked to serve cached stat, we will loose
|
||||
* the flags. */
|
||||
mask = GLFS_STAT_ALL;
|
||||
ret = glfs_statx(fs, filename, mask, &statx);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_statx", ret, out);
|
||||
|
||||
if ((statx.glfs_st_mask & GLFS_STAT_BASIC_STATS) != GLFS_STAT_BASIC_STATS) {
|
||||
fprintf(stderr, "Invalid glfs_st_mask, expecting 0x%x got 0x%x\n",
|
||||
GLFS_STAT_ALL, statx.glfs_st_mask);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bret = (sb.st_ino == statx.glfs_st_ino);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_ino == statx.glfs_st_ino)", bret, out);
|
||||
|
||||
bret = (sb.st_mode == statx.glfs_st_mode);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_mode == statx.glfs_st_mode)", bret, out);
|
||||
|
||||
bret = (sb.st_nlink == statx.glfs_st_nlink);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_nlink == statx.glfs_st_nlink)", bret, out);
|
||||
|
||||
bret = (sb.st_uid == statx.glfs_st_uid);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_uid == statx.glfs_st_uid)", bret, out);
|
||||
|
||||
bret = (sb.st_gid == statx.glfs_st_gid);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_gid == statx.glfs_st_gid)", bret, out);
|
||||
|
||||
bret = (sb.st_size == statx.glfs_st_size);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_size == statx.glfs_st_size)", bret, out);
|
||||
|
||||
bret = (sb.st_blksize == statx.glfs_st_blksize);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_blksize == statx.glfs_st_blksize)", bret, out);
|
||||
|
||||
bret = (sb.st_blocks == statx.glfs_st_blocks);
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_blocks == statx.glfs_st_blocks)", bret, out);
|
||||
|
||||
bret = (!memcmp(&sb.st_atim, &statx.glfs_st_atime,
|
||||
sizeof(struct timespec)));
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_atim == statx.glfs_st_atime)", bret, out);
|
||||
|
||||
bret = (!memcmp(&sb.st_mtim, &statx.glfs_st_mtime,
|
||||
sizeof(struct timespec)));
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_mtim == statx.glfs_st_mtime)", bret, out);
|
||||
|
||||
bret = (!memcmp(&sb.st_ctim, &statx.glfs_st_ctime,
|
||||
sizeof(struct timespec)));
|
||||
GOTO_LABEL_ON_FALSE("(sb.st_ctim == statx.glfs_st_ctime)", bret, out);
|
||||
|
||||
/* TEST 3: Check if partial masks are accepted */
|
||||
mask = GLFS_STAT_TYPE | GLFS_STAT_UID | GLFS_STAT_GID;
|
||||
ret = glfs_statx(fs, filename, mask, &statx);
|
||||
VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_statx", ret, out);
|
||||
|
||||
/* We currently still return all stats, as is acceptable based on the API
|
||||
* definition in the header (and in statx as well) */
|
||||
if ((statx.glfs_st_mask & GLFS_STAT_BASIC_STATS) != GLFS_STAT_BASIC_STATS) {
|
||||
fprintf(stderr, "Invalid glfs_st_mask, expecting 0x%x got 0x%x\n",
|
||||
GLFS_STAT_ALL, statx.glfs_st_mask);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (fd1 != NULL)
|
||||
glfs_close(fd1);
|
||||
if (fs) {
|
||||
(void)glfs_fini(fs);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
30
tests/basic/gfapi/gfapi-statx-basic.t
Executable file
30
tests/basic/gfapi/gfapi-statx-basic.t
Executable file
@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
. $(dirname $0)/../../include.rc
|
||||
. $(dirname $0)/../../volume.rc
|
||||
|
||||
cleanup;
|
||||
|
||||
TEST glusterd
|
||||
|
||||
TEST $CLI volume create $V0 ${H0}:$B0/brick1;
|
||||
EXPECT 'Created' volinfo_field $V0 'Status';
|
||||
|
||||
TEST $CLI volume start $V0;
|
||||
EXPECT 'Started' volinfo_field $V0 'Status';
|
||||
|
||||
# NOTE: Test is passing due to very specific volume configuration
|
||||
# Disable md-cache, as it does not save and return ia_flags from iatt
|
||||
# This is possibly going to be true of other xlators as well (ec/afr), need to
|
||||
# ensure these are fixed, or hack statx to return all basic attrs anyway.
|
||||
TEST $CLI volume set $V0 performance.md-cache-timeout 0
|
||||
|
||||
logdir=`gluster --print-logdir`
|
||||
|
||||
build_tester $(dirname $0)/gfapi-statx-basic.c -lgfapi
|
||||
|
||||
TEST ./$(dirname $0)/gfapi-statx-basic $V0 $logdir/gfapi-statx-basic.log
|
||||
|
||||
cleanup_tester $(dirname $0)/gfapi-statx-basic
|
||||
|
||||
cleanup;
|
Loading…
x
Reference in New Issue
Block a user