diff options
-rw-r--r-- | xlators/cluster/dht/src/dht-common.c | 5 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-common.h | 11 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-helper.c | 155 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-inode-read.c | 59 | ||||
-rw-r--r-- | xlators/cluster/dht/src/dht-messages.h | 9 |
5 files changed, 218 insertions, 21 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c index b3e30392c29..e8d7401c474 100644 --- a/xlators/cluster/dht/src/dht-common.c +++ b/xlators/cluster/dht/src/dht-common.c @@ -8404,7 +8404,10 @@ dht_entrylk_cbk (call_frame_t *frame, void *cookie, return 0; } - +/* TODO + * Sending entrylk to cached subvol can result in stale lock + * as described in the bug 1311002. + */ int dht_entrylk (call_frame_t *frame, xlator_t *this, const char *volume, loc_t *loc, const char *basename, diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h index b2e9df68996..9a71c46c8e4 100644 --- a/xlators/cluster/dht/src/dht-common.h +++ b/xlators/cluster/dht/src/dht-common.h @@ -101,6 +101,7 @@ typedef struct dht_stat_time dht_stat_time_t; struct dht_inode_ctx { dht_layout_t *layout; dht_stat_time_t time; + xlator_t *lock_subvol; }; typedef struct dht_inode_ctx dht_inode_ctx_t; @@ -285,6 +286,8 @@ struct dht_local { int op_errno; } lock; + short lock_type; + call_stub_t *stub; int32_t parent_disk_layout[4]; }; @@ -1218,4 +1221,12 @@ dht_release (xlator_t *this, fd_t *fd); int32_t dht_set_fixed_dir_stat (struct iatt *stat); + +xlator_t* +dht_get_lock_subvolume (xlator_t *this, struct gf_flock *lock, + dht_local_t *local); + +int +dht_lk_inode_unref (call_frame_t *frame, int32_t op_ret); + #endif/* _DHT_H */ diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c index 0384c2a4cc4..0a5e1128db1 100644 --- a/xlators/cluster/dht/src/dht-helper.c +++ b/xlators/cluster/dht/src/dht-helper.c @@ -2298,3 +2298,158 @@ dht_heal_full_path_done (int op_ret, call_frame_t *heal_frame, void *data) DHT_STACK_DESTROY (heal_frame); return 0; } + +/* This function must be called inside an inode lock */ +int +__dht_lock_subvol_set (inode_t *inode, xlator_t *this, + xlator_t *lock_subvol) +{ + dht_inode_ctx_t *ctx = NULL; + int ret = -1; + uint64_t value = 0; + + GF_VALIDATE_OR_GOTO (this->name, inode, out); + + ret = __inode_ctx_get0 (inode, this, &value); + if (ret || !value) { + return -1; + } + + ctx = (dht_inode_ctx_t *) value; + ctx->lock_subvol = lock_subvol; +out: + return ret; +} + +xlator_t* +dht_get_lock_subvolume (xlator_t *this, struct gf_flock *lock, + dht_local_t *local) +{ + xlator_t *subvol = NULL; + inode_t *inode = NULL; + int32_t ret = -1; + uint64_t value = 0; + xlator_t *cached_subvol = NULL; + dht_inode_ctx_t *ctx = NULL; + char gfid[GF_UUID_BUF_SIZE] = {0}; + + GF_VALIDATE_OR_GOTO (this->name, lock, out); + GF_VALIDATE_OR_GOTO (this->name, local, out); + + cached_subvol = local->cached_subvol; + + if (local->loc.inode || local->fd) { + inode = local->loc.inode ? local->loc.inode : local->fd->inode; + } + + if (!inode) + goto out; + + if (!(IA_ISDIR (inode->ia_type) || IA_ISINVAL (inode->ia_type))) { + /* + * We may get non-linked inode for directories as part + * of the selfheal code path. So checking for IA_INVAL + * type also. This will only happen for directory. + */ + subvol = local->cached_subvol; + goto out; + } + + if (lock->l_type != F_UNLCK) { + /* + * inode purging might happen on NFS between a lk + * and unlk. Due to this lk and unlk might be sent + * to different subvols. + * So during a lock request, taking a ref on inode + * to prevent inode purging. inode unref will happen + * in unlock cbk code path. + */ + inode_ref (inode); + } + + LOCK (&inode->lock); + ret = __inode_ctx_get0 (inode, this, &value); + if (!ret && value) { + ctx = (dht_inode_ctx_t *) value; + subvol = ctx->lock_subvol; + } + if (!subvol && lock->l_type != F_UNLCK && cached_subvol) { + ret = __dht_lock_subvol_set (inode, this, + cached_subvol); + if (ret) { + gf_uuid_unparse(inode->gfid, gfid); + gf_msg (this->name, GF_LOG_WARNING, 0, + DHT_MSG_SET_INODE_CTX_FAILED, + "Failed to set lock_subvol in " + "inode ctx for gfid %s", + gfid); + goto unlock; + } + subvol = cached_subvol; + } +unlock: + UNLOCK (&inode->lock); + if (!subvol && inode && lock->l_type != F_UNLCK) { + inode_unref (inode); + } +out: + return subvol; +} + +int +dht_lk_inode_unref (call_frame_t *frame, int32_t op_ret) +{ + int ret = -1; + dht_local_t *local = NULL; + inode_t *inode = NULL; + xlator_t *this = NULL; + char gfid[GF_UUID_BUF_SIZE] = {0}; + + local = frame->local; + this = frame->this; + + if (local->loc.inode || local->fd) { + inode = local->loc.inode ? local->loc.inode : local->fd->inode; + } + if (!inode) { + gf_msg (this->name, GF_LOG_WARNING, 0, + DHT_MSG_LOCK_INODE_UNREF_FAILED, + "Found a NULL inode. Failed to unref the inode"); + goto out; + } + + if (!(IA_ISDIR (inode->ia_type) || IA_ISINVAL (inode->ia_type))) { + ret = 0; + goto out; + } + + switch (local->lock_type) { + case F_RDLCK: + case F_WRLCK: + if (op_ret) { + gf_uuid_unparse(inode->gfid, gfid); + gf_msg_debug (this->name, 0, + "lock request failed for gfid %s", gfid); + inode_unref (inode); + goto out; + } + break; + + case F_UNLCK: + if (!op_ret) { + inode_unref (inode); + } else { + gf_uuid_unparse(inode->gfid, gfid); + gf_msg (this->name, GF_LOG_WARNING, 0, + DHT_MSG_LOCK_INODE_UNREF_FAILED, + "Unlock request failed for gfid %s." + "Failed to unref the inode", gfid); + goto out; + } + default: + break; + } + ret = 0; +out: + return ret; +} diff --git a/xlators/cluster/dht/src/dht-inode-read.c b/xlators/cluster/dht/src/dht-inode-read.c index 16a82cd5b98..549f1b9ea7e 100644 --- a/xlators/cluster/dht/src/dht-inode-read.c +++ b/xlators/cluster/dht/src/dht-inode-read.c @@ -997,6 +997,7 @@ dht_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } out: + dht_lk_inode_unref (frame, op_ret); DHT_STACK_UNWIND (lk, frame, op_ret, op_errno, flock, xdata); return 0; @@ -1035,7 +1036,7 @@ int dht_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int cmd, struct gf_flock *flock, dict_t *xdata) { - xlator_t *subvol = NULL; + xlator_t *lock_subvol = NULL; int op_errno = -1; dht_local_t *local = NULL; @@ -1044,11 +1045,16 @@ dht_lk (call_frame_t *frame, xlator_t *this, VALIDATE_OR_GOTO (fd, err); local = dht_local_init (frame, NULL, fd, GF_FOP_LK); + if (!local) { + op_errno = ENOMEM; + goto err; + } - subvol = dht_subvol_get_cached (this, fd->inode); - if (!subvol) { + local->lock_type = flock->l_type; + lock_subvol = dht_get_lock_subvolume (this, flock, local); + if (!lock_subvol) { gf_msg_debug (this->name, 0, - "no cached subvolume for fd=%p", fd); + "no lock subvolume for path=%p", fd); op_errno = EINVAL; goto err; } @@ -1058,7 +1064,7 @@ dht_lk (call_frame_t *frame, xlator_t *this, local->call_cnt = 1; - STACK_WIND (frame, dht_lk_cbk, subvol, subvol->fops->lk, fd, + STACK_WIND (frame, dht_lk_cbk, lock_subvol, lock_subvol->fops->lk, fd, cmd, flock, xdata); return 0; @@ -1283,6 +1289,7 @@ dht_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { + dht_lk_inode_unref (frame, op_ret); DHT_STACK_UNWIND (inodelk, frame, op_ret, op_errno, xdata); return 0; } @@ -1292,9 +1299,9 @@ int32_t dht_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, loc_t *loc, int32_t cmd, struct gf_flock *lock, dict_t *xdata) { - xlator_t *subvol = NULL; - int op_errno = -1; - dht_local_t *local = NULL; + xlator_t *lock_subvol = NULL; + int op_errno = -1; + dht_local_t *local = NULL; VALIDATE_OR_GOTO (frame, err); @@ -1308,10 +1315,11 @@ dht_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, goto err; } - subvol = local->cached_subvol; - if (!subvol) { + local->lock_type = lock->l_type; + lock_subvol = dht_get_lock_subvolume (this, lock, local); + if (!lock_subvol) { gf_msg_debug (this->name, 0, - "no cached subvolume for path=%s", loc->path); + "no lock subvolume for path=%s", loc->path); op_errno = EINVAL; goto err; } @@ -1320,7 +1328,7 @@ dht_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, STACK_WIND (frame, dht_inodelk_cbk, - subvol, subvol->fops->inodelk, + lock_subvol, lock_subvol->fops->inodelk, volume, loc, cmd, lock, xdata); return 0; @@ -1332,12 +1340,13 @@ err: return 0; } - int dht_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { + + dht_lk_inode_unref (frame, op_ret); DHT_STACK_UNWIND (finodelk, frame, op_ret, op_errno, xdata); return 0; } @@ -1347,23 +1356,35 @@ int dht_finodelk (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata) { - xlator_t *subvol = NULL; - int op_errno = -1; + xlator_t *lock_subvol = NULL; + dht_local_t *local = NULL; + int op_errno = -1; + VALIDATE_OR_GOTO (frame, err); VALIDATE_OR_GOTO (this, err); VALIDATE_OR_GOTO (fd, err); - subvol = dht_subvol_get_cached (this, fd->inode); - if (!subvol) { + local = dht_local_init (frame, NULL, fd, GF_FOP_INODELK); + if (!local) { + op_errno = ENOMEM; + goto err; + } + + local->call_cnt = 1; + local->lock_type = lock->l_type; + + lock_subvol = dht_get_lock_subvolume (this, lock, local); + if (!lock_subvol) { gf_msg_debug (this->name, 0, - "no cached subvolume for fd=%p", fd); + "no lock subvolume for fd=%p", fd); op_errno = EINVAL; goto err; } - STACK_WIND (frame, dht_finodelk_cbk, subvol, subvol->fops->finodelk, + STACK_WIND (frame, dht_finodelk_cbk, lock_subvol, + lock_subvol->fops->finodelk, volume, fd, cmd, lock, xdata); return 0; diff --git a/xlators/cluster/dht/src/dht-messages.h b/xlators/cluster/dht/src/dht-messages.h index 044292d86ca..8c0b9103df1 100644 --- a/xlators/cluster/dht/src/dht-messages.h +++ b/xlators/cluster/dht/src/dht-messages.h @@ -40,7 +40,7 @@ */ #define GLFS_DHT_BASE GLFS_MSGID_COMP_DHT -#define GLFS_DHT_NUM_MESSAGES 114 +#define GLFS_DHT_NUM_MESSAGES 116 #define GLFS_MSGID_END (GLFS_DHT_BASE + GLFS_DHT_NUM_MESSAGES + 1) /* Messages with message IDs */ @@ -1064,5 +1064,12 @@ */ #define DHT_MSG_LOCK_MIGRATION_FAILED (GLFS_DHT_BASE + 115) +/* + * @messageid 109116 + * @diagnosis + * @recommendedaction None + */ +#define DHT_MSG_LOCK_INODE_UNREF_FAILED (GLFS_DHT_BASE + 116) + #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" #endif /* _DHT_MESSAGES_H_ */ |