summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorKrutika Dhananjay <kdhananj@redhat.com>2017-01-17 16:40:04 +0530
committerRaghavendra G <rgowdapp@redhat.com>2018-08-18 07:28:53 +0000
commitc9bde3021202f1d5c5a2d19ac05a510fc1f788ac (patch)
treeeba54e5f791b33d079afae9655d5438d007c3091 /tests
parent045d70a5450daa85aa5564b6e9f93065c342ab12 (diff)
performance/readdir-ahead: keep stats of cached dentries in sync with modifications
PROBLEM: Stats of dentries that are readdirp'd ahead can become stale due to fops like writes, truncate etc that modify the file pointed by dentries. When a readdir is finally wound at offset corresponding to these entries, the iatts that are returned to the application come from readdir-ahead's cache, which are stale by now. This problem gets further aggravated when caching translators/modules cache and continue to serve this stale information. FIX: * Store the iatt in context of the inode pointed by dentry. * Whenever the inode pointed by dentry undergoes modification, in cbk of modification fop, update the iatt stored in inode-ctx to reflect the modification. * When serving a readdirp response from application, update iatts of dentries with the iatts stored in the context of inodes pointed by these dentries. * Some fops don't have valid iatts in their responses. For eg., write response whose data is still cached in write-behind will have zeroed out stat. In this case keep only ia_type and ia_gfid and reset rest of the iatt members to zero. - fuse-bridge in this case just sends "entry" information back to kernel and attr is not sent. - gfapi sets entry->inode to NULL and zeroes out the entire stat * There is one tiny race between the entry creation and a readdirp on its parent dir, which could cause the inode-ctx setting and inode ctx reading to happen on two different inode objects. To prevent this, when entry->inode doesn't eqaul to linked_inode, - fuse-bridge is made to send only "entry" information without attributes - gfapi sets entry->inode to NULL and zeroes out the entire stat. Change-Id: Ia27ff49a61922e88c73a1547ad8aacc9968a69df BUG: 1390050 Updates: bz#1390050 Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com> Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/basic/afr/split-brain-healing.t1
-rw-r--r--tests/bugs/readdir-ahead/bug-1390050.c70
-rw-r--r--tests/bugs/readdir-ahead/bug-1390050.t29
3 files changed, 99 insertions, 1 deletions
diff --git a/tests/basic/afr/split-brain-healing.t b/tests/basic/afr/split-brain-healing.t
index 773a8b33b12..c80f900b909 100644
--- a/tests/basic/afr/split-brain-healing.t
+++ b/tests/basic/afr/split-brain-healing.t
@@ -76,7 +76,6 @@ do
done
BIGGER_FILE_SIZE=$(stat -c %s file1)
-
TEST $CLI volume start $V0 force
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1
EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 3
diff --git a/tests/bugs/readdir-ahead/bug-1390050.c b/tests/bugs/readdir-ahead/bug-1390050.c
new file mode 100644
index 00000000000..5593a1d4c0c
--- /dev/null
+++ b/tests/bugs/readdir-ahead/bug-1390050.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+
+int
+main (int argc, char *argv[])
+{
+ const char *glfs_dir = NULL, *filepath = NULL;
+ DIR *dirfd = NULL;
+ int filefd = 0, ret = 0;
+ struct stat stbuf = {0, };
+ size_t size_before_write = 0;
+
+ glfs_dir = argv[1];
+ filepath = argv[2];
+ dirfd = opendir (glfs_dir);
+ if (dirfd == NULL) {
+ fprintf (stderr, "opening directory failed (%s)\n",
+ strerror (errno));
+ goto err;
+ }
+
+ filefd = open (filepath, O_RDWR);
+ if (filefd < 0) {
+ fprintf (stderr, "open failed on path %s (%s)\n", filepath,
+ strerror (errno));
+ goto err;
+ }
+
+ ret = stat (filepath, &stbuf);
+ if (ret < 0) {
+ fprintf (stderr, "stat failed on path %s (%s)\n", filepath,
+ strerror (errno));
+ goto err;
+ }
+
+ size_before_write = stbuf.st_size;
+
+ ret = write (filefd, "testdata", strlen ("testdata123") + 1);
+ if (ret <= 0) {
+ fprintf (stderr, "write failed (%s)\n", strerror (errno));
+ goto err;
+ }
+
+ while (readdir (dirfd)) {
+ /* do nothing */
+ }
+
+ ret = stat (filepath, &stbuf);
+ if (ret < 0) {
+ fprintf (stderr, "stat failed on path %s (%s)\n",
+ strerror (errno));
+ goto err;
+ }
+
+ if (stbuf.st_size == size_before_write) {
+ fprintf (stderr, "file size (%lu) has not changed even after "
+ "its written to\n", stbuf.st_size);
+ goto err;
+ }
+
+ return 0;
+err:
+ return -1;
+}
diff --git a/tests/bugs/readdir-ahead/bug-1390050.t b/tests/bugs/readdir-ahead/bug-1390050.t
new file mode 100644
index 00000000000..ab1d7d4ead9
--- /dev/null
+++ b/tests/bugs/readdir-ahead/bug-1390050.t
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+. $(dirname $0)/../../fileio.rc
+
+cleanup;
+
+TEST glusterd
+
+TEST $CLI volume create $V0 $H0:$B{0..1}/$V0
+TEST $CLI volume set $V0 readdir-ahead on
+
+DIRECTORY="$M0/subdir1/subdir2"
+
+#Make sure md-cache has large timeout to hold stat from readdirp_cbk in its cache
+TEST $CLI volume set $V0 performance.md-cache-timeout 600
+TEST $CLI volume start $V0
+TEST glusterfs --volfile-server=$H0 --volfile-id=$V0 $M0
+rm -rf $M0/*
+TEST mkdir -p $DIRECTORY
+rm -rf $DIRECTORY/*
+TEST touch $DIRECTORY/file{0..10}
+rdd_tester=$(dirname $0)/rdd-tester
+TEST build_tester $(dirname $0)/bug-1390050.c -o $rdd_tester
+TEST $rdd_tester $DIRECTORY $DIRECTORY/file4
+rm -f $rdd_tester
+cleanup;
+