diff options
| -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 59b2535105b..a0027055fad 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -5662,6 +5662,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);  | 
