summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--xlators/features/Makefile.am4
-rw-r--r--xlators/features/marker/Makefile.am3
-rw-r--r--xlators/features/marker/src/Makefile.am15
-rw-r--r--xlators/features/marker/src/marker-mem-types.h32
-rw-r--r--xlators/features/marker/src/marker.c1420
-rw-r--r--xlators/features/marker/src/marker.h65
7 files changed, 1540 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index fedde7582cd..e8d3c07a897 100644
--- a/configure.ac
+++ b/configure.ac
@@ -21,7 +21,7 @@ AM_INIT_AUTOMAKE
AM_CONFIG_HEADER([config.h])
AC_CONFIG_FILES([Makefile
- libglusterfs/Makefile
+ libglusterfs/Makefile
libglusterfs/src/Makefile
glusterfsd/Makefile
glusterfsd/src/Makefile
@@ -91,6 +91,8 @@ AC_CONFIG_FILES([Makefile
xlators/features/trash/src/Makefile
xlators/features/quota/Makefile
xlators/features/quota/src/Makefile
+ xlators/features/marker/Makefile
+ xlators/features/marker/src/Makefile
xlators/features/read-only/Makefile
xlators/features/read-only/src/Makefile
xlators/features/mac-compat/Makefile
diff --git a/xlators/features/Makefile.am b/xlators/features/Makefile.am
index 8b23b939b0e..96e503938a8 100644
--- a/xlators/features/Makefile.am
+++ b/xlators/features/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = locks trash quota read-only access-control mac-compat quiesce #path-converter # filter
+SUBDIRS = locks trash quota read-only access-control mac-compat quiesce marker#path-converter # filter
-CLEANFILES =
+CLEANFILES =
diff --git a/xlators/features/marker/Makefile.am b/xlators/features/marker/Makefile.am
new file mode 100644
index 00000000000..a985f42a877
--- /dev/null
+++ b/xlators/features/marker/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES =
diff --git a/xlators/features/marker/src/Makefile.am b/xlators/features/marker/src/Makefile.am
new file mode 100644
index 00000000000..58b12b3f594
--- /dev/null
+++ b/xlators/features/marker/src/Makefile.am
@@ -0,0 +1,15 @@
+xlator_LTLIBRARIES = marker.la
+xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features
+
+marker_la_LDFLAGS = -module -avoidversion
+
+marker_la_SOURCES = marker.c
+marker_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
+
+noinst_HEADERS = marker-mem-types.h marker.h $(top_builddir)/xlators/lib/src/libxlator.h
+
+AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -fno-strict-aliasing -D$(GF_HOST_OS) \
+ -I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/xlators/lib/src $(GF_CFLAGS) -shared -nostartfiles
+
+CLEANFILES =
+
diff --git a/xlators/features/marker/src/marker-mem-types.h b/xlators/features/marker/src/marker-mem-types.h
new file mode 100644
index 00000000000..3936ef794fc
--- /dev/null
+++ b/xlators/features/marker/src/marker-mem-types.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __MARKER_MEM_TYPES_H__
+#define __MARKER_MEM_TYPES_H__
+
+#include "mem-types.h"
+
+enum gf_marker_mem_types_ {
+ gf_marker_mt_marker_local_t = gf_common_mt_end + 1,
+ gf_marker_mt_marker_conf_t,
+ gf_marker_mt_loc_t,
+ gf_marker_mt_volume_mark,
+ gf_marker_mt_end
+};
+#endif
diff --git a/xlators/features/marker/src/marker.c b/xlators/features/marker/src/marker.c
new file mode 100644
index 00000000000..a66b0fd03e0
--- /dev/null
+++ b/xlators/features/marker/src/marker.c
@@ -0,0 +1,1420 @@
+/*Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "xlator.h"
+#include "defaults.h"
+#include "libxlator.h"
+#include "marker.h"
+#include "marker-mem-types.h"
+
+void
+fini (xlator_t *this);
+
+int32_t
+marker_start_setxattr (call_frame_t *, xlator_t *);
+
+int
+marker_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path)
+{
+ int ret = -1;
+
+ if (!loc)
+ return ret;
+
+ if (inode) {
+ loc->inode = inode_ref (inode);
+ loc->ino = inode->ino;
+ }
+
+ if (parent)
+ loc->parent = inode_ref (parent);
+
+ loc->path = gf_strdup (path);
+ if (!loc->path) {
+ gf_log ("loc fill", GF_LOG_ERROR, "strdup failed");
+ goto loc_wipe;
+ }
+
+ loc->name = strrchr (loc->path, '/');
+ if (loc->name)
+ loc->name++;
+ else
+ goto loc_wipe;
+
+ ret = 0;
+loc_wipe:
+ if (ret < 0)
+ loc_wipe (loc);
+
+ return ret;
+}
+
+int
+marker_inode_loc_fill (inode_t *inode, loc_t *loc)
+{
+ char *resolvedpath = NULL;
+ inode_t *parent = NULL;
+ int ret = -1;
+
+ if ((!inode) || (!loc))
+ return ret;
+
+ if ((inode) && (inode->ino == 1)) {
+ loc->parent = NULL;
+ goto ignore_parent;
+ }
+
+ parent = inode_parent (inode, 0, NULL);
+ if (!parent) {
+ goto err;
+ }
+
+ignore_parent:
+ ret = inode_path (inode, NULL, &resolvedpath);
+ if (ret < 0)
+ goto err;
+
+ ret = marker_loc_fill (loc, inode, parent, resolvedpath);
+ if (ret < 0)
+ goto err;
+
+err:
+ if (parent)
+ inode_unref (parent);
+
+ if (resolvedpath)
+ GF_FREE (resolvedpath);
+
+ return ret;
+}
+
+int32_t
+marker_trav_parent (marker_local_t *local)
+{
+ int32_t ret = 0;
+ loc_t loc = {0, };
+
+ ret = marker_inode_loc_fill (local->loc.parent, &loc);
+
+ if (ret == -1)
+ goto out;
+
+ loc_wipe (&local->loc);
+
+ local->loc = loc;
+out:
+ return ret;
+}
+
+int32_t
+marker_error_handler (xlator_t *this)
+{
+ marker_conf_t *priv = NULL;
+
+ priv = (marker_conf_t *) this->private;
+
+ unlink (priv->timestamp_file);
+
+ return 0;
+}
+
+int32_t
+marker_free_local (marker_local_t *local)
+{
+ loc_wipe (&local->loc);
+
+ GF_FREE (local);
+
+ return 0;
+}
+
+int32_t
+stat_stampfile (xlator_t *this, marker_conf_t *priv, struct volume_mark **status)
+{
+ struct stat buf;
+ struct volume_mark *vol_mark;
+
+ vol_mark = GF_CALLOC (sizeof (struct volume_mark), 1,
+ gf_marker_mt_volume_mark);
+
+ vol_mark->major = 1;
+ vol_mark->minor = 0;
+
+ GF_ASSERT (sizeof (priv->volume_uuid_bin) == 16);
+ memcpy (vol_mark->uuid, priv->volume_uuid_bin, 16);
+
+ if (stat (priv->timestamp_file, &buf) != -1) {
+ vol_mark->retval = 0;
+ vol_mark->sec = htonl (buf.st_ctime);
+ vol_mark->usec = htonl (ST_CTIM_NSEC (&buf)/1000);
+ } else
+ vol_mark->retval = 0;
+
+ *status = vol_mark;
+
+ return 0;
+}
+
+int32_t
+marker_getxattr_stampfile_cbk (call_frame_t *frame, xlator_t *this,
+ const char *name, struct volume_mark *vol_mark)
+{
+ int32_t ret;
+ dict_t *dict = NULL;
+
+ if (vol_mark == NULL){
+ STACK_UNWIND_STRICT (getxattr, frame, -1, ENOMEM, NULL);
+
+ goto out;
+ }
+
+ dict = dict_new ();
+
+ ret = dict_set_bin (dict, (char *)name, vol_mark,
+ sizeof (struct volume_mark));
+
+ STACK_UNWIND_STRICT (getxattr, frame, 0, 0, dict);
+
+ dict_unref (dict);
+out:
+ return 0;
+}
+
+int32_t
+call_from_special_client (call_frame_t *frame, xlator_t *this, const char *name)
+{
+ struct volume_mark *vol_mark = NULL;
+ marker_conf_t *priv = NULL;
+ gf_boolean_t ret = _gf_true;
+
+ priv = (marker_conf_t *)this->private;
+
+ if (frame->root->pid != -1 || name == NULL ||
+ strcmp (name, MARKER_XATTR_PREFIX "." VOLUME_MARK) != 0) {
+ ret = _gf_false;
+ goto out;
+ }
+
+ stat_stampfile (this, priv, &vol_mark);
+
+ marker_getxattr_stampfile_cbk (frame, this, name, vol_mark);
+out:
+ return ret;
+}
+
+int32_t
+marker_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict)
+{
+ STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict);
+ return 0;
+}
+
+int32_t
+marker_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
+ const char *name)
+{
+ gf_boolean_t ret;
+
+ gf_log (this->name, GF_LOG_DEBUG, "USER:PID = %d", frame->root->pid);
+
+ ret = call_from_special_client (frame, this, name);
+
+ if (ret == _gf_false)
+ STACK_WIND (frame, marker_getxattr_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->getxattr, loc, name);
+
+ return 0;
+}
+
+
+int32_t
+marker_setxattr_done (call_frame_t *frame)
+{
+ marker_local_t *local = NULL;
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_DESTROY (frame->root);
+
+ marker_free_local (local);
+
+ return 0;
+}
+
+int
+marker_specific_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno)
+{
+ int32_t ret = 0;
+ int32_t done = 0;
+ marker_local_t *local = NULL;
+
+ local = (marker_local_t*) frame->local;
+
+ if (op_ret == -1 && op_errno == ENOSPC) {
+ marker_error_handler (this);
+ done = 1;
+ goto out;
+ }
+
+ if (strcmp (local->loc.path, "/") == 0) {
+ done = 1;
+ goto out;
+ }
+
+ ret = marker_trav_parent (local);
+
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_DEBUG, "Error occured "
+ "while traversing to the parent, stopping marker");
+
+ done = 1;
+
+ goto out;
+ }
+
+ marker_start_setxattr (frame, this);
+
+out:
+ if (done) {
+ marker_setxattr_done (frame);
+ }
+
+ return 0;
+}
+
+int32_t
+marker_start_setxattr (call_frame_t *frame, xlator_t *this)
+{
+ int32_t ret = 0;
+ dict_t *dict = NULL;
+ marker_local_t *local = NULL;
+ marker_conf_t *priv = NULL;
+
+ priv = this->private;
+
+ local = (marker_local_t*) frame->local;
+
+ dict = dict_new ();
+
+ ret = dict_set_static_bin (dict, priv->marker_xattr,
+ (void *)local->timebuf, 8);
+
+ gf_log (this->name, GF_LOG_DEBUG, "path = %s", local->loc.path);
+
+ STACK_WIND (frame, marker_specific_setxattr_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->setxattr, &local->loc, dict, 0);
+
+ dict_unref (dict);
+
+ return 0;
+}
+
+void
+marker_gettimeofday (marker_local_t *local)
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+
+ local->timebuf [0] = htonl (tv.tv_sec);
+ local->timebuf [1] = htonl (tv.tv_usec);
+
+ return;
+}
+
+int32_t
+marker_create_frame (xlator_t *this, marker_local_t *local)
+{
+ call_frame_t *frame = NULL;
+
+ frame = create_frame (this, this->ctx->pool);
+
+ frame->local = (void *) local;
+
+ marker_start_setxattr (frame, this);
+
+ return 0;
+}
+
+int32_t
+update_marks (xlator_t *this, marker_local_t *local, int32_t ret)
+{
+ if (ret == -1 || local->pid < 0)
+ marker_free_local (local);
+ else {
+ marker_gettimeofday (local);
+
+ marker_create_frame (this, local);
+ }
+
+ return 0;
+}
+
+int32_t
+marker_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, struct iatt *preparent,
+ struct iatt *postparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "error occurred "
+ "while Creating a file %s", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, inode,
+ buf, preparent, postparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int
+marker_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
+ dict_t *params)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_mkdir_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->mkdir, loc, mode, params);
+
+ return 0;
+err:
+ STACK_UNWIND_STRICT (mkdir, frame, -1, ENOMEM, NULL,
+ NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+marker_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode,
+ struct iatt *buf, struct iatt *preparent,
+ struct iatt *postparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "error occurred "
+ "while Creating a file %s", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, fd, inode, buf,
+ preparent, postparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
+ mode_t mode, fd_t *fd, dict_t *params)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_create_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->create, loc, flags, mode, fd,
+ params);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (create, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
+ struct iatt *postbuf)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "error occurred "
+ "while write, %s", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_writev (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t offset,
+ struct iobref *iobref)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = marker_inode_loc_fill (fd->inode, &local->loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_writev_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->writev, fd, vector, count, offset,
+ iobref);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (writev, frame, -1, ENOMEM, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *preparent,
+ struct iatt *postparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "error occurred "
+ "rmdir %s", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, preparent,
+ postparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_rmdir_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->rmdir, loc, flags);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (rmdir, frame, -1, ENOMEM, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *preparent,
+ struct iatt *postparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s occurred in unlink", strerror (op_errno));
+
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent,
+ postparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_unlink_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->unlink, loc);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (unlink, frame, -1, ENOMEM, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, struct iatt *preparent,
+ struct iatt *postparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "linking a file ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (link, frame, op_ret, op_errno, inode, buf,
+ preparent, postparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, newloc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_link_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->link, oldloc, newloc);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (link, frame, -1, ENOMEM, NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *buf,
+ struct iatt *preoldparent, struct iatt *postoldparent,
+ struct iatt *prenewparent, struct iatt *postnewparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "renaming a file ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, buf, preoldparent,
+ postoldparent, prenewparent, postnewparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc,
+ loc_t *newloc)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, newloc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_rename_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->rename, oldloc, newloc);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (rename, frame, -1, ENOMEM, NULL,
+ NULL, NULL, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
+ struct iatt *postbuf)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "truncating a file ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, prebuf,
+ postbuf);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_truncate_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->truncate, loc, offset);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (truncate, frame, -1, ENOMEM, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
+ struct iatt *postbuf)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "truncating a file ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, prebuf,
+ postbuf);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = marker_inode_loc_fill (fd->inode, &local->loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_ftruncate_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->ftruncate, fd, offset);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (ftruncate, frame, -1, ENOMEM, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, struct iatt *preparent,
+ struct iatt *postparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "creating symlinks ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, inode, buf,
+ preparent, postparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int
+marker_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath,
+ loc_t *loc, dict_t *params)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_symlink_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->symlink, linkpath, loc, params);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (symlink, frame, -1, ENOMEM, NULL,
+ NULL, NULL, NULL);
+ return 0;
+}
+
+int32_t
+marker_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, struct iatt *preparent,
+ struct iatt *postparent)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "creating symlinks ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno, inode,
+ buf, preparent, postparent);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int
+marker_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
+ dev_t rdev, dict_t *parms)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_mknod_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, parms);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (mknod, frame, -1, ENOMEM, NULL,
+ NULL, NULL, NULL);
+ return 0;
+}
+
+/* when a call from the special client is received on
+ * key trusted.glusterfs.volume-mark with value "RESET"
+ * or if the value is 0length, update the change the
+ * access time and modification time via touching the
+ * timestamp file.
+ */
+int32_t
+call_from_sp_client_to_reset_tmfile (call_frame_t *frame,
+ xlator_t *this,
+ dict_t *dict)
+{
+ int32_t fd = 0;
+ int32_t op_ret = 0;
+ int32_t op_errno = 0;
+ data_t *data = NULL;
+ marker_conf_t *priv = NULL;
+
+ if (frame == NULL || this == NULL || dict == NULL)
+ return -1;
+
+ priv = this->private;
+
+ data = dict_get (dict, "trusted.glusterfs.volume-mark");
+ if (data == NULL)
+ return -1;
+
+ if (frame->root->pid != -1) {
+ op_ret = -1;
+ op_errno = EPERM;
+
+ goto out;
+ }
+
+ if (data->len == 0 || (data->len == 5 &&
+ memcmp (data->data, "RESET", 5) == 0)) {
+ fd = open (priv->timestamp_file, O_WRONLY);
+ if (fd != -1) {
+ /* this call is needed because of the unsurity
+ * whether the O_TRUNC would update the timestamps
+ * on a zero length file as well. Hence updating it
+ * manually.
+ */
+ futimens (fd, NULL);
+ close (fd);
+ }
+
+ if (fd != -1 || errno == ENOENT) {
+ op_ret = 0;
+ op_errno = 0;
+ } else {
+ op_ret = -1;
+ op_errno = errno;
+ }
+ } else {
+ op_ret = -1;
+ op_errno = EINVAL;
+ }
+out:
+ STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno);
+
+ return 0;
+}
+
+int32_t
+marker_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "creating symlinks ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
+ int32_t flags)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ret = call_from_sp_client_to_reset_tmfile (frame, this, dict);
+ if (ret == 0)
+ return 0;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_setxattr_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->setxattr, loc, dict, flags);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (setxattr, frame, -1, ENOMEM);
+
+ return 0;
+}
+
+int32_t
+marker_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "creating symlinks ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict,
+ int32_t flags)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ret = call_from_sp_client_to_reset_tmfile (frame, this, dict);
+ if (ret == 0)
+ return 0;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = marker_inode_loc_fill (fd->inode, &local->loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_fsetxattr_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (fsetxattr, frame, -1, ENOMEM);
+
+ return 0;
+}
+
+int32_t
+marker_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *statpre,
+ struct iatt *statpost)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "creating symlinks ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, statpre,
+ statpost);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
+ struct iatt *stbuf, int32_t valid)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = marker_inode_loc_fill (fd->inode, &local->loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_fsetattr_cbk, FIRST_CHILD (this),
+ FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (fsetattr, frame, -1, ENOMEM, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *statpre,
+ struct iatt *statpost)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "creating symlinks ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, statpre,
+ statpost);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
+ struct iatt *stbuf, int32_t valid)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_setattr_cbk, FIRST_CHILD (this),
+ FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (setattr, frame, -1, ENOMEM, NULL, NULL);
+
+ return 0;
+}
+
+int32_t
+marker_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "%s occured while "
+ "creating symlinks ", strerror (op_errno));
+ ret = -1;
+ }
+
+ local = (marker_local_t *) frame->local;
+
+ frame->local = NULL;
+
+ STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno);
+
+ update_marks (this, local, ret);
+
+ return 0;
+}
+
+int32_t
+marker_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
+ const char *name)
+{
+ int32_t ret = 0;
+ marker_local_t *local = NULL;
+
+ ALLOCATE_OR_GOTO (local, marker_local_t, err);
+
+ MARKER_INIT_LOCAL (frame, local);
+
+ ret = loc_copy (&local->loc, loc);
+
+ if (ret == -1)
+ goto err;
+
+ STACK_WIND (frame, marker_removexattr_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->removexattr, loc, name);
+ return 0;
+err:
+ STACK_UNWIND_STRICT (removexattr, frame, -1, ENOMEM);
+
+ return 0;
+}
+
+int32_t
+mem_acct_init (xlator_t *this)
+{
+ int ret = -1;
+
+ if (!this)
+ return ret;
+
+ ret = xlator_mem_acct_init (this, gf_marker_mt_end + 1);
+
+ if (ret != 0) {
+ gf_log(this->name, GF_LOG_ERROR, "Memory accounting init"
+ "failed");
+ return ret;
+ }
+
+ return ret;
+}
+
+int32_t
+init (xlator_t *this)
+{
+ dict_t *options = NULL;
+ data_t *data = NULL;
+ int32_t ret = 0;
+ marker_conf_t *priv = NULL;
+
+ if (!this->children) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "marker translator needs subvolume defined.");
+ return -1;
+ }
+
+ if (!this->parents) {
+ gf_log (this->name, GF_LOG_WARNING,
+ "Volume is dangling.");
+ return -1;
+ }
+
+ options = this->options;
+
+ ALLOCATE_OR_GOTO (this->private, marker_conf_t, err);
+
+ priv = this->private;
+
+ if( (data = dict_get (options, VOLUME_UUID)) != NULL) {
+ priv->volume_uuid = data->data;
+
+ ret = uuid_parse (priv->volume_uuid, priv->volume_uuid_bin);
+ if (ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "invalid volume uuid %s", priv->volume_uuid);
+ goto err;
+ }
+
+ ret = gf_asprintf (& (priv->marker_xattr), "%s.%s.%s",
+ MARKER_XATTR_PREFIX, priv->volume_uuid, XTIME);
+
+ if (ret == -1){
+ priv->marker_xattr = NULL;
+
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to allocate memory");
+ goto err;
+ }
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "the volume-uuid = %s", priv->volume_uuid);
+ } else {
+ priv->volume_uuid = NULL;
+
+ gf_log (this->name, GF_LOG_ERROR,
+ "please specify the volume-uuid"
+ "in the translator options");
+
+ return -1;
+ }
+
+ if ((data = dict_get (options, TIMESTAMP_FILE)) != NULL) {
+ priv->timestamp_file = data->data;
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "the timestamp-file is = %s",
+ priv->timestamp_file);
+
+ } else {
+ priv->timestamp_file = NULL;
+
+ gf_log (this->name, GF_LOG_ERROR,
+ "please specify the timestamp-file"
+ "in the translator options");
+
+ goto err;
+ }
+
+ return 0;
+err:
+ fini (this);
+
+ return -1;
+}
+
+void
+fini (xlator_t *this)
+{
+ marker_conf_t *priv = NULL;
+
+ priv = (marker_conf_t *) this->private;
+
+ if (priv == NULL)
+ goto out;
+
+ if (priv->volume_uuid != NULL)
+ GF_FREE (priv->volume_uuid);
+
+ if (priv->timestamp_file != NULL)
+ GF_FREE (priv->timestamp_file);
+
+ if (priv->marker_xattr != NULL)
+ GF_FREE (priv->marker_xattr);
+
+ GF_FREE (priv);
+out:
+ return ;
+}
+
+struct xlator_fops fops = {
+ .create = marker_create,
+ .unlink = marker_unlink,
+ .link = marker_link,
+ .mkdir = marker_mkdir,
+ .rmdir = marker_rmdir,
+ .writev = marker_writev,
+ .rename = marker_rename,
+ .truncate = marker_truncate,
+ .ftruncate = marker_ftruncate,
+ .symlink = marker_symlink,
+ .mknod = marker_mknod,
+ .setxattr = marker_setxattr,
+ .fsetxattr = marker_fsetxattr,
+ .setattr = marker_setattr,
+ .fsetattr = marker_fsetattr,
+ .removexattr = marker_removexattr,
+ .getxattr = marker_getxattr
+};
+
+struct xlator_cbks cbks = {
+};
+
+struct volume_options options[] = {
+ {.key = {"volume-uuid"}},
+ {.key = {"timestamp-file"}},
+ {.key = {NULL}}
+};
diff --git a/xlators/features/marker/src/marker.h b/xlators/features/marker/src/marker.h
new file mode 100644
index 00000000000..60567c3b828
--- /dev/null
+++ b/xlators/features/marker/src/marker.h
@@ -0,0 +1,65 @@
+/*Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.com>
+ This file is part of GlusterFS.
+
+ GlusterFS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ GlusterFS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "xlator.h"
+#include "defaults.h"
+#include "uuid.h"
+
+#define MARKER_XATTR_PREFIX "trusted.glusterfs"
+#define XTIME "xtime"
+#define VOLUME_MARK "volume-mark"
+#define VOLUME_UUID "volume-uuid"
+#define TIMESTAMP_FILE "timestamp-file"
+
+/*initialize the local variable*/
+#define MARKER_INIT_LOCAL(_frame,_local) do { \
+ _frame->local = _local; \
+ _local->pid = _frame->root->pid; \
+ memset (&_local->loc, 0, sizeof (loc_t)); \
+ } while (0)
+
+/* try alloc and if it fails, goto label */
+#define ALLOCATE_OR_GOTO(var, type, label) do { \
+ var = GF_CALLOC (sizeof (type), 1, \
+ gf_marker_mt_##type); \
+ if (!var) { \
+ gf_log (this->name, GF_LOG_ERROR, \
+ "out of memory :("); \
+ goto label; \
+ } \
+ } while (0)
+
+struct marker_local{
+ uint32_t timebuf[2];
+ pid_t pid;
+ loc_t loc;
+};
+typedef struct marker_local marker_local_t;
+
+struct marker_conf{
+ char *volume_uuid;
+ uuid_t volume_uuid_bin;
+ char *timestamp_file;
+ char *marker_xattr;
+};
+typedef struct marker_conf marker_conf_t;