diff options
| author | Amar Tumballi <amarts@redhat.com> | 2017-07-19 23:08:05 +0530 | 
|---|---|---|
| committer | Amar Tumballi <amarts@redhat.com> | 2017-08-04 05:26:42 +0000 | 
| commit | 590ae48c65a60c93c2e5407e3f663cef3daacc55 (patch) | |
| tree | 82e948d6e48900878a9977aceef3535506d05207 /xlators/protocol | |
| parent | f68887999e89d894c3125e3b26517221ad1543fc (diff) | |
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 <volname> auth.allow "/subdir1(192.168.1.*),/(192.168.10.*),/subdir2(192.168.8.*)"`
Updates #175
Change-Id: I7ea57f76ddbe6c3862cfe02e13f89e8a39719e11
Signed-off-by: Amar Tumballi <amarts@redhat.com>
Reviewed-on: https://review.gluster.org/17141
Smoke: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Shyamsundar Ranganathan <srangana@redhat.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Diffstat (limited to 'xlators/protocol')
| -rw-r--r-- | xlators/protocol/auth/addr/src/addr.c | 227 | ||||
| -rw-r--r-- | xlators/protocol/client/src/client-handshake.c | 21 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-common.c | 68 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-common.h | 6 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-handshake.c | 180 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 10 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-rpc-fops.c | 107 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.c | 1 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.h | 3 | 
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 cafcf28f1e9..3e62d05a05a 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 a36f6e435a7..b6dc0797dd9 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 1dc3a9cf9bd..b972918f37f 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 f3b9ced939c..3fa972e68db 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 f8f8f99f123..fa2f61315df 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 52d7f51a627..381fb6f515e 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 ba5543fdb41..c947f066833 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 e59941e4ca1..ee900712f79 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 09a2d74ff2b..ea15b561be7 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;  };  | 
