From 146944dc7f608f8a9c0034f8d308d0deff32adfa Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Mon, 7 Dec 2015 16:24:15 +0000 Subject: [PATCH 111/141] upcall: Add support to invalidate xattrs When SElinux is used, clients should get a notification that the extended attributes have been updated. Other components (like md-cache) will be able to use this too. A big part of the implementation comes from Poornima through the first version of http://review.gluster.org/12996. Also moving the flags from upcall-cache-invalidation.h to the main libglusterfs upcall-utils.h file, so that other places can easily use them in future. Change-Id: I525345bed8f22d029524ff19ccaf726a2c905454 BUG: 1284873 Signed-off-by: Niels de Vos Signed-off-by: Poornima G Reviewed-on: http://review.gluster.org/12995 Reviewed-by: soumya k Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-on: https://code.engineering.redhat.com/gerrit/87024 Reviewed-by: Rajesh Joseph Tested-by: Rajesh Joseph --- libglusterfs/src/upcall-utils.h | 40 +++ .../upcall/src/upcall-cache-invalidation.h | 34 -- xlators/features/upcall/src/upcall-internal.c | 22 +-- xlators/features/upcall/src/upcall.c | 346 +++++++++++++++++++- xlators/features/upcall/src/upcall.h | 2 +- 5 files changed, 381 insertions(+), 63 deletions(-) diff --git a/libglusterfs/src/upcall-utils.h b/libglusterfs/src/upcall-utils.h index 78db806..614276f 100644 --- a/libglusterfs/src/upcall-utils.h +++ b/libglusterfs/src/upcall-utils.h @@ -15,6 +15,46 @@ #include "compat-uuid.h" #include "compat.h" +/* Flags sent for cache_invalidation */ +#define UP_NLINK 0x00000001 /* update nlink */ +#define UP_MODE 0x00000002 /* update mode and ctime */ +#define UP_OWN 0x00000004 /* update mode,uid,gid and ctime */ +#define UP_SIZE 0x00000008 /* update fsize */ +#define UP_TIMES 0x00000010 /* update all times */ +#define UP_ATIME 0x00000020 /* update atime only */ +#define UP_PERM 0x00000040 /* update fields needed for permission + checking */ +#define UP_RENAME 0x00000080 /* this is a rename op - delete the cache + entry */ +#define UP_FORGET 0x00000100 /* inode_forget on server side - + invalidate the cache entry */ +#define UP_PARENT_TIMES 0x00000200 /* update parent dir times */ + +#define UP_XATTR 0x00000400 /* update the xattrs and ctime */ +#define UP_XATTR_RM 0x00000800 /* Remove the xattrs and update ctime */ + +/* for fops - open, read, lk, */ +#define UP_UPDATE_CLIENT (UP_ATIME) + +/* for fop - write, truncate */ +#define UP_WRITE_FLAGS (UP_SIZE | UP_TIMES) + +/* for fop - setattr */ +#define UP_ATTR_FLAGS (UP_SIZE | UP_TIMES | UP_OWN | UP_MODE | \ + UP_PERM) +/* for fop - rename */ +#define UP_RENAME_FLAGS (UP_RENAME) + +/* to invalidate parent directory entries for fops -rename, unlink, rmdir, + * mkdir, create */ +#define UP_PARENT_DENTRY_FLAGS (UP_PARENT_TIMES) + +/* for fop - unlink, link, rmdir, mkdir */ +#define UP_NLINK_FLAGS (UP_NLINK | UP_TIMES) + +#define IATT_UPDATE_FLAGS (UP_NLINK | UP_MODE | UP_OWN | UP_SIZE | \ + UP_TIMES | UP_ATIME) + typedef enum { GF_UPCALL_EVENT_NULL, GF_UPCALL_CACHE_INVALIDATION, diff --git a/xlators/features/upcall/src/upcall-cache-invalidation.h b/xlators/features/upcall/src/upcall-cache-invalidation.h index 964a72f..62b458f 100644 --- a/xlators/features/upcall/src/upcall-cache-invalidation.h +++ b/xlators/features/upcall/src/upcall-cache-invalidation.h @@ -15,40 +15,6 @@ * events post its last access */ #define CACHE_INVALIDATION_TIMEOUT "60" -/* Flags sent for cache_invalidation */ -#define UP_NLINK 0x00000001 /* update nlink */ -#define UP_MODE 0x00000002 /* update mode and ctime */ -#define UP_OWN 0x00000004 /* update mode,uid,gid and ctime */ -#define UP_SIZE 0x00000008 /* update fsize */ -#define UP_TIMES 0x00000010 /* update all times */ -#define UP_ATIME 0x00000020 /* update atime only */ -#define UP_PERM 0x00000040 /* update fields needed for - permission checking */ -#define UP_RENAME 0x00000080 /* this is a rename op - - delete the cache entry */ -#define UP_FORGET 0x00000100 /* inode_forget on server side - - invalidate the cache entry */ -#define UP_PARENT_TIMES 0x00000200 /* update parent dir times */ - -/* for fops - open, read, lk, */ -#define UP_UPDATE_CLIENT (UP_ATIME) - -/* for fop - write, truncate */ -#define UP_WRITE_FLAGS (UP_SIZE | UP_TIMES) - -/* for fop - setattr */ -#define UP_ATTR_FLAGS (UP_SIZE | UP_TIMES | UP_OWN | \ - UP_MODE | UP_PERM) -/* for fop - rename */ -#define UP_RENAME_FLAGS (UP_RENAME) - -/* to invalidate parent directory entries for fops -rename, unlink, - * rmdir, link */ -#define UP_PARENT_DENTRY_FLAGS (UP_PARENT_TIMES) - -/* for fop - unlink, link, rmdir, mkdir */ -#define UP_NLINK_FLAGS (UP_NLINK | UP_TIMES) - /* xlator options */ gf_boolean_t is_cache_invalidation_enabled(xlator_t *this); int32_t get_cache_invalidation_timeout(xlator_t *this); diff --git a/xlators/features/upcall/src/upcall-internal.c b/xlators/features/upcall/src/upcall-internal.c index 81199eb..f9005df 100644 --- a/xlators/features/upcall/src/upcall-internal.c +++ b/xlators/features/upcall/src/upcall-internal.c @@ -31,7 +31,6 @@ /* * Check if any of the upcall options are enabled: * - cache_invalidation - * - XXX: lease_lk */ gf_boolean_t is_upcall_enabled(xlator_t *this) { @@ -50,25 +49,6 @@ is_upcall_enabled(xlator_t *this) { } /* - * Check if any of cache_invalidation is enabled - */ -gf_boolean_t -is_cache_invalidation_enabled(xlator_t *this) { - upcall_private_t *priv = NULL; - gf_boolean_t is_enabled = _gf_false; - - if (this->private) { - priv = (upcall_private_t *)this->private; - - if (priv->cache_invalidation_enabled) { - is_enabled = _gf_true; - } - } - - return is_enabled; -} - -/* * Get the cache_invalidation_timeout */ int32_t @@ -476,7 +456,7 @@ upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client, upcall_inode_ctx_t *up_inode_ctx = NULL; gf_boolean_t found = _gf_false; - if (!is_cache_invalidation_enabled(this)) + if (!is_upcall_enabled(this)) return; /* server-side generated fops like quota/marker will not have any diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c index e02b1b1..ce3bd4e 100644 --- a/xlators/features/upcall/src/upcall.c +++ b/xlators/features/upcall/src/upcall.c @@ -1579,6 +1579,338 @@ err: int32_t +up_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_XATTR; + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND (setxattr, frame, op_ret, op_errno, xdata); + + return 0; +} + + +int32_t +up_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + int32_t op_errno = -1; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + local = upcall_local_init (frame, this, loc->inode); + if (!local) { + op_errno = ENOMEM; + goto err; + } + +out: + STACK_WIND (frame, up_setxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, + xdata); + + return 0; + +err: + UPCALL_STACK_UNWIND (setxattr, frame, -1, op_errno, NULL); + + return 0; +} + + +int32_t +up_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_XATTR; + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, xdata); + + return 0; +} + + +int32_t +up_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + int32_t op_errno = -1; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + local = upcall_local_init (frame, this, fd->inode); + if (!local) { + op_errno = ENOMEM; + goto err; + } + +out: + STACK_WIND (frame, up_fsetxattr_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetxattr, + fd, dict, flags, xdata); + + return 0; + +err: + UPCALL_STACK_UNWIND (fsetxattr, frame, -1, op_errno, NULL); + + return 0; +} + + +int32_t +up_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_XATTR_RM; + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND (fremovexattr, frame, op_ret, op_errno, + xdata); + return 0; +} + +int32_t +up_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + int32_t op_errno = -1; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + local = upcall_local_init (frame, this, fd->inode); + if (!local) { + op_errno = ENOMEM; + goto err; + } + +out: + STACK_WIND (frame, up_fremovexattr_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->fremovexattr, + fd, name, xdata); + return 0; + +err: + UPCALL_STACK_UNWIND (fremovexattr, frame, -1, op_errno, NULL); + + return 0; +} + +int32_t +up_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_XATTR_RM; + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND (removexattr, frame, op_ret, op_errno, + xdata); + return 0; +} + +int32_t +up_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) +{ + int32_t op_errno = -1; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + local = upcall_local_init (frame, this, loc->inode); + if (!local) { + op_errno = ENOMEM; + goto err; + } + +out: + STACK_WIND (frame, up_removexattr_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->removexattr, + loc, name, xdata); + return 0; + +err: + UPCALL_STACK_UNWIND (removexattr, frame, -1, op_errno, NULL); + + return 0; +} + + +int32_t +up_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND (fgetxattr, frame, op_ret, op_errno, + dict, xdata); + return 0; +} + + +int32_t +up_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + int32_t op_errno = -1; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + local = upcall_local_init (frame, this, fd->inode); + if (!local) { + op_errno = ENOMEM; + goto err; + } + +out: + STACK_WIND (frame, up_fgetxattr_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->fgetxattr, + fd, name, xdata); + return 0; +err: + UPCALL_STACK_UNWIND (fgetxattr, frame, -1, op_errno, + NULL, NULL); + return 0; +} + + +int32_t +up_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate (frame, this, client, local->inode, flags, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND (getxattr, frame, op_ret, op_errno, + dict, xdata); + return 0; +} + +int32_t +up_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) +{ + int32_t op_errno = -1; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF (this, out); + + local = upcall_local_init (frame, this, loc->inode); + if (!local) { + op_errno = ENOMEM; + goto err; + } + +out: + STACK_WIND (frame, up_getxattr_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->getxattr, + loc, name, xdata); + return 0; +err: + UPCALL_STACK_UNWIND (getxattr, frame, -1, op_errno, + NULL, NULL); + return 0; +} + + +int32_t mem_acct_init (xlator_t *this) { int ret = -1; @@ -1842,6 +2174,13 @@ struct xlator_fops fops = { .rmdir = up_rmdir, .rename = up_rename, + .setxattr = up_setxattr, + .fsetxattr = up_fsetxattr, + .getxattr = up_getxattr, + .fgetxattr = up_fgetxattr, + .fremovexattr = up_fremovexattr, + .removexattr = up_removexattr, + #ifdef NOT_SUPPORTED /* internal lk fops */ .inodelk = up_inodelk, @@ -1856,13 +2195,6 @@ struct xlator_fops fops = { .fsync = up_fsync, .fsyncdir = up_fsyncdir, - /* XXX: Handle xattr fops (BZ-1211863) */ - .getxattr = up_getxattr, - .fgetxattr = up_fgetxattr, - .fremovexattr = up_fremovexattr, - .removexattr = up_removexattr, - .setxattr = up_setxattr, - .fsetxattr = up_fsetxattr, .xattrop = up_xattrop, .fxattrop = up_fxattrop, #endif diff --git a/xlators/features/upcall/src/upcall.h b/xlators/features/upcall/src/upcall.h index 4d021e0..d53c6a3 100644 --- a/xlators/features/upcall/src/upcall.h +++ b/xlators/features/upcall/src/upcall.h @@ -111,7 +111,7 @@ void *upcall_reaper_thread (void *data); int upcall_reaper_thread_init (xlator_t *this); /* Xlator options */ -gf_boolean_t is_upcall_enabled(xlator_t *this); +gf_boolean_t is_upcall_enabled (xlator_t *this); /* Cache invalidation specific */ void upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, -- 1.7.1