diff options
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 131 | 
1 files changed, 131 insertions, 0 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 95926bbf576..7357331f992 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -425,6 +425,108 @@ out:  } +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, 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, xattr_req); +out: +        return ret; +} + + +int +posix_acl_xattr_set (xlator_t *this, const char *path, dict_t *xattr_req) +{ +        int          ret = 0; +        data_t      *data = NULL; +        struct stat  stat = {0, }; + +        if (!xattr_req) +                goto out; + +        if (sys_lstat (path, &stat) != 0) +                goto out; + +        data = dict_get (xattr_req, "system.posix_acl_access"); +        if (data) { +                ret = sys_lsetxattr (path, "system.posix_acl_access", +                                     data->data, data->len, 0); +                if (ret != 0) +                        goto out; +        } + +        data = dict_get (xattr_req, "system.posix_acl_default"); +        if (data) { +                ret = sys_lsetxattr (path, "system.posix_acl_default", +                                     data->data, data->len, 0); +                if (ret != 0) +                        goto out; +        } + +out: +        return ret; +} + +  int32_t  posix_lookup (call_frame_t *frame, xlator_t *this,                loc_t *loc, dict_t *xattr_req) @@ -1153,6 +1255,13 @@ posix_mknod (call_frame_t *frame, xlator_t *this,          }  #endif +        op_ret = posix_acl_xattr_set (this, real_path, params); +        if (op_ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "setting ACLs on %s failed (%s)", loc->path, +                        strerror (errno)); +        } +          op_ret = posix_lstat_with_gfid (this, real_path, &stbuf);          if (op_ret == -1) {                  op_errno = errno; @@ -1418,6 +1527,13 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,          }  #endif +        op_ret = posix_acl_xattr_set (this, real_path, params); +        if (op_ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "setting ACLs on %s failed (%s)", loc->path, +                        strerror (errno)); +        } +          op_ret = posix_lstat_with_gfid (this, real_path, &stbuf);          if (op_ret == -1) {                  op_errno = errno; @@ -1722,6 +1838,14 @@ posix_symlink (call_frame_t *frame, xlator_t *this,                  goto out;          }  #endif + +        op_ret = posix_acl_xattr_set (this, real_path, params); +        if (op_ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "setting ACLs on %s failed (%s)", loc->path, +                        strerror (errno)); +        } +          op_ret = posix_lstat_with_gfid (this, real_path, &stbuf);          if (op_ret == -1) {                  op_errno = errno; @@ -2145,6 +2269,13 @@ posix_create (call_frame_t *frame, xlator_t *this,          }  #endif +        op_ret = posix_acl_xattr_set (this, real_path, params); +        if (op_ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "setting ACLs on %s failed (%s)", loc->path, +                        strerror (errno)); +        } +          op_ret = posix_fstat_with_gfid (this, _fd, &stbuf);          if (op_ret == -1) {                  op_errno = errno;  | 
