diff options
| author | Shehjar Tikoo <shehjart@gluster.com> | 2010-12-23 04:28:26 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2010-12-29 10:20:36 -0800 | 
| commit | 03c791e2d699574dae077d05a171a768bfb28ec3 (patch) | |
| tree | 5b3f076df1dccf6f9cbe41737d0de7708cee48ba /xlators/nfs/server/src | |
| parent | f0eeffe7b658164fb060a9805aa6cc422aba213b (diff) | |
nfs: Support subdirectory exports
Enable exporting directories as separate exports. Even though the directories
wont show up in showmount output, they'll still be mount'able.
The new option:
        nfs.export-dirs <on|off>
is enabled by default so that users dont have to wait till this option
is incorporated into the gluster command line.
Signed-off-by: Shehjar Tikoo <shehjart@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 1743 (XenServer is not compatible with GlusterNFS)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=1743
Diffstat (limited to 'xlators/nfs/server/src')
| -rw-r--r-- | xlators/nfs/server/src/mount3.c | 189 | ||||
| -rw-r--r-- | xlators/nfs/server/src/mount3.h | 2 | ||||
| -rw-r--r-- | xlators/nfs/server/src/nfs.c | 9 | 
3 files changed, 183 insertions, 17 deletions
diff --git a/xlators/nfs/server/src/mount3.c b/xlators/nfs/server/src/mount3.c index 25754a30f..5f3a0a1a6 100644 --- a/xlators/nfs/server/src/mount3.c +++ b/xlators/nfs/server/src/mount3.c @@ -399,9 +399,10 @@ err:   * we need to strip out the volume name first.   */  char * -__volume_subdir (char *dirpath) +__volume_subdir (char *dirpath, char **volname)  {          char    *subdir = NULL; +        int     volname_len = 0;          if (!dirpath)                  return NULL; @@ -410,7 +411,19 @@ __volume_subdir (char *dirpath)                  dirpath++;          subdir = index (dirpath, (int)'/'); +        if (!subdir) +                goto out; +        if (!*volname) +                goto out; + +        /* subdir points to the first / after the volume name while dirpath +         * points to the first char of the volume name. +         */ +        volname_len = subdir - dirpath; +        strncpy (*volname, dirpath, volname_len); +        *(*volname + volname_len) = '\0'; +out:          return subdir;  } @@ -473,6 +486,7 @@ __mnt3_resolve_export_subdir_comp (mnt3_resolve_t *mres)          int             ret = -EFAULT;          nfs_user_t      nfu = {0, };          char            gfidstr[512]; +        uuid_t          gfid = {0, };          if (!mres)                  return ret; @@ -482,9 +496,9 @@ __mnt3_resolve_export_subdir_comp (mnt3_resolve_t *mres)                  goto err;          /* Wipe the contents of the previous component */ +        uuid_copy (gfid, mres->resolveloc.inode->gfid);          nfs_loc_wipe (&mres->resolveloc); -        ret = nfs_entry_loc_fill (mres->exp->vol->itable, -                                  mres->resolveloc.inode->gfid, nextcomp, +        ret = nfs_entry_loc_fill (mres->exp->vol->itable, gfid, nextcomp,                                    &mres->resolveloc, NFS_RESOLVE_CREATE);          if ((ret < 0) && (ret != -2)) {                  uuid_unparse (mres->resolveloc.inode->gfid, gfidstr); @@ -572,7 +586,7 @@ err:   * of the exported directory can be built.   */  int -__mnt3_resolve_export_subdir (mnt3_resolve_t *mres) +__mnt3_resolve_subdir (mnt3_resolve_t *mres)  {          char            dupsubdir[MNTPATHLEN];          char            *firstcomp = NULL; @@ -607,21 +621,16 @@ err:  int -mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms, -                            struct mnt3_export *exp) +mnt3_resolve_subdir (rpcsvc_request_t *req, struct mount3_state *ms, +                     struct mnt3_export *exp, char *subdir)  {          mnt3_resolve_t  *mres = NULL; -        char            *volume_subdir = NULL;          int             ret = -EFAULT;          struct nfs3_fh  pfh = GF_NFS3FH_STATIC_INITIALIZER; -        if ((!req) || (!ms) || (!exp)) +        if ((!req) || (!ms) || (!exp) || (!subdir))                  return ret; -        volume_subdir = __volume_subdir (exp->expname); -        if (!volume_subdir) -                goto err; -          mres = GF_CALLOC (1, sizeof (mnt3_resolve_t), gf_nfs_mt_mnt3_resolve);          if (!mres) {                  gf_log (GF_MNT, GF_LOG_ERROR, "Memory allocation failed"); @@ -631,14 +640,14 @@ mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms,          mres->exp = exp;          mres->mstate = ms;          mres->req = req; -        strcpy (mres->remainingdir, volume_subdir); +        strcpy (mres->remainingdir, subdir);          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); +        ret = __mnt3_resolve_subdir (mres);          if (ret < 0) {                  gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve export dir: %s"                          , mres->exp->expname); @@ -651,6 +660,32 @@ err:  int +mnt3_resolve_export_subdir (rpcsvc_request_t *req, struct mount3_state *ms, +                            struct mnt3_export *exp) +{ +        char            *volume_subdir = NULL; +        int             ret = -EFAULT; + +        if ((!req) || (!ms) || (!exp)) +                return ret; + +        volume_subdir = __volume_subdir (exp->expname, NULL); +        if (!volume_subdir) +                goto err; + +        ret = mnt3_resolve_subdir (req, ms, exp, exp->expname); +        if (ret < 0) { +                gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve export dir: %s" +                        , exp->expname); +                goto err; +        } + +err: +        return ret; +} + + +int  mnt3svc_mount (rpcsvc_request_t *req, struct mount3_state *ms,                 struct mnt3_export *exp)  { @@ -729,6 +764,82 @@ err:  int +mnt3_parse_dir_exports (rpcsvc_request_t *req, struct mount3_state *ms, +                        char *subdir) +{ +        char                    volname[1024]; +        struct mnt3_export      *exp = NULL; +        char                    *volname_ptr = NULL; +        int                     ret = -1; + +        if ((!ms) || (!subdir)) +                return -1; + +        volname_ptr = volname; +        subdir = __volume_subdir (subdir, &volname_ptr); +        if (!subdir) +                goto err; + +        exp = mnt3_mntpath_to_export (ms, volname); +        if (!exp) +                goto err; + +        ret = mnt3_resolve_subdir (req, ms, exp, subdir); +        if (ret < 0) { +                gf_log (GF_MNT, GF_LOG_ERROR, "Failed to resolve export dir: %s" +                        , subdir); +                goto err; +        } + +err: +        return ret; +} + + +int +mnt3_find_export (rpcsvc_request_t *req, char *path, struct mnt3_export **e) +{ +        int                     ret = -EFAULT; +        struct mount3_state     *ms = NULL; +        struct mnt3_export      *exp = NULL; +        struct nfs_state        *nfs = NULL; + +        if ((!req) || (!path) || (!e)) +                return -1; + +        ms = (struct mount3_state *)nfs_rpcsvc_request_program_private (req); +        if (!ms) { +                gf_log (GF_MNT, GF_LOG_ERROR, "Mount state not present"); +                nfs_rpcsvc_request_seterr (req, SYSTEM_ERR); +                goto err; +        } + +        nfs = (struct nfs_state *)ms->nfsx->private; +        gf_log (GF_MNT, GF_LOG_DEBUG, "dirpath: %s", path); +        exp = mnt3_mntpath_to_export (ms, path); +        if (exp) { +                ret = 0; +                *e = exp; +                goto err; +        } + +        if (!gf_mnt3_export_dirs(ms)) { +                ret = -1; +                goto err; +        } + +        ret = mnt3_parse_dir_exports (req, ms, path); +        if (ret == 0) { +                ret = -2; +                goto err; +        } + +err: +        return ret; +} + + +int  mnt3svc_mnt (rpcsvc_request_t *req)  {          struct iovec            pvec = {0, }; @@ -760,15 +871,18 @@ mnt3svc_mnt (rpcsvc_request_t *req)          }          ret = 0; +        nfs = (struct nfs_state *)ms->nfsx->private;          gf_log (GF_MNT, GF_LOG_DEBUG, "dirpath: %s", path); -        exp = mnt3_mntpath_to_export (ms, path); -        if (!exp) { +        ret = mnt3_find_export (req, path, &exp); +        if (ret == -2) { +                ret = 0; +                goto rpcerr; +        } else if (ret < 0) {                  ret = -1;                  mntstat = MNT3ERR_NOENT;                  goto mnterr;          } -        nfs = (struct nfs_state *)ms->nfsx->private;          if (!nfs_subvolume_started (nfs, exp->vol)) {                  gf_log (GF_MNT, GF_LOG_DEBUG, "Volume %s not started",                          exp->vol->name); @@ -1497,6 +1611,46 @@ err:  int +__mnt3_init_dir_export (struct mount3_state *ms, dict_t *opts) +{ +        int                     ret = -1; +        char                    *optstr  = NULL; +        /* On by default. */ +        gf_boolean_t            boolt = _gf_true; + +        if ((!ms) || (!opts)) +                return -1; + +        if (!dict_get (opts, "nfs3.export-dirs")) { +                ret = 0; +                goto err; +        } + +        ret = dict_get_str (opts, "nfs3.export-dirs", &optstr); +        if (ret < 0) { +                gf_log (GF_MNT, GF_LOG_ERROR, "Failed to read option: " +                        "nfs3.export-dirs"); +                ret = -1; +                goto err; +        } + +        gf_string2boolean (optstr, &boolt); +        ret = 0; + +err: +        if (boolt == _gf_false) { +                gf_log (GF_MNT, GF_LOG_TRACE, "Dir exports disabled"); +                ms->export_dirs = 0; +        } else { +                gf_log (GF_MNT, GF_LOG_TRACE, "Dir exports enabled"); +                ms->export_dirs = 1; +        } + +        return ret; +} + + +int  mnt3_init_options (struct mount3_state *ms, dict_t *options)  {          xlator_list_t   *volentry = NULL; @@ -1506,6 +1660,7 @@ mnt3_init_options (struct mount3_state *ms, dict_t *options)                  return -1;          __mnt3_init_volume_export (ms, options); +        __mnt3_init_dir_export (ms, options);          volentry = ms->nfsx->children;          while (volentry) {                  gf_log (GF_MNT, GF_LOG_TRACE, "Initing options for: %s", diff --git a/xlators/nfs/server/src/mount3.h b/xlators/nfs/server/src/mount3.h index d4d6d446f..ad4f21c98 100644 --- a/xlators/nfs/server/src/mount3.h +++ b/xlators/nfs/server/src/mount3.h @@ -99,8 +99,10 @@ struct mount3_state {          /* Set to 0 if exporting full volumes is disabled. On by default. */          int                     export_volumes; +        int                     export_dirs;  }; +#define gf_mnt3_export_dirs(mst)        ((mst)->export_dirs)  struct mount3_resolve_state {          struct mnt3_export      *exp; diff --git a/xlators/nfs/server/src/nfs.c b/xlators/nfs/server/src/nfs.c index 3291858ef..979fd2fb0 100644 --- a/xlators/nfs/server/src/nfs.c +++ b/xlators/nfs/server/src/nfs.c @@ -764,6 +764,15 @@ struct volume_options options[] = {                           "restrict exports only to the subdirectories specified"                           " through this option. Must be an absolute path."          }, +        { .key  = {"nfs3.export-dirs"}, +          .type = GF_OPTION_TYPE_BOOL, +          .description = "By default, all subvolumes of nfs are exported as " +                         "individual exports. There are cases where a " +                         "subdirectory or subdirectories in the volume need to " +                         "be exported separately. Enabling this option allows " +                         "any directory on a volumes to be exported separately." +                         " Directory exports are enabled by default." +        },          { .key  = {"nfs3.export-volumes"},            .type = GF_OPTION_TYPE_BOOL,            .description = "Enable or disable exporting whole volumes, instead "  | 
