diff options
| -rw-r--r-- | tests/bugs/bug-824753-file-locker.c | 42 | ||||
| -rwxr-xr-x | tests/bugs/bug-824753.t | 45 | ||||
| -rw-r--r-- | xlators/features/locks/src/posix.c | 117 | 
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 000000000..903e23e0a --- /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 000000000..38f6bf696 --- /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 34ac1cb64..2bc5f8581 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;  | 
