glusterfs/0558-afr-fix-directory-entry-count.patch
Gluster Jenkins af562eab56 autobuild v6.0-57
Related: rhbz#2055630
Resolves: bz#1600379 bz#1689375 bz#1782428 bz#1798897 bz#1815462
Resolves: bz#1889966 bz#1891403 bz#1901468 bz#1903911 bz#1908635
Resolves: bz#1917488 bz#1918018 bz#1919132 bz#1925425 bz#1927411
Resolves: bz#1927640 bz#1928676 bz#1942816 bz#1943467 bz#1945143
Resolves: bz#1946171 bz#1957191 bz#1957641
Signed-off-by: Gluster Jenkins <dkhandel+glusterjenkins@redhat.com>
2022-02-28 21:15:34 +02:00

239 lines
7.6 KiB
Diff

From 9bf6986f8ea3edd9de3d2629404f7ab11c1597de Mon Sep 17 00:00:00 2001
From: Xavi Hernandez <xhernandez@redhat.com>
Date: Tue, 9 Mar 2021 00:24:07 +0100
Subject: [PATCH 558/584] afr: fix directory entry count
AFR may hide some existing entries from a directory when reading it
because they are generated internally for private management. However
the returned number of entries from readdir() function is not updated
accordingly. So it may return a number higher than the real entries
present in the gf_dirent list.
This may cause unexpected behavior of clients, including gfapi which
incorrectly assumes that there was an entry when the list was actually
empty.
This patch also makes the check in gfapi more robust to avoid similar
issues that could appear in the future.
Backport of:
> Upstream-patch: https://github.com/gluster/glusterfs/pull/2233
> Fixes: #2232
> Change-Id: I81ba3699248a53ebb0ee4e6e6231a4301436f763
> Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
BUG: 1927411
Change-Id: I81ba3699248a53ebb0ee4e6e6231a4301436f763
Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/c/rhs-glusterfs/+/244535
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
api/src/glfs-fops.c | 3 +-
tests/bugs/replicate/issue-2232.c | 85 ++++++++++++++++++++++++++++++++++
tests/bugs/replicate/issue-2232.t | 34 ++++++++++++++
xlators/cluster/afr/src/afr-dir-read.c | 11 +++--
4 files changed, 129 insertions(+), 4 deletions(-)
create mode 100644 tests/bugs/replicate/issue-2232.c
create mode 100644 tests/bugs/replicate/issue-2232.t
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
index 6dc3b66..821d250 100644
--- a/api/src/glfs-fops.c
+++ b/api/src/glfs-fops.c
@@ -3748,8 +3748,9 @@ glfd_entry_refresh(struct glfs_fd *glfd, int plus)
errno = 0;
}
- if (ret > 0)
+ if ((ret > 0) && !list_empty(&glfd->entries)) {
glfd->next = list_entry(glfd->entries.next, gf_dirent_t, list);
+ }
gf_dirent_free(&old);
out:
diff --git a/tests/bugs/replicate/issue-2232.c b/tests/bugs/replicate/issue-2232.c
new file mode 100644
index 0000000..df547c2
--- /dev/null
+++ b/tests/bugs/replicate/issue-2232.c
@@ -0,0 +1,85 @@
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <glusterfs/api/glfs.h>
+
+int main(int argc, char **argv)
+{
+ char log[128];
+ struct dirent entry;
+ struct dirent *ent;
+ glfs_xreaddirp_stat_t *xstat;
+ int ret, flags;
+
+ if (argc != 3) {
+ fprintf(stderr, "Syntax: %s <hostname> <volume>\n", argv[0]);
+ exit(1);
+ }
+ char *hostname = argv[1];
+ char *volname = argv[2];
+
+ glfs_t *fs = glfs_new(volname);
+ if (!fs) {
+ fprintf(stderr, "glfs_new() failed\n");
+ exit(1);
+ }
+
+ ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007);
+ if (ret < 0) {
+ fprintf(stderr, "glfs_set_volfile_server() failed\n");
+ return ret;
+ }
+
+ sprintf(log, "/tmp/logs-%d.log", getpid());
+ ret = glfs_set_logging(fs, log, 9);
+ if (ret < 0) {
+ fprintf(stderr, "glfs_set_logging() failed\n");
+ return ret;
+ }
+
+ ret = glfs_init(fs);
+ if (ret < 0) {
+ fprintf(stderr, "glfs_init() failed\n");
+ return ret;
+ }
+
+ glfs_fd_t *fd = glfs_opendir(fs, "/");
+ if (fd == NULL) {
+ fprintf(stderr, "glfs_opendir() failed\n");
+ return 1;
+ }
+
+ flags = GFAPI_XREADDIRP_STAT | GFAPI_XREADDIRP_HANDLE;
+ xstat = NULL;
+ while ((ret = glfs_xreaddirplus_r(fd, flags, &xstat, &entry, &ent)) > 0) {
+ if (xstat != NULL) {
+ glfs_free(xstat);
+ }
+ if ((strcmp(ent->d_name, ".") == 0) ||
+ (strcmp(ent->d_name, "..") == 0)) {
+ xstat = NULL;
+ continue;
+ }
+ if ((xstat == NULL) || ((ret & GFAPI_XREADDIRP_HANDLE) == 0)) {
+ fprintf(stderr, "glfs_xreaddirplus_r() failed: %s\n",
+ strerror(errno));
+ return 1;
+ }
+
+ xstat = NULL;
+ }
+
+ if (ret < 0) {
+ fprintf(stderr, "glfs_xreaddirplus_r() failed\n");
+ return ret;
+ }
+
+ glfs_close(fd);
+
+ glfs_fini(fs);
+
+ return ret;
+}
diff --git a/tests/bugs/replicate/issue-2232.t b/tests/bugs/replicate/issue-2232.t
new file mode 100644
index 0000000..66a41e0
--- /dev/null
+++ b/tests/bugs/replicate/issue-2232.t
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+. $(dirname "${0}")/../../include.rc
+. $(dirname "${0}")/../../volume.rc
+
+cleanup;
+TEST gcc $(dirname "${0}")/issue-2232.c -o $(dirname "${0}")/issue-2232 -lgfapi
+TEST glusterd
+TEST pidof glusterd
+
+TEST $CLI volume create ${V0} replica 3 ${H0}:${B0}/${V0}{0..2}
+
+# Create a fake .glusterfs-anonymous-inode-... entry
+ANONINO=".glusterfs-anonymous-inode-aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
+TEST mkdir ${B0}/${V0}{0..2}/${ANONINO}
+gfid="$(uuidgen)"
+hex="0x$(echo "${gfid}" | tr -d '-')"
+TEST assign_gfid "${hex}" "${B0}/${V0}0/${ANONINO}"
+TEST assign_gfid "${hex}" "${B0}/${V0}1/${ANONINO}"
+TEST assign_gfid "${hex}" "${B0}/${V0}2/${ANONINO}"
+TEST mkdir -p "${B0}/${V0}0/.glusterfs/${gfid:0:2}/${gfid:2:2}"
+TEST mkdir -p "${B0}/${V0}1/.glusterfs/${gfid:0:2}/${gfid:2:2}"
+TEST mkdir -p "${B0}/${V0}2/.glusterfs/${gfid:0:2}/${gfid:2:2}"
+TEST ln -s "../../00/00/00000000-0000-0000-0000-000000000001/${ANONINO}" "${B0}/${V0}0/.glusterfs/${gfid:0:2}/${gfid:2:2}/${gfid}"
+TEST ln -s "../../00/00/00000000-0000-0000-0000-000000000001/${ANONINO}" "${B0}/${V0}1/.glusterfs/${gfid:0:2}/${gfid:2:2}/${gfid}"
+TEST ln -s "../../00/00/00000000-0000-0000-0000-000000000001/${ANONINO}" "${B0}/${V0}2/.glusterfs/${gfid:0:2}/${gfid:2:2}/${gfid}"
+
+TEST $CLI volume start ${V0}
+
+TEST $(dirname "${0}")/issue-2232 ${H0} ${V0}
+
+TEST rm -f $(dirname $0)/issue-2232
+
+cleanup
diff --git a/xlators/cluster/afr/src/afr-dir-read.c b/xlators/cluster/afr/src/afr-dir-read.c
index d64b6a9..a98f8df 100644
--- a/xlators/cluster/afr/src/afr-dir-read.c
+++ b/xlators/cluster/afr/src/afr-dir-read.c
@@ -157,7 +157,7 @@ afr_validate_read_subvol(inode_t *inode, xlator_t *this, int par_read_subvol)
return 0;
}
-static void
+static int32_t
afr_readdir_transform_entries(call_frame_t *frame, gf_dirent_t *subvol_entries,
int subvol, gf_dirent_t *entries, fd_t *fd)
{
@@ -168,6 +168,7 @@ afr_readdir_transform_entries(call_frame_t *frame, gf_dirent_t *subvol_entries,
afr_private_t *priv = NULL;
gf_boolean_t need_heal = _gf_false;
gf_boolean_t validate_subvol = _gf_false;
+ int32_t count = 0;
this = THIS;
priv = this->private;
@@ -184,6 +185,7 @@ afr_readdir_transform_entries(call_frame_t *frame, gf_dirent_t *subvol_entries,
list_del_init(&entry->list);
list_add_tail(&entry->list, &entries->list);
+ count++;
if (!validate_subvol)
continue;
@@ -197,6 +199,8 @@ afr_readdir_transform_entries(call_frame_t *frame, gf_dirent_t *subvol_entries,
}
}
}
+
+ return count;
}
int32_t
@@ -222,8 +226,9 @@ afr_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
}
if (op_ret >= 0)
- afr_readdir_transform_entries(frame, subvol_entries, (long)cookie,
- &entries, local->fd);
+ op_ret = afr_readdir_transform_entries(frame, subvol_entries,
+ (long)cookie, &entries,
+ local->fd);
AFR_STACK_UNWIND(readdir, frame, op_ret, op_errno, &entries, xdata);
--
1.8.3.1