summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/basic/distribute/lookup.t54
-rw-r--r--xlators/cluster/dht/src/dht-common.c532
2 files changed, 375 insertions, 211 deletions
diff --git a/tests/basic/distribute/lookup.t b/tests/basic/distribute/lookup.t
new file mode 100644
index 00000000000..f757bd99fd9
--- /dev/null
+++ b/tests/basic/distribute/lookup.t
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+. $(dirname $0)/../../nfs.rc
+. $(dirname $0)/../../common-utils.rc
+
+# Test overview:
+# Check that non-privileged users can also clean up stale linkto files
+#
+# 1. Use the current parallel-readdir behaviour of changing the DHT child subvols
+# in the graph to generate stale linkto files
+# 2. Access the file with the stale linkto file as a non-root user
+# 3. This should now succeed (returned EIO before commit 3fb1df7870e03c9de)
+
+cleanup
+
+TEST glusterd
+TEST pidof glusterd
+
+TEST $CLI volume create $V0 $H0:$B0/$V0-{1..3}
+TEST $CLI volume start $V0
+
+# Mount using FUSE and create a file
+TEST glusterfs -s $H0 --volfile-id $V0 $M0
+TEST glusterfs -s $H0 --volfile-id $V0 $M1
+
+ls $M0/FILE-1
+EXPECT "2" echo $?
+
+
+# Create a file and a directory on $M0
+TEST dd if=/dev/urandom of=$M0/FILE-1 count=1 bs=16k
+TEST mkdir $M0/dir1
+
+ls $M0/FILE-1
+EXPECT "0" echo $?
+
+ls $M0/dir1
+EXPECT "0" echo $?
+
+#Use a fresh mount so as to trigger a fresh lookup
+TEST glusterfs -s $H0 --volfile-id $V0 $M1
+
+TEST ls $M1/FILE-1
+EXPECT "0" echo $?
+
+
+ls $M1/dir1
+EXPECT "0" echo $?
+
+# Cleanup
+cleanup
+
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index 87b2d6e2bb4..9415af31bd7 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -50,6 +50,15 @@ dht_common_xattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, dict_t *dict,
dict_t *xdata);
+int
+dht_set_file_xattr_req (xlator_t *this, loc_t *loc, dict_t *xattr_req);
+
+int
+dht_set_dir_xattr_req (xlator_t *this, loc_t *loc, dict_t *xattr_req);
+
+int
+dht_do_fresh_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc);
+
/* Sets the blocks and size values to fixed values. This is to be called
* only for dirs. The caller is responsible for checking the type
@@ -1152,7 +1161,7 @@ out:
int
-dht_discover (call_frame_t *frame, xlator_t *this, loc_t *loc)
+dht_do_discover (call_frame_t *frame, xlator_t *this, loc_t *loc)
{
int ret;
dht_local_t *local = NULL;
@@ -1165,21 +1174,17 @@ dht_discover (call_frame_t *frame, xlator_t *this, loc_t *loc)
conf = this->private;
local = frame->local;
- ret = dict_set_uint32 (local->xattr_req, conf->xattr_name, 4 * 4);
- if (ret)
- gf_msg (this->name, GF_LOG_WARNING, 0,
- DHT_MSG_DICT_SET_FAILED,
- "%s: Failed to set dictionary value:key = %s",
- loc->path, conf->xattr_name);
+ ret = dht_set_file_xattr_req (this, loc, local->xattr_req);
+ if (ret) {
+ goto err;
+ }
- ret = dict_set_uint32 (local->xattr_req, conf->link_xattr_name, 256);
- if (ret)
- gf_msg (this->name, GF_LOG_WARNING, 0,
- DHT_MSG_DICT_SET_FAILED,
- "%s: Failed to set dictionary value:key = %s",
- loc->path, conf->link_xattr_name);
+ ret = dht_set_dir_xattr_req (this, loc, local->xattr_req);
+ if (ret) {
+ goto err;
+ }
- if (__is_root_gfid(local->loc.gfid)) {
+ if (loc_is_root (loc)) {
ret = dict_set_uint32 (local->xattr_req,
conf->commithash_xattr_name,
sizeof(uint32_t));
@@ -3323,20 +3328,16 @@ err:
* perform proper self-healing of dirs
*/
void
-dht_check_and_set_acl_xattr_req (inode_t *inode, dict_t *xattr_req)
+dht_check_and_set_acl_xattr_req (xlator_t *this, dict_t *xattr_req)
{
int ret = 0;
- GF_ASSERT (inode);
GF_ASSERT (xattr_req);
- if (inode->ia_type != IA_IFDIR)
- return;
-
if (!dict_get (xattr_req, POSIX_ACL_ACCESS_XATTR)) {
ret = dict_set_int8 (xattr_req, POSIX_ACL_ACCESS_XATTR, 0);
if (ret)
- gf_msg (THIS->name, GF_LOG_WARNING, -ret,
+ gf_msg (this->name, GF_LOG_WARNING, -ret,
DHT_MSG_DICT_SET_FAILED,
"Failed to set dictionary value:key = %s",
POSIX_ACL_ACCESS_XATTR);
@@ -3345,7 +3346,7 @@ dht_check_and_set_acl_xattr_req (inode_t *inode, dict_t *xattr_req)
if (!dict_get (xattr_req, POSIX_ACL_DEFAULT_XATTR)) {
ret = dict_set_int8 (xattr_req, POSIX_ACL_DEFAULT_XATTR, 0);
if (ret)
- gf_msg (THIS->name, GF_LOG_WARNING, -ret,
+ gf_msg (this->name, GF_LOG_WARNING, -ret,
DHT_MSG_DICT_SET_FAILED,
"Failed to set dictionary value:key = %s",
POSIX_ACL_DEFAULT_XATTR);
@@ -3354,12 +3355,104 @@ dht_check_and_set_acl_xattr_req (inode_t *inode, dict_t *xattr_req)
return;
}
+
+/* for directories, we need the following info:
+ * the layout : trusted.glusterfs.dht
+ * the mds information : trusted.glusterfs.dht.mds
+ * the acl info: See above
+ */
int
-dht_lookup (call_frame_t *frame, xlator_t *this,
- loc_t *loc, dict_t *xattr_req)
+dht_set_dir_xattr_req (xlator_t *this, loc_t *loc, dict_t *xattr_req)
+{
+ int ret = -EINVAL;
+ dht_conf_t *conf = NULL;
+
+ conf = this->private;
+ if (!conf) {
+ goto err;
+ }
+
+ if (!xattr_req) {
+ goto err;
+ }
+
+ /* Xattr to get the layout for a directory
+ */
+ ret = dict_set_uint32 (xattr_req, conf->xattr_name, 4 * 4);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", conf->xattr_name, loc->path);
+ goto err;
+ }
+
+ /*Non-fatal failure */
+ ret = dict_set_uint32 (xattr_req, conf->mds_xattr_key, 4);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", conf->mds_xattr_key, loc->path);
+ }
+
+ dht_check_and_set_acl_xattr_req (this, xattr_req);
+ ret = 0;
+err:
+ return ret;
+}
+
+
+int dht_set_file_xattr_req (xlator_t *this, loc_t *loc, dict_t *xattr_req)
+{
+ int ret = -EINVAL;
+ dht_conf_t *conf = NULL;
+
+ conf = this->private;
+ if (!conf) {
+ goto err;
+ }
+
+ if (!xattr_req) {
+ goto err;
+ }
+
+ /* Used to check whether this is a linkto file.
+ */
+ ret = dict_set_uint32 (xattr_req,
+ conf->link_xattr_name, 256);
+ if (ret < 0) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", conf->link_xattr_name, loc->path);
+ goto err;
+ }
+
+ /* This is used to make sure we don't unlink linkto files
+ * which are the target of an ongoing file migration.
+ */
+ ret = dict_set_uint32 (xattr_req,
+ GLUSTERFS_OPEN_FD_COUNT, 4);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", GLUSTERFS_OPEN_FD_COUNT, loc->path);
+ goto err;
+ }
+
+ ret = 0;
+err:
+ return ret;
+}
+
+
+
+int
+dht_do_revalidate (call_frame_t *frame, xlator_t *this, loc_t *loc)
{
xlator_t *subvol = NULL;
- xlator_t *hashed_subvol = NULL;
xlator_t *mds_subvol = NULL;
dht_local_t *local = NULL;
dht_conf_t *conf = NULL;
@@ -3369,6 +3462,202 @@ dht_lookup (call_frame_t *frame, xlator_t *this,
int i = 0;
int call_cnt = 0;
int gen = 0;
+
+ conf = this->private;
+ if (!conf) {
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ local = frame->local;
+ if (!local) {
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ layout = local->layout;
+ if (!layout) {
+ gf_msg_debug (this->name, 0,
+ "path = %s. No layout found in the inode ctx.",
+ loc->path);
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ /* Generation number has changed. This layout may be stale. */
+ if (layout->gen && (layout->gen < conf->gen)) {
+ gen = layout->gen;
+ dht_layout_unref (this, local->layout);
+ local->layout = NULL;
+ local->cached_subvol = NULL;
+
+ gf_msg_debug(this->name, 0,
+ "path = %s. In memory layout may be stale."
+ "(layout->gen (%d) is less than "
+ "conf->gen (%d)). Calling fresh lookup.",
+ loc->path, gen, conf->gen);
+
+ dht_do_fresh_lookup (frame, this, loc);
+ return 0;
+ }
+
+ local->inode = inode_ref (loc->inode);
+
+ /* Since we don't know whether this has changed,
+ * request all xattrs*/
+ ret = dht_set_file_xattr_req (this, loc, local->xattr_req);
+ if (ret) {
+ op_errno = -ret;
+ goto err;
+ }
+
+ ret = dht_set_dir_xattr_req (this, loc, local->xattr_req);
+ if (ret) {
+ op_errno = -ret;
+ goto err;
+ }
+
+ if (IA_ISDIR (local->inode->ia_type)) {
+ ret = dht_inode_ctx_mdsvol_get (local->inode, this,
+ &mds_subvol);
+ if (ret || !mds_subvol) {
+ gf_msg_debug (this->name, 0,
+ "path = %s. No mds subvol in inode ctx",
+ local->loc.path);
+ }
+ local->mds_subvol = mds_subvol;
+ local->call_cnt = conf->subvolume_cnt;
+ call_cnt = local->call_cnt;
+
+ for (i = 0; i < call_cnt; i++) {
+ STACK_WIND_COOKIE (frame, dht_revalidate_cbk,
+ conf->subvolumes[i],
+ conf->subvolumes[i],
+ conf->subvolumes[i]->fops->lookup,
+ loc, local->xattr_req);
+ }
+ return 0;
+ }
+
+ /* If not a dir, this should be 1 */
+ local->call_cnt = layout->cnt;
+ call_cnt = local->call_cnt;
+
+ for (i = 0; i < call_cnt; i++) {
+ subvol = layout->list[i].xlator;
+
+ gf_msg_debug (this->name, 0, "path = %s. Calling "
+ "revalidate lookup on %s",
+ loc->path, subvol->name);
+
+ STACK_WIND_COOKIE (frame, dht_revalidate_cbk, subvol,
+ subvol, subvol->fops->lookup,
+ &local->loc, local->xattr_req);
+ }
+ return 0;
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ DHT_STACK_UNWIND (lookup, frame, -1, op_errno, NULL, NULL, NULL,
+ NULL);
+ return 0;
+}
+
+int
+dht_do_fresh_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc)
+{
+ int ret = -1;
+ dht_conf_t *conf = NULL;
+ xlator_t *hashed_subvol = NULL;
+ dht_local_t *local = NULL;
+ int op_errno = -1;
+ int call_cnt = 0;
+ int i = 0;
+
+ conf = this->private;
+ if (!conf) {
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ local = frame->local;
+ if (!local) {
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ /* Since we don't know whether this is a file or a directory,
+ * request all xattrs*/
+ ret = dht_set_file_xattr_req (this, loc, local->xattr_req);
+ if (ret) {
+ op_errno = -ret;
+ goto err;
+ }
+
+ ret = dht_set_dir_xattr_req (this, loc, local->xattr_req);
+ if (ret) {
+ op_errno = -ret;
+ goto err;
+ }
+
+ /* This should have been set in dht_lookup */
+ hashed_subvol = local->hashed_subvol;
+
+ if (!hashed_subvol) {
+ gf_msg_debug (this->name, 0,
+ "%s: no subvolume in layout for path, "
+ "checking on all the subvols to see if "
+ "it is a directory", loc->path);
+
+ call_cnt = conf->subvolume_cnt;
+ local->call_cnt = call_cnt;
+
+ local->layout = dht_layout_new (this,
+ conf->subvolume_cnt);
+ if (!local->layout) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+ gf_msg_debug (this->name, 0,
+ "%s: Found null hashed subvol. Calling lookup"
+ " on all nodes.", loc->path);
+
+ for (i = 0; i < call_cnt; i++) {
+ STACK_WIND_COOKIE (frame, dht_lookup_dir_cbk,
+ conf->subvolumes[i],
+ conf->subvolumes[i],
+ conf->subvolumes[i]->fops->lookup,
+ &local->loc, local->xattr_req);
+ }
+ return 0;
+ }
+
+ /* if we have the hashed_subvol, send the lookup there first so
+ * as to see whether we have a file or a directory */
+ gf_msg_debug (this->name, 0, "Calling fresh lookup for %s on"
+ " %s", loc->path, hashed_subvol->name);
+
+ STACK_WIND_COOKIE (frame, dht_lookup_cbk, hashed_subvol,
+ hashed_subvol, hashed_subvol->fops->lookup,
+ loc, local->xattr_req);
+ return 0;
+err:
+ op_errno = (op_errno == -1) ? errno : op_errno;
+ DHT_STACK_UNWIND (lookup, frame, -1, op_errno, NULL, NULL, NULL,
+ NULL);
+ return 0;
+}
+
+
+int
+dht_lookup (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, dict_t *xattr_req)
+{
+ xlator_t *hashed_subvol = NULL;
+ dht_local_t *local = NULL;
+ dht_conf_t *conf = NULL;
+ int ret = -1;
+ int op_errno = -1;
loc_t new_loc = {0,};
VALIDATE_OR_GOTO (frame, err);
@@ -3392,7 +3681,7 @@ dht_lookup (call_frame_t *frame, xlator_t *this,
loc_wipe (&local->loc);
ret = loc_dup (&new_loc, &local->loc);
- /* we no more need 'new_loc' entries */
+ /* we no longer need 'new_loc' entries */
loc_wipe (&new_loc);
/* check if loc_dup() is successful */
@@ -3411,26 +3700,16 @@ dht_lookup (call_frame_t *frame, xlator_t *this,
local->xattr_req = dict_new ();
}
- ret = dict_set_uint32 (local->xattr_req, conf->mds_xattr_key, 4);
-
- if (ret) {
- gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
- DHT_MSG_DICT_SET_FAILED,
- "Failed to set dictionary value:key = %s for "
- "path %s", conf->mds_xattr_key, loc->path);
- }
-
-
/* Nameless lookup */
if (gf_uuid_is_null (loc->pargfid) && !gf_uuid_is_null (loc->gfid) &&
!__is_root_gfid (loc->inode->gfid)) {
local->cached_subvol = NULL;
- dht_discover (frame, this, loc);
+ dht_do_discover (frame, this, loc);
return 0;
}
- if (__is_root_gfid(loc->gfid)) {
+ if (loc_is_root (loc)) {
ret = dict_set_uint32 (local->xattr_req,
conf->commithash_xattr_name,
sizeof(uint32_t));
@@ -3444,183 +3723,14 @@ dht_lookup (call_frame_t *frame, xlator_t *this,
/* The entry has been looked up before and has an inode_ctx set
*/
if (is_revalidate (loc)) {
- layout = local->layout;
- if (!layout) {
- gf_msg_debug (this->name, 0,
- "Revalidate lookup without cache."
- " path=%s", loc->path);
- op_errno = EINVAL;
- goto err;
- }
-
- if (layout->gen && (layout->gen < conf->gen)) {
- gf_msg_trace (this->name, 0,
- "incomplete layout failure for path=%s",
- loc->path);
-
- gen = layout->gen;
- dht_layout_unref (this, local->layout);
- local->layout = NULL;
- local->cached_subvol = NULL;
-
- gf_msg_debug(this->name, 0,
- "Called revalidate lookup for %s, "
- "but layout->gen (%d) is less than "
- "conf->gen (%d), calling fresh_lookup",
- loc->path, gen, conf->gen);
-
- goto do_fresh_lookup;
- }
-
- local->inode = inode_ref (loc->inode);
-
- ret = dict_set_uint32 (local->xattr_req,
- conf->xattr_name, 4 * 4);
- if (ret) {
- gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
- DHT_MSG_DICT_SET_FAILED,
- "Failed to set dictionary value:key = %s for "
- "path %s", conf->xattr_name, loc->path);
- goto err;
- }
-
- /* need it in case file is not found on cached file
- * on revalidate path and we may encounter linkto files on
- * with dht_lookup_everywhere*/
- ret = dict_set_uint32 (local->xattr_req,
- conf->link_xattr_name, 256);
- if (ret < 0) {
- gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
- DHT_MSG_DICT_SET_FAILED,
- "Failed to set dictionary value:key = %s for "
- "path %s", conf->link_xattr_name, loc->path);
- goto err;
- }
- if (IA_ISDIR (local->inode->ia_type)) {
- ret = dht_inode_ctx_mdsvol_get (local->inode, this,
- &mds_subvol);
- if (ret || !mds_subvol) {
- gf_msg_debug (this->name, 0,
- "Failed to get mds subvol for path %s",
- local->loc.path);
- }
- local->mds_subvol = mds_subvol;
- local->call_cnt = call_cnt = conf->subvolume_cnt;
- for (i = 0; i < call_cnt; i++) {
- STACK_WIND_COOKIE (frame, dht_revalidate_cbk,
- conf->subvolumes[i],
- conf->subvolumes[i],
- conf->subvolumes[i]->fops->lookup,
- loc, local->xattr_req);
- }
- return 0;
- }
-
- call_cnt = local->call_cnt = layout->cnt;
-
- /* need it for self-healing linkfiles which is
- 'in-migration' state */
- ret = dict_set_uint32 (local->xattr_req,
- GLUSTERFS_OPEN_FD_COUNT, 4);
- if (ret) {
- gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
- DHT_MSG_DICT_SET_FAILED,
- "Failed to set dictionary value:key = %s for "
- "path %s", GLUSTERFS_OPEN_FD_COUNT, loc->path);
- goto err;
- }
- /* need it for dir self-heal */
- dht_check_and_set_acl_xattr_req (loc->inode, local->xattr_req);
-
- for (i = 0; i < call_cnt; i++) {
- subvol = layout->list[i].xlator;
-
- gf_msg_debug (this->name, 0, "calling "
- "revalidate lookup for %s at %s",
- loc->path, subvol->name);
-
- STACK_WIND_COOKIE (frame, dht_revalidate_cbk, subvol,
- subvol, subvol->fops->lookup,
- &local->loc, local->xattr_req);
-
- }
- } else {
- do_fresh_lookup:
- /* TODO: remove the hard-coding */
- ret = dict_set_uint32 (local->xattr_req,
- conf->xattr_name, 4 * 4);
- if (ret) {
- gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
- DHT_MSG_DICT_SET_FAILED,
- "Failed to set dictionary value:key = %s for "
- "path %s", conf->xattr_name, loc->path);
- goto err;
- }
-
- ret = dict_set_uint32 (local->xattr_req,
- conf->link_xattr_name, 256);
- if (ret) {
- gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
- DHT_MSG_DICT_SET_FAILED,
- "Failed to set dictionary value:key = %s for "
- "path %s", conf->link_xattr_name, loc->path);
- goto err;
- }
- /* need it for self-healing linkfiles which is
- 'in-migration' state */
- ret = dict_set_uint32 (local->xattr_req,
- GLUSTERFS_OPEN_FD_COUNT, 4);
- if (ret) {
- gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
- DHT_MSG_DICT_SET_FAILED,
- "Failed to set dictionary value:key = %s for "
- "path %s", GLUSTERFS_OPEN_FD_COUNT, loc->path);
- goto err;
- }
- /* need it for dir self-heal */
- dht_check_and_set_acl_xattr_req (loc->inode, local->xattr_req);
-
- if (!hashed_subvol) {
-
- gf_msg_debug (this->name, 0,
- "no subvolume in layout for path=%s, "
- "checking on all the subvols to see if "
- "it is a directory", loc->path);
-
- call_cnt = conf->subvolume_cnt;
- local->call_cnt = call_cnt;
-
- local->layout = dht_layout_new (this,
- conf->subvolume_cnt);
- if (!local->layout) {
- op_errno = ENOMEM;
- goto err;
- }
-
- gf_msg_debug (this->name, 0,
- "Found null hashed subvol. Calling lookup"
- " on all nodes.");
-
- for (i = 0; i < call_cnt; i++) {
- STACK_WIND_COOKIE (frame, dht_lookup_dir_cbk,
- conf->subvolumes[i],
- conf->subvolumes[i],
- conf->subvolumes[i]->fops->lookup,
- &local->loc, local->xattr_req);
- }
- return 0;
- }
-
- gf_msg_debug (this->name, 0, "Calling fresh lookup for %s on"
- " %s", loc->path, hashed_subvol->name);
-
- STACK_WIND_COOKIE (frame, dht_lookup_cbk, hashed_subvol,
- hashed_subvol, hashed_subvol->fops->lookup,
- loc, local->xattr_req);
+ dht_do_revalidate (frame, this, loc);
+ return 0;
+ } else {
+ dht_do_fresh_lookup (frame, this, loc);
+ return 0;
}
return 0;
-
err:
op_errno = (op_errno == -1) ? errno : op_errno;
DHT_STACK_UNWIND (lookup, frame, -1, op_errno, NULL, NULL, NULL,