From 69f77d28c3ecacba77fbae2f789b5110641347f3 Mon Sep 17 00:00:00 2001 From: Poornima G Date: Wed, 27 Jun 2018 14:59:40 +0530 Subject: md-cache: Do not invalidate cache post set/remove xattr Since setxattr and removexattr fops cbk do not carry poststat, the stat cache was being invalidated in setxatr/remoxattr cbk. Hence the further lookup wouldn't be served from cache. To prevent this invalidation, md-cache is modified to get the poststat in set/removexattr_cbk in dict. Co-authored with Xavi Hernandez. Change-Id: I6b946be2d20b807e2578825743c25ba5927a60b4 fixes: bz#1586018 Signed-off-by: Xavi Hernandez Signed-off-by: Poornima G --- libglusterfs/src/dict.c | 77 ++++++++++++++++++++++++++++++++++++++- libglusterfs/src/dict.h | 1 + libglusterfs/src/glusterfs.h | 2 + libglusterfs/src/libglusterfs.sym | 1 + 4 files changed, 79 insertions(+), 2 deletions(-) (limited to 'libglusterfs/src') diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index bd22477f2c4..be47def148c 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -132,6 +132,8 @@ int32_t is_data_equal (data_t *one, data_t *two) { + struct iatt *iatt1, *iatt2; + if (!one || !two || !one->data || !two->data) { gf_msg_callingfn ("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, @@ -143,11 +145,63 @@ is_data_equal (data_t *one, if (one == two) return 1; - if (one->len != two->len) + if (one->data == two->data) + return 1; + + if (one->data_type != two->data_type) { return 0; + } - if (one->data == two->data) + if (one->data_type == GF_DATA_TYPE_IATT) { + if ((one->len < sizeof(struct iatt)) || + (two->len < sizeof(struct iatt))) { + return 0; + } + + iatt1 = (struct iatt *)one->data; + iatt2 = (struct iatt *)two->data; + + /* Two iatt structs are considered equal if main fields are + * equal, even if times differ. + * TODO: maybe when ctime if fully operational we could + * enforce time matching. */ + if (iatt1->ia_ino != iatt2->ia_ino) { + return 0; + } + if (iatt1->ia_type != iatt2->ia_type) { + return 0; + } + if ((iatt1->ia_type == IA_IFBLK) || + (iatt1->ia_type == IA_IFCHR)) { + if (iatt1->ia_rdev != iatt2->ia_rdev) { + return 0; + } + } + if (gf_uuid_compare(iatt1->ia_gfid, iatt2->ia_gfid) != 0) { + return 0; + } + + /* TODO: ia_uid, ia_gid, ia_prot and ia_size can be changed + * with some commands. Here we don't have enough + * information to decide if they should match or not. */ +/* + if ((iatt1->ia_uid != iatt2->ia_uid) || + (iatt1->ia_gid != iatt2->ia_gid) || + (st_mode_from_ia(iatt1->ia_prot, iatt1->ia_type) != + st_mode_from_ia(iatt2->ia_prot, iatt2->ia_type))) { + return 0; + } + if (iatt1->ia_type == IA_IFREG) { + if (iatt1->ia_size != iatt2->ia_size) { + return 0; + } + } +*/ return 1; + } + + if (one->len != two->len) + return 0; if (memcmp (one->data, two->data, one->len) == 0) return 1; @@ -1196,6 +1250,25 @@ data_to_bin (data_t *data) return data->data; } +struct iatt * +data_to_iatt (data_t *data, char *key) +{ + VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_IATT, key, NULL); + + /* We only check for smaller size. If it's bigger we simply ignore + * the extra data. This way it's easy to do changes in the future that + * pass more data but are backward compatible (if the initial contents + * of the struct are maintained, of course). */ + if (data->len < sizeof(struct iatt)) { + gf_msg("glusterfs", GF_LOG_ERROR, ENOBUFS, + LG_MSG_UNDERSIZED_BUF, + "data value for '%s' is smaller than expected", key); + return NULL; + } + + return (struct iatt *)data->data; +} + int dict_null_foreach_fn (dict_t *d, char *k, data_t *v, void *tmp) diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index d0b05172c2e..52b6c8c62fe 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -166,6 +166,7 @@ char *data_to_str (data_t *data); void *data_to_bin (data_t *data); void *data_to_ptr (data_t *data); data_t * data_copy (data_t *old); +struct iatt *data_to_iatt (data_t *data, char *key); int dict_foreach (dict_t *this, int (*fn)(dict_t *this, diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 24f08a05f40..4c0936a9f08 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -321,6 +321,8 @@ enum gf_internal_fop_indicator { #define DHT_MODE_IN_XDATA_KEY "dht-get-mode-in-xattr" #define GET_LINK_COUNT "get-link-count" #define GF_GET_SIZE "get-size" +#define GF_PRESTAT "virt-gf-prestat" +#define GF_POSTSTAT "virt-gf-poststat" /*CTR and Marker requires inode dentry link count from posix*/ #define GF_RESPONSE_LINK_COUNT_XDATA "gf_response_link_count" diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym index 465bb63eb5c..ca952d51942 100644 --- a/libglusterfs/src/libglusterfs.sym +++ b/libglusterfs/src/libglusterfs.sym @@ -147,6 +147,7 @@ data_to_uint16 data_to_uint32 data_to_uint64 data_to_uint8 +data_to_iatt data_unref default_access default_access_cbk -- cgit