summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/storage/posix/src/posix.c516
-rw-r--r--xlators/storage/posix/src/posix.h7
2 files changed, 229 insertions, 294 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 3bd7fe025e3..87bf755cff6 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -192,32 +192,6 @@ _posix_xattr_get_set (dict_t *xattr_req,
}
-dict_t *
-posix_lookup_xattr_fill (xlator_t *this, const char *real_path, loc_t *loc,
- dict_t *xattr_req, struct stat *buf)
-{
- dict_t *xattr = NULL;
- posix_xattr_filler_t filler = {0, };
-
- xattr = get_new_dict();
- if (!xattr) {
- gf_log (this->name, GF_LOG_ERROR,
- "Out of memory.");
- goto out;
- }
-
- filler.this = this;
- filler.real_path = real_path;
- filler.xattr = xattr;
- filler.stbuf = buf;
- filler.loc = loc;
-
- dict_foreach (xattr_req, _posix_xattr_get_set, &filler);
-out:
- return xattr;
-}
-
-
static int
posix_scale_st_ino (struct posix_private *priv, struct stat *buf)
{
@@ -242,11 +216,154 @@ posix_scale_st_ino (struct posix_private *priv, struct stat *buf)
buf->st_ino = temp_ino;
ret = 0;
- out:
+out:
return ret;
}
+int
+posix_lstat_with_gen (xlator_t *this, const char *path, struct stat *stbuf_p)
+{
+ struct posix_private *priv = NULL;
+ int ret = 0;
+ char gen_key[256] = {0, };
+ uint64_t gen_val_be = 0;
+ uint64_t gen_val = 0;
+ struct stat stbuf = {0, };
+
+ priv = this->private;
+
+ ret = lstat (path, &stbuf);
+ if (ret == -1)
+ return -1;
+
+ ret = posix_scale_st_ino (priv, &stbuf);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Access to %s (on dev %lld) is crossing device (%lld)",
+ path, (unsigned long long) stbuf.st_dev,
+ (unsigned long long) priv->st_device[0]);
+ errno = EXDEV;
+ return -1;
+ }
+
+ ret = snprintf (gen_key, 1024, "trusted.%s.gen", this->name);
+
+ if (ret == 1024)
+ return -1;
+
+ ret = sys_lgetxattr (path, gen_key, (void *) &gen_val_be,
+ sizeof (gen_val_be));
+ if (ret == -1) {
+ LOCK (&priv->gen_lock);
+ {
+ gen_val = ++priv->gen_seq;
+ }
+ UNLOCK (&priv->gen_lock);
+
+ gen_val_be = hton64 (gen_val);
+
+ ret = sys_lsetxattr (path, gen_key, &gen_val_be,
+ sizeof (gen_val_be), 0);
+ } else {
+ gen_val = ntoh64 (gen_val_be);
+ }
+
+ if (ret >= 0) {
+ stbuf.st_dev = gen_val;
+ if (stbuf_p)
+ *stbuf_p = stbuf;
+ }
+
+ return ret;
+}
+
+
+int
+posix_fstat_with_gen (xlator_t *this, int fd, struct stat *stbuf_p)
+{
+ struct posix_private *priv = NULL;
+ int ret = 0;
+ char gen_key[256] = {0, };
+ uint64_t gen_val_be = 0;
+ uint64_t gen_val = 0;
+ struct stat stbuf = {0, };
+
+ priv = this->private;
+
+ ret = fstat (fd, &stbuf);
+ if (ret == -1)
+ return -1;
+
+ ret = posix_scale_st_ino (priv, &stbuf);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Access to fd %d (on dev %lld) is crossing device (%lld)",
+ fd, (unsigned long long) stbuf.st_dev,
+ (unsigned long long) priv->st_device[0]);
+ errno = EXDEV;
+ return -1;
+ }
+
+
+ ret = snprintf (gen_key, 1024, "trusted.%s.gen", this->name);
+
+ if (ret == 1024)
+ return -1;
+
+ ret = sys_fgetxattr (fd, gen_key, (void *) &gen_val_be,
+ sizeof (gen_val_be));
+ if (ret == -1) {
+ LOCK (&priv->gen_lock);
+ {
+ gen_val = ++priv->gen_seq;
+ }
+ UNLOCK (&priv->gen_lock);
+
+ gen_val_be = hton64 (gen_val);
+
+ ret = sys_fsetxattr (fd, gen_key, &gen_val_be,
+ sizeof (gen_val_be), 0);
+ } else {
+ gen_val = ntoh64 (gen_val_be);
+ }
+
+ if (ret >= 0) {
+ stbuf.st_dev = gen_val;
+ if (stbuf_p)
+ *stbuf_p = stbuf;
+ }
+
+ return ret;
+}
+
+
+dict_t *
+posix_lookup_xattr_fill (xlator_t *this, const char *real_path, loc_t *loc,
+ dict_t *xattr_req, struct stat *buf)
+{
+ dict_t *xattr = NULL;
+ posix_xattr_filler_t filler = {0, };
+
+ xattr = get_new_dict();
+ if (!xattr) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Out of memory.");
+ goto out;
+ }
+
+ filler.this = this;
+ filler.real_path = real_path;
+ filler.xattr = xattr;
+ filler.stbuf = buf;
+ filler.loc = loc;
+
+ dict_foreach (xattr_req, _posix_xattr_get_set, &filler);
+out:
+ return xattr;
+}
+
+
/*
* If the parent directory of {real_path} has the setgid bit set,
* then set {gid} to the gid of the parent. Otherwise,
@@ -254,7 +371,7 @@ posix_scale_st_ino (struct posix_private *priv, struct stat *buf)
*/
int
-setgid_override (char *real_path, gid_t *gid)
+setgid_override (xlator_t *this, char *real_path, gid_t *gid)
{
char * tmp_path = NULL;
char * parent_path = NULL;
@@ -272,7 +389,7 @@ setgid_override (char *real_path, gid_t *gid)
parent_path = dirname (tmp_path);
- op_ret = lstat (parent_path, &parent_stbuf);
+ op_ret = posix_lstat_with_gen (this, parent_path, &parent_stbuf);
if (op_ret == -1) {
op_ret = -errno;
@@ -323,7 +440,7 @@ posix_lookup (call_frame_t *frame, xlator_t *this,
priv = this->private;
- op_ret = lstat (real_path, &buf);
+ op_ret = posix_lstat_with_gen (this, real_path, &buf);
op_errno = errno;
if (op_ret == -1) {
@@ -337,47 +454,26 @@ posix_lookup (call_frame_t *frame, xlator_t *this,
goto parent;
}
- /* Make sure we don't access another mountpoint inside export dir.
- * It may cause inode number to repeat from single export point,
- * which leads to severe problems..
- */
- if (!priv->span_devices) {
- if (priv->st_device[0] != buf.st_dev) {
- op_errno = ENOENT;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, returning "
- "ENOENT", loc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &buf);
- if (-1 == op_ret) {
- op_errno = ENOENT;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- loc->path);
- goto out;
- }
- }
-
if (xattr_req && (op_ret == 0)) {
xattr = posix_lookup_xattr_fill (this, real_path, loc,
xattr_req, &buf);
}
parent:
- pathdup = strdup (real_path);
- GF_VALIDATE_OR_GOTO (this->name, pathdup, out);
+ if (loc->parent) {
+ pathdup = strdup (real_path);
+ GF_VALIDATE_OR_GOTO (this->name, pathdup, out);
- parentpath = dirname (pathdup);
+ parentpath = dirname (pathdup);
- op_ret = lstat (parentpath, &postparent);
- if (op_ret == -1) {
- op_errno = errno;
- gf_log (this->name, GF_LOG_ERROR,
- "post-operation lstat on parent of %s failed: %s",
- loc->path, strerror (op_errno));
- goto out;
+ op_ret = posix_lstat_with_gen (this, parentpath, &postparent);
+ if (op_ret == -1) {
+ op_errno = errno;
+ gf_log (this->name, GF_LOG_ERROR,
+ "post-operation lstat on parent of %s failed: %s",
+ loc->path, strerror (op_errno));
+ goto out;
+ }
}
op_ret = entry_ret;
@@ -421,7 +517,7 @@ posix_stat (call_frame_t *frame,
SET_FS_ID (frame->root->uid, frame->root->gid);
MAKE_REAL_PATH (real_path, this, loc->path);
- op_ret = lstat (real_path, &buf);
+ op_ret = posix_lstat_with_gen (this, real_path, &buf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -430,10 +526,6 @@ posix_stat (call_frame_t *frame,
goto out;
}
- if (priv->span_devices) {
- posix_scale_st_ino (priv, &buf);
- }
-
op_ret = 0;
out:
@@ -516,7 +608,7 @@ posix_setattr (call_frame_t *frame, xlator_t *this,
SET_FS_ID (frame->root->uid, frame->root->gid);
MAKE_REAL_PATH (real_path, this, loc->path);
- op_ret = lstat (real_path, &statpre);
+ op_ret = posix_lstat_with_gen (this, real_path, &statpre);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -558,7 +650,7 @@ posix_setattr (call_frame_t *frame, xlator_t *this,
}
}
- op_ret = lstat (real_path, &statpost);
+ op_ret = posix_lstat_with_gen (this, real_path, &statpost);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -645,7 +737,7 @@ posix_fsetattr (call_frame_t *frame, xlator_t *this,
}
pfd = (struct posix_fd *)(long)tmp_pfd;
- op_ret = fstat (pfd->fd, &statpre);
+ op_ret = posix_fstat_with_gen (this, pfd->fd, &statpre);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -688,7 +780,7 @@ posix_fsetattr (call_frame_t *frame, xlator_t *this,
}
}
- op_ret = fstat (pfd->fd, &statpost);
+ op_ret = posix_fstat_with_gen (this, pfd->fd, &statpost);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -886,23 +978,13 @@ posix_getdents (call_frame_t *frame, xlator_t *this,
strncat (tmp_real_path, dirent->d_name,
ZR_PATH_MAX - (strlen (tmp_real_path) + 1));
- ret = lstat (tmp_real_path, &buf);
+ ret = posix_lstat_with_gen (this, tmp_real_path, &buf);
if ((flag == GF_GET_DIR_ONLY)
&& (ret != -1 && !S_ISDIR(buf.st_mode))) {
continue;
}
- if ((!priv->span_devices)
- && (priv->st_device[0] != buf.st_dev)) {
- continue;
- } else {
- op_ret = posix_scale_st_ino (priv, &buf);
- if (-1 == op_ret) {
- continue;
- }
- }
-
tmp = CALLOC (1, sizeof (*tmp));
if (!tmp) {
@@ -1074,7 +1156,7 @@ posix_readlink (call_frame_t *frame, xlator_t *this,
dest[op_ret] = 0;
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1121,12 +1203,12 @@ posix_mknod (call_frame_t *frame, xlator_t *this,
gid = frame->root->gid;
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if ((op_ret == -1) && (errno == ENOENT)){
was_present = 0;
}
- op_ret = setgid_override (real_path, &gid);
+ op_ret = setgid_override (this, real_path, &gid);
if (op_ret < 0)
goto out;
@@ -1136,7 +1218,7 @@ posix_mknod (call_frame_t *frame, xlator_t *this,
parentpath = dirname (pathdup);
- op_ret = lstat (parentpath, &preparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &preparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1176,7 +1258,7 @@ posix_mknod (call_frame_t *frame, xlator_t *this,
}
#endif
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1185,26 +1267,7 @@ posix_mknod (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (!priv->span_devices) {
- if (priv->st_device[0] != stbuf.st_dev) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, returning "
- "EPERM", loc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &stbuf);
- if (-1 == op_ret) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- loc->path);
- goto out;
- }
- }
-
- op_ret = lstat (parentpath, &postparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &postparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1260,12 +1323,12 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,
gid = frame->root->gid;
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if ((op_ret == -1) && (errno == ENOENT)) {
was_present = 0;
}
- op_ret = setgid_override (real_path, &gid);
+ op_ret = setgid_override (this, real_path, &gid);
if (op_ret < 0)
goto out;
@@ -1275,7 +1338,7 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,
parentpath = dirname (pathdup);
- op_ret = lstat (parentpath, &preparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &preparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1304,7 +1367,7 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,
}
#endif
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1313,26 +1376,7 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (!priv->span_devices) {
- if (priv->st_device[0] != stbuf.st_dev) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, returning "
- "EPERM", loc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &stbuf);
- if (-1 == op_ret) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- loc->path);
- goto out;
- }
- }
-
- op_ret = lstat (parentpath, &postparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &postparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1388,7 +1432,7 @@ posix_unlink (call_frame_t *frame, xlator_t *this,
parentpath = dirname (pathdup);
- op_ret = lstat (parentpath, &preparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &preparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1421,7 +1465,7 @@ posix_unlink (call_frame_t *frame, xlator_t *this,
goto out;
}
- op_ret = lstat (parentpath, &postparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &postparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1474,7 +1518,7 @@ posix_rmdir (call_frame_t *frame, xlator_t *this,
parentpath = dirname (pathdup);
- op_ret = lstat (parentpath, &preparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &preparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1500,7 +1544,7 @@ posix_rmdir (call_frame_t *frame, xlator_t *this,
if (op_ret == -1)
goto out;
- op_ret = lstat (parentpath, &postparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &postparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1549,14 +1593,14 @@ posix_symlink (call_frame_t *frame, xlator_t *this,
MAKE_REAL_PATH (real_path, this, loc->path);
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if ((op_ret == -1) && (errno == ENOENT)){
was_present = 0;
}
gid = frame->root->gid;
- op_ret = setgid_override (real_path, &gid);
+ op_ret = setgid_override (this, real_path, &gid);
if (op_ret < 0)
goto out;
@@ -1566,7 +1610,7 @@ posix_symlink (call_frame_t *frame, xlator_t *this,
parentpath = dirname (pathdup);
- op_ret = lstat (parentpath, &preparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &preparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1595,7 +1639,7 @@ posix_symlink (call_frame_t *frame, xlator_t *this,
goto out;
}
#endif
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1604,26 +1648,7 @@ posix_symlink (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (!priv->span_devices) {
- if (priv->st_device[0] != stbuf.st_dev) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, returning "
- "EPERM", loc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &stbuf);
- if (-1 == op_ret) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- loc->path);
- goto out;
- }
- }
-
- op_ret = lstat (parentpath, &postparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &postparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1690,7 +1715,7 @@ posix_rename (call_frame_t *frame, xlator_t *this,
oldparentpath = dirname (oldpathdup);
- op_ret = lstat (oldparentpath, &preoldparent);
+ op_ret = posix_lstat_with_gen (this, oldparentpath, &preoldparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1704,7 +1729,7 @@ posix_rename (call_frame_t *frame, xlator_t *this,
newparentpath = dirname (newpathdup);
- op_ret = lstat (newparentpath, &prenewparent);
+ op_ret = posix_lstat_with_gen (this, newparentpath, &prenewparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1713,7 +1738,7 @@ posix_rename (call_frame_t *frame, xlator_t *this,
goto out;
}
- op_ret = lstat (real_newpath, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_newpath, &stbuf);
if ((op_ret == -1) && (errno == ENOENT)){
was_present = 0;
}
@@ -1728,7 +1753,7 @@ posix_rename (call_frame_t *frame, xlator_t *this,
goto out;
}
- op_ret = lstat (real_newpath, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_newpath, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1737,26 +1762,7 @@ posix_rename (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (!priv->span_devices) {
- if (priv->st_device[0] != stbuf.st_dev) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, returning "
- "EPERM", newloc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &stbuf);
- if (-1 == op_ret) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- newloc->path);
- goto out;
- }
- }
-
- op_ret = lstat (oldparentpath, &postoldparent);
+ op_ret = posix_lstat_with_gen (this, oldparentpath, &postoldparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1765,7 +1771,7 @@ posix_rename (call_frame_t *frame, xlator_t *this,
goto out;
}
- op_ret = lstat (newparentpath, &postnewparent);
+ op_ret = posix_lstat_with_gen (this, newparentpath, &postnewparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1828,7 +1834,7 @@ posix_link (call_frame_t *frame, xlator_t *this,
MAKE_REAL_PATH (real_oldpath, this, oldloc->path);
MAKE_REAL_PATH (real_newpath, this, newloc->path);
- op_ret = lstat (real_newpath, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_newpath, &stbuf);
if ((op_ret == -1) && (errno = ENOENT)) {
was_present = 0;
}
@@ -1841,7 +1847,7 @@ posix_link (call_frame_t *frame, xlator_t *this,
}
newparentpath = dirname (newpathdup);
- op_ret = lstat (newparentpath, &preparent);
+ op_ret = posix_lstat_with_gen (this, newparentpath, &preparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR, "lstat failed: %s: %s",
@@ -1858,7 +1864,7 @@ posix_link (call_frame_t *frame, xlator_t *this,
goto out;
}
- op_ret = lstat (real_newpath, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_newpath, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1867,7 +1873,7 @@ posix_link (call_frame_t *frame, xlator_t *this,
goto out;
}
- op_ret = lstat (newparentpath, &postparent);
+ op_ret = posix_lstat_with_gen (this, newparentpath, &postparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR, "lstat failed: %s: %s",
@@ -1875,25 +1881,6 @@ posix_link (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (!priv->span_devices) {
- if (priv->st_device[0] != stbuf.st_dev) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, returning "
- "EPERM", newloc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &stbuf);
- if (-1 == op_ret) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- newloc->path);
- goto out;
- }
- }
-
op_ret = 0;
out:
@@ -1921,7 +1908,6 @@ posix_truncate (call_frame_t *frame,
int32_t op_ret = -1;
int32_t op_errno = 0;
char *real_path = 0;
- struct stat stbuf = {0,};
struct posix_private *priv = NULL;
struct stat prebuf = {0,};
struct stat postbuf = {0,};
@@ -1938,7 +1924,7 @@ posix_truncate (call_frame_t *frame,
SET_FS_ID (frame->root->uid, frame->root->gid);
MAKE_REAL_PATH (real_path, this, loc->path);
- op_ret = lstat (real_path, &prebuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &prebuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -1956,7 +1942,7 @@ posix_truncate (call_frame_t *frame,
goto out;
}
- op_ret = lstat (real_path, &postbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &postbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR, "lstat on %s failed: %s",
@@ -1964,10 +1950,6 @@ posix_truncate (call_frame_t *frame,
goto out;
}
- if (priv->span_devices) {
- posix_scale_st_ino (priv, &stbuf);
- }
-
op_ret = 0;
out:
@@ -2016,7 +1998,7 @@ posix_create (call_frame_t *frame, xlator_t *this,
gid = frame->root->gid;
- op_ret = setgid_override (real_path, &gid);
+ op_ret = setgid_override (this, real_path, &gid);
if (op_ret < 0) {
goto out;
@@ -2028,7 +2010,7 @@ posix_create (call_frame_t *frame, xlator_t *this,
parentpath = dirname (pathdup);
- op_ret = lstat (parentpath, &preparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &preparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -2044,7 +2026,7 @@ posix_create (call_frame_t *frame, xlator_t *this,
_flags = flags | O_CREAT;
}
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if ((op_ret == -1) && (errno == ENOENT)) {
was_present = 0;
}
@@ -2072,7 +2054,7 @@ posix_create (call_frame_t *frame, xlator_t *this,
}
#endif
- op_ret = fstat (_fd, &stbuf);
+ op_ret = posix_fstat_with_gen (this, _fd, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -2080,26 +2062,7 @@ posix_create (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (!priv->span_devices) {
- if (priv->st_device[0] != stbuf.st_dev) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, returning "
- "EPERM", loc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &stbuf);
- if (-1 == op_ret) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- loc->path);
- goto out;
- }
- }
-
- op_ret = lstat (parentpath, &postparent);
+ op_ret = posix_lstat_with_gen (this, parentpath, &postparent);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -2177,7 +2140,7 @@ posix_open (call_frame_t *frame, xlator_t *this,
MAKE_REAL_PATH (real_path, this, loc->path);
- op_ret = setgid_override (real_path, &gid);
+ op_ret = setgid_override (this, real_path, &gid);
if (op_ret < 0)
goto out;
@@ -2186,7 +2149,7 @@ posix_open (call_frame_t *frame, xlator_t *this,
if (priv->o_direct)
flags |= O_DIRECT;
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if ((op_ret == -1) && (errno == ENOENT)) {
was_present = 0;
}
@@ -2229,32 +2192,13 @@ posix_open (call_frame_t *frame, xlator_t *this,
#endif
if (flags & O_CREAT) {
- op_ret = lstat (real_path, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_path, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR, "lstat on (%s) "
"failed: %s", real_path, strerror (op_errno));
goto out;
}
-
- if (!priv->span_devices) {
- if (priv->st_device[0] != stbuf.st_dev) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: different mountpoint/device, "
- "returning EPERM", loc->path);
- goto out;
- }
- } else {
- op_ret = posix_scale_st_ino (priv, &stbuf);
- if (-1 == op_ret) {
- op_errno = EPERM;
- gf_log (this->name, GF_LOG_ERROR,
- "%s: from different mountpoint",
- loc->path);
- goto out;
- }
- }
}
LOCK (&priv->lock);
@@ -2374,7 +2318,7 @@ posix_readv (call_frame_t *frame, xlator_t *this,
* we read from
*/
- op_ret = fstat (_fd, &stbuf);
+ op_ret = posix_fstat_with_gen (this, _fd, &stbuf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -2383,12 +2327,8 @@ posix_readv (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (priv->span_devices) {
- posix_scale_st_ino (priv, &stbuf);
- }
-
op_ret = vec.iov_len;
- out:
+out:
STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno,
&vec, 1, &stbuf, iobref);
@@ -2445,7 +2385,7 @@ posix_writev (call_frame_t *frame, xlator_t *this,
_fd = pfd->fd;
- op_ret = fstat (_fd, &preop);
+ op_ret = posix_fstat_with_gen (this, _fd, &preop);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -2538,7 +2478,7 @@ posix_writev (call_frame_t *frame, xlator_t *this,
fsync (_fd);
}
- ret = fstat (_fd, &postop);
+ ret = posix_fstat_with_gen (this, _fd, &postop);
if (ret == -1) {
op_ret = -1;
op_errno = errno;
@@ -2547,11 +2487,6 @@ posix_writev (call_frame_t *frame, xlator_t *this,
fd, strerror (op_errno));
goto out;
}
-
- if (priv->span_devices) {
- posix_scale_st_ino (priv, &preop);
- posix_scale_st_ino (priv, &postop);
- }
}
out:
@@ -2747,7 +2682,7 @@ posix_fsync (call_frame_t *frame, xlator_t *this,
_fd = pfd->fd;
- op_ret = fstat (_fd, &preop);
+ op_ret = posix_fstat_with_gen (this, _fd, &preop);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_DEBUG,
@@ -2772,7 +2707,7 @@ posix_fsync (call_frame_t *frame, xlator_t *this,
}
}
- op_ret = fstat (_fd, &postop);
+ op_ret = posix_fstat_with_gen (this, _fd, &postop);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_DEBUG,
@@ -2978,7 +2913,7 @@ get_file_contents (xlator_t *this, char *real_path,
key = (char *) &(name[15]);
sprintf (real_filepath, "%s/%s", real_path, key);
- op_ret = lstat (real_filepath, &stbuf);
+ op_ret = posix_lstat_with_gen (this, real_filepath, &stbuf);
if (op_ret == -1) {
op_ret = -errno;
gf_log (this->name, GF_LOG_ERROR, "lstat failed on %s: %s",
@@ -3789,7 +3724,7 @@ posix_ftruncate (call_frame_t *frame, xlator_t *this,
_fd = pfd->fd;
- op_ret = fstat (_fd, &preop);
+ op_ret = posix_fstat_with_gen (this, _fd, &preop);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -3808,7 +3743,7 @@ posix_ftruncate (call_frame_t *frame, xlator_t *this,
goto out;
}
- op_ret = fstat (_fd, &postop);
+ op_ret = posix_fstat_with_gen (this, _fd, &postop);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -3817,11 +3752,6 @@ posix_ftruncate (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (priv->span_devices) {
- posix_scale_st_ino (priv, &preop);
- posix_scale_st_ino (priv, &postop);
- }
-
op_ret = 0;
out:
@@ -3847,7 +3777,7 @@ ensure_file_type (xlator_t *this, char *pathname, mode_t mode)
int op_ret = 0;
int ret = -1;
- ret = lstat (pathname, &stbuf);
+ ret = posix_lstat_with_gen (this, pathname, &stbuf);
if (ret == -1) {
op_ret = -errno;
gf_log (this->name, GF_LOG_ERROR,
@@ -4161,7 +4091,7 @@ posix_fstat (call_frame_t *frame, xlator_t *this,
_fd = pfd->fd;
- op_ret = fstat (_fd, &buf);
+ op_ret = posix_fstat_with_gen (this, _fd, &buf);
if (op_ret == -1) {
op_errno = errno;
gf_log (this->name, GF_LOG_ERROR, "fstat failed on fd=%p: %s",
@@ -4169,13 +4099,9 @@ posix_fstat (call_frame_t *frame, xlator_t *this,
goto out;
}
- if (priv->span_devices) {
- posix_scale_st_ino (priv, &buf);
- }
-
op_ret = 0;
- out:
+out:
SET_TO_OLD_FS_ID ();
STACK_UNWIND_STRICT (fstat, frame, op_ret, op_errno, &buf);
@@ -4371,8 +4297,7 @@ posix_do_readdir (call_frame_t *frame, xlator_t *this,
*/
if ((whichop == GF_FOP_READDIRP) || (priv->span_devices)) {
strcpy (entry_path + real_path_len + 1, entry->d_name);
- lstat (entry_path, &stbuf);
- op_ret = posix_scale_st_ino (priv, &stbuf);
+ op_ret = posix_lstat_with_gen (this, entry_path, &stbuf);
if (-1 == op_ret)
continue;
} else
@@ -4583,7 +4508,7 @@ posix_checksum (call_frame_t *frame, xlator_t *this,
strcpy (tmp_real_path, real_path);
strcat (tmp_real_path, "/");
strcat (tmp_real_path, dirent->d_name);
- ret = lstat (tmp_real_path, &buf);
+ ret = posix_lstat_with_gen (this, tmp_real_path, &buf);
if (ret == -1)
continue;
@@ -4917,6 +4842,9 @@ init (xlator_t *this)
/* Start with the base */
_private->st_device[0] = buf.st_dev;
+ LOCK_INIT (&_private->gen_lock);
+ _private->gen_seq = (time (NULL) << 32);
+
#ifndef GF_DARWIN_HOST_OS
{
struct rlimit lim;
diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h
index 156bad85ae5..b16800c5c93 100644
--- a/xlators/storage/posix/src/posix.h
+++ b/xlators/storage/posix/src/posix.h
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
+#include <time.h>
#ifdef linux
#ifdef __GLIBC__
@@ -107,6 +108,12 @@ struct posix_private {
int num_devices_to_span;
dev_t *st_device;
+
+/* a global generation number sequence is used to assign generation numbers in
+ sequence.
+*/
+ uint64_t gen_seq;
+ gf_lock_t gen_lock;
};
#define POSIX_BASE_PATH(this) (((struct posix_private *)this->private)->base_path)