summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/bugs/posix/bug-1175711.c37
-rwxr-xr-xtests/bugs/posix/bug-1175711.t30
-rw-r--r--xlators/storage/posix/src/posix.c29
3 files changed, 96 insertions, 0 deletions
diff --git a/tests/bugs/posix/bug-1175711.c b/tests/bugs/posix/bug-1175711.c
new file mode 100644
index 00000000000..fbbea3f636b
--- /dev/null
+++ b/tests/bugs/posix/bug-1175711.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <assert.h>
+
+int
+main(int argc, char **argv)
+{
+ DIR *dir = NULL;
+ struct dirent *entry = NULL;
+ int ret = 0;
+ char *path = NULL;
+
+ assert (argc == 2);
+ path = argv[1];
+
+ dir = opendir(path);
+ if (!dir) {
+ printf("opendir(%s) failed.\n", path);
+ return -1;
+ }
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_type == DT_UNKNOWN) {
+ printf("d_type found to be DT_UNKNOWN\n");
+ ret = -1;
+ break;
+ }
+ }
+#endif
+
+ if (dir)
+ closedir(dir);
+
+ return ret;
+}
diff --git a/tests/bugs/posix/bug-1175711.t b/tests/bugs/posix/bug-1175711.t
new file mode 100755
index 00000000000..f4162544d92
--- /dev/null
+++ b/tests/bugs/posix/bug-1175711.t
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+
+cleanup;
+
+# Create, start and mount the volume.
+TEST glusterd;
+TEST $CLI volume create $V0 $H0:$B0/$V0;
+TEST $CLI volume start $V0;
+TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0
+
+# Compile the test program
+TEST $CC -Wall $(dirname $0)/bug-1175711.c -o $(dirname $0)/bug-1175711
+
+# Create directory and some entries inside them.
+mkdir -p $M0/dir-bug-1175711
+mkdir -p $M0/dir-bug-1175711/DT_DIR
+touch $M0/dir-bug-1175711/DT_REG
+
+# Invoke the test program and pass path of directory to it.
+TEST $(dirname $0)/bug-1175711 $M0/dir-bug-1175711
+
+# Unmount, stop and delete the volume
+EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
+TEST $CLI volume stop $V0;
+TEST $CLI volume delete $V0;
+
+cleanup;
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 474c47c911f..7475839972a 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -5966,6 +5966,24 @@ posix_entry_xattr_fill (xlator_t *this, inode_t *inode,
}
+#ifdef _DIRENT_HAVE_D_TYPE
+static int
+posix_d_type_from_ia_type (ia_type_t type)
+{
+ switch (type) {
+ case IA_IFDIR: return DT_DIR;
+ case IA_IFCHR: return DT_CHR;
+ case IA_IFBLK: return DT_BLK;
+ case IA_IFIFO: return DT_FIFO;
+ case IA_IFLNK: return DT_LNK;
+ case IA_IFREG: return DT_REG;
+ case IA_IFSOCK: return DT_SOCK;
+ default: return DT_UNKNOWN;
+ }
+}
+#endif
+
+
int
posix_readdirp_fill (xlator_t *this, fd_t *fd, gf_dirent_t *entries, dict_t *dict)
{
@@ -6023,6 +6041,17 @@ posix_readdirp_fill (xlator_t *this, fd_t *fd, gf_dirent_t *entries, dict_t *dic
entry->d_stat = stbuf;
if (stbuf.ia_ino)
entry->d_ino = stbuf.ia_ino;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (entry->d_type == DT_UNKNOWN && !IA_ISINVAL(stbuf.ia_type)) {
+ /* The platform supports d_type but the underlying
+ filesystem doesn't. We set d_type to the correct
+ value from ia_type */
+ entry->d_type =
+ posix_d_type_from_ia_type (stbuf.ia_type);
+ }
+#endif
+
inode = NULL;
}