diff options
author | Raghavendra Gowdappa <rgowdapp@redhat.com> | 2018-10-12 10:31:04 +0530 |
---|---|---|
committer | Shyamsundar Ranganathan <srangana@redhat.com> | 2018-10-17 23:36:13 +0000 |
commit | 5bc2fd4fc6a8aa65d8d2b2c22ffb6c5b70ef9dac (patch) | |
tree | 21a7815cbee00f0245fb068ce586a2a5d505aee7 | |
parent | 34e8058b7c8e906c889d6d0e155ea63037148eea (diff) |
api: fill out attribute information if not valid
translators like readdir-ahead selectively retain entry information of
iatt (gfid and type) when rest of the iatt is invalidated (for write
invalidating ia_size, (m)(c)times etc). Fuse-bridge uses this
information and sends only entry information in readdirplus
response. However such option doesn't exist in gfapi. This patch
modifies gfapi to populate the stat by forcing an extra lookup.
Thanks to Shyamsundar Ranganathan <srangana@redhat.com> and Prashanth
Pai <ppai@redhat.com> for tests.
Change-Id: Ieb5f8fc76359c327627b7d8420aaf20810e53000
Fixes: bz#1630804
Signed-off-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
Signed-off-by: Soumya Koduri <skoduri@redhat.com>
(cherry picked from commit 6257276d9de3f15643f159b2ec627a67c84fc23d)
-rw-r--r-- | api/src/glfs-fops.c | 12 | ||||
-rw-r--r-- | tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.c | 112 | ||||
-rw-r--r-- | tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.t | 25 |
3 files changed, 147 insertions, 2 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index 9f61e41629c..cafbeb7f515 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -2869,12 +2869,20 @@ glfd_entry_refresh(struct glfs_fd *glfd, int plus) if (plus) { list_for_each_entry(entry, &entries.list, list) { - if (!entry->inode && !IA_ISDIR(entry->d_stat.ia_type)) { + if ((!entry->inode && (!IA_ISDIR(entry->d_stat.ia_type))) || + ((entry->d_stat.ia_ctime == 0) && + strcmp(entry->d_name, ".") && + strcmp(entry->d_name, ".."))) { /* entry->inode for directories will be * always set to null to force a lookup - * on the dentry. Also we will have + * on the dentry. Hence to not degrade + * readdir performance, we skip lookups + * for directory entries. Also we will have * proper stat if directory present on * hashed subvolume. + * + * In addition, if the stat is invalid, force + * lookup to fetch proper stat. */ gf_fill_iatt_for_dirent(entry, fd->inode, subvol); } diff --git a/tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.c b/tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.c new file mode 100644 index 00000000000..d151784627c --- /dev/null +++ b/tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.c @@ -0,0 +1,112 @@ +#include <inttypes.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <glusterfs/api/glfs.h> +#include <glusterfs/api/glfs-handles.h> + +#define VALIDATE_AND_GOTO_LABEL_ON_ERROR(func, ret, label) \ + do { \ + if (ret < 0) { \ + fprintf(stderr, "%s : returned error %d (%s)\n", func, ret, \ + strerror(errno)); \ + goto label; \ + } \ + } while (0) + +int +main(int argc, char *argv[]) +{ + int ret = -1; + int flags = O_WRONLY | O_CREAT | O_TRUNC; + int do_write = 0; + glfs_t *fs = NULL; + glfs_fd_t *fd1 = NULL; + glfs_fd_t *fd2 = NULL; + char *volname = NULL; + char *logfile = NULL; + const char *dirname = "/some_dir1"; + const char *filename = "/some_dir1/testfile"; + const char *short_filename = "testfile"; + struct stat sb; + char buf[512]; + struct dirent *entry = NULL; + + if (argc != 4) { + fprintf(stderr, "Invalid argument\n"); + fprintf(stderr, "Usage: %s <volname> <logfile> <do-write [0/1]\n", + argv[0]); + return 1; + } + + volname = argv[1]; + logfile = argv[2]; + do_write = atoi(argv[3]); + + fs = glfs_new(volname); + if (!fs) + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_new", ret, out); + + ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_volfile_server", ret, out); + + ret = glfs_set_logging(fs, logfile, 7); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_set_logging", ret, out); + + ret = glfs_init(fs); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_init", ret, out); + + ret = glfs_mkdir(fs, dirname, 0755); + if (ret && errno != EEXIST) + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_mkdir", ret, out); + + fd1 = glfs_creat(fs, filename, flags, 0644); + if (fd1 == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_creat", ret, out); + } + + if (do_write) { + ret = glfs_write(fd1, "hello world", 11, flags); + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_write", ret, out); + } + + fd2 = glfs_opendir(fs, dirname); + if (fd2 == NULL) { + ret = -1; + VALIDATE_AND_GOTO_LABEL_ON_ERROR("glfs_opendir", ret, out); + } + + do { + ret = glfs_readdirplus_r(fd2, &sb, (struct dirent *)buf, &entry); + if (entry != NULL) { + if (!strcmp(entry->d_name, short_filename)) { + if (sb.st_mode == 0) { + fprintf( + stderr, + "Mode bits are incorrect: d_name - %s, st_mode - %jd\n", + entry->d_name, (intmax_t)sb.st_mode); + ret = -1; + goto out; + } + } + } + } while (entry != NULL); + +out: + if (fd1 != NULL) + glfs_close(fd1); + if (fd2 != NULL) + glfs_closedir(fd2); + + if (fs) { + /* + * If this fails (as it does on Special Snowflake NetBSD for no + * good reason), it shouldn't affect the result of the test. + */ + (void)glfs_fini(fs); + } + + return ret; +} diff --git a/tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.t b/tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.t new file mode 100644 index 00000000000..ac59aeeb47b --- /dev/null +++ b/tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.t @@ -0,0 +1,25 @@ +#!/bin/bash + +. $(dirname $0)/../../../include.rc +. $(dirname $0)/../../../volume.rc + +cleanup; + +TEST glusterd + +TEST $CLI volume create $V0 ${H0}:$B0/brick1; +EXPECT 'Created' volinfo_field $V0 'Status'; + +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +logdir=`gluster --print-logdir` + +build_tester $(dirname $0)/gfapi-bz1630804.c -lgfapi + +TEST ./$(dirname $0)/gfapi-bz1630804 $V0 $logdir/gfapi-bz1630804.log 0 +TEST ./$(dirname $0)/gfapi-bz1630804 $V0 $logdir/gfapi-bz1630804.log 1 + +cleanup_tester $(dirname $0)/gfapi-trunc + +cleanup; |