summaryrefslogtreecommitdiffstats
path: root/xlators/storage/posix/src/posix.c
diff options
context:
space:
mode:
authorAshish Pandey <aspandey@redhat.com>2015-11-26 14:35:49 +0530
committerPranith Kumar Karampuri <pkarampu@redhat.com>2016-01-25 03:37:10 -0800
commit195548f55b09bf71db92929b7b734407b863093c (patch)
tree08b113e723811733528e46fb454fb1e397e69820 /xlators/storage/posix/src/posix.c
parentfa6545a323df920768dd25989537e6a350c10432 (diff)
storage/posix: Implement .unlink directory
Problem: For EC volume, If a file descriptor is open and file has been unlinked, any further write on that fd will fail. When a write request comes, EC internally reads some blocks using anonymous fd. This read will fail as the file has already been unlinked. Solution: To solve this issue, we are using .unlink directory to keep track of unlinked file. If a file is to be unlinked while its fd is open, move this to .unlink directory and unlink it from .glusterfs and real path. Once all the fd will be closed, remove this entry form .unlink directory. master - http://review.gluster.org/#/c/12816/ Change-Id: I8344edb0d340bdb883dc46458c16edbc336916b9 BUG: 1291557 Signed-off-by: Ashish Pandey <aspandey@redhat.com> Reviewed-on: http://review.gluster.org/12968 Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com> Tested-by: Pranith Kumar Karampuri <pkarampu@redhat.com> Smoke: Gluster Build System <jenkins@build.gluster.com> CentOS-regression: Gluster Build System <jenkins@build.gluster.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Diffstat (limited to 'xlators/storage/posix/src/posix.c')
-rw-r--r--xlators/storage/posix/src/posix.c196
1 files changed, 187 insertions, 9 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 600ebf3f0fa..d57d53d5fca 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -106,10 +106,32 @@ int
posix_forget (xlator_t *this, inode_t *inode)
{
uint64_t tmp_cache = 0;
- if (!inode_ctx_del (inode, this, &tmp_cache))
- dict_destroy ((dict_t *)(long)tmp_cache);
+ int ret = 0;
+ char *unlink_path = NULL;
+ struct posix_private *priv_posix = NULL;
- return 0;
+ priv_posix = (struct posix_private *) this->private;
+
+ ret = inode_ctx_del (inode, this, &tmp_cache);
+ if (ret < 0) {
+ ret = 0;
+ goto out;
+ }
+ if (tmp_cache == GF_UNLINK_TRUE) {
+ POSIX_GET_FILE_UNLINK_PATH(priv_posix->base_path,
+ inode->gfid, unlink_path);
+ if (!unlink_path) {
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
+ P_MSG_UNLINK_FAILED,
+ "Failed to remove gfid :%s",
+ uuid_utoa (inode->gfid));
+ ret = -1;
+ goto out;
+ }
+ ret = sys_unlink(unlink_path);
+ }
+out:
+ return ret;
}
/* Regular fops */
@@ -1461,16 +1483,93 @@ out:
return 0;
}
+int
+posix_add_unlink_to_ctx (inode_t *inode, xlator_t *this, char *unlink_path)
+{
+ uint64_t ctx = GF_UNLINK_FALSE;
+ int ret = 0;
+
+ if (!unlink_path) {
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
+ P_MSG_UNLINK_FAILED,
+ "Creation of unlink entry failed for gfid: %s",
+ unlink_path);
+ ret = -1;
+ goto out;
+ }
+
+ ctx = GF_UNLINK_TRUE;
+ ret = posix_inode_ctx_set (inode, this, ctx);
+ if (ret < 0) {
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+int32_t
+posix_move_gfid_to_unlink (xlator_t *this, uuid_t gfid, loc_t *loc)
+{
+ char *unlink_path = NULL;
+ char *gfid_path = NULL;
+ struct stat stbuf = {0, };
+ int ret = 0;
+ struct posix_private *priv_posix = NULL;
+
+ priv_posix = (struct posix_private *) this->private;
+
+ MAKE_HANDLE_GFID_PATH (gfid_path, this, gfid, NULL);
+
+ POSIX_GET_FILE_UNLINK_PATH (priv_posix->base_path,
+ loc->inode->gfid, unlink_path);
+ if (!unlink_path) {
+ ret = -1;
+ goto out;
+ }
+ gf_msg_debug (this->name, 0,
+ "Moving gfid: %s to unlink_path : %s",
+ gfid_path, unlink_path);
+ ret = sys_rename (gfid_path, unlink_path);
+ if (ret < 0) {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ P_MSG_UNLINK_FAILED,
+ "Creation of unlink entry failed for gfid: %s",
+ unlink_path);
+ goto out;
+ }
+ ret = posix_add_unlink_to_ctx (loc->inode, this, unlink_path);
+ if (ret < 0)
+ goto out;
+
+out:
+ return ret;
+}
+
int32_t
posix_unlink_gfid_handle_and_entry (xlator_t *this, const char *real_path,
- struct iatt *stbuf, int32_t *op_errno)
+ struct iatt *stbuf, int32_t *op_errno,
+ loc_t *loc)
{
- int32_t ret = 0;
+ int32_t ret = 0;
+ struct posix_private *priv = NULL;
+ int fd_count = 0;
- /* Unlink the gfid_handle_first */
+ priv = this->private;
+ /* Unlink the gfid_handle_first */
if (stbuf && stbuf->ia_nlink == 1) {
- ret = posix_handle_unset (this, stbuf->ia_gfid, NULL);
+
+ LOCK (&loc->inode->lock);
+
+ if (loc->inode->fd_count == 0) {
+ UNLOCK (&loc->inode->lock);
+ ret = posix_handle_unset (this, stbuf->ia_gfid, NULL);
+ } else {
+ UNLOCK (&loc->inode->lock);
+ ret = posix_move_gfid_to_unlink (this, stbuf->ia_gfid,
+ loc);
+ }
if (ret) {
gf_msg (this->name, GF_LOG_ERROR, errno,
P_MSG_UNLINK_FAILED, "unlink of gfid handle "
@@ -1484,7 +1583,6 @@ posix_unlink_gfid_handle_and_entry (xlator_t *this, const char *real_path,
if (ret == -1) {
if (op_errno)
*op_errno = errno;
-
gf_msg (this->name, GF_LOG_ERROR, errno, P_MSG_UNLINK_FAILED,
"unlink of %s failed", real_path);
goto err;
@@ -1638,7 +1736,7 @@ posix_unlink (call_frame_t *frame, xlator_t *this,
}
op_ret = posix_unlink_gfid_handle_and_entry (this, real_path, &stbuf,
- &op_errno);
+ &op_errno, loc);
if (op_ret == -1) {
goto out;
}
@@ -6177,6 +6275,77 @@ out:
return ret;
}
+int32_t
+posix_create_unlink_dir (xlator_t *this) {
+
+ char *unlink_path = NULL;
+ char *landfill_path = NULL;
+ struct posix_private *priv = NULL;
+ struct stat stbuf;
+ int ret = -1;
+ uuid_t gfid = {0};
+ char gfid_str[64] = {0};
+
+ priv = this->private;
+
+ unlink_path = alloca (strlen (priv->base_path) + 1 +
+ strlen (GF_UNLINK_PATH) + 1);
+ sprintf (unlink_path, "%s/%s", priv->base_path,
+ GF_UNLINK_PATH);
+
+ gf_uuid_generate (gfid);
+ uuid_utoa_r (gfid, gfid_str);
+
+ landfill_path = alloca (strlen (priv->base_path) + 1 +
+ strlen (GF_LANDFILL_PATH) + 1 +
+ strlen (gfid_str) + 1);
+ sprintf (landfill_path, "%s/%s/%s", priv->base_path,
+ GF_LANDFILL_PATH, gfid_str);
+
+ ret = sys_stat (unlink_path, &stbuf);
+ switch (ret) {
+ case -1:
+ if (errno != ENOENT) {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ P_MSG_HANDLE_CREATE,
+ "Checking for %s failed",
+ unlink_path);
+ return -1;
+ }
+ break;
+ case 0:
+ if (!S_ISDIR (stbuf.st_mode)) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ P_MSG_HANDLE_CREATE,
+ "Not a directory: %s",
+ unlink_path);
+ return -1;
+ }
+ ret = sys_rename (unlink_path, landfill_path);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ P_MSG_HANDLE_CREATE,
+ "Can not delete directory %s ",
+ unlink_path);
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+ ret = sys_mkdir (unlink_path, 0600);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, errno,
+ P_MSG_HANDLE_CREATE,
+ "Creating directory %s failed",
+ unlink_path);
+ return -1;
+ }
+
+ return 0;
+}
+
+
/**
* init -
@@ -6588,6 +6757,15 @@ init (xlator_t *this)
goto out;
}
+ op_ret = posix_create_unlink_dir (this);
+ if (op_ret == -1) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ P_MSG_HANDLE_CREATE,
+ "Creation of unlink directory failed");
+ ret = -1;
+ goto out;
+ }
+
_private->aio_init_done = _gf_false;
_private->aio_capable = _gf_false;