diff options
-rw-r--r-- | libglusterfs/src/common-utils.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/compat.c | 244 | ||||
-rw-r--r-- | libglusterfs/src/compat.h | 8 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
-rw-r--r-- | libglusterfs/src/inode.c | 2 | ||||
-rw-r--r-- | libglusterfs/src/inode.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/syscall.c | 6 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.c | 16 |
8 files changed, 260 insertions, 21 deletions
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 0cb53d1bfe5..0d93e5bee91 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -144,6 +144,8 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE]; } while (0); #endif +#define GF_HIDDEN_PATH ".glusterfs" + static inline void iov_free (struct iovec *vector, int count) { diff --git a/libglusterfs/src/compat.c b/libglusterfs/src/compat.c index 2102216317d..914fb200683 100644 --- a/libglusterfs/src/compat.c +++ b/libglusterfs/src/compat.c @@ -35,9 +35,10 @@ #include "compat.h" #include "common-utils.h" +#include "iatt.h" +#include "inode.h" #ifdef GF_SOLARIS_HOST_OS - int solaris_fsetxattr(int fd, const char* key, @@ -97,6 +98,125 @@ solaris_fgetxattr(int fd, return ret; } +/* Solaris does not support xattr for symlinks and dev files. Since gfid and + other trusted attributes are stored as xattrs, we need to provide support for + them. A mapped regular file is stored in the /.glusterfs_xattr_inode of the export dir. + All xattr ops related to the special files are redirected to this map file. +*/ + +int +make_export_path (const char *real_path, char **path) +{ + int ret = -1; + char *tmp = NULL; + char *export_path = NULL; + char *dup = NULL; + char *ptr = NULL; + char *freeptr = NULL; + uuid_t gfid = {0, }; + + export_path = GF_CALLOC (1, sizeof (char) * PATH_MAX, 0); + if (!export_path) + goto out; + + dup = gf_strdup (real_path); + if (!dup) + goto out; + + freeptr = dup; + ret = solaris_getxattr ("/", GFID_XATTR_KEY, gfid, 16); + /* Return value of getxattr */ + if (ret == 16) { + if (!__is_root_gfid (gfid)){ + strcat (export_path, "/"); + ret = 0; + goto done; + } + } + + do { + ptr = strtok_r (dup, "/", &tmp); + if (!ptr) + break; + strcat (export_path, dup); + ret = solaris_getxattr (export_path, GFID_XATTR_KEY, gfid, 16); + if (ret == 16) { + if (!__is_root_gfid (gfid)) { + ret = 0; + goto done; + } + } + strcat (export_path, "/"); + dup = tmp; + } while (ptr); + + goto out; + +done: + if (!ret) { + *path = export_path; + } +out: + if (freeptr) + GF_FREE (freeptr); + if (ret && export_path) + GF_FREE (export_path); + + return ret; +} +int +solaris_xattr_resolve_path (const char *real_path, char **path) +{ + int ret = -1; + char *export_path = NULL; + char xattr_path[PATH_MAX] = {0, }; + struct stat lstatbuf = {0, }; + struct iatt stbuf = {0, }; + struct stat statbuf = {0, }; + + ret = lstat (real_path, &lstatbuf); + if (ret != 0 ) + return ret; + iatt_from_stat (&stbuf, &lstatbuf); + if (IA_ISREG(stbuf.ia_type) || IA_ISDIR(stbuf.ia_type)) + return -1; + + ret = make_export_path (real_path, &export_path); + if (!ret && export_path) { + strcat (export_path, "/"GF_SOLARIS_XATTR_DIR); + if (lstat (export_path, &statbuf)) { + ret = mkdir (export_path, 0777); + if (ret && (errno != EEXIST)) { + gf_log ("", GF_LOG_DEBUG, "mkdir failed," + " errno: %d", errno); + goto out; + } + } + + snprintf(xattr_path, PATH_MAX, "%s%s%lu", export_path, + "/", stbuf.ia_ino); + + ret = lstat (xattr_path, &statbuf); + + if (ret) { + ret = mknod (xattr_path, S_IFREG|O_WRONLY, 0); + if (ret && (errno != EEXIST)) { + gf_log ("", GF_LOG_WARNING,"Failed to create " + "mapped file %s, error %d", xattr_path, + errno); + goto out; + } + } + *path = gf_strdup (xattr_path); + } +out: + if (export_path) + GF_FREE (export_path); + if (*path) + return 0; + else + return -1; +} int solaris_setxattr(const char *path, @@ -107,21 +227,30 @@ solaris_setxattr(const char *path, { int attrfd = -1; int ret = 0; - - attrfd = attropen (path, key, flags|O_CREAT|O_WRONLY, 0777); + char *mapped_path = NULL; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrfd = attropen (mapped_path, key, flags|O_CREAT|O_WRONLY, + 0777); + } else { + attrfd = attropen (path, key, flags|O_CREAT|O_WRONLY, 0777); + } if (attrfd >= 0) { ftruncate (attrfd, 0); ret = write (attrfd, value, size); close (attrfd); + ret = 0; } else { if (errno != ENOENT) gf_log ("libglusterfs", GF_LOG_ERROR, "Couldn't set extended attribute for %s (%d)", path, errno); - return -1; + ret = -1; } - - return 0; + if (mapped_path) + GF_FREE (mapped_path); + return ret; } @@ -135,8 +264,15 @@ solaris_listxattr(const char *path, DIR *dirptr = NULL; struct dirent *dent = NULL; int newfd = -1; - - attrdirfd = attropen (path, ".", O_RDONLY, 0); + char *mapped_path = NULL; + int ret = -1; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrdirfd = attropen (mapped_path, ".", O_RDONLY, 0); + } else { + attrdirfd = attropen (path, ".", O_RDONLY, 0); + } if (attrdirfd >= 0) { newfd = dup(attrdirfd); dirptr = fdopendir(newfd); @@ -167,14 +303,19 @@ solaris_listxattr(const char *path, if (closedir(dirptr) == -1) { close (attrdirfd); - return -1; + len = -1; + goto out; } } else { close (attrdirfd); - return -1; + len = -1; + goto out; } close (attrdirfd); } +out: + if (mapped_path) + GF_FREE (mapped_path); return len; } @@ -238,17 +379,28 @@ solaris_removexattr(const char *path, const char* key) { int ret = -1; - int attrfd = attropen (path, ".", O_RDONLY, 0); + int attrfd = -1; + char *mapped_path = NULL; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrfd = attropen (mapped_path, ".", O_RDONLY, 0); + } else { + attrfd = attropen (path, ".", O_RDONLY, 0); + } if (attrfd >= 0) { ret = unlinkat (attrfd, key, 0); close (attrfd); } else { if (errno == ENOENT) errno = ENODATA; - return -1; + ret = -1; } - - return ret; + + if (mapped_path) + GF_FREE (mapped_path); + + return ret; } int @@ -259,8 +411,15 @@ solaris_getxattr(const char *path, { int attrfd = -1; int ret = 0; - - attrfd = attropen (path, key, O_RDONLY, 0); + char *mapped_path = NULL; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrfd = attropen (mapped_path, key, O_RDONLY, 0); + } else { + attrfd = attropen (path, key, O_RDONLY, 0); + } + if (attrfd >= 0) { if (size == 0) { struct stat buf; @@ -277,8 +436,10 @@ solaris_getxattr(const char *path, gf_log ("libglusterfs", GF_LOG_DEBUG, "Couldn't read extended attribute for the file %s (%d)", path, errno); - return -1; + ret = -1; } + if (mapped_path) + GF_FREE (mapped_path); return ret; } @@ -326,6 +487,55 @@ asprintf (char **buf, const char *fmt, ...) return status; } +int solaris_unlink (const char *path) +{ + char *mapped_path = NULL; + struct stat stbuf = {0, }; + int ret = -1; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + + + if (!ret && mapped_path) { + if (lstat(path, &stbuf)) { + gf_log ("",GF_LOG_WARNING, "Stat failed on mapped" + " file %s with error %d", mapped_path, errno); + goto out; + } + if (stbuf.st_nlink == 1) { + if(remove (mapped_path)) + gf_log ("", GF_LOG_WARNING, "Failed to remove mapped " + "file %s. Errno %d", mapped_path, errno); + } + + } + +out: + if (mapped_path) + GF_FREE (mapped_path); + + return unlink (path); +} + +int +solaris_rename (const char *old_path, const char *new_path) +{ + char *mapped_path = NULL; + int ret = -1; + + ret = solaris_xattr_resolve_path (new_path, &mapped_path); + + + if (!ret && mapped_path) { + if (!remove (mapped_path)) + gf_log ("", GF_LOG_WARNING, "Failed to remove mapped " + "file %s. Errno %d", mapped_path, errno); + GF_FREE (mapped_path); + } + + return rename(old_path, new_path); + +} #endif /* GF_SOLARIS_HOST_OS */ #ifndef HAVE_STRNLEN diff --git a/libglusterfs/src/compat.h b/libglusterfs/src/compat.h index 690b4f9e689..cae3342efc6 100644 --- a/libglusterfs/src/compat.h +++ b/libglusterfs/src/compat.h @@ -280,6 +280,14 @@ int solaris_fsetxattr(int fd, const char* key, const char *value, size_t size, int flags); int solaris_flistxattr(int fd, char *list, size_t size); +int solaris_rename (const char *oldpath, const char *newpath); + +int solaris_unlink (const char *pathname); + +#define GF_SOLARIS_XATTR_DIR ".glusterfs_xattr_inode" + +int solaris_xattr_resolve_path (const char *real_path, char **path); + #endif /* GF_SOLARIS_HOST_OS */ #ifndef HAVE_ARGP diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index aaf00c31158..6e23c283a4a 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -70,6 +70,7 @@ #define GF_XATTR_PATHINFO_KEY "trusted.glusterfs.pathinfo" #define GF_XATTR_LINKINFO_KEY "trusted.distribute.linkinfo" +#define GFID_XATTR_KEY "trusted.gfid" #define ZR_FILE_CONTENT_STR "glusterfs.file." #define ZR_FILE_CONTENT_STRLEN 15 diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 919f82143ae..e193d782400 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -636,7 +636,7 @@ inode_get (inode_table_t *table, ino_t ino, uint64_t gen) } -static int +int __is_root_gfid (uuid_t gfid) { uuid_t root; diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index 15a4f98f7bd..375ff3ee4e5 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -182,4 +182,6 @@ int inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, uint64_t *value2); +int +__is_root_gfid (uuid_t gfid); #endif /* _INODE_H */ diff --git a/libglusterfs/src/syscall.c b/libglusterfs/src/syscall.c index c0855f1d157..6750b313da7 100644 --- a/libglusterfs/src/syscall.c +++ b/libglusterfs/src/syscall.c @@ -95,6 +95,9 @@ sys_mkdir (const char *pathname, mode_t mode) int sys_unlink (const char *pathname) { +#ifdef GF_SOLARIS_HOST_OS + return solaris_unlink (pathname); +#endif return unlink (pathname); } @@ -116,6 +119,9 @@ sys_symlink (const char *oldpath, const char *newpath) int sys_rename (const char *oldpath, const char *newpath) { +#ifdef GF_SOLARIS_HOST_OS + return solaris_rename (oldpath, newpath); +#endif return rename (oldpath, newpath); } diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 457a3511880..e3130f4f1e0 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -56,7 +56,6 @@ #include "glusterfs3-xdr.h" #include "hashfn.h" -#define GFID_XATTR_KEY "trusted.gfid" #undef HAVE_SET_FSID #ifdef HAVE_SET_FSID @@ -1471,7 +1470,7 @@ posix_unlink (call_frame_t *frame, xlator_t *this, } } - op_ret = unlink (real_path); + op_ret = sys_unlink (real_path); if (op_ret == -1) { op_errno = errno; gf_log (this->name, GF_LOG_ERROR, @@ -1778,7 +1777,7 @@ posix_rename (call_frame_t *frame, xlator_t *this, was_present = 0; } - op_ret = rename (real_oldpath, real_newpath); + op_ret = sys_rename (real_oldpath, real_newpath); if (op_ret == -1) { op_errno = errno; gf_log (this->name, @@ -3969,6 +3968,8 @@ posix_do_readdir (call_frame_t *frame, xlator_t *this, struct iatt stbuf = {0, }; char base_path[PATH_MAX] = {0,}; gf_dirent_t *tmp_entry = NULL; + struct stat statbuf = {0, }; + char hidden_path[PATH_MAX] = {0, }; VALIDATE_OR_GOTO (frame, out); VALIDATE_OR_GOTO (this, out); @@ -4058,6 +4059,15 @@ posix_do_readdir (call_frame_t *frame, xlator_t *this, && (!strcmp(entry->d_name, GF_REPLICATE_TRASH_DIR))) continue; + if ((!strcmp (real_path, base_path)) + && (!strncmp (GF_HIDDEN_PATH, entry->d_name, + strlen(GF_HIDDEN_PATH)))) { + snprintf (hidden_path, PATH_MAX, "%s/%s", real_path, + entry->d_name); + ret = lstat (hidden_path, &statbuf); + if (!ret && S_ISDIR (statbuf.st_mode)) + continue; + } this_size = max (sizeof (gf_dirent_t), sizeof (gfs3_dirplist)) + strlen (entry->d_name) + 1; |