summaryrefslogtreecommitdiffstats
path: root/xlators/storage
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/storage')
-rw-r--r--xlators/storage/posix/src/posix-handle.h22
-rw-r--r--xlators/storage/posix/src/posix.c34
-rw-r--r--xlators/storage/posix/src/posix.h3
3 files changed, 55 insertions, 4 deletions
diff --git a/xlators/storage/posix/src/posix-handle.h b/xlators/storage/posix/src/posix-handle.h
index a34b936229b..0ce9575251f 100644
--- a/xlators/storage/posix/src/posix-handle.h
+++ b/xlators/storage/posix/src/posix-handle.h
@@ -15,10 +15,16 @@
#include "config.h"
#endif
+#include <limits.h>
#include <sys/types.h>
#include "xlator.h"
#include "gf-dirent.h"
+/* From Open Group Base Specifications Issue 6 */
+#ifndef _XOPEN_PATH_MAX
+#define _XOPEN_PATH_MAX 1024
+#endif
+
#define TRASH_DIR "landfill"
#define UUID0_STR "00000000-0000-0000-0000-000000000000"
@@ -120,10 +126,18 @@
} while (0)
#define MAKE_REAL_PATH(var, this, path) do { \
- var = alloca (strlen (path) + POSIX_BASE_PATH_LEN(this) + 2); \
- strcpy (var, POSIX_BASE_PATH(this)); \
- strcpy (&var[POSIX_BASE_PATH_LEN(this)], path); \
- } while (0)
+ size_t path_len = strlen(path); \
+ size_t var_len = path_len + POSIX_BASE_PATH_LEN(this) + 1; \
+ if (POSIX_PATH_MAX(this) != -1 && \
+ var_len >= POSIX_PATH_MAX(this)) { \
+ var = alloca (path_len + 1); \
+ strcpy (var, (path[0] == '/') ? path + 1 : path); \
+ } else { \
+ var = alloca (var_len); \
+ strcpy (var, POSIX_BASE_PATH(this)); \
+ strcpy (&var[POSIX_BASE_PATH_LEN(this)], path); \
+ } \
+ } while (0)
#define MAKE_HANDLE_PATH(var, this, gfid, base) do { \
int __len; \
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 4abea837765..6b12d39df79 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -5663,6 +5663,40 @@ init (xlator_t *this)
_private->base_path = gf_strdup (dir_data->data);
_private->base_path_length = strlen (_private->base_path);
+ /*
+ * _XOPEN_PATH_MAX is the longest file path len we MUST
+ * support according to POSIX standard. When prepended
+ * by the brick base path it may exceed backed filesystem
+ * capacity (which MAY be bigger than _XOPEN_PATH_MAX). If
+ * this is the case, chdir() to the brick base path and
+ * use relative paths when they are too long. See also
+ * MAKE_REAL_PATH in posix-handle.h
+ */
+ _private->path_max = pathconf(_private->base_path, _PC_PATH_MAX);
+ if (_private->path_max != -1 &&
+ _XOPEN_PATH_MAX + _private->base_path_length > _private->path_max) {
+ ret = chdir(_private->base_path);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "chdir() to \"%s\" failed",
+ _private->base_path);
+ goto out;
+ }
+#ifdef __NetBSD__
+ /*
+ * At least on NetBSD, the chdir() above uncovers a
+ * race condition which cause file lookup to fail
+ * with ENODATA for a few seconds. The volume quickly
+ * reaches a sane state, but regression tests are fast
+ * enough to choke on it. The reason is obscure (as
+ * often with race conditions), but sleeping here for
+ * a second seems to workaround the problem.
+ */
+ sleep(1);
+#endif
+ }
+
+
LOCK_INIT (&_private->lock);
ret = dict_get_str (this->options, "hostname", &_private->hostname);
diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h
index efd52f00b18..5bb5e873c82 100644
--- a/xlators/storage/posix/src/posix.h
+++ b/xlators/storage/posix/src/posix.h
@@ -76,6 +76,7 @@ struct posix_fd {
struct posix_private {
char *base_path;
int32_t base_path_length;
+ int32_t path_max;
gf_lock_t lock;
@@ -189,6 +190,8 @@ typedef struct {
#define POSIX_BASE_PATH_LEN(this) (((struct posix_private *)this->private)->base_path_length)
+#define POSIX_PATH_MAX(this) (((struct posix_private *)this->private)->path_max)
+
/* Helper functions */
int posix_gfid_set (xlator_t *this, const char *path, loc_t *loc,
dict_t *xattr_req);