diff options
Diffstat (limited to 'xlators/features/snapview-server/src/snapview-server.c')
| -rw-r--r-- | xlators/features/snapview-server/src/snapview-server.c | 160 | 
1 files changed, 131 insertions, 29 deletions
diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c index 21f3dbee563..a9c95850f3e 100644 --- a/xlators/features/snapview-server/src/snapview-server.c +++ b/xlators/features/snapview-server/src/snapview-server.c @@ -575,8 +575,10 @@ svs_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd,                  op_errno = 0;                  goto out;          } else if (inode_ctx->type == SNAP_VIEW_VIRTUAL_INODE) { -                fs = inode_ctx->fs; -                object = inode_ctx->object; + +                SVS_GET_INODE_CTX_INFO(inode_ctx, fs, object, this, loc, op_ret, +                                       op_errno, out); +                  glfd = glfs_h_opendir (fs, object);                  if (!glfd) {                          op_ret = -1; @@ -701,8 +703,10 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,                  op_errno = EINVAL;                  goto out;          } else if (inode_ctx->type == SNAP_VIEW_VIRTUAL_INODE) { -                fs = inode_ctx->fs; -                object = inode_ctx->object; + +                SVS_GET_INODE_CTX_INFO(inode_ctx, fs, object, this, loc, op_ret, +                                       op_errno, out); +                  dict = dict_new ();                  if (!dict) {                          gf_log (this->name, GF_LOG_ERROR, "failed to " @@ -1439,6 +1443,118 @@ unwind:          return 0;  } +/* + * This function is mainly helpful for NFS. Till now NFS server was not linking + * the inodes in readdirp, which caused problems when below operations were + * performed. + * + * 1) ls -l in one of the snaopshots (snapview-server would generate gfids for + *    each entry on the fly and link the inodes associated with those entries) + * 2) NFS server upon getting readdirp reply would not link the inodes of the + *    entries. But it used to generate filehandles for each entry and associate + *    the gfid of that entry with the filehandle and send it as part of the + *    reply to nfs client. + * 3) NFS client would send the filehandle of one of those entries when some + *    activity is done on it. + * 4) NFS server would not be able to find the inode for the gfid present in the + *    filehandle (as the inode was not linked) and would go for hard resolution + *    by sending a lookup on the gfid by creating a new inode. + * 5) snapview-client will not able to identify whether the inode is a real + *    inode existing in the main volume or a virtual inode existing in the + *    snapshots as there would not be any inode context. + * 6) Since the gfid upon which lookup is sent is a virtual gfid which is not + *    present in the disk, lookup would fail and the application would get an + *    error. + * + * The above problem is fixed by the below commit which makes snapview server + * more compatible with nfs server (1dea949cb60c3814c9206df6ba8dddec8d471a94). + * But now because NFS server does inode linking in readdirp has introduced + * the below issue. + * In readdirp though snapview-server allocates inode contexts it does not + * actually perform lookup on each entry it obtained in readdirp (as doing + * a lookup via gfapi over the network for each entry would be costly). + * + * Till now it was not a problem with NFS server, as NFS was sending a lookup on + * the gfid it got from NFS client, for which it was not able to find the right + * inode. So snapview-server was able to get the fs instance (glfs_t) of the + * snapshot volume to which the entry belongs to, and the handle for the entry + * from the corresponding snapshot volume and fill those informations in the + * inode context. + * + * But now, since NFS server is able to find the inode from the inode table for + * the gfid it got from the NFS client, it wont send lookup. Rather it directly + * sends the fop it received from the client. Now this causes problems for + * snapview-server. Because for each fop snapview-server assumes that lookup has + * been performed on that entry and the entry's inode context contains the + * pointers for the fs instance and the handle to the entry in that fs. When NFS + * server sends the fop and snapview-server finds that the fs instance and the + * handle within the inode context are NULL it unwinds with EINVAL. + * + * So to handle this, if fs instance or handle within the inode context are + * NULL, then do a lookup based on parent inode context's fs instance. And + * unwind the results obtained as part of lookup + */ + +int32_t +svs_get_handle (xlator_t *this, loc_t *loc, svs_inode_t *inode_ctx, +                int32_t *op_errno) +{ +        svs_inode_t   *parent_ctx   = NULL; +        int            ret          = -1; +        inode_t       *parent       = NULL; +        struct iatt    postparent   = {0, }; +        struct iatt    buf          = {0, }; +        char           uuid1[64]; + +        GF_VALIDATE_OR_GOTO ("snap-view-daemon", this, out); +        GF_VALIDATE_OR_GOTO (this->name, loc, out); +        GF_VALIDATE_OR_GOTO (this->name, loc->inode, out); + +        if (loc->path) { +                if (!loc->name || (loc->name && !strcmp (loc->name, ""))) { +                        loc->name = strrchr (loc->path, '/'); +                        if (loc->name) +                                loc->name++; +                } +        } + +        if (loc->parent) +                parent = inode_ref (loc->parent); +        else { +                parent = inode_find (loc->inode->table, loc->pargfid); +                if (!parent) +                        parent = inode_parent (loc->inode, NULL, NULL); +        } + +        if (parent) +                parent_ctx = svs_inode_ctx_get (this, parent); + +        if (!parent_ctx) { +                gf_log (this->name, GF_LOG_WARNING, "failed to get the parent " +                        "context for %s (%s)", loc->path, +                        uuid_utoa_r (loc->inode->gfid, uuid1)); +                *op_errno = EINVAL; +                goto out; +        } + +        if (parent_ctx) { +                if (parent_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE) +                        ret = svs_lookup_snapshot (this, loc, &buf, +                                                   &postparent, parent, +                                                   parent_ctx, op_errno); +                else +                        ret = svs_lookup_entry (this, loc, &buf, +                                                &postparent, parent, +                                                parent_ctx, op_errno); +        } + +out: +        if (parent) +                inode_unref (parent); + +        return ret; +} +  int32_t  svs_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)  { @@ -1477,8 +1593,10 @@ svs_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)                  svs_iatt_fill (loc->inode->gfid, &buf);                  op_ret = 0;          } else if (inode_ctx->type == SNAP_VIEW_VIRTUAL_INODE) { -                fs = inode_ctx->fs; -                object = inode_ctx->object; + +                SVS_GET_INODE_CTX_INFO(inode_ctx, fs, object, this, loc, op_ret, +                                       op_errno, out); +                  ret = glfs_h_stat (fs, object, &stat);                  if (ret) {                          gf_log (this->name, GF_LOG_ERROR, "glfs_h_stat on %s " @@ -1599,8 +1717,8 @@ svs_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,          if (inode_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE)                  GF_ASSERT (0); // on entry point it should always be opendir -        fs = inode_ctx->fs; -        object = inode_ctx->object; +        SVS_GET_INODE_CTX_INFO(inode_ctx, fs, object, this, loc, op_ret, +                               op_errno, out);          glfd = glfs_h_open (fs, object, flags);          if (!glfd) { @@ -1749,25 +1867,8 @@ svs_readlink (call_frame_t *frame, xlator_t *this,                  goto out;          } -        fs = inode_ctx->fs; -        if (!fs) { -                gf_log (this->name, GF_LOG_ERROR, "failed to get the fs " -                        "instance for %s (gfid: %s)", loc->name, -                        uuid_utoa (loc->inode->gfid)); -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } - -        object = inode_ctx->object; -        if (!object) { -                gf_log (this->name, GF_LOG_ERROR, "failed to get the object " -                        "for %s (gfid: %s)", loc->name, -                        uuid_utoa (loc->inode->gfid)); -                op_ret = -1; -                op_errno = ESTALE; -                goto out; -        } +        SVS_GET_INODE_CTX_INFO(inode_ctx, fs, object, this, loc, op_ret, +                               op_errno, out);          ret = glfs_h_stat (fs, object, &stat);          if (ret) { @@ -1850,8 +1951,9 @@ svs_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int mask,                  goto out;          } -        fs = inode_ctx->fs; -        object = inode_ctx->object; + +        SVS_GET_INODE_CTX_INFO(inode_ctx, fs, object, this, loc, op_ret, +                               op_errno, out);          /* The actual posix_acl xlator does acl checks differently for             fuse and nfs. So set frame->root->pid as fspid of the syncop  | 
