summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/bugs/bug-824753-file-locker.c42
-rwxr-xr-xtests/bugs/bug-824753.t45
-rw-r--r--xlators/features/locks/src/posix.c117
3 files changed, 188 insertions, 16 deletions
diff --git a/tests/bugs/bug-824753-file-locker.c b/tests/bugs/bug-824753-file-locker.c
new file mode 100644
index 00000000000..903e23e0a1f
--- /dev/null
+++ b/tests/bugs/bug-824753-file-locker.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+
+int main (int argc, char *argv[])
+{
+ int fd = -1;
+ int ret = -1;
+ char command[2048] = "";
+ char filepath[255] = "";
+ struct flock fl;
+
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 7;
+ fl.l_len = 1;
+ fl.l_pid = getpid();
+
+ snprintf(filepath, 255, "%s/%s", argv[4], argv[5]);
+
+ fd = open(filepath, O_RDWR);
+
+ if (fd == -1)
+ return -1;
+
+ if (fcntl(fd, F_SETLKW, &fl) == -1) {
+ return -1;
+ }
+
+ snprintf(command, sizeof(command),
+ "gluster volume clear-locks %s /%s kind all posix 0,7-1 |"
+ " grep %s | awk -F'..: ' '{print $1}' | grep %s:%s/%s",
+ argv[1], argv[5], argv[2], argv[2], argv[3], argv[1]);
+
+ ret = system (command);
+ close(fd);
+
+ if (ret)
+ return -1;
+ else
+ return 0;
+}
diff --git a/tests/bugs/bug-824753.t b/tests/bugs/bug-824753.t
new file mode 100755
index 00000000000..38f6bf6965f
--- /dev/null
+++ b/tests/bugs/bug-824753.t
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+. $(dirname $0)/../include.rc
+
+cleanup;
+
+## Start and create a volume
+TEST glusterd;
+TEST pidof glusterd;
+TEST $CLI volume info;
+
+TEST $CLI volume create $V0 replica 2 stripe 2 $H0:$B0/${V0}{1,2,3,4,5,6,7,8};
+
+function volinfo_field()
+{
+ local vol=$1;
+ local field=$2;
+
+ $CLI volume info $vol | grep "^$field: " | sed 's/.*: //';
+}
+
+## Verify volume is is created
+EXPECT "$V0" volinfo_field $V0 'Volume Name';
+EXPECT 'Created' volinfo_field $V0 'Status';
+
+## Start volume and verify
+TEST $CLI volume start $V0;
+EXPECT 'Started' volinfo_field $V0 'Status';
+
+TEST glusterfs -s $H0 --volfile-id=$V0 $M0
+touch $M0/file1;
+
+TEST gcc -g $(dirname $0)/bug-824753-file-locker.c -o $(dirname $0)/file-locker
+
+TEST $(dirname $0)/file-locker $V0 $H0 $B0 $M0 file1
+
+## Finish up
+TEST rm -f $(dirname $0)/file-locker
+TEST $CLI volume stop $V0;
+EXPECT 'Stopped' volinfo_field $V0 'Status';
+
+TEST $CLI volume delete $V0;
+TEST ! $CLI volume info $V0;
+
+cleanup;
diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c
index 34ac1cb6480..2bc5f8581f9 100644
--- a/xlators/features/locks/src/posix.c
+++ b/xlators/features/locks/src/posix.c
@@ -40,6 +40,9 @@
void do_blocked_rw (pl_inode_t *);
static int __rw_allowable (pl_inode_t *, posix_lock_t *, glusterfs_fop_t);
+static int format_brickname(char *);
+int pl_lockinfo_get_brickname (xlator_t *, inode_t *, int32_t *);
+static int fetch_pathinfo(xlator_t *, inode_t *, int32_t *, char **);
static pl_fdctx_t *
pl_new_fdctx ()
@@ -388,7 +391,7 @@ int32_t
pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
const char *name, dict_t *xdata)
{
- int op_errno = EINVAL;
+ int32_t op_errno = EINVAL;
int op_ret = -1;
int32_t bcount = 0;
int32_t gcount = 0;
@@ -396,7 +399,8 @@ pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
char *lk_summary = NULL;
pl_inode_t *pl_inode = NULL;
dict_t *dict = NULL;
- clrlk_args args = {0,};
+ clrlk_args args = {0,};
+ char *brickname = NULL;
if (!name)
goto usual;
@@ -443,29 +447,48 @@ pl_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
goto out;
}
+ op_ret = fetch_pathinfo (this, loc->inode, &op_errno, &brickname);
+ if (op_ret) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Couldn't get brickname");
+ } else {
+ op_ret = format_brickname(brickname);
+ if (op_ret) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Couldn't format brickname");
+ GF_FREE(brickname);
+ brickname = NULL;
+ }
+ }
+
if (!gcount && !bcount) {
if (gf_asprintf (&lk_summary, "No locks cleared.") == -1) {
+ op_ret = -1;
op_errno = ENOMEM;
goto out;
}
} else if (gf_asprintf (&lk_summary, "%s: %s blocked locks=%d "
- "granted locks=%d", this->name,
+ "granted locks=%d",
+ (brickname == NULL)? this->name : brickname,
(args.type == CLRLK_INODE)? "inode":
(args.type == CLRLK_ENTRY)? "entry":
(args.type == CLRLK_POSIX)? "posix": " ",
bcount, gcount) == -1) {
+ op_ret = -1;
op_errno = ENOMEM;
goto out;
}
strncpy (key, name, strlen (name));
if (dict_set_dynstr (dict, key, lk_summary)) {
+ op_ret = -1;
op_errno = ENOMEM;
goto out;
}
op_ret = 0;
out:
+ GF_FREE(brickname);
STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, xdata);
GF_FREE (args.opts);
@@ -481,16 +504,47 @@ usual:
return 0;
}
-int
-pl_lockinfo_get_brickname (xlator_t *this, inode_t *inode, int32_t *op_errno)
+static int
+format_brickname(char *brickname)
+{
+ int ret = -1;
+ char *hostname = NULL;
+ char *volume = NULL;
+ char *saveptr = NULL;
+
+ if (!brickname)
+ goto out;
+
+ strtok_r(brickname, ":", &saveptr);
+ hostname = gf_strdup(strtok_r(NULL, ":", &saveptr));
+ if (hostname == NULL)
+ goto out;
+ volume = gf_strdup(strtok_r(NULL, ".", &saveptr));
+ if (volume == NULL)
+ goto out;
+
+ sprintf(brickname, "%s:%s", hostname, volume);
+
+ ret = 0;
+out:
+ GF_FREE(hostname);
+ GF_FREE(volume);
+ return ret;
+}
+
+static int
+fetch_pathinfo (xlator_t *this, inode_t *inode, int32_t *op_errno,
+ char **brickname)
{
int ret = -1;
loc_t loc = {0, };
dict_t *dict = NULL;
- posix_locks_private_t *priv = NULL;
- char *brickname = NULL, *end = NULL;
- priv = this->private;
+ if (!brickname)
+ goto out;
+
+ if (!op_errno)
+ goto out;
uuid_copy (loc.gfid, inode->gfid);
loc.inode = inode_ref (inode);
@@ -502,30 +556,60 @@ pl_lockinfo_get_brickname (xlator_t *this, inode_t *inode, int32_t *op_errno)
goto out;
}
- ret = dict_get_str (dict, GF_XATTR_PATHINFO_KEY, &brickname);
- if (brickname == NULL) {
+ ret = dict_get_str (dict, GF_XATTR_PATHINFO_KEY, brickname);
+ if (ret)
goto out;
+
+ *brickname = gf_strdup(*brickname);
+ if (*brickname == NULL) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+out:
+ if (dict != NULL) {
+ dict_unref (dict);
}
+ loc_wipe(&loc);
+
+ return ret;
+}
+
+
+int
+pl_lockinfo_get_brickname (xlator_t *this, inode_t *inode, int32_t *op_errno)
+{
+ int ret = -1;
+ posix_locks_private_t *priv = NULL;
+ char *brickname = NULL;
+ char *end = NULL;
+ char *tmp = NULL;
+
+ priv = this->private;
+
+ ret = fetch_pathinfo (this, inode, op_errno, &brickname);
+ if (ret)
+ goto out;
end = strrchr (brickname, ':');
if (!end) {
+ GF_FREE(brickname);
+ ret = -1;
goto out;
}
+ tmp = brickname;
brickname = gf_strndup (brickname, (end - brickname));
if (brickname == NULL) {
+ ret = -1;
goto out;
}
priv->brickname = brickname;
ret = 0;
out:
- if (dict != NULL) {
- dict_unref (dict);
- }
-
- inode_unref (loc.inode);
-
+ GF_FREE(tmp);
return ret;
}
@@ -2473,6 +2557,7 @@ fini (xlator_t *this)
if (!priv)
return 0;
this->private = NULL;
+ GF_FREE (priv->brickname);
GF_FREE (priv);
return 0;