diff options
| -rwxr-xr-x[-rw-r--r--] | tests/bugs/bug-767585-gfid.t | 3 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-helpers.c | 68 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 2 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.h | 2 | 
4 files changed, 72 insertions, 3 deletions
diff --git a/tests/bugs/bug-767585-gfid.t b/tests/bugs/bug-767585-gfid.t index 0cb6e3cb7..49cf7423f 100644..100755 --- a/tests/bugs/bug-767585-gfid.t +++ b/tests/bugs/bug-767585-gfid.t @@ -12,7 +12,6 @@ gfid1="0x8428b7193a764bf8be8046fb860b8993"  gfid2="0x85ad91afa2f74694bf52c3326d048209"  cleanup; -  TEST glusterd  TEST pidof glusterd  TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}0 $H0:$B0/${V0}1 @@ -25,6 +24,8 @@ touch $B0/${V0}0/c $B0/${V0}1/c  TEST setfattr -n trusted.gfid -v $gfid1 $B0/${V0}0/b  TEST setfattr -n trusted.gfid -v $gfid2 $B0/${V0}1/c +sleep 2 +  cd $M0  TEST ls -l a  TEST ls -l b diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c index 616664a3d..2fa55eda0 100644 --- a/xlators/storage/posix/src/posix-helpers.c +++ b/xlators/storage/posix/src/posix-helpers.c @@ -901,6 +901,74 @@ unlock:          UNLOCK (&priv->lock);  } +static int +is_fresh_file (struct stat *stat) +{ +        struct timeval tv; + +        gettimeofday (&tv, NULL); + +        if ((stat->st_ctime >= (tv.tv_sec - 1)) +            && (stat->st_ctime <= tv.tv_sec)) +                return 1; + +        return 0; +} + + +int +posix_gfid_heal (xlator_t *this, const char *path, loc_t *loc, dict_t *xattr_req) +{ +        /* The purpose of this function is to prevent a race +           where an inode creation FOP (like mkdir/mknod/create etc) +           races with lookup in the following way: + +                   {create thread}       |    {lookup thread} +                                         | +                                         t0 +                      mkdir ("name")     | +                                         t1 +                                         |     posix_gfid_set ("name", 2); +                                         t2 +             posix_gfid_set ("name", 1); | +                                         t3 +                      lstat ("name");    |     lstat ("name"); + +          In the above case mkdir FOP would have resulted with GFID 2 while +          it should have been GFID 1. It matters in the case where GFID would +          have gotten set to 1 on other subvolumes of replciate/distribute + +          The "solution" here is that, if we detect lookup is attempting to +          set a GFID on a file which is created very recently, but does not +          yet have a GFID (i.e, between t1 and t2), then "fake" it as though +          posix_gfid_heal was called at t0 instead. +        */ + +        uuid_t       uuid_curr; +        int          ret = 0; +        struct stat  stat = {0, }; + +        if (!xattr_req) +                goto out; + +        if (sys_lstat (path, &stat) != 0) +                goto out; + +        ret = sys_lgetxattr (path, GFID_XATTR_KEY, uuid_curr, 16); +        if (ret != 16) { +                if (is_fresh_file (&stat)) { +                        ret = -1; +                        errno = ENOENT; +                        goto out; +                } +        } + +        ret = posix_gfid_set (this, path, loc, xattr_req); +out: +        return ret; +} + +  int  posix_acl_xattr_set (xlator_t *this, const char *path, dict_t *xattr_req)  { diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index e917766b5..0a7030213 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -129,7 +129,7 @@ posix_lookup (call_frame_t *frame, xlator_t *this,                  MAKE_ENTRY_HANDLE (real_path, par_path, this, loc, &buf);                  if (uuid_is_null (loc->inode->gfid)) { -                        posix_gfid_set (this, real_path, loc, xdata); +                        posix_gfid_heal (this, real_path, loc, xdata);                          MAKE_ENTRY_HANDLE (real_path, par_path, this,                                             loc, &buf);                  } diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index c834b29d9..a957e1876 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -188,7 +188,7 @@ int posix_get_file_contents (xlator_t *this, uuid_t pargfid,  int posix_set_file_contents (xlator_t *this, const char *path, char *key,                               data_t *value, int flags);  int posix_acl_xattr_set (xlator_t *this, const char *path, dict_t *xattr_req); -int posix_gfid_heal (xlator_t *this, const char *path, dict_t *xattr_req); +int posix_gfid_heal (xlator_t *this, const char *path, loc_t *loc, dict_t *xattr_req);  int posix_entry_create_xattr_set (xlator_t *this, const char *path,                                    dict_t *dict);  | 
