diff options
| author | ShyamsundarR <srangana@redhat.com> | 2018-11-21 09:43:23 -0500 | 
|---|---|---|
| committer | Amar Tumballi <amarts@redhat.com> | 2019-01-07 14:43:27 +0000 | 
| commit | c31f1c232a6673c4e3fc3188e15ae0e708a54613 (patch) | |
| tree | 195a5c281b7d88991fb9bdc3c4570fec6ca95366 | |
| parent | f99f51ca87fd8703947df985901cbce37bc6c818 (diff) | |
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>
| -rw-r--r-- | api/src/gfapi.aliases | 2 | ||||
| -rw-r--r-- | api/src/gfapi.map | 7 | ||||
| -rw-r--r-- | api/src/glfs-fops.c | 140 | ||||
| -rw-r--r-- | api/src/glfs-handles.h | 1 | ||||
| -rw-r--r-- | api/src/glfs-internal.h | 28 | ||||
| -rw-r--r-- | api/src/glfs.h | 98 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs/iatt.h | 17 | ||||
| -rw-r--r-- | tests/basic/gfapi/gfapi-statx-basic.c | 184 | ||||
| -rwxr-xr-x | tests/basic/gfapi/gfapi-statx-basic.t | 30 | 
9 files changed, 500 insertions, 7 deletions
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases index 0e52c38d346..73b0bb67bcf 100644 --- a/api/src/gfapi.aliases +++ b/api/src/gfapi.aliases @@ -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 diff --git a/api/src/gfapi.map b/api/src/gfapi.map index 1be2953ce9a..b7f0dab2340 100644 --- a/api/src/gfapi.map +++ b/api/src/gfapi.map @@ -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; diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index 272e75c818c..d3255d18c0f 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -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)  { @@ -456,6 +541,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)  {      int ret = -1; diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h index 09b3b2ed493..89b1ed0f2e6 100644 --- a/api/src/glfs-handles.h +++ b/api/src/glfs-handles.h @@ -12,7 +12,6 @@  #define _GLFS_HANDLES_H  #include "glfs.h" -#include <inttypes.h>  /* GLFS OBJECT BASED OPERATIONS   * diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index 8fdfec8ca02..d372413fd56 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -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 */ diff --git a/api/src/glfs.h b/api/src/glfs.h index 160a784222f..7f0a34ae9e7 100644 --- a/api/src/glfs.h +++ b/api/src/glfs.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]; diff --git a/libglusterfs/src/glusterfs/iatt.h b/libglusterfs/src/glusterfs/iatt.h index 339c84ccc45..bee7a0afa77 100644 --- a/libglusterfs/src/glusterfs/iatt.h +++ b/libglusterfs/src/glusterfs/iatt.h @@ -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); diff --git a/tests/basic/gfapi/gfapi-statx-basic.c b/tests/basic/gfapi/gfapi-statx-basic.c new file mode 100644 index 00000000000..a4943fa0fd1 --- /dev/null +++ b/tests/basic/gfapi/gfapi-statx-basic.c @@ -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; +} diff --git a/tests/basic/gfapi/gfapi-statx-basic.t b/tests/basic/gfapi/gfapi-statx-basic.t new file mode 100755 index 00000000000..d9acbce2f99 --- /dev/null +++ b/tests/basic/gfapi/gfapi-statx-basic.t @@ -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;  | 
