From 74d92e322e3c9f4f70ddfbf9b0e2140922009658 Mon Sep 17 00:00:00 2001 From: Venkatesh Somyajulu Date: Tue, 15 Jul 2014 18:17:19 +0530 Subject: cluster/dht: Fix races to avoid deletion of linkto file Explanation of Race between rebalance processes: https://bugzilla.redhat.com/show_bug.cgi?id=1110694#c4 STATE 1: BRICK-1 only one brick Cached File in the system STATE 2: Add brick-2 BRICK-1 BRICK-2 STATE 3: Lookup of File on brick-2 by this node's rebalance will fail because hashed file is not created yet. So dht_lookup_everywhere is about to get called. STATE 4: As part of lookup link file at brick-2 will be created. STATE 5: getxattr to check that cached file belongs to this node is done STATE 6: dht_lookup_everywhere_cbk detects the link created by rebalance-1. It will unlink it. STATE 7: getxattr at the link file with "pathinfo" key will be called will fail as the link file is deleted by rebalance on node-2 Fix: So in the STATE 6, we should avoid the deletion of link file. Every time dht_lookup_everywhere gets called, lookup will be performed on all the nodes. So to avoid STATE 6, if linkto file is found, it is not deleted until valid case is found in dht_lookup_everywhere_done. Case 1: if linkto file points to cached node, and cached file exists, uwind with success. Case 2: if linkto does not point to current cached node, and cached file exists: a) Unlink stale link file b) Create new link file Case 3: Only linkto file exists: Delete linkto file Case 4: Only cached file Create link file (Handled event without patch) Case 5: Neither cached nor hashed file is present Return with ENOENT (handled even without patch) Change-Id: Ibf53671410d8d613b8e2e7e5d0ec30fc7dcc0298 BUG: 1116150 Signed-off-by: Venkatesh Somyajulu Reviewed-on: http://review.gluster.org/8231 Reviewed-by: Vijay Bellur Tested-by: Vijay Bellur --- xlators/storage/posix/src/posix.c | 76 +++++++++++++++++++++++++++++++++------ xlators/storage/posix/src/posix.h | 2 ++ 2 files changed, 67 insertions(+), 11 deletions(-) (limited to 'xlators/storage/posix') diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index eb0bac66d06..63b65edcda5 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -1343,17 +1343,22 @@ int32_t posix_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, dict_t *xdata) { - int32_t op_ret = -1; - int32_t op_errno = 0; - char *real_path = NULL; - char *par_path = NULL; - int32_t fd = -1; - struct iatt stbuf = {0,}; - struct posix_private *priv = NULL; - struct iatt preparent = {0,}; - struct iatt postparent = {0,}; - char *pgfid_xattr_key = NULL; - int32_t nlink_samepgfid = 0; + int32_t op_ret = -1; + int32_t op_errno = 0; + char *real_path = NULL; + char *par_path = NULL; + int32_t fd = -1; + struct iatt stbuf = {0,}; + struct posix_private *priv = NULL; + struct iatt preparent = {0,}; + struct iatt postparent = {0,}; + char *pgfid_xattr_key = NULL; + int32_t nlink_samepgfid = 0; + int32_t unlink_if_linkto = 0; + int32_t check_open_fd = 0; + int32_t skip_unlink = 0; + ssize_t xattr_size = -1; + int32_t is_dht_linkto_file = 0; DECLARE_OLD_FS_ID_VAR; @@ -1377,6 +1382,55 @@ posix_unlink (call_frame_t *frame, xlator_t *this, posix_handle_unset (this, stbuf.ia_gfid, NULL); priv = this->private; + + op_ret = dict_get_int32 (xdata, "dont-unlink-for-open-fd", + &check_open_fd); + + if (!op_ret && check_open_fd) { + + LOCK (&loc->inode->lock); + + if (loc->inode->fd_count) { + skip_unlink = 1; + } + + UNLOCK (&loc->inode->lock); + + if (skip_unlink) { + op_ret = -1; + op_errno = EBUSY; + goto out; + } + } + + + op_ret = dict_get_int32 (xdata, "unlink-only-if-dht-linkto-file", + &unlink_if_linkto); + + if (!op_ret && unlink_if_linkto) { + + LOCK (&loc->inode->lock); + + xattr_size = sys_lgetxattr (real_path, LINKTO, NULL, 0); + + if (xattr_size <= 0) { + skip_unlink = 1; + } else { + is_dht_linkto_file = IS_DHT_LINKFILE_MODE (&stbuf); + if (!is_dht_linkto_file) + skip_unlink = 1; + } + + UNLOCK (&loc->inode->lock); + + if (skip_unlink) { + op_ret = -1; + op_errno = EBUSY; + goto out; + } + } + + if (priv->background_unlink) { if (IA_ISREG (loc->inode->ia_type)) { fd = open (real_path, O_RDONLY); diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index c9bfc984da5..aa4a66c3051 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -53,6 +53,8 @@ #define VECTOR_SIZE 64 * 1024 /* vector size 64KB*/ #define MAX_NO_VECT 1024 +#define LINKTO "trusted.glusterfs.dht.linkto" + #define POSIX_GFID_HANDLE_SIZE(base_path_len) (base_path_len + SLEN("/") \ + SLEN(GF_HIDDEN_PATH) + SLEN("/") \ + SLEN("00/") \ -- cgit