diff options
Diffstat (limited to 'xlators/features/snapview-server/src')
-rw-r--r-- | xlators/features/snapview-server/src/snapview-server.c | 282 |
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; } |