From eb362c74db84d95aac07febf0d888bd98b3fb2b9 Mon Sep 17 00:00:00 2001 From: N Balachandran Date: Sat, 6 Feb 2016 21:09:29 +0530 Subject: cluster/tier: Create linkfiles to hardlinks correctly There is a bug in the way hardlinks are handled in tiered volumes. Ideally, the tier linkto files on the cold tier to files that are hardlinks to each other on the hot tier, should themselves be hardlinks of each other. As they are not, they end up being files with the same gfid but different names for the cold tier dht, and end up overwriting the cached-subvol information stored in the dht inode-ctx. Change-Id: Ic658a316836e6a1729cfea848b7d212674b0edd2 BUG: 1305277 Signed-off-by: N Balachandran Reviewed-on: http://review.gluster.org/13391 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-by: Dan Lambright Tested-by: Dan Lambright --- xlators/cluster/dht/src/tier-common.c | 126 ++++++++++++++++++++++++++++++++++ xlators/cluster/dht/src/tier-common.h | 5 ++ xlators/cluster/dht/src/tier.c | 2 +- 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/xlators/cluster/dht/src/tier-common.c b/xlators/cluster/dht/src/tier-common.c index 27a780d6f6c..08664ae6a16 100644 --- a/xlators/cluster/dht/src/tier-common.c +++ b/xlators/cluster/dht/src/tier-common.c @@ -16,6 +16,132 @@ #include "tier-common.h" #include "tier.h" +int +dht_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, + inode_t *inode, struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + + +int +tier_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, + inode_t *inode, struct iatt *stbuf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + dht_local_t *local = NULL; + dht_conf_t *conf = NULL; + loc_t *oldloc = NULL; + loc_t *newloc = NULL; + + local = frame->local; + conf = this->private; + + oldloc = &local->loc; + newloc = &local->loc2; + + if (op_ret == -1) { + /* No continuation on DHT inode missing errors, as we should + * then have a good stbuf that states P2 happened. We would + * get inode missing if, the file completed migrated between + * the lookup and the link call */ + goto out; + } + + if (local->call_cnt != 1) { + goto out; + } + + local->call_cnt = 2; + + /* Do this on the hot tier now */ + + STACK_WIND (frame, tier_link_cbk, local->cached_subvol, + local->cached_subvol->fops->link, + oldloc, newloc, xdata); + + return 0; + +out: + DHT_STRIP_PHASE1_FLAGS (stbuf); + + DHT_STACK_UNWIND (link, frame, op_ret, op_errno, inode, stbuf, + preparent, postparent, NULL); + + return 0; +} + + +int +tier_link (call_frame_t *frame, xlator_t *this, + loc_t *oldloc, loc_t *newloc, dict_t *xdata) +{ + xlator_t *cached_subvol = NULL; + xlator_t *hashed_subvol = NULL; + int op_errno = -1; + int ret = -1; + dht_local_t *local = NULL; + dht_conf_t *conf = NULL; + + + VALIDATE_OR_GOTO (frame, err); + VALIDATE_OR_GOTO (this, err); + VALIDATE_OR_GOTO (oldloc, err); + VALIDATE_OR_GOTO (newloc, err); + + conf = this->private; + + local = dht_local_init (frame, oldloc, NULL, GF_FOP_LINK); + if (!local) { + op_errno = ENOMEM; + goto err; + } + local->call_cnt = 1; + + cached_subvol = local->cached_subvol; + + if (!cached_subvol) { + gf_msg_debug (this->name, 0, + "no cached subvolume for path=%s", oldloc->path); + op_errno = ENOENT; + goto err; + } + + hashed_subvol = TIER_HASHED_SUBVOL; + + ret = loc_copy (&local->loc2, newloc); + if (ret == -1) { + op_errno = ENOMEM; + goto err; + } + + if (hashed_subvol == cached_subvol) { + STACK_WIND (frame, dht_link_cbk, + cached_subvol, cached_subvol->fops->link, + oldloc, newloc, xdata); + return 0; + } + + + /* Create hardlinks to both the data file on the hot tier + and the linkto file on the cold tier */ + + gf_uuid_copy (local->gfid, oldloc->inode->gfid); + + STACK_WIND (frame, tier_link_cbk, + hashed_subvol, hashed_subvol->fops->link, + oldloc, newloc, xdata); + + return 0; +err: + op_errno = (op_errno == -1) ? errno : op_errno; + DHT_STACK_UNWIND (link, frame, -1, op_errno, NULL, NULL, NULL, NULL, + NULL); + return 0; +} + + + int tier_create_unlink_stale_linkto_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, int op_errno, diff --git a/xlators/cluster/dht/src/tier-common.h b/xlators/cluster/dht/src/tier-common.h index 17cddcdd3e4..0ef96aca032 100644 --- a/xlators/cluster/dht/src/tier-common.h +++ b/xlators/cluster/dht/src/tier-common.h @@ -53,5 +53,10 @@ tier_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t yoff, dict_t *xdata); + + +int +tier_link (call_frame_t *frame, xlator_t *this, + loc_t *oldloc, loc_t *newloc, dict_t *xdata); #endif diff --git a/xlators/cluster/dht/src/tier.c b/xlators/cluster/dht/src/tier.c index 8a756b88c27..ce11fa7d7ca 100644 --- a/xlators/cluster/dht/src/tier.c +++ b/xlators/cluster/dht/src/tier.c @@ -2378,7 +2378,7 @@ struct xlator_fops fops = { .fsyncdir = dht_fsyncdir, .symlink = dht_symlink, .unlink = tier_unlink, - .link = dht_link, + .link = tier_link, .mkdir = dht_mkdir, .rmdir = dht_rmdir, .rename = dht_rename, -- cgit