diff options
author | Vikas Gorur <vikas@gluster.com> | 2009-12-02 07:48:45 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2009-12-02 10:29:23 -0800 |
commit | c04c1a170dcc605efcf80c8ae2674b69488b591d (patch) | |
tree | 31add18b6173c517454bdc48d9d508250a1eaded /xlators/storage | |
parent | 90328b827768552a05bb12abf62d09c9566309d1 (diff) |
storage/posix: Added janitor thread.
The janitor thread deletes all files and directories in
the "/" GF_REPLICATE_TRASH_DIR directory. This directory
is used by replicate self-heal to dump files and
directories it deletes.
This is needed because letting replicate walk the directory
tree and delete a directory and all its children is too racy.
Instead, replicate self-heal only does an atomic rename(),
and the janitor thread takes care of actually deleting them.
Signed-off-by: Vikas Gorur <vikas@gluster.com>
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 227 (replicate selfheal does not remove directory with contents in it)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=227
Diffstat (limited to 'xlators/storage')
-rw-r--r-- | xlators/storage/posix/src/posix.c | 115 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.h | 5 |
2 files changed, 119 insertions, 1 deletions
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 325c69634ec..1219620f197 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -29,6 +29,7 @@ #include <sys/resource.h> #include <errno.h> #include <libgen.h> +#include <pthread.h> #include <ftw.h> #ifndef GF_BSD_HOST_OS @@ -50,7 +51,7 @@ #include "syscall.h" #include "statedump.h" #include "locking.h" -#include <libgen.h> +#include "timer.h" #undef HAVE_SET_FSID #ifdef HAVE_SET_FSID @@ -1322,6 +1323,95 @@ posix_mknod (call_frame_t *frame, xlator_t *this, return 0; } + +static int +janitor_walker (const char *fpath, const struct stat *sb, + int typeflag, struct FTW *ftwbuf) +{ + switch (sb->st_mode & S_IFMT) { + case S_IFREG: + case S_IFBLK: + case S_IFLNK: + case S_IFCHR: + case S_IFIFO: + case S_IFSOCK: + gf_log (THIS->name, GF_LOG_TRACE, + "unlinking %s", fpath); + unlink (fpath); + break; + + case S_IFDIR: + if (ftwbuf->level) { /* don't remove top level dir */ + gf_log (THIS->name, GF_LOG_TRACE, + "removing directory %s", fpath); + + rmdir (fpath); + } + break; + } + + return FTW_CONTINUE; +} + + +#define JANITOR_SLEEP_DURATION 2 + +static void * +posix_janitor_thread_proc (void *data) +{ + xlator_t * this = NULL; + struct posix_private *priv = NULL; + + this = data; + priv = this->private; + + THIS = this; + + while (1) { + gf_log (this->name, GF_LOG_TRACE, + "janitor woke up, cleaning out /" GF_REPLICATE_TRASH_DIR); + + nftw (priv->trash_path, + janitor_walker, + 32, + FTW_DEPTH | FTW_PHYS); + + sleep (JANITOR_SLEEP_DURATION); + } + + return NULL; +} + + +static void +posix_spawn_janitor_thread (xlator_t *this) +{ + struct posix_private *priv = NULL; + int ret = 0; + + priv = this->private; + + LOCK (&priv->lock); + { + if (!priv->janitor_present) { + ret = pthread_create (&priv->janitor, NULL, + posix_janitor_thread_proc, this); + + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "spawning janitor thread failed: %s", + strerror (errno)); + goto unlock; + } + + priv->janitor_present = _gf_true; + } + } +unlock: + UNLOCK (&priv->lock); +} + + int32_t posix_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode) @@ -1384,6 +1474,14 @@ posix_mkdir (call_frame_t *frame, xlator_t *this, goto out; } + if (!strcmp (loc->path, "/" GF_REPLICATE_TRASH_DIR)) { + gf_log (this->name, GF_LOG_TRACE, + "got mkdir %s, spawning janitor thread", + loc->path); + + posix_spawn_janitor_thread (this); + } + #ifndef HAVE_SET_FSID op_ret = chown (real_path, frame->root->uid, gid); if (op_ret == -1) { @@ -4738,6 +4836,21 @@ init (xlator_t *this) _private->base_path = strdup (dir_data->data); _private->base_path_length = strlen (_private->base_path); + _private->trash_path = CALLOC (1, _private->base_path_length + + strlen ("/") + + strlen (GF_REPLICATE_TRASH_DIR) + + 1); + + if (!_private->trash_path) { + gf_log (this->name, GF_LOG_ERROR, + "Out of memory."); + ret = -1; + goto out; + } + + strncpy (_private->trash_path, _private->base_path, _private->base_path_length); + strcat (_private->trash_path, "/" GF_REPLICATE_TRASH_DIR); + LOCK_INIT (&_private->lock); ret = gethostname (_private->hostname, 256); diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index b16800c5c93..0a99caeb636 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -114,6 +114,11 @@ struct posix_private { */ uint64_t gen_seq; gf_lock_t gen_lock; + +/* janitor thread which cleans up /.trash (created by replicate) */ + pthread_t janitor; + gf_boolean_t janitor_present; + char * trash_path; }; #define POSIX_BASE_PATH(this) (((struct posix_private *)this->private)->base_path) |