From 4521520e2640f52ceb74cda8001c0e894d9b155c Mon Sep 17 00:00:00 2001 From: Amar Tumballi Date: Wed, 27 Sep 2017 12:37:59 +0530 Subject: [PATCH 621/622] glusterfsd: allow subdir mount Changes: 1. Take subdir mount option in client (mount.gluster / glusterfsd) 2. Pass the subdir mount to server-handshake (from client-handshake) 3. Handle subdir-mount dir's lookup in server-first-lookup and handle all fops resolution accordingly with proper gfid of subdir 4. Change the auth/addr module to handle the multiple subdir entries in option, and valid parsing. How to use the feature: `# mount -t glusterfs $hostname:/$volname/$subdir /$mount_point` Or `# mount -t glusterfs $hostname:/$volname -osubdir_mount=$subdir /$mount_point` Option can be set like: `# gluster volume set auth.allow "/subdir1(192.168.1.*),/(192.168.10.*),/subdir2(192.168.8.*)"` > Upstream: > Reviewed-on: https://review.gluster.org/17141 > Updates #175 > Also includes fixes from: https://review.gluster.org/18184 > Also includes fixes from: https://review.gluster.org/18322 BUG: 1017362 Signed-Off-By: Amar Tumballi Change-Id: Ia722e9190064061bb46da45e467be2253b19c81b Reviewed-on: https://code.engineering.redhat.com/gerrit/119138 Tested-by: RHGS Build Bot Reviewed-by: Atin Mukherjee --- doc/glusterfs.8 | 3 + doc/mount.glusterfs.8 | 7 +- glusterfsd/src/glusterfsd.c | 10 ++ glusterfsd/src/glusterfsd.h | 1 + libglusterfs/src/client_t.c | 15 +- libglusterfs/src/client_t.h | 8 +- libglusterfs/src/glusterfs.h | 3 + libglusterfs/src/options.c | 62 +++++++- tests/features/subdir-mount.t | 99 ++++++++++++ xlators/mount/fuse/utils/mount.glusterfs.in | 17 ++- xlators/protocol/auth/addr/src/addr.c | 202 ++++++++++++++++++------- xlators/protocol/client/src/client-handshake.c | 21 ++- xlators/protocol/server/src/server-common.c | 68 +++++++-- xlators/protocol/server/src/server-common.h | 6 +- xlators/protocol/server/src/server-handshake.c | 180 +++++++++++++++------- xlators/protocol/server/src/server-helpers.c | 10 +- xlators/protocol/server/src/server-rpc-fops.c | 107 ++++++++----- xlators/protocol/server/src/server.c | 1 + xlators/protocol/server/src/server.h | 3 + 19 files changed, 650 insertions(+), 173 deletions(-) create mode 100644 tests/features/subdir-mount.t diff --git a/doc/glusterfs.8 b/doc/glusterfs.8 index fc28ef6..6f180b1 100644 --- a/doc/glusterfs.8 +++ b/doc/glusterfs.8 @@ -98,6 +98,9 @@ Mount the filesystem in 'worm' mode. .TP \fB\-\-xlator\-option=VOLUME\-NAME.OPTION=VALUE\fR Add/Override a translator option for a volume with the specified value. +.TP +\fB\-\-subdir\-mount=SUBDIR\-MOUNT\-PATH\fR +Mount subdirectory instead of the '/' of volume. .SS "Fuse options" .PP diff --git a/doc/mount.glusterfs.8 b/doc/mount.glusterfs.8 index 4e82c2f..e16bbec 100644 --- a/doc/mount.glusterfs.8 +++ b/doc/mount.glusterfs.8 @@ -12,11 +12,11 @@ .SH NAME .B mount.glusterfs - script to mount native GlusterFS volume .SH SYNOPSIS -.B mount -t glusterfs [-o ] :/ +.B mount -t glusterfs [-o ] :/[/] .B .TP .B mount -t glusterfs [-o ] ,, -.B ,..:/ +.B ,..:/[/] .TP .TP .B mount -t glusterfs [-o ] @@ -95,6 +95,9 @@ Disable direct I/O mode in fuse kernel module \fBcongestion\-threshold=\fRN Set fuse module's congestion threshold to N [default: 48] .TP +\fsubdir\-mount=\fRN +Set the subdirectory mount option [default: NULL, ie, no subdirectory mount] +.TP .TP \fBbackup\-volfile\-servers=\fRSERVERLIST Provide list of backup volfile servers in the following format [default: None] diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index 110cbb3..8782ba2 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -154,6 +154,8 @@ static struct argp_option gf_options[] = { "Enable SELinux label (extended attributes) support on inodes"}, {"capability", ARGP_CAPABILITY_KEY, 0, 0, "Enable Capability (extended attributes) support on inodes"}, + {"subdir-mount", ARGP_SUBDIR_MOUNT_KEY, "SUBDIR-PATH", 0, + "Mount subdirectory given [default: NULL]"}, {"print-netgroups", ARGP_PRINT_NETGROUPS, "NETGROUP-FILE", 0, "Validate the netgroups file and print it out"}, @@ -1235,6 +1237,14 @@ parse_opts (int key, char *arg, struct argp_state *state) argp_failure (state, -1, 0, "unknown secure-mgmt setting \"%s\"", arg); break; + case ARGP_SUBDIR_MOUNT_KEY: + if (arg[0] != '/') { + argp_failure (state, -1, 0, + "expect '/%s', provided just \"%s\"", arg, arg); + break; + } + cmd_args->subdir_mount = gf_strdup (arg); + break; } return 0; diff --git a/glusterfsd/src/glusterfsd.h b/glusterfsd/src/glusterfsd.h index 4d697f3..938d422 100644 --- a/glusterfsd/src/glusterfsd.h +++ b/glusterfsd/src/glusterfsd.h @@ -98,6 +98,7 @@ enum argp_option_keys { ARGP_OOM_SCORE_ADJ_KEY = 176, #endif #endif + ARGP_SUBDIR_MOUNT_KEY = 177, }; struct _gfd_vol_top_priv_t { diff --git a/libglusterfs/src/client_t.c b/libglusterfs/src/client_t.c index 97cf9f9..f4fdb52 100644 --- a/libglusterfs/src/client_t.c +++ b/libglusterfs/src/client_t.c @@ -159,7 +159,8 @@ gf_client_clienttable_destroy (clienttable_t *clienttable) * as long as ref.bind is > 0 client should be alive. */ client_t * -gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid) +gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid, + char *subdir_mount) { client_t *client = NULL; cliententry_t *cliententry = NULL; @@ -204,6 +205,8 @@ gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid) } client->this = this; + if (subdir_mount != NULL) + client->subdir_mount = gf_strdup (subdir_mount); LOCK_INIT (&client->scratch_ctx.lock); @@ -373,6 +376,10 @@ client_destroy (client_t *client) list_for_each_entry (gtrav, &client->this->ctx->graphs, list) { gf_client_destroy_recursive (gtrav->top, client); } + if (client->subdir_inode) + inode_unref (client->subdir_inode); + + GF_FREE (client->subdir_mount); GF_FREE (client->auth.data); GF_FREE (client->scratch_ctx.ctx); GF_FREE (client->client_uid); @@ -776,6 +783,12 @@ gf_client_dump_fdtables (xlator_t *this) client->client_uid); } + if (client->subdir_mount) { + gf_proc_dump_build_key (key, "conn", + "%d.subdir", count); + gf_proc_dump_write (key, "%s", + client->subdir_mount); + } gf_proc_dump_build_key (key, "conn", "%d.ref", count); gf_proc_dump_write (key, GF_PRI_ATOMIC, diff --git a/libglusterfs/src/client_t.h b/libglusterfs/src/client_t.h index 31f1bd0..cd9afa2 100644 --- a/libglusterfs/src/client_t.h +++ b/libglusterfs/src/client_t.h @@ -40,6 +40,11 @@ typedef struct _client_t { char *username; char *passwd; } auth; + + /* subdir_mount */ + char *subdir_mount; + inode_t *subdir_inode; + uuid_t subdir_gfid; } client_t; #define GF_CLIENTCTX_INITIAL_SIZE 8 @@ -72,7 +77,8 @@ typedef struct clienttable clienttable_t; struct rpcsvc_auth_data; client_t * -gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid); +gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, + char *client_uid, char *subdir_mount); void gf_client_put (client_t *client, gf_boolean_t *detached); diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index c58cae1..d13e5bd 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -400,6 +400,9 @@ struct _cmd_args { /* Should management connections use SSL? */ int secure_mgmt; + + /* For the subdir mount */ + char *subdir_mount; }; typedef struct _cmd_args cmd_args_t; diff --git a/libglusterfs/src/options.c b/libglusterfs/src/options.c index 02928a9..0ad4e53 100644 --- a/libglusterfs/src/options.c +++ b/libglusterfs/src/options.c @@ -599,21 +599,70 @@ xlator_option_validate_addr_list (xlator_t *xl, const char *key, char *dup_val = NULL; char *addr_tok = NULL; char *save_ptr = NULL; + char *entry = NULL; + char *entry_ptr = NULL; + char *dir_and_addr = NULL; + char *addr_ptr = NULL; + char *addr_list = NULL; + char *addr = NULL; + char *dir = NULL; char errstr[4096] = {0,}; dup_val = gf_strdup (value); if (!dup_val) goto out; - addr_tok = strtok_r (dup_val, ",", &save_ptr); - if (addr_tok == NULL) + if (dup_val[0] != '/' && !strchr (dup_val, '(')) { + /* Possible old format, handle it for back-ward compatibility */ + addr_tok = strtok_r (dup_val, ",", &save_ptr); + while (addr_tok) { + if (!valid_internet_address (addr_tok, _gf_true)) + goto out; + + addr_tok = strtok_r (NULL, ",", &save_ptr); + } + ret = 0; goto out; - while (addr_tok) { - if (!valid_internet_address (addr_tok, _gf_true)) + } + + /* Lets handle the value with new format */ + entry = strtok_r (dup_val, ",", &entry_ptr); + while (entry) { + dir_and_addr = gf_strdup (entry); + if (!dir_and_addr) goto out; - addr_tok = strtok_r (NULL, ",", &save_ptr); + dir = strtok_r (dir_and_addr, "(", &addr_ptr); + if (dir[0] != '/') { + /* Valid format should be starting from '/' */ + goto out; + } + /* dir = strtok_r (NULL, " =", &addr_tmp); */ + addr = strtok_r (NULL, ")", &addr_ptr); + if (!addr) + goto out; + + addr_list = gf_strdup (addr); + if (!addr_list) + goto out; + + /* This format be separated by '|' */ + addr_tok = strtok_r (addr_list, "|", &save_ptr); + if (addr_tok == NULL) + goto out; + while (addr_tok) { + if (!valid_internet_address (addr_tok, _gf_true)) + goto out; + + addr_tok = strtok_r (NULL, "|", &save_ptr); + } + entry = strtok_r (NULL, ",", &entry_ptr); + GF_FREE (dir_and_addr); + GF_FREE (addr_list); + addr_list = NULL; + dir_and_addr = NULL; } + ret = 0; out: @@ -626,7 +675,8 @@ out: *op_errstr = gf_strdup (errstr); } GF_FREE (dup_val); - + GF_FREE (dir_and_addr); + GF_FREE (addr_list); return ret; } diff --git a/tests/features/subdir-mount.t b/tests/features/subdir-mount.t new file mode 100644 index 0000000..2fb0be4 --- /dev/null +++ b/tests/features/subdir-mount.t @@ -0,0 +1,99 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../nfs.rc + +cleanup; + +## Start and create a volume +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{1,2,3,4}; + +## Start volume and verify +TEST $CLI volume start $V0; + +## Mount FUSE with caching disabled (read-write) +TEST $GFS -s $H0 --volfile-id $V0 --volume-name ${V0}-dht $M0; + +TEST ! stat $M0/subdir1; +TEST mkdir $M0/subdir1; +TEST ! stat $M0/subdir2; +TEST mkdir $M0/subdir2; +TEST ! stat $M0/subdir1/subdir1.1; +TEST mkdir $M0/subdir1/subdir1.1; +TEST ! stat $M0/subdir1/subdir1.1/subdir1.2; +TEST mkdir $M0/subdir1/subdir1.1/subdir1.2; + +# mount volume/subdir1 +TEST $GFS --subdir-mount /subdir1 -s $H0 --volfile-id $V0 --volume-name ${V0}-dht $M1; + +TEST touch $M0/topfile; +TEST ! stat $M1/topfile; + +TEST touch $M1/subdir1_file; +TEST ! stat $M0/subdir1_file; +TEST stat $M0/subdir1/subdir1_file; + +# mount volume/subdir2 +TEST $GFS --subdir-mount /subdir2 -s $H0 --volfile-id $V0 $M2; + +TEST ! stat $M2/topfile; + +TEST touch $M2/subdir2_file; +TEST ! stat $M0/subdir2_file; +TEST ! stat $M1/subdir2_file; +TEST stat $M0/subdir2/subdir2_file; + +# umount $M1 / $M2 +TEST umount $M1 +TEST umount $M2 + +# mount non-existing subdir ; this works with mount.glusterfs, +# but with glusterfs, the script doesn't returns error. +#TEST ! $GFS --subdir-mount subdir_not_there -s $H0 --volfile-id $V0 $M1; + +# mount subdir with depth +TEST $GFS --subdir-mount /subdir1/subdir1.1/subdir1.2 -s $H0 --volfile-id $V0 $M2; +TEST ! stat $M2/topfile; +TEST touch $M2/subdir1.2_file; +TEST ! stat $M0/subdir1.2_file; +TEST stat $M0/subdir1/subdir1.1/subdir1.2/subdir1.2_file; + +TEST umount $M2 + +# Lets validate the options # Not having '*' in here as there was some +# problem with option validation with this +TEST $CLI volume set $V0 auth.allow 192.168.1.1 + +TEST $CLI volume set $V0 auth.allow "192.168.1.1,10.10.\*.\*,::1" + +TEST $CLI volume set $V0 auth.allow "/subdir1\(1.2.3.4\),/\(192.168.10.2\|192.168.11.1\),/subdir2\(1.2.3.4\)" + +# directories should be absolute +TEST ! $CLI volume set $V0 auth.allow "subdir2\(1.2.3.4\)" + +# support subdir inside subdir +TEST $CLI volume set $V0 auth.allow '/subdir1/subdir1.1/subdir1.2/\(1.2.3.4\|::1\),/\(192.168.10.1\|192.168.11.1\),/subdir2\(1.2.3.4\)' + +# /subdir2 has not allowed IP +TEST $GFS --subdir-mount /subdir2 -s $H0 --volfile-id $V0 $M1 +TEST stat $M1 + +TEST $GFS --subdir-mount /subdir1/subdir1.1/subdir1.2 -s $H0 --volfile-id $V0 $M2 +TEST stat $M2 + +# umount $M1 / $M2 +TEST umount $M0 +TEST umount $M1 +TEST umount $M2 + + +TEST $CLI volume stop $V0; +TEST $CLI volume delete $V0; +TEST ! $CLI volume info $V0; + +## This should clean the mountpoints +cleanup; diff --git a/xlators/mount/fuse/utils/mount.glusterfs.in b/xlators/mount/fuse/utils/mount.glusterfs.in index 2c5e466..e294c5a 100755 --- a/xlators/mount/fuse/utils/mount.glusterfs.in +++ b/xlators/mount/fuse/utils/mount.glusterfs.in @@ -297,6 +297,10 @@ start_glusterfs () cmd_line=$(echo "$cmd_line --fuse-mountopts=$fuse_mountopts"); fi + if [ -n "$subdir_mount" ]; then + cmd_line=$(echo "$cmd_line --subdir-mount=/$subdir_mount"); + fi + cmd_line=$(echo "$cmd_line $mount_point"); $cmd_line; if [ $? -ne 0 ]; then @@ -415,6 +419,9 @@ with_options() "volume-id") volume_id=$value ;; + "subdir-mount") + subdir_mount=$value + ;; "volfile-check") volfile_check=$value ;; @@ -631,7 +638,15 @@ main () server_ip=$(echo "$volfile_loc" | sed -n 's/\([a-zA-Z0-9:%.\-]*\):.*/\1/p'); volume_str=$(echo "$volfile_loc" | sed -n 's/.*:\([^ ]*\).*/\1/p'); [ -n "$volume_str" ] && { - volume_id="$volume_str"; + volume_id=$volume_str + volume_str_temp=$volume_str + first_char=$(echo "$volume_str" | cut -c 1); + [ ${first_char} = '/' ] && { + volume_str_temp=$(echo "$volume_str" | cut -c 2-); + [ $(echo $volume_str_temp | grep -c "/") -eq 1 ] && { + volume_id=$(echo "$volume_str_temp" | cut -f1 -d '/'); + subdir_mount=$(echo "$volume_str_temp" | cut -f2- -d '/'); + } } volfile_loc=""; [ -z "$volume_id" -o -z "$server_ip" ] && { diff --git a/xlators/protocol/auth/addr/src/addr.c b/xlators/protocol/auth/addr/src/addr.c index 7ccbb57..eb933f8 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) { @@ -35,15 +173,12 @@ gf_auth (dict_t *input_params, dict_t *config_params) 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; + char *subdir = NULL; name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!name) { @@ -98,6 +233,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) { @@ -143,60 +284,19 @@ 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++; - } - - 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++; - } - - 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 5f55752..4e6ac74 100644 --- a/xlators/protocol/client/src/client-handshake.c +++ b/xlators/protocol/client/src/client-handshake.c @@ -1136,13 +1136,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, @@ -1376,6 +1383,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 2cabcf9..100b198 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); } @@ -447,17 +480,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); @@ -466,6 +488,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..ba5b11a 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 3ad3d84..647f144 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); @@ -508,6 +509,9 @@ get_frame_from_request (rpcsvc_request_t *req) frame->local = req; + + state = CALL_STATE (frame); + state->client = client; out: return frame; } @@ -2226,7 +2230,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; @@ -2729,8 +2733,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 a9f5d86..bd7ec7a 100644 --- a/xlators/protocol/server/src/server-rpc-fops.c +++ b/xlators/protocol/server/src/server-rpc-fops.c @@ -41,6 +41,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 @@ -1194,8 +1206,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) ==> (%s)", @@ -1204,7 +1216,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; @@ -1595,8 +1607,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) ==> (%s)", @@ -1606,7 +1618,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); @@ -3406,7 +3418,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, @@ -3464,7 +3476,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; @@ -3947,7 +3959,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; @@ -4534,7 +4548,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, @@ -4651,7 +4665,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; @@ -4713,7 +4729,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, @@ -4792,7 +4808,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, @@ -4868,7 +4884,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, @@ -4944,7 +4960,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, @@ -5017,7 +5033,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); @@ -5081,8 +5097,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); @@ -5143,7 +5158,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, @@ -5202,7 +5217,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, @@ -5261,7 +5276,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, @@ -5331,7 +5346,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, @@ -5402,7 +5417,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, @@ -5459,7 +5474,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, @@ -5518,7 +5533,8 @@ 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; @@ -5584,7 +5600,9 @@ 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; @@ -5648,7 +5666,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; @@ -5711,7 +5730,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) { @@ -5802,7 +5821,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: @@ -5891,7 +5910,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); @@ -5959,7 +5978,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); @@ -6018,7 +6037,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, @@ -6079,7 +6098,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; @@ -6146,7 +6166,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, @@ -6206,11 +6227,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, @@ -6261,7 +6284,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, @@ -6318,7 +6341,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: @@ -6502,10 +6525,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, @@ -6563,7 +6588,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, @@ -6616,7 +6641,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, @@ -6673,7 +6698,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 b3dc417..71b25bc 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -430,6 +430,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 b419b05..1be9a38 100644 --- a/xlators/protocol/server/src/server.h +++ b/xlators/protocol/server/src/server.h @@ -206,6 +206,9 @@ struct _server_state { struct iobuf *rsp_iobuf; struct iobref *rsp_iobref; compound_args_t *args; + + /* subdir mount */ + client_t *client; }; -- 1.8.3.1