diff options
author | shishir gowda <shishirng@gluster.com> | 2011-03-04 02:22:37 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2011-03-04 00:41:15 -0800 |
commit | 5b909c83de45e9457eef773cb24770b47d51a632 (patch) | |
tree | 4de0148ce00c572308b96c43e4f95ae49b88c2fa | |
parent | 0066a093a258bfd1a9130134318c3df3571a091d (diff) |
Solaris xattr support for symlink and special files.v3.1.3qa3
Since glusterfs uses xattr for storing gfid, and xattr support for
symlinks and special files does not exist in solaris. The work around
is provided by creating hidden files under export directory on solaris
hosts only. the hidden files ares maintained in .glusterfs_xattr_inode directory,
and all xattr ops on symlink and special files are redirected to respective
inodes.
All dir entries with name starting as .glusterfs (GF_HIDDEN_PATH) will
not be shown in readdir ops.
Signed-off-by: shishir gowda <shishirng@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 2213 (Symlink fails with ENODATA)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2213
-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; |