diff options
Diffstat (limited to 'xlators/storage')
-rw-r--r-- | xlators/storage/posix/src/posix-handle.h | 22 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.c | 34 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.h | 3 |
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); |