summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/dict.c
diff options
context:
space:
mode:
authorPoornima G <pgurusid@redhat.com>2018-06-27 14:59:40 +0530
committerAmar Tumballi <amarts@redhat.com>2018-07-11 04:11:59 +0000
commit69f77d28c3ecacba77fbae2f789b5110641347f3 (patch)
tree746f1470476a981b6becaedb6c7c1e681f457f41 /libglusterfs/src/dict.c
parentaf6c6429f9743f287baaad68f8e3d56ed7390d1b (diff)
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 <xhernandez@redhat.com> Signed-off-by: Poornima G <pgurusid@redhat.com>
Diffstat (limited to 'libglusterfs/src/dict.c')
-rw-r--r--libglusterfs/src/dict.c77
1 files changed, 75 insertions, 2 deletions
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)