diff options
author | Krutika Dhananjay <kdhananj@redhat.com> | 2017-01-17 16:40:04 +0530 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2018-08-18 07:28:53 +0000 |
commit | c9bde3021202f1d5c5a2d19ac05a510fc1f788ac (patch) | |
tree | eba54e5f791b33d079afae9655d5438d007c3091 /tests/bugs | |
parent | 045d70a5450daa85aa5564b6e9f93065c342ab12 (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/bugs')
-rw-r--r-- | tests/bugs/readdir-ahead/bug-1390050.c | 70 | ||||
-rw-r--r-- | tests/bugs/readdir-ahead/bug-1390050.t | 29 |
2 files changed, 99 insertions, 0 deletions
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; + |