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);  | 
