diff options
| -rw-r--r-- | libglusterfs/src/inode.c | 26 | ||||
| -rw-r--r-- | libglusterfs/src/inode.h | 3 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-rpc-fops.c | 56 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.h | 3 | 
4 files changed, 66 insertions, 22 deletions
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index f660effcc7c..50ef98fba20 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1314,6 +1314,32 @@ inode_parent (inode_t *inode, uuid_t pargfid, const char *name)          return parent;  } +static int +__inode_has_dentry (inode_t *inode) +{ +        if (!inode) { +                gf_msg_callingfn (THIS->name, GF_LOG_WARNING, 0, +                                  LG_MSG_INODE_NOT_FOUND, "inode not found"); +                return 0; +        } + +        return !list_empty (&inode->dentry_list); +} + +int +inode_has_dentry (inode_t *inode) +{ + +        int dentry_present = 0; + +        LOCK (&inode->lock); +        { +                dentry_present = __inode_has_dentry (inode); +        } +        UNLOCK (&inode->lock); + +        return dentry_present; +}  int  __inode_path (inode_t *inode, const char *name, char **bufp) diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index 633e771fc3d..46fe8f6ac80 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -273,4 +273,7 @@ inode_set_need_lookup (inode_t *inode, xlator_t *this);  gf_boolean_t  inode_needs_lookup (inode_t *inode, xlator_t *this); +int +inode_has_dentry (inode_t *inode); +  #endif /* _INODE_H */ diff --git a/xlators/protocol/server/src/server-rpc-fops.c b/xlators/protocol/server/src/server-rpc-fops.c index 6c5d51d3dfb..d2a829f0363 100644 --- a/xlators/protocol/server/src/server-rpc-fops.c +++ b/xlators/protocol/server/src/server-rpc-fops.c @@ -27,6 +27,16 @@                  ret = RPCSVC_ACTOR_ERROR;                       \          } while (0) +void +forget_inode_if_no_dentry (inode_t *inode) +{ +        if (!inode_has_dentry (inode)) +                inode_forget (inode, 0); + +        return; +} + +  /* Callback function section */  int  server_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -103,6 +113,23 @@ server_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,                                  inode_unlink (state->loc.inode,                                                state->loc.parent,                                                state->loc.name); +                                /** +                                 * If the entry is not present, then just +                                 * unlinking the associated dentry is not +                                 * suffecient. This condition should be +                                 * treated as unlink of the entry. So along +                                 * with deleting the entry, its also important +                                 * to forget the inode for it (if the dentry +                                 * being considered was the last dentry). +                                 * Otherwise it might lead to inode leak. +                                 * It also might lead to wrong decisions being +                                 * taken if the future lookups on this inode are +                                 * successful since they are able to find the +                                 * inode in the inode table (atleast gfid based +                                 * lookups will be successful, if the lookup +                                 * is a soft lookup) +                                 */ +                                forget_inode_if_no_dentry (state->loc.inode);                          }                  }                  goto out; @@ -411,7 +438,6 @@ server_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  {          gfs3_rmdir_rsp       rsp    = {0,};          server_state_t      *state  = NULL; -        inode_t             *parent = NULL;          rpcsvc_request_t    *req    = NULL;          GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, @@ -432,15 +458,11 @@ server_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          inode_unlink (state->loc.inode, state->loc.parent,                        state->loc.name); -        parent = inode_parent (state->loc.inode, 0, NULL); -        if (parent) -                /* parent should not be found for directories after -                 * inode_unlink, since directories cannot have -                 * hardlinks. -                 */ -                inode_unref (parent); -        else -                inode_forget (state->loc.inode, 0); +        /* parent should not be found for directories after +         * inode_unlink, since directories cannot have +         * hardlinks. +         */ +        forget_inode_if_no_dentry (state->loc.inode);          gf_stat_from_iatt (&rsp.preparent, preparent);          gf_stat_from_iatt (&rsp.postparent, postparent); @@ -1021,12 +1043,7 @@ server_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          if (tmp_inode) {                  inode_unlink (tmp_inode, state->loc2.parent,                                state->loc2.name); -                tmp_parent = inode_parent (tmp_inode, 0, NULL); -                if (tmp_parent) -                        inode_unref (tmp_parent); -                else -                        inode_forget (tmp_inode, 0); - +                forget_inode_if_no_dentry (tmp_inode);                  inode_unref (tmp_inode);          } @@ -1062,7 +1079,6 @@ server_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  {          gfs3_unlink_rsp      rsp    = {0,};          server_state_t      *state  = NULL; -        inode_t             *parent = NULL;          rpcsvc_request_t    *req    = NULL;          GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, @@ -1087,11 +1103,7 @@ server_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,          inode_unlink (state->loc.inode, state->loc.parent,                        state->loc.name); -        parent = inode_parent (state->loc.inode, 0, NULL); -        if (parent) -                inode_unref (parent); -        else -                inode_forget (state->loc.inode, 0); +        forget_inode_if_no_dentry (state->loc.inode);          gf_stat_from_iatt (&rsp.preparent, preparent);          gf_stat_from_iatt (&rsp.postparent, postparent); diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h index 6caf44926c9..1055b72dad5 100644 --- a/xlators/protocol/server/src/server.h +++ b/xlators/protocol/server/src/server.h @@ -172,4 +172,7 @@ server_submit_reply (call_frame_t *frame, rpcsvc_request_t *req, void *arg,  int gf_server_check_setxattr_cmd (call_frame_t *frame, dict_t *dict);  int gf_server_check_getxattr_cmd (call_frame_t *frame, const char *name); +void +forget_inode_if_no_dentry (inode_t *inode); +  #endif /* !_SERVER_H */  | 
