summaryrefslogtreecommitdiffstats
path: root/xlators/features/snapview-server/src/snapview-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/features/snapview-server/src/snapview-server.c')
-rw-r--r--xlators/features/snapview-server/src/snapview-server.c282
1 files changed, 204 insertions, 78 deletions
diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c
index 47344113406..99965a4ccef 100644
--- a/xlators/features/snapview-server/src/snapview-server.c
+++ b/xlators/features/snapview-server/src/snapview-server.c
@@ -1627,18 +1627,73 @@ out:
return 0;
}
+/*
+ * This function adds the xattr keys present in the list (@list) to the dict.
+ * But the list contains only the names of the xattrs (and no value, as
+ * the gfapi functions for the listxattr operations would return only the
+ * names of the xattrs in the buffer provided by the caller, though they had
+ * got the values of those xattrs from posix) as described in the man page of
+ * listxattr. But before unwinding snapview-server has to put those names
+ * back into the dict. But to get the values for those xattrs it has to do the
+ * getxattr operation on each xattr which might turn out to be a costly
+ * operation. So for each of the xattrs present in the list, a 0 byte value
+ * ("") is set into the dict before unwinding. This can be treated as an
+ * indicator to other xlators which want to cache the xattrs (as of now,
+ * md-cache which caches acl and selinux related xattrs) to not to cache the
+ * values of the xattrs present in the dict.
+ */
+int32_t
+svs_add_xattrs_to_dict (xlator_t *this, dict_t *dict, char *list, ssize_t size)
+{
+ char keybuffer[4096] = {0,};
+ size_t remaining_size = 0;
+ int32_t list_offset = 0;
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO ("snapview-daemon", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, dict, out);
+ GF_VALIDATE_OR_GOTO (this->name, list, out);
+
+ remaining_size = size;
+ list_offset = 0;
+ while (remaining_size > 0) {
+ strcpy (keybuffer, list + list_offset);
+#ifdef GF_DARWIN_HOST_OS
+ /* The protocol expect namespace for now */
+ char *newkey = NULL;
+ gf_add_prefix (XATTR_USER_PREFIX, keybuffer, &newkey);
+ strcpy (keybuffer, newkey);
+ GF_FREE (newkey);
+#endif
+ ret = dict_set_str (dict, keybuffer, "");
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR, "dict set operation "
+ "for the key %s failed.", keybuffer);
+ goto out;
+ }
+
+ remaining_size -= strlen (keybuffer) + 1;
+ list_offset += strlen (keybuffer) + 1;
+ } /* while (remaining_size > 0) */
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
int32_t
svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
dict_t *xdata)
{
- svs_inode_t *inode_ctx = NULL;
- int32_t op_ret = -1;
- int32_t op_errno = EINVAL;
- glfs_t *fs = NULL;
- glfs_object_t *object = NULL;
- char *value = 0;
- ssize_t size = 0;
- dict_t *dict = NULL;
+ svs_inode_t *inode_ctx = NULL;
+ int32_t op_ret = -1;
+ int32_t op_errno = EINVAL;
+ glfs_t *fs = NULL;
+ glfs_object_t *object = NULL;
+ char *value = 0;
+ ssize_t size = 0;
+ dict_t *dict = NULL;
GF_VALIDATE_OR_GOTO ("snap-view-daemon", this, out);
GF_VALIDATE_OR_GOTO ("snap-view-daemon", frame, out);
@@ -1654,8 +1709,11 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
goto out;
}
- /* Fake success is sent if the getxattr is on entry point directory
- or the inode is SNAP_VIEW_ENTRY_POINT_INODE
+ /* EINVAL is sent if the getxattr is on entry point directory
+ or the inode is SNAP_VIEW_ENTRY_POINT_INODE. Entry point is
+ a virtual directory on which setxattr operations are not
+ allowed. If getxattr has to be faked as success, then a value
+ for the name of the xattr has to be sent which we dont have.
*/
if (inode_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE) {
op_ret = -1;
@@ -1664,19 +1722,30 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
} else if (inode_ctx->type == SNAP_VIEW_VIRTUAL_INODE) {
fs = inode_ctx->fs;
object = inode_ctx->object;
+ dict = dict_new ();
+ if (!dict) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate dict");
+ op_ret = -1;
+ op_errno = ENOMEM;
+ goto out;
+ }
+
size = glfs_h_getxattrs (fs, object, name, NULL, 0);
if (size == -1) {
- gf_log (this->name, GF_LOG_ERROR, "getxattr on %s "
- "failed (key: %s)", loc->name, name);
+ gf_log (this->name, GF_LOG_ERROR, "getxattr "
+ "on %s failed (key: %s)", loc->name,
+ name);
op_ret = -1;
op_errno = errno;
goto out;
}
- value = GF_CALLOC (size + 1, sizeof (char), gf_common_mt_char);
+ value = GF_CALLOC (size + 1, sizeof (char),
+ gf_common_mt_char);
if (!value) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "memory for getxattr on %s (key: %s)",
- loc->name, name);
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate memory for getxattr on %s "
+ "(key: %s)", loc->name, name);
op_ret = -1;
op_errno = ENOMEM;
goto out;
@@ -1684,35 +1753,38 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
size = glfs_h_getxattrs (fs, object, name, value, size);
if (size == -1) {
- gf_log (this->name, GF_LOG_ERROR, "failed to get the "
- "xattr %s for entry %s", name, loc->name);
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "get the xattr %s for entry %s", name,
+ loc->name);
op_ret = -1;
op_errno = errno;
goto out;
}
value[size] = '\0';
- dict = dict_new ();
- if (!dict) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "dict");
- op_ret = -1;
- op_errno = ENOMEM;
- goto out;
- }
-
- op_ret = dict_set_dynptr (dict, (char *)name, value, size);
- if (op_ret < 0) {
- op_errno = -op_ret;
- gf_log (this->name, GF_LOG_ERROR, "dict set operation "
- "for %s for the key %s failed.", loc->path,
- name);
+ if (name) {
+ op_ret = dict_set_dynptr (dict, (char *)name, value,
+ size);
+ if (op_ret < 0) {
+ op_errno = -op_ret;
+ gf_log (this->name, GF_LOG_ERROR, "dict set "
+ "operation for %s for the key %s "
+ "failed.", loc->path, name);
+ GF_FREE (value);
+ value = NULL;
+ goto out;
+ }
+ } else {
+ op_ret = svs_add_xattrs_to_dict (this, dict, value,
+ size);
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "add the xattrs from the list to dict");
+ op_errno = ENOMEM;
+ goto out;
+ }
GF_FREE (value);
- goto out;
}
-
- op_ret = 0;
- op_errno = 0;
}
out:
@@ -1721,6 +1793,9 @@ out:
STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, NULL);
+ if (dict)
+ dict_unref (dict);
+
return 0;
}
@@ -1761,8 +1836,11 @@ svs_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name,
}
glfd = sfd->fd;
- /* Fake success is sent if the getxattr is on entry point directory
- or the inode is SNAP_VIEW_ENTRY_POINT_INODE
+ /* EINVAL is sent if the getxattr is on entry point directory
+ or the inode is SNAP_VIEW_ENTRY_POINT_INODE. Entry point is
+ a virtual directory on which setxattr operations are not
+ allowed. If getxattr has to be faked as success, then a value
+ for the name of the xattr has to be sent which we dont have.
*/
if (inode_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE) {
op_ret = -1;
@@ -1771,53 +1849,98 @@ svs_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name,
}
if (inode_ctx->type == SNAP_VIEW_VIRTUAL_INODE) {
- size = glfs_fgetxattr (glfd, name, NULL, 0);
- if (size == -1) {
- gf_log (this->name, GF_LOG_ERROR, "getxattr on %s "
- "failed (key: %s)", uuid_utoa (fd->inode->gfid),
- name);
- op_ret = -1;
- op_errno = errno;
- goto out;
- }
- value = GF_CALLOC (size + 1, sizeof (char), gf_common_mt_char);
- if (!value) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "memory for getxattr on %s (key: %s)",
- uuid_utoa (fd->inode->gfid), name);
- op_ret = -1;
- op_errno = ENOMEM;
- goto out;
- }
-
- size = glfs_fgetxattr (glfd, name, value, size);
- if (size == -1) {
- gf_log (this->name, GF_LOG_ERROR, "failed to get the "
- "xattr %s for inode %s", name,
- uuid_utoa (fd->inode->gfid));
- op_ret = -1;
- op_errno = errno;
- goto out;
- }
- value[size] = '\0';
-
dict = dict_new ();
if (!dict) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "dict");
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate dict");
op_ret = -1;
op_errno = ENOMEM;
goto out;
}
- op_ret = dict_set_dynptr (dict, (char *)name, value, size);
- if (op_ret < 0) {
- op_errno = -op_ret;
- gf_log (this->name, GF_LOG_ERROR, "dict set operation "
- "for gfid %s for the key %s failed.",
- uuid_utoa (fd->inode->gfid), name);
+ if (name) {
+ size = glfs_fgetxattr (glfd, name, NULL, 0);
+ if (size == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "getxattr on "
+ "%s failed (key: %s)",
+ uuid_utoa (fd->inode->gfid), name);
+ op_ret = -1;
+ op_errno = errno;
+ goto out;
+ }
+ value = GF_CALLOC (size + 1, sizeof (char),
+ gf_common_mt_char);
+ if (!value) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate memory for getxattr on %s "
+ "(key: %s)",
+ uuid_utoa (fd->inode->gfid), name);
+ op_ret = -1;
+ op_errno = ENOMEM;
+ goto out;
+ }
+
+ size = glfs_fgetxattr (glfd, name, value, size);
+ if (size == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "get the xattr %s for inode %s", name,
+ uuid_utoa (fd->inode->gfid));
+ op_ret = -1;
+ op_errno = errno;
+ goto out;
+ }
+ value[size] = '\0';
+
+ op_ret = dict_set_dynptr (dict, (char *)name, value,
+ size);
+ if (op_ret < 0) {
+ op_errno = -op_ret;
+ gf_log (this->name, GF_LOG_ERROR, "dict set "
+ "operation for gfid %s for the key %s "
+ "failed.",
+ uuid_utoa (fd->inode->gfid), name);
+ GF_FREE (value);
+ goto out;
+ }
+ } else {
+ size = glfs_flistxattr (glfd, NULL, 0);
+ if (size == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "listxattr "
+ "on %s failed",
+ uuid_utoa (fd->inode->gfid));
+ goto out;
+ }
+
+ value = GF_CALLOC (size + 1, sizeof (char),
+ gf_common_mt_char);
+ if (!value) {
+ op_ret = -1;
+ op_errno = ENOMEM;
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate buffer for xattr list (%s)",
+ uuid_utoa (fd->inode->gfid));
+ goto out;
+ }
+
+ size = glfs_flistxattr (glfd, value, size);
+ if (size == -1) {
+ op_ret = -1;
+ op_errno = errno;
+ gf_log (this->name, GF_LOG_ERROR, "listxattr "
+ "on %s failed",
+ uuid_utoa (fd->inode->gfid));
+ goto out;
+ }
+
+ op_ret = svs_add_xattrs_to_dict (this, dict, value,
+ size);
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "add the xattrs from the list to dict");
+ op_errno = ENOMEM;
+ goto out;
+ }
GF_FREE (value);
- goto out;
}
op_ret = 0;
@@ -1830,6 +1953,9 @@ out:
STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict, NULL);
+ if (dict)
+ dict_unref (dict);
+
return 0;
}