diff options
Diffstat (limited to 'xlators/storage/posix/src/posix-helpers.c')
-rw-r--r-- | xlators/storage/posix/src/posix-helpers.c | 323 |
1 files changed, 229 insertions, 94 deletions
diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c index edc64f583da..31a4e667d17 100644 --- a/xlators/storage/posix/src/posix-helpers.c +++ b/xlators/storage/posix/src/posix-helpers.c @@ -264,19 +264,22 @@ out: } int -posix_lstat_with_gfid (xlator_t *this, const char *path, struct iatt *stbuf_p) +posix_fdstat (xlator_t *this, int fd, struct iatt *stbuf_p) { int ret = 0; - struct stat lstatbuf = {0, }; + struct stat fstatbuf = {0, }; struct iatt stbuf = {0, }; - ret = lstat (path, &lstatbuf); + ret = fstat (fd, &fstatbuf); if (ret == -1) goto out; - iatt_from_stat (&stbuf, &lstatbuf); + if (fstatbuf.st_nlink && !S_ISDIR (fstatbuf.st_mode)) + fstatbuf.st_nlink--; - ret = posix_fill_gfid_path (this, path, &stbuf); + iatt_from_stat (&stbuf, &fstatbuf); + + ret = posix_fill_gfid_fd (this, fd, &stbuf); if (ret) gf_log_callingfn (this->name, GF_LOG_DEBUG, "failed to get gfid"); @@ -284,33 +287,105 @@ posix_lstat_with_gfid (xlator_t *this, const char *path, struct iatt *stbuf_p) if (stbuf_p) *stbuf_p = stbuf; + out: return ret; } int -posix_fstat_with_gfid (xlator_t *this, int fd, struct iatt *stbuf_p) +posix_istat (xlator_t *this, uuid_t gfid, const char *basename, + struct iatt *buf_p) { - int ret = 0; - struct stat fstatbuf = {0, }; - struct iatt stbuf = {0, }; + char *real_path = NULL; + struct stat lstatbuf = {0, }; + struct iatt stbuf = {0, }; + int ret = 0; + struct posix_private *priv = NULL; - ret = fstat (fd, &fstatbuf); - if (ret == -1) + + priv = this->private; + + MAKE_HANDLE_PATH (real_path, this, gfid, basename); + + ret = lstat (real_path, &lstatbuf); + + if (ret == -1) { + if (errno != ENOENT && errno != ELOOP) + gf_log (this->name, GF_LOG_WARNING, + "lstat failed on %s (%s)", + real_path, strerror (errno)); goto out; + } - iatt_from_stat (&stbuf, &fstatbuf); + if ((lstatbuf.st_ino == priv->handledir.st_ino) && + (lstatbuf.st_dev == priv->handledir.st_dev)) { + errno = ENOENT; + return -1; + } - ret = posix_fill_gfid_fd (this, fd, &stbuf); - if (ret) - gf_log_callingfn (this->name, GF_LOG_DEBUG, "failed to get gfid"); + if (!S_ISDIR (lstatbuf.st_mode)) + lstatbuf.st_nlink --; + + iatt_from_stat (&stbuf, &lstatbuf); + + if (basename) + posix_fill_gfid_path (this, real_path, &stbuf); + else + uuid_copy (stbuf.ia_gfid, gfid); posix_fill_ino_from_gfid (this, &stbuf); - if (stbuf_p) - *stbuf_p = stbuf; + if (buf_p) + *buf_p = stbuf; +out: + return ret; +} + + +int +posix_pstat (xlator_t *this, uuid_t gfid, const char *path, + struct iatt *buf_p) +{ + struct stat lstatbuf = {0, }; + struct iatt stbuf = {0, }; + int ret = 0; + struct posix_private *priv = NULL; + + + priv = this->private; + + ret = lstat (path, &lstatbuf); + + if (ret == -1) { + if (errno != ENOENT) + gf_log (this->name, GF_LOG_WARNING, + "lstat failed on %s (%s)", + path, strerror (errno)); + goto out; + } + + if ((lstatbuf.st_ino == priv->handledir.st_ino) && + (lstatbuf.st_dev == priv->handledir.st_dev)) { + errno = ENOENT; + return -1; + } + + if (!S_ISDIR (lstatbuf.st_mode)) + lstatbuf.st_nlink --; + + iatt_from_stat (&stbuf, &lstatbuf); + + if (gfid && !uuid_is_null (gfid)) + uuid_copy (stbuf.ia_gfid, gfid); + else + posix_fill_gfid_path (this, path, &stbuf); + + posix_fill_ino_from_gfid (this, &stbuf); + + if (buf_p) + *buf_p = stbuf; out: return ret; } @@ -340,63 +415,15 @@ out: } -/* - * If the parent directory of {real_path} has the setgid bit set, - * then set {gid} to the gid of the parent. Otherwise, - * leave {gid} unchanged. - */ - -int -setgid_override (xlator_t *this, char *real_path, gid_t *gid) -{ - char * tmp_path = NULL; - char * parent_path = NULL; - struct iatt parent_stbuf; - - int op_ret = 0; - - tmp_path = gf_strdup (real_path); - if (!tmp_path) { - op_ret = -ENOMEM; - goto out; - } - - parent_path = dirname (tmp_path); - - op_ret = posix_lstat_with_gfid (this, parent_path, &parent_stbuf); - if (op_ret == -1) { - op_ret = -errno; - gf_log_callingfn (this->name, GF_LOG_ERROR, - "lstat on parent directory (%s) failed: %s", - parent_path, strerror (errno)); - goto out; - } - - if (parent_stbuf.ia_prot.sgid) { - /* - * Entries created inside a setgid directory - * should inherit the gid from the parent - */ - - *gid = parent_stbuf.ia_gid; - } -out: - - if (tmp_path) - GF_FREE (tmp_path); - - return op_ret; -} - - int -posix_gfid_set (xlator_t *this, const char *path, dict_t *xattr_req) +posix_gfid_set (xlator_t *this, const char *path, loc_t *loc, dict_t *xattr_req) { void *uuid_req = NULL; uuid_t uuid_curr; int ret = 0; struct stat stat = {0, }; + if (!xattr_req) goto out; @@ -406,17 +433,31 @@ posix_gfid_set (xlator_t *this, const char *path, dict_t *xattr_req) ret = sys_lgetxattr (path, GFID_XATTR_KEY, uuid_curr, 16); if (ret == 16) { ret = 0; - goto out; + goto verify_handle; } ret = dict_get_ptr (xattr_req, "gfid-req", &uuid_req); if (ret) { - gf_log_callingfn (this->name, GF_LOG_DEBUG, - "failed to get the gfid from dict"); + gf_log (this->name, GF_LOG_DEBUG, + "failed to get the gfid from dict for %s", + loc->path); goto out; } ret = sys_lsetxattr (path, GFID_XATTR_KEY, uuid_req, 16, XATTR_CREATE); + if (ret != 0) { + gf_log (this->name, GF_LOG_WARNING, + "setting GFID on %s failed (%s)", path, + strerror (errno)); + goto out; + } + uuid_copy (uuid_curr, uuid_req); + +verify_handle: + if (!S_ISDIR (stat.st_mode)) + ret = posix_handle_hard (this, path, uuid_curr, &stat); + else + ret = posix_handle_soft (this, path, loc, uuid_curr, &stat); out: return ret; @@ -424,22 +465,26 @@ out: int -posix_set_file_contents (xlator_t *this, const char *real_path, - data_pair_t *trav, int flags) +posix_set_file_contents (xlator_t *this, const char *path, data_pair_t *trav, + int flags) { char * key = NULL; - char real_filepath[ZR_PATH_MAX] = {0,}; + char real_path[PATH_MAX]; int32_t file_fd = -1; int op_ret = 0; int ret = -1; + + /* XXX: does not handle assigning GFID to created files */ + return -1; + key = &(trav->key[15]); - sprintf (real_filepath, "%s/%s", real_path, key); + sprintf (real_path, "%s/%s", path, key); if (flags & XATTR_REPLACE) { /* if file exists, replace it * else, error out */ - file_fd = open (real_filepath, O_TRUNC|O_WRONLY); + file_fd = open (real_path, O_TRUNC|O_WRONLY); if (file_fd == -1) { goto create; @@ -453,7 +498,7 @@ posix_set_file_contents (xlator_t *this, const char *real_path, gf_log (this->name, GF_LOG_ERROR, "write failed while doing setxattr " "for key %s on path %s: %s", - key, real_filepath, strerror (errno)); + key, real_path, strerror (errno)); goto out; } @@ -462,14 +507,14 @@ posix_set_file_contents (xlator_t *this, const char *real_path, op_ret = -errno; gf_log (this->name, GF_LOG_ERROR, "close failed on %s: %s", - real_filepath, strerror (errno)); + real_path, strerror (errno)); goto out; } } create: /* we know file doesn't exist, create it */ - file_fd = open (real_filepath, O_CREAT|O_WRONLY, 0644); + file_fd = open (real_path, O_CREAT|O_WRONLY, 0644); if (file_fd == -1) { op_ret = -errno; @@ -485,7 +530,7 @@ posix_set_file_contents (xlator_t *this, const char *real_path, gf_log (this->name, GF_LOG_ERROR, "write failed on %s while setxattr with " "key %s: %s", - real_filepath, key, strerror (errno)); + real_path, key, strerror (errno)); goto out; } @@ -495,7 +540,7 @@ posix_set_file_contents (xlator_t *this, const char *real_path, gf_log (this->name, GF_LOG_ERROR, "close failed on %s while setxattr with " "key %s: %s", - real_filepath, key, strerror (errno)); + real_path, key, strerror (errno)); goto out; } } @@ -506,33 +551,32 @@ out: int -posix_get_file_contents (xlator_t *this, const char *real_path, +posix_get_file_contents (xlator_t *this, uuid_t pargfid, const char *name, char **contents) { - char real_filepath[ZR_PATH_MAX] = {0,}; - char * key = NULL; + char *real_path = NULL; int32_t file_fd = -1; struct iatt stbuf = {0,}; int op_ret = 0; int ret = -1; - key = (char *) &(name[15]); - sprintf (real_filepath, "%s/%s", real_path, key); - op_ret = posix_lstat_with_gfid (this, real_filepath, &stbuf); + MAKE_HANDLE_PATH (real_path, this, pargfid, name); + + op_ret = posix_istat (this, pargfid, name, &stbuf); if (op_ret == -1) { op_ret = -errno; gf_log (this->name, GF_LOG_ERROR, "lstat failed on %s: %s", - real_filepath, strerror (errno)); + real_path, strerror (errno)); goto out; } - file_fd = open (real_filepath, O_RDONLY); + file_fd = open (real_path, O_RDONLY); if (file_fd == -1) { op_ret = -errno; gf_log (this->name, GF_LOG_ERROR, "open failed on %s: %s", - real_filepath, strerror (errno)); + real_path, strerror (errno)); goto out; } @@ -547,7 +591,7 @@ posix_get_file_contents (xlator_t *this, const char *real_path, if (ret <= 0) { op_ret = -1; gf_log (this->name, GF_LOG_ERROR, "read on %s failed: %s", - real_filepath, strerror (errno)); + real_path, strerror (errno)); goto out; } @@ -558,7 +602,7 @@ posix_get_file_contents (xlator_t *this, const char *real_path, if (op_ret == -1) { op_ret = -errno; gf_log (this->name, GF_LOG_ERROR, "close on %s failed: %s", - real_filepath, strerror (errno)); + real_path, strerror (errno)); goto out; } @@ -775,9 +819,6 @@ posix_janitor_thread_proc (void *data) closedir (pfd->dir); } - if (pfd->path) - GF_FREE (pfd->path); - GF_FREE (pfd); } } @@ -882,3 +923,97 @@ posix_entry_create_xattr_set (xlator_t *this, const char *path, out: return ret; } + + +static int +__posix_fd_ctx_get (fd_t *fd, xlator_t *this, struct posix_fd **pfd_p) +{ + uint64_t tmp_pfd = 0; + struct posix_fd *pfd = NULL; + int ret = -1; + char *real_path = NULL; + int _fd = -1; + DIR *dir = NULL; + + ret = __fd_ctx_get (fd, this, &tmp_pfd); + if (ret == 0) { + pfd = (void *)(long) tmp_pfd; + ret = 0; + goto out; + } + + if (fd->pid != -1) + /* anonymous fd */ + goto out; + + MAKE_HANDLE_PATH (real_path, this, fd->inode->gfid, NULL); + + pfd = GF_CALLOC (1, sizeof (*pfd), gf_posix_mt_posix_fd); + if (!pfd) { + goto out; + } + pfd->fd = -1; + + if (fd->inode->ia_type == IA_IFDIR) { + dir = opendir (real_path); + if (!dir) { + GF_FREE (pfd); + pfd = NULL; + goto out; + } + _fd = dirfd (dir); + } + + if (fd->inode->ia_type == IA_IFREG) { + _fd = open (real_path, O_RDWR|O_LARGEFILE); + if (_fd == -1) { + GF_FREE (pfd); + pfd = NULL; + goto out; + } + } + + pfd->fd = _fd; + pfd->dir = dir; + + ret = __fd_ctx_set (fd, this, (uint64_t) (long) pfd); + if (ret != 0) { + if (_fd != -1) + close (_fd); + if (dir) + closedir (dir); + GF_FREE (pfd); + pfd = NULL; + goto out; + } + + ret = 0; +out: + if (pfd_p) + *pfd_p = pfd; + return ret; +} + + +int +posix_fd_ctx_get (fd_t *fd, xlator_t *this, struct posix_fd **pfd) +{ + int ret; + + LOCK (&fd->inode->lock); + { + ret = __posix_fd_ctx_get (fd, this, pfd); + } + UNLOCK (&fd->inode->lock); + + return ret; +} + + +int +posix_fd_ctx_get_off (fd_t *fd, xlator_t *this, struct posix_fd **pfd, + off_t offset) +{ + return posix_fd_ctx_get (fd, this, pfd); +} + |