diff options
-rwxr-xr-x | tests/bugs/upcall/bug-1369430.t | 43 | ||||
-rw-r--r-- | xlators/features/upcall/src/upcall.c | 43 |
2 files changed, 85 insertions, 1 deletions
diff --git a/tests/bugs/upcall/bug-1369430.t b/tests/bugs/upcall/bug-1369430.t new file mode 100755 index 00000000000..f53c17a1495 --- /dev/null +++ b/tests/bugs/upcall/bug-1369430.t @@ -0,0 +1,43 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +## 1. Start glusterd +TEST glusterd; + +## 2. Lets create volume +TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2,3}; + +## 3. Start the volume +TEST $CLI volume start $V0 + +## 4. Enable the upcall xlator, and increase the md-cache timeout to max +TEST $CLI volume set $V0 features.cache-invalidation on +TEST $CLI volume set $V0 features.cache-invalidation-timeout 600 +TEST $CLI volume set $V0 performance.cache-invalidation on +TEST $CLI volume set $V0 performance.md-cache-timeout 600 +TEST $CLI volume set $V0 performance.cache-samba-metadata on + +## 8. Create two gluster mounts +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M0 +TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M1 + +## 10. Create directory and files from the M0 +TEST mkdir $M0/dir1 +TEST touch $M0/dir1/file{1..5} + +## 12. Access the files via readdirp, from M1 +TEST ls -l $M1/dir1/ + +# Change the stat of one of the files from M0 and wait for it to +# invalidate the md-cache of another mount M0 +echo "hello" > $M0/dir1/file2 +sleep 2; + +## 13. Expct non zero size when stat from M1 +EXPECT_NOT "0" stat -c %s $M1/dir1/file2 + +cleanup; diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c index c7b74ed3c29..2e1dd60187d 100644 --- a/xlators/features/upcall/src/upcall.c +++ b/xlators/features/upcall/src/upcall.c @@ -1304,6 +1304,47 @@ err: } int32_t +up_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + gf_dirent_t *entry = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL, NULL); + + /* upcall_cache_invalidate optimises, by not calling inode_ctx_get + * if local->upcall_inode_ctx is set. Hence before processing + * the readdir entries unset this */ + local->upcall_inode_ctx = NULL; + list_for_each_entry (entry, &entries->list, list) { + if (entry->inode == NULL) { + continue; + } + upcall_cache_invalidate (frame, this, client, entry->inode, + flags, &entry->d_stat, NULL, NULL, + NULL); + } + +out: + UPCALL_STACK_UNWIND (readdirp, frame, op_ret, op_errno, entries, xdata); + + return 0; +} + +int32_t up_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *dict) { @@ -1319,7 +1360,7 @@ up_readdirp (call_frame_t *frame, xlator_t *this, } out: - STACK_WIND (frame, up_readdir_cbk, + STACK_WIND (frame, up_readdirp_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, fd, size, off, dict); |