summaryrefslogtreecommitdiffstats
path: root/xlators/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/protocol')
-rw-r--r--xlators/protocol/auth/addr/src/addr.c227
-rw-r--r--xlators/protocol/client/src/client-handshake.c21
-rw-r--r--xlators/protocol/server/src/server-common.c68
-rw-r--r--xlators/protocol/server/src/server-common.h6
-rw-r--r--xlators/protocol/server/src/server-handshake.c180
-rw-r--r--xlators/protocol/server/src/server-helpers.c10
-rw-r--r--xlators/protocol/server/src/server-rpc-fops.c107
-rw-r--r--xlators/protocol/server/src/server.c1
-rw-r--r--xlators/protocol/server/src/server.h3
9 files changed, 436 insertions, 187 deletions
diff --git a/xlators/protocol/auth/addr/src/addr.c b/xlators/protocol/auth/addr/src/addr.c
index cafcf28..3e62d05 100644
--- a/xlators/protocol/auth/addr/src/addr.c
+++ b/xlators/protocol/auth/addr/src/addr.c
@@ -16,13 +16,151 @@
#include "dict.h"
#include "rpc-transport.h"
-#define ADDR_DELIMITER " ,"
+#define ENTRY_DELIMITER ","
+#define ADDR_DELIMITER "|"
#define PRIVILEGED_PORT_CEILING 1024
#ifndef AF_INET_SDP
#define AF_INET_SDP 27
#endif
+/* An option for subdir validation be like below */
+
+/* 1. '*'
+ 2. '192.168.*'
+ 3. '
+ 4. '!10.10.1*' (Today as per the code, if negate is set on one entry, its never reset)
+ 5. '192.168.1.*, 10.1.10.*';168.168.2.* =/dir;* =/another-dir'
+
+*/
+
+int
+compare_addr_and_update (char *option_str, char *peer_addr, char *subvol,
+ char *delimiter,
+ auth_result_t *result, auth_result_t status)
+{
+ char *addr_str = NULL;
+ char *tmp = NULL;
+ char negate = 0;
+ char match = 0;
+ int length = 0;
+ int ret = 0;
+
+ addr_str = strtok_r (option_str, delimiter, &tmp);
+
+ while (addr_str) {
+ gf_log (subvol, GF_LOG_INFO,
+ "%s = \"%s\", received addr = \"%s\"",
+ (status == AUTH_ACCEPT) ? "allowed" : "rejected",
+ addr_str, peer_addr);
+ if (addr_str[0] == '!') {
+ negate = 1;
+ addr_str++;
+ }
+
+ length = strlen(addr_str);
+ if ((addr_str[0] != '*') &&
+ valid_host_name (addr_str, length)) {
+ match = gf_is_same_address(addr_str, peer_addr);
+ if (match) {
+ *result = status;
+ goto out;
+ }
+ } else {
+ match = fnmatch (addr_str, peer_addr, 0);
+ if (negate ? match : !match) {
+ *result = status;
+ goto out;
+ }
+ }
+
+ addr_str = strtok_r (NULL, delimiter, &tmp);
+ }
+
+ ret = -1;
+out:
+ return ret;
+}
+
+
+void
+parse_entries_and_compare (char *option_str, char *peer_addr, char *subvol,
+ char *subdir, auth_result_t *result, auth_result_t status)
+{
+ char *entry = NULL;
+ char *entry_cpy = NULL;
+ char *directory = NULL;
+ char *entries = NULL;
+ char *addr_str = NULL;
+ char *addr = NULL;
+ char *tmp = NULL;
+ char *tmpdir = NULL;
+ int ret = 0;
+
+ if (!subdir) {
+ gf_log (subvol, GF_LOG_WARNING,
+ "subdir entry not present, not performing any operation.");
+ goto out;
+ }
+
+ entries = gf_strdup (option_str);
+ if (!entries)
+ goto out;
+
+ if (entries[0] != '/' && !strchr (entries, '(')) {
+ /* Backward compatible option */
+ ret = compare_addr_and_update (entries, peer_addr, subvol,
+ ",", result, status);
+ goto out;
+ }
+
+ entry = strtok_r (entries, ENTRY_DELIMITER, &tmp);
+ while (entry) {
+ entry_cpy = gf_strdup (entry);
+ if (!entry_cpy) {
+ goto out;
+ }
+
+ directory = strtok_r (entry_cpy, "(", &tmpdir);
+ if (directory[0] != '/')
+ goto out;
+
+ /* send second portion, after ' =' if directory matches */
+ if (strcmp (subdir, directory))
+ goto next_entry;
+
+ addr_str = strtok_r (NULL, ")", &tmpdir);
+ if (!addr_str)
+ goto out;
+
+ addr = gf_strdup (addr_str);
+ if (!addr)
+ goto out;
+
+ gf_log (subvol, GF_LOG_INFO, "Found an entry for dir %s (%s),"
+ " performing validation", subdir, addr);
+
+ ret = compare_addr_and_update (addr, peer_addr, subvol,
+ ADDR_DELIMITER, result, status);
+ if (ret == 0) {
+ break;
+ }
+
+ GF_FREE (addr);
+ addr = NULL;
+
+ next_entry:
+ entry = strtok_r (NULL, ENTRY_DELIMITER, &tmp);
+ GF_FREE (entry_cpy);
+ entry_cpy = NULL;
+ }
+
+out:
+ GF_FREE (entries);
+ GF_FREE (entry_cpy);
+ GF_FREE (addr);
+}
+
auth_result_t
gf_auth (dict_t *input_params, dict_t *config_params)
{
@@ -34,17 +172,12 @@ gf_auth (dict_t *input_params, dict_t *config_params)
data_t *peer_info_data = NULL;
data_t *allow_addr = NULL;
data_t *reject_addr = NULL;
- char *addr_str = NULL;
- char *tmp = NULL;
- char *addr_cpy = NULL;
char *service = NULL;
uint16_t peer_port = 0;
- char negate = 0;
- char match = 0;
char peer_addr[UNIX_PATH_MAX] = {0,};
char *type = NULL;
gf_boolean_t allow_insecure = _gf_false;
- int length = 0;
+ char *subdir = NULL;
name = data_to_str (dict_get (input_params, "remote-subvolume"));
if (!name) {
@@ -99,6 +232,12 @@ gf_auth (dict_t *input_params, dict_t *config_params)
goto out;
}
+
+ ret = dict_get_str (input_params, "subdir-mount", &subdir);
+ if (ret) {
+ subdir = "/";
+ }
+
peer_info = data_to_ptr (peer_info_data);
switch (((struct sockaddr *) &peer_info->sockaddr)->sa_family) {
@@ -144,82 +283,18 @@ gf_auth (dict_t *input_params, dict_t *config_params)
}
if (reject_addr) {
- addr_cpy = gf_strdup (reject_addr->data);
- if (!addr_cpy)
+ parse_entries_and_compare (reject_addr->data, peer_addr, name,
+ subdir, &result, AUTH_REJECT);
+ if (result == AUTH_REJECT)
goto out;
-
- addr_str = strtok_r (addr_cpy, ADDR_DELIMITER, &tmp);
-
- while (addr_str) {
- gf_log (name, GF_LOG_DEBUG,
- "rejected = \"%s\", received addr = \"%s\"",
- addr_str, peer_addr);
- if (addr_str[0] == '!') {
- negate = 1;
- addr_str++;
- }
-
- length = strlen(addr_str);
- if ((addr_str[0] != '*') &&
- valid_host_name (addr_str, length)) {
- match = gf_is_same_address(addr_str, peer_addr);
- if (match) {
- result = AUTH_REJECT;
- goto out;
- }
- } else {
- match = fnmatch (addr_str, peer_addr, 0);
- if (negate ? match : !match) {
- result = AUTH_REJECT;
- goto out;
- }
- }
-
- addr_str = strtok_r (NULL, ADDR_DELIMITER, &tmp);
- }
- GF_FREE (addr_cpy);
- addr_cpy = NULL;
}
if (allow_addr) {
- addr_cpy = gf_strdup (allow_addr->data);
- if (!addr_cpy)
- goto out;
-
- addr_str = strtok_r (addr_cpy, ADDR_DELIMITER, &tmp);
-
- while (addr_str) {
- gf_log (name, GF_LOG_INFO,
- "allowed = \"%s\", received addr = \"%s\"",
- addr_str, peer_addr);
- if (addr_str[0] == '!') {
- negate = 1;
- addr_str++;
- }
-
- length = strlen(addr_str);
- if ((addr_str[0] != '*') &&
- valid_host_name (addr_str, length)) {
- match = gf_is_same_address(addr_str, peer_addr);
- if (match) {
- result = AUTH_ACCEPT;
- goto out;
- }
- } else {
- match = fnmatch (addr_str, peer_addr, 0);
- if (negate ? match : !match) {
- result = AUTH_ACCEPT;
- goto out;
- }
- }
-
- addr_str = strtok_r (NULL, ADDR_DELIMITER, &tmp);
- }
+ parse_entries_and_compare (allow_addr->data, peer_addr, name,
+ subdir, &result, AUTH_ACCEPT);
}
out:
- GF_FREE (addr_cpy);
-
return result;
}
diff --git a/xlators/protocol/client/src/client-handshake.c b/xlators/protocol/client/src/client-handshake.c
index a36f6e4..b6dc079 100644
--- a/xlators/protocol/client/src/client-handshake.c
+++ b/xlators/protocol/client/src/client-handshake.c
@@ -1137,13 +1137,20 @@ client_setvolume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *m
if (op_ret < 0) {
gf_msg (this->name, GF_LOG_ERROR, op_errno,
PC_MSG_SETVOLUME_FAIL,
- "SETVOLUME on remote-host failed");
+ "SETVOLUME on remote-host failed: %s", remote_error);
+
errno = op_errno;
if (remote_error &&
(strcmp ("Authentication failed", remote_error) == 0)) {
auth_fail = _gf_true;
op_ret = 0;
}
+ if ((op_errno == ENOENT) && this->ctx->cmd_args.subdir_mount) {
+ /* A case of subdir not being present at the moment,
+ ride on auth_fail framework to notify the error */
+ auth_fail = _gf_true;
+ op_ret = 0;
+ }
if (op_errno == ESTALE) {
ret = client_notify_dispatch (this,
GF_EVENT_VOLFILE_MODIFIED,
@@ -1377,6 +1384,18 @@ client_setvolume (xlator_t *this, struct rpc_clnt *rpc)
"'volfile-checksum'");
}
+ if (this->ctx->cmd_args.subdir_mount) {
+ ret = dict_set_str (options, "subdir-mount",
+ this->ctx->cmd_args.subdir_mount);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Failed to set subdir_mount");
+ /* It makes sense to fail, as per the CLI, we
+ should be doing a subdir_mount */
+ goto fail;
+ }
+ }
+
ret = dict_set_int16 (options, "clnt-lk-version",
client_get_lk_ver (conf));
if (ret < 0) {
diff --git a/xlators/protocol/server/src/server-common.c b/xlators/protocol/server/src/server-common.c
index 1dc3a9c..b972918 100644
--- a/xlators/protocol/server/src/server-common.c
+++ b/xlators/protocol/server/src/server-common.c
@@ -10,8 +10,24 @@
#include "xdr-nfs3.h"
void
-server_post_stat (gfs3_stat_rsp *rsp, struct iatt *stbuf)
+server_post_stat (server_state_t *state, gfs3_stat_rsp *rsp, struct iatt *stbuf)
{
+ if (state->client->subdir_mount) {
+ if (gf_uuid_compare (stbuf->ia_gfid,
+ state->client->subdir_gfid)) {
+ /* This is very important as when we send iatt of
+ root-inode, fuse/client expect the gfid to be 1,
+ along with inode number. As for subdirectory mount,
+ we use inode table which is shared by everyone, but
+ make sure we send fops only from subdir and below,
+ we have to alter inode gfid and send it to client */
+ uuid_t gfid = {0,};
+
+ gfid[15] = 1;
+ stbuf->ia_ino = 1;
+ gf_uuid_copy (stbuf->ia_gfid, gfid);
+ }
+ }
gf_stat_from_iatt (&rsp->stat, stbuf);
}
@@ -166,8 +182,25 @@ server_post_ftruncate (gfs3_ftruncate_rsp *rsp, struct iatt *prebuf,
}
void
-server_post_fstat (gfs3_fstat_rsp *rsp, struct iatt *stbuf)
+server_post_fstat (server_state_t *state, gfs3_fstat_rsp *rsp,
+ struct iatt *stbuf)
{
+ if (state->client->subdir_mount) {
+ if (gf_uuid_compare (stbuf->ia_gfid,
+ state->client->subdir_gfid)) {
+ /* This is very important as when we send iatt of
+ root-inode, fuse/client expect the gfid to be 1,
+ along with inode number. As for subdirectory mount,
+ we use inode table which is shared by everyone, but
+ make sure we send fops only from subdir and below,
+ we have to alter inode gfid and send it to client */
+ uuid_t gfid = {0,};
+
+ gfid[15] = 1;
+ stbuf->ia_ino = 1;
+ gf_uuid_copy (stbuf->ia_gfid, gfid);
+ }
+ }
gf_stat_from_iatt (&rsp->stat, stbuf);
}
@@ -444,17 +477,6 @@ server_post_lookup (gfs3_lookup_rsp *rsp, call_frame_t *frame,
root_inode = frame->root->client->bound_xl->itable->root;
- if (inode == root_inode) {
- /* we just looked up root ("/") */
- stbuf->ia_ino = 1;
- rootgfid[15] = 1;
- gf_uuid_copy (stbuf->ia_gfid, rootgfid);
- if (inode->ia_type == 0)
- inode->ia_type = stbuf->ia_type;
- }
-
- gf_stat_from_iatt (&rsp->stat, stbuf);
-
if (!__is_root_gfid (inode->gfid)) {
link_inode = inode_link (inode, state->loc.parent,
state->loc.name, stbuf);
@@ -463,6 +485,26 @@ server_post_lookup (gfs3_lookup_rsp *rsp, call_frame_t *frame,
inode_unref (link_inode);
}
}
+
+ if ((inode == root_inode) ||
+ (state->client->subdir_mount &&
+ (inode == state->client->subdir_inode))) {
+ /* we just looked up root ("/") OR
+ subdir mount directory, which is root ('/') in client */
+ /* This is very important as when we send iatt of
+ root-inode, fuse/client expect the gfid to be 1,
+ along with inode number. As for subdirectory mount,
+ we use inode table which is shared by everyone, but
+ make sure we send fops only from subdir and below,
+ we have to alter inode gfid and send it to client */
+ stbuf->ia_ino = 1;
+ rootgfid[15] = 1;
+ gf_uuid_copy (stbuf->ia_gfid, rootgfid);
+ if (inode->ia_type == 0)
+ inode->ia_type = stbuf->ia_type;
+ }
+
+ gf_stat_from_iatt (&rsp->stat, stbuf);
}
void
diff --git a/xlators/protocol/server/src/server-common.h b/xlators/protocol/server/src/server-common.h
index f3b9ced..3fa972e 100644
--- a/xlators/protocol/server/src/server-common.h
+++ b/xlators/protocol/server/src/server-common.h
@@ -9,7 +9,8 @@
#include "xdr-nfs3.h"
void
-server_post_stat (gfs3_stat_rsp *rsp, struct iatt *stbuf);
+server_post_stat (server_state_t *state,
+ gfs3_stat_rsp *rsp, struct iatt *stbuf);
void
server_post_readlink (gfs3_readlink_rsp *rsp, struct iatt *stbuf,
@@ -61,7 +62,8 @@ server_post_ftruncate (gfs3_ftruncate_rsp *rsp, struct iatt *prebuf,
struct iatt *postbuf);
void
-server_post_fstat (gfs3_fstat_rsp *rsp, struct iatt *stbuf);
+server_post_fstat (server_state_t *state,
+ gfs3_fstat_rsp *rsp, struct iatt *stbuf);
void
server_post_lk (xlator_t *this, gfs3_lk_rsp *rsp, struct gf_flock *lock);
diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c
index f8f8f99..fa2f613 100644
--- a/xlators/protocol/server/src/server-handshake.c
+++ b/xlators/protocol/server/src/server-handshake.c
@@ -19,6 +19,7 @@
#include "server-messages.h"
#include "syscall.h"
#include "events.h"
+#include "syncop.h"
struct __get_xl_struct {
const char *name;
@@ -303,7 +304,7 @@ fail:
return 0;
}
-void
+static void
server_first_lookup_done (rpcsvc_request_t *req, gf_setvolume_rsp *rsp) {
server_submit_reply (NULL, req, rsp, NULL, 0, NULL,
@@ -313,41 +314,64 @@ server_first_lookup_done (rpcsvc_request_t *req, gf_setvolume_rsp *rsp) {
GF_FREE (rsp);
}
-
-int
-server_first_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno,
- inode_t *inode, struct iatt *buf, dict_t *xattr,
- struct iatt *postparent)
+static inode_t *
+do_path_lookup (xlator_t *xl, dict_t *dict, inode_t *parinode, char *basename)
{
- rpcsvc_request_t *req = NULL;
- gf_setvolume_rsp *rsp = NULL;
+ int ret = 0;
+ loc_t loc = {0,};
+ uuid_t gfid = {0,};
+ struct iatt iatt = {0,};
+ inode_t *inode = NULL;
+
+ loc.parent = parinode;
+ loc_touchup (&loc, basename);
+ loc.inode = inode_new (xl->itable);
+
+ gf_uuid_generate (gfid);
+ ret = dict_set_static_bin (dict, "gfid-req", gfid, 16);
+ if (ret) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "failed to set 'gfid-req' for subdir");
+ goto out;
+ }
- req = cookie;
- rsp = frame->local;
- frame->local = NULL;
+ ret = syncop_lookup (xl, &loc, &iatt, NULL, dict, NULL);
+ if (ret < 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "first lookup on subdir (%s) failed: %s",
+ basename, strerror (errno));
+ }
- if (op_ret < 0 || buf == NULL)
- gf_log (this->name, GF_LOG_WARNING, "server first lookup failed"
- " on root inode: %s", strerror (op_errno));
- /* Ignore error from lookup, don't set
- * failure in rsp->op_ret. lookup on a snapview-server
- * can fail with ESTALE
- */
- server_first_lookup_done (req, rsp);
+ /* Inode linking is required so that the
+ resolution happens all fine for future fops */
+ inode = inode_link (loc.inode, loc.parent, loc.name, &iatt);
- STACK_DESTROY (frame->root);
+ /* Extra ref so the pointer is valid till client is valid */
+ /* FIXME: not a priority, but this can lead to some inode
+ leaks if subdir is more than 1 level depth. Leak is only
+ per subdir entry, and not dependent on number of
+ connections, so it should be fine for now */
+ inode_ref (inode);
- return 0;
+out:
+ return inode;
}
int
-server_first_lookup (xlator_t *this, xlator_t *xl, rpcsvc_request_t *req,
- gf_setvolume_rsp *rsp)
+server_first_lookup (xlator_t *this, client_t *client, dict_t *reply)
{
- call_frame_t *frame = NULL;
loc_t loc = {0, };
+ struct iatt iatt = {0,};
+ dict_t *dict = NULL;
+ int ret = 0;
+ xlator_t *xl = client->bound_xl;
+ char *msg = NULL;
+ inode_t *inode = NULL;
+ char *bname = NULL;
+ char *str = NULL;
+ char *tmp = NULL;
+ char *saveptr = NULL;
loc.path = "/";
loc.name = "";
@@ -355,31 +379,67 @@ server_first_lookup (xlator_t *this, xlator_t *xl, rpcsvc_request_t *req,
loc.parent = NULL;
gf_uuid_copy (loc.gfid, loc.inode->gfid);
- frame = create_frame (this, this->ctx->pool);
- if (!frame) {
- gf_log ("fuse", GF_LOG_ERROR, "failed to create frame");
- goto err;
+ ret = syncop_lookup (xl, &loc, &iatt, NULL, NULL, NULL);
+ if (ret < 0)
+ gf_log (xl->name, GF_LOG_ERROR, "lookup on root failed: %s",
+ strerror (errno));
+ /* Ignore error from lookup, don't set
+ * failure in rsp->op_ret. lookup on a snapview-server
+ * can fail with ESTALE
+ */
+ /* TODO-SUBDIR-MOUNT: validate above comment with respect to subdir lookup */
+
+ if (client->subdir_mount) {
+ str = tmp = gf_strdup (client->subdir_mount);
+ dict = dict_new ();
+ inode = xl->itable->root;
+ bname = strtok_r (str, "/", &saveptr);
+ while (bname != NULL) {
+ inode = do_path_lookup (xl, dict, inode, bname);
+ if (inode == NULL) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "first lookup on subdir (%s) failed: %s",
+ client->subdir_mount, strerror (errno));
+ ret = -1;
+ goto fail;
+ }
+ bname = strtok_r (NULL, "/", &saveptr);
+ }
+
+ /* Can be used in server_resolve() */
+ gf_uuid_copy (client->subdir_gfid, inode->gfid);
+ client->subdir_inode = inode;
}
- frame->local = (void *)rsp;
- frame->root->uid = frame->root->gid = 0;
- frame->root->pid = -1;
- frame->root->type = GF_OP_TYPE_FOP;
+ ret = 0;
+ goto out;
- STACK_WIND_COOKIE (frame, server_first_lookup_cbk, (void *)req, xl,
- xl->fops->lookup, &loc, NULL);
+fail:
+ /* we should say to client, it is not possible
+ to connect */
+ ret = gf_asprintf (&msg, "subdirectory for mount \"%s\" is not found",
+ client->subdir_mount);
+ if (-1 == ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ PS_MSG_ASPRINTF_FAILED,
+ "asprintf failed while setting error msg");
+ }
+ ret = dict_set_dynstr (reply, "ERROR", msg);
+ if (ret < 0)
+ gf_msg_debug (this->name, 0, "failed to set error "
+ "msg");
- return 0;
+ ret = -1;
+out:
+ if (dict)
+ dict_unref (dict);
-err:
- rsp->op_ret = -1;
- rsp->op_errno = ENOMEM;
- server_first_lookup_done (req, rsp);
+ inode_unref (loc.inode);
- frame->local = NULL;
- STACK_DESTROY (frame->root);
+ if (tmp)
+ GF_FREE (tmp);
- return -1;
+ return ret;
}
int
@@ -414,6 +474,7 @@ server_setvolume (rpcsvc_request_t *req)
int32_t mgmt_version = 0;
glusterfs_ctx_t *ctx = NULL;
struct _child_status *tmp = NULL;
+ char *subdir_mount = NULL;
params = dict_new ();
reply = dict_new ();
@@ -544,6 +605,11 @@ server_setvolume (rpcsvc_request_t *req)
goto fail;
}
+ ret = dict_get_str (params, "subdir-mount", &subdir_mount);
+ if (ret < 0) {
+ /* Not a problem at all as the key is optional */
+ }
+
/*lk_verion :: [1..2^31-1]*/
ret = dict_get_uint32 (params, "clnt-lk-version", &lk_version);
if (ret < 0) {
@@ -558,7 +624,7 @@ server_setvolume (rpcsvc_request_t *req)
goto fail;
}
- client = gf_client_get (this, &req->cred, client_uid);
+ client = gf_client_get (this, &req->cred, client_uid, subdir_mount);
if (client == NULL) {
op_ret = -1;
op_errno = ENOMEM;
@@ -713,14 +779,18 @@ server_setvolume (rpcsvc_request_t *req)
gf_event (EVENT_CLIENT_CONNECT, "client_uid=%s;"
"client_identifier=%s;server_identifier=%s;"
- "brick_path=%s",
+ "brick_path=%s,subdir_mount=%s",
client->client_uid,
req->trans->peerinfo.identifier,
req->trans->myinfo.identifier,
- name);
+ name, subdir_mount);
op_ret = 0;
client->bound_xl = xl;
+
+ /* Don't be confused by the below line (like how ERROR can
+ be Success), key checked on client is 'ERROR' and hence
+ we send 'Success' in this key */
ret = dict_set_str (reply, "ERROR", "Success");
if (ret < 0)
gf_msg_debug (this->name, 0, "failed to set error "
@@ -796,6 +866,16 @@ server_setvolume (rpcsvc_request_t *req)
gf_msg_debug (this->name, 0, "failed to set 'transport-ptr'");
fail:
+ /* It is important to validate the lookup on '/' as part of handshake,
+ because if lookup itself can't succeed, we should communicate this
+ to client. Very important in case of subdirectory mounts, where if
+ client is trying to mount a non-existing directory */
+ if (op_ret >= 0 && client->bound_xl->itable) {
+ op_ret = server_first_lookup (this, client, reply);
+ if (op_ret == -1)
+ op_errno = ENOENT;
+ }
+
rsp = GF_CALLOC (1, sizeof (gf_setvolume_rsp),
gf_server_mt_setvolume_rsp_t);
GF_ASSERT (rsp);
@@ -842,10 +922,8 @@ fail:
req->trans->xl_private = NULL;
}
- if (op_ret >= 0 && client->bound_xl->itable)
- server_first_lookup (this, client->bound_xl, req, rsp);
- else
- server_first_lookup_done (req, rsp);
+ /* Send the response properly */
+ server_first_lookup_done (req, rsp);
free (args.dict.dict_val);
@@ -904,7 +982,7 @@ server_set_lk_version (rpcsvc_request_t *req)
goto fail;
}
- client = gf_client_get (this, &req->cred, args.uid);
+ client = gf_client_get (this, &req->cred, args.uid, NULL);
serv_ctx = server_ctx_get (client, client->this);
if (serv_ctx == NULL) {
gf_msg (this->name, GF_LOG_INFO, 0,
diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c
index 52d7f51..381fb6f 100644
--- a/xlators/protocol/server/src/server-helpers.c
+++ b/xlators/protocol/server/src/server-helpers.c
@@ -423,6 +423,7 @@ get_frame_from_request (rpcsvc_request_t *req)
clienttable_t *clienttable = NULL;
unsigned int i = 0;
rpc_transport_t *trans = NULL;
+ server_state_t *state = NULL;
GF_VALIDATE_OR_GOTO ("server", req, out);
@@ -507,6 +508,9 @@ get_frame_from_request (rpcsvc_request_t *req)
frame->local = req;
+
+ state = CALL_STATE (frame);
+ state->client = client;
out:
return frame;
}
@@ -2225,7 +2229,7 @@ server_populate_compound_response (xlator_t *this, gfs3_compound_rsp *rsp,
rsp_args->xdata.xdata_len,
rsp_args->op_errno, out);
if (!this_args_cbk->op_ret) {
- server_post_stat (rsp_args,
+ server_post_stat (state, rsp_args,
&this_args_cbk->stat);
}
rsp_args->op_ret = this_args_cbk->op_ret;
@@ -2728,8 +2732,8 @@ server_populate_compound_response (xlator_t *this, gfs3_compound_rsp *rsp,
rsp_args->xdata.xdata_len,
rsp_args->op_errno, out);
if (!this_args_cbk->op_ret) {
- server_post_fstat (rsp_args,
- &this_args_cbk->stat);
+ server_post_fstat (state, rsp_args,
+ &this_args_cbk->stat);
}
rsp_args->op_ret = this_args_cbk->op_ret;
rsp_args->op_errno = gf_errno_to_error
diff --git a/xlators/protocol/server/src/server-rpc-fops.c b/xlators/protocol/server/src/server-rpc-fops.c
index ba5543f..c947f06 100644
--- a/xlators/protocol/server/src/server-rpc-fops.c
+++ b/xlators/protocol/server/src/server-rpc-fops.c
@@ -45,6 +45,18 @@ forget_inode_if_no_dentry (inode_t *inode)
return;
}
+static void
+set_resolve_gfid (client_t *client, uuid_t resolve_gfid,
+ char *on_wire_gfid)
+{
+ if (client->subdir_mount &&
+ __is_root_gfid ((unsigned char *)on_wire_gfid)) {
+ /* set the subdir_mount's gfid for proper resolution */
+ gf_uuid_copy (resolve_gfid, client->subdir_gfid);
+ } else {
+ memcpy (resolve_gfid, on_wire_gfid, 16);
+ }
+}
/* Callback function section */
int
@@ -1230,8 +1242,8 @@ server_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val,
rsp.xdata.xdata_len, op_errno, out);
+ state = CALL_STATE (frame);
if (op_ret) {
- state = CALL_STATE (frame);
gf_msg (this->name, fop_log_level (GF_FOP_FSTAT, op_errno),
op_errno, PS_MSG_STAT_INFO,
"%"PRId64": FSTAT %"PRId64" (%s), client: %s, "
@@ -1242,7 +1254,7 @@ server_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto out;
}
- server_post_fstat (&rsp, stbuf);
+ server_post_fstat (state, &rsp, stbuf);
out:
rsp.op_ret = op_ret;
@@ -1647,8 +1659,8 @@ server_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val,
rsp.xdata.xdata_len, op_errno, out);
+ state = CALL_STATE (frame);
if (op_ret) {
- state = CALL_STATE (frame);
gf_msg (this->name, fop_log_level (GF_FOP_STAT, op_errno),
op_errno, PS_MSG_STAT_INFO,
"%"PRId64": STAT %s (%s), client: %s, error-xlator: %s",
@@ -1660,7 +1672,7 @@ server_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto out;
}
- server_post_stat (&rsp, stbuf);
+ server_post_stat (state, &rsp, stbuf);
out:
rsp.op_ret = op_ret;
rsp.op_errno = gf_errno_to_error (op_errno);
@@ -3476,7 +3488,7 @@ server3_3_stat (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -3534,7 +3546,7 @@ server3_3_setattr (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
gf_stat_to_iatt (&args.stbuf, &state->stbuf);
state->valid = args.valid;
@@ -4017,7 +4029,9 @@ server3_3_create (rpcsvc_request_t *req)
state->mode = args.mode;
state->umask = args.umask;
state->flags = gf_flags_to_flags (args.flags);
- memcpy (state->resolve.pargfid, args.pargfid, 16);
+
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.pargfid);
if (state->flags & O_EXCL) {
state->resolve.type = RESOLVE_NOT;
@@ -4604,7 +4618,7 @@ server3_3_fstat (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -4721,7 +4735,9 @@ server3_3_unlink (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.bname = gf_strdup (args.bname);
- memcpy (state->resolve.pargfid, args.pargfid, 16);
+
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.pargfid);
state->flags = args.xflags;
@@ -4783,7 +4799,7 @@ server3_3_setxattr (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->flags = args.flags;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
dict,
@@ -4862,7 +4878,7 @@ server3_3_fsetxattr (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
state->flags = args.flags;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
dict,
@@ -4938,7 +4954,7 @@ server3_3_fxattrop (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
state->flags = args.flags;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
dict,
@@ -5014,7 +5030,7 @@ server3_3_xattrop (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->flags = args.flags;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
dict,
@@ -5087,7 +5103,7 @@ server3_3_getxattr (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
if (args.namelen) {
state->name = gf_strdup (args.name);
@@ -5151,8 +5167,7 @@ server3_3_fgetxattr (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
- memcpy (state->resolve.gfid, args.gfid, 16);
-
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
if (args.namelen)
state->name = gf_strdup (args.name);
@@ -5213,7 +5228,7 @@ server3_3_removexattr (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
state->name = gf_strdup (args.name);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
@@ -5272,7 +5287,7 @@ server3_3_fremovexattr (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
state->name = gf_strdup (args.name);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
@@ -5331,7 +5346,7 @@ server3_3_opendir (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -5401,7 +5416,7 @@ server3_3_readdirp (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
state->offset = args.offset;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
/* here, dict itself works as xdata */
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
@@ -5472,7 +5487,7 @@ server3_3_readdir (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
state->offset = args.offset;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -5529,7 +5544,7 @@ server3_3_fsyncdir (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.fd_no = args.fd;
state->flags = args.data;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -5588,7 +5603,9 @@ server3_3_mknod (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_NOT;
- memcpy (state->resolve.pargfid, args.pargfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.pargfid);
+
state->resolve.bname = gf_strdup (args.bname);
state->mode = args.mode;
@@ -5654,7 +5671,8 @@ server3_3_mkdir (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_NOT;
- memcpy (state->resolve.pargfid, args.pargfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.pargfid);
state->resolve.bname = gf_strdup (args.bname);
state->mode = args.mode;
@@ -5718,7 +5736,8 @@ server3_3_rmdir (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.pargfid, args.pargfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.pargfid);
state->resolve.bname = gf_strdup (args.bname);
state->flags = args.xflags;
@@ -5781,7 +5800,7 @@ server3_3_inodelk (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_EXACT;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
cmd = args.cmd;
switch (cmd) {
@@ -5872,7 +5891,7 @@ server3_3_finodelk (rpcsvc_request_t *req)
state->volume = gf_strdup (args.volume);
state->resolve.fd_no = args.fd;
state->cmd = args.cmd;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
switch (state->cmd) {
case GF_LK_GETLK:
@@ -5961,7 +5980,7 @@ server3_3_entrylk (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_EXACT;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
if (args.namelen)
state->name = gf_strdup (args.name);
@@ -6029,7 +6048,7 @@ server3_3_fentrylk (rpcsvc_request_t *req)
state->resolve.fd_no = args.fd;
state->cmd = args.cmd;
state->type = args.type;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
if (args.namelen)
state->name = gf_strdup (args.name);
@@ -6088,7 +6107,7 @@ server3_3_access (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
state->mask = args.mask;
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
@@ -6149,7 +6168,8 @@ server3_3_symlink (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_NOT;
- memcpy (state->resolve.pargfid, args.pargfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.pargfid);
state->resolve.bname = gf_strdup (args.bname);
state->name = gf_strdup (args.linkname);
state->umask = args.umask;
@@ -6216,7 +6236,8 @@ server3_3_link (rpcsvc_request_t *req)
state->resolve2.type = RESOLVE_NOT;
state->resolve2.bname = gf_strdup (args.newbname);
- memcpy (state->resolve2.pargfid, args.newgfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve2.pargfid,
+ args.newgfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -6276,11 +6297,13 @@ server3_3_rename (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_MUST;
state->resolve.bname = gf_strdup (args.oldbname);
- memcpy (state->resolve.pargfid, args.oldgfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.oldgfid);
state->resolve2.type = RESOLVE_MAY;
state->resolve2.bname = gf_strdup (args.newbname);
- memcpy (state->resolve2.pargfid, args.newgfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve2.pargfid,
+ args.newgfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -6331,7 +6354,7 @@ server3_3_lease (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
gf_proto_lease_to_lease (&args.lease, &state->lease);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
@@ -6388,7 +6411,7 @@ server3_3_lk (rpcsvc_request_t *req)
state->resolve.fd_no = args.fd;
state->cmd = args.cmd;
state->type = args.type;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
switch (state->cmd) {
case GF_LK_GETLK:
@@ -6571,10 +6594,12 @@ server3_3_lookup (rpcsvc_request_t *req)
state->resolve.type = RESOLVE_DONTCARE;
if (args.bname && strcmp (args.bname, "")) {
- memcpy (state->resolve.pargfid, args.pargfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.pargfid,
+ args.pargfid);
state->resolve.bname = gf_strdup (args.bname);
} else {
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client,
+ state->resolve.gfid, args.gfid);
}
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
@@ -6632,7 +6657,7 @@ server3_3_statfs (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
state->xdata,
@@ -6684,7 +6709,7 @@ server3_3_getactivelk (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
/* here, dict itself works as xdata */
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
@@ -6740,7 +6765,7 @@ server3_3_setactivelk (rpcsvc_request_t *req)
}
state->resolve.type = RESOLVE_MUST;
- memcpy (state->resolve.gfid, args.gfid, 16);
+ set_resolve_gfid (frame->root->client, state->resolve.gfid, args.gfid);
/* here, dict itself works as xdata */
GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl,
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
index e59941e..ee90071 100644
--- a/xlators/protocol/server/src/server.c
+++ b/xlators/protocol/server/src/server.c
@@ -424,6 +424,7 @@ _check_for_auth_option (dict_t *d, char *k, data_t *v,
goto out;
}
+ /* TODO-SUBDIR-MOUNT: fix the format */
tmp_addr_list = gf_strdup (v->data);
addr = strtok_r (tmp_addr_list, ",", &tmp_str);
if (!addr)
diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h
index 09a2d74..ea15b56 100644
--- a/xlators/protocol/server/src/server.h
+++ b/xlators/protocol/server/src/server.h
@@ -204,6 +204,9 @@ struct _server_state {
struct iobuf *rsp_iobuf;
struct iobref *rsp_iobref;
compound_args_t *args;
+
+ /* subdir mount */
+ client_t *client;
};