From c31f1c232a6673c4e3fc3188e15ae0e708a54613 Mon Sep 17 00:00:00 2001 From: ShyamsundarR Date: Wed, 21 Nov 2018 09:43:23 -0500 Subject: gfapi: new api glfs_statx as linux's statx Change-Id: I44dd6ceef0954ae7fc13f920e84d81bbd3f6a774 Updates: #389 Signed-off-by: Kinglong Mee Signed-off-by: ShyamsundarR --- api/src/gfapi.aliases | 2 + api/src/gfapi.map | 7 ++- api/src/glfs-fops.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ api/src/glfs-handles.h | 1 - api/src/glfs-internal.h | 28 ++++++++++ api/src/glfs.h | 98 ++++++++++++++++++++++++++++++++- 6 files changed, 273 insertions(+), 3 deletions(-) (limited to 'api') 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 #include #include "glusterfs3.h" +#include #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) { 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 /* 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 #include #include -#include +#include +#include /* * 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]; -- cgit