summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
Diffstat (limited to 'xlators')
-rw-r--r--xlators/storage/posix/src/posix-messages.h8
-rw-r--r--xlators/storage/posix/src/posix.c103
-rw-r--r--xlators/storage/posix/src/posix.h2
-rw-r--r--xlators/system/posix-acl/src/posix-acl.c121
4 files changed, 227 insertions, 7 deletions
diff --git a/xlators/storage/posix/src/posix-messages.h b/xlators/storage/posix/src/posix-messages.h
index 9916aed92cd..9f267dfe0d9 100644
--- a/xlators/storage/posix/src/posix-messages.h
+++ b/xlators/storage/posix/src/posix-messages.h
@@ -893,6 +893,14 @@
*
*/
+#define P_MSG_BUFFER_OVERFLOW (POSIX_COMP_BASE + 105)
+/*!
+ * @messageid
+ * @diagnosis
+ * @recommendedaction
+ *
+ */
+
/*------------*/
#define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 5e9dbf7ee5c..36d2c857835 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -3266,8 +3266,10 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
int32_t op_ret = -1;
int32_t op_errno = 0;
char * real_path = NULL;
+ char *acl_xattr = NULL;
struct iatt stbuf = {0};
int32_t ret = 0;
+ size_t acl_size = 0;
dict_t *xattr = NULL;
posix_xattr_filler_t filler = {0,};
@@ -3306,6 +3308,10 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
goto out;
}
+ xattr = dict_new();
+ if (!xattr)
+ goto out;
+
/*
* FIXFIX: Send the stbuf info in the xdata for now
* This is used by DHT to redirect FOPs if the file is being migrated
@@ -3316,10 +3322,98 @@ posix_setxattr (call_frame_t *frame, xlator_t *this,
if (ret)
goto out;
- xattr = dict_new();
- if (!xattr)
+ ret = posix_set_iatt_in_dict (xattr, &stbuf);
+ }
+
+/*
+ * ACL can be set on a file/folder using GF_POSIX_ACL_*_KEY xattrs which
+ * won't aware of access-control xlator. To update its context correctly,
+ * POSIX_ACL_*_XATTR stored in xdata which is send in the call_back path.
+ */
+ if (dict_get (dict, GF_POSIX_ACL_ACCESS)) {
+
+ /*
+ * The size of buffer will be know after calling sys_lgetxattr,
+ * so first we allocate buffer with large size(~4k), then we
+ * reduced into required size using GF_REALLO().
+ */
+ acl_xattr = GF_CALLOC (1, ACL_BUFFER_MAX, gf_posix_mt_char);
+ if (!acl_xattr) {
+ ret = -1;
goto out;
- ret = posix_set_iatt_in_dict (xattr, &stbuf);
+ }
+
+ acl_size = sys_lgetxattr (real_path, POSIX_ACL_ACCESS_XATTR,
+ acl_xattr, ACL_BUFFER_MAX);
+
+ if (acl_size < 0) {
+ gf_msg (this->name, GF_LOG_WARNING, errno,
+ P_MSG_XATTR_FAILED, "Posix acl is not set "
+ "properly at the backend");
+ ret = -1;
+ goto out;
+ }
+
+ /* If acl_size is more than max buffer size, just ignore it */
+ if (acl_size >= ACL_BUFFER_MAX) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ P_MSG_BUFFER_OVERFLOW, "size of acl is more"
+ "than the buffer");
+ ret = -1;
+ goto out;
+ }
+
+ acl_xattr = GF_REALLOC (acl_xattr, acl_size);
+ ret = dict_set_bin (xattr, POSIX_ACL_ACCESS_XATTR,
+ acl_xattr, acl_size);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ P_MSG_SET_XDATA_FAIL, "failed to set"
+ "xdata for acl");
+ ret = -1;
+ goto out;
+ }
+ }
+
+ GF_FREE (acl_xattr);
+ acl_xattr = NULL;
+
+ if (dict_get (dict, GF_POSIX_ACL_DEFAULT)) {
+
+ acl_xattr = GF_CALLOC (1, ACL_BUFFER_MAX, gf_posix_mt_char);
+ if (!acl_xattr) {
+ ret = -1;
+ goto out;
+ }
+ acl_size = sys_lgetxattr (real_path, POSIX_ACL_DEFAULT_XATTR,
+ acl_xattr, ACL_BUFFER_MAX);
+
+ if (acl_size < 0) {
+ gf_msg (this->name, GF_LOG_WARNING, errno,
+ P_MSG_XATTR_FAILED, "Posix acl is not set "
+ "properly at the backend");
+ ret = -1;
+ goto out;
+ }
+
+ if (acl_size >= ACL_BUFFER_MAX) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ P_MSG_BUFFER_OVERFLOW, "size of acl is more"
+ "than the buffer");
+ ret = -1;
+ goto out;
+ }
+
+ acl_xattr = GF_REALLOC (acl_xattr, acl_size);
+ ret = dict_set_bin (xattr, POSIX_ACL_DEFAULT_XATTR,
+ acl_xattr, acl_size);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ P_MSG_SET_XDATA_FAIL, "failed to set"
+ "xdata for acl");
+ ret = -1;
+ goto out;
+ }
}
out:
SET_TO_OLD_FS_ID ();
@@ -3329,6 +3423,9 @@ out:
if (xattr)
dict_unref(xattr);
+ if (acl_xattr)
+ GF_FREE (acl_xattr);
+
return 0;
}
diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h
index b85338e930e..cc7ed0402fe 100644
--- a/xlators/storage/posix/src/posix.h
+++ b/xlators/storage/posix/src/posix.h
@@ -48,6 +48,8 @@
#define VECTOR_SIZE 64 * 1024 /* vector size 64KB*/
#define MAX_NO_VECT 1024
+#define ACL_BUFFER_MAX 4096 /* size of character buffer */
+
#define LINKTO "trusted.glusterfs.dht.linkto"
#define POSIX_GFID_HANDLE_SIZE(base_path_len) (base_path_len + SLEN("/") \
diff --git a/xlators/system/posix-acl/src/posix-acl.c b/xlators/system/posix-acl/src/posix-acl.c
index 05608696ea6..da2ccbd1c54 100644
--- a/xlators/system/posix-acl/src/posix-acl.c
+++ b/xlators/system/posix-acl/src/posix-acl.c
@@ -306,6 +306,26 @@ posix_acl_ctx_get (inode_t *inode, xlator_t *this)
return ctx;
}
+int
+__posix_acl_set_specific (inode_t *inode, xlator_t *this,
+ gf_boolean_t is_access, struct posix_acl *acl)
+{
+ int ret = 0;
+ struct posix_acl_ctx *ctx = NULL;
+
+ ctx = posix_acl_ctx_get (inode, this);
+ if (!ctx) {
+ ret = -1;
+ goto out;
+ }
+
+ if (is_access)
+ ctx->acl_access = acl;
+ else
+ ctx->acl_default = acl;
+out:
+ return ret;
+}
int
__posix_acl_set (inode_t *inode, xlator_t *this, struct posix_acl *acl_access,
@@ -426,6 +446,36 @@ posix_acl_unref (xlator_t *this, struct posix_acl *acl)
posix_acl_destroy (this, acl);
}
+int
+posix_acl_set_specific (inode_t *inode, xlator_t *this, struct posix_acl *acl,
+ gf_boolean_t is_access)
+{
+ int ret = 0;
+ int oldret = 0;
+ struct posix_acl *old_acl = NULL;
+ struct posix_acl_conf *conf = NULL;
+
+ conf = this->private;
+
+ LOCK (&conf->acl_lock);
+ {
+ if (is_access)
+ oldret = __posix_acl_get (inode, this, &old_acl, NULL);
+ else
+ oldret = __posix_acl_get (inode, this, NULL, &old_acl);
+ if (acl)
+ acl->refcnt++;
+ ret = __posix_acl_set_specific (inode, this, is_access, acl);
+ }
+ UNLOCK (&conf->acl_lock);
+
+ if (oldret == 0) {
+ if (old_acl)
+ posix_acl_unref (this, old_acl);
+ }
+
+ return ret;
+}
int
posix_acl_set (inode_t *inode, xlator_t *this, struct posix_acl *acl_access,
@@ -497,7 +547,6 @@ unlock:
return ret;
}
-
mode_t
posix_acl_inherit_mode (struct posix_acl *acl, mode_t modein)
{
@@ -1883,11 +1932,71 @@ posix_acl_setxattr_update (xlator_t *this, inode_t *inode, dict_t *xattr)
return ret;
}
+/* *
+ * Posix acl can be set using other xattr such as GF_POSIX_ACL_ACCESS/
+ * GF_POSIX_ACL_DEFAULT which requires to update the context of
+ * access-control translator
+ */
+int
+handling_other_acl_related_xattr (xlator_t *this, inode_t *inode, dict_t *xattr)
+{
+ struct posix_acl *acl = NULL;
+ struct posix_acl_ctx *ctx = NULL;
+ data_t *data = NULL;
+ int ret = 0;
+
+ ctx = posix_acl_ctx_get (inode, this);
+ if (!ctx) {
+ ret = -1;
+ goto out;
+ }
+
+ data = dict_get (xattr, POSIX_ACL_ACCESS_XATTR);
+ if (data) {
+ ctx = posix_acl_ctx_get (inode, this);
+ if (!ctx) {
+ ret = -1;
+ goto out;
+ }
+
+ acl = posix_acl_from_xattr (this, data->data, data->len);
+ ret = posix_acl_set_specific (inode, this, acl, _gf_true);
+ if (ret)
+ goto out;
+
+ if (acl)
+ posix_acl_access_set_mode (acl, ctx);
+
+ }
+
+ if (acl)
+ posix_acl_unref (this, acl);
+
+ data = dict_get (xattr, POSIX_ACL_DEFAULT_XATTR);
+ if (data) {
+ acl = posix_acl_from_xattr (this, data->data, data->len);
+
+ ret = posix_acl_set_specific (inode, this, acl, _gf_false);
+ }
+
+out:
+ if (acl)
+ posix_acl_unref (this, acl);
+
+ return ret;
+}
int
posix_acl_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, dict_t *xdata)
{
+
+ /*
+ * Update the context of posix_acl_translator, if any of
+ * POSIX_ACL_*_XATTR set in the call back
+ */
+ handling_other_acl_related_xattr (this, (inode_t *)cookie, xdata);
+
STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xdata);
return 0;
@@ -1907,9 +2016,13 @@ posix_acl_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
posix_acl_setxattr_update (this, loc->inode, xattr);
- STACK_WIND (frame, posix_acl_setxattr_cbk,
- FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr,
- loc, xattr, flags, xdata);
+ /*
+ * inode is required in call back function to update the context
+ * this translator
+ */
+ STACK_WIND_COOKIE (frame, posix_acl_setxattr_cbk, loc->inode,
+ FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr,
+ loc, xattr, flags, xdata);
return 0;
red:
STACK_UNWIND_STRICT (setxattr, frame, -1, op_errno, xdata);