diff options
| author | Prashanth Pai <ppai@redhat.com> | 2016-04-27 13:37:07 +0530 | 
|---|---|---|
| committer | Niels de Vos <ndevos@redhat.com> | 2016-05-03 07:53:46 -0700 | 
| commit | fff596880afe0e06b433fd3afbe1a2335bf88709 (patch) | |
| tree | b781b643707ef5ee60e85f8eae74ef274832b653 | |
| parent | f995110fb794d6e7e3af8cf6e247ef4d4318098d (diff) | |
posix: Set correct d_type for readdirp() calls
dirent.d_type can contain the type of the directory entry. The 'd_type'
struct member in dirent is present in Linux and many BSD flavours.
However, filling d_type with correct value requires support from the
underlying filesystem. If not, d_type is set to DT_UNKNOWN. XFS added
support for d_type as part of their newer version 5 on-disk format.
However, this requires Linux >= 3.15, xfsprogs >= 3.2.0 and the bricks
to be formatted using the new format.
This patch enables posix xlator to set d_type to the right value even
when the underlying filesystem does not support it. d_type can be set
using information previously fetched by stat() on the dir entry.
This will aid FUSE applications to leverage d_type to avoid the expense
of calling lstat() if further actions depend on the type of the file.
Refer `man 3 readdir` and `man 2 getdents`
> Change-Id: Ic5a262fe4c64122726b4fae2d1bea375c559ca04
> Signed-off-by: Prashanth Pai <ppai@redhat.com>
> Reviewed-on: http://review.gluster.org/14095
> Smoke: Gluster Build System <jenkins@build.gluster.com>
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
> CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
> Reviewed-by: Jeff Darcy <jdarcy@redhat.com>
(cherry picked from commit 77def44d497d090ef3f393b6d9403c1a29dcf993)
Change-Id: Iaaf2a7c85ce8deb9043772e04a76b904d8bf076e
BUG: 1332396
Signed-off-by: Prashanth Pai <ppai@redhat.com>
Reviewed-on: http://review.gluster.org/14175
Smoke: Gluster Build System <jenkins@build.gluster.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Reviewed-by: Niels de Vos <ndevos@redhat.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
| -rw-r--r-- | tests/bugs/posix/bug-1175711.c | 37 | ||||
| -rwxr-xr-x | tests/bugs/posix/bug-1175711.t | 30 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 29 | 
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 b823257d540..6cd7df54909 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -6059,6 +6059,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)  { @@ -6116,6 +6134,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;          }  | 
