diff options
| author | Shehjar Tikoo <shehjart@gluster.com> | 2010-09-14 02:39:11 +0000 | 
|---|---|---|
| committer | Vijay Bellur <vijay@dev.gluster.com> | 2010-09-14 02:32:03 -0700 | 
| commit | 9ff89d858075d8f916c76a9ade84b9844da4d23e (patch) | |
| tree | 535ea0f8456078a74eeeb920edc646cf58c9beee /xlators/nfs | |
| parent | 2152dae595438b919fbcb7349d15ead139e120d8 (diff) | |
nfs,nfs3,mnt3: Transition fh resolution to gfid
Signed-off-by: Shehjar Tikoo <shehjart@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 971 (dynamic volume management)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=971
Diffstat (limited to 'xlators/nfs')
| -rw-r--r-- | xlators/nfs/server/src/mount3.c | 125 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3.h | 5 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-common.c | 20 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-common.h | 7 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-fops.c | 61 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs-fops.h | 1 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs.c | 107 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs.h | 6 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3-fh.c | 83 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3-fh.h | 36 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3-helpers.c | 239 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3-helpers.h | 52 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.c | 467 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs3.h | 4 | 
14 files changed, 847 insertions, 366 deletions
diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index c61cf0a488a..3ea4bc8e893 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -211,6 +211,29 @@ free_err:  } +int +__mnt3_get_volume_id (struct mount3_state *ms, xlator_t *mntxl, +                      uuid_t volumeid) +{ +        int                     ret = -1; +        struct mnt3_export      *exp = NULL; + +        if ((!ms) || (!mntxl)) +                return ret; + +        list_for_each_entry (exp, &ms->exportlist, explist) { +                if (exp->vol == mntxl) { +                        uuid_copy (volumeid, exp->volumeid); +                        ret = 0; +                        goto out; +                } +        } + +out: +        return ret; +} + +  int32_t  mnt3svc_lookup_mount_cbk (call_frame_t *frame, void  *cookie,                            xlator_t *this, int32_t op_ret, int32_t op_errno, @@ -226,6 +249,8 @@ mnt3svc_lookup_mount_cbk (call_frame_t *frame, void  *cookie,          int                     autharrlen = 0;          rpcsvc_t                *svc = NULL;          xlator_t                *mntxl = NULL; +        uuid_t                  volumeid = {0, }; +        char                    fhstr[1024];          req = (rpcsvc_request_t *)frame->local; @@ -246,10 +271,19 @@ mnt3svc_lookup_mount_cbk (call_frame_t *frame, void  *cookie,          if (status != MNT3_OK)                  goto xmit_res; -        fh = nfs3_fh_build_root_fh (ms->nfsx->children, mntxl);          mnt3svc_update_mountlist (ms, req, mntxl->name); +        if (gf_nfs_dvm_off (nfs_state (ms->nfsx))) { +                fh = nfs3_fh_build_indexed_root_fh (ms->nfsx->children, mntxl); +                goto xmit_res; +        } + +        __mnt3_get_volume_id (ms, mntxl, volumeid); +        fh = nfs3_fh_build_uuid_root_fh (volumeid); +  xmit_res: -        gf_log (GF_MNT, GF_LOG_DEBUG, "Mount reply status: %d", status); +        nfs3_fh_to_str (&fh, fhstr); +        gf_log (GF_MNT, GF_LOG_DEBUG, "MNT reply: fh %s, status: %d", fhstr, +                status);          if (op_ret == 0) {                  svc = nfs_rpcsvc_request_service (req);                  autharrlen = nfs_rpcsvc_auth_array (svc, mntxl->name, autharr, @@ -336,11 +370,13 @@ mnt3svc_volume_mount (rpcsvc_request_t *req, struct mount3_state *ms,  {          inode_t         *exportinode = NULL;          int             ret = -EFAULT; +        uuid_t          rootgfid = {0, };          if ((!req) || (!exp) || (!ms))                  return ret; -        exportinode = inode_get (exp->vol->itable, 1, 0); +        rootgfid[15] = 1; +        exportinode = inode_find (exp->vol->itable, rootgfid);          if (!exportinode) {                  gf_log (GF_MNT, GF_LOG_ERROR, "Faild to get root inode");                  ret = -ENOENT; @@ -434,9 +470,8 @@ __mnt3_resolve_export_subdir_comp (mnt3_resolve_t *mres)          char            dupsubdir[MNTPATHLEN];          char            *nextcomp = NULL;          int             ret = -EFAULT; -        uint64_t        parino = 0; -        uint64_t        pargen = 0;          nfs_user_t      nfu = {0, }; +        char            gfidstr[512];          if (!mres)                  return ret; @@ -445,17 +480,15 @@ __mnt3_resolve_export_subdir_comp (mnt3_resolve_t *mres)          if (!nextcomp)                  goto err; -        parino = mres->resolveloc.inode->ino; -          /* Wipe the contents of the previous component */          nfs_loc_wipe (&mres->resolveloc); -        ret = nfs_entry_loc_fill (mres->exp->vol->itable, parino, pargen, -                                  nextcomp, &mres->resolveloc, -                                  NFS_RESOLVE_CREATE); +        ret = nfs_entry_loc_fill (mres->exp->vol->itable, +                                  mres->resolveloc.inode->gfid, nextcomp, +                                  &mres->resolveloc, NFS_RESOLVE_CREATE);          if ((ret < 0) && (ret != -2)) { +                uuid_unparse (mres->resolveloc.inode->gfid, gfidstr);                  gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve and create " -                        "inode: parent %"PRIu64", gen: %"PRIu64", entry %s", -                        parino, pargen, nextcomp); +                        "inode: parent gfid %s, entry %s", gfidstr, nextcomp);                  ret = -EFAULT;                  goto err;          } @@ -544,6 +577,7 @@ __mnt3_resolve_export_subdir (mnt3_resolve_t *mres)          char            *firstcomp = NULL;          int             ret = -EFAULT;          nfs_user_t      nfu = {0, }; +        uuid_t          rootgfid = {0, };          if (!mres)                  return ret; @@ -552,7 +586,8 @@ __mnt3_resolve_export_subdir (mnt3_resolve_t *mres)          if (!firstcomp)                  goto err; -        ret = nfs_entry_loc_fill (mres->exp->vol->itable, 1, 0, firstcomp, +        rootgfid[15] = 1; +        ret = nfs_entry_loc_fill (mres->exp->vol->itable, rootgfid, firstcomp,                                    &mres->resolveloc, NFS_RESOLVE_CREATE);          if ((ret < 0) && (ret != -2)) {                  gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve and create " @@ -577,6 +612,7 @@ mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms,          mnt3_resolve_t  *mres = NULL;          char            *volume_subdir = NULL;          int             ret = -EFAULT; +        struct nfs3_fh  pfh = GF_NFS3FH_STATIC_INITIALIZER;          if ((!req) || (!ms) || (!exp))                  return ret; @@ -595,9 +631,12 @@ mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms,          mres->mstate = ms;          mres->req = req;          strcpy (mres->remainingdir, volume_subdir); -        mres->parentfh = nfs3_fh_build_root_fh (mres->mstate->nfsx->children, -                                                mres->exp->vol); +        if (gf_nfs_dvm_off (nfs_state (ms->nfsx))) +                pfh = nfs3_fh_build_indexed_root_fh (mres->mstate->nfsx->children, mres->exp->vol); +        else +                pfh = nfs3_fh_build_uuid_root_fh (exp->volumeid); +        mres->parentfh = pfh;          ret = __mnt3_resolve_export_subdir (mres);          if (ret < 0) {                  gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve export dir: %s" @@ -1205,7 +1244,8 @@ err:  struct mnt3_export * -mnt3_init_export_ent (struct mount3_state *ms, xlator_t *xl, char *exportpath) +mnt3_init_export_ent (struct mount3_state *ms, xlator_t *xl, char *exportpath, +                      uuid_t volumeid)  {          struct mnt3_export      *exp = NULL;          int                     alloclen = 0; @@ -1247,6 +1287,11 @@ mnt3_init_export_ent (struct mount3_state *ms, xlator_t *xl, char *exportpath)                  ret = snprintf (exp->expname, alloclen, "/%s", xl->name);          } +        /* Just copy without discrimination, we'll determine whether to +         * actually use it when a mount request comes in and a file handle +         * needs to be built. +         */ +        uuid_copy (exp->volumeid, volumeid);          exp->vol = xl;  err:          return exp; @@ -1255,7 +1300,7 @@ err:  int  __mnt3_init_volume_direxports (struct mount3_state *ms, xlator_t *xlator, -                               char *optstr) +                               char *optstr, uuid_t volumeid)  {          struct mnt3_export      *newexp = NULL;          int                     ret = -1; @@ -1274,7 +1319,7 @@ __mnt3_init_volume_direxports (struct mount3_state *ms, xlator_t *xlator,          token = strtok_r (dupopt, ",", &savptr);          while (token) { -                newexp = mnt3_init_export_ent (ms, xlator, token); +                newexp = mnt3_init_export_ent (ms, xlator, token, volumeid);                  if (!newexp) {                          gf_log (GF_MNT, GF_LOG_ERROR, "Failed to init dir "                                  "export: %s", token); @@ -1302,10 +1347,48 @@ __mnt3_init_volume (struct mount3_state *ms, dict_t *opts, xlator_t *xlator)          int                     ret = -1;          char                    searchstr[1024];          char                    *optstr  = NULL; +        uuid_t                  volumeid = {0, };          if ((!ms) || (!xlator) || (!opts))                  return -1; +        uuid_clear (volumeid); +        if (gf_nfs_dvm_off (nfs_state (ms->nfsx))) +                goto no_dvm; + +        ret = snprintf (searchstr, 1024, "nfs3.%s.volume-id", xlator->name); +        if (ret < 0) { +                gf_log (GF_MNT, GF_LOG_ERROR, "snprintf failed"); +                ret = -1; +                goto err; +        } + +        if (dict_get (opts, searchstr)) { +                ret = dict_get_str (opts, searchstr, &optstr); +                if (ret < 0) { +                        gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option" +                                ": %s", searchstr); +                        ret = -1; +                        goto err; +                } +        } else { +                gf_log (GF_MNT, GF_LOG_ERROR, "DVM is on but volume-id not " +                        "given for volume: %s", xlator->name); +                ret = -1; +                goto err; +        } + +        if (optstr) { +                ret = uuid_parse (optstr, volumeid); +                if (ret < 0) { +                        gf_log (GF_MNT, GF_LOG_ERROR, "Failed to parse volume " +                                "UUID"); +                        ret = -1; +                        goto err; +                } +        } + +no_dvm:          ret = snprintf (searchstr, 1024, "nfs3.%s.export-dir", xlator->name);          if (ret < 0) {                  gf_log (GF_MNT, GF_LOG_ERROR, "snprintf failed"); @@ -1322,17 +1405,17 @@ __mnt3_init_volume (struct mount3_state *ms, dict_t *opts, xlator_t *xlator)                          goto err;                  } -                ret = __mnt3_init_volume_direxports (ms, xlator, optstr); +                ret = __mnt3_init_volume_direxports (ms, xlator, optstr, +                                                     volumeid);                  if (ret == -1) {                          gf_log (GF_MNT, GF_LOG_ERROR, "Dir export setup failed"                                  " for volume: %s", xlator->name);                          goto err;                  } -          }          if (ms->export_volumes) { -                newexp = mnt3_init_export_ent (ms, xlator, NULL); +                newexp = mnt3_init_export_ent (ms, xlator, NULL, volumeid);                  if (!newexp) {                          ret = -1;                          goto err; diff --git a/xlators/nfs/server/src/mount3.h b/xlators/nfs/server/src/mount3.h index f555bc7f18a..16b89f6da02 100644 --- a/xlators/nfs/server/src/mount3.h +++ b/xlators/nfs/server/src/mount3.h @@ -34,6 +34,7 @@  #include "xdr-nfs3.h"  #include "locking.h"  #include "nfs3-fh.h" +#include "uuid.h"  /* Registered with portmap */  #define GF_MOUNTV3_PORT         38465 @@ -73,6 +74,10 @@ struct mnt3_export {          char                    *expname;          xlator_t                *vol;          int                     exptype; + +        /* Extracted from nfs volume options if nfs.dynamicvolumes is on. +         */ +        uuid_t                  volumeid;  };  struct mount3_state { diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c index 9f68f714649..970eb41c571 100644 --- a/xlators/nfs/server/src/nfs-common.c +++ b/xlators/nfs/server/src/nfs-common.c @@ -264,9 +264,8 @@ err:          return ret;  } -  int -nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *loc) +nfs_gfid_loc_fill (inode_table_t *itable, uuid_t gfid, loc_t *loc)  {          int             ret = -EFAULT;          inode_t         *inode = NULL; @@ -274,7 +273,7 @@ nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *loc)          if (!loc)                  return ret; -        inode = inode_get (itable, ino, gen); +        inode = inode_find (itable, gfid);          if (!inode) {                  ret = -ENOENT;                  goto err; @@ -290,6 +289,17 @@ err:  int +nfs_root_loc_fill (inode_table_t *itable, loc_t *loc) +{ +        uuid_t  rootgfid = {0, }; + +        rootgfid[15] = 1; +        return nfs_gfid_loc_fill (itable, rootgfid, loc); +} + + + +int  nfs_parent_inode_loc_fill (inode_t *parent, inode_t *entryinode, char *entry,                             loc_t *loc)  { @@ -317,7 +327,7 @@ err:   * On other errors, return -3. 0 on success.   */  int -nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry, +nfs_entry_loc_fill (inode_table_t *itable, uuid_t pargfid, char *entry,                      loc_t *loc, int how)  {          inode_t         *parent = NULL; @@ -329,7 +339,7 @@ nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry,          if ((!itable) || (!entry) || (!loc))                  return ret; -        parent = inode_get (itable, ino, gen); +        parent = inode_find (itable, pargfid);          ret = -1;          /* Will need hard resolution now */ diff --git a/xlators/nfs/server/src/nfs-common.h b/xlators/nfs/server/src/nfs-common.h index 20003aa7130..25fc1cf405b 100644 --- a/xlators/nfs/server/src/nfs-common.h +++ b/xlators/nfs/server/src/nfs-common.h @@ -30,6 +30,7 @@  #include "xlator.h"  #include "rpcsvc.h"  #include "iatt.h" +#include "uuid.h"  #define NFS_PATH_MAX    PATH_MAX  #define NFS_NAME_MAX    NAME_MAX @@ -67,10 +68,12 @@ extern int  nfs_inode_loc_fill (inode_t *inode, loc_t *loc);  extern int -nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *l); +nfs_ino_loc_fill (inode_table_t *itable, uuid_t gfid, loc_t *l);  extern int -nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry, +nfs_entry_loc_fill (inode_table_t *itable, uuid_t pargfid, char *entry,                      loc_t *loc, int how); +extern int +nfs_root_loc_fill (inode_table_t *itable, loc_t *loc);  #endif diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c index 544f6c9e6b1..3f342710b25 100644 --- a/xlators/nfs/server/src/nfs-fops.c +++ b/xlators/nfs/server/src/nfs-fops.c @@ -71,6 +71,9 @@ nfs_fop_local_wipe (xlator_t *nfsx, struct nfs_fop_local *l)          if (l->newparent)                  inode_unref (l->newparent); +        if (l->dictgfid) +                dict_unref (l->dictgfid); +          mem_put (nfs->foppool, l);          return; @@ -222,6 +225,49 @@ err:                  }                                                              \          } while (0)                                                            \ +dict_t * +nfs_gfid_dict () +{ +        uuid_t  newgfid = {0, }; +        char    *dyngfid = NULL; +        dict_t  *dictgfid = NULL; +        int     ret = -1; + +        dyngfid = GF_CALLOC (1, sizeof (uuid_t), gf_common_mt_char); +        uuid_generate (newgfid); +        memcpy (dyngfid, newgfid, sizeof (uuid_t)); + +        dictgfid = dict_new (); +        if (!dictgfid) { +                gf_log (GF_NFS, GF_LOG_ERROR, "Failed to create gfid dict"); +                goto out; +        } + +        ret = dict_set_bin (dictgfid, "gfid-req", dyngfid, sizeof (uuid_t)); +        if (ret < 0) { +                dict_unref (dictgfid); +                dictgfid = NULL; +        } + +out: +        return dictgfid; +} + +#define nfs_fop_gfid_setup(nflcl, retval, erlbl)                        \ +        do {                                                            \ +                if (nflcl) {                                            \ +                        (nflcl)->dictgfid = nfs_gfid_dict ();           \ +                                                                        \ +                        if (!((nflcl)->dictgfid)) {                     \ +                                retval = -EFAULT;                       \ +                                goto erlbl;                             \ +                        }                                               \ +                }                                                       \ +        } while (0)                                                     \ + + + +  /* Fops Layer Explained   * The fops layer has three types of functions. They can all be identified by   * their names. Here are the three patterns: @@ -281,9 +327,10 @@ nfs_fop_lookup (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *loc,          nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);          nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);          nfs_fop_save_root_ino (nfl, loc); +        nfs_fop_gfid_setup (nfl, ret, err);          STACK_WIND_COOKIE (frame, nfs_fop_lookup_cbk, xl, xl, -                           xl->fops->lookup, loc, NULL); +                           xl->fops->lookup, loc, nfl->dictgfid);          ret = 0;  err: @@ -603,9 +650,10 @@ nfs_fop_create (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,          nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);          nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);          nfs_fop_save_root_ino (nfl, pathloc); +        nfs_fop_gfid_setup (nfl, ret, err);          STACK_WIND_COOKIE (frame, nfs_fop_create_cbk, xl, xl, xl->fops->create, -                           pathloc, flags, mode, fd, NULL); +                           pathloc, flags, mode, fd, nfl->dictgfid);          ret = 0;  err: @@ -700,9 +748,10 @@ nfs_fop_mkdir (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,          nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);          nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);          nfs_fop_save_root_ino (nfl, pathloc); +        nfs_fop_gfid_setup (nfl, ret, err);          STACK_WIND_COOKIE  (frame, nfs_fop_mkdir_cbk, xl, xl, xl->fops->mkdir, -                            pathloc, mode, NULL); +                            pathloc, mode, nfl->dictgfid);          ret = 0;  err:          if (ret < 0) { @@ -747,9 +796,10 @@ nfs_fop_symlink (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, char *target,          nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);          nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);          nfs_fop_save_root_ino (nfl, pathloc); +        nfs_fop_gfid_setup (nfl, ret, err);          STACK_WIND_COOKIE  (frame, nfs_fop_symlink_cbk, xl, xl, -                            xl->fops->symlink, target, pathloc, NULL); +                            xl->fops->symlink, target, pathloc, nfl->dictgfid);          ret = 0;  err:          if (ret < 0) { @@ -841,9 +891,10 @@ nfs_fop_mknod (xlator_t *nfsx, xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,          nfs_fop_handle_frame_create (frame, nfsx, nfu, ret, err);          nfs_fop_handle_local_init (frame, nfsx, nfl, cbk, local, ret, err);          nfs_fop_save_root_ino (nfl, pathloc); +        nfs_fop_gfid_setup (nfl, ret, err);          STACK_WIND_COOKIE  (frame, nfs_fop_mknod_cbk, xl, xl, xl->fops->mknod, -                            pathloc, mode, dev, NULL); +                            pathloc, mode, dev, nfl->dictgfid);          ret = 0;  err:          if (ret < 0) { diff --git a/xlators/nfs/server/src/nfs-fops.h b/xlators/nfs/server/src/nfs-fops.h index be445a641eb..3fb157aebf3 100644 --- a/xlators/nfs/server/src/nfs-fops.h +++ b/xlators/nfs/server/src/nfs-fops.h @@ -99,6 +99,7 @@ struct nfs_fop_local {          char            path[NFS_NAME_MAX];          char            newpath[NFS_NAME_MAX];          xlator_t        *nfsx; +        dict_t          *dictgfid;  };  extern struct nfs_fop_local * diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index 8f3c8b2f520..431765332ca 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -457,29 +457,33 @@ mem_acct_init (xlator_t *this)          return ret;  } -int -init (xlator_t *this) { +struct nfs_state * +nfs_init_state (xlator_t *this) +{          struct nfs_state        *nfs = NULL;          int                     ret = -1;          unsigned int            fopspoolsize = 0; +        char                    *optstr = NULL; +        gf_boolean_t            boolt = _gf_false;          if (!this) -                return -1; +                return NULL;          if ((!this->children) || (!this->children->xlator)) {                  gf_log (GF_NFS, GF_LOG_ERROR, "nfs must have at least one"                          " child subvolume"); -                return -1; +                return NULL;          }          nfs = GF_CALLOC (1, sizeof (*nfs), gf_nfs_mt_nfs_state);          if (!nfs) {                  gf_log (GF_NFS, GF_LOG_ERROR, "memory allocation failed"); -                return -1; +                return NULL;          } -        /* RPC service needs to be started before NFS versions can be inited. */ +        /* RPC service needs to be started before NFS versions can be +         * inited. */          nfs->rpcsvc =  nfs_rpcsvc_init (this->ctx, this->options);          if (!nfs->rpcsvc) {                  gf_log (GF_NFS, GF_LOG_ERROR, "RPC service init failed"); @@ -491,33 +495,86 @@ init (xlator_t *this) {          /* FIXME: Really saddens me to see this as xlator wide. */          nfs->foppool = mem_pool_new (struct nfs_fop_local, fopspoolsize);          if (!nfs->foppool) { -                gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate fops local" -                        " pool"); +                gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate fops " +                        "local pool");                  goto free_rpcsvc;          } +        nfs->dynamicvolumes = GF_NFS_DVM_OFF; +        if (dict_get (this->options, "nfs.dynamic-volumes")) { +                ret = dict_get_str (this->options, "nfs.dynamic-volumes", +                                    &optstr); +                if (ret < 0) { +                        gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse dict"); +                        goto free_foppool; +                } + +                ret = gf_string2boolean (optstr, &boolt); +                if (ret < 0) { +                        gf_log (GF_NFS, GF_LOG_ERROR, "Failed to parse bool " +                                "string"); +                        goto free_foppool; +                } + +                if (boolt == _gf_true) +                        nfs->dynamicvolumes = GF_NFS_DVM_ON; +        } +          this->private = (void *)nfs;          INIT_LIST_HEAD (&nfs->versions); + +        ret = 0; + +free_foppool: +        if (ret < 0) +                mem_pool_destroy (nfs->foppool); + +free_rpcsvc: +        /* +         * rpcsvc_deinit */ +free_nfs: +        if (ret < 0) { +                GF_FREE (nfs); +                nfs = NULL; +        } + +        return nfs; +} + + +int +init (xlator_t *this) { + +        struct nfs_state        *nfs = NULL; +        int                     ret = -1; + +        if (!this) +                return -1; + +        nfs = nfs_init_state (this); +        if (!nfs) { +                gf_log (GF_NFS, GF_LOG_ERROR, "Failed to init nfs option"); +                return -1; +        } +          ret = nfs_add_all_initiators (nfs);          if (ret == -1) {                  gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add initiators"); -                goto free_nfs; +                goto err;          }          ret = nfs_init_subvolumes (nfs, this->children);          if (ret == -1) { -                gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NFS exports"); -                goto free_rpcsvc; +                gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NFS " +                        "exports"); +                goto err;          } -free_rpcsvc: -        /* -         * rpcsvc_deinit */ -free_nfs: -        if (ret == -1) -                GF_FREE (nfs); +        ret = 0; +err: +        if (ret == 0) +                gf_log (GF_NFS, GF_LOG_INFO, "NFS service started"); -        gf_log (GF_NFS, GF_LOG_DEBUG, "NFS service started");          return ret;  } @@ -731,6 +788,20 @@ struct volume_options options[] = {                    " using hostnames in rpc-auth.addr.* filters. By default, "                    " name lookup is on."          }, +        { .key  = {"nfs.dynamic-volumes"}, +          .type = GF_OPTION_TYPE_BOOL, +          .description = "Internal option set to tell gnfs to use a different" +                         " scheme for encoding file handles when DVM is being" +                         " used." +        }, +        { .key  = {"nfs3.%s.volume-id"}, +          .type = GF_OPTION_TYPE_STR, +          .description = "When nfs.dynamic-volumes is set, gnfs expects every " +                         "subvolume to have this option set for it, so that " +                         "gnfs can use this option to identify the volume. " +                         "If all subvolumes do not have this option set, an " +                         "error is reported." +        },  	{ .key  = {NULL} },  }; diff --git a/xlators/nfs/server/src/nfs.h b/xlators/nfs/server/src/nfs.h index b4973834558..baee0ce0f6a 100644 --- a/xlators/nfs/server/src/nfs.h +++ b/xlators/nfs/server/src/nfs.h @@ -42,6 +42,9 @@  #define GF_NFS_MIN_MEMFACTOR            1  #define GF_NFS_MAX_MEMFACTOR            30 +#define GF_NFS_DVM_ON                   1 +#define GF_NFS_DVM_OFF                  2 +  /* Callback into a version-specific NFS protocol.   * The return type is used by the nfs.c code to register the protocol.   * with the RPC service. @@ -68,8 +71,11 @@ struct nfs_state {          int                     upsubvols;          xlator_t                **initedxl;          int                     subvols_started; +        int                     dynamicvolumes;  }; +#define gf_nfs_dvm_on(nfsstt)   (((struct nfs_state *)nfsstt)->dynamicvolumes == GF_NFS_DVM_ON) +#define gf_nfs_dvm_off(nfsstt)  (((struct nfs_state *)nfsstt)->dynamicvolumes == GF_NFS_DVM_OFF)  /* We have one gid more than the glusterfs maximum since we pass the primary   * gid as the first element of the array. diff --git a/xlators/nfs/server/src/nfs3-fh.c b/xlators/nfs/server/src/nfs3-fh.c index 7a7a06da058..10c00ba3287 100644 --- a/xlators/nfs/server/src/nfs3-fh.c +++ b/xlators/nfs/server/src/nfs3-fh.c @@ -49,15 +49,6 @@ nfs3_fh_validate (struct nfs3_fh *fh)  } -xlator_t * -nfs3_fh_to_xlator (xlator_list_t *cl, struct nfs3_fh *fh) -{ -	if ((!cl) || (!fh)) -		return NULL; - -	return nfs_xlid_to_xlator (cl, fh->xlatorid); -} -  void  nfs3_fh_init (struct nfs3_fh *fh, struct iatt *buf)  { @@ -68,24 +59,35 @@ nfs3_fh_init (struct nfs3_fh *fh, struct iatt *buf)          fh->ident[1] = GF_NFSFH_IDENT1;          fh->hashcount = 0; -        fh->gen = buf->ia_gen; -        fh->ino = buf->ia_ino; - +        uuid_copy (fh->gfid, buf->ia_gfid);  }  struct nfs3_fh -nfs3_fh_build_root_fh (xlator_list_t *cl, xlator_t *xl) +nfs3_fh_build_indexed_root_fh (xlator_list_t *cl, xlator_t *xl)  {          struct nfs3_fh  fh = {{0}, };          struct iatt     buf = {0, };          if ((!cl) || (!xl))                  return fh; +        buf.ia_gfid[15] = 1;          nfs3_fh_init (&fh, &buf); -        fh.xlatorid = nfs_xlator_to_xlid (cl, xl); -        fh.ino = 1; -        fh.gen = 0; +        fh.exportid [15] = nfs_xlator_to_xlid (cl, xl); + +        return fh; +} + + +struct nfs3_fh +nfs3_fh_build_uuid_root_fh (uuid_t volumeid) +{ +        struct nfs3_fh  fh = {{0}, }; +        struct iatt     buf = {0, }; + +        nfs3_fh_init (&fh, &buf); +        uuid_copy (fh.exportid, volumeid); +          return fh;  } @@ -93,10 +95,13 @@ nfs3_fh_build_root_fh (xlator_list_t *cl, xlator_t *xl)  int  nfs3_fh_is_root_fh (struct nfs3_fh *fh)  { +        uuid_t  rootgfid = {0, 1}; +          if (!fh)                  return 0; -        if (fh->hashcount == 0) +        rootgfid[15] = 1; +        if (uuid_compare (fh->gfid, rootgfid) == 0)                  return 1;          return 0; @@ -104,10 +109,12 @@ nfs3_fh_is_root_fh (struct nfs3_fh *fh)  nfs3_hash_entry_t -nfs3_fh_hash_entry (ino_t ino, uint64_t gen) +nfs3_fh_hash_entry (uuid_t gfid)  {          nfs3_hash_entry_t       hash = 0;          int                     shiftsize = 48; +        uint64_t                ino = 0; +        uint64_t                gen = 0;          nfs3_hash_entry_t       inomsb = 0;          nfs3_hash_entry_t       inolsb = 0;          nfs3_hash_entry_t       inols23b = 0; @@ -116,6 +123,7 @@ nfs3_fh_hash_entry (ino_t ino, uint64_t gen)          nfs3_hash_entry_t       genlsb = 0;          nfs3_hash_entry_t       genls23b = 0; +        memcpy (&ino, &gfid[8], 8);          hash = ino;          while (shiftsize != 0) {                  hash ^= (ino >> shiftsize); @@ -139,6 +147,7 @@ nfs3_fh_hash_entry (ino_t ino, uint64_t gen)          inols23b = (inols23b << 8);  //        gf_log ("FILEHDNALE", GF_LOG_TRACE, "inols23b  %d", inols23b); +        memcpy (&gen, &gfid[0], 8);          genmsb = (gen >> 56);  //        gf_log ("FILEHANDLE", GF_LOG_TRACE, "inomsb %d", inomsb); @@ -163,11 +172,16 @@ nfs3_fh_hash_entry (ino_t ino, uint64_t gen)  void  nfs3_fh_to_str (struct nfs3_fh *fh, char *str)  { +        char            gfid[512]; +        char            exportid[512]; +          if ((!fh) || (!str))                  return; -        sprintf (str, "FH: hashcount %d, xlid %d, gen %"PRIu64", ino %"PRIu64, -                 fh->hashcount, fh->xlatorid, fh->gen, fh->ino); +        uuid_unparse (fh->gfid, gfid); +        uuid_unparse (fh->exportid, exportid); +        sprintf (str, "FH: hashcount %d, exportid %s, gfid %s", +                 fh->hashcount, exportid, gfid);  } @@ -175,12 +189,16 @@ void  nfs3_log_fh (struct nfs3_fh *fh)  {  //        int     x = 0; +        char    gfidstr[512]; +        char    exportidstr[512]; +          if (!fh)                  return; -        gf_log ("nfs3-fh", GF_LOG_TRACE, "filehandle: hashcount %d, xlid %d, " -                "gen %"PRIu64", ino %"PRIu64, fh->hashcount, fh->xlatorid, -                fh->gen, fh->ino); +        uuid_unparse (fh->gfid, gfidstr); +        uuid_unparse (fh->exportid, exportidstr); +        gf_log ("nfs3-fh", GF_LOG_TRACE, "filehandle: hashcount %d, exportid %d" +                ", gfid 0x%s", fh->hashcount, exportidstr, gfidstr);  /*          for (; x < fh->hashcount; ++x)                  gf_log ("FILEHANDLE", GF_LOG_TRACE, "Hash %d: %d", x, @@ -197,12 +215,9 @@ nfs3_fh_build_parent_fh (struct nfs3_fh *child, struct iatt *newstat,                  return -1;          nfs3_fh_init (newfh, newstat); -        newfh->xlatorid = child->xlatorid; -        if ((newstat->ia_ino == 1) && (newstat->ia_gen == 0)) { -                newfh->ino = 1; -                newfh->gen = 0; +        uuid_copy (newfh->exportid, child->exportid); +        if (newstat->ia_ino == 1)                  goto done; -        }          newfh->hashcount = child->hashcount - 1;          memcpy (newfh->entryhash, child->entryhash, @@ -215,7 +230,6 @@ done:  } -  int  nfs3_fh_build_child_fh (struct nfs3_fh *parent, struct iatt *newstat,                          struct nfs3_fh *newfh) @@ -227,12 +241,7 @@ nfs3_fh_build_child_fh (struct nfs3_fh *parent, struct iatt *newstat,                  return -1;          nfs3_fh_init (newfh, newstat); -        newfh->xlatorid = parent->xlatorid; -        if ((newstat->ia_ino == 1) && (newstat->ia_gen == 0)) { -                newfh->ino = 1; -                newfh->gen = 0; -                goto done; -        } +        uuid_copy (newfh->exportid, parent->exportid);          newfh->hashcount = parent->hashcount + 1;          /* Only copy the hashes that are available in the parent file @@ -249,11 +258,9 @@ nfs3_fh_build_child_fh (struct nfs3_fh *parent, struct iatt *newstat,           * array of the child entry. */          if (newfh->hashcount <= GF_NFSFH_MAXHASHES) {                  entry = newfh->hashcount - 1; -                newfh->entryhash[entry] = nfs3_fh_hash_entry (parent->ino, -                                                              parent->gen); +                newfh->entryhash[entry] = nfs3_fh_hash_entry (parent->gfid);          } -done:  //        nfs3_log_fh (newfh);          return 0; diff --git a/xlators/nfs/server/src/nfs3-fh.h b/xlators/nfs/server/src/nfs3-fh.h index 4ee4423951c..987063e7407 100644 --- a/xlators/nfs/server/src/nfs3-fh.h +++ b/xlators/nfs/server/src/nfs3-fh.h @@ -29,13 +29,14 @@  #include "xdr-nfs3.h"  #include "iatt.h"  #include <sys/types.h> +#include "uuid.h"  /* BIG FAT WARNING: The file handle code is tightly coupled to NFSv3 file   * handles for now. This will change if and when we need v4. */  #define GF_NFSFH_IDENT0         ':'  #define GF_NFSFH_IDENT1         'O'  #define GF_NFSFH_IDENT_SIZE     (sizeof(char) * 2) -#define GF_NFSFH_STATIC_SIZE    (GF_NFSFH_IDENT_SIZE + sizeof (uint16_t) + sizeof (uint16_t) + sizeof (uint64_t) + sizeof(uint64_t)) +#define GF_NFSFH_STATIC_SIZE    (GF_NFSFH_IDENT_SIZE + (2*sizeof (uuid_t)) + sizeof (uint16_t))  #define GF_NFSFH_MAX_HASH_BYTES (NFS3_FHSIZE - GF_NFSFH_STATIC_SIZE)  /* Each hash element in the file handle is of 2 bytes thus giving @@ -46,6 +47,7 @@ typedef uint16_t                nfs3_hash_entry_t;  #define GF_NFSFH_MAXHASHES      ((int)(GF_NFSFH_MAX_HASH_BYTES / GF_NFSFH_ENTRYHASH_SIZE))  #define nfs3_fh_hashcounted_size(hcount) (GF_NFSFH_STATIC_SIZE + (hcount * GF_NFSFH_ENTRYHASH_SIZE)) +#define nfs3_fh_exportid_to_index(exprtid)      ((uint16_t)exprtid[15])  /* ATTENTION: Change in size of the structure below should be reflected in the   * GF_NFSFH_STATIC_SIZE.   */ @@ -56,18 +58,28 @@ struct nfs3_fh {           */          char                    ident[2]; +        /* UUID that identifies an export. The value stored in exportid +         * depends on the usage of gluster nfs. If the DVM is enabled using +         * the nfs.dynamic-volumes option then exportid will contain the UUID +         * of the volume so that gnfs is able to identify volumes uniquely +         * through volume additions,deletions,migrations, etc. +         * +         * When not using dvm, exportid contains the index of the volume +         * based on the position of the volume in the list of subvolumes +         * for gnfs. +         */ +        uuid_t              exportid; + +        /* File/dir gfid. */ +        uuid_t                  gfid; +          /* Number of file/ino hash elements that follow the ino. */          uint16_t                hashcount; -        /* Basically, the position/index of an xlator among the children of -         * the NFS xlator. -         */ -        uint16_t                xlatorid; -        uint64_t                gen; -        uint64_t                ino;          nfs3_hash_entry_t       entryhash[GF_NFSFH_MAXHASHES];  } __attribute__((__packed__)); +#define GF_NFS3FH_STATIC_INITIALIZER    {{0},}  extern uint32_t  nfs3_fh_compute_size (struct nfs3_fh *fh); @@ -76,16 +88,13 @@ extern int  nfs3_fh_hash_index_is_beyond (struct nfs3_fh *fh, int hashidx);  extern uint16_t -nfs3_fh_hash_entry (ino_t ino, uint64_t gen); +nfs3_fh_hash_entry (uuid_t gfid);  extern int  nfs3_fh_validate (struct nfs3_fh *fh); -extern xlator_t * -nfs3_fh_to_xlator (xlator_list_t *cl, struct nfs3_fh *fh); -  extern struct nfs3_fh -nfs3_fh_build_root_fh (xlator_list_t *cl, xlator_t *xl); +nfs3_fh_build_indexed_root_fh (xlator_list_t *cl, xlator_t *xl);  extern int  nfs3_fh_is_root_fh (struct nfs3_fh *fh); @@ -103,4 +112,7 @@ nfs3_fh_to_str (struct nfs3_fh *fh, char *str);  extern int  nfs3_fh_build_parent_fh (struct nfs3_fh *child, struct iatt *newstat,                           struct nfs3_fh *newfh); + +extern struct nfs3_fh +nfs3_fh_build_uuid_root_fh (uuid_t volumeid);  #endif diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c index 5a5a0b29df3..9ccfb07ca40 100644 --- a/xlators/nfs/server/src/nfs3-helpers.c +++ b/xlators/nfs/server/src/nfs3-helpers.c @@ -92,12 +92,12 @@ struct nfs3stat_strerror nfs3stat_strerror_table[] = {  void -nfs3_map_xlid_to_statdev (struct iatt *ia, uint16_t xlid) +nfs3_map_deviceid_to_statdev (struct iatt *ia, uint64_t deviceid)  {          if (!ia)                  return; -        ia->ia_dev = xlid; +        ia->ia_dev = deviceid;  } @@ -395,15 +395,11 @@ nfs3_fill_lookup3res_success (lookup3res *res, nfsstat3 stat,          obj.attributes_follow = FALSE;          dir.attributes_follow = FALSE; -        if (buf && fh) { -                nfs3_map_xlid_to_statdev (buf, fh->xlatorid); +        if (buf)                  obj = nfs3_stat_to_post_op_attr (buf); -        } -        if (postparent && fh) { -                nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); +        if (postparent)                  dir = nfs3_stat_to_post_op_attr (postparent); -        }          res->lookup3res_u.resok.obj_attributes = obj;          res->lookup3res_u.resok.dir_attributes = dir; @@ -412,10 +408,13 @@ nfs3_fill_lookup3res_success (lookup3res *res, nfsstat3 stat,  void  nfs3_fill_lookup3res (lookup3res *res, nfsstat3 stat, struct nfs3_fh *newfh, -                      struct iatt *buf, struct iatt *postparent) +                      struct iatt *buf, struct iatt *postparent, +                      uint64_t deviceid)  {          memset (res, 0, sizeof (*res)); +        nfs3_map_deviceid_to_statdev (buf, deviceid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid);          if (stat != NFS3_OK)                  nfs3_fill_lookup3res_error (res, stat, postparent);          else @@ -432,7 +431,7 @@ nfs3_extract_getattr_fh (getattr3args *args)  void  nfs3_fill_getattr3res (getattr3res *res, nfsstat3 stat, struct iatt *buf, -                       uint16_t xlid) +                       uint64_t deviceid)  {          memset (res, 0, sizeof (*res)); @@ -440,7 +439,7 @@ nfs3_fill_getattr3res (getattr3res *res, nfsstat3 stat, struct iatt *buf,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (buf, xlid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          res->getattr3res_u.resok.obj_attributes = nfs3_stat_to_fattr3 (buf);  } @@ -455,7 +454,7 @@ nfs3_extract_fsinfo_fh (fsinfo3args *args)  void  nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res, -                      nfsstat3 status, struct iatt *fsroot, uint16_t xlid) +                      nfsstat3 status, struct iatt *fsroot, uint64_t deviceid)  {          fsinfo3resok    resok = {{0}, };          nfstime3        tdelta = GF_NFS3_TIMEDELTA_SECS; @@ -465,7 +464,7 @@ nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res,          if (status != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (fsroot, xlid); +        nfs3_map_deviceid_to_statdev (fsroot, deviceid);          resok.obj_attributes = nfs3_stat_to_post_op_attr (fsroot);          resok.rtmax = nfs3->readsize;          resok.rtpref = nfs3->readsize; @@ -677,7 +676,8 @@ nfs3_stat_to_accessbits (struct iatt *buf, uint32_t request, uid_t uid,  void  nfs3_fill_access3res (access3res *res, nfsstat3 status, struct iatt *buf, -                      uint32_t accbits, uid_t uid, gid_t gid, uint16_t xlid) +                      uint32_t accbits, uid_t uid, gid_t gid, +                      uint64_t deviceid)  {          post_op_attr    objattr;          uint32_t        accres = 0; @@ -687,7 +687,7 @@ nfs3_fill_access3res (access3res *res, nfsstat3 status, struct iatt *buf,          if (status != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (buf, xlid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          objattr = nfs3_stat_to_post_op_attr (buf);          accres = nfs3_stat_to_accessbits (buf, accbits, uid, gid); @@ -829,7 +829,7 @@ nfs3_fh_to_post_op_fh3 (struct nfs3_fh *fh)  entryp3 * -nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh) +nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh, uint64_t devid)  {          entryp3         *ent = NULL;          struct nfs3_fh  newfh = {{0}, }; @@ -862,7 +862,7 @@ nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh)          strcpy (ent->name, entry->d_name);          nfs3_fh_build_child_fh (dirfh, &entry->d_stat, &newfh); -        nfs3_map_xlid_to_statdev (&entry->d_stat, dirfh->xlatorid); +        nfs3_map_deviceid_to_statdev (&entry->d_stat, devid);          ent->name_attributes = nfs3_stat_to_post_op_attr (&entry->d_stat);          ent->name_handle = nfs3_fh_to_post_op_fh3 (&newfh);  err: @@ -873,7 +873,8 @@ err:  void  nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,                         uint64_t cverf, struct iatt *dirstat, -                       gf_dirent_t *entries, count3 count, int is_eof) +                       gf_dirent_t *entries, count3 count, int is_eof, +                       uint64_t deviceid)  {          post_op_attr    dirattr;          entry3          *ent = NULL; @@ -887,7 +888,7 @@ nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (dirstat, dirfh->xlatorid); +        nfs3_map_deviceid_to_statdev (dirstat, deviceid);          dirattr = nfs3_stat_to_post_op_attr (dirstat);          res->readdir3res_u.resok.dir_attributes = dirattr;          res->readdir3res_u.resok.reply.eof = (bool_t)is_eof; @@ -928,10 +929,11 @@ nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,  void -nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh, -                        uint64_t cverf, struct iatt *dirstat, -                        gf_dirent_t *entries, count3 dircount, count3 maxcount, -                        int is_eof) +nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, +                        struct nfs3_fh *dirfh, uint64_t cverf, +                        struct iatt *dirstat, gf_dirent_t *entries, +                        count3 dircount, count3 maxcount, int is_eof, +                        uint64_t deviceid)  {          post_op_attr    dirattr;          entryp3         *ent = NULL; @@ -946,7 +948,7 @@ nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (dirstat, dirfh->xlatorid); +        nfs3_map_deviceid_to_statdev (dirstat, deviceid);          dirattr = nfs3_stat_to_post_op_attr (dirstat);          res->readdirp3res_u.resok.dir_attributes = dirattr;          res->readdirp3res_u.resok.reply.eof = (bool_t)is_eof; @@ -964,7 +966,7 @@ nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh,                      (strcmp (entries->d_name, "..") == 0))                          goto nextentry;                          */ -                ent = nfs3_fill_entryp3 (entries, dirfh); +                ent = nfs3_fill_entryp3 (entries, dirfh, deviceid);                  if (!ent)                          break; @@ -1050,7 +1052,7 @@ nfs3_prep_fsstat3args (fsstat3args *args, struct nfs3_fh *fh)  void  nfs3_fill_fsstat3res (fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf, -                      struct iatt *postbuf, uint16_t xlid) +                      struct iatt *postbuf, uint64_t deviceid)  {          post_op_attr    poa;          fsstat3resok    resok; @@ -1060,7 +1062,7 @@ nfs3_fill_fsstat3res (fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (postbuf, xlid); +        nfs3_map_deviceid_to_statdev (postbuf, deviceid);          poa = nfs3_stat_to_post_op_attr (postbuf);          resok.tbytes = (size3)(fsbuf->f_frsize * fsbuf->f_blocks);          resok.fbytes = (size3)(fsbuf->f_bsize * fsbuf->f_bfree); @@ -1209,7 +1211,7 @@ nfs3_stat_to_wcc_data (struct iatt *pre, struct iatt *post)  void  nfs3_fill_create3res (create3res *res, nfsstat3 stat, struct nfs3_fh *newfh,                        struct iatt *newbuf, struct iatt *preparent, -                      struct iatt *postparent) +                      struct iatt *postparent, uint64_t deviceid)  {          post_op_attr    poa = {0, };          wcc_data        dirwcc = {{0}, }; @@ -1220,14 +1222,12 @@ nfs3_fill_create3res (create3res *res, nfsstat3 stat, struct nfs3_fh *newfh,                  return;          nfs3_fill_post_op_fh3 (newfh, &res->create3res_u.resok.obj); -        nfs3_map_xlid_to_statdev (newbuf, newfh->xlatorid); +        nfs3_map_deviceid_to_statdev (newbuf, deviceid);          poa = nfs3_stat_to_post_op_attr (newbuf);          res->create3res_u.resok.obj_attributes = poa; -        if (preparent) { -                nfs3_map_xlid_to_statdev (preparent, newfh->xlatorid); -                nfs3_map_xlid_to_statdev (postparent, newfh->xlatorid); -                dirwcc = nfs3_stat_to_wcc_data (preparent, postparent); -        } +        nfs3_map_deviceid_to_statdev (preparent, deviceid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid); +        dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);          res->create3res_u.resok.dir_wcc = dirwcc;  } @@ -1251,7 +1251,7 @@ nfs3_prep_setattr3args (setattr3args *args, struct nfs3_fh *fh)  void  nfs3_fill_setattr3res (setattr3res *res, nfsstat3 stat, struct iatt *preop, -                       struct iatt *postop, uint16_t xlid) +                       struct iatt *postop, uint64_t deviceid)  {          wcc_data        wcc;          memset (res, 0, sizeof (*res)); @@ -1259,8 +1259,8 @@ nfs3_fill_setattr3res (setattr3res *res, nfsstat3 stat, struct iatt *preop,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (preop, xlid); -        nfs3_map_xlid_to_statdev (postop, xlid); +        nfs3_map_deviceid_to_statdev (preop, deviceid); +        nfs3_map_deviceid_to_statdev (postop, deviceid);          wcc = nfs3_stat_to_wcc_data (preop, postop);          res->setattr3res_u.resok.obj_wcc = wcc;  } @@ -1279,7 +1279,7 @@ nfs3_prep_mkdir3args (mkdir3args *args, struct nfs3_fh *dirfh, char *name)  void  nfs3_fill_mkdir3res (mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh,                       struct iatt *buf, struct iatt *preparent, -                     struct iatt *postparent) +                     struct iatt *postparent, uint64_t deviceid)  {          wcc_data        dirwcc;          post_op_attr    poa; @@ -1290,10 +1290,10 @@ nfs3_fill_mkdir3res (mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh,                  return;          nfs3_fill_post_op_fh3 (fh, &res->mkdir3res_u.resok.obj); -        nfs3_map_xlid_to_statdev (buf, fh->xlatorid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          poa = nfs3_stat_to_post_op_attr (buf); -        nfs3_map_xlid_to_statdev (preparent, fh->xlatorid); -        nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); +        nfs3_map_deviceid_to_statdev (preparent, deviceid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid);          dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);          res->mkdir3res_u.resok.obj_attributes = poa;          res->mkdir3res_u.resok.dir_wcc = dirwcc; @@ -1315,7 +1315,7 @@ nfs3_prep_symlink3args (symlink3args *args, struct nfs3_fh *dirfh, char *name,  void  nfs3_fill_symlink3res (symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh,                         struct iatt *buf, struct iatt *preparent, -                       struct iatt *postparent) +                       struct iatt *postparent, uint64_t deviceid)  {          wcc_data        dirwcc;          post_op_attr    poa; @@ -1326,10 +1326,10 @@ nfs3_fill_symlink3res (symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh,                  return;          nfs3_fill_post_op_fh3 (fh, &res->symlink3res_u.resok.obj); -        nfs3_map_xlid_to_statdev (buf, fh->xlatorid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          poa = nfs3_stat_to_post_op_attr (buf); -        nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); -        nfs3_map_xlid_to_statdev (preparent, fh->xlatorid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid); +        nfs3_map_deviceid_to_statdev (preparent, deviceid);          dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);          res->symlink3res_u.resok.obj_attributes = poa;          res->symlink3res_u.resok.dir_wcc = dirwcc; @@ -1348,7 +1348,7 @@ nfs3_prep_readlink3args (readlink3args *args, struct nfs3_fh *fh)  void  nfs3_fill_readlink3res (readlink3res *res, nfsstat3 stat, char *path, -                        struct iatt *buf, uint16_t xlid) +                        struct iatt *buf, uint64_t deviceid)  {          post_op_attr    poa; @@ -1358,7 +1358,7 @@ nfs3_fill_readlink3res (readlink3res *res, nfsstat3 stat, char *path,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (buf, xlid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          poa = nfs3_stat_to_post_op_attr (buf);          res->readlink3res_u.resok.data = (void *)path;          res->readlink3res_u.resok.symlink_attributes = poa; @@ -1377,7 +1377,7 @@ nfs3_prep_mknod3args (mknod3args *args, struct nfs3_fh *fh, char *name)  void  nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,                       struct iatt *buf, struct iatt *preparent, -                     struct iatt *postparent) +                     struct iatt *postparent, uint64_t deviceid)  {          post_op_attr    poa;          wcc_data        wccdir; @@ -1388,10 +1388,10 @@ nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,                  return;          nfs3_fill_post_op_fh3 (fh, &res->mknod3res_u.resok.obj); -        nfs3_map_xlid_to_statdev (buf, fh->xlatorid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          poa = nfs3_stat_to_post_op_attr (buf); -        nfs3_map_xlid_to_statdev (preparent, fh->xlatorid); -        nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); +        nfs3_map_deviceid_to_statdev (preparent, deviceid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid);          wccdir = nfs3_stat_to_wcc_data (preparent, postparent);          res->mknod3res_u.resok.obj_attributes = poa;          res->mknod3res_u.resok.dir_wcc = wccdir; @@ -1401,7 +1401,7 @@ nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,  void  nfs3_fill_remove3res (remove3res *res, nfsstat3 stat, struct iatt *preparent, -                      struct iatt *postparent, uint16_t xlid) +                      struct iatt *postparent, uint64_t deviceid)  {          wcc_data        dirwcc; @@ -1410,8 +1410,8 @@ nfs3_fill_remove3res (remove3res *res, nfsstat3 stat, struct iatt *preparent,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (preparent, xlid); -        nfs3_map_xlid_to_statdev (postparent, xlid); +        nfs3_map_deviceid_to_statdev (preparent, deviceid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid);          dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);          res->remove3res_u.resok.dir_wcc = dirwcc;  } @@ -1437,7 +1437,7 @@ nfs3_prep_rmdir3args (rmdir3args *args, struct nfs3_fh *fh, char *name)  void  nfs3_fill_rmdir3res (rmdir3res *res, nfsstat3 stat, struct iatt *preparent, -                     struct iatt *postparent, uint16_t xlid) +                     struct iatt *postparent, uint64_t deviceid)  {          wcc_data        dirwcc;          memset (res, 0, sizeof (*res)); @@ -1446,8 +1446,8 @@ nfs3_fill_rmdir3res (rmdir3res *res, nfsstat3 stat, struct iatt *preparent,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (postparent, xlid); -        nfs3_map_xlid_to_statdev (preparent, xlid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid); +        nfs3_map_deviceid_to_statdev (preparent, deviceid);          dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);          res->rmdir3res_u.resok.dir_wcc = dirwcc;  } @@ -1467,7 +1467,7 @@ nfs3_prep_link3args (link3args *args, struct nfs3_fh *target,  void  nfs3_fill_link3res (link3res *res, nfsstat3 stat, struct iatt *buf,                      struct iatt *preparent, struct iatt *postparent, -                    uint16_t xlid) +                    uint64_t deviceid)  {          post_op_attr    poa;          wcc_data        dirwcc; @@ -1477,9 +1477,9 @@ nfs3_fill_link3res (link3res *res, nfsstat3 stat, struct iatt *buf,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (preparent, xlid); -        nfs3_map_xlid_to_statdev (postparent, xlid); -        nfs3_map_xlid_to_statdev (buf, xlid); +        nfs3_map_deviceid_to_statdev (preparent, deviceid); +        nfs3_map_deviceid_to_statdev (postparent, deviceid); +        nfs3_map_deviceid_to_statdev (buf,deviceid);          poa = nfs3_stat_to_post_op_attr (buf);          dirwcc = nfs3_stat_to_wcc_data (preparent, postparent);          res->link3res_u.resok.file_attributes = poa; @@ -1506,7 +1506,7 @@ void  nfs3_fill_rename3res (rename3res *res, nfsstat3 stat, struct iatt *buf,                        struct iatt *preoldparent, struct iatt *postoldparent,                        struct iatt *prenewparent, struct iatt *postnewparent, -                      uint16_t xlid) +                      uint64_t deviceid)  {          wcc_data        dirwcc; @@ -1516,11 +1516,11 @@ nfs3_fill_rename3res (rename3res *res, nfsstat3 stat, struct iatt *buf,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (preoldparent, xlid); -        nfs3_map_xlid_to_statdev (postoldparent, xlid); -        nfs3_map_xlid_to_statdev (prenewparent, xlid); -        nfs3_map_xlid_to_statdev (postnewparent, xlid); -        nfs3_map_xlid_to_statdev (buf, xlid); +        nfs3_map_deviceid_to_statdev (preoldparent, deviceid); +        nfs3_map_deviceid_to_statdev (postoldparent, deviceid); +        nfs3_map_deviceid_to_statdev (prenewparent, deviceid); +        nfs3_map_deviceid_to_statdev (postnewparent, deviceid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          dirwcc = nfs3_stat_to_wcc_data (preoldparent, postoldparent);          res->rename3res_u.resok.fromdir_wcc = dirwcc;          dirwcc = nfs3_stat_to_wcc_data (prenewparent, postnewparent); @@ -1539,7 +1539,7 @@ nfs3_prep_write3args (write3args *args, struct nfs3_fh *fh)  void  nfs3_fill_write3res (write3res *res, nfsstat3 stat, count3 count,                       stable_how stable, uint64_t wverf, struct iatt *prestat, -                     struct iatt *poststat, uint16_t xlid) +                     struct iatt *poststat, uint64_t deviceid)  {          write3resok     resok;          memset (res, 0, sizeof (*res)); @@ -1547,8 +1547,8 @@ nfs3_fill_write3res (write3res *res, nfsstat3 stat, count3 count,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (prestat, xlid); -        nfs3_map_xlid_to_statdev (poststat, xlid); +        nfs3_map_deviceid_to_statdev (prestat, deviceid); +        nfs3_map_deviceid_to_statdev (poststat, deviceid);          resok.file_wcc = nfs3_stat_to_wcc_data (prestat, poststat);          resok.count = count;          resok.committed = stable; @@ -1568,15 +1568,16 @@ nfs3_prep_commit3args (commit3args *args, struct nfs3_fh *fh)  void  nfs3_fill_commit3res (commit3res *res, nfsstat3 stat, uint64_t wverf, -                      struct iatt *prestat, struct iatt *poststat,uint16_t xlid) +                      struct iatt *prestat, struct iatt *poststat, +                      uint64_t deviceid)  {          memset (res, 0, sizeof (*res));          res->status = stat;          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (poststat, xlid); -        nfs3_map_xlid_to_statdev (prestat, xlid); +        nfs3_map_deviceid_to_statdev (poststat, deviceid); +        nfs3_map_deviceid_to_statdev (prestat, deviceid);          res->commit3res_u.resok.file_wcc = nfs3_stat_to_wcc_data (prestat,                                                                    poststat);          memcpy (res->commit3res_u.resok.verf, &wverf, sizeof (wverf)); @@ -1584,7 +1585,7 @@ nfs3_fill_commit3res (commit3res *res, nfsstat3 stat, uint64_t wverf,  void  nfs3_fill_read3res (read3res *res, nfsstat3 stat, count3 count, -                    struct iatt *poststat, int is_eof, uint16_t xlid) +                    struct iatt *poststat, int is_eof, uint64_t deviceid)  {          post_op_attr    poa; @@ -1593,7 +1594,7 @@ nfs3_fill_read3res (read3res *res, nfsstat3 stat, count3 count,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (poststat, xlid); +        nfs3_map_deviceid_to_statdev (poststat, deviceid);          poa = nfs3_stat_to_post_op_attr (poststat);          res->read3res_u.resok.file_attributes = poa;          res->read3res_u.resok.count = count; @@ -1612,7 +1613,7 @@ nfs3_prep_read3args (read3args *args, struct nfs3_fh *fh)  void  nfs3_fill_pathconf3res (pathconf3res *res, nfsstat3 stat, struct iatt *buf, -                        uint16_t xlid) +                        uint64_t deviceid)  {          pathconf3resok  resok; @@ -1621,7 +1622,7 @@ nfs3_fill_pathconf3res (pathconf3res *res, nfsstat3 stat, struct iatt *buf,          if (stat != NFS3_OK)                  return; -        nfs3_map_xlid_to_statdev (buf, xlid); +        nfs3_map_deviceid_to_statdev (buf, deviceid);          resok.obj_attributes = nfs3_stat_to_post_op_attr (buf);          resok.linkmax = 256;          resok.name_max = NFS_NAME_MAX; @@ -2496,6 +2497,7 @@ nfs3_fh_resolve_check_entry (struct nfs3_fh *fh, gf_dirent_t *candidate,          struct iatt             *ia = NULL;          int                     ret = GF_NFS3_FHRESOLVE_NOTFOUND;          nfs3_hash_entry_t       entryhash = 0; +        char                    gfidstr[512];          if ((!fh) || (!candidate))                  return ret; @@ -2505,10 +2507,11 @@ nfs3_fh_resolve_check_entry (struct nfs3_fh *fh, gf_dirent_t *candidate,                  goto found_entry;          ia = &candidate->d_stat; -        if ((ia->ia_gen == fh->gen) && (ia->ia_ino == fh->ino)) { -                gf_log (GF_NFS3, GF_LOG_TRACE, "Found entry: gen: %"PRId64 -                        " ino: %"PRId64", name: %s, hashcount %d", ia->ia_gen, -                        ia->ia_ino, candidate->d_name, hashidx); +        if ((uuid_compare (candidate->d_stat.ia_gfid, fh->gfid)) == 0) { +                uuid_unparse (candidate->d_stat.ia_gfid, gfidstr); +                gf_log (GF_NFS3, GF_LOG_TRACE, "Found entry: gfid: %s, " +                        "name: %s, hashcount %d", gfidstr, candidate->d_name, +                        hashidx);                  ret = GF_NFS3_FHRESOLVE_FOUND;                  goto found_entry;          } @@ -2521,7 +2524,7 @@ nfs3_fh_resolve_check_entry (struct nfs3_fh *fh, gf_dirent_t *candidate,          if (!IA_ISDIR (candidate->d_stat.ia_type))                  goto found_entry;          entryhash = fh->entryhash[hashidx]; -        if (entryhash == nfs3_fh_hash_entry (ia->ia_ino, ia->ia_gen)) { +        if (entryhash == nfs3_fh_hash_entry (ia->ia_gfid)) {                  gf_log (GF_NFS3, GF_LOG_TRACE, "Found hash match: %s: %d, "                          "hashidx: %d", candidate->d_name, entryhash, hashidx);                  ret = GF_NFS3_FHRESOLVE_DIRFOUND; @@ -2571,20 +2574,17 @@ nfs3_fh_resolve_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  int  nfs3_fh_resolve_found_entry (nfs3_call_state_t *cs, gf_dirent_t *candidate)  { -        uint64_t        dirino = 0; -        uint64_t        dirgen = 0;          int             ret = 0;          nfs_user_t      nfu = {0, }; +        uuid_t          gfid = {0, };          if ((!cs) || (!candidate))                  return -EFAULT; -        dirino = cs->resolvedloc.inode->ino; - +        uuid_copy (gfid, cs->resolvedloc.inode->gfid);          nfs_loc_wipe (&cs->resolvedloc); -        ret = nfs_entry_loc_fill (cs->vol->itable, dirino, dirgen, -                                  candidate->d_name, &cs->resolvedloc, -                                  NFS_RESOLVE_CREATE); +        ret = nfs_entry_loc_fill (cs->vol->itable, gfid, candidate->d_name, +                                  &cs->resolvedloc, NFS_RESOLVE_CREATE);          if (ret == -ENOENT) {                  gf_log (GF_NFS3, GF_LOG_TRACE, "Entry not in itable, needs"                          " lookup"); @@ -2634,20 +2634,17 @@ err:  int  nfs3_fh_resolve_found_parent (nfs3_call_state_t *cs, gf_dirent_t *candidate)  { -        uint64_t        dirino = 0; -        uint64_t        dirgen = 0;          int             ret = 0;          nfs_user_t      nfu = {0, }; +        uuid_t          gfid = {0, };          if ((!cs) || (!candidate))                  return -EFAULT; -        dirino = cs->resolvedloc.inode->ino; - +        uuid_copy (gfid, cs->resolvedloc.inode->gfid);          nfs_loc_wipe (&cs->resolvedloc); -        ret = nfs_entry_loc_fill (cs->vol->itable, dirino, dirgen, -                                  candidate->d_name, &cs->resolvedloc, -                                  NFS_RESOLVE_CREATE); +        ret = nfs_entry_loc_fill (cs->vol->itable, gfid, candidate->d_name, +                                  &cs->resolvedloc, NFS_RESOLVE_CREATE);          if (ret == -ENOENT) {                  nfs_user_root_create (&nfu);                  ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, @@ -2789,11 +2786,11 @@ out:  int -nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uint64_t ino, uint64_t gen, -                          char *entry) +nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uuid_t dirgfid, char *entry)  {          int             ret = -EFAULT;          nfs_user_t      nfu = {0, }; +        char            gfidstr[512];          if (!cs)                  return ret; @@ -2808,10 +2805,10 @@ nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uint64_t ino, uint64_t gen,          }          nfs_user_root_create (&nfu); -        gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard dir resolution: ino:" -                " %"PRIu64", gen: %"PRIu64", entry: %s, next hashcount: %d", -                ino, gen, entry, cs->hashidx); -        ret = nfs_entry_loc_fill (cs->vol->itable, ino, gen, entry, +        uuid_unparse (dirgfid, gfidstr); +        gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard dir resolution: gfid: %s, " +                "entry: %s, next hashcount: %d", gfidstr, entry, cs->hashidx); +        ret = nfs_entry_loc_fill (cs->vol->itable, dirgfid, entry,                                    &cs->resolvedloc, NFS_RESOLVE_CREATE);          if (ret == 0) { @@ -2851,21 +2848,17 @@ int  nfs3_fh_resolve_check_response (nfs3_call_state_t *cs, gf_dirent_t *candidate,                                  int response, off_t last_offt)  { -        uint64_t        dirino = 0; -        uint64_t        dirgen = 0;          int             ret = -EFAULT;          nfs_user_t      nfu = {0, };          if (!cs)                  return ret; -        dirino = cs->resolvedloc.inode->ino; -          switch (response) {          case GF_NFS3_FHRESOLVE_DIRFOUND:                  nfs3_fh_resolve_close_cwd (cs); -                nfs3_fh_resolve_dir_hard (cs, dirino, dirgen, +                nfs3_fh_resolve_dir_hard (cs, cs->resolvedloc.inode->gfid,                                            candidate->d_name);                  break; @@ -2891,6 +2884,7 @@ nfs3_fh_resolve_search_dir (nfs3_call_state_t *cs, gf_dirent_t *entries)          gf_dirent_t     *candidate = NULL;          int             ret = GF_NFS3_FHRESOLVE_NOTFOUND;          off_t           lastoff = 0; +        char            gfidstr[512];          if ((!cs) || (!entries))                  return -EFAULT; @@ -2900,9 +2894,9 @@ nfs3_fh_resolve_search_dir (nfs3_call_state_t *cs, gf_dirent_t *entries)          list_for_each_entry (candidate, &entries->list, list) {                  lastoff = candidate->d_off; -                gf_log (GF_NFS3, GF_LOG_TRACE, "Candidate: %s, ino: %"PRIu64 -                        ", gen: %"PRIu64, candidate->d_name, candidate->d_ino, -                        candidate->d_stat.ia_gen); +                uuid_unparse (candidate->d_stat.ia_gfid, gfidstr); +                gf_log (GF_NFS3, GF_LOG_TRACE, "Candidate: %s, gfid: %s", +                        PRIu64, candidate->d_name, gfidstr);                  ret = nfs3_fh_resolve_check_entry (&cs->resolvefh, candidate,                                                     cs->hashidx);                  if (ret != GF_NFS3_FHRESOLVE_NOTFOUND) @@ -2946,6 +2940,7 @@ nfs3_fh_resolve_inode_hard (nfs3_call_state_t *cs)  {          int             ret = -EFAULT;          nfs_user_t      nfu = {0, }; +        char            gfidstr[512];          if (!cs)                  return ret; @@ -2960,11 +2955,11 @@ nfs3_fh_resolve_inode_hard (nfs3_call_state_t *cs)          }          nfs_user_root_create (&nfu); -        gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution for: ino:" -                " %"PRIu64", gen: %"PRIu64", hashcount: %d, current hashidx " -                "%d", cs->resolvefh.ino, cs->resolvefh.gen, +        uuid_unparse (cs->resolvefh.gfid, gfidstr); +        gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution for: gfid 0x%s", +                ", hashcount: %d, current hashidx %d", gfidstr,                  cs->resolvefh.hashcount, cs->hashidx); -        ret = nfs_ino_loc_fill (cs->vol->itable, 1, 0, &cs->resolvedloc); +        ret = nfs_root_loc_fill (cs->vol->itable, &cs->resolvedloc);          if (ret == 0) {                  gf_log (GF_NFS3, GF_LOG_TRACE, "Dir will be opened: %s", @@ -2988,20 +2983,21 @@ nfs3_fh_resolve_entry_hard (nfs3_call_state_t *cs)  {          int             ret = -EFAULT;          nfs_user_t      nfu = {0, }; +        char            gfidstr[512];          if (!cs)                  return ret;          nfs_loc_wipe (&cs->resolvedloc);          nfs_user_root_create (&nfu); -        gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: ino:" -                " %"PRIu64", gen: %"PRIu64", entry: %s, hashidx: %d", -                cs->resolvefh.ino, cs->resolvefh.gen, cs->resolventry, +        uuid_unparse (cs->resolvefh.gfid, gfidstr); +        gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: gfid: %s " +                ", entry: %s, hashidx: %d", gfidstr, cs->resolventry,                  cs->hashidx); -        ret = nfs_entry_loc_fill (cs->vol->itable, cs->resolvefh.ino, -                                  cs->resolvefh.gen, cs->resolventry, -                                  &cs->resolvedloc, NFS_RESOLVE_CREATE); +        ret = nfs_entry_loc_fill (cs->vol->itable, cs->resolvefh.gfid, +                                  cs->resolventry, &cs->resolvedloc, +                                  NFS_RESOLVE_CREATE);          if (ret == -2) {                  gf_log (GF_NFS3, GF_LOG_TRACE, "Entry needs lookup: %s", @@ -3031,8 +3027,7 @@ nfs3_fh_resolve_inode (nfs3_call_state_t *cs)                  return ret;          gf_log (GF_NFS3, GF_LOG_TRACE, "FH needs inode resolution"); -        inode = inode_get (cs->vol->itable, cs->resolvefh.ino, -                           cs->resolvefh.gen); +        inode = inode_find (cs->vol->itable, cs->resolvefh.gfid);          if (!inode)                  ret = nfs3_fh_resolve_inode_hard (cs);          else diff --git a/xlators/nfs/server/src/nfs3-helpers.h b/xlators/nfs/server/src/nfs3-helpers.h index db76b5cce77..b708993c400 100644 --- a/xlators/nfs/server/src/nfs3-helpers.h +++ b/xlators/nfs/server/src/nfs3-helpers.h @@ -46,7 +46,8 @@ nfs3_errno_to_nfsstat3 (int errnum);  extern void  nfs3_fill_lookup3res (lookup3res *res, nfsstat3 stat, struct nfs3_fh *newfh, -                      struct iatt *stbuf, struct iatt *postparent); +                      struct iatt *stbuf, struct iatt *postparent, +                      uint64_t deviceid);  extern post_op_attr  nfs3_stat_to_post_op_attr (struct iatt *buf); @@ -56,14 +57,14 @@ nfs3_extract_getattr_fh (getattr3args *args);  extern void  nfs3_fill_getattr3res (getattr3res *res, nfsstat3 stat, struct iatt *buf, -                       uint16_t xlid); +                       uint64_t deviceid);  extern struct nfs3_fh  nfs3_extract_fsinfo_fh (fsinfo3args *args);  extern void  nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res, -                      nfsstat3 status, struct iatt *fsroot, uint16_t xlid); +                      nfsstat3 status, struct iatt *fsroot,uint64_t deviceid);  /* Functions containing _prep_ are used specifically to work around   * the memory allocations that happen inside Sun RPC library. @@ -99,7 +100,8 @@ nfs3_prep_access3args (access3args *args, struct nfs3_fh *fh);  extern void  nfs3_fill_access3res (access3res *res, nfsstat3 status, struct iatt *buf, -                      uint32_t accbits, uid_t uid, gid_t gid, uint16_t xlid); +                      uint32_t accbits, uid_t uid, gid_t gid, +                      uint64_t deviceid);  extern char *  nfs3_fhcache_getpath (struct nfs3_state *nfs3, struct nfs3_fh *fh); @@ -113,16 +115,18 @@ nfs3_prep_readdir3args (readdir3args *ra, struct nfs3_fh *fh);  extern void  nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dfh,                         uint64_t cverf, struct iatt *dirstat, -                       gf_dirent_t *entries, count3 count, int is_eof); +                       gf_dirent_t *entries, count3 count, int is_eof, +                       uint64_t deviceid);  extern void  nfs3_prep_readdirp3args (readdirp3args *ra, struct nfs3_fh *fh);  extern void -nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh, -                        uint64_t cverf, struct iatt *dirstat, -                        gf_dirent_t *entries, count3 dircount, count3 maxcount, -                        int is_eof); +nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, +                        struct nfs3_fh *dirfh, uint64_t cverf, +                        struct iatt *dirstat, gf_dirent_t *entries, +                        count3 dircount, count3 maxcount, int is_eof, +                        uint64_t deviceid);  extern void  nfs3_free_readdirp3res (readdirp3res *res); @@ -135,14 +139,14 @@ nfs3_prep_fsstat3args (fsstat3args *args, struct nfs3_fh *fh);  extern void  nfs3_fill_fsstat3res (fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf, -                      struct iatt *postbuf, uint16_t xlid); +                      struct iatt *postbuf, uint64_t deviceid);  extern int32_t  nfs3_sattr3_to_setattr_valid (sattr3 *sattr, struct iatt *buf, mode_t *omode);  extern void  nfs3_fill_create3res (create3res *res, nfsstat3 stat, struct nfs3_fh *newfh,                        struct iatt *newbuf, struct iatt *preparent, -                      struct iatt *postparent); +                      struct iatt *postparent, uint64_t deviceid);  extern void  nfs3_prep_create3args (create3args *args, struct nfs3_fh *fh, char *name); @@ -152,7 +156,7 @@ nfs3_prep_setattr3args (setattr3args *args, struct nfs3_fh *fh);  extern void  nfs3_fill_setattr3res (setattr3res *res, nfsstat3 stat, struct iatt *preop, -                       struct iatt *postop, uint16_t xlid); +                       struct iatt *postop, uint64_t deviceid);  extern void  nfs3_prep_mkdir3args (mkdir3args *args, struct nfs3_fh *dirfh, char *name); @@ -160,7 +164,7 @@ nfs3_prep_mkdir3args (mkdir3args *args, struct nfs3_fh *dirfh, char *name);  extern void  nfs3_fill_mkdir3res (mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh,                       struct iatt *buf, struct iatt *preparent, -                     struct iatt *postparent); +                     struct iatt *postparent, uint64_t deviceid);  extern void  nfs3_prep_symlink3args (symlink3args *args, struct nfs3_fh *dirfh, char *name, @@ -169,14 +173,14 @@ nfs3_prep_symlink3args (symlink3args *args, struct nfs3_fh *dirfh, char *name,  extern void  nfs3_fill_symlink3res (symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh,                         struct iatt *buf, struct iatt *preparent, -                       struct iatt *postparent); +                       struct iatt *postparent, uint64_t deviceid);  extern void  nfs3_prep_readlink3args (readlink3args *args, struct nfs3_fh *fh);  extern void  nfs3_fill_readlink3res (readlink3res *res, nfsstat3 stat, char *path, -                        struct iatt *buf, uint16_t xlid); +                        struct iatt *buf, uint64_t deviceid);  extern void  nfs3_prep_mknod3args (mknod3args *args, struct nfs3_fh *fh, char *name); @@ -184,17 +188,17 @@ nfs3_prep_mknod3args (mknod3args *args, struct nfs3_fh *fh, char *name);  extern void  nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh,                       struct iatt *buf, struct iatt *preparent, -                     struct iatt *postparent); +                     struct iatt *postparent, uint64_t deviceid);  extern void  nfs3_fill_remove3res (remove3res *res, nfsstat3 stat, struct iatt *preparent, -                      struct iatt *postparent, uint16_t xlid); +                      struct iatt *postparent, uint64_t deviceid);  extern void  nfs3_prep_remove3args (remove3args *args, struct nfs3_fh *fh, char *name);  extern void  nfs3_fill_rmdir3res (rmdir3res *res, nfsstat3 stat, struct iatt *preparent, -                     struct iatt *postparent, uint16_t xlid); +                     struct iatt *postparent, uint64_t deviceid);  extern void  nfs3_prep_rmdir3args (rmdir3args *args, struct nfs3_fh *fh, char *name); @@ -202,7 +206,7 @@ nfs3_prep_rmdir3args (rmdir3args *args, struct nfs3_fh *fh, char *name);  extern void  nfs3_fill_link3res (link3res *res, nfsstat3 stat, struct iatt *buf,                      struct iatt *preparent, struct iatt *postparent, -                    uint16_t xlid); +                    uint64_t deviceid);  extern void  nfs3_prep_link3args (link3args *args, struct nfs3_fh *target, @@ -217,7 +221,7 @@ extern void  nfs3_fill_rename3res (rename3res *res, nfsstat3 stat, struct iatt *buf,                        struct iatt *preoldparent, struct iatt *postoldparent,                        struct iatt *prenewparent, struct iatt *postnewparent, -                      uint16_t xlid); +                      uint64_t deviceid);  extern void  nfs3_prep_write3args (write3args *args, struct nfs3_fh *fh); @@ -225,7 +229,7 @@ nfs3_prep_write3args (write3args *args, struct nfs3_fh *fh);  extern void  nfs3_fill_write3res (write3res *res, nfsstat3 stat, count3 count,                       stable_how stable, uint64_t wverf, struct iatt *prestat, -                     struct iatt *poststat, uint16_t xlid); +                     struct iatt *poststat, uint64_t deviceid);  extern void  nfs3_prep_commit3args (commit3args *args, struct nfs3_fh *fh); @@ -233,11 +237,11 @@ nfs3_prep_commit3args (commit3args *args, struct nfs3_fh *fh);  extern void  nfs3_fill_commit3res (commit3res *res, nfsstat3 stat, uint64_t wverf,                        struct iatt *prestat, struct iatt *poststat, -                      uint16_t xlid); +                      uint64_t deviceid);  extern void  nfs3_fill_read3res (read3res *res, nfsstat3 stat, count3 count, -                    struct iatt *poststat, int is_eof, uint16_t xlid); +                    struct iatt *poststat, int is_eof, uint64_t deviceid);  extern void  nfs3_prep_read3args (read3args *args, struct nfs3_fh *fh); @@ -247,7 +251,7 @@ nfs3_prep_pathconf3args (pathconf3args *args, struct nfs3_fh *fh);  extern void  nfs3_fill_pathconf3res (pathconf3res *res, nfsstat3 stat, struct iatt *buf, -                        uint16_t xlid); +                        uint64_t deviceid);  extern int  nfs3_cached_inode_opened (xlator_t *nfsxl, inode_t *inode); diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c index 057ccb60e25..c4aaef3c308 100644 --- a/xlators/nfs/server/src/nfs3.c +++ b/xlators/nfs/server/src/nfs3.c @@ -67,11 +67,86 @@                  }                                                       \          } while (0);                                                    \ -#define nfs3_export_access(nfs3state, xlid) ((nfs3state)->exports[xlid]).access -#define nfs3_check_rw_volaccess(nfs3state, xlid, status, label)          \ -        do {                                                             \ -                if (nfs3_export_access (nfs3state,xlid)!=GF_NFS3_VOLACCESS_RW){\ +struct nfs3_export * +__nfs3_get_export_by_index (struct nfs3_state *nfs3, uuid_t exportid) +{ +        struct nfs3_export      *exp = NULL; +        int                     index = 0; +        int                     searchindex = 0; + +        searchindex = nfs3_fh_exportid_to_index (exportid); +        list_for_each_entry (exp, &nfs3->exports, explist) { +                if (searchindex == index) +                        goto found; + +                ++index; +        } + +        exp = NULL; +found: +        return exp; +} + + +struct nfs3_export * +__nfs3_get_export_by_volumeid (struct nfs3_state *nfs3, uuid_t exportid) +{ +        struct nfs3_export      *exp = NULL; + +        list_for_each_entry (exp, &nfs3->exports, explist) { +                if (!uuid_compare (exportid, exp->volumeid)) +                        goto found; +        } + +        exp = NULL; +found: +        return exp; +} + + +struct nfs3_export * +__nfs3_get_export_by_exportid (struct nfs3_state *nfs3, uuid_t exportid) +{ +        struct nfs3_export      *exp = NULL; + +        if (!nfs3) +                return exp; + +        if (gf_nfs_dvm_off (nfs_state(nfs3->nfsx))) +                exp = __nfs3_get_export_by_index (nfs3, exportid); +        else +                exp = __nfs3_get_export_by_volumeid (nfs3, exportid); + +        return exp; +} + + +int +nfs3_export_access (struct nfs3_state *nfs3, uuid_t exportid) +{ +        int                     ret = GF_NFS3_VOLACCESS_RO; +        struct nfs3_export      *exp = NULL; + +        if (!nfs3) +                return ret; + +        exp = __nfs3_get_export_by_exportid (nfs3, exportid); + +        if (!exp) { +                gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to get export by ID"); +                goto err; +        } + +        ret = exp->access; + +err: +        return ret; +} + +#define nfs3_check_rw_volaccess(nfs3state, exid, status, label)         \ +        do {                                                            \ +                if (nfs3_export_access (nfs3state,exid)!=GF_NFS3_VOLACCESS_RW){\                          gf_log (GF_NFS3, GF_LOG_TRACE, "No read-write access");\                          status = NFS3ERR_ROFS;                          \                          goto label;                                     \ @@ -80,9 +155,28 @@ +xlator_t * +nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh) +{ +        xlator_t                *vol = NULL; +        struct nfs3_export      *exp = NULL; + +        if ((!nfs3) || (!fh)) +                return vol; + +        exp = __nfs3_get_export_by_exportid (nfs3, fh->exportid); +        if (!exp) +                goto out; + +        vol = exp->subvol; +out: +        return vol; +} + +  #define nfs3_map_fh_to_volume(nfs3state, handle, rqst, volume, status, label) \          do {                                                            \ -                volume = nfs3_fh_to_xlator ((nfs3state)->exportslist, handle); \ +                volume = nfs3_fh_to_xlator ((nfs3state), handle);       \                  if (!volume) {                                          \                          gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to map " \                                  "FH to vol");                           \ @@ -124,6 +218,29 @@          } while (0)                                                     \ +int +__nfs3_get_volume_id (struct nfs3_state *nfs3, xlator_t *xl, +                      uuid_t volumeid) +{ +        int                     ret = -1; +        struct nfs3_export      *exp = NULL; + +        if ((!nfs3) || (!xl)) +                return ret; + +        list_for_each_entry (exp, &nfs3->exports, explist) { +                if (exp->subvol == xl) { +                        uuid_copy (volumeid, exp->volumeid); +                        ret = 0; +                        goto out; +                } +        } + +out: +        return ret; +} + +  #define nfs3_funge_solaris_zerolen_fh(nfs3st, fhd, enam, nfsst, erl)    \          do {                                                            \                  xlator_t        *fungexl = NULL;                        \ @@ -133,16 +250,56 @@                          goto erl;                                       \                  }                                                       \                                                                          \ -                (fhd)->xlatorid = nfs_xlator_to_xlid ((nfs3st)->exportslist, \ -                                                      fungexl);         \ -                (fhd)->gen = 0;                                         \ -                (fhd)->ino = 1;                                         \ -                (enam) = NULL;                                          \ +                if ((gf_nfs_dvm_off (nfs_state (nfs3st->nfsx)))) {      \ +                        (fhd)->exportid[15] = nfs_xlator_to_xlid ((nfs3st)->exportslist, fungexl);                                                 \ +                        (fhd)->gfid[15] = 1;                            \ +                        (enam) = NULL;                                  \ +                } else {                                                \ +                        if(!__nfs3_get_volume_id ((nfs3st), fungexl, (fhd)->exportid)) { \ +                                (nfsst) = NFS3ERR_STALE;                \ +                                goto erl;                               \ +                        }                                               \ +                }                                                       \          } while (0)                                                     \ -#define nfs3_export_sync_trusted(nf3stt, xlid) ((nf3stt)->exports[xlid]).trusted_sync -#define nfs3_export_write_trusted(nf3stt, xlid) ((nf3stt)->exports[xlid]).trusted_write + +int +nfs3_export_sync_trusted (struct nfs3_state *nfs3, uuid_t exportid) +{ +        struct nfs3_export      *exp = NULL; +        int                     ret = 0; + +        if (!nfs3) +                return ret; + +        exp = __nfs3_get_export_by_exportid (nfs3, exportid); +        if (!exp) +                goto err; + +        ret = exp->trusted_sync; +err: +        return ret; +} + + +int +nfs3_export_write_trusted (struct nfs3_state *nfs3, uuid_t exportid) +{ +        struct nfs3_export      *exp = NULL; +        int                     ret = 0; + +        if (!nfs3) +                return ret; + +        exp = __nfs3_get_export_by_exportid (nfs3, exportid); +        if (!exp) +                goto err; + +        ret = exp->trusted_write; +err: +        return ret; +}  int  nfs3_solaris_zerolen_fh (struct nfs3_fh *fh, int fhlen) @@ -355,18 +512,27 @@ err:  } -uint16_t -nfs3_request_xlator_id (rpcsvc_request_t *rq) +uint64_t +nfs3_request_xlator_deviceid (rpcsvc_request_t *rq)  {          struct nfs3_state       *nfs3 = NULL;          xlator_t                *xl = NULL; +        uint64_t                devid = 0; +        uuid_t                  volumeid = {0, };          if (!rq)                  return 0;          xl = nfs_rpcsvc_request_private (rq);          nfs3 = nfs_rpcsvc_request_program_private (rq); -        return nfs_xlator_to_xlid (nfs3->exportslist, xl); +        if (gf_nfs_dvm_off (nfs_state (nfs3->nfsx))) +                devid = (uint64_t)nfs_xlator_to_xlid (nfs3->exportslist, xl); +        else { +                __nfs3_get_volume_id (nfs3, xl, volumeid); +                memcpy (&devid, &volumeid[15], sizeof (devid)); +        } + +        return devid;  } @@ -386,10 +552,10 @@ int  nfs3_getattr_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *buf)  {          getattr3res     res; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_getattr3res (&res, status, buf, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_getattr3res (&res, status, buf, deviceid);          nfs3svc_submit_reply (req, &res,                                (nfs3_serializer)xdr_serialize_getattr3res); @@ -558,10 +724,10 @@ nfs3_setattr_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preop,                      struct iatt *postop)  {          setattr3res     res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_setattr3res (&res, stat, preop, postop, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_setattr3res (&res, stat, preop, postop, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer) xdr_serialize_setattr3res);          return 0; @@ -761,7 +927,7 @@ nfs3_setattr (rpcsvc_request_t *req, struct nfs3_fh *fh, sattr3 *sattr,          nfs3_validate_gluster_fh (fh, stat, nfs3err);          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->setattr_valid = nfs3_sattr3_to_setattr_valid (sattr, &cs->stbuf, @@ -837,8 +1003,10 @@ nfs3_lookup_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,                     struct iatt *stbuf, struct iatt *postparent)  {          lookup3res      res = {0, }; +        uint64_t        deviceid = 0; -        nfs3_fill_lookup3res (&res, stat, newfh, stbuf, postparent); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_lookup3res (&res, stat, newfh, stbuf, postparent, deviceid);          return nfs3svc_submit_reply (req, &res,                                       (nfs3_serializer)xdr_serialize_lookup3res);  } @@ -880,6 +1048,8 @@ nfs3svc_lookup_parentdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          struct nfs3_fh                  newfh = {{0}, };          nfsstat3                        status = NFS3_OK;          nfs3_call_state_t               *cs = NULL; +        uuid_t                          volumeid = {0, }; +        struct nfs3_state               *nfs3 = NULL;          cs = frame->local;          if (op_ret == -1) { @@ -887,15 +1057,23 @@ nfs3svc_lookup_parentdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                  goto xmit_res;          } +        nfs3 = cs->nfs3state;          /* If the buf inode shows that this is a root dir's buf, then the file           * handle needs to be specially crafted, in all other cases, we'll just           * create the handle normally using the buffer of the parent dir.           */ -        if (buf->ia_ino != 1) +        if (buf->ia_ino != 1) {                  nfs3_fh_build_parent_fh (&cs->fh, buf, &newfh); -        else -                newfh = nfs3_fh_build_root_fh (cs->nfs3state->exportslist, -                                               cs->vol); +                goto xmit_res; +        } + +        if (gf_nfs_dvm_off (nfs_state (nfs3->nfsx))) +                newfh = nfs3_fh_build_indexed_root_fh (nfs3->exportslist, +                                                       cs->vol); +        else { +                __nfs3_get_volume_id (nfs3, cs->vol, volumeid); +                newfh = nfs3_fh_build_uuid_root_fh (volumeid); +        }  xmit_res:          nfs3_log_newfh_res (nfs_rpcsvc_request_xid (cs->req), "LOOKUP", status, @@ -1095,13 +1273,12 @@ nfs3_access_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *buf,                     uint32_t accbits)  {          access3res      res; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); +        deviceid = nfs3_request_xlator_deviceid (req);          nfs3_fill_access3res (&res, status, buf, accbits,                                nfs_rpcsvc_request_uid (req), -                              nfs_rpcsvc_request_gid (req) -                              , xlid); +                              nfs_rpcsvc_request_gid (req), deviceid);          nfs3svc_submit_reply (req, &res,                                (nfs3_serializer)xdr_serialize_access3res);          return 0; @@ -1231,10 +1408,10 @@ nfs3_readlink_reply (rpcsvc_request_t *req, nfsstat3 stat, char *path,                       struct iatt *buf)  {          readlink3res    res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_readlink3res (&res, stat, path, buf, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_readlink3res (&res, stat, path, buf, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_readlink3res); @@ -1374,10 +1551,10 @@ nfs3_read_reply (rpcsvc_request_t *req, nfsstat3 stat, count3 count,                   struct iatt *poststat, int is_eof)  {          read3res                res = {0, }; -        uint16_t                xlid = 0; +        uint64_t                deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_read3res (&res, stat, count, poststat, is_eof, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_read3res (&res, stat, count, poststat, is_eof, deviceid);          if (stat == NFS3_OK) {                  nfs_xdr_vector_round_up (vec, vcount, count);                  /* iob can be zero if the file size was zero. If so, op_ret @@ -1564,11 +1741,11 @@ nfs3_write_reply (rpcsvc_request_t *req, nfsstat3 stat, count3 count,                    struct iatt *poststat)  {          write3res       res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); +        deviceid = nfs3_request_xlator_deviceid (req);          nfs3_fill_write3res (&res, stat, count, stable, wverf, prestat, -                             poststat, xlid); +                             poststat, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_write3res); @@ -1692,9 +1869,9 @@ nfs3svc_write_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          cs->maxcount = op_ret;          write_trusted = nfs3_export_write_trusted (cs->nfs3state, -                                                   cs->resolvefh.xlatorid); +                                                   cs->resolvefh.exportid);          sync_trusted = nfs3_export_sync_trusted (cs->nfs3state, -                                                 cs->resolvefh.xlatorid); +                                                 cs->resolvefh.exportid);          ret = nfs3_write_how (&cs->writetype, write_trusted, sync_trusted);          if (ret == -1)                  goto err; @@ -1831,7 +2008,7 @@ nfs3_write (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,          nfs3_validate_gluster_fh (fh, stat, nfs3err);          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->datacount = count;          cs->dataoffset = offset; @@ -1983,8 +2160,11 @@ nfs3_create_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *newfh,                     struct iatt *postparent)  {          create3res      res = {0, }; +        uint64_t        deviceid = 0; -        nfs3_fill_create3res (&res, stat, newfh, newbuf, preparent, postparent); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_create3res (&res, stat, newfh, newbuf, preparent, postparent, +                              deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_create3res);          return 0; @@ -2219,7 +2399,7 @@ nfs3_create (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->cookieverf = cverf; @@ -2284,8 +2464,11 @@ nfs3_mkdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,                    struct iatt *postparent)  {          mkdir3res       res = {0, }; +        uint64_t        deviceid = 0; -        nfs3_fill_mkdir3res (&res, stat, fh, buf, preparent, postparent); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_mkdir3res (&res, stat, fh, buf, preparent, postparent, +                             deviceid);          nfs3svc_submit_reply (req, &res,                                (nfs3_serializer)xdr_serialize_mkdir3res);          return 0; @@ -2423,7 +2606,7 @@ nfs3_mkdir (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->parent = *dirfh; @@ -2481,8 +2664,11 @@ nfs3_symlink_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,                      struct iatt *postparent)  {          symlink3res     res = {0, }; +        uint64_t        deviceid = 0; -        nfs3_fill_symlink3res (&res, stat, fh, buf, preparent, postparent); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_symlink3res (&res, stat, fh, buf, preparent, postparent, +                               deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_symlink3res); @@ -2570,7 +2756,7 @@ nfs3_symlink (rpcsvc_request_t *req, struct nfs3_fh *dirfh, char *name,          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->parent = *dirfh; @@ -2638,7 +2824,11 @@ nfs3_mknod_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *fh,                    struct iatt *postparent)  {          mknod3res       res = {0, }; -        nfs3_fill_mknod3res (&res, stat, fh, buf, preparent, postparent); +        uint64_t        deviceid = 0; + +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_mknod3res (&res, stat, fh, buf, preparent, postparent, +                             deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_mknod3res); @@ -2838,7 +3028,7 @@ nfs3_mknod (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name,          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->mknodtype = nodedata->type; @@ -2915,10 +3105,10 @@ nfs3_remove_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent                     , struct iatt *postparent)  {          remove3res      res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_remove3res (&res, stat, preparent, postparent, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_remove3res (&res, stat, preparent, postparent, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_remove3res);          return 0; @@ -3037,7 +3227,7 @@ nfs3_remove (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          ret = nfs3_fh_resolve_and_resume (cs, fh, name, nfs3_remove_resume); @@ -3094,10 +3284,10 @@ nfs3_rmdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *preparent,                    struct iatt *postparent)  {          rmdir3res       res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_rmdir3res (&res, stat, preparent, postparent, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_rmdir3res (&res, stat, preparent, postparent, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_rmdir3res);          return 0; @@ -3180,7 +3370,7 @@ nfs3_rmdir (rpcsvc_request_t *req, struct nfs3_fh *fh, char *name)          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_validate_strlen_or_goto (name, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          ret = nfs3_fh_resolve_and_resume (cs, fh, name, nfs3_rmdir_resume); @@ -3238,11 +3428,11 @@ nfs3_rename_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf,                     struct iatt *prenewparent, struct iatt *postnewparent)  {          rename3res      res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); +        deviceid = nfs3_request_xlator_deviceid (req);          nfs3_fill_rename3res (&res, stat, buf, preoldparent, postoldparent, -                              prenewparent, postnewparent, xlid); +                              prenewparent, postnewparent, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer) xdr_serialize_rename3res); @@ -3383,7 +3573,7 @@ nfs3_rename (rpcsvc_request_t *req, struct nfs3_fh *olddirfh, char *oldname,          nfs3_validate_strlen_or_goto(oldname, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, olddirfh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, olddirfh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, olddirfh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          /* While we resolve the source (fh, name) pair, we need to keep a copy @@ -3454,10 +3644,10 @@ nfs3_link_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf,                   struct iatt *preparent, struct iatt *postparent)  {          link3res        res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_link3res (&res, stat, buf, preparent, postparent, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_link3res (&res, stat, buf, preparent, postparent, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_link3res); @@ -3572,7 +3762,7 @@ nfs3_link (rpcsvc_request_t *req, struct nfs3_fh *targetfh,          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_validate_strlen_or_goto(newname, NFS_NAME_MAX, nfs3err, stat, ret);          nfs3_map_fh_to_volume (nfs3, dirfh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, dirfh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, dirfh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->fh = *dirfh; @@ -3638,10 +3828,12 @@ nfs3_readdirp_reply (rpcsvc_request_t *req, nfsstat3 stat,struct nfs3_fh *dirfh,                       uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,                       count3 dircount, count3 maxcount, int is_eof)  { -        readdirp3res     res = {0, }; +        readdirp3res    res = {0, }; +        uint64_t        deviceid = 0; +        deviceid = nfs3_request_xlator_deviceid (req);          nfs3_fill_readdirp3res (&res, stat, dirfh, cverf, dirstat, entries, -                                dircount, maxcount, is_eof); +                                dircount, maxcount, is_eof, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer) xdr_serialize_readdirp3res);          nfs3_free_readdirp3res (&res); @@ -3656,9 +3848,11 @@ nfs3_readdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *dirfh,                      count3 count, int is_eof)  {          readdir3res     res = {0, }; +        uint64_t        deviceid = 0; +        deviceid = nfs3_request_xlator_deviceid (req);          nfs3_fill_readdir3res (&res, stat, dirfh, cverf, dirstat, entries, count -                               , is_eof); +                               , is_eof, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer) xdr_serialize_readdir3res);          nfs3_free_readdir3res (&res); @@ -3987,10 +4181,10 @@ nfs3_fsstat_reply (rpcsvc_request_t *req, nfsstat3 stat, struct statvfs *fsbuf,                     struct iatt *postbuf)  {          fsstat3res      res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_fsstat3res (&res, stat, fsbuf, postbuf, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_fsstat3res (&res, stat, fsbuf, postbuf, deviceid);          return nfs3svc_submit_reply (req, &res,                                       (nfs3_serializer)xdr_serialize_fsstat3res); @@ -4162,11 +4356,11 @@ nfs3_fsinfo_reply (rpcsvc_request_t *req, nfsstat3 status, struct iatt *fsroot)  {          fsinfo3res              res;          struct nfs3_state       *nfs3 = NULL; -        uint16_t                xlid = 0; +        uint64_t                deviceid = 0; -        xlid = nfs3_request_xlator_id (req); +        deviceid = nfs3_request_xlator_deviceid (req);          nfs3 = nfs_rpcsvc_request_program_private (req); -        nfs3_fill_fsinfo3res (nfs3, &res, status, fsroot, xlid); +        nfs3_fill_fsinfo3res (nfs3, &res, status, fsroot, deviceid);          nfs3svc_submit_reply (req, &res,                                (nfs3_serializer)xdr_serialize_fsinfo3res); @@ -4301,10 +4495,10 @@ int  nfs3_pathconf_reply (rpcsvc_request_t *req, nfsstat3 stat, struct iatt *buf)  {          pathconf3res    res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_pathconf3res (&res, stat, buf, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_pathconf3res (&res, stat, buf, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_pathconf3res);          return 0; @@ -4440,10 +4634,10 @@ nfs3_commit_reply (rpcsvc_request_t *req, nfsstat3 stat, uint64_t wverf,                     struct iatt *prestat, struct iatt *poststat)  {          commit3res      res = {0, }; -        uint16_t        xlid = 0; +        uint64_t        deviceid = 0; -        xlid = nfs3_request_xlator_id (req); -        nfs3_fill_commit3res (&res, stat, wverf, prestat, poststat, xlid); +        deviceid = nfs3_request_xlator_deviceid (req); +        nfs3_fill_commit3res (&res, stat, wverf, prestat, poststat, deviceid);          nfs3svc_submit_reply (req, (void *)&res,                                (nfs3_serializer)xdr_serialize_commit3res); @@ -4489,7 +4683,7 @@ nfs3_commit_resume (void *carg)          cs = (nfs3_call_state_t *)carg;          nfs3_check_fh_resolve_status (cs, stat, nfs3err); -        if (nfs3_export_sync_trusted (cs->nfs3state, cs->resolvefh.xlatorid)) { +        if (nfs3_export_sync_trusted (cs->nfs3state, cs->resolvefh.exportid)) {                  ret = -1;                  stat = NFS3_OK;                  goto nfs3err; @@ -4564,7 +4758,7 @@ nfs3_commit (rpcsvc_request_t *req, struct nfs3_fh *fh, offset3 offset,          nfs3_validate_gluster_fh (fh, stat, nfs3err);          nfs3_validate_nfs3_state (req, nfs3, stat, nfs3err, ret);          nfs3_map_fh_to_volume (nfs3, fh, req, vol, stat, nfs3err); -        nfs3_check_rw_volaccess (nfs3, fh->xlatorid, stat, nfs3err); +        nfs3_check_rw_volaccess (nfs3, fh->exportid, stat, nfs3err);          nfs3_handle_call_state_init (nfs3, cs, req, vol, stat, nfs3err);          cs->datacount = count; @@ -4753,18 +4947,60 @@ err:          return ret;  } +  int -nfs3_init_subvolume_options (struct nfs3_export *exp, dict_t *options) +nfs3_init_subvolume_options (struct nfs3_state *nfs3, struct nfs3_export *exp)  {          int             ret = -1;          char            *optstr = NULL;          char            searchkey[1024];          char            *name = NULL;          gf_boolean_t    boolt = _gf_false; +        uuid_t          volumeid = {0, }; +        dict_t          *options = NULL; -        if ((!exp) || (!options)) +        if ((!exp) || (!nfs3))                  return -1; +        options = nfs3->nfsx->options; +        uuid_clear (volumeid); +        if (gf_nfs_dvm_off (nfs_state (nfs3->nfsx))) +                goto no_dvm; + +        ret = snprintf (searchkey, 1024, "nfs3.%s.volume-id",exp->subvol->name); +        if (ret < 0) { +                gf_log (GF_MNT, GF_LOG_ERROR, "snprintf failed"); +                ret = -1; +                goto err; +        } + +        if (dict_get (options, searchkey)) { +                ret = dict_get_str (options, searchkey, &optstr); +                if (ret < 0) { +                        gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option" +                                ": %s", searchkey); +                        ret = -1; +                        goto err; +                } +        } else { +                gf_log (GF_MNT, GF_LOG_ERROR, "DVM is on but volume-id not " +                        "given for volume: %s", exp->subvol->name); +                ret = -1; +                goto err; +        } + +        if (optstr) { +                ret = uuid_parse (optstr, volumeid); +                if (ret < 0) { +                        gf_log (GF_MNT, GF_LOG_ERROR, "Failed to parse volume " +                                "UUID"); +                        ret = -1; +                        goto err; +                } +                uuid_copy (exp->volumeid, volumeid); +        } + +no_dvm:          /* Volume Access */          name = exp->subvol->name;          ret = snprintf (searchkey, 1024, "nfs3.%s.volume-access", name); @@ -4880,64 +5116,58 @@ err:  } -int -nfs3_init_subvolume (struct nfs3_state *nfs3, xlator_t *nfsx, xlator_t *subvol, -                     int xlid) +struct nfs3_export * +nfs3_init_subvolume (struct nfs3_state *nfs3, xlator_t *subvol)  {          int                     ret = -1;          struct nfs3_export      *exp = NULL; -        if ((!nfs3) || (!nfsx) || (!subvol)) -                return -1; +        if ((!nfs3) || (!subvol)) +                return NULL; -        exp = &nfs3->exports[xlid]; +        exp = GF_CALLOC (1, sizeof (*exp), gf_nfs_mt_nfs3_export);          exp->subvol = subvol; - +        INIT_LIST_HEAD (&exp->explist);          gf_log (GF_NFS3, GF_LOG_TRACE, "Initing state: %s", exp->subvol->name); -        ret = nfs3_init_subvolume_options (exp, nfsx->options); -        if (ret == -1) +        ret = nfs3_init_subvolume_options (nfs3, exp); +        if (ret == -1) {                  gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to init subvol"); +                goto exp_free; +        } -        return ret; +        ret = 0; +exp_free: +        if (ret < 0) { +                GF_FREE (exp); +                exp = NULL; +        } + +        return exp;  }  int -nfs3_init_subvolumes (struct nfs3_state *nfs3, xlator_t *nfsx) +nfs3_init_subvolumes (struct nfs3_state *nfs3)  { -        int                     xl_count = 0;          int                     ret = -1;          struct xlator_list      *xl_list = NULL; +        struct nfs3_export      *exp = NULL; -        if ((!nfs3) || (!nfsx)) +        if (!nfs3)                  return -1; -        xl_list = nfsx->children; -        while (xl_list) { -                ++xl_count; -                xl_list = xl_list->next; -        } +        xl_list = nfs3->nfsx->children; -        nfs3->exports = GF_CALLOC (xl_count, sizeof (struct nfs3_export), -                                   gf_nfs_mt_nfs3_export); -        if (!nfs3->exports) { -                gf_log (GF_NFS3, GF_LOG_ERROR, "Memory allocation failed"); -                goto err; -        } - -        xl_list = nfsx->children; -        xl_count = 0;           /* Re-using xl_count. */          while (xl_list) { -                ret = nfs3_init_subvolume (nfs3, nfsx, xl_list->xlator, -                                           xl_count); -                if (ret == -1) { +                exp = nfs3_init_subvolume (nfs3, xl_list->xlator); +                if (!exp) {                          gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to init subvol: "                                  "%s", xl_list->xlator->name);                          goto err;                  } +                list_add_tail (&exp->explist, &nfs3->exports);                  xl_list = xl_list->next; -                ++xl_count;          }          ret = 0; @@ -4983,7 +5213,8 @@ nfs3_init_state (xlator_t *nfsx)          nfs3->nfsx = nfsx;          nfs3->exportslist = nfsx->children; -        ret = nfs3_init_subvolumes (nfs3, nfsx); +        INIT_LIST_HEAD (&nfs3->exports); +        ret = nfs3_init_subvolumes (nfs3);          if (ret == -1) {                  gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to init per-subvolume "                          "state"); diff --git a/xlators/nfs/server/src/nfs3.h b/xlators/nfs/server/src/nfs3.h index 1565f26345b..f7683eaa789 100644 --- a/xlators/nfs/server/src/nfs3.h +++ b/xlators/nfs/server/src/nfs3.h @@ -82,7 +82,9 @@ struct nfs3_fd_entry {  /* Per subvolume nfs3 specific state */  struct nfs3_export { +        struct list_head        explist;          xlator_t                *subvol; +        uuid_t                  volumeid;          int                     access;          int                     trusted_sync;          int                     trusted_write; @@ -108,7 +110,7 @@ struct nfs3_state {           */          xlator_list_t           *exportslist; -        struct nfs3_export      *exports; +        struct list_head        exports;          /* Mempool for allocations of struct nfs3_local */          struct mem_pool         *localpool;  | 
