summaryrefslogtreecommitdiffstats
path: root/libglusterfs
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/src/common-utils.h2
-rw-r--r--libglusterfs/src/compat.c244
-rw-r--r--libglusterfs/src/compat.h8
-rw-r--r--libglusterfs/src/glusterfs.h1
-rw-r--r--libglusterfs/src/inode.c2
-rw-r--r--libglusterfs/src/inode.h2
-rw-r--r--libglusterfs/src/syscall.c6
7 files changed, 247 insertions, 18 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);
}