summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/storage/posix/src/posix.c83
-rw-r--r--xlators/storage/posix/src/posix.h6
2 files changed, 80 insertions, 9 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 9ee6ed5105c..28b6d9ef4bd 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -208,6 +208,35 @@ out:
}
+static int
+posix_scale_st_ino (struct posix_private *priv, struct stat *buf)
+{
+ int i = 0;
+ int ret = -1;
+ ino_t temp_ino = 0;
+
+ for (i = 0; i < priv->num_devices_to_span; i++) {
+ if (buf->st_dev == priv->st_device[i])
+ break;
+ if (priv->st_device[i] == 0) {
+ priv->st_device[i] = buf->st_dev;
+ break;
+ }
+ }
+
+ if (i == priv->num_devices_to_span)
+ goto out;
+
+ temp_ino = (buf->st_ino * priv->num_devices_to_span) + i;
+
+ buf->st_ino = temp_ino;
+
+ ret = 0;
+ out:
+ return ret;
+}
+
+
int32_t
posix_lookup (call_frame_t *frame, xlator_t *this,
loc_t *loc, dict_t *xattr_req)
@@ -245,13 +274,24 @@ posix_lookup (call_frame_t *frame, xlator_t *this,
* It may cause inode number to repeat from single export point,
* which leads to severe problems..
*/
- if (priv->base_stdev != buf.st_dev) {
- op_errno = ENOENT;
- gf_log (this->name, GF_LOG_WARNING,
- "%s: different mountpoint/device, returning "
- "ENOENT", loc->path);
- goto out;
- }
+ if (!priv->span_devices) {
+ if (priv->st_device[0] != buf.st_dev) {
+ op_errno = ENOENT;
+ gf_log (this->name, GF_LOG_WARNING,
+ "%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_WARNING,
+ "%s: from different mountpoint",
+ loc->path);
+ goto out;
+ }
+ }
if (xattr_req && (op_ret == 0)) {
xattr = posix_lookup_xattr_fill (this, real_path, loc,
@@ -3849,7 +3889,6 @@ init (xlator_t *this)
_private->base_path = strdup (dir_data->data);
_private->base_path_length = strlen (_private->base_path);
- _private->base_stdev = buf.st_dev;
{
/* Stats related variables */
@@ -3890,6 +3929,32 @@ init (xlator_t *this)
"for every open)");
}
+ _private->num_devices_to_span = 1;
+
+ tmp_data = dict_get (this->options, "span-devices");
+ if (tmp_data) {
+ if (gf_string2int32 (tmp_data->data,
+ &_private->num_devices_to_span) == -1) {
+ ret = -1;
+ gf_log (this->name, GF_LOG_ERROR,
+ "wrong option provided for 'span-devices'");
+ goto out;
+ }
+ if (_private->num_devices_to_span > 1) {
+ gf_log (this->name, GF_LOG_INFO,
+ "spaning enabled accross %d mounts",
+ _private->num_devices_to_span);
+ _private->span_devices = 1;
+ }
+ if (!_private->num_devices_to_span < 1)
+ _private->num_devices_to_span = 1;
+ }
+ _private->st_device = CALLOC (1, (sizeof (dev_t) *
+ _private->num_devices_to_span));
+
+ /* Start with the base */
+ _private->st_device[0] = buf.st_dev;
+
#ifndef GF_DARWIN_HOST_OS
{
struct rlimit lim;
@@ -3997,5 +4062,7 @@ struct volume_options options[] = {
.type = GF_OPTION_TYPE_BOOL },
{ .key = {"mandate-attribute"},
.type = GF_OPTION_TYPE_BOOL },
+ { .key = {"span-devices"},
+ .type = GF_OPTION_TYPE_INT },
{ .key = {NULL} }
};
diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h
index e41bff94755..88860a57116 100644
--- a/xlators/storage/posix/src/posix.h
+++ b/xlators/storage/posix/src/posix.h
@@ -64,7 +64,6 @@ struct posix_fd {
struct posix_private {
char *base_path;
int32_t base_path_length;
- dev_t base_stdev;
/* Statistics, provides activity of the server */
struct xlator_stats stats;
@@ -91,6 +90,11 @@ struct posix_private {
gf_boolean_t export_statfs;
gf_boolean_t o_direct; /* always open files in O_DIRECT mode */
+
+ gf_boolean_t span_devices;
+
+ int num_devices_to_span;
+ dev_t *st_device;
};
#define POSIX_BASE_PATH(this) (((struct posix_private *)this->private)->base_path)