summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
Diffstat (limited to 'api')
-rw-r--r--api/src/glfs-fops.c74
-rw-r--r--api/src/glfs-internal.h1
-rw-r--r--api/src/glfs-mem-types.h1
-rw-r--r--api/src/glfs.c3
-rw-r--r--api/src/glfs.h19
5 files changed, 96 insertions, 2 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
index 7572a94f2ac..10bb7d38b4d 100644
--- a/api/src/glfs-fops.c
+++ b/api/src/glfs-fops.c
@@ -13,7 +13,15 @@
#include "glfs-mem-types.h"
#include "syncop.h"
#include "glfs.h"
+#include <limits.h>
+#ifdef NAME_MAX
+#define GF_NAME_MAX NAME_MAX
+#else
+#define GF_NAME_MAX 255
+#endif
+
+#define READDIRBUF_SIZE (sizeof(struct dirent) + GF_NAME_MAX + 1)
int
glfs_loc_link (loc_t *loc, struct iatt *iatt)
@@ -1918,7 +1926,7 @@ gf_dirent_to_dirent (gf_dirent_t *gf_dirent, struct dirent *dirent)
dirent->d_namlen = strlen (gf_dirent->d_name);
#endif
- strncpy (dirent->d_name, gf_dirent->d_name, 256);
+ strncpy (dirent->d_name, gf_dirent->d_name, GF_NAME_MAX + 1);
}
@@ -2012,16 +2020,56 @@ glfd_entry_next (struct glfs_fd *glfd, int plus)
}
+static struct dirent *
+glfs_readdirbuf_get (struct glfs_fd *glfd)
+{
+ struct dirent *buf = NULL;
+
+ LOCK (&glfd->fd->lock);
+ {
+ buf = glfd->readdirbuf;
+ if (buf) {
+ memset (buf, 0, READDIRBUF_SIZE);
+ goto unlock;
+ }
+
+ buf = GF_CALLOC (1, READDIRBUF_SIZE, glfs_mt_readdirbuf_t);
+ if (!buf) {
+ errno = ENOMEM;
+ goto unlock;
+ }
+
+ glfd->readdirbuf = buf;
+ }
+unlock:
+ UNLOCK (&glfd->fd->lock);
+
+ return buf;
+}
+
+
int
-glfs_readdirplus_r (struct glfs_fd *glfd, struct stat *stat, struct dirent *buf,
+glfs_readdirplus_r (struct glfs_fd *glfd, struct stat *stat, struct dirent *ext,
struct dirent **res)
{
int ret = 0;
gf_dirent_t *entry = NULL;
+ struct dirent *buf = NULL;
__glfs_entry_fd (glfd);
errno = 0;
+
+ if (ext)
+ buf = ext;
+ else
+ buf = glfs_readdirbuf_get (glfd);
+
+ if (!buf) {
+ errno = ENOMEM;
+ return -1;
+ }
+
entry = glfd_entry_next (glfd, !!stat);
if (errno)
ret = -1;
@@ -2050,6 +2098,28 @@ glfs_readdir_r (struct glfs_fd *glfd, struct dirent *buf, struct dirent **res)
}
+struct dirent *
+glfs_readdirplus (struct glfs_fd *glfd, struct stat *stat)
+{
+ struct dirent *res = NULL;
+ int ret = -1;
+
+ ret = glfs_readdirplus_r (glfd, stat, NULL, &res);
+ if (ret)
+ return NULL;
+
+ return res;
+}
+
+
+
+struct dirent *
+glfs_readdir (struct glfs_fd *glfd)
+{
+ return glfs_readdirplus (glfd, NULL);
+}
+
+
int
glfs_statvfs (struct glfs *fs, const char *path, struct statvfs *buf)
{
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h
index 1b1c1c7f624..ec1d5579df7 100644
--- a/api/src/glfs-internal.h
+++ b/api/src/glfs-internal.h
@@ -95,6 +95,7 @@ struct glfs_fd {
fd_t *fd; /* Currently guared by @fs->mutex. TODO: per-glfd lock */
struct list_head entries;
gf_dirent_t *next;
+ struct dirent *readdirbuf;
};
/* glfs object handle introduced for the alternate gfapi implementation based
diff --git a/api/src/glfs-mem-types.h b/api/src/glfs-mem-types.h
index 25b155b9c8a..3301b3da537 100644
--- a/api/src/glfs-mem-types.h
+++ b/api/src/glfs-mem-types.h
@@ -24,6 +24,7 @@ enum glfs_mem_types_ {
glfs_mt_volfile_t,
glfs_mt_xlator_cmdline_option_t,
glfs_mt_glfs_object_t,
+ glfs_mt_readdirbuf_t,
glfs_mt_end
};
diff --git a/api/src/glfs.c b/api/src/glfs.c
index ed731eae958..e94419c2d57 100644
--- a/api/src/glfs.c
+++ b/api/src/glfs.c
@@ -384,6 +384,9 @@ glfs_fd_destroy (struct glfs_fd *glfd)
if (glfd->fd)
fd_unref (glfd->fd);
+
+ GF_FREE (glfd->readdirbuf);
+
GF_FREE (glfd);
}
diff --git a/api/src/glfs.h b/api/src/glfs.h
index d179b87ba42..18fda496ea2 100644
--- a/api/src/glfs.h
+++ b/api/src/glfs.h
@@ -468,12 +468,31 @@ int glfs_link (glfs_t *fs, const char *oldpath, const char *newpath);
glfs_fd_t *glfs_opendir (glfs_t *fs, const char *path);
+/*
+ * @glfs_readdir_r and @glfs_readdirplus_r ARE thread safe AND re-entrant,
+ * but the interface has ambiguity about the size of @dirent to be allocated
+ * before calling the APIs. 512 byte buffer (for @dirent) is sufficient for
+ * all known systems which are tested againt glusterfs/gfapi, but may be
+ * insufficient in the future.
+ */
+
int glfs_readdir_r (glfs_fd_t *fd, struct dirent *dirent,
struct dirent **result);
int glfs_readdirplus_r (glfs_fd_t *fd, struct stat *stat, struct dirent *dirent,
struct dirent **result);
+/*
+ * @glfs_readdir and @glfs_readdirplus are NEITHER thread safe NOR re-entrant
+ * when called on the same directory handle. However they ARE thread safe
+ * AND re-entrant when called on different directory handles (which may be
+ * referring to the same directory too.)
+ */
+
+struct dirent *glfs_readdir (glfs_fd_t *fd);
+
+struct dirent *glfs_readdirplus (glfs_fd_t *fd, struct stat *stat);
+
long glfs_telldir (glfs_fd_t *fd);
void glfs_seekdir (glfs_fd_t *fd, long offset);