summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglusterfs/src/inode.c26
-rw-r--r--libglusterfs/src/inode.h3
-rw-r--r--xlators/protocol/server/src/server-rpc-fops.c56
-rw-r--r--xlators/protocol/server/src/server.h3
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 */