diff options
Diffstat (limited to 'xlators/features')
220 files changed, 9933 insertions, 12435 deletions
diff --git a/xlators/features/Makefile.am b/xlators/features/Makefile.am index 6ef19af0860..c57897f11ea 100644 --- a/xlators/features/Makefile.am +++ b/xlators/features/Makefile.am @@ -2,10 +2,13 @@ if BUILD_CLOUDSYNC CLOUDSYNC_DIR = cloudsync endif +if BUILD_METADISP + METADISP_DIR = metadisp +endif + +SUBDIRS = locks quota read-only quiesce marker index barrier arbiter upcall \ + compress changelog gfid-access snapview-client snapview-server trash \ + shard bit-rot leases selinux sdfs namespace $(CLOUDSYNC_DIR) thin-arbiter \ + utime $(METADISP_DIR) -SUBDIRS = locks quota read-only quiesce marker index barrier \ - arbiter compress changelog changetimerecorder \ - gfid-access $(GLUPY_SUBDIR) upcall snapview-client snapview-server \ - trash shard bit-rot leases selinux sdfs namespace $(CLOUDSYNC_DIR) thin-arbiter \ - utime CLEANFILES = diff --git a/xlators/features/arbiter/src/arbiter-mem-types.h b/xlators/features/arbiter/src/arbiter-mem-types.h index 0f77cfd05f4..05d18374c46 100644 --- a/xlators/features/arbiter/src/arbiter-mem-types.h +++ b/xlators/features/arbiter/src/arbiter-mem-types.h @@ -9,7 +9,7 @@ #ifndef __ARBITER_MEM_TYPES_H__ #define __ARBITER_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> typedef enum gf_arbiter_mem_types_ { gf_arbiter_mt_inode_ctx_t = gf_common_mt_end + 1, diff --git a/xlators/features/arbiter/src/arbiter.c b/xlators/features/arbiter/src/arbiter.c index 436f228a566..83a97e3354b 100644 --- a/xlators/features/arbiter/src/arbiter.c +++ b/xlators/features/arbiter/src/arbiter.c @@ -10,9 +10,9 @@ #include "arbiter.h" #include "arbiter-mem-types.h" -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> static arbiter_inode_ctx_t * __arbiter_inode_ctx_get(inode_t *inode, xlator_t *this) @@ -31,7 +31,7 @@ __arbiter_inode_ctx_get(inode_t *inode, xlator_t *this) if (!ctx) goto out; - ret = __inode_ctx_put(inode, this, (uint64_t)ctx); + ret = __inode_ctx_put(inode, this, (uint64_t)(uintptr_t)ctx); if (ret) { GF_FREE(ctx); ctx = NULL; @@ -365,3 +365,16 @@ struct xlator_cbks cbks = { struct volume_options options[] = { {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "arbiter", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/arbiter/src/arbiter.h b/xlators/features/arbiter/src/arbiter.h index ce1c909f70f..546db7b751a 100644 --- a/xlators/features/arbiter/src/arbiter.h +++ b/xlators/features/arbiter/src/arbiter.h @@ -11,8 +11,8 @@ #ifndef _ARBITER_H #define _ARBITER_H -#include "locking.h" -#include "common-utils.h" +#include <glusterfs/locking.h> +#include <glusterfs/common-utils.h> typedef struct arbiter_inode_ctx_ { struct iatt iattbuf; diff --git a/xlators/features/barrier/src/barrier-mem-types.h b/xlators/features/barrier/src/barrier-mem-types.h index 93ccab633ce..71ed7898d9c 100644 --- a/xlators/features/barrier/src/barrier-mem-types.h +++ b/xlators/features/barrier/src/barrier-mem-types.h @@ -11,7 +11,7 @@ #ifndef __BARRIER_MEM_TYPES_H__ #define __BARRIER_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_barrier_mem_types_ { gf_barrier_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/barrier/src/barrier.c b/xlators/features/barrier/src/barrier.c index 1c5c5ffdc22..852bbacb99d 100644 --- a/xlators/features/barrier/src/barrier.c +++ b/xlators/features/barrier/src/barrier.c @@ -9,10 +9,10 @@ */ #include "barrier.h" -#include "defaults.h" -#include "call-stub.h" +#include <glusterfs/defaults.h> +#include <glusterfs/call-stub.h> -#include "statedump.h" +#include <glusterfs/statedump.h> void barrier_local_set_gfid(call_frame_t *frame, uuid_t gfid, xlator_t *this) @@ -461,16 +461,14 @@ out: int notify(xlator_t *this, int event, void *data, ...) { - barrier_priv_t *priv = NULL; + barrier_priv_t *priv = this->private; dict_t *dict = NULL; - gf_boolean_t past = _gf_false; int ret = -1; int barrier_enabled = _gf_false; struct list_head queue = { 0, }; - priv = this->private; GF_ASSERT(priv); INIT_LIST_HEAD(&queue); @@ -488,35 +486,27 @@ notify(xlator_t *this, int event, void *data, ...) LOCK(&priv->lock); { - past = priv->barrier_enabled; - - switch (past) { - case _gf_false: - if (barrier_enabled) { - ret = __barrier_enable(this, priv); - if (ret) - goto unlock; - } else { - gf_log(this->name, GF_LOG_ERROR, - "Already disabled."); - goto unlock; - } - break; - - case _gf_true: - if (!barrier_enabled) { - __barrier_disable(this, &queue); - } else { - gf_log(this->name, GF_LOG_ERROR, "Already enabled"); - goto unlock; - } - break; + if (!priv->barrier_enabled) { + if (barrier_enabled) { + ret = __barrier_enable(this, priv); + } else { + UNLOCK(&priv->lock); + gf_log(this->name, GF_LOG_ERROR, "Already disabled."); + goto post_unlock; + } + } else { + if (!barrier_enabled) { + __barrier_disable(this, &queue); + ret = 0; + } else { + UNLOCK(&priv->lock); + gf_log(this->name, GF_LOG_ERROR, "Already enabled"); + goto post_unlock; + } } - ret = 0; } - unlock: UNLOCK(&priv->lock); - + post_unlock: if (!list_empty(&queue)) barrier_dequeue_all(this, &queue); @@ -536,7 +526,6 @@ int reconfigure(xlator_t *this, dict_t *options) { barrier_priv_t *priv = NULL; - gf_boolean_t past = _gf_false; int ret = -1; gf_boolean_t barrier_enabled = _gf_false; uint32_t timeout = { @@ -556,23 +545,17 @@ reconfigure(xlator_t *this, dict_t *options) LOCK(&priv->lock); { - past = priv->barrier_enabled; - - switch (past) { - case _gf_false: - if (barrier_enabled) { - ret = __barrier_enable(this, priv); - if (ret) { - goto unlock; - } + if (!priv->barrier_enabled) { + if (barrier_enabled) { + ret = __barrier_enable(this, priv); + if (ret) { + goto unlock; } - break; - - case _gf_true: - if (!barrier_enabled) { - __barrier_disable(this, &queue); - } - break; + } + } else { + if (!barrier_enabled) { + __barrier_disable(this, &queue); + } } priv->timeout.tv_sec = timeout; ret = 0; @@ -746,13 +729,13 @@ barrier_dump_priv(xlator_t *this) gf_proc_dump_build_key(key, "xlator.features.barrier", "priv"); gf_proc_dump_add_section("%s", key); + gf_proc_dump_build_key(key, "barrier", "enabled"); LOCK(&priv->lock); { - gf_proc_dump_build_key(key, "barrier", "enabled"); gf_proc_dump_write(key, "%d", priv->barrier_enabled); gf_proc_dump_build_key(key, "barrier", "timeout"); - gf_proc_dump_write(key, "%" PRId64, priv->timeout.tv_sec); + gf_proc_dump_write(key, "%ld", priv->timeout.tv_sec); if (priv->barrier_enabled) { gf_proc_dump_build_key(key, "barrier", "queue_size"); gf_proc_dump_write(key, "%d", priv->queue_size); @@ -809,3 +792,18 @@ struct volume_options options[] = { "blocked acknowledgements are sent to the application"}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .dumpops = &dumpops, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "barrier", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/barrier/src/barrier.h b/xlators/features/barrier/src/barrier.h index d11d71d151e..1337f311f7d 100644 --- a/xlators/features/barrier/src/barrier.h +++ b/xlators/features/barrier/src/barrier.h @@ -12,9 +12,9 @@ #define __BARRIER_H__ #include "barrier-mem-types.h" -#include "xlator.h" -#include "timer.h" -#include "call-stub.h" +#include <glusterfs/xlator.h> +#include <glusterfs/timer.h> +#include <glusterfs/call-stub.h> #define BARRIER_FOP_CBK(fop_name, label, frame, this, params...) \ do { \ @@ -65,11 +65,12 @@ typedef struct { gf_timer_t *timer; - gf_boolean_t barrier_enabled; gf_lock_t lock; struct list_head queue; struct timespec timeout; uint32_t queue_size; + gf_boolean_t barrier_enabled; + char _pad[3]; /* manual padding */ } barrier_priv_t; int diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h b/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h index 6f59933a31d..5bc5103a27c 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h @@ -11,7 +11,7 @@ #ifndef _BITROT_BITD_MESSAGES_H_ #define _BITROT_BITD_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * @@ -47,6 +47,55 @@ GLFS_MSGID(BITROT_BITD, BRB_MSG_FD_CREATE_FAILED, BRB_MSG_READV_FAILED, BRB_MSG_SCRUB_THREAD_CLEANUP, BRB_MSG_SCRUBBER_CLEANED, BRB_MSG_GENERIC_SSM_INFO, BRB_MSG_ZERO_TIMEOUT_BUG, BRB_MSG_BAD_OBJ_READDIR_FAIL, BRB_MSG_SSM_FAILED, - BRB_MSG_SCRUB_WAIT_FAILED); + BRB_MSG_SCRUB_WAIT_FAILED, BRB_MSG_TRIGGER_SIGN_FAILED, + BRB_MSG_EVENT_UNHANDLED, BRB_MSG_COULD_NOT_SCHEDULE_SCRUB, + BRB_MSG_THREAD_CREATION_FAILED, BRB_MSG_MEM_POOL_ALLOC, + BRB_MSG_SAVING_HASH_FAILED); +#define BRB_MSG_FD_CREATE_FAILED_STR "failed to create fd for the inode" +#define BRB_MSG_READV_FAILED_STR "readv failed" +#define BRB_MSG_BLOCK_READ_FAILED_STR "reading block failed" +#define BRB_MSG_NO_MEMORY_STR "failed to allocate memory" +#define BRB_MSG_CALC_CHECKSUM_FAILED_STR "calculating checksum failed" +#define BRB_MSG_GET_SIGN_FAILED_STR "failed to get the signature" +#define BRB_MSG_SET_SIGN_FAILED_STR "signing failed" +#define BRB_MSG_OP_FAILED_STR "failed on object" +#define BRB_MSG_TRIGGER_SIGN_FAILED_STR "Could not trigger signing" +#define BRB_MSG_READ_AND_SIGN_FAILED_STR "reading and signing of object failed" +#define BRB_MSG_SET_TIMER_FAILED_STR "Failed to allocate object expiry timer" +#define BRB_MSG_GET_SUBVOL_FAILED_STR \ + "failed to get the subvolume for the brick" +#define BRB_MSG_PATH_FAILED_STR "path failed" +#define BRB_MSG_SKIP_OBJECT_STR "Entry is marked corrupted. skipping" +#define BRB_MSG_PARTIAL_VERSION_PRESENCE_STR \ + "PArtial version xattr presence detected, ignoring" +#define BRB_MSG_TRIGGER_SIGN_STR "Triggering signing" +#define BRB_MSG_CRAWLING_START_STR \ + "Crawling brick, scanning for unsigned objects" +#define BRB_MSG_CRAWLING_FINISH_STR "Completed crawling brick" +#define BRB_MSG_REGISTER_FAILED_STR "Register to changelog failed" +#define BRB_MSG_SPAWN_FAILED_STR "failed to spawn" +#define BRB_MSG_CONNECTED_TO_BRICK_STR "Connected to brick" +#define BRB_MSG_LOOKUP_FAILED_STR "lookup on root failed" +#define BRB_MSG_GET_INFO_FAILED_STR "failed to get stub info" +#define BRB_MSG_SCRUB_THREAD_CLEANUP_STR "Error cleaning up scanner thread" +#define BRB_MSG_SCRUBBER_CLEANED_STR "clened up scrubber for brick" +#define BRB_MSG_SUBVOL_CONNECT_FAILED_STR \ + "callback handler for subvolume failed" +#define BRB_MSG_MEM_ACNT_FAILED_STR "Memory accounting init failed" +#define BRB_MSG_EVENT_UNHANDLED_STR "Event unhandled for child" +#define BRB_MSG_INVALID_SUBVOL_STR "Got event from invalid subvolume" +#define BRB_MSG_RESCHEDULE_SCRUBBER_FAILED_STR \ + "on demand scrub schedule failed. Scrubber is not in pending state." +#define BRB_MSG_COULD_NOT_SCHEDULE_SCRUB_STR \ + "Could not schedule ondemand scrubbing. Scrubbing will continue " \ + "according to old frequency." +#define BRB_MSG_THREAD_CREATION_FAILED_STR "thread creation failed" +#define BRB_MSG_RATE_LIMIT_INFO_STR "Rate Limit Info" +#define BRB_MSG_MEM_POOL_ALLOC_STR "failed to allocate mem-pool for timer" +#define BRB_MSG_NO_CHILD_STR "FATAL: no children" +#define BRB_MSG_TIMER_WHEEL_UNAVAILABLE_STR "global timer wheel unavailable" +#define BRB_MSG_BITROT_LOADED_STR "bit-rot xlator loaded" +#define BRB_MSG_SAVING_HASH_FAILED_STR \ + "failed to allocate memory for saving hash of the object" #endif /* !_BITROT_BITD_MESSAGES_H_ */ diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.c b/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.c index 34e20f9df11..5cef2ffa5e5 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.c @@ -40,21 +40,21 @@ br_inc_scrubbed_file(br_scrub_stats_t *scrub_stat) } void -br_update_scrub_start_time(br_scrub_stats_t *scrub_stat, struct timeval *tv) +br_update_scrub_start_time(br_scrub_stats_t *scrub_stat, time_t time) { if (!scrub_stat) return; pthread_mutex_lock(&scrub_stat->lock); { - scrub_stat->scrub_start_tv.tv_sec = tv->tv_sec; + scrub_stat->scrub_start_time = time; } pthread_mutex_unlock(&scrub_stat->lock); } void br_update_scrub_finish_time(br_scrub_stats_t *scrub_stat, char *timestr, - struct timeval *tv) + time_t time) { int lst_size = 0; @@ -67,10 +67,10 @@ br_update_scrub_finish_time(br_scrub_stats_t *scrub_stat, char *timestr, pthread_mutex_lock(&scrub_stat->lock); { - scrub_stat->scrub_end_tv.tv_sec = tv->tv_sec; + scrub_stat->scrub_end_time = time; - scrub_stat->scrub_duration = scrub_stat->scrub_end_tv.tv_sec - - scrub_stat->scrub_start_tv.tv_sec; + scrub_stat->scrub_duration = scrub_stat->scrub_end_time - + scrub_stat->scrub_start_time; snprintf(scrub_stat->last_scrub_time, lst_size, "%s", timestr); } diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.h b/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.h index 24128b90a66..f022aa831eb 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.h @@ -15,20 +15,22 @@ #include <sys/time.h> #include <pthread.h> +#include <glusterfs/common-utils.h> + struct br_scrub_stats { - uint64_t scrubbed_files; /* Total number of scrubbed file */ + uint64_t scrubbed_files; /* Total number of scrubbed files. */ - uint64_t unsigned_files; /* Total number of unsigned file */ + uint64_t unsigned_files; /* Total number of unsigned files. */ - uint64_t scrub_duration; /* Duration of last scrub */ + uint64_t scrub_duration; /* Duration of last scrub. */ - char last_scrub_time[1024]; /*last scrub completion time */ + char last_scrub_time[GF_TIMESTR_SIZE]; /* Last scrub completion time. */ - struct timeval scrub_start_tv; /* Scrubbing starting time*/ + time_t scrub_start_time; /* Scrubbing starting time. */ - struct timeval scrub_end_tv; /* Scrubbing finishing time */ + time_t scrub_end_time; /* Scrubbing finishing time. */ - int8_t scrub_running; /* Scrub running or not */ + int8_t scrub_running; /* Whether scrub running or not. */ pthread_mutex_t lock; }; @@ -40,9 +42,9 @@ br_inc_unsigned_file_count(br_scrub_stats_t *scrub_stat); void br_inc_scrubbed_file(br_scrub_stats_t *scrub_stat); void -br_update_scrub_start_time(br_scrub_stats_t *scrub_stat, struct timeval *tv); +br_update_scrub_start_time(br_scrub_stats_t *scrub_stat, time_t time); void br_update_scrub_finish_time(br_scrub_stats_t *scrub_stat, char *timestr, - struct timeval *tv); + time_t time); #endif /* __BIT_ROT_SCRUB_STATUS_H__ */ diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c index 63903b0d235..289dd53f610 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.c @@ -12,15 +12,15 @@ #include <ctype.h> #include <sys/uio.h> -#include "glusterfs.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> #include "bit-rot-scrub.h" #include <pthread.h> #include "bit-rot-bitd-messages.h" #include "bit-rot-scrub-status.h" -#include "events.h" +#include <glusterfs/events.h> struct br_scrubbers { pthread_t scrubthread; @@ -601,25 +601,23 @@ br_fsscan_deactivate(xlator_t *this) static void br_scrubber_log_time(xlator_t *this, const char *sfx) { - char timestr[1024] = { - 0, - }; - struct timeval tv = { + char timestr[GF_TIMESTR_SIZE] = { 0, }; br_private_t *priv = NULL; + time_t now = 0; + now = gf_time(); priv = this->private; - gettimeofday(&tv, NULL); - gf_time_fmt(timestr, sizeof(timestr), tv.tv_sec, gf_timefmt_FT); + gf_time_fmt(timestr, sizeof(timestr), now, gf_timefmt_FT); if (strcasecmp(sfx, "started") == 0) { - br_update_scrub_start_time(&priv->scrub_stat, &tv); + br_update_scrub_start_time(&priv->scrub_stat, now); gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_START, "Scrubbing %s at %s", sfx, timestr); } else { - br_update_scrub_finish_time(&priv->scrub_stat, timestr, &tv); + br_update_scrub_finish_time(&priv->scrub_stat, timestr, now); gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_FINISH, "Scrubbing %s at %s", sfx, timestr); } @@ -628,15 +626,13 @@ br_scrubber_log_time(xlator_t *this, const char *sfx) static void br_fsscanner_log_time(xlator_t *this, br_child_t *child, const char *sfx) { - char timestr[1024] = { - 0, - }; - struct timeval tv = { + char timestr[GF_TIMESTR_SIZE] = { 0, }; + time_t now = 0; - gettimeofday(&tv, NULL); - gf_time_fmt(timestr, sizeof(timestr), tv.tv_sec, gf_timefmt_FT); + now = gf_time(); + gf_time_fmt(timestr, sizeof(timestr), now, gf_timefmt_FT); if (strcasecmp(sfx, "started") == 0) { gf_msg_debug(this->name, 0, "Scrubbing \"%s\" %s at %s", @@ -720,8 +716,10 @@ br_scrubber_exit_control(xlator_t *this) if (scrub_monitor->state == BR_SCRUB_STATE_ACTIVE) { (void)br_fsscan_activate(this); } else { + UNLOCK(&scrub_monitor->lock); gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_INFO, "Volume waiting to get rescheduled.."); + return; } } UNLOCK(&scrub_monitor->lock); @@ -917,10 +915,7 @@ br_fsscan_schedule(xlator_t *this) { uint32_t timo = 0; br_private_t *priv = NULL; - struct timeval tv = { - 0, - }; - char timestr[1024] = { + char timestr[GF_TIMESTR_SIZE] = { 0, }; struct br_scrubber *fsscrub = NULL; @@ -931,8 +926,7 @@ br_fsscan_schedule(xlator_t *this) fsscrub = &priv->fsscrub; scrub_monitor = &priv->scrub_monitor; - (void)gettimeofday(&tv, NULL); - scrub_monitor->boot = tv.tv_sec; + scrub_monitor->boot = gf_time(); timo = br_fsscan_calculate_timeout(fsscrub->frequency); if (timo == 0) { @@ -973,12 +967,10 @@ int32_t br_fsscan_activate(xlator_t *this) { uint32_t timo = 0; - char timestr[1024] = { - 0, - }; - struct timeval now = { + char timestr[GF_TIMESTR_SIZE] = { 0, }; + time_t now = 0; br_private_t *priv = NULL; struct br_scrubber *fsscrub = NULL; struct br_monitor *scrub_monitor = NULL; @@ -987,7 +979,7 @@ br_fsscan_activate(xlator_t *this) fsscrub = &priv->fsscrub; scrub_monitor = &priv->scrub_monitor; - (void)gettimeofday(&now, NULL); + now = gf_time(); timo = br_fsscan_calculate_timeout(fsscrub->frequency); if (timo == 0) { gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_ZERO_TIMEOUT_BUG, @@ -1001,7 +993,7 @@ br_fsscan_activate(xlator_t *this) } pthread_mutex_unlock(&scrub_monitor->donelock); - gf_time_fmt(timestr, sizeof(timestr), (now.tv_sec + timo), gf_timefmt_FT); + gf_time_fmt(timestr, sizeof(timestr), now + timo, gf_timefmt_FT); (void)gf_tw_mod_timer(priv->timer_wheel, scrub_monitor->timer, timo); _br_monitor_set_scrub_state(scrub_monitor, BR_SCRUB_STATE_PENDING); @@ -1018,12 +1010,10 @@ br_fsscan_reschedule(xlator_t *this) { int32_t ret = 0; uint32_t timo = 0; - char timestr[1024] = { - 0, - }; - struct timeval now = { + char timestr[GF_TIMESTR_SIZE] = { 0, }; + time_t now = 0; br_private_t *priv = NULL; struct br_scrubber *fsscrub = NULL; struct br_monitor *scrub_monitor = NULL; @@ -1035,7 +1025,7 @@ br_fsscan_reschedule(xlator_t *this) if (!fsscrub->frequency_reconf) return 0; - (void)gettimeofday(&now, NULL); + now = gf_time(); timo = br_fsscan_calculate_timeout(fsscrub->frequency); if (timo == 0) { gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_ZERO_TIMEOUT_BUG, @@ -1043,7 +1033,7 @@ br_fsscan_reschedule(xlator_t *this) return -1; } - gf_time_fmt(timestr, sizeof(timestr), (now.tv_sec + timo), gf_timefmt_FT); + gf_time_fmt(timestr, sizeof(timestr), now + timo, gf_timefmt_FT); pthread_mutex_lock(&scrub_monitor->donelock); { @@ -1071,23 +1061,19 @@ br_fsscan_ondemand(xlator_t *this) { int32_t ret = 0; uint32_t timo = 0; - char timestr[1024] = { - 0, - }; - struct timeval now = { + char timestr[GF_TIMESTR_SIZE] = { 0, }; + time_t now = 0; br_private_t *priv = NULL; struct br_monitor *scrub_monitor = NULL; priv = this->private; scrub_monitor = &priv->scrub_monitor; - (void)gettimeofday(&now, NULL); - + now = gf_time(); timo = BR_SCRUB_ONDEMAND; - - gf_time_fmt(timestr, sizeof(timestr), (now.tv_sec + timo), gf_timefmt_FT); + gf_time_fmt(timestr, sizeof(timestr), now + timo, gf_timefmt_FT); pthread_mutex_lock(&scrub_monitor->donelock); { @@ -1545,9 +1531,11 @@ br_scrubber_log_option(xlator_t *this, br_private_t *priv, [BR_SCRUB_THROTTLE_LAZY] = "lazy", [BR_SCRUB_THROTTLE_NORMAL] = "normal", [BR_SCRUB_THROTTLE_AGGRESSIVE] = "aggressive", + [BR_SCRUB_THROTTLE_STALLED] = "stalled", }; char *scrub_freq_str[] = { + [0] = "", [BR_FSSCRUB_FREQ_HOURLY] = "hourly", [BR_FSSCRUB_FREQ_DAILY] = "daily", [BR_FSSCRUB_FREQ_WEEKLY] = "weekly", @@ -1560,6 +1548,8 @@ br_scrubber_log_option(xlator_t *this, br_private_t *priv, return; /* logged as pause */ if (fsscrub->frequency_reconf || fsscrub->throttle_reconf) { + if (fsscrub->throttle == BR_SCRUB_THROTTLE_VOID) + return; gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_TUNABLE, "SCRUB TUNABLES:: [Frequency: %s, Throttle: %s]", scrub_freq_str[fsscrub->frequency], @@ -1651,7 +1641,7 @@ br_read_bad_object_dir(xlator_t *this, br_child_t *child, fd_t *fd, int32_t ret = -1; off_t offset = 0; int32_t count = 0; - char key[PATH_MAX] = { + char key[32] = { 0, }; dict_t *out_dict = NULL; @@ -1689,7 +1679,7 @@ br_read_bad_object_dir(xlator_t *this, br_child_t *child, fd_t *fd, } ret = count; - ret = dict_set_int32(dict, "count", count); + ret = dict_set_int32_sizen(dict, "count", count); out: return ret; @@ -1771,10 +1761,10 @@ br_collect_bad_objects_of_child(xlator_t *this, br_child_t *child, dict_t *dict, { int32_t ret = -1; int32_t count = 0; - char key[PATH_MAX] = { + char key[32] = { 0, }; - char main_key[PATH_MAX] = { + char main_key[32] = { 0, }; int32_t j = 0; @@ -1786,15 +1776,15 @@ br_collect_bad_objects_of_child(xlator_t *this, br_child_t *child, dict_t *dict, char *path = NULL; int32_t len = 0; - ret = dict_get_int32(child_dict, "count", &count); + ret = dict_get_int32_sizen(child_dict, "count", &count); if (ret) goto out; tmp_count = total_count; for (j = 0; j < count; j++) { - snprintf(key, PATH_MAX, "quarantine-%d", j); - ret = dict_get_str(child_dict, key, &entry); + len = snprintf(key, sizeof(key), "quarantine-%d", j); + ret = dict_get_strn(child_dict, key, len, &entry); if (ret) continue; @@ -1804,7 +1794,7 @@ br_collect_bad_objects_of_child(xlator_t *this, br_child_t *child, dict_t *dict, if ((len < 0) || (len >= PATH_MAX)) { continue; } - snprintf(main_key, PATH_MAX, "quarantine-%d", tmp_count); + snprintf(main_key, sizeof(main_key), "quarantine-%d", tmp_count); ret = dict_set_dynstr_with_alloc(dict, main_key, tmp); if (!ret) diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.h b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.h index 7a3c14abb93..4e5f67bc021 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-scrub.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot-scrub.h @@ -11,7 +11,7 @@ #ifndef __BIT_ROT_SCRUB_H__ #define __BIT_ROT_SCRUB_H__ -#include "xlator.h" +#include <glusterfs/xlator.h> #include "bit-rot.h" void * diff --git a/xlators/features/bit-rot/src/bitd/bit-rot-ssm.h b/xlators/features/bit-rot/src/bitd/bit-rot-ssm.h index f3fbe2928b7..37b45a42eac 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot-ssm.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot-ssm.h @@ -11,7 +11,7 @@ #ifndef __BIT_ROT_SSM_H__ #define __BIT_ROT_SSM_H__ -#include "xlator.h" +#include <glusterfs/xlator.h> typedef enum br_scrub_state { BR_SCRUB_STATE_INACTIVE = 0, diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.c b/xlators/features/bit-rot/src/bitd/bit-rot.c index 40932268c9b..a2f1c343a1d 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.c +++ b/xlators/features/bit-rot/src/bitd/bit-rot.c @@ -9,12 +9,9 @@ */ #include <ctype.h> -#include <sys/uio.h> -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "compat-errno.h" +#include <glusterfs/logging.h> +#include <glusterfs/compat-errno.h> #include "bit-rot.h" #include "bit-rot-scrub.h" @@ -244,8 +241,8 @@ br_object_open(xlator_t *this, br_object_t *object, inode_t *inode, ret = -EINVAL; fd = fd_create(inode, 0); if (!fd) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_FD_CREATE_FAILED, - "failed to create fd for the inode %s", uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_FD_CREATE_FAILED, + "gfid=%s", uuid_utoa(inode->gfid), NULL); goto out; } @@ -296,11 +293,11 @@ br_object_read_block_and_sign(xlator_t *this, fd_t *fd, br_child_t *child, tbf = priv->tbf; ret = syncop_readv(child->xl, fd, size, offset, 0, &iovec, &count, &iobref, - NULL, NULL); + NULL, NULL, NULL); if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, BRB_MSG_READV_FAILED, - "readv on %s failed", uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, errno, BRB_MSG_READV_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); ret = -1; goto out; } @@ -350,10 +347,9 @@ br_calculate_obj_checksum(unsigned char *md, br_child_t *child, fd_t *fd, ret = br_object_read_block_and_sign(this, fd, child, offset, block, &sha256); if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_BLOCK_READ_FAILED, - "reading block with " - "offset %lu of object %s failed", - offset, uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_BLOCK_READ_FAILED, + "offset=%" PRIu64, offset, "object-gfid=%s", + uuid_utoa(fd->inode->gfid), NULL); break; } @@ -395,28 +391,23 @@ br_object_read_sign(inode_t *linked_inode, fd_t *fd, br_object_t *object, md = GF_MALLOC(SHA256_DIGEST_LENGTH, gf_common_mt_char); if (!md) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY, - "failed to allocate memory for saving hash of the " - "object %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_SAVING_HASH_FAILED, + "object-gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto out; } ret = br_object_checksum(md, object, fd, iatt); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_CALC_CHECKSUM_FAILED, - "calculating checksum " - "for the object %s failed", - uuid_utoa(linked_inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_CALC_CHECKSUM_FAILED, + "object-gfid=%s", uuid_utoa(linked_inode->gfid), NULL); goto free_signature; } sign = br_prepare_signature(md, SHA256_DIGEST_LENGTH, BR_SIGNATURE_TYPE_SHA256, object); if (!sign) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_SIGN_FAILED, - "failed to get the signature for the object %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_SIGN_FAILED, + "object-gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto free_signature; } @@ -424,17 +415,16 @@ br_object_read_sign(inode_t *linked_inode, fd_t *fd, br_object_t *object, signature_size(SHA256_DIGEST_LENGTH), _gf_true); if (!xattr) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SET_SIGN_FAILED, - "dict allocation for signing failed for the object %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SET_SIGN_FAILED, + "dict-allocation object-gfid=%s", uuid_utoa(fd->inode->gfid), + NULL); goto free_isign; } ret = syncop_fsetxattr(object->child->xl, fd, xattr, 0, NULL, NULL); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SET_SIGN_FAILED, - "fsetxattr of signature to the object %s failed", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SET_SIGN_FAILED, + "fsetxattr object-gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto unref_dict; } @@ -467,8 +457,8 @@ br_log_object(xlator_t *this, char *op, uuid_t gfid, int32_t op_errno) "[reason: %s]", op, uuid_utoa(gfid), strerror(op_errno)); } else { - gf_msg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_OP_FAILED, - "%s() failed on object %s", op, uuid_utoa(gfid)); + gf_smsg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_OP_FAILED, "op=%s", + op, "gfid=%s", uuid_utoa(gfid), NULL); } } @@ -482,8 +472,8 @@ br_log_object_path(xlator_t *this, char *op, const char *path, int32_t op_errno) "[reason: %s]", op, path, strerror(op_errno)); } else { - gf_msg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_OP_FAILED, - "%s() failed on object %s", op, path); + gf_smsg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_OP_FAILED, "op=%s", + op, "path=%s", path, NULL); } } @@ -512,8 +502,8 @@ br_trigger_sign(xlator_t *this, br_child_t *child, inode_t *linked_inode, ret = -1; fd = fd_create(linked_inode, 0); if (!fd) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_FD_CREATE_FAILED, - "Failed to create fd [GFID %s]", uuid_utoa(linked_inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_FD_CREATE_FAILED, + "gfid=%s", uuid_utoa(linked_inode->gfid), NULL); goto cleanup_dict; } @@ -537,9 +527,9 @@ cleanup_dict: dict_unref(dict); out: if (ret) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRB_MSG_TRIGGER_SIGN, - "Could not trigger signingd for %s (reopen hint: %d)", - uuid_utoa(linked_inode->gfid), val); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRB_MSG_TRIGGER_SIGN_FAILED, + "gfid=%s", uuid_utoa(linked_inode->gfid), "reopen-hint-val=%d", + val, NULL); } } @@ -619,10 +609,8 @@ br_sign_object(br_object_t *object) ret = br_object_read_sign(linked_inode, fd, object, &iatt); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_READ_AND_SIGN_FAILED, - "reading and signing of " - "the object %s failed", - uuid_utoa(linked_inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_READ_AND_SIGN_FAILED, + "gfid=%s", uuid_utoa(linked_inode->gfid), NULL); goto unref_fd; } @@ -676,8 +664,8 @@ br_process_object(void *arg) ret = br_sign_object(object); if (ret && !br_object_sign_softerror(-ret)) - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SIGN_FAILED, - "SIGNING FAILURE [%s]", uuid_utoa(object->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SET_SIGN_FAILED, + "gfid=%s", uuid_utoa(object->gfid), NULL); GF_FREE(object); } @@ -779,9 +767,8 @@ br_schedule_object_reopen(xlator_t *this, br_object_t *object, timer = br_initialize_timer(this, object, child, ev); if (!timer) - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SET_TIMER_FAILED, - "Failed to allocate object expiry timer [GFID: %s]", - uuid_utoa(object->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SET_TIMER_FAILED, + "gfid=%s", uuid_utoa(object->gfid), NULL); return timer ? 0 : -1; } @@ -828,15 +815,15 @@ br_brick_callback(void *xl, char *brick, void *data, changelog_event_t *ev) child = br_get_child_from_brick_path(this, brick); if (!child) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_SUBVOL_FAILED, - "failed to get the subvolume for the brick %s", brick); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_SUBVOL_FAILED, + "brick=%s", brick, NULL); goto out; } object = br_initialize_object(this, child, ev); if (!object) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY, - "failed to allocate object memory [GFID: %s]", uuid_utoa(gfid)); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY, + "object-gfid=%s", uuid_utoa(gfid), NULL); goto out; } @@ -888,8 +875,8 @@ br_check_object_need_sign(xlator_t *this, dict_t *xattr, br_child_t *child) ret = dict_get_ptr(xattr, GLUSTERFS_GET_OBJECT_SIGNATURE, (void **)&sign); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_SIGN_FAILED, - "failed to get object signature info"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_SIGN_FAILED, + "object-info", NULL); goto out; } @@ -928,9 +915,9 @@ br_prepare_loc(xlator_t *this, br_child_t *child, loc_t *parent, ret = inode_path(parent->inode, entry->d_name, (char **)&loc->path); if (ret < 0 || !loc->path) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_PATH_FAILED, - "inode_path on %s (parent: %s) failed", entry->d_name, - uuid_utoa(parent->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_PATH_FAILED, + "inode_path=%s", entry->d_name, "parent-gfid=%s", + uuid_utoa(parent->inode->gfid), NULL); goto out; } @@ -974,6 +961,7 @@ bitd_oneshot_crawl(xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, int32_t ret = -1; inode_t *linked_inode = NULL; gf_boolean_t need_signing = _gf_false; + gf_boolean_t need_reopen = _gf_true; GF_VALIDATE_OR_GOTO("bit-rot", subvol, out); GF_VALIDATE_OR_GOTO("bit-rot", data, out); @@ -1021,8 +1009,8 @@ bitd_oneshot_crawl(xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, */ if (bitd_is_bad_file(this, child, &loc, NULL)) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRB_MSG_SKIP_OBJECT, - "Entry [%s] is marked corrupted.. skipping.", loc.path); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRB_MSG_SKIP_OBJECT, "path=%s", + loc.path, NULL); goto unref_inode; } @@ -1039,23 +1027,32 @@ bitd_oneshot_crawl(xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, if (op_errno == ENODATA && (iatt.ia_size != 0)) need_signing = _gf_true; if (op_errno == EINVAL) - gf_msg(this->name, GF_LOG_WARNING, 0, - BRB_MSG_PARTIAL_VERSION_PRESENCE, - "Partial " - "version xattr presence detected, ignoring " - "[GFID: %s]", - uuid_utoa(linked_inode->gfid)); + gf_smsg(this->name, GF_LOG_WARNING, 0, + BRB_MSG_PARTIAL_VERSION_PRESENCE, "gfid=%s", + uuid_utoa(linked_inode->gfid), NULL); } else { need_signing = br_check_object_need_sign(this, xattr, child); + + /* + * If we are here means, bitrot daemon has started. Is it just + * a simple restart of the daemon or is it started because the + * feature is enabled is something hard to determine. Hence, + * if need_signing is false (because bit-rot version and signature + * are present), then still go ahead and sign it. + */ + if (!need_signing) { + need_signing = _gf_true; + need_reopen = _gf_true; + } } if (!need_signing) goto unref_dict; - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_TRIGGER_SIGN, - "Triggering signing for %s [GFID: %s | Brick: %s]", loc.path, - uuid_utoa(linked_inode->gfid), child->brick_path); - br_trigger_sign(this, child, linked_inode, &loc, _gf_true); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_TRIGGER_SIGN, "path=%s", + loc.path, "gfid=%s", uuid_utoa(linked_inode->gfid), "Brick-path=%s", + child->brick_path, NULL); + br_trigger_sign(this, child, linked_inode, &loc, need_reopen); ret = 0; @@ -1087,17 +1084,16 @@ br_oneshot_signer(void *arg) THIS = this; - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_CRAWLING_START, - "Crawling brick [%s], scanning for unsigned objects", - child->brick_path); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_CRAWLING_START, "brick-path=%s", + child->brick_path, NULL); loc.inode = child->table->root; (void)syncop_ftw_throttle(child->xl, &loc, GF_CLIENT_PID_BITD, child, bitd_oneshot_crawl, BR_CRAWL_THROTTLE_COUNT, BR_CRAWL_THROTTLE_ZZZ); - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_CRAWLING_FINISH, - "Completed crawling brick [%s]", child->brick_path); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_CRAWLING_FINISH, + "brick-path=%s", child->brick_path, NULL); return NULL; } @@ -1141,9 +1137,7 @@ br_enact_signer(xlator_t *this, br_child_t *child, br_stub_init_t *stub) ret = gf_changelog_register_generic(brick, 1, 1, this->ctx->cmd_args.log_file, -1, this); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, errno, BRB_MSG_REGISTER_FAILED, - "Register to changelog " - "failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, BRB_MSG_REGISTER_FAILED, NULL); goto dealloc; } @@ -1151,8 +1145,8 @@ br_enact_signer(xlator_t *this, br_child_t *child, br_stub_init_t *stub) ret = gf_thread_create(&child->thread, NULL, br_oneshot_signer, child, "brosign"); if (ret) - gf_msg(this->name, GF_LOG_WARNING, 0, BRB_MSG_SPAWN_FAILED, - "failed to spawn FS crawler thread"); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRB_MSG_SPAWN_FAILED, + "FS-crawler-thread", NULL); else child->threadrunning = 1; @@ -1180,9 +1174,9 @@ br_launch_scrubber(xlator_t *this, br_child_t *child, struct br_scanfs *fsscan, ret = gf_thread_create(&child->thread, NULL, br_fsscanner, child, "brfsscan"); if (ret != 0) { - gf_msg(this->name, GF_LOG_ALERT, 0, BRB_MSG_SPAWN_FAILED, - "failed to spawn bitrot scrubber daemon [Brick: %s]", - child->brick_path); + gf_smsg(this->name, GF_LOG_ALERT, 0, BRB_MSG_SPAWN_FAILED, + "bitrot-scrubber-daemon Brick-path=%s", child->brick_path, + NULL); goto error_return; } @@ -1270,8 +1264,8 @@ br_child_enaction(xlator_t *this, br_child_t *child, br_stub_init_t *stub) if (!ret) { child->witnessed = 1; _br_set_child_state(child, BR_CHILD_STATE_CONNECTED); - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_CONNECTED_TO_BRICK, - "Connected to brick %s..", child->brick_path); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_CONNECTED_TO_BRICK, + "brick-path=%s", child->brick_path, NULL); } } pthread_mutex_unlock(&child->lock); @@ -1318,8 +1312,8 @@ br_brick_connect(xlator_t *this, br_child_t *child) if (ret) { op_errno = -ret; ret = -1; - gf_msg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_LOOKUP_FAILED, - "lookup on root failed"); + gf_smsg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_LOOKUP_FAILED, + NULL); goto wipeloc; } @@ -1328,15 +1322,14 @@ br_brick_connect(xlator_t *this, br_child_t *child) if (ret) { op_errno = -ret; ret = -1; - gf_msg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_GET_INFO_FAILED, - "failed to get stub info"); + gf_smsg(this->name, GF_LOG_ERROR, op_errno, BRB_MSG_GET_INFO_FAILED, + NULL); goto wipeloc; } ret = dict_get_ptr(xattr, GLUSTERFS_GET_BR_STUB_INIT_TIME, (void **)&stub); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_INFO_FAILED, - "failed to extract stub information"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_GET_INFO_FAILED, NULL); goto free_dict; } @@ -1406,11 +1399,10 @@ br_cleanup_scrubber(xlator_t *this, br_child_t *child) */ ret = gf_thread_cleanup_xint(child->thread); if (ret) - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_THREAD_CLEANUP, - "Error cleaning up scanner thread"); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUB_THREAD_CLEANUP, NULL); - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUBBER_CLEANED, - "Cleaned up scrubber for brick [%s]", child->brick_path); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_SCRUBBER_CLEANED, + "brick-path=%s", child->brick_path, NULL); return 0; } @@ -1495,9 +1487,8 @@ br_handle_events(void *arg) child = childev->child; ret = childev->call(this, child); if (ret) - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SUBVOL_CONNECT_FAILED, - "callback handler for subvolume [%s] failed", - child->xl->name); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_SUBVOL_CONNECT_FAILED, + "name=%s", child->xl->name, NULL); GF_FREE(childev); } @@ -1515,8 +1506,7 @@ mem_acct_init(xlator_t *this) ret = xlator_mem_acct_init(this, gf_br_stub_mt_end + 1); if (ret != 0) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRB_MSG_MEM_ACNT_FAILED, - "Memory accounting init failed"); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRB_MSG_MEM_ACNT_FAILED, NULL); return ret; } @@ -1533,8 +1523,8 @@ _br_qchild_event(xlator_t *this, br_child_t *child, br_child_handler *call) childev = GF_CALLOC(1, sizeof(*childev), gf_br_mt_br_child_event_t); if (!childev) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY, - "Event unhandled for child.. [Brick: %s]", child->xl->name); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_EVENT_UNHANDLED, + "Brick-name=%s", child->xl->name, NULL); return; } @@ -1629,10 +1619,8 @@ notify(xlator_t *this, int32_t event, void *data, ...) switch (event) { case GF_EVENT_CHILD_UP: if (idx < 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_INVALID_SUBVOL, - "Got event %d from " - "invalid subvolume", - event); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_INVALID_SUBVOL, + "event=%d", event, NULL); goto out; } @@ -1660,9 +1648,8 @@ notify(xlator_t *this, int32_t event, void *data, ...) case GF_EVENT_CHILD_DOWN: if (idx < 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, - BRB_MSG_INVALID_SUBVOL_CHILD, - "Got event %d from invalid subvolume", event); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_INVALID_SUBVOL, + "event=%d", event, NULL); goto out; } @@ -1703,11 +1690,9 @@ notify(xlator_t *this, int32_t event, void *data, ...) "called"); if (scrub_monitor->state != BR_SCRUB_STATE_PENDING) { - gf_msg(this->name, GF_LOG_ERROR, 0, - BRB_MSG_RESCHEDULE_SCRUBBER_FAILED, - "on demand scrub schedule failed. Scrubber is " - "not in pending state. Current state is %d", - scrub_monitor->state); + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRB_MSG_RESCHEDULE_SCRUBBER_FAILED, "Current-state=%d", + scrub_monitor->state, NULL); return -2; } @@ -1719,11 +1704,8 @@ notify(xlator_t *this, int32_t event, void *data, ...) pthread_mutex_unlock(&priv->lock); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - BRB_MSG_RESCHEDULE_SCRUBBER_FAILED, - "Could not schedule ondemand scrubbing. " - "Scrubbing will continue according to " - "old frequency."); + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRB_MSG_COULD_NOT_SCHEDULE_SCRUB, NULL); } gf_msg_debug(this->name, 0, "returning %d", ret); break; @@ -1735,22 +1717,26 @@ out: return 0; } -/** - * Initialize signer specific structures, spawn worker threads. - */ - static void br_fini_signer(xlator_t *this, br_private_t *priv) { int i = 0; - for (; i < BR_WORKERS; i++) { + if (priv == NULL) + return; + + for (; i < priv->signer_th_count; i++) { (void)gf_thread_cleanup_xint(priv->obj_queue->workers[i]); } + GF_FREE(priv->obj_queue->workers); pthread_cond_destroy(&priv->object_cond); } +/** + * Initialize signer specific structures, spawn worker threads. + */ + static int32_t br_init_signer(xlator_t *this, br_private_t *priv) { @@ -1770,13 +1756,17 @@ br_init_signer(xlator_t *this, br_private_t *priv) goto cleanup_cond; INIT_LIST_HEAD(&priv->obj_queue->objects); - for (i = 0; i < BR_WORKERS; i++) { + priv->obj_queue->workers = GF_CALLOC( + priv->signer_th_count, sizeof(pthread_t), gf_br_mt_br_worker_t); + if (!priv->obj_queue->workers) + goto cleanup_obj_queue; + + for (i = 0; i < priv->signer_th_count; i++) { ret = gf_thread_create(&priv->obj_queue->workers[i], NULL, br_process_object, this, "brpobj"); if (ret != 0) { - gf_msg(this->name, GF_LOG_ERROR, -ret, BRB_MSG_SPAWN_FAILED, - "thread creation" - " failed"); + gf_smsg(this->name, GF_LOG_ERROR, -ret, + BRB_MSG_THREAD_CREATION_FAILED, NULL); ret = -1; goto cleanup_threads; } @@ -1788,7 +1778,9 @@ cleanup_threads: for (i--; i >= 0; i--) { (void)gf_thread_cleanup_xint(priv->obj_queue->workers[i]); } + GF_FREE(priv->obj_queue->workers); +cleanup_obj_queue: GF_FREE(priv->obj_queue); cleanup_cond: @@ -1841,18 +1833,17 @@ br_rate_limit_signer(xlator_t *this, int child_count, int numbricks) if (contribution == 0) contribution = 1; spec.rate = BR_HASH_CALC_READ_SIZE * contribution; - spec.maxlimit = BR_WORKERS * BR_HASH_CALC_READ_SIZE; + spec.maxlimit = priv->signer_th_count * BR_HASH_CALC_READ_SIZE; #endif if (!spec.rate) - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_RATE_LIMIT_INFO, - "[Rate Limit Info] \"FULL THROTTLE\""); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_RATE_LIMIT_INFO, + "FULL THROTTLE", NULL); else - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_RATE_LIMIT_INFO, - "[Rate Limit Info] \"tokens/sec (rate): %lu, " - "maxlimit: %lu\"", - spec.rate, spec.maxlimit); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_RATE_LIMIT_INFO, + "tokens/sec-rate=%lu", spec.rate, "maxlimit=%lu", spec.maxlimit, + NULL); priv->tbf = tbf_init(&spec, 1); return priv->tbf ? 0 : -1; @@ -1861,11 +1852,16 @@ br_rate_limit_signer(xlator_t *this, int child_count, int numbricks) static int32_t br_signer_handle_options(xlator_t *this, br_private_t *priv, dict_t *options) { - if (options) + if (options) { GF_OPTION_RECONF("expiry-time", priv->expiry_time, options, uint32, error_return); - else + GF_OPTION_RECONF("signer-threads", priv->signer_th_count, options, + uint32, error_return); + } else { GF_OPTION_INIT("expiry-time", priv->expiry_time, uint32, error_return); + GF_OPTION_INIT("signer-threads", priv->signer_th_count, uint32, + error_return); + } return 0; @@ -1881,6 +1877,8 @@ br_signer_init(xlator_t *this, br_private_t *priv) GF_OPTION_INIT("expiry-time", priv->expiry_time, uint32, error_return); GF_OPTION_INIT("brick-count", numbricks, int32, error_return); + GF_OPTION_INIT("signer-threads", priv->signer_th_count, uint32, + error_return); ret = br_rate_limit_signer(this, priv->child_count, numbricks); if (ret) @@ -1967,8 +1965,8 @@ br_init_children(xlator_t *this, br_private_t *priv) child->timer_pool = mem_pool_new(struct gf_tw_timer_list, 4096); if (!child->timer_pool) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY, - "failed to allocate mem-pool for timer"); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_MEM_POOL_ALLOC, + NULL); errno = ENOMEM; goto freechild; } @@ -1994,15 +1992,13 @@ init(xlator_t *this) br_private_t *priv = NULL; if (!this->children) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_NO_CHILD, - "FATAL: no children"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_NO_CHILD, NULL); goto out; } priv = GF_CALLOC(1, sizeof(*priv), gf_br_mt_br_private_t); if (!priv) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY, - "failed to allocate memory (->priv)"); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, BRB_MSG_NO_MEMORY, NULL); goto out; } @@ -2020,8 +2016,8 @@ init(xlator_t *this) priv->timer_wheel = glusterfs_ctx_tw_get(this->ctx); if (!priv->timer_wheel) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_TIMER_WHEEL_UNAVAILABLE, - "global timer wheel unavailable"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_TIMER_WHEEL_UNAVAILABLE, + NULL); goto cleanup; } @@ -2043,15 +2039,14 @@ init(xlator_t *this) ret = gf_thread_create(&priv->thread, NULL, br_handle_events, this, "brhevent"); if (ret != 0) { - gf_msg(this->name, GF_LOG_ERROR, -ret, BRB_MSG_SPAWN_FAILED, - "thread creation failed"); + gf_smsg(this->name, GF_LOG_ERROR, -ret, BRB_MSG_THREAD_CREATION_FAILED, + NULL); ret = -1; } if (!ret) { - gf_msg(this->name, GF_LOG_INFO, 0, BRB_MSG_BITROT_LOADED, - "bit-rot xlator loaded in \"%s\" mode", - (priv->iamscrubber) ? "SCRUBBER" : "SIGNER"); + gf_smsg(this->name, GF_LOG_INFO, 0, BRB_MSG_BITROT_LOADED, "mode=%s", + (priv->iamscrubber) ? "SCRUBBER" : "SIGNER", NULL); return 0; } @@ -2098,9 +2093,8 @@ br_reconfigure_monitor(xlator_t *this) ret = br_scrub_state_machine(this, _gf_false); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRB_MSG_RESCHEDULE_SCRUBBER_FAILED, - "Could not reschedule scrubber for the volume. Scrubbing " - "will continue according to old frequency."); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRB_MSG_COULD_NOT_SCHEDULE_SCRUB, + NULL); } } @@ -2211,5 +2205,28 @@ struct volume_options options[] = { .description = "Pause/Resume scrub. Upon resume, scrubber " "continues from where it left off.", }, + { + .key = {"signer-threads"}, + .type = GF_OPTION_TYPE_INT, + .default_value = BR_WORKERS, + .op_version = {GD_OP_VERSION_8_0}, + .flags = OPT_FLAG_SETTABLE, + .description = "Number of signing process threads. As a best " + "practice, set this to the number of processor cores", + }, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "bit-rot", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/bit-rot/src/bitd/bit-rot.h b/xlators/features/bit-rot/src/bitd/bit-rot.h index 962b4d717e6..8ac7dcdac3d 100644 --- a/xlators/features/bit-rot/src/bitd/bit-rot.h +++ b/xlators/features/bit-rot/src/bitd/bit-rot.h @@ -11,17 +11,17 @@ #ifndef __BIT_ROT_H__ #define __BIT_ROT_H__ -#include "glusterfs.h" -#include "logging.h" -#include "dict.h" -#include "xlator.h" -#include "defaults.h" -#include "syncop.h" -#include "syncop-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/syncop.h> +#include <glusterfs/syncop-utils.h> #include "changelog.h" #include "timer-wheel.h" -#include "throttle-tbf.h" +#include <glusterfs/throttle-tbf.h> #include "bit-rot-ssm.h" #include "bit-rot-common.h" @@ -30,12 +30,6 @@ #include <openssl/sha.h> -/** - * TODO: make this configurable. As a best practice, set this to the - * number of processor cores. - */ -#define BR_WORKERS 4 - typedef enum scrub_throttle { BR_SCRUB_THROTTLE_VOID = -1, BR_SCRUB_THROTTLE_LAZY = 0, @@ -108,12 +102,12 @@ struct br_child { typedef struct br_child br_child_t; struct br_obj_n_workers { - struct list_head objects; /* queue of objects expired from the - timer wheel and ready to be picked - up for signing */ - pthread_t workers[BR_WORKERS]; /* Threads which pick up the objects - from the above queue and start - signing each object */ + struct list_head objects; /* queue of objects expired from the + timer wheel and ready to be picked + up for signing */ + pthread_t *workers; /* Threads which pick up the objects + from the above queue and start + signing each object */ }; struct br_scrubber { @@ -209,6 +203,8 @@ struct br_private { uint32_t expiry_time; /* objects "wait" time */ + uint32_t signer_th_count; /* Number of signing process threads */ + tbf_t *tbf; /* token bucket filter */ gf_boolean_t iamscrubber; /* function as a fs scrubber */ diff --git a/xlators/features/bit-rot/src/stub/bit-rot-common.h b/xlators/features/bit-rot/src/stub/bit-rot-common.h index ef683ac7f9f..20561aa7764 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-common.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-common.h @@ -11,7 +11,7 @@ #ifndef __BIT_ROT_COMMON_H__ #define __BIT_ROT_COMMON_H__ -#include "glusterfs.h" +#include <glusterfs/glusterfs.h> #include "bit-rot-object-version.h" #define BR_VXATTR_VERSION (1 << 0) diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c b/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c index cb567297b60..8ac13a09941 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c @@ -133,8 +133,8 @@ br_stub_add(xlator_t *this, uuid_t gfid) * show up less number of objects. That's fine as we'll have * the log files that will have the missing information. */ - gf_msg(this->name, GF_LOG_WARNING, errno, BRS_MSG_LINK_FAIL, - "failed to record gfid [%s]", uuid_utoa(gfid)); + gf_smsg(this->name, GF_LOG_WARNING, errno, BRS_MSG_LINK_FAIL, "gfid=%s", + uuid_utoa(gfid), NULL); } return 0; @@ -157,10 +157,8 @@ br_stub_del(xlator_t *this, uuid_t gfid) uuid_utoa(gfid)); ret = sys_unlink(gfid_path); if (ret && (errno != ENOENT)) { - gf_msg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJ_UNLINK_FAIL, - "%s: failed to delete bad object link from quarantine " - "directory", - gfid_path); + gf_smsg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJ_UNLINK_FAIL, + "path=%s", gfid_path, NULL); ret = -errno; goto out; } @@ -200,13 +198,13 @@ br_stub_check_stub_directory(xlator_t *this, char *fullpath) } if (ret) - gf_msg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJECT_DIR_FAIL, - "failed to create stub directory [%s]", fullpath); + gf_smsg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJECT_DIR_FAIL, + "create-path=%s", fullpath, NULL); return ret; error_return: - gf_msg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJECT_DIR_FAIL, - "Failed to verify stub directory [%s]", fullpath); + gf_smsg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJECT_DIR_FAIL, + "verify-path=%s", fullpath, NULL); return -1; } @@ -231,8 +229,8 @@ br_stub_check_stub_file(xlator_t *this, char *path) goto error_return; fd = sys_creat(path, 0); if (fd < 0) - gf_msg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJECT_DIR_FAIL, - "Failed to create stub file [%s]", path); + gf_smsg(this->name, GF_LOG_ERROR, errno, + BRS_MSG_BAD_OBJECT_DIR_FAIL, "create-path=%s", path, NULL); } if (fd >= 0) { @@ -243,8 +241,8 @@ br_stub_check_stub_file(xlator_t *this, char *path) return ret; error_return: - gf_msg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJECT_DIR_FAIL, - "Failed to verify stub file [%s]", path); + gf_smsg(this->name, GF_LOG_ERROR, errno, BRS_MSG_BAD_OBJECT_DIR_FAIL, + "verify-path=%s", path, NULL); return -1; } @@ -463,12 +461,9 @@ br_stub_fill_readdir(fd_t *fd, br_stub_fd_t *fctx, DIR *dir, off_t off, seekdir(dir, off); #ifndef GF_LINUX_HOST_OS if ((u_long)telldir(dir) != off && off != fctx->bad_object.dir_eof) { - gf_msg(THIS->name, GF_LOG_ERROR, 0, - BRS_MSG_BAD_OBJECT_DIR_SEEK_FAIL, - "seekdir(0x%llx) failed on dir=%p: " - "Invalid argument (offset reused from " - "another DIR * structure?)", - off, dir); + gf_smsg(THIS->name, GF_LOG_ERROR, 0, + BRS_MSG_BAD_OBJECT_DIR_SEEK_FAIL, "off=(0x%llx)", off, + "dir=%p", dir, NULL); errno = EINVAL; count = -1; goto out; @@ -480,9 +475,9 @@ br_stub_fill_readdir(fd_t *fd, br_stub_fd_t *fctx, DIR *dir, off_t off, in_case = (u_long)telldir(dir); if (in_case == -1) { - gf_msg(THIS->name, GF_LOG_ERROR, 0, - BRS_MSG_BAD_OBJECT_DIR_TELL_FAIL, - "telldir failed on dir=%p: %s", dir, strerror(errno)); + gf_smsg(THIS->name, GF_LOG_ERROR, 0, + BRS_MSG_BAD_OBJECT_DIR_TELL_FAIL, "dir=%p", dir, "err=%s", + strerror(errno), NULL); goto out; } @@ -490,9 +485,9 @@ br_stub_fill_readdir(fd_t *fd, br_stub_fd_t *fctx, DIR *dir, off_t off, entry = sys_readdir(dir, scratch); if (!entry || errno != 0) { if (errno == EBADF) { - gf_msg(THIS->name, GF_LOG_WARNING, 0, - BRS_MSG_BAD_OBJECT_DIR_READ_FAIL, - "readdir failed on dir=%p: %s", dir, strerror(errno)); + gf_smsg(THIS->name, GF_LOG_WARNING, 0, + BRS_MSG_BAD_OBJECT_DIR_READ_FAIL, "dir=%p", dir, + "err=%s", strerror(errno), NULL); goto out; } break; @@ -514,12 +509,9 @@ br_stub_fill_readdir(fd_t *fd, br_stub_fd_t *fctx, DIR *dir, off_t off, #ifndef GF_LINUX_HOST_OS if ((u_long)telldir(dir) != in_case && in_case != fctx->bad_object.dir_eof) { - gf_msg(THIS->name, GF_LOG_ERROR, 0, - BRS_MSG_BAD_OBJECT_DIR_SEEK_FAIL, - "seekdir(0x%llx) failed on dir=%p: " - "Invalid argument (offset reused from " - "another DIR * structure?)", - in_case, dir); + gf_smsg(THIS->name, GF_LOG_ERROR, 0, + BRS_MSG_BAD_OBJECT_DIR_SEEK_FAIL, "in_case=(0x%llx)", + in_case, "dir=%p", dir, NULL); errno = EINVAL; count = -1; goto out; @@ -531,9 +523,9 @@ br_stub_fill_readdir(fd_t *fd, br_stub_fd_t *fctx, DIR *dir, off_t off, this_entry = gf_dirent_for_name(entry->d_name); if (!this_entry) { - gf_msg(THIS->name, GF_LOG_ERROR, 0, BRS_MSG_NO_MEMORY, - "could not create gf_dirent for entry %s: (%s)", - entry->d_name, strerror(errno)); + gf_smsg(THIS->name, GF_LOG_ERROR, 0, + BRS_MSG_CREATE_GF_DIRENT_FAILED, "entry-name=%s", + entry->d_name, "err=%s", strerror(errno), NULL); goto out; } /* @@ -580,8 +572,8 @@ br_stub_readdir_wrapper(call_frame_t *frame, xlator_t *this, fd_t *fd, fctx = br_stub_fd_ctx_get(this, fd); if (!fctx) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_GET_FD_CONTEXT_FAILED, - "pfd is NULL, fd=%p", fd); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_GET_FD_CONTEXT_FAILED, + "fd=%p", fd, NULL); op_errno = -ret; goto done; } @@ -589,8 +581,8 @@ br_stub_readdir_wrapper(call_frame_t *frame, xlator_t *this, fd_t *fd, dir = fctx->bad_object.dir; if (!dir) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_BAD_HANDLE_DIR_NULL, - "dir is NULL for fd=%p", fd); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_BAD_HANDLE_DIR_NULL, + "fd=%p", fd, NULL); op_errno = EINVAL; goto done; } @@ -680,10 +672,7 @@ br_stub_bad_objects_path(xlator_t *this, fd_t *fd, gf_dirent_t *entries, * be shown. */ if (!tmp_dict) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_NO_MEMORY, - "failed to allocate new dict for saving the paths " - "of the corrupted objects. Scrub status will only " - "display the gfid"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ALLOC_FAILED, NULL); goto out; } } @@ -707,9 +696,8 @@ br_stub_bad_objects_path(xlator_t *this, fd_t *fd, gf_dirent_t *entries, uuid_utoa(gfid), hpath); br_stub_entry_xattr_fill(this, hpath, entry, tmp_dict); } else - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_PATH_GET_FAILED, - "failed to get the path for the inode %s", - uuid_utoa_r(gfid, str_gfid)); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_PATH_GET_FAILED, + "gfid=%s", uuid_utoa_r(gfid, str_gfid), NULL); inode = NULL; hpath = NULL; @@ -744,10 +732,8 @@ br_stub_get_path_of_gfid(xlator_t *this, inode_t *parent, inode_t *inode, ret = syncop_gfid_to_path_hard(parent->table, FIRST_CHILD(this), gfid, inode, path, _gf_true); if (ret < 0) - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_PATH_GET_FAILED, - "failed to get the path xattr from disk for the " - " gfid %s. Trying to get path from the memory", - uuid_utoa_r(gfid, gfid_str)); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_PATH_GET_FAILED, + "gfid=%s", uuid_utoa_r(gfid, gfid_str), NULL); /* * Try with soft resolution of path if hard resolve fails. Because @@ -768,9 +754,8 @@ br_stub_get_path_of_gfid(xlator_t *this, inode_t *parent, inode_t *inode, ret = syncop_gfid_to_path_hard(parent->table, FIRST_CHILD(this), gfid, inode, path, _gf_false); if (ret < 0) - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_PATH_GET_FAILED, - "failed to get the path from the memory for gfid %s", - uuid_utoa_r(gfid, gfid_str)); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_PATH_GET_FAILED, + "from-memory gfid=%s", uuid_utoa_r(gfid, gfid_str), NULL); } out: @@ -804,10 +789,8 @@ br_stub_entry_xattr_fill(xlator_t *this, char *hpath, gf_dirent_t *entry, ret = dict_set_dynstr(dict, entry->d_name, hpath); if (ret) - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_DICT_SET_FAILED, - "failed to set the actual path %s as the value in the " - "dict for the corrupted object %s", - hpath, entry->d_name); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_DICT_SET_FAILED, + "path=%s", hpath, "object-name=%s", entry->d_name, NULL); out: return; } diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h b/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h index a3e7b03291e..9d93caf069f 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h @@ -11,7 +11,7 @@ #ifndef _BR_MEM_TYPES_H #define _BR_MEM_TYPES_H -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum br_mem_types { gf_br_stub_mt_private_t = gf_common_mt_end + 1, @@ -29,6 +29,7 @@ enum br_mem_types { gf_br_stub_mt_sigstub_t, gf_br_mt_br_child_event_t, gf_br_stub_mt_misc, + gf_br_mt_br_worker_t, gf_br_stub_mt_end, }; diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h b/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h index cccc3b9c599..6c15a166f18 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h @@ -11,7 +11,7 @@ #ifndef _BITROT_STUB_MESSAGES_H_ #define _BITROT_STUB_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * @@ -39,6 +39,79 @@ GLFS_MSGID(BITROT_STUB, BRS_MSG_NO_MEMORY, BRS_MSG_SET_EVENT_FAILED, BRS_MSG_BAD_HANDLE_DIR_NULL, BRS_MSG_BAD_OBJ_THREAD_FAIL, BRS_MSG_BAD_OBJ_DIR_CLOSE_FAIL, BRS_MSG_LINK_FAIL, BRS_MSG_BAD_OBJ_UNLINK_FAIL, BRS_MSG_DICT_SET_FAILED, - BRS_MSG_PATH_GET_FAILED); + BRS_MSG_PATH_GET_FAILED, BRS_MSG_NULL_LOCAL, + BRS_MSG_SPAWN_SIGN_THRD_FAILED, BRS_MSG_KILL_SIGN_THREAD, + BRS_MSG_NON_BITD_PID, BRS_MSG_SIGN_PREPARE_FAIL, + BRS_MSG_USING_DEFAULT_THREAD_SIZE, BRS_MSG_ALLOC_MEM_FAILED, + BRS_MSG_DICT_ALLOC_FAILED, BRS_MSG_CREATE_GF_DIRENT_FAILED, + BRS_MSG_ALLOC_FAILED, BRS_MSG_PATH_XATTR_GET_FAILED, + BRS_MSG_VERSION_PREPARE_FAIL); +#define BRS_MSG_MEM_ACNT_FAILED_STR "Memory accounting init failed" +#define BRS_MSG_BAD_OBJ_THREAD_FAIL_STR "pthread_init failed" +#define BRS_MSG_USING_DEFAULT_THREAD_SIZE_STR "Using default thread stack size" +#define BRS_MSG_NO_CHILD_STR "FATAL: no children" +#define BRS_MSG_SPAWN_SIGN_THRD_FAILED_STR \ + "failed to create the new thread for signer" +#define BRS_MSG_BAD_CONTAINER_FAIL_STR \ + "failed to launch the thread for storing bad gfids" +#define BRS_MSG_CANCEL_SIGN_THREAD_FAILED_STR \ + "Could not cancel sign serializer thread" +#define BRS_MSG_KILL_SIGN_THREAD_STR "killed the signer thread" +#define BRS_MSG_GET_INODE_CONTEXT_FAILED_STR \ + "failed to init the inode context for the inode" +#define BRS_MSG_ADD_FD_TO_INODE_STR "failed to add fd to the inode" +#define BRS_MSG_NO_MEMORY_STR "local allocation failed" +#define BRS_MSG_BAD_OBJECT_ACCESS_STR "bad object accessed. Returning" +#define BRS_MSG_SIGN_VERSION_ERROR_STR "Signing version exceeds current version" +#define BRS_MSG_NON_BITD_PID_STR \ + "PID from where signature request came, does not belong to bit-rot " \ + "daemon. Unwinding the fop" +#define BRS_MSG_SIGN_PREPARE_FAIL_STR \ + "failed to prepare the signature. Unwinding the fop" +#define BRS_MSG_VERSION_PREPARE_FAIL_STR \ + "failed to prepare the version. Unwinding the fop" +#define BRS_MSG_STUB_ALLOC_FAILED_STR "failed to allocate stub fop, Unwinding" +#define BRS_MSG_BAD_OBJ_MARK_FAIL_STR "failed to mark object as bad" +#define BRS_MSG_NON_SCRUB_BAD_OBJ_MARK_STR \ + "bad object marking is not from the scrubber" +#define BRS_MSG_ALLOC_MEM_FAILED_STR "failed to allocate memory" +#define BRS_MSG_SET_INTERNAL_XATTR_STR "called on the internal xattr" +#define BRS_MSG_REMOVE_INTERNAL_XATTR_STR "removexattr called on internal xattr" +#define BRS_MSG_CREATE_ANONYMOUS_FD_FAILED_STR \ + "failed to create anonymous fd for the inode" +#define BRS_MSG_ADD_FD_TO_LIST_FAILED_STR "failed add fd to the list" +#define BRS_MSG_SET_FD_CONTEXT_FAILED_STR \ + "failed to set the fd context for the file" +#define BRS_MSG_NULL_LOCAL_STR "local is NULL" +#define BRS_MSG_DICT_ALLOC_FAILED_STR \ + "dict allocation failed: cannot send IPC FOP to changelog" +#define BRS_MSG_SET_EVENT_FAILED_STR "cannot set release event in dict" +#define BRS_MSG_CREATE_FRAME_FAILED_STR "create_frame() failure" +#define BRS_MSG_BAD_OBJ_DIR_CLOSE_FAIL_STR "closedir error" +#define BRS_MSG_LINK_FAIL_STR "failed to record gfid" +#define BRS_MSG_BAD_OBJ_UNLINK_FAIL_STR \ + "failed to delete bad object link from quaratine directory" +#define BRS_MSG_BAD_OBJECT_DIR_FAIL_STR "failed stub directory" +#define BRS_MSG_BAD_OBJECT_DIR_SEEK_FAIL_STR \ + "seekdir failed. Invalid argument (offset reused from another DIR * " \ + "structure)" +#define BRS_MSG_BAD_OBJECT_DIR_TELL_FAIL_STR "telldir failed on dir" +#define BRS_MSG_BAD_OBJECT_DIR_READ_FAIL_STR "readdir failed on dir" +#define BRS_MSG_CREATE_GF_DIRENT_FAILED_STR "could not create gf_dirent" +#define BRS_MSG_GET_FD_CONTEXT_FAILED_STR "pfd is NULL" +#define BRS_MSG_BAD_HANDLE_DIR_NULL_STR "dir if NULL" +#define BRS_MSG_ALLOC_FAILED_STR \ + "failed to allocate new dict for saving the paths of the corrupted " \ + "objects. Scrub status will only display the gfid" +#define BRS_MSG_PATH_GET_FAILED_STR "failed to get the path" +#define BRS_MSG_PATH_XATTR_GET_FAILED_STR \ + "failed to get the path xattr from disk for the gfid. Trying to get path " \ + "from the memory" +#define BRS_MSG_DICT_SET_FAILED_STR \ + "failed to set the actual path as the value in the dict for the " \ + "corrupted object" +#define BRS_MSG_SET_CONTEXT_FAILED_STR \ + "could not set fd context for release callback" +#define BRS_MSG_CHANGE_VERSION_FAILED_STR "change version failed" #endif /* !_BITROT_STUB_MESSAGES_H_ */ diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.c b/xlators/features/bit-rot/src/stub/bit-rot-stub.c index 2f5cc2b18dd..447dd47ff41 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.c +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.c @@ -12,12 +12,11 @@ #include <sys/uio.h> #include <signal.h> -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> #include "changelog.h" -#include "compat-errno.h" -#include "call-stub.h" +#include <glusterfs/compat-errno.h> +#include <glusterfs/call-stub.h> #include "bit-rot-stub.h" #include "bit-rot-stub-mem-types.h" @@ -26,6 +25,15 @@ #define BR_STUB_REQUEST_COOKIE 0x1 +void +br_stub_lock_cleaner(void *arg) +{ + pthread_mutex_t *clean_mutex = arg; + + pthread_mutex_unlock(clean_mutex); + return; +} + void * br_stub_signth(void *); @@ -48,8 +56,7 @@ mem_acct_init(xlator_t *this) ret = xlator_mem_acct_init(this, gf_br_stub_mt_end + 1); if (ret != 0) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_MEM_ACNT_FAILED, - "Memory accounting init failed"); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_MEM_ACNT_FAILED, NULL); return ret; } @@ -64,29 +71,29 @@ br_stub_bad_object_container_init(xlator_t *this, br_stub_private_t *priv) ret = pthread_cond_init(&priv->container.bad_cond, NULL); if (ret != 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_THREAD_FAIL, - "pthread_cond_init failed (%d)", ret); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_THREAD_FAIL, + "cond_init ret=%d", ret, NULL); goto out; } ret = pthread_mutex_init(&priv->container.bad_lock, NULL); if (ret != 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_THREAD_FAIL, - "pthread_mutex_init failed (%d)", ret); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_THREAD_FAIL, + "mutex_init ret=%d", ret, NULL); goto cleanup_cond; } ret = pthread_attr_init(&w_attr); if (ret != 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_THREAD_FAIL, - "pthread_attr_init failed (%d)", ret); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_THREAD_FAIL, + "attr_init ret=%d", ret, NULL); goto cleanup_lock; } ret = pthread_attr_setstacksize(&w_attr, BAD_OBJECT_THREAD_STACK_SIZE); if (ret == EINVAL) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_BAD_OBJ_THREAD_FAIL, - "Using default thread stack size"); + gf_smsg(this->name, GF_LOG_WARNING, 0, + BRS_MSG_USING_DEFAULT_THREAD_SIZE, NULL); } INIT_LIST_HEAD(&priv->container.bad_queue); @@ -122,8 +129,7 @@ init(xlator_t *this) br_stub_private_t *priv = NULL; if (!this->children) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_NO_CHILD, - "FATAL: no children"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_NO_CHILD, NULL); goto error_return; } @@ -161,16 +167,20 @@ init(xlator_t *this) * assigned inside the thread. So setting this->private here. */ this->private = priv; + if (!priv->do_versioning) + return 0; ret = gf_thread_create(&priv->signth, NULL, br_stub_signth, this, "brssign"); - if (ret != 0) + if (ret != 0) { + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SPAWN_SIGN_THRD_FAILED, + NULL); goto cleanup_lock; + } ret = br_stub_bad_object_container_init(this, priv); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_CONTAINER_FAIL, - "failed to launch the thread for storing bad gfids"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_CONTAINER_FAIL, NULL); goto cleanup_lock; } @@ -183,6 +193,7 @@ cleanup_lock: pthread_mutex_destroy(&priv->lock); free_mempool: mem_pool_destroy(priv->local_pool); + priv->local_pool = NULL; free_priv: GF_FREE(priv); this->private = NULL; @@ -211,10 +222,62 @@ reconfigure(xlator_t *this, dict_t *options) priv = this->private; - GF_OPTION_RECONF("bitrot", priv->do_versioning, options, bool, out); + GF_OPTION_RECONF("bitrot", priv->do_versioning, options, bool, err); + if (priv->do_versioning && !priv->signth) { + ret = gf_thread_create(&priv->signth, NULL, br_stub_signth, this, + "brssign"); + if (ret != 0) { + gf_smsg(this->name, GF_LOG_WARNING, 0, + BRS_MSG_SPAWN_SIGN_THRD_FAILED, NULL); + goto err; + } + + ret = br_stub_bad_object_container_init(this, priv); + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_CONTAINER_FAIL, + NULL); + goto err; + } + } else { + if (priv->signth) { + if (gf_thread_cleanup_xint(priv->signth)) { + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRS_MSG_CANCEL_SIGN_THREAD_FAILED, NULL); + } else { + gf_smsg(this->name, GF_LOG_INFO, 0, BRS_MSG_KILL_SIGN_THREAD, + NULL); + priv->signth = 0; + } + } + + if (priv->container.thread) { + if (gf_thread_cleanup_xint(priv->container.thread)) { + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRS_MSG_CANCEL_SIGN_THREAD_FAILED, NULL); + } + priv->container.thread = 0; + } + } ret = 0; -out: + return ret; +err: + if (priv->signth) { + if (gf_thread_cleanup_xint(priv->signth)) { + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRS_MSG_CANCEL_SIGN_THREAD_FAILED, NULL); + } + priv->signth = 0; + } + + if (priv->container.thread) { + if (gf_thread_cleanup_xint(priv->container.thread)) { + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRS_MSG_CANCEL_SIGN_THREAD_FAILED, NULL); + } + priv->container.thread = 0; + } + ret = -1; return ret; } @@ -245,10 +308,13 @@ fini(xlator_t *this) if (!priv) return; + if (!priv->do_versioning) + goto cleanup; + ret = gf_thread_cleanup_xint(priv->signth); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_CANCEL_SIGN_THREAD_FAILED, - "Could not cancel sign serializer thread"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_CANCEL_SIGN_THREAD_FAILED, + NULL); goto out; } priv->signth = 0; @@ -262,13 +328,10 @@ fini(xlator_t *this) GF_FREE(sigstub); } - pthread_mutex_destroy(&priv->lock); - pthread_cond_destroy(&priv->cond); - ret = gf_thread_cleanup_xint(priv->container.thread); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_CANCEL_SIGN_THREAD_FAILED, - "Could not cancel sign serializer thread"); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_CANCEL_SIGN_THREAD_FAILED, + NULL); goto out; } @@ -280,14 +343,18 @@ fini(xlator_t *this) call_stub_destroy(stub); } + pthread_mutex_destroy(&priv->container.bad_lock); + pthread_cond_destroy(&priv->container.bad_cond); + +cleanup: + pthread_mutex_destroy(&priv->lock); + pthread_cond_destroy(&priv->cond); + if (priv->local_pool) { mem_pool_destroy(priv->local_pool); priv->local_pool = NULL; } - pthread_mutex_destroy(&priv->container.bad_lock); - pthread_cond_destroy(&priv->container.bad_cond); - this->private = NULL; GF_FREE(priv); @@ -357,8 +424,8 @@ br_stub_prepare_version_request(xlator_t *this, dict_t *dict, priv = this->private; br_set_ongoingversion(obuf, oversion, priv->boot); - return dict_set_static_bin(dict, BITROT_CURRENT_VERSION_KEY, (void *)obuf, - sizeof(br_version_t)); + return dict_set_bin(dict, BITROT_CURRENT_VERSION_KEY, (void *)obuf, + sizeof(br_version_t)); } static int @@ -369,8 +436,7 @@ br_stub_prepare_signing_request(dict_t *dict, br_signature_t *sbuf, br_set_signature(sbuf, sign, signaturelen, &size); - return dict_set_static_bin(dict, BITROT_SIGNING_VERSION_KEY, (void *)sbuf, - size); + return dict_set_bin(dict, BITROT_SIGNING_VERSION_KEY, (void *)sbuf, size); } /** @@ -410,7 +476,7 @@ br_stub_init_inode_versions(xlator_t *this, fd_t *fd, inode_t *inode, goto free_ctx; if (ctx_addr) - *ctx_addr = (uint64_t)ctx; + *ctx_addr = (uint64_t)(uintptr_t)ctx; return 0; free_ctx: @@ -510,11 +576,9 @@ br_stub_need_versioning(xlator_t *this, fd_t *fd, gf_boolean_t *versioning, ret = br_stub_init_inode_versions(this, fd, fd->inode, version, _gf_true, _gf_false, &ctx_addr); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - BRS_MSG_GET_INODE_CONTEXT_FAILED, - "failed to " - " init the inode context for the inode %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRS_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(fd->inode->gfid), NULL); goto error_return; } } @@ -548,10 +612,8 @@ br_stub_anon_fd_ctx(xlator_t *this, fd_t *fd, br_stub_inode_ctx_t *ctx) if (!br_stub_fd) { ret = br_stub_add_fd_to_inode(this, fd, ctx); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ADD_FD_TO_INODE, - "failed to add fd to " - "the inode (gfid: %s)", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ADD_FD_TO_INODE, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto out; } } @@ -571,9 +633,8 @@ br_stub_versioning_prep(call_frame_t *frame, xlator_t *this, fd_t *fd, local = br_stub_alloc_local(this); if (!local) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, BRS_MSG_NO_MEMORY, - "local allocation failed (gfid: %s)", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, BRS_MSG_NO_MEMORY, "gfid=%s", + uuid_utoa(fd->inode->gfid), NULL); goto error_return; } @@ -643,8 +704,8 @@ br_stub_check_bad_object(xlator_t *this, inode_t *inode, int32_t *op_ret, ret = br_stub_is_bad_object(this, inode); if (ret == -2) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJECT_ACCESS, - "%s is a bad object. Returning", uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJECT_ACCESS, + "gfid=%s", uuid_utoa(inode->gfid), NULL); *op_ret = -1; *op_errno = EIO; } @@ -653,9 +714,9 @@ br_stub_check_bad_object(xlator_t *this, inode_t *inode, int32_t *op_ret, ret = br_stub_init_inode_versions(this, NULL, inode, version, _gf_true, _gf_false, NULL); if (ret) { - gf_msg( - this->name, GF_LOG_ERROR, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, - "failed to init inode context for %s", uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRS_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(inode->gfid), NULL); *op_ret = -1; *op_errno = EINVAL; } @@ -792,23 +853,27 @@ br_stub_perform_incversioning(xlator_t *this, call_frame_t *frame, op_errno = ENOMEM; dict = dict_new(); if (!dict) - goto done; + goto out; ret = br_stub_alloc_versions(&obuf, NULL, 0); - if (ret) - goto dealloc_dict; + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ALLOC_MEM_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); + goto out; + } ret = br_stub_prepare_version_request(this, dict, obuf, writeback_version); - if (ret) - goto dealloc_versions; + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_VERSION_PREPARE_FAIL, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); + br_stub_dealloc_versions(obuf); + goto out; + } ret = br_stub_fd_versioning( this, frame, stub, dict, fd, br_stub_fd_incversioning_cbk, writeback_version, BR_STUB_INCREMENTAL_VERSIONING, !WRITEBACK_DURABLE); - -dealloc_versions: - br_stub_dealloc_versions(obuf); -dealloc_dict: - dict_unref(dict); -done: +out: + if (dict) + dict_unref(dict); if (ret) { if (local) frame->local = NULL; @@ -846,6 +911,24 @@ br_stub_signth(void *arg) THIS = this; while (1) { + /* + * Disabling bit-rot feature leads to this particular thread + * getting cleaned up by reconfigure via a call to the function + * gf_thread_cleanup_xint (which in turn calls pthread_cancel + * and pthread_join). But, if this thread had held the mutex + * &priv->lock at the time of cancellation, then it leads to + * deadlock in future when bit-rot feature is enabled (which + * again spawns this thread which cant hold the lock as the + * mutex is still held by the previous instance of the thread + * which got killed). Also, the br_stub_handle_object_signature + * function which is called whenever file has to be signed + * also gets blocked as it too attempts to acquire &priv->lock. + * + * So, arrange for the lock to be unlocked as part of the + * cleanup of this thread using pthread_cleanup_push and + * pthread_cleanup_pop. + */ + pthread_cleanup_push(br_stub_lock_cleaner, &priv->lock); pthread_mutex_lock(&priv->lock); { while (list_empty(&priv->squeue)) @@ -856,6 +939,7 @@ br_stub_signth(void *arg) list_del_init(&sigstub->list); } pthread_mutex_unlock(&priv->lock); + pthread_cleanup_pop(0); call_resume(sigstub->stub); @@ -931,10 +1015,9 @@ br_stub_compare_sign_version(xlator_t *this, inode_t *inode, if (invalid) { ret = -1; - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SIGN_VERSION_ERROR, - "Signing version exceeds " - "current version [%lu > %lu]", - sbuf->signedversion, ctx->currentversion); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SIGN_VERSION_ERROR, + "Signing-ver=%lu", sbuf->signedversion, "current-ver=%lu", + ctx->currentversion, NULL); } out: @@ -945,31 +1028,36 @@ static int br_stub_prepare_signature(xlator_t *this, dict_t *dict, inode_t *inode, br_isignature_t *sign, int *fakesuccess) { - int32_t ret = 0; + int32_t ret = -1; size_t signaturelen = 0; br_signature_t *sbuf = NULL; if (!br_is_signature_type_valid(sign->signaturetype)) - goto error_return; + goto out; signaturelen = sign->signaturelen; ret = br_stub_alloc_versions(NULL, &sbuf, signaturelen); - if (ret) - goto error_return; + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ALLOC_MEM_FAILED, + "gfid=%s", uuid_utoa(inode->gfid), NULL); + ret = -1; + goto out; + } ret = br_stub_prepare_signing_request(dict, sbuf, sign, signaturelen); - if (ret) - goto dealloc_versions; + if (ret) { + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_SIGN_PREPARE_FAIL, + "gfid=%s", uuid_utoa(inode->gfid), NULL); + ret = -1; + br_stub_dealloc_versions(sbuf); + goto out; + } + /* At this point sbuf has been added to dict, so the memory will be freed + * when the data from the dict is destroyed + */ ret = br_stub_compare_sign_version(this, inode, sbuf, dict, fakesuccess); - if (ret) - goto dealloc_versions; - - return 0; - -dealloc_versions: - br_stub_dealloc_versions(sbuf); -error_return: - return -1; +out: + return ret; } static void @@ -986,12 +1074,18 @@ br_stub_handle_object_signature(call_frame_t *frame, xlator_t *this, fd_t *fd, priv = this->private; - if (frame->root->pid != GF_CLIENT_PID_BITD) + if (frame->root->pid != GF_CLIENT_PID_BITD) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, BRS_MSG_NON_BITD_PID, + "PID=%d", frame->root->pid, NULL); goto dofop; + } ret = br_stub_prepare_signature(this, dict, fd->inode, sign, &fakesuccess); - if (ret) + if (ret) { + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SIGN_PREPARE_FAIL, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto dofop; + } if (fakesuccess) { op_ret = op_errno = 0; goto dofop; @@ -1141,10 +1235,8 @@ br_stub_handle_object_reopen(call_frame_t *frame, xlator_t *this, fd_t *fd, stub = fop_fsetxattr_cbk_stub(frame, br_stub_fsetxattr_resume, 0, 0, NULL); if (!stub) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, - "failed to allocate stub for fsetxattr fop (gfid: %s)," - " unwinding", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, + "fsetxattr gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto cleanup_local; } @@ -1198,9 +1290,8 @@ br_stub_fsetxattr_bad_object_cbk(call_frame_t *frame, void *cookie, */ ret = br_stub_mark_object_bad(this, local->u.context.inode); if (ret) - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_MARK_FAIL, - "failed to mark object %s as bad", - uuid_utoa(local->u.context.inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_MARK_FAIL, + "gfid=%s", uuid_utoa(local->u.context.inode->gfid), NULL); ret = br_stub_add(this, local->u.context.inode->gfid); @@ -1220,18 +1311,15 @@ br_stub_handle_bad_object_key(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t op_errno = EINVAL; if (frame->root->pid != GF_CLIENT_PID_SCRUB) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_NON_SCRUB_BAD_OBJ_MARK, - "bad object marking " - "on %s is not from the scrubber", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_NON_SCRUB_BAD_OBJ_MARK, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto unwind; } local = br_stub_alloc_local(this); if (!local) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_NO_MEMORY, - "failed to allocate memory for fsetxattr on %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ALLOC_MEM_FAILED, + "fsetxattr gfid=%s", uuid_utoa(fd->inode->gfid), NULL); op_ret = -1; op_errno = ENOMEM; goto unwind; @@ -1270,10 +1358,9 @@ br_stub_handle_internal_xattr(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t op_ret = -1; int32_t op_errno = EINVAL; - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_SET_INTERNAL_XATTR, - "setxattr called" - " on the internal xattr %s for inode %s", - key, uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_SET_INTERNAL_XATTR, + "setxattr key=%s", key, "inode-gfid=%s", uuid_utoa(fd->inode->gfid), + NULL); STACK_UNWIND_STRICT(fsetxattr, frame, op_ret, op_errno, NULL); return 0; @@ -1291,10 +1378,8 @@ br_stub_dump_xattr(xlator_t *this, dict_t *dict, int *op_errno) goto out; } dict_dump_to_str(dict, dump, BR_STUB_DUMP_STR_SIZE, format); - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_SET_INTERNAL_XATTR, - "fsetxattr called on " - "internal xattr %s", - dump); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_SET_INTERNAL_XATTR, + "fsetxattr dump=%s", dump, NULL); out: if (dump) { GF_FREE(dump); @@ -1331,6 +1416,8 @@ br_stub_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, /* object signature request */ ret = dict_get_bin(dict, GLUSTERFS_SET_OBJECT_SIGNATURE, (void **)&sign); if (!ret) { + gf_msg_debug(this->name, 0, "got SIGNATURE request on %s", + uuid_utoa(fd->inode->gfid)); br_stub_handle_object_signature(frame, this, fd, dict, sign, xdata); goto done; } @@ -1423,10 +1510,8 @@ br_stub_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, if (!strcmp(BITROT_OBJECT_BAD_KEY, name) || !strcmp(BITROT_SIGNING_VERSION_KEY, name) || !strcmp(BITROT_CURRENT_VERSION_KEY, name)) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_REMOVE_INTERNAL_XATTR, - "removexattr called" - " on internal xattr %s for file %s", - name, loc->path); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_REMOVE_INTERNAL_XATTR, + "name=%s", name, "file-path=%s", loc->path, NULL); goto unwind; } @@ -1448,10 +1533,9 @@ br_stub_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, if (!strcmp(BITROT_OBJECT_BAD_KEY, name) || !strcmp(BITROT_SIGNING_VERSION_KEY, name) || !strcmp(BITROT_CURRENT_VERSION_KEY, name)) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_REMOVE_INTERNAL_XATTR, - "removexattr called" - " on internal xattr %s for inode %s", - name, uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_REMOVE_INTERNAL_XATTR, + "name=%s", name, "inode-gfid=%s", uuid_utoa(fd->inode->gfid), + NULL); goto unwind; } @@ -1476,7 +1560,7 @@ br_stub_listxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret < 0) goto unwind; - br_stub_remove_vxattrs(xattr); + br_stub_remove_vxattrs(xattr, _gf_true); unwind: STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, xattr, xdata); @@ -1537,10 +1621,8 @@ br_stub_is_object_stale(xlator_t *this, call_frame_t *frame, inode_t *inode, ret = br_stub_get_inode_ctx(this, inode, &ctx_addr); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, - "failed to get the " - "inode context for %s", - uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(inode->gfid), NULL); goto out; } @@ -1588,6 +1670,11 @@ br_stub_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, local = frame->local; frame->local = NULL; + if (!local) { + op_ret = -1; + op_errno = EINVAL; + goto unwind; + } inode = local->u.context.inode; op_ret = -1; @@ -1650,14 +1737,12 @@ br_stub_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, op_ret = totallen; delkeys: - br_stub_remove_vxattrs(xattr); + br_stub_remove_vxattrs(xattr, _gf_true); unwind: STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, xattr, xdata); - if (local) { - br_stub_cleanup_local(local); - br_stub_dealloc_local(local); - } + br_stub_cleanup_local(local); + br_stub_dealloc_local(local); return 0; } @@ -1708,9 +1793,7 @@ br_stub_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { void *cookie = NULL; - uuid_t rootgfid = { - 0, - }; + static uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; fop_getxattr_cbk_t cbk = br_stub_getxattr_cbk; int32_t op_ret = -1; int32_t op_errno = EINVAL; @@ -1722,8 +1805,6 @@ br_stub_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, GF_VALIDATE_OR_GOTO(this->name, this->private, unwind); GF_VALIDATE_OR_GOTO(this->name, loc->inode, unwind); - rootgfid[15] = 1; - if (!name) { cbk = br_stub_listxattr_cbk; goto wind; @@ -1793,16 +1874,13 @@ br_stub_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata) { void *cookie = NULL; - uuid_t rootgfid = { - 0, - }; + static uuid_t rootgfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; fop_fgetxattr_cbk_t cbk = br_stub_getxattr_cbk; int32_t op_ret = -1; int32_t op_errno = EINVAL; br_stub_local_t *local = NULL; br_stub_private_t *priv = NULL; - rootgfid[15] = 1; priv = this->private; if (!name) { @@ -2022,10 +2100,8 @@ br_stub_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, offset, flags, iobref, xdata); if (!stub) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, - "failed to allocate stub for write fop (gfid: %s), " - "unwinding", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, + "write gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto cleanup_local; } @@ -2138,10 +2214,8 @@ br_stub_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, stub = fop_ftruncate_stub(frame, br_stub_ftruncate_resume, fd, offset, xdata); if (!stub) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, - "failed to allocate stub for ftruncate fop (gfid: %s)," - " unwinding", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, + "ftruncate gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto cleanup_local; } @@ -2245,10 +2319,8 @@ br_stub_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, fd = fd_anonymous(loc->inode); if (!fd) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_CREATE_ANONYMOUS_FD_FAILED, - "failed to create " - "anonymous fd for the inode %s", - uuid_utoa(loc->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_CREATE_ANONYMOUS_FD_FAILED, + "inode-gfid=%s", uuid_utoa(loc->inode->gfid), NULL); goto unwind; } @@ -2278,10 +2350,8 @@ br_stub_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, stub = fop_truncate_stub(frame, br_stub_truncate_resume, loc, offset, xdata); if (!stub) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, - "failed to allocate stub for truncate fop (gfid: %s), " - "unwinding", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_STUB_ALLOC_FAILED, + "truncate gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto cleanup_local; } @@ -2354,11 +2424,9 @@ br_stub_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, ret = br_stub_init_inode_versions(this, fd, fd->inode, version, _gf_true, _gf_false, &ctx_addr); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - BRS_MSG_GET_INODE_CONTEXT_FAILED, - "failed to init the inode context for " - "the file %s (gfid: %s)", - loc->path, uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, + BRS_MSG_GET_INODE_CONTEXT_FAILED, "path=%s", loc->path, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto unwind; } } @@ -2377,9 +2445,8 @@ br_stub_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, ret = br_stub_add_fd_to_inode(this, fd, ctx); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ADD_FD_TO_LIST_FAILED, - "failed add fd to the list (gfid: %s)", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_ADD_FD_TO_LIST_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto unwind; } @@ -2410,10 +2477,8 @@ br_stub_add_fd_to_inode(xlator_t *this, fd_t *fd, br_stub_inode_ctx_t *ctx) ret = br_stub_require_release_call(this, fd, &br_stub_fd); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_SET_FD_CONTEXT_FAILED, - "failed to set the fd " - "context for the file (gfid: %s)", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_SET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto out; } @@ -2700,17 +2765,37 @@ br_stub_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (!IA_ISREG(entry->d_stat.ia_type)) continue; + /* + * Readdirp for most part is a bulk lookup for all the entries + * present in the directory being read. Ideally, for each + * entry, the handling should be similar to that of a lookup + * callback. But for now, just keeping this as it has been + * until now (which means, this comment has been added much + * later as part of a change that wanted to send the flag + * of true/false to br_stub_remove_vxattrs to indicate whether + * the bad-object xattr should be removed from the entry->dict + * or not). Until this change, the function br_stub_remove_vxattrs + * was just removing all the xattrs associated with bit-rot-stub + * (like version, bad-object, signature etc). But, there are + * scenarios where we only want to send bad-object xattr and not + * others. So this comment is part of that change which also + * mentions about another possible change that might be needed + * in future. + * But for now, adding _gf_true means functionally its same as + * what this function was doing before. Just remove all the stub + * related xattrs. + */ ret = br_stub_get_inode_ctx(this, entry->inode, &ctxaddr); if (ret < 0) ctxaddr = 0; if (ctxaddr) { /* already has the context */ - br_stub_remove_vxattrs(entry->dict); + br_stub_remove_vxattrs(entry->dict, _gf_true); continue; } ret = br_stub_lookup_version(this, entry->inode->gfid, entry->inode, entry->dict); - br_stub_remove_vxattrs(entry->dict); + br_stub_remove_vxattrs(entry->dict, _gf_true); if (ret) { /** * there's no per-file granularity support in case of @@ -2846,13 +2931,22 @@ br_stub_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t ret = 0; br_stub_private_t *priv = NULL; gf_boolean_t ver_enabled = _gf_false; + gf_boolean_t remove_bad_file_marker = _gf_true; BR_STUB_VER_ENABLED_IN_CALLPATH(frame, ver_enabled); priv = this->private; if (op_ret < 0) { (void)br_stub_handle_lookup_error(this, inode, op_errno); - goto unwind; + + /* + * If the lookup error is not ENOENT, then it is better + * to send the bad file marker to the higher layer (if + * it has been set) + */ + if (op_errno != ENOENT) + remove_bad_file_marker = _gf_false; + goto delkey; } BR_STUB_VER_COND_GOTO(priv, (!ver_enabled), delkey); @@ -2873,7 +2967,13 @@ br_stub_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (ret) { op_ret = -1; op_errno = EIO; - goto unwind; + /* + * This flag ensures that in the label @delkey below, + * bad file marker is not removed from the dictinary, + * but other virtual xattrs (such as version, signature) + * are removed. + */ + remove_bad_file_marker = _gf_false; } goto delkey; } @@ -2897,11 +2997,11 @@ br_stub_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, */ op_ret = -1; op_errno = EIO; - goto unwind; + goto delkey; } delkey: - br_stub_remove_vxattrs(xattr); + br_stub_remove_vxattrs(xattr, remove_bad_file_marker); unwind: STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, stbuf, xattr, postparent); @@ -3086,6 +3186,10 @@ br_stub_unlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret < 0) goto unwind; + if (!local) { + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_NULL_LOCAL, NULL); + goto unwind; + } inode = local->u.context.inode; if (!IA_ISREG(inode->ia_type)) goto unwind; @@ -3101,9 +3205,8 @@ br_stub_unlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, * has to be removed manually. Its not a good idea to fail * the fop, as the object has already been deleted. */ - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, - "failed to get the context for the inode %s", - uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, + "inode-gfid=%s", uuid_utoa(inode->gfid), NULL); goto unwind; } @@ -3146,9 +3249,9 @@ br_stub_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int flag, if (!local) { op_ret = -1; op_errno = ENOMEM; - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, BRS_MSG_NO_MEMORY, - "failed to allocate memory for local (path: %s, gfid: %s)", - loc->path, uuid_utoa(loc->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, BRS_MSG_ALLOC_MEM_FAILED, + "local path=%s", loc->path, "gfid=%s", + uuid_utoa(loc->inode->gfid), NULL); goto unwind; } @@ -3223,23 +3326,21 @@ br_stub_send_ipc_fop(xlator_t *this, fd_t *fd, unsigned long releaseversion, xdata = dict_new(); if (!xdata) { - gf_msg(this->name, GF_LOG_WARNING, ENOMEM, BRS_MSG_NO_MEMORY, - "dict allocation failed: cannot send IPC FOP " - "to changelog"); + gf_smsg(this->name, GF_LOG_WARNING, ENOMEM, BRS_MSG_DICT_ALLOC_FAILED, + NULL); goto out; } ret = dict_set_static_bin(xdata, "RELEASE-EVENT", &ev, CHANGELOG_EV_SIZE); if (ret) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SET_EVENT_FAILED, - "cannot set release event in dict"); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SET_EVENT_FAILED, NULL); goto dealloc_dict; } frame = create_frame(this, this->ctx->pool); if (!frame) { - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_CREATE_FRAME_FAILED, - "create_frame() failure"); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_CREATE_FRAME_FAILED, + NULL); goto dealloc_dict; } @@ -3374,8 +3475,8 @@ br_stub_releasedir(xlator_t *this, fd_t *fd) if (fctx->bad_object.dir) { ret = sys_closedir(fctx->bad_object.dir); if (ret) - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_DIR_CLOSE_FAIL, - "closedir error: %s", strerror(errno)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_BAD_OBJ_DIR_CLOSE_FAIL, + "error=%s", strerror(errno), NULL); } GF_FREE(fctx); @@ -3403,14 +3504,14 @@ br_stub_ictxmerge(xlator_t *this, fd_t *fd, inode_t *inode, ret = br_stub_get_inode_ctx(this, inode, &ctxaddr); if (ret < 0) goto done; - ctx = (br_stub_inode_ctx_t *)ctxaddr; + ctx = (br_stub_inode_ctx_t *)(uintptr_t)ctxaddr; LOCK(&linked_inode->lock); { ret = __br_stub_get_inode_ctx(this, linked_inode, &lctxaddr); if (ret < 0) goto unblock; - lctx = (br_stub_inode_ctx_t *)lctxaddr; + lctx = (br_stub_inode_ctx_t *)(uintptr_t)lctxaddr; GF_ASSERT(list_is_singular(&ctx->fd_list)); br_stub_fd = list_first_entry(&ctx->fd_list, br_stub_fd_t, list); @@ -3473,3 +3574,17 @@ struct volume_options options[] = { .default_value = "{{ brick.path }}"}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "bitrot-stub", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/bit-rot/src/stub/bit-rot-stub.h b/xlators/features/bit-rot/src/stub/bit-rot-stub.h index a15667e323a..edd79a77e4f 100644 --- a/xlators/features/bit-rot/src/stub/bit-rot-stub.h +++ b/xlators/features/bit-rot/src/stub/bit-rot-stub.h @@ -10,20 +10,20 @@ #ifndef __BIT_ROT_STUB_H__ #define __BIT_ROT_STUB_H__ -#include "glusterfs.h" -#include "logging.h" -#include "dict.h" -#include "xlator.h" -#include "defaults.h" -#include "call-stub.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/call-stub.h> #include "bit-rot-stub-mem-types.h" -#include "syscall.h" -#include "common-utils.h" +#include <glusterfs/syscall.h> +#include <glusterfs/common-utils.h> #include "bit-rot-common.h" #include "bit-rot-stub-messages.h" #include "glusterfs3-xdr.h" -#include "syncop.h" -#include "syncop-utils.h" +#include <glusterfs/syncop.h> +#include <glusterfs/syncop-utils.h> #define BAD_OBJECT_THREAD_STACK_SIZE ((size_t)(1024 * 1024)) #define BR_STUB_DUMP_STR_SIZE 65536 @@ -222,8 +222,8 @@ br_stub_require_release_call(xlator_t *this, fd_t *fd, br_stub_fd_t **fd_ctx) ret = br_stub_fd_ctx_set(this, fd, br_stub_fd); if (ret) - gf_msg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SET_CONTEXT_FAILED, - "could not set fd context (for release callback"); + gf_smsg(this->name, GF_LOG_WARNING, 0, BRS_MSG_SET_CONTEXT_FAILED, + NULL); else *fd_ctx = br_stub_fd; @@ -255,7 +255,7 @@ br_stub_get_inode_ctx(xlator_t *this, inode_t *inode, uint64_t *ctx) static inline int br_stub_set_inode_ctx(xlator_t *this, inode_t *inode, br_stub_inode_ctx_t *ctx) { - uint64_t ctx_addr = (uint64_t)ctx; + uint64_t ctx_addr = (uint64_t)(uintptr_t)ctx; return inode_ctx_set(inode, this, &ctx_addr); } @@ -273,10 +273,9 @@ __br_stub_set_ongoing_version(br_stub_inode_ctx_t *ctx, unsigned long version) if (ctx->currentversion < version) ctx->currentversion = version; else - gf_msg("bit-rot-stub", GF_LOG_WARNING, 0, BRS_MSG_CHANGE_VERSION_FAILED, - "current version: %lu" - "new version: %lu", - ctx->currentversion, version); + gf_smsg("bit-rot-stub", GF_LOG_WARNING, 0, + BRS_MSG_CHANGE_VERSION_FAILED, "current version=%lu", + ctx->currentversion, "new version=%lu", version, NULL); } static inline int @@ -359,10 +358,18 @@ br_stub_is_internal_xattr(const char *name) } static inline void -br_stub_remove_vxattrs(dict_t *xattr) +br_stub_remove_vxattrs(dict_t *xattr, gf_boolean_t remove_bad_marker) { if (xattr) { - dict_del(xattr, BITROT_OBJECT_BAD_KEY); + /* + * When a file is corrupted, bad-object should be + * set in the dict. But, other info such as version, + * signature etc should not be set. Hence the flag + * remove_bad_marker. The consumer should know whether + * to send the bad-object info in the dict or not. + */ + if (remove_bad_marker) + dict_del(xattr, BITROT_OBJECT_BAD_KEY); dict_del(xattr, BITROT_CURRENT_VERSION_KEY); dict_del(xattr, BITROT_SIGNING_VERSION_KEY); dict_del(xattr, BITROT_SIGNING_XATTR_SIZE_KEY); @@ -390,9 +397,8 @@ br_stub_is_bad_object(xlator_t *this, inode_t *inode) ret = br_stub_get_inode_ctx(this, inode, &ctx_addr); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, - "failed to get the inode context for the inode %s", - uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, + "inode-gfid=%s", uuid_utoa(inode->gfid), NULL); bad_object = -1; goto out; } @@ -420,10 +426,8 @@ br_stub_mark_object_bad(xlator_t *this, inode_t *inode) ret = br_stub_get_inode_ctx(this, inode, &ctx_addr); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, - "failed to get the " - "inode context for the inode %s", - uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, BRS_MSG_GET_INODE_CONTEXT_FAILED, + "inode-gfid=%s", uuid_utoa(inode->gfid), NULL); goto out; } diff --git a/xlators/features/changelog/lib/examples/python/changes.py b/xlators/features/changelog/lib/examples/python/changes.py index c410d3b000d..c410d3b000d 100644..100755 --- a/xlators/features/changelog/lib/examples/python/changes.py +++ b/xlators/features/changelog/lib/examples/python/changes.py diff --git a/xlators/features/changelog/lib/examples/python/libgfchangelog.py b/xlators/features/changelog/lib/examples/python/libgfchangelog.py index 2cdbf1152b9..2da9f2d2a8c 100644 --- a/xlators/features/changelog/lib/examples/python/libgfchangelog.py +++ b/xlators/features/changelog/lib/examples/python/libgfchangelog.py @@ -1,8 +1,10 @@ import os from ctypes import * +from ctypes.util import find_library class Changes(object): - libgfc = CDLL("libgfchangelog.so", mode=RTLD_GLOBAL, use_errno=True) + libgfc = CDLL(find_library("gfchangelog"), mode=RTLD_GLOBAL, + use_errno=True) @classmethod def geterrno(cls): diff --git a/xlators/features/changelog/lib/src/Makefile.am b/xlators/features/changelog/lib/src/Makefile.am index c4b9a3df692..c933ec53ed2 100644 --- a/xlators/features/changelog/lib/src/Makefile.am +++ b/xlators/features/changelog/lib/src/Makefile.am @@ -1,7 +1,7 @@ libgfchangelog_la_CFLAGS = -Wall $(GF_CFLAGS) $(GF_DARWIN_LIBGLUSTERFS_CFLAGS) \ -DDATADIR=\"$(localstatedir)\" -libgfchangelog_la_CPPFLAGS = $(GF_CPPFLAGS) -D__USE_FILE_OFFSET64 -fpic \ +libgfchangelog_la_CPPFLAGS = $(GF_CPPFLAGS) -D__USE_FILE_OFFSET64 -D__USE_LARGEFILE64 -fpic \ -I../../../src/ -I$(top_srcdir)/libglusterfs/src \ -I$(top_srcdir)/xlators/features/changelog/src \ -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src \ diff --git a/xlators/features/changelog/lib/src/changelog-lib-messages.h b/xlators/features/changelog/lib/src/changelog-lib-messages.h index 32b3497d89d..d7fe7274353 100644 --- a/xlators/features/changelog/lib/src/changelog-lib-messages.h +++ b/xlators/features/changelog/lib/src/changelog-lib-messages.h @@ -11,7 +11,7 @@ #ifndef _CHANGELOG_LIB_MESSAGES_H_ #define _CHANGELOG_LIB_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * @@ -34,7 +34,7 @@ GLFS_MSGID( CHANGELOG_LIB_MSG_MMAP_FAILED, CHANGELOG_LIB_MSG_MUNMAP_FAILED, CHANGELOG_LIB_MSG_ASCII_ERROR, CHANGELOG_LIB_MSG_STAT_FAILED, CHANGELOG_LIB_MSG_GET_XATTR_FAILED, CHANGELOG_LIB_MSG_PUBLISH_ERROR, - CHANGELOG_LIB_MSG_PARSE_ERROR, CHANGELOG_LIB_MSG_TOTAL_LOG_INFO, + CHANGELOG_LIB_MSG_PARSE_ERROR, CHANGELOG_LIB_MSG_MIN_MAX_INFO, CHANGELOG_LIB_MSG_CLEANUP_ERROR, CHANGELOG_LIB_MSG_UNLINK_FAILED, CHANGELOG_LIB_MSG_NOTIFY_REGISTER_FAILED, CHANGELOG_LIB_MSG_INVOKE_RPC_FAILED, CHANGELOG_LIB_MSG_DRAINING_EVENT_INFO, @@ -43,6 +43,32 @@ GLFS_MSGID( CHANGELOG_LIB_MSG_NOTIFY_REGISTER_INFO, CHANGELOG_LIB_MSG_THREAD_CLEANUP_WARNING, CHANGELOG_LIB_MSG_COPY_FROM_BUFFER_FAILED, - CHANGELOG_LIB_MSG_PTHREAD_JOIN_FAILED, CHANGELOG_LIB_MSG_HIST_FAILED); + CHANGELOG_LIB_MSG_PTHREAD_JOIN_FAILED, CHANGELOG_LIB_MSG_HIST_FAILED, + CHANGELOG_LIB_MSG_DRAINED_EVENT_INFO, CHANGELOG_LIB_MSG_PARSE_ERROR_CEASED, + CHANGELOG_LIB_MSG_REQUESTING_INFO, CHANGELOG_LIB_MSG_FINAL_INFO); + +#define CHANGELOG_LIB_MSG_NOTIFY_REGISTER_INFO_STR "Registering brick" +#define CHANGELOG_LIB_MSG_RENAME_FAILED_STR "error moving changelog file" +#define CHANGELOG_LIB_MSG_OPEN_FAILED_STR "cannot open changelog file" +#define CHANGELOG_LIB_MSG_UNLINK_FAILED_STR "failed to unlink" +#define CHANGELOG_LIB_MSG_FAILED_TO_RMDIR_STR "failed to rmdir" +#define CHANGELOG_LIB_MSG_STAT_FAILED_STR "stat failed on changelog file" +#define CHANGELOG_LIB_MSG_PARSE_ERROR_STR "could not parse changelog" +#define CHANGELOG_LIB_MSG_PARSE_ERROR_CEASED_STR \ + "parsing error, ceased publishing..." +#define CHANGELOG_LIB_MSG_HTIME_ERROR_STR "fop failed on htime file" +#define CHANGELOG_LIB_MSG_GET_XATTR_FAILED_STR \ + "error extracting max timstamp from htime file" +#define CHANGELOG_LIB_MSG_MIN_MAX_INFO_STR "changelogs min max" +#define CHANGELOG_LIB_MSG_REQUESTING_INFO_STR "Requesting historical changelogs" +#define CHANGELOG_LIB_MSG_FINAL_INFO_STR "FINAL" +#define CHANGELOG_LIB_MSG_HIST_FAILED_STR \ + "Requested changelog range is not available" +#define CHANGELOG_LIB_MSG_GET_TIME_ERROR_STR "wrong result" +#define CHANGELOG_LIB_MSG_CLEANING_BRICK_ENTRY_INFO_STR \ + "Cleaning brick entry for brick" +#define CHANGELOG_LIB_MSG_DRAINING_EVENT_INFO_STR "Draining event" +#define CHANGELOG_LIB_MSG_DRAINED_EVENT_INFO_STR "Drained event" +#define CHANGELOG_LIB_MSG_FREEING_ENTRY_INFO_STR "freeing entry" #endif /* !_CHANGELOG_MESSAGES_H_ */ diff --git a/xlators/features/changelog/lib/src/gf-changelog-api.c b/xlators/features/changelog/lib/src/gf-changelog-api.c index 1b6e932596d..81a5cbfec10 100644 --- a/xlators/features/changelog/lib/src/gf-changelog-api.c +++ b/xlators/features/changelog/lib/src/gf-changelog-api.c @@ -8,10 +8,10 @@ cases as published by the Free Software Foundation. */ -#include "compat-uuid.h" -#include "globals.h" -#include "glusterfs.h" -#include "syscall.h" +#include <glusterfs/compat-uuid.h> +#include <glusterfs/globals.h> +#include <glusterfs/glusterfs.h> +#include <glusterfs/syscall.h> #include "gf-changelog-helpers.h" #include "gf-changelog-journal.h" @@ -56,8 +56,8 @@ gf_changelog_done(char *file) ret = sys_rename(buffer, to_path); if (ret) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_RENAME_FAILED, "cannot move changelog file", - "from=%s", file, "to=%s", to_path, NULL); + CHANGELOG_LIB_MSG_RENAME_FAILED, "from=%s", file, "to=%s", + to_path, NULL); goto out; } diff --git a/xlators/features/changelog/lib/src/gf-changelog-helpers.c b/xlators/features/changelog/lib/src/gf-changelog-helpers.c index fd15ec68ab8..75f8a6dfc08 100644 --- a/xlators/features/changelog/lib/src/gf-changelog-helpers.c +++ b/xlators/features/changelog/lib/src/gf-changelog-helpers.c @@ -11,13 +11,7 @@ #include "changelog-mem-types.h" #include "gf-changelog-helpers.h" #include "changelog-lib-messages.h" -#include "syscall.h" - -ssize_t -gf_changelog_read_path(int fd, char *buffer, size_t bufsize) -{ - return sys_read(fd, buffer, bufsize); -} +#include <glusterfs/syscall.h> size_t gf_changelog_write(int fd, char *buffer, size_t len) @@ -64,20 +58,7 @@ gf_rfc3986_encode_space_newline(unsigned char *s, char *enc, char *estr) * made a part of libglusterfs. */ -static pthread_key_t rl_key; -static pthread_once_t rl_once = PTHREAD_ONCE_INIT; - -static void -readline_destructor(void *ptr) -{ - GF_FREE(ptr); -} - -static void -readline_once(void) -{ - pthread_key_create(&rl_key, readline_destructor); -} +static __thread read_line_t thread_tsd = {}; static ssize_t my_read(read_line_t *tsd, int fd, char *ptr) @@ -97,27 +78,6 @@ my_read(read_line_t *tsd, int fd, char *ptr) return 1; } -static int -gf_readline_init_once(read_line_t **tsd) -{ - if (pthread_once(&rl_once, readline_once) != 0) - return -1; - - *tsd = pthread_getspecific(rl_key); - if (*tsd) - goto out; - - *tsd = GF_CALLOC(1, sizeof(**tsd), gf_changelog_mt_libgfchangelog_rl_t); - if (!*tsd) - return -1; - - if (pthread_setspecific(rl_key, *tsd) != 0) - return -1; - -out: - return 0; -} - ssize_t gf_readline(int fd, void *vptr, size_t maxlen) { @@ -125,10 +85,7 @@ gf_readline(int fd, void *vptr, size_t maxlen) size_t rc = 0; char c = ' '; char *ptr = NULL; - read_line_t *tsd = NULL; - - if (gf_readline_init_once(&tsd)) - return -1; + read_line_t *tsd = &thread_tsd; ptr = vptr; for (n = 1; n < maxlen; n++) { @@ -151,10 +108,7 @@ off_t gf_lseek(int fd, off_t offset, int whence) { off_t off = 0; - read_line_t *tsd = NULL; - - if (gf_readline_init_once(&tsd)) - return -1; + read_line_t *tsd = &thread_tsd; off = sys_lseek(fd, offset, whence); if (off == -1) @@ -169,10 +123,7 @@ gf_lseek(int fd, off_t offset, int whence) int gf_ftruncate(int fd, off_t length) { - read_line_t *tsd = NULL; - - if (gf_readline_init_once(&tsd)) - return -1; + read_line_t *tsd = &thread_tsd; if (sys_ftruncate(fd, 0)) return -1; diff --git a/xlators/features/changelog/lib/src/gf-changelog-helpers.h b/xlators/features/changelog/lib/src/gf-changelog-helpers.h index cfb26a0081e..9c609d33172 100644 --- a/xlators/features/changelog/lib/src/gf-changelog-helpers.h +++ b/xlators/features/changelog/lib/src/gf-changelog-helpers.h @@ -14,9 +14,9 @@ #include <unistd.h> #include <dirent.h> #include <limits.h> -#include "locking.h" +#include <glusterfs/locking.h> -#include <xlator.h> +#include <glusterfs/xlator.h> #include "changelog.h" @@ -205,9 +205,6 @@ typedef struct gf_private { void * gf_changelog_process(void *data); -ssize_t -gf_changelog_read_path(int fd, char *buffer, size_t bufsize); - void gf_rfc3986_encode_space_newline(unsigned char *s, char *enc, char *estr); diff --git a/xlators/features/changelog/lib/src/gf-changelog-journal-handler.c b/xlators/features/changelog/lib/src/gf-changelog-journal-handler.c index ef46bf50c97..7f6e2329e71 100644 --- a/xlators/features/changelog/lib/src/gf-changelog-journal-handler.c +++ b/xlators/features/changelog/lib/src/gf-changelog-journal-handler.c @@ -8,11 +8,11 @@ cases as published by the Free Software Foundation. */ -#include "compat-uuid.h" -#include "globals.h" -#include "glusterfs.h" -#include "syscall.h" -#include "compat-errno.h" +#include <glusterfs/compat-uuid.h> +#include <glusterfs/globals.h> +#include <glusterfs/glusterfs.h> +#include <glusterfs/syscall.h> +#include <glusterfs/compat-errno.h> #include "gf-changelog-helpers.h" @@ -526,9 +526,8 @@ gf_changelog_publish(xlator_t *this, gf_changelog_journal_t *jnl, ret = sys_rename(to_path, dest); if (ret) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_RENAME_FAILED, - "error moving changelog to processing dir", "path=%s", to_path, - NULL); + CHANGELOG_LIB_MSG_RENAME_FAILED, "from=%s", to_path, "to=%s", + dest, NULL); } out: @@ -564,14 +563,14 @@ gf_changelog_consume(xlator_t *this, gf_changelog_journal_t *jnl, if (ret || !S_ISREG(stbuf.st_mode)) { ret = -1; gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_LIB_MSG_STAT_FAILED, - "stat failed on changelog file", "path=%s", from_path, NULL); + "path=%s", from_path, NULL); goto out; } fd1 = open(from_path, O_RDONLY); if (fd1 < 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_LIB_MSG_OPEN_FAILED, - "cannot open changelog file", "path=%s", from_path, NULL); + "path=%s", from_path, NULL); goto out; } @@ -579,7 +578,7 @@ gf_changelog_consume(xlator_t *this, gf_changelog_journal_t *jnl, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd2 < 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_LIB_MSG_OPEN_FAILED, - "cannot create ascii changelog file", "path=%s", to_path, NULL); + "path=%s", to_path, NULL); goto close_fd; } else { ret = gf_changelog_decode(this, jnl, fd1, fd2, &stbuf, &zerob); @@ -594,9 +593,8 @@ gf_changelog_consume(xlator_t *this, gf_changelog_journal_t *jnl, ret = sys_rename(to_path, dest); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_RENAME_FAILED, - "error moving changelog to processing dir", "path=%s", - to_path, NULL); + CHANGELOG_LIB_MSG_RENAME_FAILED, "from=%s", to_path, + "to=%s", dest, NULL); } /* remove it from .current if it's an empty file */ @@ -605,9 +603,8 @@ gf_changelog_consume(xlator_t *this, gf_changelog_journal_t *jnl, ret = sys_unlink(to_path); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_UNLINK_FAILED, - "could not unlink empty changelog", "path=%s", to_path, - NULL); + CHANGELOG_LIB_MSG_UNLINK_FAILED, "name=empty changelog", + "path=%s", to_path, NULL); } } @@ -828,7 +825,7 @@ gf_changelog_open_dirs(xlator_t *this, gf_changelog_journal_t *jnl) ret = recursive_rmdir(jnl->jnl_current_dir); if (ret) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_FAILED_TO_RMDIR, "Failed to rmdir", "path=%s", + CHANGELOG_LIB_MSG_FAILED_TO_RMDIR, "path=%s", jnl->jnl_current_dir, NULL); goto out; } @@ -849,7 +846,7 @@ gf_changelog_open_dirs(xlator_t *this, gf_changelog_journal_t *jnl) ret = recursive_rmdir(jnl->jnl_processing_dir); if (ret) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_FAILED_TO_RMDIR, "Failed to rmdir", "path=%s", + CHANGELOG_LIB_MSG_FAILED_TO_RMDIR, "path=%s", jnl->jnl_processing_dir, NULL); goto out; } diff --git a/xlators/features/changelog/lib/src/gf-changelog-reborp.c b/xlators/features/changelog/lib/src/gf-changelog-reborp.c index 8dfda4c79c5..56b11cbb705 100644 --- a/xlators/features/changelog/lib/src/gf-changelog-reborp.c +++ b/xlators/features/changelog/lib/src/gf-changelog-reborp.c @@ -15,14 +15,14 @@ #include "changelog-rpc-common.h" #include "changelog-lib-messages.h" -#include "syscall.h" +#include <glusterfs/syscall.h> /** * Reverse socket: actual data transfer handler. Connection * initiator is PROBER, data transfer is REBORP. */ -struct rpcsvc_program *gf_changelog_reborp_programs[]; +static struct rpcsvc_program *gf_changelog_reborp_programs[]; void * gf_changelog_connection_janitor(void *arg) @@ -55,9 +55,8 @@ gf_changelog_connection_janitor(void *arg) ev = &entry->event; gf_smsg(this->name, GF_LOG_INFO, 0, - CHANGELOG_LIB_MSG_CLEANING_BRICK_ENTRY_INFO, - "Cleaning brick entry for brick", "brick=%s", entry->brick, - NULL); + CHANGELOG_LIB_MSG_CLEANING_BRICK_ENTRY_INFO, "brick=%s", + entry->brick, NULL); /* 0x0: disable rpc-clnt */ rpc_clnt_disable(RPC_PROBER(entry)); @@ -71,21 +70,19 @@ gf_changelog_connection_janitor(void *arg) while (!list_empty(&ev->events)) { event = list_first_entry(&ev->events, struct gf_event, list); gf_smsg(this->name, GF_LOG_INFO, 0, - CHANGELOG_LIB_MSG_DRAINING_EVENT_INFO, "Draining event", - "seq=%lu", event->seq, "payload=%d", event->count, NULL); + CHANGELOG_LIB_MSG_DRAINING_EVENT_INFO, "seq=%lu", + event->seq, "payload=%d", event->count, NULL); GF_FREE(event); drained++; } gf_smsg(this->name, GF_LOG_INFO, 0, - CHANGELOG_LIB_MSG_DRAINING_EVENT_INFO, "Drained events", - "num=%lu", drained, NULL); + CHANGELOG_LIB_MSG_DRAINED_EVENT_INFO, "num=%lu", drained, NULL); /* 0x3: freeup brick entry */ gf_smsg(this->name, GF_LOG_INFO, 0, - CHANGELOG_LIB_MSG_FREEING_ENTRY_INFO, "freeing entry", - "entry=%p", entry, NULL); + CHANGELOG_LIB_MSG_FREEING_ENTRY_INFO, "entry=%p", entry, NULL); LOCK_DESTROY(&entry->statelock); GF_FREE(entry); } @@ -112,9 +109,7 @@ gf_changelog_reborp_rpcsvc_notify(rpcsvc_t *rpc, void *mydata, ret = sys_unlink(RPC_SOCK(entry)); if (ret != 0) gf_smsg(this->name, GF_LOG_WARNING, errno, - CHANGELOG_LIB_MSG_UNLINK_FAILED, - "failed to unlink " - "reverse socket", + CHANGELOG_LIB_MSG_UNLINK_FAILED, "name=reverse socket", "path=%s", RPC_SOCK(entry), NULL); if (entry->connected) GF_CHANGELOG_INVOKE_CBK(this, entry->connected, entry->brick, @@ -353,7 +348,9 @@ gf_changelog_event_handler(rpcsvc_request_t *req, xlator_t *this, } gf_msg_debug(this->name, 0, - "seq: %lu [%s] (time: %lu.%lu), (vec: %d, len: %zd)", + "seq: %" PRIu64 " [%s] (time: %" PRIu64 ".%" PRIu64 + "), " + "(vec: %d, len: %zd)", rpc_req.seq, entry->brick, rpc_req.tv_sec, rpc_req.tv_usec, payloadcnt, payloadlen); @@ -389,11 +386,10 @@ gf_changelog_reborp_handle_event(rpcsvc_request_t *req) return gf_changelog_event_handler(req, this, entry); } -rpcsvc_actor_t gf_changelog_reborp_actors[CHANGELOG_REV_PROC_MAX] = { +static rpcsvc_actor_t gf_changelog_reborp_actors[CHANGELOG_REV_PROC_MAX] = { [CHANGELOG_REV_PROC_EVENT] = {"CHANGELOG EVENT HANDLER", - CHANGELOG_REV_PROC_EVENT, - gf_changelog_reborp_handle_event, NULL, 0, - DRC_NA}, + gf_changelog_reborp_handle_event, NULL, + CHANGELOG_REV_PROC_EVENT, DRC_NA, 0}, }; /** @@ -402,7 +398,7 @@ rpcsvc_actor_t gf_changelog_reborp_actors[CHANGELOG_REV_PROC_MAX] = { * and that's required to invoke the callback with the appropriate * brick path and it's private data. */ -struct rpcsvc_program gf_changelog_reborp_prog = { +static struct rpcsvc_program gf_changelog_reborp_prog = { .progname = "LIBGFCHANGELOG REBORP", .prognum = CHANGELOG_REV_RPC_PROCNUM, .progver = CHANGELOG_REV_RPC_PROCVER, @@ -411,7 +407,7 @@ struct rpcsvc_program gf_changelog_reborp_prog = { .synctask = _gf_false, }; -struct rpcsvc_program *gf_changelog_reborp_programs[] = { +static struct rpcsvc_program *gf_changelog_reborp_programs[] = { &gf_changelog_reborp_prog, NULL, }; diff --git a/xlators/features/changelog/lib/src/gf-changelog-rpc.h b/xlators/features/changelog/lib/src/gf-changelog-rpc.h index 975307b99d3..5c82d6f1c08 100644 --- a/xlators/features/changelog/lib/src/gf-changelog-rpc.h +++ b/xlators/features/changelog/lib/src/gf-changelog-rpc.h @@ -11,7 +11,7 @@ #ifndef __GF_CHANGELOG_RPC_H #define __GF_CHANGELOG_RPC_H -#include "xlator.h" +#include <glusterfs/xlator.h> #include "gf-changelog-helpers.h" #include "changelog-rpc-common.h" diff --git a/xlators/features/changelog/lib/src/gf-changelog.c b/xlators/features/changelog/lib/src/gf-changelog.c index c7791c62950..57c3d39ef76 100644 --- a/xlators/features/changelog/lib/src/gf-changelog.c +++ b/xlators/features/changelog/lib/src/gf-changelog.c @@ -22,11 +22,11 @@ #endif #include <string.h> -#include "globals.h" -#include "glusterfs.h" -#include "logging.h" -#include "defaults.h" -#include "syncop.h" +#include <glusterfs/globals.h> +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/defaults.h> +#include <glusterfs/syncop.h> #include "gf-changelog-rpc.h" #include "gf-changelog-helpers.h" @@ -100,48 +100,48 @@ gf_changelog_ctx_defaults_init(glusterfs_ctx_t *ctx) ctx->iobuf_pool = iobuf_pool_new(); if (!ctx->iobuf_pool) - return -1; + goto free_pool; - ctx->event_pool = event_pool_new(GF_CHANGELOG_EVENT_POOL_SIZE, - GF_CHANGELOG_EVENT_THREAD_COUNT); + ctx->event_pool = gf_event_pool_new(GF_CHANGELOG_EVENT_POOL_SIZE, + GF_CHANGELOG_EVENT_THREAD_COUNT); if (!ctx->event_pool) - return -1; + goto free_pool; pool = GF_CALLOC(1, sizeof(call_pool_t), gf_changelog_mt_libgfchangelog_call_pool_t); if (!pool) - return -1; + goto free_pool; /* frame_mem_pool size 112 * 64 */ pool->frame_mem_pool = mem_pool_new(call_frame_t, 32); if (!pool->frame_mem_pool) - return -1; + goto free_pool; /* stack_mem_pool size 256 * 128 */ pool->stack_mem_pool = mem_pool_new(call_stack_t, 16); if (!pool->stack_mem_pool) - return -1; + goto free_pool; ctx->stub_mem_pool = mem_pool_new(call_stub_t, 16); if (!ctx->stub_mem_pool) - return -1; + goto free_pool; ctx->dict_pool = mem_pool_new(dict_t, 32); if (!ctx->dict_pool) - return -1; + goto free_pool; ctx->dict_pair_pool = mem_pool_new(data_pair_t, 512); if (!ctx->dict_pair_pool) - return -1; + goto free_pool; ctx->dict_data_pool = mem_pool_new(data_t, 512); if (!ctx->dict_data_pool) - return -1; + goto free_pool; ctx->logbuf_pool = mem_pool_new(log_buf_t, 256); if (!ctx->logbuf_pool) - return -1; + goto free_pool; INIT_LIST_HEAD(&pool->all_frames); LOCK_INIT(&pool->lock); @@ -158,6 +158,31 @@ gf_changelog_ctx_defaults_init(glusterfs_ctx_t *ctx) setrlimit(RLIMIT_CORE, &lim); return 0; + +free_pool: + if (pool) { + GF_FREE(pool->frame_mem_pool); + + GF_FREE(pool->stack_mem_pool); + + GF_FREE(pool); + } + + GF_FREE(ctx->stub_mem_pool); + + GF_FREE(ctx->dict_pool); + + GF_FREE(ctx->dict_pair_pool); + + GF_FREE(ctx->dict_data_pool); + + GF_FREE(ctx->logbuf_pool); + + GF_FREE(ctx->iobuf_pool); + + GF_FREE(ctx->event_pool); + + return -1; } /* TODO: cleanup ctx defaults */ @@ -212,9 +237,8 @@ gf_changelog_init_master() { int ret = 0; - mem_pools_init_early(); ret = gf_changelog_init_context(); - mem_pools_init_late(); + mem_pools_init(); return ret; } @@ -549,9 +573,8 @@ gf_changelog_register_generic(struct gf_brick_spec *bricks, int count, brick = bricks; while (count--) { gf_smsg(this->name, GF_LOG_INFO, 0, - CHANGELOG_LIB_MSG_NOTIFY_REGISTER_INFO, "Registering brick", - "brick=%s", brick->brick_path, "notify_filter=%d", - brick->filter, NULL); + CHANGELOG_LIB_MSG_NOTIFY_REGISTER_INFO, "brick=%s", + brick->brick_path, "notify_filter=%d", brick->filter, NULL); ret = gf_changelog_register_brick(this, brick, need_order, xl); if (ret != 0) { diff --git a/xlators/features/changelog/lib/src/gf-history-changelog.c b/xlators/features/changelog/lib/src/gf-history-changelog.c index c8a31ebbd73..a16219f3664 100644 --- a/xlators/features/changelog/lib/src/gf-history-changelog.c +++ b/xlators/features/changelog/lib/src/gf-history-changelog.c @@ -8,10 +8,10 @@ #endif #include <string.h> -#include "globals.h" -#include "glusterfs.h" -#include "logging.h" -#include "syscall.h" +#include <glusterfs/globals.h> +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/syscall.h> #include "gf-changelog-helpers.h" #include "gf-changelog-journal.h" @@ -79,8 +79,8 @@ gf_history_changelog_done(char *file) ret = sys_rename(buffer, to_path); if (ret) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_RENAME_FAILED, "cannot move changelog file", - "from=%s", file, "to=%s", to_path, NULL); + CHANGELOG_LIB_MSG_RENAME_FAILED, "from=%s", file, "to=%s", + to_path, NULL); goto out; } @@ -522,8 +522,7 @@ gf_changelog_consume_wrap(void *data) _gf_true); if (ret) { gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_LIB_MSG_PARSE_ERROR, - "could not parse changelog", "name=%s", ccd->changelog, - NULL); + "name=%s", ccd->changelog, NULL); goto out; } } @@ -564,9 +563,6 @@ gf_history_consume(void *data) {0}, }; gf_changelog_consume_data_t *curr = NULL; - char thread_name[GF_THREAD_NAMEMAX] = { - 0, - }; hist_data = (gf_changelog_history_data_t *)data; if (hist_data == NULL) { @@ -612,12 +608,10 @@ gf_history_consume(void *data) curr->retval = 0; memset(curr->changelog, '\0', PATH_MAX); - snprintf(thread_name, sizeof(thread_name), "clogc%03hx", - ((iter + 1) & 0x3ff)); ret = gf_thread_create(&th_id[iter], NULL, gf_changelog_consume_wrap, curr, - thread_name); + "clogc%03hx", (iter + 1) & 0x3ff); if (ret) { gf_msg(this->name, GF_LOG_ERROR, ret, CHANGELOG_LIB_MSG_THREAD_CREATION_FAILED, @@ -647,9 +641,8 @@ gf_history_consume(void *data) curr = &ccd[iter]; if (ccd->retval) { publish = _gf_false; - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_LIB_MSG_PARSE_ERROR, - "parsing error, ceased publishing..."); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_LIB_MSG_PARSE_ERROR_CEASED, NULL); continue; } @@ -728,7 +721,7 @@ gf_changelog_extract_min_max(const char *dname, const char *htime_dir, int *fd, if (ret) { ret = -1; gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_LIB_MSG_HTIME_ERROR, - "stat() failed on htime file", "path=%s", htime_file, NULL); + "op=stat", "path=%s", htime_file, NULL); goto out; } @@ -742,7 +735,7 @@ gf_changelog_extract_min_max(const char *dname, const char *htime_dir, int *fd, if (*fd < 0) { ret = -1; gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_LIB_MSG_HTIME_ERROR, - "open() failed for htime file", "path=%s", htime_file, NULL); + "op=open", "path=%s", htime_file, NULL); goto out; } @@ -751,17 +744,15 @@ gf_changelog_extract_min_max(const char *dname, const char *htime_dir, int *fd, if (ret < 0) { ret = -1; gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_GET_XATTR_FAILED, - "error extracting max timstamp from htime file" - "path=%s", - htime_file, NULL); + CHANGELOG_LIB_MSG_GET_XATTR_FAILED, "path=%s", htime_file, + NULL); goto out; } sscanf(x_value, "%lu:%lu", max_ts, total); - gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_LIB_MSG_TOTAL_LOG_INFO, - "changelogs min max", "min=%lu", *min_ts, "max=%lu", *max_ts, - "total_changelogs=%lu", *total, NULL); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_LIB_MSG_MIN_MAX_INFO, + "min=%lu", *min_ts, "max=%lu", *max_ts, "total_changelogs=%lu", + *total, NULL); ret = 0; @@ -842,15 +833,14 @@ gf_history_changelog(char *changelog_dir, unsigned long start, goto out; } - gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_LIB_MSG_TOTAL_LOG_INFO, - "Requesting historical changelogs", "start=%lu", start, "end=%lu", - end, NULL); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_LIB_MSG_REQUESTING_INFO, + "start=%lu", start, "end=%lu", end, NULL); /* basic sanity check */ if (start > end || n_parallel <= 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_LIB_MSG_HIST_FAILED, - "Sanity check failed", "start=%lu", start, "end=%lu", end, - "thread_count=%d", n_parallel, NULL); + "start=%lu", start, "end=%lu", end, "thread_count=%d", + n_parallel, NULL); ret = -1; goto out; } @@ -864,7 +854,7 @@ gf_history_changelog(char *changelog_dir, unsigned long start, dirp = sys_opendir(htime_dir); if (dirp == NULL) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_LIB_MSG_HTIME_ERROR, - "open dir on htime failed", "path=%s", htime_dir, NULL); + "op=opendir", "path=%s", htime_dir, NULL); ret = -1; goto out; } @@ -876,9 +866,8 @@ gf_history_changelog(char *changelog_dir, unsigned long start, if (!entry || errno != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_HIST_FAILED, - "Requested changelog range is not availbale", "start=%lu", - start, "end=%lu", end, NULL); + CHANGELOG_LIB_MSG_HIST_FAILED, "start=%lu", start, + "end=%lu", end, NULL); ret = -2; break; } @@ -916,9 +905,8 @@ gf_history_changelog(char *changelog_dir, unsigned long start, if (gf_history_check(fd, from, start, len) != 0) { ret = -1; gf_smsg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_LIB_MSG_GET_TIME_ERROR, - "wrong result for start", "start=%lu", start, "idx=%lu", - from, NULL); + CHANGELOG_LIB_MSG_GET_TIME_ERROR, "for=start", + "start=%lu", start, "idx=%lu", from, NULL); goto out; } @@ -949,9 +937,8 @@ gf_history_changelog(char *changelog_dir, unsigned long start, if (gf_history_check(fd, to, end2, len) != 0) { ret = -1; gf_smsg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_LIB_MSG_GET_TIME_ERROR, - "wrong result for end", "start=%lu", end2, "idx=%lu", - to, NULL); + CHANGELOG_LIB_MSG_GET_TIME_ERROR, "for=end", + "start=%lu", end2, "idx=%lu", to, NULL); goto out; } @@ -963,9 +950,9 @@ gf_history_changelog(char *changelog_dir, unsigned long start, if (ret == -1) goto out; - gf_smsg(this->name, GF_LOG_INFO, 0, - CHANGELOG_LIB_MSG_TOTAL_LOG_INFO, "FINAL", "from=%lu", ts1, - "to=%lu", ts2, "changes=%lu", (to - from + 1), NULL); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_LIB_MSG_FINAL_INFO, + "from=%lu", ts1, "to=%lu", ts2, "changes=%lu", + (to - from + 1), NULL); hist_data = GF_CALLOC(1, sizeof(gf_changelog_history_data_t), gf_changelog_mt_history_data_t); @@ -1003,11 +990,9 @@ gf_history_changelog(char *changelog_dir, unsigned long start, } else { /* end of range check */ gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_LIB_MSG_HIST_FAILED, - "Requested changelog range is not " - "available. Retrying next HTIME", - "start=%lu", start, "end=%lu", end, "chlog_min=%lu", min_ts, - "chlog_max=%lu", max_ts, NULL); + CHANGELOG_LIB_MSG_HIST_FAILED, "start=%lu", start, + "end=%lu", end, "chlog_min=%lu", min_ts, "chlog_max=%lu", + max_ts, NULL); } } /* end of readdir() */ diff --git a/xlators/features/changelog/src/changelog-barrier.c b/xlators/features/changelog/src/changelog-barrier.c index e8d742404df..0fb89ddb127 100644 --- a/xlators/features/changelog/src/changelog-barrier.c +++ b/xlators/features/changelog/src/changelog-barrier.c @@ -10,7 +10,7 @@ #include "changelog-helpers.h" #include "changelog-messages.h" -#include "call-stub.h" +#include <glusterfs/call-stub.h> /* Enqueue a stub*/ void @@ -53,14 +53,14 @@ chlog_barrier_dequeue_all(xlator_t *this, struct list_head *queue) { call_stub_t *stub = NULL; - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BARRIER_INFO, - "Dequeuing all the changelog barriered fops"); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_DEQUEUING_BARRIER_FOPS, + NULL); while ((stub = __chlog_barrier_dequeue(this, queue))) call_resume(stub); - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BARRIER_INFO, - "Dequeuing changelog barriered fops is finished"); + gf_smsg(this->name, GF_LOG_INFO, 0, + CHANGELOG_MSG_DEQUEUING_BARRIER_FOPS_FINISHED, NULL); return; } @@ -80,8 +80,7 @@ chlog_barrier_timeout(void *data) INIT_LIST_HEAD(&queue); - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_BARRIER_ERROR, - "Disabling changelog barrier because of the timeout."); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_BARRIER_TIMEOUT, NULL); LOCK(&priv->lock); { @@ -120,8 +119,8 @@ __chlog_barrier_enable(xlator_t *this, changelog_priv_t *priv) priv->timer = gf_timer_call_after(this->ctx, priv->timeout, chlog_barrier_timeout, (void *)this); if (!priv->timer) { - gf_msg(this->name, GF_LOG_CRITICAL, 0, CHANGELOG_MSG_BARRIER_ERROR, - "Couldn't add changelog barrier timeout event."); + gf_smsg(this->name, GF_LOG_CRITICAL, 0, + CHANGELOG_MSG_TIMEOUT_ADD_FAILED, NULL); goto out; } diff --git a/xlators/features/changelog/src/changelog-encoders.h b/xlators/features/changelog/src/changelog-encoders.h index ca42c4c4fe0..26252696d56 100644 --- a/xlators/features/changelog/src/changelog-encoders.h +++ b/xlators/features/changelog/src/changelog-encoders.h @@ -11,8 +11,8 @@ #ifndef _CHANGELOG_ENCODERS_H #define _CHANGELOG_ENCODERS_H -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "changelog-helpers.h" diff --git a/xlators/features/changelog/src/changelog-ev-handle.c b/xlators/features/changelog/src/changelog-ev-handle.c index 3ed6ff821d9..aa94459de5a 100644 --- a/xlators/features/changelog/src/changelog-ev-handle.c +++ b/xlators/features/changelog/src/changelog-ev-handle.c @@ -134,6 +134,8 @@ changelog_rpc_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, changelog_clnt_t *c_clnt = NULL; changelog_priv_t *priv = NULL; changelog_ev_selector_t *selection = NULL; + uint64_t clntcnt = 0; + uint64_t xprtcnt = 0; crpc = mydata; this = crpc->this; @@ -144,6 +146,7 @@ changelog_rpc_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, switch (event) { case RPC_CLNT_CONNECT: selection = &priv->ev_selection; + GF_ATOMIC_INC(priv->clntcnt); LOCK(&c_clnt->wait_lock); { @@ -176,12 +179,23 @@ changelog_rpc_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, changelog_set_disconnect_flag(crpc, _gf_true); } UNLOCK(&crpc->lock); + LOCK(&c_clnt->active_lock); + { + list_del_init(&crpc->list); + } + UNLOCK(&c_clnt->active_lock); break; case RPC_CLNT_MSG: case RPC_CLNT_DESTROY: /* Free up mydata */ changelog_rpc_clnt_unref(crpc); + clntcnt = GF_ATOMIC_DEC(priv->clntcnt); + xprtcnt = GF_ATOMIC_GET(priv->xprtcnt); + if (this->cleanup_starting) { + if (!clntcnt && !xprtcnt) + changelog_process_cleanup_event(this); + } break; case RPC_CLNT_PING: break; @@ -211,8 +225,8 @@ changelog_ev_connector(void *data) changelog_rpc_notify); if (!crpc->rpc) { gf_smsg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_RPC_CONNECT_ERROR, - "failed to connect back", "path=%s", crpc->sock, NULL); + CHANGELOG_MSG_RPC_CONNECT_ERROR, "path=%s", crpc->sock, + NULL); crpc->cleanup(crpc); goto mutex_unlock; } @@ -364,9 +378,8 @@ changelog_ev_dispatch(void *data) ret = rbuf_wait_for_completion(c_clnt->rbuf, opaque, _dispatcher, c_clnt); if (ret) - gf_msg(this->name, GF_LOG_WARNING, 0, - CHANGELOG_MSG_PUT_BUFFER_FAILED, - "failed to put buffer after consumption"); + gf_smsg(this->name, GF_LOG_WARNING, 0, + CHANGELOG_MSG_PUT_BUFFER_FAILED, NULL); } return NULL; diff --git a/xlators/features/changelog/src/changelog-ev-handle.h b/xlators/features/changelog/src/changelog-ev-handle.h index 7e543a0edb3..cc1af58a276 100644 --- a/xlators/features/changelog/src/changelog-ev-handle.h +++ b/xlators/features/changelog/src/changelog-ev-handle.h @@ -11,11 +11,11 @@ #ifndef __CHANGELOG_EV_HANDLE_H #define __CHANGELOG_EV_HANDLE_H -#include "list.h" -#include "xlator.h" +#include <glusterfs/list.h> +#include <glusterfs/xlator.h> #include "rpc-clnt.h" -#include "rot-buffs.h" +#include <glusterfs/rot-buffs.h> struct changelog_clnt; @@ -131,4 +131,6 @@ changelog_ev_queue_connection(changelog_clnt_t *, changelog_rpc_clnt_t *); void changelog_ev_cleanup_connections(xlator_t *, changelog_clnt_t *); +void +changelog_process_cleanup_event(xlator_t *); #endif diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c index 53219bf2d78..e561997d858 100644 --- a/xlators/features/changelog/src/changelog-helpers.c +++ b/xlators/features/changelog/src/changelog-helpers.c @@ -8,11 +8,11 @@ cases as published by the Free Software Foundation. */ -#include "xlator.h" -#include "defaults.h" -#include "logging.h" -#include "iobuf.h" -#include "syscall.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/logging.h> +#include <glusterfs/iobuf.h> +#include <glusterfs/syscall.h> #include "changelog-helpers.h" #include "changelog-encoders.h" @@ -22,6 +22,7 @@ #include "changelog-encoders.h" #include "changelog-rpc-common.h" #include <pthread.h> +#include <time.h> static void changelog_cleanup_free_mutex(void *arg_mutex) @@ -41,16 +42,15 @@ changelog_thread_cleanup(xlator_t *this, pthread_t thr_id) /* send a cancel request to the thread */ ret = pthread_cancel(thr_id); if (ret != 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_CANCEL_FAILED, "could not cancel thread"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_PTHREAD_CANCEL_FAILED, NULL); goto out; } ret = pthread_join(thr_id, &retval); if ((ret != 0) || (retval != PTHREAD_CANCELED)) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_CANCEL_FAILED, - "cancel request not adhered as expected"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_PTHREAD_CANCEL_FAILED, NULL); } out: @@ -153,27 +153,6 @@ changelog_init_event_selection(xlator_t *this, return 0; } -int -changelog_cleanup_event_selection(xlator_t *this, - changelog_ev_selector_t *selection) -{ - int j = CHANGELOG_EV_SELECTION_RANGE; - - LOCK(&selection->reflock); - { - while (j--) { - if (selection->ref[j] > 0) - gf_msg(this->name, GF_LOG_WARNING, 0, - CHANGELOG_MSG_CLEANUP_ON_ACTIVE_REF, - "changelog event selection cleaning up " - " on active references"); - } - } - UNLOCK(&selection->reflock); - - return LOCK_DESTROY(&selection->reflock); -} - static void changelog_perform_dispatch(xlator_t *this, changelog_priv_t *priv, void *mem, size_t size) @@ -263,8 +242,7 @@ changelog_write(int fd, char *buffer, size_t len) } int -htime_update(xlator_t *this, changelog_priv_t *priv, unsigned long ts, - char *buffer) +htime_update(xlator_t *this, changelog_priv_t *priv, time_t ts, char *buffer) { char changelog_path[PATH_MAX + 1] = { 0, @@ -277,8 +255,8 @@ htime_update(xlator_t *this, changelog_priv_t *priv, unsigned long ts, int ret = 0; if (priv->htime_fd == -1) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_HTIME_ERROR, - "Htime fd not available for updation"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_HTIME_ERROR, + "reason=fd not available", NULL); ret = -1; goto out; } @@ -288,13 +266,13 @@ htime_update(xlator_t *this, changelog_priv_t *priv, unsigned long ts, goto out; } if (changelog_write(priv->htime_fd, (void *)changelog_path, len + 1) < 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_HTIME_ERROR, - "Htime file content write failed"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_HTIME_ERROR, + "reason=write failed", NULL); ret = -1; goto out; } - len = snprintf(x_value, sizeof(x_value), "%lu:%d", ts, + len = snprintf(x_value, sizeof(x_value), "%ld:%d", ts, priv->rollover_count); if (len >= sizeof(x_value)) { ret = -1; @@ -303,12 +281,12 @@ htime_update(xlator_t *this, changelog_priv_t *priv, unsigned long ts, if (sys_fsetxattr(priv->htime_fd, HTIME_KEY, x_value, len, XATTR_REPLACE)) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_HTIME_ERROR, - "Htime xattr updation failed with XATTR_REPLACE", + "reason=xattr updation failed", "XATTR_REPLACE=true", "changelog=%s", changelog_path, NULL); if (sys_fsetxattr(priv->htime_fd, HTIME_KEY, x_value, len, 0)) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_HTIME_ERROR, - "Htime xattr updation failed", "changelog=%s", + "reason=xattr updation failed", "changelog=%s", changelog_path, NULL); ret = -1; goto out; @@ -346,15 +324,15 @@ cl_is_empty(xlator_t *this, int fd) ret = sys_fstat(fd, &stbuf); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSTAT_OP_FAILED, - "Could not stat (CHANGELOG)"); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSTAT_OP_FAILED, + NULL); goto out; } ret = sys_lseek(fd, 0, SEEK_SET); if (ret == -1) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_LSEEK_OP_FAILED, - "Could not lseek (CHANGELOG)"); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_LSEEK_OP_FAILED, + NULL); goto out; } @@ -390,8 +368,8 @@ update_path(xlator_t *this, char *cl_path) found = strstr(cl_path, up_cl); if (found == NULL) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_LSEEK_OP_FAILED, - "Could not find CHANGELOG in changelog path"); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_PATH_NOT_FOUND, + NULL); goto out; } else { memcpy(found, low_cl, sizeof(low_cl) - 1); @@ -403,18 +381,22 @@ out: } static int -changelog_rollover_changelog(xlator_t *this, changelog_priv_t *priv, - unsigned long ts) +changelog_rollover_changelog(xlator_t *this, changelog_priv_t *priv, time_t ts) { int ret = -1; int notify = 0; int cl_empty_flag = 0; + struct tm *gmt; + char yyyymmdd[40]; char ofile[PATH_MAX] = { 0, }; char nfile[PATH_MAX] = { 0, }; + char nfile_dir[PATH_MAX] = { + 0, + }; changelog_event_t ev = { 0, }; @@ -422,33 +404,37 @@ changelog_rollover_changelog(xlator_t *this, changelog_priv_t *priv, if (priv->changelog_fd != -1) { ret = sys_fsync(priv->changelog_fd); if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_FSYNC_OP_FAILED, "fsync failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_FSYNC_OP_FAILED, NULL); } ret = cl_is_empty(this, priv->changelog_fd); if (ret == 1) { cl_empty_flag = 1; } else if (ret == -1) { /* Log error but proceed as usual */ - gf_msg(this->name, GF_LOG_WARNING, 0, - CHANGELOG_MSG_DETECT_EMPTY_CHANGELOG_FAILED, - "Error detecting empty changelog"); + gf_smsg(this->name, GF_LOG_WARNING, 0, + CHANGELOG_MSG_DETECT_EMPTY_CHANGELOG_FAILED, NULL); } sys_close(priv->changelog_fd); priv->changelog_fd = -1; } + /* Get GMT time. */ + gmt = gmtime(&ts); + + strftime(yyyymmdd, sizeof(yyyymmdd), "%Y/%m/%d", gmt); + (void)snprintf(ofile, PATH_MAX, "%s/" CHANGELOG_FILE_NAME, priv->changelog_dir); - (void)snprintf(nfile, PATH_MAX, "%s/" CHANGELOG_FILE_NAME ".%lu", - priv->changelog_dir, ts); + (void)snprintf(nfile, PATH_MAX, "%s/%s/" CHANGELOG_FILE_NAME ".%ld", + priv->changelog_dir, yyyymmdd, ts); + (void)snprintf(nfile_dir, PATH_MAX, "%s/%s", priv->changelog_dir, yyyymmdd); if (cl_empty_flag == 1) { ret = sys_unlink(ofile); if (ret) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_UNLINK_OP_FAILED, - "error unlinking empty changelog", "path=%s", ofile, NULL); + CHANGELOG_MSG_UNLINK_OP_FAILED, "path=%s", ofile, NULL); ret = 0; /* Error in unlinking empty changelog should not break further changelog operation, so reset return value to 0*/ @@ -456,13 +442,26 @@ changelog_rollover_changelog(xlator_t *this, changelog_priv_t *priv, } else { ret = sys_rename(ofile, nfile); + /* Changelog file rename gets ENOENT when parent dir doesn't exist */ + if (errno == ENOENT) { + ret = mkdir_p(nfile_dir, 0600, _gf_true); + + if ((ret == -1) && (EEXIST != errno)) { + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_MKDIR_ERROR, "%s", nfile_dir, NULL); + goto out; + } + + ret = sys_rename(ofile, nfile); + } + if (ret && (errno == ENOENT)) { ret = 0; goto out; } if (ret) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_RENAME_ERROR, - "error renaming", "from=%s", ofile, "to=%s", nfile, NULL); + "from=%s", ofile, "to=%s", nfile, NULL); } } @@ -476,8 +475,8 @@ changelog_rollover_changelog(xlator_t *this, changelog_priv_t *priv, } ret = htime_update(this, priv, ts, nfile); if (ret == -1) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_HTIME_ERROR, - "could not update htime file"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_HTIME_ERROR, + NULL); goto out; } } @@ -501,15 +500,10 @@ out: { if (ret) { priv->bn.bnotify_error = _gf_true; - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_EXPLICIT_ROLLOVER_FAILED, - "Fail snapshot because of " - "previous errors"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_EXPLICIT_ROLLOVER_FAILED, NULL); } else { gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BNOTIFY_INFO, - "Explicit " - "rollover changelog signaling " - "bnotify", "changelog=%s", nfile, NULL); } priv->bn.bnotify = _gf_false; @@ -556,8 +550,8 @@ find_current_htime(int ht_dir_fd, const char *ht_dir_path, char *ht_file_bname) cnt = scandir(ht_dir_path, &namelist, filter_cur_par_dirs, alphasort); if (cnt < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_SCAN_DIR_FAILED, - "scandir failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_SCAN_DIR_FAILED, + NULL); } else if (cnt > 0) { if (snprintf(ht_file_bname, NAME_MAX, "%s", namelist[cnt - 1]->d_name) >= NAME_MAX) { @@ -566,16 +560,15 @@ find_current_htime(int ht_dir_fd, const char *ht_dir_path, char *ht_file_bname) } if (sys_fsetxattr(ht_dir_fd, HTIME_CURRENT, ht_file_bname, strlen(ht_file_bname), 0)) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_FSETXATTR_FAILED, - "fsetxattr failed: HTIME_CURRENT"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_FSETXATTR_FAILED, "HTIME_CURRENT", NULL); ret = -1; goto out; } if (sys_fsync(ht_dir_fd) < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_FSYNC_OP_FAILED, "fsync failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_FSYNC_OP_FAILED, NULL); ret = -1; goto out; } @@ -596,7 +589,7 @@ out: * returns -1 on failure or error */ int -htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) +htime_open(xlator_t *this, changelog_priv_t *priv, time_t ts) { int ht_file_fd = -1; int ht_dir_fd = -1; @@ -632,7 +625,7 @@ htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) ht_dir_fd = open(ht_dir_path, O_RDONLY); if (ht_dir_fd == -1) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_OPEN_FAILED, - "open failed", "path=%s", ht_dir_path, NULL); + "path=%s", ht_dir_path, NULL); ret = -1; goto out; } @@ -640,9 +633,8 @@ htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) size = sys_fgetxattr(ht_dir_fd, HTIME_CURRENT, ht_file_bname, sizeof(ht_file_bname)); if (size < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FGETXATTR_FAILED, - "Error extracting" - " HTIME_CURRENT."); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FGETXATTR_FAILED, + "name=HTIME_CURRENT", NULL); /* If upgrade scenario, find the latest HTIME.TSTAMP file * and use the same. If error, create a new HTIME.TSTAMP @@ -650,20 +642,18 @@ htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) */ cnt = find_current_htime(ht_dir_fd, ht_dir_path, ht_file_bname); if (cnt <= 0) { - gf_msg(this->name, GF_LOG_INFO, errno, CHANGELOG_MSG_HTIME_INFO, - "HTIME_CURRENT not found. Changelog enabled" - " before init"); + gf_smsg(this->name, GF_LOG_INFO, errno, + CHANGELOG_MSG_NO_HTIME_CURRENT, NULL); sys_close(ht_dir_fd); return htime_create(this, priv, ts); } - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_HTIME_ERROR, - "Error extracting" - " HTIME_CURRENT."); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_HTIME_CURRENT_ERROR, NULL); } - gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_HTIME_INFO, - "HTIME_CURRENT", "path=%s", ht_file_bname, NULL); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_HTIME_CURRENT, "path=%s", + ht_file_bname, NULL); len = snprintf(ht_file_path, PATH_MAX, "%s/%s", ht_dir_path, ht_file_bname); if ((len < 0) || (len >= PATH_MAX)) { ret = -1; @@ -676,7 +666,7 @@ htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (ht_file_fd < 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_OPEN_FAILED, - "unable to open htime file", "path=%s", ht_file_path, NULL); + "path=%s", ht_file_path, NULL); ret = -1; goto out; } @@ -686,8 +676,8 @@ htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) ret = sys_fstat(ht_file_fd, &stat_buf); if (ret < 0) { - gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_HTIME_ERROR, - "unable to stat htime file", "path=%s", ht_file_path, NULL); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_HTIME_STAT_ERROR, + "path=%s", ht_file_path, NULL); ret = -1; goto out; } @@ -696,9 +686,7 @@ htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) size = sys_fgetxattr(ht_file_fd, HTIME_KEY, x_value, sizeof(x_value)); if (size < 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FGETXATTR_FAILED, - "error extracting max" - " timstamp from htime file", - "path=%s", ht_file_path, NULL); + "name=%s", HTIME_KEY, "path=%s", ht_file_path, NULL); ret = -1; goto out; } @@ -710,14 +698,11 @@ htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts) total1 = stat_buf.st_size / record_len; if (total != total1) { gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_TOTAL_LOG_INFO, - "Mismatch of changelog count. " - "INIT CASE", "xattr_total=%lu", total, "size_total=%lu", total1, NULL); } - gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_TOTAL_LOG_INFO, - "INIT CASE", "min=%lu", min_ts, "max=%lu", max_ts, - "total_changelogs=%lu", total, NULL); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_TOTAL_LOG_INFO, "min=%lu", + min_ts, "max=%lu", max_ts, "total_changelogs=%lu", total, NULL); if (total < total1) priv->rollover_count = total1 + 1; @@ -734,7 +719,7 @@ out: * returns -1 on failure or error */ int -htime_create(xlator_t *this, changelog_priv_t *priv, unsigned long ts) +htime_create(xlator_t *this, changelog_priv_t *priv, time_t ts) { int ht_file_fd = -1; int ht_dir_fd = -1; @@ -751,15 +736,13 @@ htime_create(xlator_t *this, changelog_priv_t *priv, unsigned long ts) int flags = 0; int32_t len = 0; - gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_HTIME_INFO, - "Changelog enable: Creating new " - "HTIME file", - "name=%lu", ts, NULL); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_NEW_HTIME_FILE, + "name=%ld", ts, NULL); CHANGELOG_FILL_HTIME_DIR(priv->changelog_dir, ht_dir_path); /* get the htime file name in ht_file_path */ - len = snprintf(ht_file_path, PATH_MAX, "%s/%s.%lu", ht_dir_path, + len = snprintf(ht_file_path, PATH_MAX, "%s/%s.%ld", ht_dir_path, HTIME_FILE_NAME, ts); if ((len < 0) || (len >= PATH_MAX)) { ret = -1; @@ -771,23 +754,23 @@ htime_create(xlator_t *this, changelog_priv_t *priv, unsigned long ts) S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (ht_file_fd < 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_OPEN_FAILED, - "unable to create htime file", "path=%s", ht_file_path, NULL); + "path=%s", ht_file_path, NULL); ret = -1; goto out; } if (sys_fsetxattr(ht_file_fd, HTIME_KEY, HTIME_INITIAL_VALUE, sizeof(HTIME_INITIAL_VALUE) - 1, 0)) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSETXATTR_FAILED, - "Htime xattr initialization failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_XATTR_INIT_FAILED, NULL); ret = -1; goto out; } ret = sys_fsync(ht_file_fd); if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSYNC_OP_FAILED, - "fsync failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSYNC_OP_FAILED, + NULL); goto out; } @@ -800,26 +783,25 @@ htime_create(xlator_t *this, changelog_priv_t *priv, unsigned long ts) ht_dir_fd = open(ht_dir_path, O_RDONLY); if (ht_dir_fd == -1) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_OPEN_FAILED, - "open failed", "path=%s", ht_dir_path, NULL); + "path=%s", ht_dir_path, NULL); ret = -1; goto out; } - (void)snprintf(ht_file_bname, sizeof(ht_file_bname), "%s.%lu", + (void)snprintf(ht_file_bname, sizeof(ht_file_bname), "%s.%ld", HTIME_FILE_NAME, ts); if (sys_fsetxattr(ht_dir_fd, HTIME_CURRENT, ht_file_bname, strlen(ht_file_bname), 0)) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSETXATTR_FAILED, - "fsetxattr failed:" - " HTIME_CURRENT"); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSETXATTR_FAILED, + " HTIME_CURRENT", NULL); ret = -1; goto out; } ret = sys_fsync(ht_dir_fd); if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSYNC_OP_FAILED, - "fsync failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_FSYNC_OP_FAILED, + NULL); goto out; } @@ -873,7 +855,7 @@ changelog_snap_open(xlator_t *this, changelog_priv_t *priv) fd = open(c_snap_path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd < 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_OPEN_FAILED, - "unable to open file", "path=%s", c_snap_path, NULL); + "path=%s", c_snap_path, NULL); ret = -1; goto out; } @@ -905,8 +887,8 @@ changelog_snap_logging_start(xlator_t *this, changelog_priv_t *priv) int ret = 0; ret = changelog_snap_open(this, priv); - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_SNAP_INFO, - "Now starting to log in call path"); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_SNAP_INFO, "starting", + NULL); return ret; } @@ -926,8 +908,8 @@ changelog_snap_logging_stop(xlator_t *this, changelog_priv_t *priv) sys_close(priv->c_snap_fd); priv->c_snap_fd = -1; - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_SNAP_INFO, - "Stopped to log in call path"); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_SNAP_INFO, "Stopped", + NULL); return ret; } @@ -955,9 +937,6 @@ changelog_open_journal(xlator_t *this, changelog_priv_t *priv) fd = open(changelog_path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd < 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_OPEN_FAILED, - "unable to open/create changelog file." - " change-logging will be" - " inactive", "path=%s", changelog_path, NULL); goto out; } @@ -980,8 +959,8 @@ out: } int -changelog_start_next_change(xlator_t *this, changelog_priv_t *priv, - unsigned long ts, gf_boolean_t finale) +changelog_start_next_change(xlator_t *this, changelog_priv_t *priv, time_t ts, + gf_boolean_t finale) { int ret = -1; @@ -1002,21 +981,12 @@ changelog_entry_length() return sizeof(changelog_log_data_t); } -int +void changelog_fill_rollover_data(changelog_log_data_t *cld, gf_boolean_t is_last) { - struct timeval tv = { - 0, - }; - cld->cld_type = CHANGELOG_TYPE_ROLLOVER; - - if (gettimeofday(&tv, NULL)) - return -1; - - cld->cld_roll_time = (unsigned long)tv.tv_sec; + cld->cld_roll_time = gf_time(); cld->cld_finale = is_last; - return 0; } int @@ -1074,11 +1044,10 @@ changelog_snap_handle_ascii_change(xlator_t *this, changelog_log_data_t *cld) ret = changelog_snap_write_change(priv, buffer, off); if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_WRITE_FAILED, - "error writing csnap to disk"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_WRITE_FAILED, + "csnap", NULL); } - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_SNAP_INFO, - "Successfully wrote to csnap"); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_WROTE_TO_CSNAP, NULL); ret = 0; out: return ret; @@ -1095,9 +1064,8 @@ changelog_handle_change(xlator_t *this, changelog_priv_t *priv, ret = changelog_start_next_change(this, priv, cld->cld_roll_time, cld->cld_finale); if (ret) - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_GET_TIME_OP_FAILED, - "Problem rolling over changelog(s)"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_GET_TIME_OP_FAILED, NULL); goto out; } @@ -1111,16 +1079,16 @@ changelog_handle_change(xlator_t *this, changelog_priv_t *priv, if (CHANGELOG_TYPE_IS_FSYNC(cld->cld_type)) { ret = sys_fsync(priv->changelog_fd); if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_FSYNC_OP_FAILED, "fsync failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_FSYNC_OP_FAILED, NULL); } goto out; } ret = priv->ce->encode(this, cld); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_WRITE_FAILED, - "error writing changelog to disk"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_WRITE_FAILED, + "changelog", NULL); } out: @@ -1143,6 +1111,7 @@ changelog_local_init(xlator_t *this, inode_t *inode, uuid_t gfid, gf_msg_callingfn(this->name, GF_LOG_WARNING, 0, CHANGELOG_MSG_INODE_NOT_FOUND, "inode needed for version checking !!!"); + goto out; } @@ -1211,7 +1180,7 @@ changelog_drain_black_fops(xlator_t *this, changelog_priv_t *priv) ret = pthread_mutex_lock(&priv->dm.drain_black_mutex); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_PTHREAD_ERROR, - "pthread error", "error=%d", ret, NULL); + "error=%d", ret, NULL); while (priv->dm.black_fop_cnt > 0) { gf_msg_debug(this->name, 0, "Conditional wait on black fops: %ld", priv->dm.black_fop_cnt); @@ -1220,14 +1189,14 @@ changelog_drain_black_fops(xlator_t *this, changelog_priv_t *priv) &priv->dm.drain_black_mutex); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_COND_WAIT_FAILED, - "pthread cond wait failed", "error=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_COND_WAIT_FAILED, "error=%d", ret, + NULL); } priv->dm.drain_wait_black = _gf_false; ret = pthread_mutex_unlock(&priv->dm.drain_black_mutex); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_PTHREAD_ERROR, - "pthread error", "error=%d", ret, NULL); + "error=%d", ret, NULL); pthread_cleanup_pop(0); gf_msg_debug(this->name, 0, "Woke up: Conditional wait on black fops"); } @@ -1247,7 +1216,7 @@ changelog_drain_white_fops(xlator_t *this, changelog_priv_t *priv) ret = pthread_mutex_lock(&priv->dm.drain_white_mutex); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_PTHREAD_ERROR, - "pthread error", "error=%d", ret, NULL); + "error=%d", ret, NULL); while (priv->dm.white_fop_cnt > 0) { gf_msg_debug(this->name, 0, "Conditional wait on white fops : %ld", priv->dm.white_fop_cnt); @@ -1256,14 +1225,14 @@ changelog_drain_white_fops(xlator_t *this, changelog_priv_t *priv) &priv->dm.drain_white_mutex); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_COND_WAIT_FAILED, - "pthread cond wait failed", "error=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_COND_WAIT_FAILED, "error=%d", ret, + NULL); } priv->dm.drain_wait_white = _gf_false; ret = pthread_mutex_unlock(&priv->dm.drain_white_mutex); if (ret) gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_PTHREAD_ERROR, - "pthread error", "error=%d", ret, NULL); + "error=%d", ret, NULL); pthread_cleanup_pop(0); gf_msg_debug(this->name, 0, "Woke up: Conditional wait on white fops"); } @@ -1292,7 +1261,7 @@ changelog_rollover(void *data) while (1) { (void)pthread_testcancel(); - tv.tv_sec = time(NULL) + priv->rollover_time; + tv.tv_sec = gf_time() + priv->rollover_time; tv.tv_nsec = 0; ret = 0; /* Reset ret to zero */ @@ -1315,12 +1284,12 @@ changelog_rollover(void *data) pthread_cleanup_pop(0); if (ret == 0) { - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BARRIER_INFO, - "Explicit wakeup on barrier notify"); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BARRIER_INFO, + NULL); priv->explicit_rollover = _gf_true; } else if (ret && ret != ETIMEDOUT) { - gf_msg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_SELECT_FAILED, - "pthread_cond_timedwait failed"); + gf_smsg(this->name, GF_LOG_ERROR, errno, + CHANGELOG_MSG_SELECT_FAILED, NULL); continue; } else if (ret && ret == ETIMEDOUT) { gf_msg_debug(this->name, 0, "Wokeup on timeout"); @@ -1373,13 +1342,7 @@ changelog_rollover(void *data) if (priv->explicit_rollover == _gf_true) sleep(1); - ret = changelog_fill_rollover_data(&cld, _gf_false); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_GET_TIME_OP_FAILED, - "failed to fill rollover data"); - continue; - } + changelog_fill_rollover_data(&cld, _gf_false); _mask_cancellation(); @@ -1427,9 +1390,8 @@ changelog_fsync_thread(void *data) ret = changelog_inject_single_event(this, priv, &cld); if (ret) - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_INJECT_FSYNC_FAILED, - "failed to inject fsync event"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_INJECT_FSYNC_FAILED, NULL); _unmask_cancellation(); } @@ -1466,7 +1428,7 @@ static int __changelog_inode_ctx_set(xlator_t *this, inode_t *inode, changelog_inode_ctx_t *ctx) { - uint64_t ctx_addr = (uint64_t)ctx; + uint64_t ctx_addr = (uint64_t)(uintptr_t)ctx; return __inode_ctx_set(inode, this, &ctx_addr); } @@ -1851,23 +1813,21 @@ changelog_fill_entry_buf(call_frame_t *frame, xlator_t *this, loc_t *loc, parent = inode_parent(loc->inode, 0, 0); if (!parent) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_INODE_NOT_FOUND, - "Parent inode not found", "gfid=%s", - uuid_utoa(loc->inode->gfid), NULL); + "type=parent", "gfid=%s", uuid_utoa(loc->inode->gfid), NULL); goto err; } CHANGELOG_INIT_NOCHECK(this, *local, loc->inode, loc->inode->gfid, 5); if (!(*local)) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_LOCAL_INIT_FAILED, - "changelog local" - " initiatilization failed"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_LOCAL_INIT_FAILED, + NULL); goto err; } co = changelog_get_usable_buffer(*local); if (!co) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_NO_MEMORY, - "Failed to get buffer"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_GET_BUFFER_FAILED, + NULL); goto err; } diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h index 10d457e8cf5..38fa7590c32 100644 --- a/xlators/features/changelog/src/changelog-helpers.h +++ b/xlators/features/changelog/src/changelog-helpers.h @@ -11,14 +11,14 @@ #ifndef _CHANGELOG_HELPERS_H #define _CHANGELOG_HELPERS_H -#include "locking.h" -#include "timer.h" +#include <glusterfs/locking.h> +#include <glusterfs/timer.h> #include "pthread.h" -#include "iobuf.h" -#include "rot-buffs.h" +#include <glusterfs/iobuf.h> +#include <glusterfs/rot-buffs.h> #include "changelog-misc.h" -#include "call-stub.h" +#include <glusterfs/call-stub.h> #include "rpcsvc.h" #include "changelog-ev-handle.h" @@ -31,7 +31,7 @@ */ typedef struct changelog_log_data { /* rollover related */ - unsigned long cld_roll_time; + time_t cld_roll_time; /* reopen changelog? */ gf_boolean_t cld_finale; @@ -97,12 +97,6 @@ struct changelog_encoder { typedef struct changelog_time_slice { /** - * just in case we need nanosecond granularity some day. - * field is unused as of now (maybe we'd need it later). - */ - struct timeval tv_start; - - /** * version of changelog file, incremented each time changes * rollover. */ @@ -190,8 +184,12 @@ typedef struct changelog_ev_selector { /* changelog's private structure */ struct changelog_priv { + /* changelog journalling */ gf_boolean_t active; + /* changelog live notifications */ + gf_boolean_t rpc_active; + /* to generate unique socket file per brick */ char *changelog_brick; @@ -307,6 +305,24 @@ struct changelog_priv { /* glusterfind dependency to capture paths on deleted entries*/ gf_boolean_t capture_del_path; + + /* Save total no. of listners */ + gf_atomic_t listnercnt; + + /* Save total no. of xprt are associated with listner */ + gf_atomic_t xprtcnt; + + /* Save xprt list */ + struct list_head xprt_list; + + /* Save total no. of client connection */ + gf_atomic_t clntcnt; + + /* Save cleanup brick in victim */ + xlator_t *victim; + + /* Status to save cleanup notify status */ + gf_boolean_t notify_down; }; struct changelog_local { @@ -401,11 +417,11 @@ changelog_local_t * changelog_local_init(xlator_t *this, inode_t *inode, uuid_t gfid, int xtra_records, gf_boolean_t update_flag); int -changelog_start_next_change(xlator_t *this, changelog_priv_t *priv, - unsigned long ts, gf_boolean_t finale); +changelog_start_next_change(xlator_t *this, changelog_priv_t *priv, time_t ts, + gf_boolean_t finale); int changelog_open_journal(xlator_t *this, changelog_priv_t *priv); -int +void changelog_fill_rollover_data(changelog_log_data_t *cld, gf_boolean_t is_last); int changelog_inject_single_event(xlator_t *this, changelog_priv_t *priv, @@ -429,12 +445,11 @@ changelog_fsync_thread(void *data); int changelog_forget(xlator_t *this, inode_t *inode); int -htime_update(xlator_t *this, changelog_priv_t *priv, unsigned long ts, - char *buffer); +htime_update(xlator_t *this, changelog_priv_t *priv, time_t ts, char *buffer); int -htime_open(xlator_t *this, changelog_priv_t *priv, unsigned long ts); +htime_open(xlator_t *this, changelog_priv_t *priv, time_t ts); int -htime_create(xlator_t *this, changelog_priv_t *priv, unsigned long ts); +htime_create(xlator_t *this, changelog_priv_t *priv, time_t ts); /* Geo-Rep snapshot dependency changes */ void @@ -492,8 +507,6 @@ changelog_deselect_event(xlator_t *, changelog_ev_selector_t *, unsigned int); int changelog_init_event_selection(xlator_t *, changelog_ev_selector_t *); int -changelog_cleanup_event_selection(xlator_t *, changelog_ev_selector_t *); -int changelog_ev_selected(xlator_t *, changelog_ev_selector_t *, unsigned int); void changelog_dispatch_event(xlator_t *, changelog_priv_t *, changelog_event_t *); @@ -656,8 +669,8 @@ resolve_pargfid_to_path(xlator_t *this, const uuid_t gfid, char **path, #define CHANGELOG_NOT_ON_THEN_GOTO(priv, ret, label) \ do { \ if (!priv->active) { \ - gf_msg(this->name, GF_LOG_WARNING, 0, CHANGELOG_MSG_NOT_ACTIVE, \ - "Changelog is not active, return success"); \ + gf_smsg(this->name, GF_LOG_WARNING, 0, \ + CHANGELOG_MSG_CHANGELOG_NOT_ACTIVE, NULL); \ ret = 0; \ goto label; \ } \ @@ -668,7 +681,7 @@ resolve_pargfid_to_path(xlator_t *this, const uuid_t gfid, char **path, do { \ if (ret) { \ gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_PTHREAD_ERROR, \ - "pthread error", "error=%d", ret, NULL); \ + "error=%d", ret, NULL); \ ret = -1; \ goto label; \ } \ @@ -679,7 +692,7 @@ resolve_pargfid_to_path(xlator_t *this, const uuid_t gfid, char **path, do { \ if (ret) { \ gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_PTHREAD_ERROR, \ - "pthread error", "error=%d", ret, NULL); \ + "error=%d", ret, NULL); \ ret = -1; \ flag = _gf_true; \ goto label; \ @@ -691,7 +704,7 @@ resolve_pargfid_to_path(xlator_t *this, const uuid_t gfid, char **path, do { \ if (ret) { \ gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_PTHREAD_ERROR, \ - "pthread error", "error=%d", ret, NULL); \ + "error=%d", ret, NULL); \ ret = -1; \ pthread_mutex_unlock(&mutex); \ goto label; \ diff --git a/xlators/features/changelog/src/changelog-mem-types.h b/xlators/features/changelog/src/changelog-mem-types.h index 1e3786c6298..a2d8a9cbe93 100644 --- a/xlators/features/changelog/src/changelog-mem-types.h +++ b/xlators/features/changelog/src/changelog-mem-types.h @@ -11,7 +11,7 @@ #ifndef _CHANGELOG_MEM_TYPES_H #define _CHANGELOG_MEM_TYPES_H -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_changelog_mem_types { gf_changelog_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/changelog/src/changelog-messages.h b/xlators/features/changelog/src/changelog-messages.h index dbf133ec836..cb0e16c85d8 100644 --- a/xlators/features/changelog/src/changelog-messages.h +++ b/xlators/features/changelog/src/changelog-messages.h @@ -11,7 +11,7 @@ #ifndef _CHANGELOG_MESSAGES_H_ #define _CHANGELOG_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * @@ -24,7 +24,7 @@ */ GLFS_MSGID( - CHANGELOG, CHANGELOG_MSG_OPEN_FAILED, CHANGELOG_MSG_NO_MEMORY, + CHANGELOG, CHANGELOG_MSG_OPEN_FAILED, CHANGELOG_MSG_BARRIER_FOP_FAILED, CHANGELOG_MSG_VOL_MISCONFIGURED, CHANGELOG_MSG_RENAME_ERROR, CHANGELOG_MSG_READ_ERROR, CHANGELOG_MSG_HTIME_ERROR, CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, @@ -37,11 +37,11 @@ GLFS_MSGID( CHANGELOG_MSG_FSYNC_OP_FAILED, CHANGELOG_MSG_TOTAL_LOG_INFO, CHANGELOG_MSG_SNAP_INFO, CHANGELOG_MSG_SELECT_FAILED, CHANGELOG_MSG_FCNTL_FAILED, CHANGELOG_MSG_BNOTIFY_INFO, - CHANGELOG_MSG_ENTRY_BUF_INFO, CHANGELOG_MSG_NOT_ACTIVE, + CHANGELOG_MSG_ENTRY_BUF_INFO, CHANGELOG_MSG_CHANGELOG_NOT_ACTIVE, CHANGELOG_MSG_LOCAL_INIT_FAILED, CHANGELOG_MSG_NOTIFY_REGISTER_FAILED, CHANGELOG_MSG_PROGRAM_NAME_REG_FAILED, CHANGELOG_MSG_HANDLE_PROBE_ERROR, CHANGELOG_MSG_SET_FD_CONTEXT, CHANGELOG_MSG_FREEUP_FAILED, - CHANGELOG_MSG_HTIME_INFO, CHANGELOG_MSG_RPC_SUBMIT_REPLY_FAILED, + CHANGELOG_MSG_RECONFIGURE, CHANGELOG_MSG_RPC_SUBMIT_REPLY_FAILED, CHANGELOG_MSG_RPC_BUILD_ERROR, CHANGELOG_MSG_RPC_CONNECT_ERROR, CHANGELOG_MSG_RPC_START_ERROR, CHANGELOG_MSG_BUFFER_STARVATION_ERROR, CHANGELOG_MSG_SCAN_DIR_FAILED, CHANGELOG_MSG_FSETXATTR_FAILED, @@ -52,6 +52,121 @@ GLFS_MSGID( CHANGELOG_MSG_FSTAT_OP_FAILED, CHANGELOG_MSG_LSEEK_OP_FAILED, CHANGELOG_MSG_STRSTR_OP_FAILED, CHANGELOG_MSG_UNLINK_OP_FAILED, CHANGELOG_MSG_DETECT_EMPTY_CHANGELOG_FAILED, - CHANGELOG_MSG_READLINK_OP_FAILED, CHANGELOG_MSG_EXPLICIT_ROLLOVER_FAILED); + CHANGELOG_MSG_READLINK_OP_FAILED, CHANGELOG_MSG_EXPLICIT_ROLLOVER_FAILED, + CHANGELOG_MSG_RPCSVC_NOTIFY_FAILED, CHANGELOG_MSG_MEMORY_INIT_FAILED, + CHANGELOG_MSG_NO_MEMORY, CHANGELOG_MSG_HTIME_STAT_ERROR, + CHANGELOG_MSG_HTIME_CURRENT_ERROR, CHANGELOG_MSG_BNOTIFY_COND_INFO, + CHANGELOG_MSG_NO_HTIME_CURRENT, CHANGELOG_MSG_HTIME_CURRENT, + CHANGELOG_MSG_NEW_HTIME_FILE, CHANGELOG_MSG_MKDIR_ERROR, + CHANGELOG_MSG_PATH_NOT_FOUND, CHANGELOG_MSG_XATTR_INIT_FAILED, + CHANGELOG_MSG_WROTE_TO_CSNAP, CHANGELOG_MSG_UNUSED_0, + CHANGELOG_MSG_GET_BUFFER_FAILED, CHANGELOG_MSG_BARRIER_STATE_NOTIFY, + CHANGELOG_MSG_BARRIER_DISABLED, CHANGELOG_MSG_BARRIER_ALREADY_DISABLED, + CHANGELOG_MSG_BARRIER_ON_ERROR, CHANGELOG_MSG_BARRIER_ENABLE, + CHANGELOG_MSG_BARRIER_KEY_NOT_FOUND, CHANGELOG_MSG_ERROR_IN_DICT_GET, + CHANGELOG_MSG_UNUSED_1, CHANGELOG_MSG_UNUSED_2, + CHANGELOG_MSG_DEQUEUING_BARRIER_FOPS, + CHANGELOG_MSG_DEQUEUING_BARRIER_FOPS_FINISHED, + CHANGELOG_MSG_BARRIER_TIMEOUT, CHANGELOG_MSG_TIMEOUT_ADD_FAILED, + CHANGELOG_MSG_CLEANUP_ALREADY_SET); +#define CHANGELOG_MSG_BARRIER_FOP_FAILED_STR \ + "failed to barrier FOPs, disabling changelog barrier" +#define CHANGELOG_MSG_MEMORY_INIT_FAILED_STR "memory accounting init failed" +#define CHANGELOG_MSG_NO_MEMORY_STR "failed to create local memory pool" +#define CHANGELOG_MSG_ENTRY_BUF_INFO_STR \ + "Entry cannot be captured for gfid, Capturing DATA entry." +#define CHANGELOG_MSG_PTHREAD_ERROR_STR "pthread error" +#define CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED_STR "pthread_mutex_init failed" +#define CHANGELOG_MSG_PTHREAD_COND_INIT_FAILED_STR "pthread_cond_init failed" +#define CHANGELOG_MSG_HTIME_ERROR_STR "failed to update HTIME file" +#define CHANGELOG_MSG_HTIME_STAT_ERROR_STR "unable to stat htime file" +#define CHANGELOG_MSG_HTIME_CURRENT_ERROR_STR "Error extracting HTIME_CURRENT." +#define CHANGELOG_MSG_UNLINK_OP_FAILED_STR "error unlinking empty changelog" +#define CHANGELOG_MSG_RENAME_ERROR_STR "error renaming" +#define CHANGELOG_MSG_MKDIR_ERROR_STR "unable to create directory" +#define CHANGELOG_MSG_BNOTIFY_INFO_STR \ + "Explicit rollover changelog signaling bnotify" +#define CHANGELOG_MSG_BNOTIFY_COND_INFO_STR "Woke up: bnotify conditional wait" +#define CHANGELOG_MSG_RECONFIGURE_STR "Reconfigure: Changelog Enable" +#define CHANGELOG_MSG_NO_HTIME_CURRENT_STR \ + "HTIME_CURRENT not found. Changelog enabled before init" +#define CHANGELOG_MSG_HTIME_CURRENT_STR "HTIME_CURRENT" +#define CHANGELOG_MSG_NEW_HTIME_FILE_STR \ + "Changelog enable: Creating new HTIME file" +#define CHANGELOG_MSG_FGETXATTR_FAILED_STR "fgetxattr failed" +#define CHANGELOG_MSG_TOTAL_LOG_INFO_STR "changelog info" +#define CHANGELOG_MSG_PTHREAD_COND_WAIT_FAILED_STR "pthread cond wait failed" +#define CHANGELOG_MSG_INODE_NOT_FOUND_STR "inode not found" +#define CHANGELOG_MSG_READLINK_OP_FAILED_STR \ + "could not read the link from the gfid handle" +#define CHANGELOG_MSG_OPEN_FAILED_STR "unable to open file" +#define CHANGELOG_MSG_RPC_CONNECT_ERROR_STR "failed to connect back" +#define CHANGELOG_MSG_BUFFER_STARVATION_ERROR_STR \ + "Failed to get buffer for RPC dispatch" +#define CHANGELOG_MSG_PTHREAD_CANCEL_FAILED_STR "could not cancel thread" +#define CHANGELOG_MSG_FSTAT_OP_FAILED_STR "Could not stat (CHANGELOG)" +#define CHANGELOG_MSG_LSEEK_OP_FAILED_STR "Could not lseek (changelog)" +#define CHANGELOG_MSG_PATH_NOT_FOUND_STR \ + "Could not find CHANGELOG in changelog path" +#define CHANGELOG_MSG_FSYNC_OP_FAILED_STR "fsync failed" +#define CHANGELOG_MSG_DETECT_EMPTY_CHANGELOG_FAILED_STR \ + "Error detecting empty changelog" +#define CHANGELOG_MSG_EXPLICIT_ROLLOVER_FAILED_STR \ + "Fail snapshot because of previous errors" +#define CHANGELOG_MSG_SCAN_DIR_FAILED_STR "scandir failed" +#define CHANGELOG_MSG_FSETXATTR_FAILED_STR "fsetxattr failed" +#define CHANGELOG_MSG_XATTR_INIT_FAILED_STR "Htime xattr initialization failed" +#define CHANGELOG_MSG_SNAP_INFO_STR "log in call path" +#define CHANGELOG_MSG_WRITE_FAILED_STR "error writing to disk" +#define CHANGELOG_MSG_WROTE_TO_CSNAP_STR "Successfully wrote to csnap" +#define CHANGELOG_MSG_GET_TIME_OP_FAILED_STR "Problem rolling over changelog(s)" +#define CHANGELOG_MSG_BARRIER_INFO_STR "Explicit wakeup on barrier notify" +#define CHANGELOG_MSG_SELECT_FAILED_STR "pthread_cond_timedwait failed" +#define CHANGELOG_MSG_INJECT_FSYNC_FAILED_STR "failed to inject fsync event" +#define CHANGELOG_MSG_LOCAL_INIT_FAILED_STR \ + "changelog local initialization failed" +#define CHANGELOG_MSG_GET_BUFFER_FAILED_STR "Failed to get buffer" +#define CHANGELOG_MSG_SET_FD_CONTEXT_STR \ + "could not set fd context(for release cbk)" +#define CHANGELOG_MSG_DICT_GET_FAILED_STR "Barrier failed" +#define CHANGELOG_MSG_BARRIER_STATE_NOTIFY_STR "Barrier notification" +#define CHANGELOG_MSG_BARRIER_ERROR_STR \ + "Received another barrier off notification while already off" +#define CHANGELOG_MSG_BARRIER_DISABLED_STR "disabled changelog barrier" +#define CHANGELOG_MSG_BARRIER_ALREADY_DISABLED_STR \ + "Changelog barrier already disabled" +#define CHANGELOG_MSG_BARRIER_ON_ERROR_STR \ + "Received another barrier on notification when last one is not served yet" +#define CHANGELOG_MSG_BARRIER_ENABLE_STR "Enabled changelog barrier" +#define CHANGELOG_MSG_BARRIER_KEY_NOT_FOUND_STR "barrier key not found" +#define CHANGELOG_MSG_ERROR_IN_DICT_GET_STR \ + "Something went wrong in dict_get_str_boolean" +#define CHANGELOG_MSG_DIR_OPTIONS_NOT_SET_STR "changelog-dir option is not set" +#define CHANGELOG_MSG_FREEUP_FAILED_STR "could not cleanup bootstrapper" +#define CHANGELOG_MSG_CHILD_MISCONFIGURED_STR \ + "translator needs a single subvolume" +#define CHANGELOG_MSG_VOL_MISCONFIGURED_STR \ + "dangling volume. please check volfile" +#define CHANGELOG_MSG_DEQUEUING_BARRIER_FOPS_STR \ + "Dequeuing all the changelog barriered fops" +#define CHANGELOG_MSG_DEQUEUING_BARRIER_FOPS_FINISHED_STR \ + "Dequeuing changelog barriered fops is finished" +#define CHANGELOG_MSG_BARRIER_TIMEOUT_STR \ + "Disabling changelog barrier because of the timeout" +#define CHANGELOG_MSG_TIMEOUT_ADD_FAILED_STR \ + "Couldn't add changelog barrier timeout event" +#define CHANGELOG_MSG_RPC_BUILD_ERROR_STR "failed to build rpc options" +#define CHANGELOG_MSG_NOTIFY_REGISTER_FAILED_STR "failed to register notify" +#define CHANGELOG_MSG_RPC_START_ERROR_STR "failed to start rpc" +#define CHANGELOG_MSG_CREATE_FRAME_FAILED_STR "failed to create frame" +#define CHANGELOG_MSG_RPC_SUBMIT_REPLY_FAILED_STR "failed to serialize reply" +#define CHANGELOG_MSG_PROGRAM_NAME_REG_FAILED_STR "cannot register program" +#define CHANGELOG_MSG_CHANGELOG_NOT_ACTIVE_STR \ + "Changelog is not active, return success" +#define CHANGELOG_MSG_PUT_BUFFER_FAILED_STR \ + "failed to put buffer after consumption" +#define CHANGELOG_MSG_CLEANUP_ALREADY_SET_STR \ + "cleanup_starting flag is already set for xl" +#define CHANGELOG_MSG_HANDLE_PROBE_ERROR_STR "xdr decoding error" #endif /* !_CHANGELOG_MESSAGES_H_ */ diff --git a/xlators/features/changelog/src/changelog-misc.h b/xlators/features/changelog/src/changelog-misc.h index 04d1bdeba03..e2addc09414 100644 --- a/xlators/features/changelog/src/changelog-misc.h +++ b/xlators/features/changelog/src/changelog-misc.h @@ -11,8 +11,8 @@ #ifndef _CHANGELOG_MISC_H #define _CHANGELOG_MISC_H -#include "glusterfs.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/common-utils.h> #define CHANGELOG_MAX_TYPE 4 #define CHANGELOG_FILE_NAME "CHANGELOG" diff --git a/xlators/features/changelog/src/changelog-rpc-common.c b/xlators/features/changelog/src/changelog-rpc-common.c index ce01bf7a133..125246a17e1 100644 --- a/xlators/features/changelog/src/changelog-rpc-common.c +++ b/xlators/features/changelog/src/changelog-rpc-common.c @@ -11,7 +11,7 @@ #include "changelog-rpc-common.h" #include "changelog-messages.h" -#include "syscall.h" +#include <glusterfs/syscall.h> /** ***************************************************** Client Interface @@ -28,7 +28,7 @@ changelog_rpc_poller(void *arg) { xlator_t *this = arg; - (void)event_dispatch(this->ctx->event_pool); + (void)gf_event_dispatch(this->ctx->event_pool); return NULL; } @@ -47,10 +47,10 @@ changelog_rpc_client_init(xlator_t *this, void *cbkdata, char *sockfile, if (!options) goto error_return; - ret = rpc_transport_unix_options_build(&options, sockfile, 0); + ret = rpc_transport_unix_options_build(options, sockfile, 0); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_BUILD_ERROR, - "failed to build rpc options"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_BUILD_ERROR, + NULL); goto dealloc_dict; } @@ -60,19 +60,19 @@ changelog_rpc_client_init(xlator_t *this, void *cbkdata, char *sockfile, ret = rpc_clnt_register_notify(rpc, fn, cbkdata); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_NOTIFY_REGISTER_FAILED, - "failed to register notify"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_NOTIFY_REGISTER_FAILED, NULL); goto dealloc_rpc_clnt; } ret = rpc_clnt_start(rpc); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_START_ERROR, - "failed to start rpc"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_START_ERROR, + NULL); goto dealloc_rpc_clnt; } + dict_unref(options); return rpc; dealloc_rpc_clnt: @@ -164,8 +164,8 @@ changelog_invoke_rpc(xlator_t *this, struct rpc_clnt *rpc, frame = create_frame(this, this->ctx->pool); if (!frame) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_CREATE_FRAME_FAILED, - "failed to create frame"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_CREATE_FRAME_FAILED, + NULL); goto error_return; } @@ -238,8 +238,8 @@ changelog_rpc_sumbit_reply(rpcsvc_request_t *req, void *arg, iob = __changelog_rpc_serialize_reply(req, arg, &iov, xdrproc); if (!iob) - gf_msg("", GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_SUBMIT_REPLY_FAILED, - "failed to serialize reply"); + gf_smsg("", GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_SUBMIT_REPLY_FAILED, + NULL); else iobref_add(iobref, iob); @@ -260,6 +260,10 @@ changelog_rpc_server_destroy(xlator_t *this, rpcsvc_t *rpc, char *sockfile, rpcsvc_listener_t *listener = NULL; rpcsvc_listener_t *next = NULL; struct rpcsvc_program *prog = NULL; + rpc_transport_t *trans = NULL; + + if (!rpc) + return; while (*progs) { prog = *progs; @@ -269,22 +273,25 @@ changelog_rpc_server_destroy(xlator_t *this, rpcsvc_t *rpc, char *sockfile, list_for_each_entry_safe(listener, next, &rpc->listeners, list) { - rpcsvc_listener_destroy(listener); + if (listener->trans) { + trans = listener->trans; + rpc_transport_disconnect(trans, _gf_false); + } } (void)rpcsvc_unregister_notify(rpc, fn, this); - sys_unlink(sockfile); - if (rpc->rxpool) { - mem_pool_destroy(rpc->rxpool); - rpc->rxpool = NULL; - } /* TODO Avoid freeing rpc object in case of brick multiplex after freeing rpc object svc->rpclock corrupted and it takes more time to detach a brick */ - if (!this->cleanup_starting) + if (!this->cleanup_starting) { + if (rpc->rxpool) { + mem_pool_destroy(rpc->rxpool); + rpc->rxpool = NULL; + } GF_FREE(rpc); + } } rpcsvc_t * @@ -301,24 +308,23 @@ changelog_rpc_server_init(xlator_t *this, char *sockfile, void *cbkdata, options = dict_new(); if (!options) - goto error_return; + return NULL; - ret = rpcsvc_transport_unix_options_build(&options, sockfile); + ret = rpcsvc_transport_unix_options_build(options, sockfile); if (ret) goto dealloc_dict; rpc = rpcsvc_init(this, this->ctx, options, 8); if (rpc == NULL) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_START_ERROR, - "failed to init rpc"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_RPC_START_ERROR, + NULL); goto dealloc_dict; } ret = rpcsvc_register_notify(rpc, fn, cbkdata); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_NOTIFY_REGISTER_FAILED, - "failed to register notify function"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_NOTIFY_REGISTER_FAILED, NULL); goto dealloc_rpc; } @@ -332,11 +338,10 @@ changelog_rpc_server_init(xlator_t *this, char *sockfile, void *cbkdata, prog = *progs; ret = rpcsvc_program_register(rpc, prog, _gf_false); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_PROGRAM_NAME_REG_FAILED, - "cannot register program " - "(name: %s, prognum: %d, pogver: %d)", - prog->progname, prog->prognum, prog->progver); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_PROGRAM_NAME_REG_FAILED, "name%s", + prog->progname, "prognum=%d", prog->prognum, "pogver=%d", + prog->progver, NULL); goto dealloc_rpc; } @@ -350,6 +355,5 @@ dealloc_rpc: GF_FREE(rpc); dealloc_dict: dict_unref(options); -error_return: return NULL; } diff --git a/xlators/features/changelog/src/changelog-rpc-common.h b/xlators/features/changelog/src/changelog-rpc-common.h index 2d3f06e60c0..4d9aa2c694b 100644 --- a/xlators/features/changelog/src/changelog-rpc-common.h +++ b/xlators/features/changelog/src/changelog-rpc-common.h @@ -13,8 +13,8 @@ #include "rpcsvc.h" #include "rpc-clnt.h" -#include "gf-event.h" -#include "call-stub.h" +#include <glusterfs/gf-event.h> +#include <glusterfs/call-stub.h> #include "changelog-xdr.h" #include "xdr-generic.h" diff --git a/xlators/features/changelog/src/changelog-rpc.c b/xlators/features/changelog/src/changelog-rpc.c index 828f85e8e45..440b88091a6 100644 --- a/xlators/features/changelog/src/changelog-rpc.c +++ b/xlators/features/changelog/src/changelog-rpc.c @@ -8,12 +8,12 @@ cases as published by the Free Software Foundation. */ -#include "syscall.h" +#include <glusterfs/syscall.h> #include "changelog-rpc.h" #include "changelog-mem-types.h" #include "changelog-ev-handle.h" -struct rpcsvc_program *changelog_programs[]; +static struct rpcsvc_program *changelog_programs[]; static void changelog_cleanup_dispatchers(xlator_t *this, changelog_priv_t *priv, int count) @@ -43,9 +43,6 @@ changelog_cleanup_rpc_threads(xlator_t *this, changelog_priv_t *priv) /** terminate dispatcher thread(s) */ changelog_cleanup_dispatchers(this, priv, priv->nr_dispatchers); - /* TODO: what about pending and waiting connections? */ - changelog_ev_cleanup_connections(this, conn); - /* destroy locks */ ret = pthread_mutex_destroy(&conn->pending_lock); if (ret != 0) @@ -72,9 +69,6 @@ changelog_init_rpc_threads(xlator_t *this, changelog_priv_t *priv, rbuf_t *rbuf, int j = 0; int ret = 0; changelog_clnt_t *conn = NULL; - char thread_name[GF_THREAD_NAMEMAX] = { - 0, - }; conn = &priv->connections; @@ -114,9 +108,9 @@ changelog_init_rpc_threads(xlator_t *this, changelog_priv_t *priv, rbuf_t *rbuf, /* spawn dispatcher threads */ for (; j < nr_dispatchers; j++) { - snprintf(thread_name, sizeof(thread_name), "clogd%03hx", (j & 0x3ff)); ret = gf_thread_create(&priv->ev_dispatcher[j], NULL, - changelog_ev_dispatch, conn, thread_name); + changelog_ev_dispatch, conn, "clogd%03hx", + j & 0x3ff); if (ret != 0) { changelog_cleanup_dispatchers(this, priv, j); break; @@ -147,48 +141,146 @@ int changelog_rpcsvc_notify(rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, void *data) { + xlator_t *this = NULL; + rpc_transport_t *trans = NULL; + rpc_transport_t *xprt = NULL; + rpc_transport_t *xp_next = NULL; + changelog_priv_t *priv = NULL; + uint64_t listnercnt = 0; + uint64_t xprtcnt = 0; + uint64_t clntcnt = 0; + rpcsvc_listener_t *listener = NULL; + rpcsvc_listener_t *next = NULL; + gf_boolean_t listner_found = _gf_false; + socket_private_t *sockpriv = NULL; + + if (!xl || !data || !rpc) { + gf_msg_callingfn("changelog", GF_LOG_WARNING, 0, + CHANGELOG_MSG_RPCSVC_NOTIFY_FAILED, + "Calling rpc_notify without initializing"); + goto out; + } + + this = xl; + trans = data; + priv = this->private; + + if (!priv) { + gf_msg_callingfn("changelog", GF_LOG_WARNING, 0, + CHANGELOG_MSG_RPCSVC_NOTIFY_FAILED, + "Calling rpc_notify without priv initializing"); + goto out; + } + + if (event == RPCSVC_EVENT_ACCEPT) { + GF_ATOMIC_INC(priv->xprtcnt); + LOCK(&priv->lock); + { + list_add_tail(&trans->list, &priv->xprt_list); + } + UNLOCK(&priv->lock); + goto out; + } + + if (event == RPCSVC_EVENT_DISCONNECT) { + list_for_each_entry_safe(listener, next, &rpc->listeners, list) + { + if (listener && listener->trans) { + if (listener->trans == trans) { + listnercnt = GF_ATOMIC_DEC(priv->listnercnt); + listner_found = _gf_true; + rpcsvc_listener_destroy(listener); + } + } + } + + if (listnercnt > 0) { + goto out; + } + if (listner_found) { + LOCK(&priv->lock); + list_for_each_entry_safe(xprt, xp_next, &priv->xprt_list, list) + { + sockpriv = (socket_private_t *)(xprt->private); + gf_log("changelog", GF_LOG_INFO, + "Send disconnect" + " on socket %d", + sockpriv->sock); + rpc_transport_disconnect(xprt, _gf_false); + } + UNLOCK(&priv->lock); + goto out; + } + LOCK(&priv->lock); + { + list_del_init(&trans->list); + } + UNLOCK(&priv->lock); + + xprtcnt = GF_ATOMIC_DEC(priv->xprtcnt); + clntcnt = GF_ATOMIC_GET(priv->clntcnt); + if (!xprtcnt && !clntcnt) { + changelog_process_cleanup_event(this); + } + } + +out: return 0; } void +changelog_process_cleanup_event(xlator_t *this) +{ + gf_boolean_t cleanup_notify = _gf_false; + changelog_priv_t *priv = NULL; + char sockfile[UNIX_PATH_MAX] = { + 0, + }; + + if (!this) + return; + priv = this->private; + if (!priv) + return; + + LOCK(&priv->lock); + { + cleanup_notify = priv->notify_down; + priv->notify_down = _gf_true; + } + UNLOCK(&priv->lock); + + if (priv->victim && !cleanup_notify) { + default_notify(this, GF_EVENT_PARENT_DOWN, priv->victim); + + if (priv->rpc) { + /* sockfile path could have been saved to avoid this */ + CHANGELOG_MAKE_SOCKET_PATH(priv->changelog_brick, sockfile, + UNIX_PATH_MAX); + sys_unlink(sockfile); + (void)rpcsvc_unregister_notify(priv->rpc, changelog_rpcsvc_notify, + this); + if (priv->rpc->rxpool) { + mem_pool_destroy(priv->rpc->rxpool); + priv->rpc->rxpool = NULL; + } + GF_FREE(priv->rpc); + priv->rpc = NULL; + } + } +} + +void changelog_destroy_rpc_listner(xlator_t *this, changelog_priv_t *priv) { char sockfile[UNIX_PATH_MAX] = { 0, }; - changelog_clnt_t *c_clnt = &priv->connections; - changelog_rpc_clnt_t *crpc = NULL; - int nofconn = 0; /* sockfile path could have been saved to avoid this */ CHANGELOG_MAKE_SOCKET_PATH(priv->changelog_brick, sockfile, UNIX_PATH_MAX); changelog_rpc_server_destroy(this, priv->rpc, sockfile, changelog_rpcsvc_notify, changelog_programs); - - /* TODO Below approach is not perfect to wait for cleanup - all active connections without this code brick process - can be crash in case of brick multiplexing if any in-progress - request process on rpc by changelog xlator after - cleanup resources - */ - - if (c_clnt) { - do { - nofconn = 0; - LOCK(&c_clnt->active_lock); - list_for_each_entry(crpc, &c_clnt->active, list) { nofconn++; } - UNLOCK(&c_clnt->active_lock); - LOCK(&c_clnt->wait_lock); - list_for_each_entry(crpc, &c_clnt->waitq, list) { nofconn++; } - UNLOCK(&c_clnt->wait_lock); - pthread_mutex_lock(&c_clnt->pending_lock); - list_for_each_entry(crpc, &c_clnt->pending, list) { nofconn++; } - pthread_mutex_unlock(&c_clnt->pending_lock); - - } while (nofconn); /* Wait for all connection cleanup */ - } - - (void)changelog_cleanup_rpc_threads(this, priv); } rpcsvc_t * @@ -287,16 +379,15 @@ changelog_handle_probe(rpcsvc_request_t *req) this = req->trans->xl; if (this->cleanup_starting) { - gf_msg(this->name, GF_LOG_DEBUG, 0, CHANGELOG_MSG_HANDLE_PROBE_ERROR, - "cleanup_starting flag is already set for xl"); + gf_smsg(this->name, GF_LOG_DEBUG, 0, CHANGELOG_MSG_CLEANUP_ALREADY_SET, + NULL); return 0; } ret = xdr_to_generic(req->msg[0], &rpc_req, (xdrproc_t)xdr_changelog_probe_req); if (ret < 0) { - gf_msg("", GF_LOG_ERROR, 0, CHANGELOG_MSG_HANDLE_PROBE_ERROR, - "xdr decoding error"); + gf_smsg("", GF_LOG_ERROR, 0, CHANGELOG_MSG_HANDLE_PROBE_ERROR, NULL); req->rpc_err = GARBAGE_ARGS; goto handle_xdr_error; } @@ -328,13 +419,13 @@ submit_rpc: * RPC declarations */ -rpcsvc_actor_t changelog_svc_actors[CHANGELOG_RPC_PROC_MAX] = { +static rpcsvc_actor_t changelog_svc_actors[CHANGELOG_RPC_PROC_MAX] = { [CHANGELOG_RPC_PROBE_FILTER] = {"CHANGELOG PROBE FILTER", - CHANGELOG_RPC_PROBE_FILTER, - changelog_handle_probe, NULL, 0, DRC_NA}, + changelog_handle_probe, NULL, + CHANGELOG_RPC_PROBE_FILTER, DRC_NA, 0}, }; -struct rpcsvc_program changelog_svc_prog = { +static struct rpcsvc_program changelog_svc_prog = { .progname = CHANGELOG_RPC_PROGNAME, .prognum = CHANGELOG_RPC_PROGNUM, .progver = CHANGELOG_RPC_PROGVER, @@ -343,7 +434,7 @@ struct rpcsvc_program changelog_svc_prog = { .synctask = _gf_true, }; -struct rpcsvc_program *changelog_programs[] = { +static struct rpcsvc_program *changelog_programs[] = { &changelog_svc_prog, NULL, }; diff --git a/xlators/features/changelog/src/changelog-rpc.h b/xlators/features/changelog/src/changelog-rpc.h index 8002cea5091..b1707565249 100644 --- a/xlators/features/changelog/src/changelog-rpc.h +++ b/xlators/features/changelog/src/changelog-rpc.h @@ -11,7 +11,7 @@ #ifndef __CHANGELOG_RPC_H #define __CHANGELOG_RPC_H -#include "xlator.h" +#include <glusterfs/xlator.h> #include "changelog-helpers.h" /* one time */ diff --git a/xlators/features/changelog/src/changelog-rt.c b/xlators/features/changelog/src/changelog-rt.c index 968c76b8b20..841545ae359 100644 --- a/xlators/features/changelog/src/changelog-rt.c +++ b/xlators/features/changelog/src/changelog-rt.c @@ -8,9 +8,9 @@ cases as published by the Free Software Foundation. */ -#include "xlator.h" -#include "defaults.h" -#include "logging.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/logging.h> #include "changelog-rt.h" #include "changelog-mem-types.h" diff --git a/xlators/features/changelog/src/changelog-rt.h b/xlators/features/changelog/src/changelog-rt.h index df0d5b03487..28b9827d85b 100644 --- a/xlators/features/changelog/src/changelog-rt.h +++ b/xlators/features/changelog/src/changelog-rt.h @@ -11,8 +11,8 @@ #ifndef _CHANGELOG_RT_H #define _CHANGELOG_RT_H -#include "locking.h" -#include "timer.h" +#include <glusterfs/locking.h> +#include <glusterfs/timer.h> #include "pthread.h" #include "changelog-helpers.h" diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c index 35a523316ed..6a6e5af859e 100644 --- a/xlators/features/changelog/src/changelog.c +++ b/xlators/features/changelog/src/changelog.c @@ -8,11 +8,11 @@ cases as published by the Free Software Foundation. */ -#include "xlator.h" -#include "defaults.h" -#include "syscall.h" -#include "logging.h" -#include "iobuf.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/syscall.h> +#include <glusterfs/logging.h> +#include <glusterfs/iobuf.h> #include "changelog-rt.h" @@ -34,6 +34,12 @@ static struct changelog_bootstrap cb_bootstrap[] = { }, }; +static int +changelog_init_rpc(xlator_t *this, changelog_priv_t *priv); + +static int +changelog_init(xlator_t *this, changelog_priv_t *priv); + /* Entry operations - TYPE III */ /** @@ -149,9 +155,8 @@ changelog_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflags, goto out; } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", - "fop=rmdir", NULL); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, + CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=rmdir", NULL); chlog_barrier_dequeue_all(this, &queue); } @@ -298,9 +303,8 @@ changelog_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflags, goto out; } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", - "fop=unlink", NULL); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, + CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=unlink", NULL); chlog_barrier_dequeue_all(this, &queue); } @@ -418,9 +422,8 @@ changelog_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, goto out; } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", - "fop=rename", NULL); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, + CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=rename", NULL); chlog_barrier_dequeue_all(this, &queue); } /* changelog barrier */ @@ -531,8 +534,7 @@ changelog_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=link", NULL); chlog_barrier_dequeue_all(this, &queue); } @@ -660,9 +662,8 @@ changelog_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", - "fop=mkdir", NULL); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, + CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=mkdir", NULL); chlog_barrier_dequeue_all(this, &queue); } @@ -782,9 +783,8 @@ changelog_symlink(call_frame_t *frame, xlator_t *this, const char *linkname, } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", - "fop=symlink", NULL); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, + CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=symlink", NULL); chlog_barrier_dequeue_all(this, &queue); } @@ -929,9 +929,8 @@ changelog_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", - "fop=mknod", NULL); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, + CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=mknod", NULL); chlog_barrier_dequeue_all(this, &queue); } @@ -972,8 +971,8 @@ changelog_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, CHANGELOG_OP_TYPE_RELEASE)) { ret = fd_ctx_set(fd, this, (uint64_t)(long)0x1); if (ret) - gf_msg(this->name, GF_LOG_WARNING, 0, CHANGELOG_MSG_SET_FD_CONTEXT, - "could not set fd context (for release cbk)"); + gf_smsg(this->name, GF_LOG_WARNING, 0, CHANGELOG_MSG_SET_FD_CONTEXT, + NULL); } changelog_update(this, priv, local, CHANGELOG_TYPE_ENTRY); @@ -1083,9 +1082,8 @@ changelog_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, } if (barrier_enabled && !stub) { - gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Failed to barrier FOPs, disabling changelog barrier", - "fop=create", NULL); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, + CHANGELOG_MSG_BARRIER_FOP_FAILED, "fop=create", NULL); chlog_barrier_dequeue_all(this, &queue); } @@ -1388,9 +1386,6 @@ changelog_handle_virtual_xattr(call_frame_t *frame, xlator_t *this, loc_t *loc, ret = changelog_fill_entry_buf(frame, this, loc, &local); if (ret) { gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_ENTRY_BUF_INFO, - "Entry cannot be" - " captured for gfid, Capturing DATA" - " entry.", "gfid=%s", uuid_utoa(loc->inode->gfid), NULL); goto unwind; } @@ -1806,8 +1801,8 @@ changelog_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, CHANGELOG_OP_TYPE_RELEASE)) { ret = fd_ctx_set(fd, this, (uint64_t)(long)0x1); if (ret) - gf_msg(this->name, GF_LOG_WARNING, 0, CHANGELOG_MSG_SET_FD_CONTEXT, - "could not set fd context (for release cbk)"); + gf_smsg(this->name, GF_LOG_WARNING, 0, CHANGELOG_MSG_SET_FD_CONTEXT, + NULL); } unwind: @@ -2004,6 +1999,15 @@ notify(xlator_t *this, int event, void *data, ...) struct list_head queue = { 0, }; + uint64_t xprtcnt = 0; + uint64_t clntcnt = 0; + changelog_clnt_t *conn = NULL; + gf_boolean_t cleanup_notify = _gf_false; + char sockfile[UNIX_PATH_MAX] = { + 0, + }; + rpcsvc_listener_t *listener = NULL; + rpcsvc_listener_t *next = NULL; INIT_LIST_HEAD(&queue); @@ -2011,6 +2015,50 @@ notify(xlator_t *this, int event, void *data, ...) if (!priv) goto out; + if (event == GF_EVENT_PARENT_DOWN) { + priv->victim = data; + gf_log(this->name, GF_LOG_INFO, + "cleanup changelog rpc connection of brick %s", + priv->victim->name); + + if (priv->rpc_active) { + this->cleanup_starting = 1; + changelog_destroy_rpc_listner(this, priv); + conn = &priv->connections; + if (conn) + changelog_ev_cleanup_connections(this, conn); + xprtcnt = GF_ATOMIC_GET(priv->xprtcnt); + clntcnt = GF_ATOMIC_GET(priv->clntcnt); + if (!xprtcnt && !clntcnt) { + LOCK(&priv->lock); + { + cleanup_notify = priv->notify_down; + priv->notify_down = _gf_true; + } + UNLOCK(&priv->lock); + if (priv->rpc) { + list_for_each_entry_safe(listener, next, + &priv->rpc->listeners, list) + { + if (listener->trans) { + rpc_transport_unref(listener->trans); + } + } + rpcsvc_destroy(priv->rpc); + priv->rpc = NULL; + } + CHANGELOG_MAKE_SOCKET_PATH(priv->changelog_brick, sockfile, + UNIX_PATH_MAX); + sys_unlink(sockfile); + if (!cleanup_notify) + default_notify(this, GF_EVENT_PARENT_DOWN, data); + } + } else { + default_notify(this, GF_EVENT_PARENT_DOWN, data); + } + goto out; + } + if (event == GF_EVENT_TRANSLATOR_OP) { dict = data; @@ -2018,15 +2066,15 @@ notify(xlator_t *this, int event, void *data, ...) switch (barrier) { case DICT_ERROR: - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_DICT_GET_FAILED, - "Barrier dict_get_str_boolean failed"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_DICT_GET_FAILED, "dict_get_str_boolean", + NULL); ret = -1; goto out; case BARRIER_OFF: - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BARRIER_INFO, - "Barrier off notification"); + gf_smsg(this->name, GF_LOG_INFO, 0, + CHANGELOG_MSG_BARRIER_STATE_NOTIFY, "off", NULL); CHANGELOG_NOT_ON_THEN_GOTO(priv, ret, out); LOCK(&priv->c_snap_lock); @@ -2043,10 +2091,8 @@ notify(xlator_t *this, int event, void *data, ...) UNLOCK(&priv->bflags.lock); if (ret == -1) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_BARRIER_ERROR, - "Received another barrier off" - " notification while already off"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_BARRIER_ERROR, NULL); goto out; } @@ -2064,13 +2110,11 @@ notify(xlator_t *this, int event, void *data, ...) */ if (ret == 0) { chlog_barrier_dequeue_all(this, &queue); - gf_msg(this->name, GF_LOG_INFO, 0, - CHANGELOG_MSG_BARRIER_INFO, - "Disabled changelog barrier"); + gf_smsg(this->name, GF_LOG_INFO, 0, + CHANGELOG_MSG_BARRIER_DISABLED, NULL); } else { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_BARRIER_ERROR, - "Changelog barrier already disabled"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_BARRIER_ALREADY_DISABLED, NULL); } LOCK(&priv->bflags.lock); @@ -2082,8 +2126,8 @@ notify(xlator_t *this, int event, void *data, ...) goto out; case BARRIER_ON: - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BARRIER_INFO, - "Barrier on notification"); + gf_smsg(this->name, GF_LOG_INFO, 0, + CHANGELOG_MSG_BARRIER_STATE_NOTIFY, "on", NULL); CHANGELOG_NOT_ON_THEN_GOTO(priv, ret, out); LOCK(&priv->c_snap_lock); @@ -2102,11 +2146,8 @@ notify(xlator_t *this, int event, void *data, ...) UNLOCK(&priv->bflags.lock); if (ret == -1) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_BARRIER_ERROR, - "Received another barrier on" - "notification when last one is" - "not served yet"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_BARRIER_ON_ERROR, NULL); goto out; } @@ -2129,14 +2170,14 @@ notify(xlator_t *this, int event, void *data, ...) goto out; } - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BARRIER_INFO, - "Enabled changelog barrier"); + gf_smsg(this->name, GF_LOG_INFO, 0, + CHANGELOG_MSG_BARRIER_ENABLE, NULL); ret = changelog_barrier_notify(priv, buf); if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_WRITE_FAILED, - "Explicit roll over: write failed"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_WRITE_FAILED, "Explicit roll over", + NULL); changelog_barrier_cleanup(this, priv, &queue); ret = -1; goto out; @@ -2160,21 +2201,20 @@ notify(xlator_t *this, int event, void *data, ...) } ret1 = pthread_mutex_unlock(&priv->bn.bnotify_mutex); CHANGELOG_PTHREAD_ERROR_HANDLE_1(ret1, out, bclean_req); - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_BNOTIFY_INFO, - "Woke up: bnotify conditional wait"); + gf_smsg(this->name, GF_LOG_INFO, 0, + CHANGELOG_MSG_BNOTIFY_COND_INFO, NULL); goto out; case DICT_DEFAULT: - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_DICT_GET_FAILED, "barrier key not found"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + CHANGELOG_MSG_BARRIER_KEY_NOT_FOUND, NULL); ret = -1; goto out; default: - gf_msg(this->name, GF_LOG_ERROR, EINVAL, - CHANGELOG_MSG_DICT_GET_FAILED, - "Something went bad in dict_get_str_boolean"); + gf_smsg(this->name, GF_LOG_ERROR, EINVAL, + CHANGELOG_MSG_ERROR_IN_DICT_GET, NULL); ret = -1; goto out; } @@ -2200,9 +2240,8 @@ mem_acct_init(xlator_t *this) ret = xlator_mem_acct_init(this, gf_changelog_mt_end + 1); if (ret != 0) { - gf_msg(this->name, GF_LOG_WARNING, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "Memory accounting" - " init failed"); + gf_smsg(this->name, GF_LOG_WARNING, ENOMEM, + CHANGELOG_MSG_MEMORY_INIT_FAILED, NULL); return ret; } @@ -2213,23 +2252,11 @@ static int changelog_init(xlator_t *this, changelog_priv_t *priv) { int i = 0; - int ret = -1; - struct timeval tv = { - 0, - }; + int ret = 0; changelog_log_data_t cld = { 0, }; - ret = gettimeofday(&tv, NULL); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_GET_TIME_OP_FAILED, "gettimeofday() failure"); - goto out; - } - - priv->slice.tv_start = tv; - priv->maps[CHANGELOG_TYPE_DATA] = "D "; priv->maps[CHANGELOG_TYPE_METADATA] = "M "; priv->maps[CHANGELOG_TYPE_METADATA_XATTR] = "M "; @@ -2248,9 +2275,7 @@ changelog_init(xlator_t *this, changelog_priv_t *priv) * in case there was an encoding change. so... things are kept * simple here. */ - ret = changelog_fill_rollover_data(&cld, _gf_false); - if (ret) - goto out; + changelog_fill_rollover_data(&cld, _gf_false); ret = htime_open(this, priv, cld.cld_roll_time); /* call htime open with cld's rollover_time */ @@ -2288,8 +2313,8 @@ changelog_barrier_pthread_init(xlator_t *this, changelog_priv_t *priv) if ((ret = pthread_mutex_init(&priv->bn.bnotify_mutex, NULL)) != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, - "bnotify pthread_mutex_init failed", "ret=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, "name=bnotify", + "ret=%d", ret, NULL); ret = -1; goto out; } @@ -2297,8 +2322,8 @@ changelog_barrier_pthread_init(xlator_t *this, changelog_priv_t *priv) if ((ret = pthread_cond_init(&priv->bn.bnotify_cond, NULL)) != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_COND_INIT_FAILED, - "bnotify pthread_cond_init failed", "ret=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_COND_INIT_FAILED, "name=bnotify", + "ret=%d", ret, NULL); ret = -1; goto out; } @@ -2306,8 +2331,8 @@ changelog_barrier_pthread_init(xlator_t *this, changelog_priv_t *priv) if ((ret = pthread_mutex_init(&priv->dm.drain_black_mutex, NULL)) != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, - "drain_black pthread_mutex_init failed", "ret=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, "name=drain_black", + "ret=%d", ret, NULL); ret = -1; goto out; } @@ -2315,8 +2340,8 @@ changelog_barrier_pthread_init(xlator_t *this, changelog_priv_t *priv) if ((ret = pthread_cond_init(&priv->dm.drain_black_cond, NULL)) != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_COND_INIT_FAILED, - "drain_black pthread_cond_init failed", "ret=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_COND_INIT_FAILED, "name=drain_black", + "ret=%d", ret, NULL); ret = -1; goto out; } @@ -2324,8 +2349,8 @@ changelog_barrier_pthread_init(xlator_t *this, changelog_priv_t *priv) if ((ret = pthread_mutex_init(&priv->dm.drain_white_mutex, NULL)) != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, - "drain_white pthread_mutex_init failed", "ret=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, "name=drain_white", + "ret=%d", ret, NULL); ret = -1; goto out; } @@ -2333,8 +2358,8 @@ changelog_barrier_pthread_init(xlator_t *this, changelog_priv_t *priv) if ((ret = pthread_cond_init(&priv->dm.drain_white_cond, NULL)) != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, - CHANGELOG_MSG_PTHREAD_COND_INIT_FAILED, - "drain_white pthread_cond_init failed", "ret=%d", ret, NULL); + CHANGELOG_MSG_PTHREAD_COND_INIT_FAILED, "name=drain_white", + "ret=%d", ret, NULL); ret = -1; goto out; } @@ -2343,7 +2368,7 @@ changelog_barrier_pthread_init(xlator_t *this, changelog_priv_t *priv) if ((pthread_mutex_init(&priv->cr.lock, NULL)) != 0) { gf_smsg(this->name, GF_LOG_ERROR, errno, CHANGELOG_MSG_PTHREAD_MUTEX_INIT_FAILED, - "changelog_rollover lock init failed", "ret=%d", ret, NULL); + "name=changelog_rollover", "ret=%d", ret, NULL); ret = -1; goto out; } @@ -2394,6 +2419,22 @@ changelog_barrier_pthread_destroy(changelog_priv_t *priv) LOCK_DESTROY(&priv->bflags.lock); } +static void +changelog_cleanup_rpc(xlator_t *this, changelog_priv_t *priv) +{ + /* terminate rpc server */ + if (!this->cleanup_starting) + changelog_destroy_rpc_listner(this, priv); + + (void)changelog_cleanup_rpc_threads(this, priv); + /* cleanup rot buffs */ + rbuf_dtor(priv->rbuf); + + /* cleanup poller thread */ + if (priv->poller) + (void)changelog_thread_cleanup(this, priv->poller); +} + int reconfigure(xlator_t *this, dict_t *options) { @@ -2402,6 +2443,9 @@ reconfigure(xlator_t *this, dict_t *options) changelog_priv_t *priv = NULL; gf_boolean_t active_earlier = _gf_true; gf_boolean_t active_now = _gf_true; + gf_boolean_t rpc_active_earlier = _gf_true; + gf_boolean_t rpc_active_now = _gf_true; + gf_boolean_t iniate_rpc = _gf_false; changelog_time_slice_t *slice = NULL; changelog_log_data_t cld = { 0, @@ -2412,9 +2456,6 @@ reconfigure(xlator_t *this, dict_t *options) char csnap_dir[PATH_MAX] = { 0, }; - struct timeval tv = { - 0, - }; uint32_t timeout = 0; priv = this->private; @@ -2423,14 +2464,15 @@ reconfigure(xlator_t *this, dict_t *options) ret = -1; active_earlier = priv->active; + rpc_active_earlier = priv->rpc_active; /* first stop the rollover and the fsync thread */ changelog_cleanup_helper_threads(this, priv); GF_OPTION_RECONF("changelog-dir", tmp, options, str, out); if (!tmp) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_DIR_OPTIONS_NOT_SET, - "\"changelog-dir\" option is not set"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_DIR_OPTIONS_NOT_SET, + NULL); goto out; } @@ -2456,6 +2498,29 @@ reconfigure(xlator_t *this, dict_t *options) goto out; GF_OPTION_RECONF("changelog", active_now, options, bool, out); + GF_OPTION_RECONF("changelog-notification", rpc_active_now, options, bool, + out); + + /* If journalling is enabled, enable rpc notifications */ + if (active_now && !active_earlier) { + if (!rpc_active_earlier) + iniate_rpc = _gf_true; + } + + if (rpc_active_now && !rpc_active_earlier) { + iniate_rpc = _gf_true; + } + + /* TODO: Disable of changelog-notifications is not supported for now + * as there is no clean way of cleaning up of rpc resources + */ + + if (iniate_rpc) { + ret = changelog_init_rpc(this, priv); + if (ret) + goto out; + priv->rpc_active = _gf_true; + } /** * changelog_handle_change() handles changes that could possibly @@ -2482,9 +2547,7 @@ reconfigure(xlator_t *this, dict_t *options) out); if (active_now || active_earlier) { - ret = changelog_fill_rollover_data(&cld, !active_now); - if (ret) - goto out; + changelog_fill_rollover_data(&cld, !active_now); slice = &priv->slice; @@ -2501,15 +2564,9 @@ reconfigure(xlator_t *this, dict_t *options) if (active_now) { if (!active_earlier) { - gf_msg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_HTIME_INFO, - "Reconfigure: Changelog Enable"); - if (gettimeofday(&tv, NULL)) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CHANGELOG_MSG_HTIME_ERROR, "unable to fetch htime"); - ret = -1; - goto out; - } - htime_create(this, priv, tv.tv_sec); + gf_smsg(this->name, GF_LOG_INFO, 0, CHANGELOG_MSG_RECONFIGURE, + NULL); + htime_create(this, priv, gf_time()); } ret = changelog_spawn_helper_threads(this, priv); } @@ -2534,8 +2591,7 @@ changelog_freeup_options(xlator_t *this, changelog_priv_t *priv) ret = priv->cb->dtor(this, &priv->cd); if (ret) - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_FREEUP_FAILED, - "could not cleanup bootstrapper"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_FREEUP_FAILED, NULL); GF_FREE(priv->changelog_brick); GF_FREE(priv->changelog_dir); } @@ -2587,6 +2643,7 @@ changelog_init_options(xlator_t *this, changelog_priv_t *priv) goto dealloc_2; GF_OPTION_INIT("changelog", priv->active, bool, dealloc_2); + GF_OPTION_INIT("changelog-notification", priv->rpc_active, bool, dealloc_2); GF_OPTION_INIT("capture-del-path", priv->capture_del_path, bool, dealloc_2); GF_OPTION_INIT("op-mode", tmp, str, dealloc_2); @@ -2625,20 +2682,6 @@ error_return: return -1; } -static void -changelog_cleanup_rpc(xlator_t *this, changelog_priv_t *priv) -{ - /* terminate rpc server */ - changelog_destroy_rpc_listner(this, priv); - - /* cleanup rot buffs */ - rbuf_dtor(priv->rbuf); - - /* cleanup poller thread */ - if (priv->poller) - (void)changelog_thread_cleanup(this, priv->poller); -} - static int changelog_init_rpc(xlator_t *this, changelog_priv_t *priv) { @@ -2679,14 +2722,14 @@ init(xlator_t *this) GF_VALIDATE_OR_GOTO("changelog", this, error_return); if (!this->children || this->children->next) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_CHILD_MISCONFIGURED, - "translator needs a single subvolume"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_CHILD_MISCONFIGURED, + NULL); goto error_return; } if (!this->parents) { - gf_msg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_VOL_MISCONFIGURED, - "dangling volume. please check volfile"); + gf_smsg(this->name, GF_LOG_ERROR, 0, CHANGELOG_MSG_VOL_MISCONFIGURED, + NULL); goto error_return; } @@ -2696,13 +2739,18 @@ init(xlator_t *this) this->local_pool = mem_pool_new(changelog_local_t, 64); if (!this->local_pool) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, - "failed to create local memory pool"); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, CHANGELOG_MSG_NO_MEMORY, + NULL); goto cleanup_priv; } LOCK_INIT(&priv->lock); LOCK_INIT(&priv->c_snap_lock); + GF_ATOMIC_INIT(priv->listnercnt, 0); + GF_ATOMIC_INIT(priv->clntcnt, 0); + GF_ATOMIC_INIT(priv->xprtcnt, 0); + INIT_LIST_HEAD(&priv->xprt_list); + priv->htime_fd = -1; ret = changelog_init_options(this, priv); if (ret) @@ -2730,10 +2778,13 @@ init(xlator_t *this) INIT_LIST_HEAD(&priv->queue); priv->barrier_enabled = _gf_false; - /* RPC ball rolling.. */ - ret = changelog_init_rpc(this, priv); - if (ret) - goto cleanup_barrier; + if (priv->rpc_active || priv->active) { + /* RPC ball rolling.. */ + ret = changelog_init_rpc(this, priv); + if (ret) + goto cleanup_barrier; + priv->rpc_active = _gf_true; + } ret = changelog_init(this, priv); if (ret) @@ -2745,13 +2796,16 @@ init(xlator_t *this) return 0; cleanup_rpc: - changelog_cleanup_rpc(this, priv); + if (priv->rpc_active) { + changelog_cleanup_rpc(this, priv); + } cleanup_barrier: changelog_barrier_pthread_destroy(priv); cleanup_options: changelog_freeup_options(this, priv); cleanup_mempool: mem_pool_destroy(this->local_pool); + this->local_pool = NULL; cleanup_priv: GF_FREE(priv); error_return: @@ -2770,9 +2824,11 @@ fini(xlator_t *this) priv = this->private; if (priv) { - /* terminate RPC server/threads */ - changelog_cleanup_rpc(this, priv); - + if (priv->active || priv->rpc_active) { + /* terminate RPC server/threads */ + changelog_cleanup_rpc(this, priv); + GF_FREE(priv->ev_dispatcher); + } /* call barrier_disable to cancel timer */ if (priv->barrier_enabled) __chlog_barrier_disable(this, &queue); @@ -2841,6 +2897,13 @@ struct volume_options options[] = { .flags = OPT_FLAG_SETTABLE, .level = OPT_STATUS_BASIC, .tags = {"journal", "georep", "glusterfind"}}, + {.key = {"changelog-notification"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "enable/disable changelog live notification", + .op_version = {3}, + .level = OPT_STATUS_BASIC, + .tags = {"bitrot", "georep"}}, {.key = {"changelog-brick"}, .type = GF_OPTION_TYPE_PATH, .description = "brick path to generate unique socket file name." @@ -2910,3 +2973,17 @@ struct volume_options options[] = { .tags = {"journal", "glusterfind"}}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "changelog", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/changetimerecorder/src/Makefile.am b/xlators/features/changetimerecorder/src/Makefile.am deleted file mode 100644 index 620017e3309..00000000000 --- a/xlators/features/changetimerecorder/src/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features - -# changetimerecorder can only get build when libgfdb is enabled -if BUILD_GFDB - xlator_LTLIBRARIES = changetimerecorder.la -endif - -changetimerecorder_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) - -changetimerecorder_la_SOURCES = changetimerecorder.c \ - ctr-helper.c ctr-xlator-ctx.c - -changetimerecorder_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la\ - $(top_builddir)/libglusterfs/src/gfdb/libgfdb.la - -noinst_HEADERS = ctr-messages.h changetimerecorder.h ctr_mem_types.h \ - ctr-helper.h ctr-xlator-ctx.h - -AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ - -I$(top_srcdir)/libglusterfs/src/gfdb \ - -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src \ - -DDATADIR=\"$(localstatedir)\" - -AM_CFLAGS = -Wall $(GF_CFLAGS) $(SQLITE_CFLAGS) - -CLEANFILES = diff --git a/xlators/features/changetimerecorder/src/changetimerecorder.c b/xlators/features/changetimerecorder/src/changetimerecorder.c deleted file mode 100644 index 04b89e5a540..00000000000 --- a/xlators/features/changetimerecorder/src/changetimerecorder.c +++ /dev/null @@ -1,2358 +0,0 @@ -/* - Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ -#include <ctype.h> -#include <sys/uio.h> - -#include "gfdb_sqlite3.h" -#include "ctr-helper.h" -#include "ctr-messages.h" -#include "syscall.h" - -#include "changetimerecorder.h" -#include "tier-ctr-interface.h" - -/*******************************inode forget***********************************/ -int -ctr_forget(xlator_t *this, inode_t *inode) -{ - fini_ctr_xlator_ctx(this, inode); - return 0; -} - -/************************** Look up heal **************************************/ -/* -Problem: The CTR xlator records file meta (heat/hardlinks) -into the data. This works fine for files which are created -after ctr xlator is switched ON. But for files which were -created before CTR xlator is ON, CTR xlator is not able to -record either of the meta i.e heat or hardlinks. Thus making -those files immune to promotions/demotions. - -Solution: The solution that is implemented in this patch is -do ctr-db heal of all those pre-existent files, using named lookup. -For this purpose we use the inode-xlator context variable option -in gluster. -The inode-xlator context variable for ctr xlator will have the -following, - a. A Lock for the context variable - b. A hardlink list: This list represents the successful looked - up hardlinks. -These are the scenarios when the hardlink list is updated: -1) Named-Lookup: Whenever a named lookup happens on a file, in the - wind path we copy all required hardlink and inode information to - ctr_db_record structure, which resides in the frame->local variable. - We don't update the database in wind. During the unwind, we read the - information from the ctr_db_record and , - Check if the inode context variable is created, if not we create it. - Check if the hard link is there in the hardlink list. - If its not there we add it to the list and send a update to the - database using libgfdb. - Please note: The database transaction can fail(and we ignore) as there - already might be a record in the db. This update to the db is to heal - if its not there. - If its there in the list we ignore it. -2) Inode Forget: Whenever an inode forget hits we clear the hardlink list in - the inode context variable and delete the inode context variable. - Please note: An inode forget may happen for two reason, - a. when the inode is delete. - b. the in-memory inode is evicted from the inode table due to cache limits. -3) create: whenever a create happens we create the inode context variable and - add the hardlink. The database updation is done as usual by ctr. -4) link: whenever a hardlink is created for the inode, we create the inode - context variable, if not present, and add the hardlink to the list. -5) unlink: whenever a unlink happens we delete the hardlink from the list. -6) mknod: same as create. -7) rename: whenever a rename happens we update the hardlink in list. if the - hardlink was not present for updation, we add the hardlink to the list. - -What is pending: -1) This solution will only work for named lookups. -2) We don't track afr-self-heal/dht-rebalancer traffic for healing. - -*/ - -/* This function does not write anything to the db, - * just created the local variable - * for the frame and sets values for the ctr_db_record */ -static int -ctr_lookup_wind(call_frame_t *frame, xlator_t *this, - gf_ctr_inode_context_t *ctr_inode_cx) -{ - int ret = -1; - gf_ctr_private_t *_priv = NULL; - gf_ctr_local_t *ctr_local = NULL; - - GF_ASSERT(frame); - GF_ASSERT(frame->root); - GF_ASSERT(this); - IS_CTR_INODE_CX_SANE(ctr_inode_cx); - - _priv = this->private; - GF_ASSERT(_priv); - - if (_priv->ctr_record_wind && ctr_inode_cx->ia_type != IA_IFDIR) { - frame->local = init_ctr_local_t(this); - if (!frame->local) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_CREATE_CTR_LOCAL_ERROR_WIND, - "WIND: Error while creating ctr local"); - goto out; - }; - ctr_local = frame->local; - /*Definitely no internal fops will reach here*/ - ctr_local->is_internal_fop = _gf_false; - /*Don't record counters*/ - CTR_DB_REC(ctr_local).do_record_counters = _gf_false; - /*Don't record time at all*/ - CTR_DB_REC(ctr_local).do_record_times = _gf_false; - - /* Copy gfid into db record*/ - gf_uuid_copy(CTR_DB_REC(ctr_local).gfid, *(ctr_inode_cx->gfid)); - - /* Set fop_path and fop_type, required by libgfdb to make - * decision while inserting the record */ - CTR_DB_REC(ctr_local).gfdb_fop_path = ctr_inode_cx->fop_path; - CTR_DB_REC(ctr_local).gfdb_fop_type = ctr_inode_cx->fop_type; - - /* Copy hard link info*/ - gf_uuid_copy(CTR_DB_REC(ctr_local).pargfid, - *((NEW_LINK_CX(ctr_inode_cx))->pargfid)); - if (snprintf(CTR_DB_REC(ctr_local).file_name, - sizeof(CTR_DB_REC(ctr_local).file_name), "%s", - NEW_LINK_CX(ctr_inode_cx)->basename) >= - sizeof(CTR_DB_REC(ctr_local).file_name)) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_CREATE_CTR_LOCAL_ERROR_WIND, - "WIND: Error copying filename of ctr local"); - goto out; - } - /* Since we are in lookup we can ignore errors while - * Inserting in the DB, because there may be many - * to write to the DB attempts for healing. - * We don't want to log all failed attempts and - * bloat the log*/ - ctr_local->gfdb_db_record.ignore_errors = _gf_true; - } - - ret = 0; - -out: - - if (ret) { - free_ctr_local(ctr_local); - frame->local = NULL; - } - - return ret; -} - -/* This function inserts the ctr_db_record populated by ctr_lookup_wind - * in to the db. It also destroys the frame->local created by ctr_lookup_wind */ -static int -ctr_lookup_unwind(call_frame_t *frame, xlator_t *this) -{ - int ret = -1; - gf_ctr_private_t *_priv = NULL; - gf_ctr_local_t *ctr_local = NULL; - - GF_ASSERT(frame); - GF_ASSERT(this); - - _priv = this->private; - GF_ASSERT(_priv); - - GF_ASSERT(_priv->_db_conn); - - ctr_local = frame->local; - - if (ctr_local && (ctr_local->ia_inode_type != IA_IFDIR)) { - ret = insert_record(_priv->_db_conn, &ctr_local->gfdb_db_record); - if (ret == -1) { - gf_msg(this->name, - _gfdb_log_level(GF_LOG_ERROR, - ctr_local->gfdb_db_record.ignore_errors), - 0, CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND, - "UNWIND: Error filling ctr local"); - goto out; - } - } - ret = 0; -out: - free_ctr_local(ctr_local); - frame->local = NULL; - return ret; -} - -/****************************************************************************** - * - * FOPS HANDLING BELOW - * - * ***************************************************************************/ - -/****************************LOOKUP********************************************/ - -int32_t -ctr_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *dict, struct iatt *postparent) -{ - int ret = -1; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - gf_ctr_local_t *ctr_local = NULL; - ctr_heal_ret_val_t ret_val = CTR_CTX_ERROR; - gf_boolean_t _is_heal_needed = _gf_false; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - - /* if the lookup failed lookup don't do anything*/ - if (op_ret == -1) { - gf_msg_trace(this->name, 0, "lookup failed with %s", - strerror(op_errno)); - goto out; - } - - /* Ignore directory lookups */ - if (inode->ia_type == IA_IFDIR) { - goto out; - } - - /* if frame local was not set by the ctr_lookup() - * so don't so anything*/ - if (!frame->local) { - goto out; - } - - /* if the lookup is for dht link donot record*/ - if (dht_is_linkfile(buf, dict)) { - gf_msg_trace(this->name, 0, - "Ignoring Lookup " - "for dht link file"); - goto out; - } - - ctr_local = frame->local; - /*Assign the proper inode type*/ - ctr_local->ia_inode_type = inode->ia_type; - - /* Copy gfid directly from inode */ - gf_uuid_copy(CTR_DB_REC(ctr_local).gfid, inode->gfid); - - /* Checking if gfid and parent gfid is valid */ - if (gf_uuid_is_null(CTR_DB_REC(ctr_local).gfid) || - gf_uuid_is_null(CTR_DB_REC(ctr_local).pargfid)) { - gf_msg_trace(this->name, 0, "Invalid GFID"); - goto out; - } - - /* if its a first entry - * then mark the ctr_record for create - * A create will attempt a file and a hard link created in the db*/ - ctr_xlator_ctx = get_ctr_xlator_ctx(this, inode); - if (!ctr_xlator_ctx) { - /* This marks inode heal */ - CTR_DB_REC(ctr_local).gfdb_fop_type = GFDB_FOP_CREATE_WRITE; - _is_heal_needed = _gf_true; - } - - /* Copy the correct gfid from resolved inode */ - gf_uuid_copy(CTR_DB_REC(ctr_local).gfid, inode->gfid); - - /* Add hard link to the list */ - ret_val = add_hard_link_ctx(frame, this, inode); - if (ret_val == CTR_CTX_ERROR) { - gf_msg_trace(this->name, 0, "Failed adding hardlink to list"); - goto out; - } - /* If inode needs healing then heal the hardlink also */ - else if (ret_val & CTR_TRY_INODE_HEAL) { - /* This marks inode heal */ - CTR_DB_REC(ctr_local).gfdb_fop_type = GFDB_FOP_CREATE_WRITE; - _is_heal_needed = _gf_true; - } - /* If hardlink needs healing */ - else if (ret_val & CTR_TRY_HARDLINK_HEAL) { - _is_heal_needed = _gf_true; - } - - /* If lookup heal needed */ - if (!_is_heal_needed) - goto out; - - /* FINALLY HEAL : Inserts the ctr_db_record populated by ctr_lookup_wind - * in to the db. It also destroys the frame->local - * created by ctr_lookup_wind */ - ret = ctr_lookup_unwind(frame, this); - if (ret) { - gf_msg_trace(this->name, 0, "Failed healing/inserting link"); - } - -out: - free_ctr_local((gf_ctr_local_t *)frame->local); - frame->local = NULL; - - STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, buf, dict, - postparent); - - return 0; -} - -int32_t -ctr_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) -{ - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - gf_ctr_link_context_t ctr_link_cx; - gf_ctr_link_context_t *_link_cx = &ctr_link_cx; - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - GF_ASSERT(frame); - GF_ASSERT(frame->root); - - /* Don't handle nameless lookups*/ - if (!loc->parent || !loc->name) - goto out; - - /*fill ctr link context*/ - FILL_CTR_LINK_CX(_link_cx, loc->parent->gfid, loc->name, out); - - /* Fill ctr inode context*/ - /* IA_IFREG : We assume its a file in the wind - * but in the unwind we are sure what the inode is a file - * or directory - * gfid: we are just filling loc->gfid which is not correct. - * In unwind we fill the correct gfid for successful lookup*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, IA_IFREG, loc->gfid, _link_cx, NULL, - GFDB_FOP_DENTRY_WRITE, GFDB_FOP_WIND); - - /* Create the frame->local and populate ctr_db_record - * No writing to the db yet */ - ret = ctr_lookup_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_LINK_WIND_FAILED, - "Failed to insert link wind"); - } - -out: - STACK_WIND(frame, ctr_lookup_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, loc, xdata); - return 0; -} - -/****************************WRITEV********************************************/ -int32_t -ctr_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, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_WRITEV_UNWIND_FAILED, - "Failed to insert writev unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(writev, frame, op_ret, op_errno, prebuf, postbuf, - xdata); - - return 0; -} - -int32_t -ctr_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, - int32_t count, off_t off, uint32_t flags, struct iobref *iobref, - dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, fd->inode->ia_type, fd->inode->gfid, NULL, - NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_WRITEV_WIND_FAILED, - "Failed to insert writev wind"); - } - -out: - STACK_WIND(frame, ctr_writev_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->writev, fd, vector, count, off, flags, - iobref, xdata); - - return 0; -} - -/******************************setattr*****************************************/ - -int32_t -ctr_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *preop_stbuf, - struct iatt *postop_stbuf, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_SETATTR_UNWIND_FAILED, - "Failed to insert setattr unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(setattr, frame, op_ret, op_errno, preop_stbuf, - postop_stbuf, xdata); - - return 0; -} - -int32_t -ctr_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf, - int32_t valid, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, loc->inode->ia_type, loc->inode->gfid, - NULL, NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_SETATTR_WIND_FAILED, - "Failed to insert setattr wind"); - } -out: - - STACK_WIND(frame, ctr_setattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setattr, loc, stbuf, valid, xdata); - - return 0; -} - -/*************************** fsetattr ***************************************/ -int32_t -ctr_fsetattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *preop_stbuf, - struct iatt *postop_stbuf, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_SETATTR_UNWIND_FAILED, - "Failed to insert fsetattr unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(fsetattr, frame, op_ret, op_errno, preop_stbuf, - postop_stbuf, xdata); - - return 0; -} - -int32_t -ctr_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, - int32_t valid, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, fd->inode->ia_type, fd->inode->gfid, NULL, - NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_SETATTR_WIND_FAILED, - "Failed to insert fsetattr wind"); - } -out: - STACK_WIND(frame, ctr_fsetattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetattr, fd, stbuf, valid, xdata); - - return 0; -} -/****************************fremovexattr************************************/ - -int32_t -ctr_fremovexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_FREMOVEXATTR_UNWIND_FAILED, - "Failed to insert fremovexattr unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(fremovexattr, frame, op_ret, op_errno, xdata); - - return 0; -} - -int32_t -ctr_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, fd->inode->ia_type, fd->inode->gfid, NULL, - NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_FREMOVEXATTR_WIND_FAILED, - "Failed to insert fremovexattr wind"); - } - -out: - STACK_WIND(frame, ctr_fremovexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); - return 0; -} - -/****************************removexattr*************************************/ - -int32_t -ctr_removexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_REMOVEXATTR_UNWIND_FAILED, - "Failed to insert removexattr unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(removexattr, frame, op_ret, op_errno, xdata); - - return 0; -} - -int32_t -ctr_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, loc->inode->ia_type, loc->inode->gfid, - NULL, NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_REMOVEXATTR_WIND_FAILED, - "Failed to insert removexattr wind"); - } - -out: - STACK_WIND(frame, ctr_removexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); - return 0; -} - -/****************************truncate****************************************/ - -int32_t -ctr_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, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_TRUNCATE_UNWIND_FAILED, - "Failed to insert truncate unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(truncate, frame, op_ret, op_errno, prebuf, postbuf, - xdata); - - return 0; -} - -int32_t -ctr_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, - dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, loc->inode->ia_type, loc->inode->gfid, - NULL, NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_TRUNCATE_WIND_FAILED, - "Failed to insert truncate wind"); - } -out: - STACK_WIND(frame, ctr_truncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); - return 0; -} - -/****************************ftruncate***************************************/ - -int32_t -ctr_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, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_FTRUNCATE_UNWIND_FAILED, - "Failed to insert ftruncate unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(ftruncate, frame, op_ret, op_errno, prebuf, postbuf, - xdata); - - return 0; -} - -int32_t -ctr_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, - dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, fd->inode->ia_type, fd->inode->gfid, NULL, - NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_FTRUNCATE_WIND_FAILED, - "Failed to insert ftruncate wind"); - } - -out: - STACK_WIND(frame, ctr_ftruncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); - return 0; -} - -/****************************rename******************************************/ -int32_t -ctr_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, - dict_t *xdata) -{ - int ret = -1; - uint32_t remaining_links = -1; - gf_ctr_local_t *ctr_local = NULL; - gfdb_fop_type_t fop_type = GFDB_FOP_INVALID_OP; - gfdb_fop_path_t fop_path = GFDB_FOP_INVALID; - - GF_ASSERT(frame); - GF_ASSERT(this); - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_DENTRY_WRITE, - GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_RENAME_UNWIND_FAILED, - "Failed to insert rename unwind"); - goto out; - } - - if (!xdata) - goto out; - /* - * - * Extracting GF_RESPONSE_LINK_COUNT_XDATA from POSIX Xlator - * This is only set when we are overwriting hardlinks. - * - * */ - ret = dict_get_uint32(xdata, GF_RESPONSE_LINK_COUNT_XDATA, - &remaining_links); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_GET_CTR_RESPONSE_LINK_COUNT_XDATA_FAILED, - "Failed to getting GF_RESPONSE_LINK_COUNT_XDATA"); - remaining_links = -1; - goto out; - } - - ctr_local = frame->local; - if (!ctr_local) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_NULL_LOCAL, - "ctr_local is NULL."); - goto out; - } - - /* This is not the only link */ - if (remaining_links > 1) { - fop_type = GFDB_FOP_DENTRY_WRITE; - fop_path = GFDB_FOP_UNDEL; - } - /* Last link that was deleted */ - else if (remaining_links == 1) { - fop_type = GFDB_FOP_DENTRY_WRITE; - fop_path = GFDB_FOP_UNDEL_ALL; - } else { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_RENAME_UNWIND_FAILED, - "Invalid link count from posix"); - goto out; - } - - ret = ctr_delete_hard_link_from_db( - this, CTR_DB_REC(ctr_local).old_gfid, CTR_DB_REC(ctr_local).pargfid, - CTR_DB_REC(ctr_local).file_name, fop_type, fop_path); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_UNLINK_UNWIND_FAILED, - "Failed to delete records of %s", - CTR_DB_REC(ctr_local).old_file_name); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(rename, frame, op_ret, op_errno, buf, preoldparent, - postoldparent, prenewparent, postnewparent, xdata); - - return 0; -} - -int32_t -ctr_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, - dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - gf_ctr_link_context_t new_link_cx, old_link_cx; - gf_ctr_link_context_t *_nlink_cx = &new_link_cx; - gf_ctr_link_context_t *_olink_cx = &old_link_cx; - int is_dict_created = 0; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - /*Fill old link context*/ - FILL_CTR_LINK_CX(_olink_cx, oldloc->pargfid, oldloc->name, out); - - /*Fill new link context*/ - FILL_CTR_LINK_CX(_nlink_cx, newloc->pargfid, newloc->name, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, oldloc->inode->ia_type, - oldloc->inode->gfid, _nlink_cx, _olink_cx, - GFDB_FOP_DENTRY_WRITE, GFDB_FOP_WIND); - - /* If the rename is a overwrite of hardlink - * rename ("file1", "file2") - * file1 is hardlink for gfid say 00000000-0000-0000-0000-00000000000A - * file2 is hardlink for gfid say 00000000-0000-0000-0000-00000000000B - * so we are saving file2 gfid in old_gfid so that we delete entries - * from the db during rename callback if the fop is successful - * */ - if (newloc->inode) { - /* This is the GFID from where the newloc hardlink will be - * unlinked */ - _inode_cx->old_gfid = &newloc->inode->gfid; - } - - /* Is a metatdata fop */ - _inode_cx->is_metadata_fop = _gf_true; - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_RENAME_WIND_FAILED, - "Failed to insert rename wind"); - } else { - /* We are doing updation of hard link in inode context in wind - * As we don't get the "inode" in the call back for rename */ - ret = update_hard_link_ctx(frame, this, oldloc->inode); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_UPDATE_HARDLINK_FAILED, - "Failed " - "updating hard link in ctr inode context"); - goto out; - } - - /* If the newloc has an inode. i.e acquiring hardlink of an - * exisitng file i.e overwritting a file. - * */ - if (newloc->inode) { - /* Getting the ctr inode context variable for - * inode whose hardlink will be acquired during - * the rename - * */ - ctr_xlator_ctx = get_ctr_xlator_ctx(this, newloc->inode); - if (!ctr_xlator_ctx) { - /* Since there is no ctr inode context - * so nothing more to do */ - ret = 0; - goto out; - } - - /* Deleting hardlink from context variable */ - ret = ctr_delete_hard_link(this, ctr_xlator_ctx, newloc->pargfid, - newloc->name); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_DELETE_HARDLINK_FAILED, - "Failed to delete hard link"); - goto out; - } - - /* Requesting for number of hardlinks on the newloc - * inode from POSIX. - * */ - is_dict_created = set_posix_link_request(this, &xdata); - if (is_dict_created == -1) { - ret = -1; - goto out; - } - } - } - -out: - STACK_WIND(frame, ctr_rename_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); - - if (is_dict_created == 1) { - dict_unref(xdata); - } - - return 0; -} - -/****************************unlink******************************************/ -int32_t -ctr_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, dict_t *xdata) -{ - int ret = -1; - uint32_t remaining_links = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - if (!xdata) - goto out; - - /* - * - * Extracting GF_RESPONSE_LINK_COUNT_XDATA from POSIX Xlator - * - * */ - ret = dict_get_uint32(xdata, GF_RESPONSE_LINK_COUNT_XDATA, - &remaining_links); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_GET_CTR_RESPONSE_LINK_COUNT_XDATA_FAILED, - "Failed to getting GF_RESPONSE_LINK_COUNT_XDATA"); - remaining_links = -1; - } - - /*This is not the only link*/ - if (remaining_links != 1) { - ret = ctr_insert_unwind(frame, this, GFDB_FOP_DENTRY_WRITE, - GFDB_FOP_UNDEL); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_UNLINK_UNWIND_FAILED, - "Failed to insert unlink unwind"); - } - } - /*Last link that was deleted*/ - else if (remaining_links == 1) { - ret = ctr_insert_unwind(frame, this, GFDB_FOP_DENTRY_WRITE, - GFDB_FOP_UNDEL_ALL); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_UNLINK_UNWIND_FAILED, - "Failed to insert unlink unwind"); - } - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(unlink, frame, op_ret, op_errno, preparent, postparent, - xdata); - - return 0; -} - -int32_t -ctr_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, - dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - gf_ctr_link_context_t ctr_link_cx; - gf_ctr_link_context_t *_link_cx = &ctr_link_cx; - gf_boolean_t is_xdata_created = _gf_false; - struct iatt dummy_stat = {0}; - - GF_ASSERT(frame); - - CTR_IS_DISABLED_THEN_GOTO(this, out); - - /*Fill link context*/ - FILL_CTR_LINK_CX(_link_cx, loc->pargfid, loc->name, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, loc->inode->ia_type, loc->inode->gfid, - _link_cx, NULL, GFDB_FOP_DENTRY_WRITE, - GFDB_FOP_WDEL); - - /*Internal FOP*/ - _inode_cx->is_internal_fop = is_internal_fop(frame, xdata); - - /* Is a metadata FOP */ - _inode_cx->is_metadata_fop = _gf_true; - - /* If its a internal FOP and dht link file donot record*/ - if (_inode_cx->is_internal_fop && dht_is_linkfile(&dummy_stat, xdata)) { - goto out; - } - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_UNLINK_UNWIND_FAILED, - "Failed to insert unlink wind"); - } else { - /* We are doing delete of hard link in inode context in wind - * As we don't get the "inode" in the call back for rename */ - ret = delete_hard_link_ctx(frame, this, loc->inode); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_DELETE_HARDLINK_FAILED, - "Failed " - "deleting hard link from ctr inode context"); - } - } - - /* - * - * Sending GF_REQUEST_LINK_COUNT_XDATA - * to POSIX Xlator to send link count in unwind path - * - * */ - /*create xdata if NULL*/ - if (!xdata) { - xdata = dict_new(); - is_xdata_created = (xdata) ? _gf_true : _gf_false; - } - if (!xdata) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_XDATA_NULL, - "xdata is NULL :Cannot send " - "GF_REQUEST_LINK_COUNT_XDATA to posix"); - goto out; - } - - ret = dict_set_int32(xdata, GF_REQUEST_LINK_COUNT_XDATA, 1); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_SET_CTR_RESPONSE_LINK_COUNT_XDATA_FAILED, - "Failed setting GF_REQUEST_LINK_COUNT_XDATA"); - if (is_xdata_created) { - dict_unref(xdata); - } - goto out; - } - -out: - STACK_WIND(frame, ctr_unlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); - - if (is_xdata_created) - dict_unref(xdata); - - return 0; -} - -/****************************fsync******************************************/ -int32_t -ctr_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, - dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_FSYNC_UNWIND_FAILED, - "Failed to insert fsync unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(fsync, frame, op_ret, op_errno, prebuf, postbuf, xdata); - - return 0; -} - -int32_t -ctr_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, - dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, fd->inode->ia_type, fd->inode->gfid, NULL, - NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_FSYNC_WIND_FAILED, - "Failed to insert fsync wind"); - } - -out: - STACK_WIND(frame, ctr_fsync_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsync, fd, flags, xdata); - return 0; -} - -/****************************setxattr****************************************/ - -int -ctr_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_FSYNC_UNWIND_FAILED, - "Failed to insert setxattr unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(setxattr, frame, op_ret, op_errno, xdata); - - return 0; -} - -int -ctr_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr, - int flags, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, loc->inode->ia_type, loc->inode->gfid, - NULL, NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_SETATTR_WIND_FAILED, - "Failed to insert setxattr wind"); - } - -out: - STACK_WIND(frame, ctr_setxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, loc, xattr, flags, xdata); - return 0; -} -/**************************** fsetxattr *************************************/ -int32_t -ctr_fsetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_WRITE, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_FSYNC_UNWIND_FAILED, - "Failed to insert fsetxattr unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(fsetxattr, frame, op_ret, op_errno, xdata); - - return 0; -} - -int32_t -ctr_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, - int32_t flags, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, fd->inode->ia_type, fd->inode->gfid, NULL, - NULL, GFDB_FOP_INODE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_SETATTR_WIND_FAILED, - "Failed to insert fsetxattr wind"); - } - -out: - STACK_WIND(frame, ctr_fsetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); - return 0; -} -/****************************mknod*******************************************/ - -int32_t -ctr_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, dict_t *xdata) -{ - int ret = -1; - ctr_heal_ret_val_t ret_val = CTR_CTX_ERROR; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - /* Add hard link to the list */ - ret_val = add_hard_link_ctx(frame, this, inode); - if (ret_val == CTR_CTX_ERROR) { - gf_msg_trace(this->name, 0, "Failed adding hard link"); - } - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_CREATE_WRITE, - GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_MKNOD_UNWIND_FAILED, - "Failed to insert mknod unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(mknod, frame, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); - - return 0; -} - -int -ctr_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, - dev_t rdev, mode_t umask, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - gf_ctr_link_context_t ctr_link_cx; - gf_ctr_link_context_t *_link_cx = &ctr_link_cx; - uuid_t gfid = { - 0, - }; - uuid_t *ptr_gfid = &gfid; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - GF_ASSERT(frame); - GF_ASSERT(frame->root); - - /*get gfid from xdata dict*/ - ret = dict_get_gfuuid(xdata, "gfid-req", &gfid); - if (ret) { - gf_msg_debug(this->name, 0, "failed to get gfid from dict"); - goto out; - } - - /*fill ctr link context*/ - FILL_CTR_LINK_CX(_link_cx, loc->pargfid, loc->name, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, loc->inode->ia_type, *ptr_gfid, _link_cx, - NULL, GFDB_FOP_CREATE_WRITE, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_MKNOD_WIND_FAILED, - "Failed to insert mknod wind"); - } - -out: - STACK_WIND(frame, ctr_mknod_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, xdata); - return 0; -} - -/****************************create******************************************/ -int -ctr_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, - int op_errno, fd_t *fd, inode_t *inode, struct iatt *stbuf, - struct iatt *preparent, struct iatt *postparent, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = add_hard_link_ctx(frame, this, inode); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_ADD_HARDLINK_FAILED, - "Failed adding hard link"); - } - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_CREATE_WRITE, - GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_CREATE_UNWIND_FAILED, - "Failed to insert create unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(create, frame, op_ret, op_errno, fd, inode, stbuf, - preparent, postparent, xdata); - - return 0; -} - -int -ctr_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, - mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - gf_ctr_link_context_t ctr_link_cx; - gf_ctr_link_context_t *_link_cx = &ctr_link_cx; - uuid_t gfid = { - 0, - }; - uuid_t *ptr_gfid = &gfid; - struct iatt dummy_stat = {0}; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - - GF_ASSERT(frame); - GF_ASSERT(frame->root); - - /*Get GFID from Xdata dict*/ - ret = dict_get_gfuuid(xdata, "gfid-req", &gfid); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_GET_GFID_FROM_DICT_FAILED, - "failed to get gfid from dict"); - goto out; - } - - /*fill ctr link context*/ - FILL_CTR_LINK_CX(_link_cx, loc->pargfid, loc->name, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, loc->inode->ia_type, *ptr_gfid, _link_cx, - NULL, GFDB_FOP_CREATE_WRITE, GFDB_FOP_WIND); - - /*Internal FOP*/ - _inode_cx->is_internal_fop = is_internal_fop(frame, xdata); - - /* If its a internal FOP and dht link file donot record*/ - if (_inode_cx->is_internal_fop && dht_is_linkfile(&dummy_stat, xdata)) { - goto out; - } - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, &ctr_inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_CREATE_WIND_FAILED, - "Failed to insert create wind"); - } -out: - STACK_WIND(frame, ctr_create_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, fd, - xdata); - return 0; -} - -/****************************link********************************************/ - -int -ctr_link_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, - int op_errno, inode_t *inode, struct iatt *stbuf, - struct iatt *preparent, struct iatt *postparent, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - /* Add hard link to the list */ - ret = add_hard_link_ctx(frame, this, inode); - if (ret) { - gf_msg_trace(this->name, 0, "Failed adding hard link"); - } - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_DENTRY_WRITE, - GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_CREATE_UNWIND_FAILED, - "Failed to insert create unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(link, frame, op_ret, op_errno, inode, stbuf, preparent, - postparent, xdata); - return 0; -} - -int -ctr_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, - dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - gf_ctr_link_context_t ctr_link_cx; - gf_ctr_link_context_t *_link_cx = &ctr_link_cx; - struct iatt dummy_stat = {0}; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - - GF_ASSERT(frame); - GF_ASSERT(frame->root); - - /*fill ctr link context*/ - FILL_CTR_LINK_CX(_link_cx, newloc->pargfid, newloc->name, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, oldloc->inode->ia_type, - oldloc->inode->gfid, _link_cx, NULL, - GFDB_FOP_DENTRY_WRITE, GFDB_FOP_WIND); - - /*Internal FOP*/ - _inode_cx->is_internal_fop = is_internal_fop(frame, xdata); - - /* Is a metadata fop */ - _inode_cx->is_metadata_fop = _gf_true; - - /* If its a internal FOP and dht link file donot record*/ - if (_inode_cx->is_internal_fop && dht_is_linkfile(&dummy_stat, xdata)) { - goto out; - } - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_LINK_WIND_FAILED, - "Failed to insert link wind"); - } - -out: - STACK_WIND(frame, ctr_link_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); - return 0; -} - -/******************************readv*****************************************/ -int -ctr_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, - int op_errno, struct iovec *vector, int count, struct iatt *stbuf, - struct iobref *iobref, dict_t *xdata) -{ - int ret = -1; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, out); - - ret = ctr_insert_unwind(frame, this, GFDB_FOP_INODE_READ, GFDB_FOP_UNWIND); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_CREATE_UNWIND_FAILED, - "Failed to insert create unwind"); - } - -out: - ctr_free_frame_local(frame); - - STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, vector, count, stbuf, - iobref, xdata); - return 0; -} - -int -ctr_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, - uint32_t flags, dict_t *xdata) -{ - int ret = -1; - gf_ctr_inode_context_t ctr_inode_cx; - gf_ctr_inode_context_t *_inode_cx = &ctr_inode_cx; - - CTR_IS_DISABLED_THEN_GOTO(this, out); - CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, xdata, out); - - /*Fill ctr inode context*/ - FILL_CTR_INODE_CONTEXT(_inode_cx, fd->inode->ia_type, fd->inode->gfid, NULL, - NULL, GFDB_FOP_INODE_READ, GFDB_FOP_WIND); - - /*record into the database*/ - ret = ctr_insert_wind(frame, this, _inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_READV_WIND_FAILED, - "Failed to insert readv wind"); - } - -out: - STACK_WIND(frame, ctr_readv_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readv, fd, size, off, flags, xdata); - return 0; -} - -/*******************************ctr_ipc****************************************/ - -/*This is the call back function per record/file from data base*/ -static int -ctr_db_query_callback(gfdb_query_record_t *gfdb_query_record, void *args) -{ - int ret = -1; - ctr_query_cbk_args_t *query_cbk_args = args; - - GF_VALIDATE_OR_GOTO("ctr", query_cbk_args, out); - - ret = gfdb_write_query_record(query_cbk_args->query_fd, gfdb_query_record); - if (ret) { - gf_msg("ctr", GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "Failed to write to query file"); - goto out; - } - - query_cbk_args->count++; - - ret = 0; -out: - return ret; -} - -/* This function does all the db queries related to tiering and - * generates/populates new/existing query file - * inputs: - * xlator_t *this : CTR Translator - * void *conn_node : Database connection - * char *query_file: the query file that needs to be updated - * gfdb_ipc_ctr_params_t *ipc_ctr_params: the query parameters - * Return: - * On success 0 - * On failure -1 - * */ -int -ctr_db_query(xlator_t *this, void *conn_node, char *query_file, - gfdb_ipc_ctr_params_t *ipc_ctr_params) -{ - int ret = -1; - ctr_query_cbk_args_t query_cbk_args = {0}; - - GF_VALIDATE_OR_GOTO("ctr", this, out); - GF_VALIDATE_OR_GOTO(this->name, conn_node, out); - GF_VALIDATE_OR_GOTO(this->name, query_file, out); - GF_VALIDATE_OR_GOTO(this->name, ipc_ctr_params, out); - - /*Query for eligible files from db*/ - query_cbk_args.query_fd = open(query_file, O_WRONLY | O_CREAT | O_APPEND, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (query_cbk_args.query_fd < 0) { - gf_msg(this->name, GF_LOG_ERROR, errno, CTR_MSG_FATAL_ERROR, - "Failed to open query file %s", query_file); - goto out; - } - if (!ipc_ctr_params->is_promote) { - if (ipc_ctr_params->emergency_demote) { - /* emergency demotion mode */ - ret = find_all(conn_node, ctr_db_query_callback, - (void *)&query_cbk_args, - ipc_ctr_params->query_limit); - } else { - if (ipc_ctr_params->write_freq_threshold == 0 && - ipc_ctr_params->read_freq_threshold == 0) { - ret = find_unchanged_for_time(conn_node, ctr_db_query_callback, - (void *)&query_cbk_args, - &ipc_ctr_params->time_stamp); - } else { - ret = find_unchanged_for_time_freq( - conn_node, ctr_db_query_callback, (void *)&query_cbk_args, - &ipc_ctr_params->time_stamp, - ipc_ctr_params->write_freq_threshold, - ipc_ctr_params->read_freq_threshold, _gf_false); - } - } - } else { - if (ipc_ctr_params->write_freq_threshold == 0 && - ipc_ctr_params->read_freq_threshold == 0) { - ret = find_recently_changed_files(conn_node, ctr_db_query_callback, - (void *)&query_cbk_args, - &ipc_ctr_params->time_stamp); - } else { - ret = find_recently_changed_files_freq( - conn_node, ctr_db_query_callback, (void *)&query_cbk_args, - &ipc_ctr_params->time_stamp, - ipc_ctr_params->write_freq_threshold, - ipc_ctr_params->read_freq_threshold, _gf_false); - } - } - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: query from db failed"); - goto out; - } - - ret = clear_files_heat(conn_node); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: Failed to clear db entries"); - goto out; - } - - ret = 0; -out: - - if (!ret) - ret = query_cbk_args.count; - - if (query_cbk_args.query_fd >= 0) { - sys_close(query_cbk_args.query_fd); - query_cbk_args.query_fd = -1; - } - - return ret; -} - -void * -ctr_compact_thread(void *args) -{ - int ret = -1; - void *db_conn = NULL; - - xlator_t *this = NULL; - gf_ctr_private_t *priv = NULL; - gf_boolean_t compact_active = _gf_false; - gf_boolean_t compact_mode_switched = _gf_false; - - this = (xlator_t *)args; - - GF_VALIDATE_OR_GOTO("ctr", this, out); - - priv = this->private; - - db_conn = priv->_db_conn; - compact_active = priv->compact_active; - compact_mode_switched = priv->compact_mode_switched; - - gf_msg("ctr-compact", GF_LOG_INFO, 0, CTR_MSG_SET, "Starting compaction"); - - ret = compact_db(db_conn, compact_active, compact_mode_switched); - - if (ret) { - gf_msg("ctr-compact", GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to perform the compaction"); - } - - ret = pthread_mutex_lock(&priv->compact_lock); - - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to acquire lock"); - goto out; - } - - /* We are done compaction on this brick. Set all flags to false */ - priv->compact_active = _gf_false; - priv->compact_mode_switched = _gf_false; - - ret = pthread_mutex_unlock(&priv->compact_lock); - - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to release lock"); - goto out; - } - -out: - return NULL; -} - -int -ctr_ipc_helper(xlator_t *this, dict_t *in_dict, dict_t *out_dict) -{ - int ret = -1; - char *ctr_ipc_ops = NULL; - gf_ctr_private_t *priv = NULL; - char *db_version = NULL; - char *db_param_key = NULL; - char *db_param = NULL; - char *query_file = NULL; - gfdb_ipc_ctr_params_t *ipc_ctr_params = NULL; - int result = 0; - pthread_t compact_thread; - - GF_VALIDATE_OR_GOTO("ctr", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); - priv = this->private; - GF_VALIDATE_OR_GOTO(this->name, priv->_db_conn, out); - GF_VALIDATE_OR_GOTO(this->name, in_dict, out); - GF_VALIDATE_OR_GOTO(this->name, out_dict, out); - - GET_DB_PARAM_FROM_DICT(this->name, in_dict, GFDB_IPC_CTR_KEY, ctr_ipc_ops, - out); - - /*if its a db clear operation */ - if (strncmp(ctr_ipc_ops, GFDB_IPC_CTR_CLEAR_OPS, - SLEN(GFDB_IPC_CTR_CLEAR_OPS)) == 0) { - ret = clear_files_heat(priv->_db_conn); - if (ret) - goto out; - - } /* if its a query operation, in which case its query + clear db*/ - else if (strncmp(ctr_ipc_ops, GFDB_IPC_CTR_QUERY_OPS, - SLEN(GFDB_IPC_CTR_QUERY_OPS)) == 0) { - ret = dict_get_str(in_dict, GFDB_IPC_CTR_GET_QFILE_PATH, &query_file); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed extracting query file path"); - goto out; - } - - ret = dict_get_bin(in_dict, GFDB_IPC_CTR_GET_QUERY_PARAMS, - (void *)&ipc_ctr_params); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed extracting query parameters"); - goto out; - } - - ret = ctr_db_query(this, priv->_db_conn, query_file, ipc_ctr_params); - - ret = dict_set_int32(out_dict, GFDB_IPC_CTR_RET_QUERY_COUNT, ret); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed setting query reply"); - goto out; - } - - } /* if its a query for db version */ - else if (strncmp(ctr_ipc_ops, GFDB_IPC_CTR_GET_DB_VERSION_OPS, - SLEN(GFDB_IPC_CTR_GET_DB_VERSION_OPS)) == 0) { - ret = get_db_version(priv->_db_conn, &db_version); - if (ret == -1 || !db_version) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed extracting db version "); - goto out; - } - - SET_DB_PARAM_TO_DICT(this->name, out_dict, GFDB_IPC_CTR_RET_DB_VERSION, - db_version, ret, error); - - } /* if its a query for a db setting */ - else if (strncmp(ctr_ipc_ops, GFDB_IPC_CTR_GET_DB_PARAM_OPS, - SLEN(GFDB_IPC_CTR_GET_DB_PARAM_OPS)) == 0) { - ret = dict_get_str(in_dict, GFDB_IPC_CTR_GET_DB_KEY, &db_param_key); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed extracting db param key"); - goto out; - } - - ret = get_db_params(priv->_db_conn, db_param_key, &db_param); - if (ret == -1 || !db_param) { - goto out; - } - - SET_DB_PARAM_TO_DICT(this->name, out_dict, db_param_key, db_param, ret, - error); - } /* if its an attempt to compact the database */ - else if (strncmp(ctr_ipc_ops, GFDB_IPC_CTR_SET_COMPACT_PRAGMA, - SLEN(GFDB_IPC_CTR_SET_COMPACT_PRAGMA)) == 0) { - ret = pthread_mutex_lock(&priv->compact_lock); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to acquire lock for compaction"); - goto out; - } - - if ((priv->compact_active || priv->compact_mode_switched)) { - /* Compaction in progress. LEAVE */ - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Compaction already in progress."); - pthread_mutex_unlock(&priv->compact_lock); - goto out; - } - /* At this point, we should be the only one on the brick */ - /* compacting */ - - /* Grab the arguments from the dictionary */ - ret = dict_get_int32(in_dict, "compact_active", &result); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to get compaction type"); - goto out; - } - - if (result) { - priv->compact_active = _gf_true; - } - - ret = dict_get_int32(in_dict, "compact_mode_switched", &result); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to see if compaction switched"); - goto out; - } - - if (result) { - priv->compact_mode_switched = _gf_true; - gf_msg("ctr-compact", GF_LOG_TRACE, 0, CTR_MSG_SET, - "Pre-thread: Compact mode switch is true"); - } else { - gf_msg("ctr-compact", GF_LOG_TRACE, 0, CTR_MSG_SET, - "Pre-thread: Compact mode switch is false"); - } - - ret = pthread_mutex_unlock(&priv->compact_lock); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to release lock for compaction"); - goto out; - } - - ret = gf_thread_create(&compact_thread, NULL, ctr_compact_thread, - (void *)this, "ctrcomp"); - - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed to spawn compaction thread"); - goto out; - } - - goto out; - } /* default case */ - else { - goto out; - } - - ret = 0; - goto out; -error: - GF_FREE(db_param_key); - GF_FREE(db_param); - GF_FREE(db_version); -out: - return ret; -} - -/* IPC Call from tier migrator to clear the heat on the DB */ -int32_t -ctr_ipc(call_frame_t *frame, xlator_t *this, int32_t op, dict_t *in_dict) -{ - int ret = -1; - gf_ctr_private_t *priv = NULL; - dict_t *out_dict = NULL; - - GF_ASSERT(this); - priv = this->private; - GF_ASSERT(priv); - GF_ASSERT(priv->_db_conn); - GF_VALIDATE_OR_GOTO(this->name, in_dict, wind); - - if (op != GF_IPC_TARGET_CTR) - goto wind; - - out_dict = dict_new(); - if (!out_dict) { - goto out; - } - - ret = ctr_ipc_helper(this, in_dict, out_dict); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_SET, - "Failed in ctr_ipc_helper"); - } -out: - - STACK_UNWIND_STRICT(ipc, frame, ret, 0, out_dict); - - if (out_dict) - dict_unref(out_dict); - - return 0; - -wind: - STACK_WIND(frame, default_ipc_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ipc, op, in_dict); - - return 0; -} - -/* Call to initialize db for ctr xlator while ctr is enabled */ -int32_t -initialize_ctr_resource(xlator_t *this, gf_ctr_private_t *priv) -{ - int ret_db = -1; - dict_t *params_dict = NULL; - - if (!priv) - goto error; - - /* For compaction */ - priv->compact_active = _gf_false; - priv->compact_mode_switched = _gf_false; - ret_db = pthread_mutex_init(&priv->compact_lock, NULL); - - if (ret_db) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: Failed initializing compaction mutex"); - goto error; - } - - params_dict = dict_new(); - if (!params_dict) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INIT_DB_PARAMS_FAILED, - "DB Params cannot initialized!"); - goto error; - } - - /*Extract db params options*/ - ret_db = extract_db_params(this, params_dict, priv->gfdb_db_type); - if (ret_db) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_EXTRACT_DB_PARAM_OPTIONS_FAILED, - "Failed extracting db params options"); - goto error; - } - - /*Create a memory pool for ctr xlator*/ - this->local_pool = mem_pool_new(gf_ctr_local_t, 64); - if (!this->local_pool) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_CREATE_LOCAL_MEMORY_POOL_FAILED, - "failed to create local memory pool"); - ret_db = -1; - goto error; - } - - /*Initialize Database Connection*/ - priv->_db_conn = init_db(params_dict, priv->gfdb_db_type); - if (!priv->_db_conn) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: Failed initializing data base"); - ret_db = -1; - goto error; - } - - ret_db = 0; - goto out; - -error: - if (this) - mem_pool_destroy(this->local_pool); - - if (priv) { - GF_FREE(priv->ctr_db_path); - } - GF_FREE(priv); - -out: - if (params_dict) - dict_unref(params_dict); - - return ret_db; -} - -/******************************************************************************/ -int -reconfigure(xlator_t *this, dict_t *options) -{ - char *temp_str = NULL; - int ret = 0; - gf_ctr_private_t *priv = NULL; - - priv = this->private; - - if (dict_get_str(options, "changetimerecorder.frequency", &temp_str)) { - gf_msg(this->name, GF_LOG_TRACE, 0, CTR_MSG_SET, "set"); - } - - GF_OPTION_RECONF("ctr-enabled", priv->enabled, options, bool, out); - if (!priv->enabled) { - gf_msg(GFDB_DATA_STORE, GF_LOG_INFO, 0, CTR_MSG_XLATOR_DISABLED, - "CTR Xlator is not enabled so skip ctr reconfigure"); - goto out; - } - - /* If ctr is enabled after skip init for ctr xlator then call - initialize_ctr_resource during reconfigure phase to allocate resources - for xlator - */ - if (priv->enabled && !priv->_db_conn) { - ret = initialize_ctr_resource(this, priv); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: Failed ctr initialize resource"); - goto out; - } - } - - GF_OPTION_RECONF("record-counters", priv->ctr_record_counter, options, bool, - out); - - GF_OPTION_RECONF("ctr-record-metadata-heat", priv->ctr_record_metadata_heat, - options, bool, out); - - GF_OPTION_RECONF("ctr_link_consistency", priv->ctr_link_consistency, - options, bool, out); - - GF_OPTION_RECONF("ctr_lookupheal_inode_timeout", - priv->ctr_lookupheal_inode_timeout, options, uint64, out); - - GF_OPTION_RECONF("ctr_lookupheal_link_timeout", - priv->ctr_lookupheal_link_timeout, options, uint64, out); - - GF_OPTION_RECONF("record-exit", priv->ctr_record_unwind, options, bool, - out); - - GF_OPTION_RECONF("record-entry", priv->ctr_record_wind, options, bool, out); - - /* If database is sqlite */ - if (priv->gfdb_db_type == GFDB_SQLITE3) { - /* AUTOCHECKPOINT */ - if (dict_get_str(options, GFDB_SQL_PARAM_WAL_AUTOCHECK, &temp_str) == - 0) { - ret = set_db_params(priv->_db_conn, "wal_autocheckpoint", temp_str); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_SET_VALUE_TO_SQL_PARAM_FAILED, - "Failed to set %s", GFDB_SQL_PARAM_WAL_AUTOCHECK); - } - } - - /* CACHE_SIZE */ - if (dict_get_str(options, GFDB_SQL_PARAM_CACHE_SIZE, &temp_str) == 0) { - ret = set_db_params(priv->_db_conn, "cache_size", temp_str); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_SET_VALUE_TO_SQL_PARAM_FAILED, - "Failed to set %s", GFDB_SQL_PARAM_CACHE_SIZE); - } - } - } - - ret = 0; - -out: - - return ret; -} - -/****************************init********************************************/ - -int32_t -init(xlator_t *this) -{ - gf_ctr_private_t *priv = NULL; - int ret_db = -1; - - if (!this) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: ctr this is not initialized"); - return -1; - } - - if (!this->children || this->children->next) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: ctr should have exactly one child"); - return -1; - } - - if (!this->parents) { - gf_msg(this->name, GF_LOG_WARNING, 0, CTR_MSG_DANGLING_VOLUME, - "dangling volume. check volfile "); - } - - priv = GF_CALLOC(1, sizeof(*priv), gf_ctr_mt_private_t); - if (!priv) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, CTR_MSG_CALLOC_FAILED, - "Calloc did not work!!!"); - return -1; - } - - /*Default values for the translator*/ - priv->ctr_record_wind = _gf_true; - priv->ctr_record_unwind = _gf_false; - priv->ctr_hot_brick = _gf_false; - priv->gfdb_db_type = GFDB_SQLITE3; - priv->gfdb_sync_type = GFDB_DB_SYNC; - priv->_db_conn = NULL; - priv->ctr_lookupheal_link_timeout = CTR_DEFAULT_HARDLINK_EXP_PERIOD; - priv->ctr_lookupheal_inode_timeout = CTR_DEFAULT_INODE_EXP_PERIOD; - - /*Extract ctr xlator options*/ - ret_db = extract_ctr_options(this, priv); - if (ret_db) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_EXTRACT_CTR_XLATOR_OPTIONS_FAILED, - "Failed extracting ctr xlator options"); - return -1; - } - - if (!priv->enabled) { - gf_msg(GFDB_DATA_STORE, GF_LOG_INFO, 0, CTR_MSG_XLATOR_DISABLED, - "CTR Xlator is not enabled so skip ctr init"); - goto out; - } - - ret_db = initialize_ctr_resource(this, priv); - if (ret_db) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_FATAL_ERROR, - "FATAL: Failed ctr initialize resource"); - return -1; - } - -out: - this->private = (void *)priv; - return 0; -} - -int -notify(xlator_t *this, int event, void *data, ...) -{ - gf_ctr_private_t *priv = NULL; - int ret = 0; - - priv = this->private; - - if (!priv) - goto out; - - ret = default_notify(this, event, data); - -out: - return ret; -} - -int32_t -mem_acct_init(xlator_t *this) -{ - int ret = -1; - - GF_VALIDATE_OR_GOTO("ctr", this, out); - - ret = xlator_mem_acct_init(this, gf_ctr_mt_end + 1); - - if (ret != 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_MEM_ACC_INIT_FAILED, - "Memory accounting init" - "failed"); - return ret; - } -out: - return ret; -} - -void -fini(xlator_t *this) -{ - gf_ctr_private_t *priv = NULL; - - priv = this->private; - - if (priv && priv->enabled) { - if (fini_db(priv->_db_conn)) { - gf_msg(this->name, GF_LOG_WARNING, 0, CTR_MSG_CLOSE_DB_CONN_FAILED, - "Failed closing " - "db connection"); - } - - if (priv->_db_conn) - priv->_db_conn = NULL; - - GF_FREE(priv->ctr_db_path); - if (pthread_mutex_destroy(&priv->compact_lock)) { - gf_msg(this->name, GF_LOG_WARNING, 0, CTR_MSG_CLOSE_DB_CONN_FAILED, - "Failed to " - "destroy the compaction mutex"); - } - } - GF_FREE(priv); - mem_pool_destroy(this->local_pool); - this->local_pool = NULL; - - return; -} - -struct xlator_fops fops = { - /*lookup*/ - .lookup = ctr_lookup, - /*write fops */ - .mknod = ctr_mknod, - .create = ctr_create, - .truncate = ctr_truncate, - .ftruncate = ctr_ftruncate, - .setxattr = ctr_setxattr, - .fsetxattr = ctr_fsetxattr, - .removexattr = ctr_removexattr, - .fremovexattr = ctr_fremovexattr, - .unlink = ctr_unlink, - .link = ctr_link, - .rename = ctr_rename, - .writev = ctr_writev, - .setattr = ctr_setattr, - .fsetattr = ctr_fsetattr, - /*read fops*/ - .readv = ctr_readv, - /* IPC call*/ - .ipc = ctr_ipc}; - -struct xlator_cbks cbks = {.forget = ctr_forget}; - -struct volume_options options[] = { - {.key = - { - "ctr-enabled", - }, - .type = GF_OPTION_TYPE_BOOL, - .value = {"on", "off"}, - .default_value = "off", - .description = "Enables the CTR", - .flags = OPT_FLAG_SETTABLE}, - {.key = {"record-entry"}, - .type = GF_OPTION_TYPE_BOOL, - .value = {"on", "off"}, - .default_value = "on"}, - {.key = {"record-exit"}, - .type = GF_OPTION_TYPE_BOOL, - .value = {"on", "off"}, - .default_value = "off"}, - {.key = {"record-counters"}, - .type = GF_OPTION_TYPE_BOOL, - .value = {"on", "off"}, - .default_value = "off", - .op_version = {GD_OP_VERSION_3_7_0}, - .flags = OPT_FLAG_SETTABLE, - .tags = {}}, - {.key = {"ctr-record-metadata-heat"}, - .type = GF_OPTION_TYPE_BOOL, - .value = {"on", "off"}, - .default_value = "off", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_0}, - .tags = {}}, - {.key = {"ctr_link_consistency"}, - .type = GF_OPTION_TYPE_BOOL, - .value = {"on", "off"}, - .default_value = "off", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_0}, - .tags = {}}, - {.key = {"ctr_lookupheal_link_timeout"}, - .type = GF_OPTION_TYPE_INT, - .default_value = "300", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_2}, - .tags = {}}, - {.key = {"ctr_lookupheal_inode_timeout"}, - .type = GF_OPTION_TYPE_INT, - .default_value = "300", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_2}, - .tags = {}}, - {.key = {"hot-brick"}, - .type = GF_OPTION_TYPE_BOOL, - .value = {"on", "off"}, - .default_value = "off"}, - {.key = {"db-type"}, - .type = GF_OPTION_TYPE_STR, - .value = {"hashfile", "rocksdb", "changelog", "sqlite3", "hyperdex"}, - .default_value = "sqlite3", - .op_version = {GD_OP_VERSION_3_7_0}, - .flags = OPT_FLAG_SETTABLE, - .tags = {}}, - {.key = {"db-sync"}, - .type = GF_OPTION_TYPE_STR, - .value = {"sync", "async"}, - .default_value = "sync"}, - {.key = {"db-path"}, .type = GF_OPTION_TYPE_PATH}, - {.key = {"db-name"}, .type = GF_OPTION_TYPE_STR}, - {.key = {GFDB_SQL_PARAM_SYNC}, - .type = GF_OPTION_TYPE_STR, - .value = {"off", "normal", "full"}, - .default_value = "normal"}, - {.key = {GFDB_SQL_PARAM_JOURNAL_MODE}, - .type = GF_OPTION_TYPE_STR, - .value = {"delete", "truncate", "persist", "memory", "wal", "off"}, - .default_value = "wal", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_0}, - .tags = {}}, - {.key = {GFDB_SQL_PARAM_AUTO_VACUUM}, - .type = GF_OPTION_TYPE_STR, - .value = {"off", "full", "incr"}, - .default_value = "off", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_0}, - .tags = {}}, - {.key = {GFDB_SQL_PARAM_WAL_AUTOCHECK}, - .type = GF_OPTION_TYPE_INT, - .default_value = "25000", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_0}, - .tags = {}}, - {.key = {GFDB_SQL_PARAM_CACHE_SIZE}, - .type = GF_OPTION_TYPE_INT, - .default_value = "12500", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_0}, - .tags = {}}, - {.key = {GFDB_SQL_PARAM_PAGE_SIZE}, - .type = GF_OPTION_TYPE_INT, - .default_value = "4096", - .flags = OPT_FLAG_SETTABLE, - .op_version = {GD_OP_VERSION_3_7_0}, - .tags = {}}, - {.key = {NULL}}, -}; diff --git a/xlators/features/changetimerecorder/src/changetimerecorder.h b/xlators/features/changetimerecorder/src/changetimerecorder.h deleted file mode 100644 index 2a8bbd18c5b..00000000000 --- a/xlators/features/changetimerecorder/src/changetimerecorder.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - Copyright (c) 2006-2015 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#ifndef __CTR_H -#define __CTR_H - -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" -#include "ctr_mem_types.h" -#include "ctr-helper.h" - -#endif /* __CTR_H */ diff --git a/xlators/features/changetimerecorder/src/ctr-helper.c b/xlators/features/changetimerecorder/src/ctr-helper.c deleted file mode 100644 index e1e65735cef..00000000000 --- a/xlators/features/changetimerecorder/src/ctr-helper.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#include "gfdb_sqlite3.h" -#include "ctr-helper.h" -#include "ctr-messages.h" - -/******************************************************************************* - * - * Fill unwind into db record - * - ******************************************************************************/ -int -fill_db_record_for_unwind(xlator_t *this, gf_ctr_local_t *ctr_local, - gfdb_fop_type_t fop_type, gfdb_fop_path_t fop_path) -{ - int ret = -1; - gfdb_time_t *ctr_uwtime = NULL; - gf_ctr_private_t *_priv = NULL; - - GF_ASSERT(this); - _priv = this->private; - GF_ASSERT(_priv); - - GF_ASSERT(ctr_local); - - /*If not unwind path error*/ - if (!isunwindpath(fop_path)) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_WRONG_FOP_PATH, - "Wrong fop_path. Should be unwind"); - goto out; - } - - ctr_uwtime = &CTR_DB_REC(ctr_local).gfdb_unwind_change_time; - CTR_DB_REC(ctr_local).gfdb_fop_path = fop_path; - CTR_DB_REC(ctr_local).gfdb_fop_type = fop_type; - - ret = gettimeofday(ctr_uwtime, NULL); - if (ret == -1) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CTR_MSG_FILL_UNWIND_TIME_REC_ERROR, - "Error " - "filling unwind time record %s", - strerror(errno)); - goto out; - } - - /* Special case i.e if its a tier rebalance - * + cold tier brick - * + its a create/mknod FOP - * we record unwind time as zero */ - if (ctr_local->client_pid == GF_CLIENT_PID_TIER_DEFRAG && - (!_priv->ctr_hot_brick) && isdentrycreatefop(fop_type)) { - memset(ctr_uwtime, 0, sizeof(*ctr_uwtime)); - } - ret = 0; -out: - return ret; -} - -/******************************************************************************* - * - * Fill wind into db record - * - ******************************************************************************/ -int -fill_db_record_for_wind(xlator_t *this, gf_ctr_local_t *ctr_local, - gf_ctr_inode_context_t *ctr_inode_cx) -{ - int ret = -1; - gfdb_time_t *ctr_wtime = NULL; - gf_ctr_private_t *_priv = NULL; - - GF_ASSERT(this); - _priv = this->private; - GF_ASSERT(_priv); - GF_ASSERT(ctr_local); - IS_CTR_INODE_CX_SANE(ctr_inode_cx); - - /*if not wind path error!*/ - if (!iswindpath(ctr_inode_cx->fop_path)) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_WRONG_FOP_PATH, - "Wrong fop_path. Should be wind"); - goto out; - } - - ctr_wtime = &CTR_DB_REC(ctr_local).gfdb_wind_change_time; - CTR_DB_REC(ctr_local).gfdb_fop_path = ctr_inode_cx->fop_path; - CTR_DB_REC(ctr_local).gfdb_fop_type = ctr_inode_cx->fop_type; - CTR_DB_REC(ctr_local).link_consistency = _priv->ctr_link_consistency; - - ret = gettimeofday(ctr_wtime, NULL); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, errno, - CTR_MSG_FILL_UNWIND_TIME_REC_ERROR, - "Error filling wind time record %s", strerror(errno)); - goto out; - } - - /* Special case i.e if its a tier rebalance - * + cold tier brick - * + its a create/mknod FOP - * we record wind time as zero */ - if (ctr_local->client_pid == GF_CLIENT_PID_TIER_DEFRAG && - (!_priv->ctr_hot_brick) && isdentrycreatefop(ctr_inode_cx->fop_type)) { - memset(ctr_wtime, 0, sizeof(*ctr_wtime)); - } - - /* Copy gfid into db record */ - gf_uuid_copy(CTR_DB_REC(ctr_local).gfid, *(ctr_inode_cx->gfid)); - - /* Copy older gfid if any */ - if (ctr_inode_cx->old_gfid && - (!gf_uuid_is_null(*(ctr_inode_cx->old_gfid)))) { - gf_uuid_copy(CTR_DB_REC(ctr_local).old_gfid, *(ctr_inode_cx->old_gfid)); - } - - /*Hard Links*/ - if (isdentryfop(ctr_inode_cx->fop_type)) { - /*new link fop*/ - if (NEW_LINK_CX(ctr_inode_cx)) { - gf_uuid_copy(CTR_DB_REC(ctr_local).pargfid, - *((NEW_LINK_CX(ctr_inode_cx))->pargfid)); - strcpy(CTR_DB_REC(ctr_local).file_name, - NEW_LINK_CX(ctr_inode_cx)->basename); - } - /*rename fop*/ - if (OLD_LINK_CX(ctr_inode_cx)) { - gf_uuid_copy(CTR_DB_REC(ctr_local).old_pargfid, - *((OLD_LINK_CX(ctr_inode_cx))->pargfid)); - strcpy(CTR_DB_REC(ctr_local).old_file_name, - OLD_LINK_CX(ctr_inode_cx)->basename); - } - } - - ret = 0; -out: - /*On error roll back and clean the record*/ - if (ret == -1) { - CLEAR_CTR_DB_RECORD(ctr_local); - } - return ret; -} - -/****************************************************************************** - * - * CTR xlator init related functions - * - * - * ****************************************************************************/ -static int -extract_sql_params(xlator_t *this, dict_t *params_dict) -{ - int ret = -1; - char *db_path = NULL; - char *db_name = NULL; - char *db_full_path = NULL; - - GF_ASSERT(this); - GF_ASSERT(params_dict); - - /*Extract the path of the db*/ - db_path = NULL; - GET_DB_PARAM_FROM_DICT_DEFAULT(this->name, this->options, "db-path", - db_path, "/var/run/gluster/"); - - /*Extract the name of the db*/ - db_name = NULL; - GET_DB_PARAM_FROM_DICT_DEFAULT(this->name, this->options, "db-name", - db_name, "gf_ctr_db.db"); - - /*Construct full path of the db*/ - ret = gf_asprintf(&db_full_path, "%s/%s", db_path, db_name); - if (ret < 0) { - gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, - CTR_MSG_CONSTRUCT_DB_PATH_FAILED, - "Construction of full db path failed!"); - goto out; - } - - /*Setting the SQL DB Path*/ - SET_DB_PARAM_TO_DICT(this->name, params_dict, GFDB_SQL_PARAM_DBPATH, - db_full_path, ret, out); - - /*Extract rest of the sql params*/ - ret = gfdb_set_sql_params(this->name, this->options, params_dict); - if (ret) { - gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, - CTR_MSG_SET_VALUE_TO_SQL_PARAM_FAILED, - "Failed setting values to sql param dict!"); - } - - ret = 0; - -out: - if (ret) - GF_FREE(db_full_path); - return ret; -} - -int -extract_db_params(xlator_t *this, dict_t *params_dict, gfdb_db_type_t db_type) -{ - int ret = -1; - - GF_ASSERT(this); - GF_ASSERT(params_dict); - - switch (db_type) { - case GFDB_SQLITE3: - ret = extract_sql_params(this, params_dict); - if (ret) - goto out; - break; - case GFDB_ROCKS_DB: - case GFDB_HYPERDEX: - case GFDB_HASH_FILE_STORE: - case GFDB_INVALID_DB: - case GFDB_DB_END: - goto out; - } - ret = 0; -out: - return ret; -} - -int -extract_ctr_options(xlator_t *this, gf_ctr_private_t *_priv) -{ - int ret = -1; - char *_val_str = NULL; - - GF_ASSERT(this); - GF_ASSERT(_priv); - - /*Checking if the CTR Translator is enabled. By default its disabled*/ - _priv->enabled = _gf_false; - GF_OPTION_INIT("ctr-enabled", _priv->enabled, bool, out); - if (!_priv->enabled) { - gf_msg(GFDB_DATA_STORE, GF_LOG_INFO, 0, CTR_MSG_XLATOR_DISABLED, - "CTR Xlator is disabled."); - ret = 0; - goto out; - } - - /*Extract db type*/ - GF_OPTION_INIT("db-type", _val_str, str, out); - _priv->gfdb_db_type = gf_string2gfdbdbtype(_val_str); - - /*Extract flag for record on wind*/ - GF_OPTION_INIT("record-entry", _priv->ctr_record_wind, bool, out); - - /*Extract flag for record on unwind*/ - GF_OPTION_INIT("record-exit", _priv->ctr_record_unwind, bool, out); - - /*Extract flag for record on counters*/ - GF_OPTION_INIT("record-counters", _priv->ctr_record_counter, bool, out); - - /* Extract flag for record metadata heat */ - GF_OPTION_INIT("ctr-record-metadata-heat", _priv->ctr_record_metadata_heat, - bool, out); - - /*Extract flag for link consistency*/ - GF_OPTION_INIT("ctr_link_consistency", _priv->ctr_link_consistency, bool, - out); - - /*Extract ctr_lookupheal_inode_timeout */ - GF_OPTION_INIT("ctr_lookupheal_inode_timeout", - _priv->ctr_lookupheal_inode_timeout, uint64, out); - - /*Extract ctr_lookupheal_link_timeout*/ - GF_OPTION_INIT("ctr_lookupheal_link_timeout", - _priv->ctr_lookupheal_link_timeout, uint64, out); - - /*Extract flag for hot tier brick*/ - GF_OPTION_INIT("hot-brick", _priv->ctr_hot_brick, bool, out); - - /*Extract flag for sync mode*/ - GF_OPTION_INIT("db-sync", _val_str, str, out); - _priv->gfdb_sync_type = gf_string2gfdbdbsync(_val_str); - - ret = 0; - -out: - return ret; -} diff --git a/xlators/features/changetimerecorder/src/ctr-helper.h b/xlators/features/changetimerecorder/src/ctr-helper.h deleted file mode 100644 index 3268c9d2fb9..00000000000 --- a/xlators/features/changetimerecorder/src/ctr-helper.h +++ /dev/null @@ -1,854 +0,0 @@ -/* - Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#ifndef __CTR_HELPER_H -#define __CTR_HELPER_H - -#include "xlator.h" -#include "ctr_mem_types.h" -#include "iatt.h" -#include "glusterfs.h" -#include "xlator.h" -#include "defaults.h" -#include "logging.h" -#include "common-utils.h" -#include <time.h> -#include <sys/time.h> -#include <pthread.h> - -#include "gfdb_data_store.h" -#include "ctr-xlator-ctx.h" -#include "ctr-messages.h" - -#define CTR_DEFAULT_HARDLINK_EXP_PERIOD 300 /* Five mins */ -#define CTR_DEFAULT_INODE_EXP_PERIOD 300 /* Five mins */ - -typedef struct ctr_query_cbk_args { - int query_fd; - int count; -} ctr_query_cbk_args_t; - -/*CTR Xlator Private structure*/ -typedef struct gf_ctr_private { - gf_boolean_t enabled; - char *ctr_db_path; - gf_boolean_t ctr_hot_brick; - gf_boolean_t ctr_record_wind; - gf_boolean_t ctr_record_unwind; - gf_boolean_t ctr_record_counter; - gf_boolean_t ctr_record_metadata_heat; - gf_boolean_t ctr_link_consistency; - gfdb_db_type_t gfdb_db_type; - gfdb_sync_type_t gfdb_sync_type; - gfdb_conn_node_t *_db_conn; - uint64_t ctr_lookupheal_link_timeout; - uint64_t ctr_lookupheal_inode_timeout; - gf_boolean_t compact_active; - gf_boolean_t compact_mode_switched; - pthread_mutex_t compact_lock; -} gf_ctr_private_t; - -/* - * gf_ctr_local_t is the ctr xlator local data structure that is stored in - * the call_frame of each FOP. - * - * gfdb_db_record: The gf_ctr_local contains a gfdb_db_record object, which is - * used by the insert_record() api from the libgfdb. The gfdb_db_record object - * will contain all the inode and hardlink(only for dentry fops: create, - * mknod,link, unlink, rename).The ctr_local is keep alive till the unwind - * call and will be release during the unwind. The same gfdb_db_record will - * used for the unwind insert_record() api, to record unwind in the database. - * - * ia_inode_type in gf_ctr_local will tell the type of the inode. This is - * important for during the unwind path. As we will not have the inode during - * the unwind path. We would have include this in the gfdb_db_record itself - * but currently we record only file inode information. - * - * is_internal_fop in gf_ctr_local will tell us if this is a internal fop and - * take special/no action. We don't record change/access times or increement - * heat counter for internal fops from rebalancer. - * */ -typedef struct gf_ctr_local { - gfdb_db_record_t gfdb_db_record; - ia_type_t ia_inode_type; - gf_boolean_t is_internal_fop; - gf_special_pid_t client_pid; -} gf_ctr_local_t; -/* - * Easy access of gfdb_db_record of ctr_local - * */ -#define CTR_DB_REC(ctr_local) (ctr_local->gfdb_db_record) - -/*Clear db record*/ -#define CLEAR_CTR_DB_RECORD(ctr_local) \ - do { \ - ctr_local->gfdb_db_record.gfdb_fop_path = GFDB_FOP_INVALID; \ - memset(&(ctr_local->gfdb_db_record.gfdb_wind_change_time), 0, \ - sizeof(gfdb_time_t)); \ - memset(&(ctr_local->gfdb_db_record.gfdb_unwind_change_time), 0, \ - sizeof(gfdb_time_t)); \ - gf_uuid_clear(ctr_local->gfdb_db_record.gfid); \ - gf_uuid_clear(ctr_local->gfdb_db_record.pargfid); \ - memset(ctr_local->gfdb_db_record.file_name, 0, GF_NAME_MAX + 1); \ - memset(ctr_local->gfdb_db_record.old_file_name, 0, GF_NAME_MAX + 1); \ - ctr_local->gfdb_db_record.gfdb_fop_type = GFDB_FOP_INVALID_OP; \ - ctr_local->ia_inode_type = IA_INVAL; \ - } while (0) - -static gf_ctr_local_t * -init_ctr_local_t(xlator_t *this) -{ - gf_ctr_local_t *ctr_local = NULL; - - GF_ASSERT(this); - - ctr_local = mem_get0(this->local_pool); - if (!ctr_local) { - gf_msg(GFDB_DATA_STORE, GF_LOG_ERROR, 0, - CTR_MSG_CREATE_CTR_LOCAL_ERROR_WIND, - "Error while creating ctr local"); - goto out; - } - - CLEAR_CTR_DB_RECORD(ctr_local); -out: - return ctr_local; -} - -static void -free_ctr_local(gf_ctr_local_t *ctr_local) -{ - if (ctr_local) - mem_put(ctr_local); -} - -/****************************************************************************** - * - * - * Context Carrier Structures - * - * - * ****************************************************************************/ - -/* - * Context Carrier structures are used to carry relevant information about - * inodes and links from the fops calls to the ctr_insert_wind. - * These structure just have pointers to the original data and donot - * do a deep copy of any data. This info is deep copied to - * ctr_local->gfdb_db_record and passed to insert_record() api of libgfdb. This - * info remains persistent for the unwind in ctr_local->gfdb_db_record - * and once used will be destroyed. - * - * gf_ctr_link_context_t : Context structure for hard links - * gf_ctr_inode_context_t : Context structure for inodes - * - * */ - -/*Context Carrier Structure for hard links*/ -typedef struct gf_ctr_link_context { - uuid_t *pargfid; - const char *basename; -} gf_ctr_link_context_t; - -/*Context Carrier Structure for inodes*/ -typedef struct gf_ctr_inode_context { - ia_type_t ia_type; - uuid_t *gfid; - uuid_t *old_gfid; - gf_ctr_link_context_t *new_link_cx; - gf_ctr_link_context_t *old_link_cx; - gfdb_fop_type_t fop_type; - gfdb_fop_path_t fop_path; - gf_boolean_t is_internal_fop; - /* Indicating metadata fops */ - gf_boolean_t is_metadata_fop; -} gf_ctr_inode_context_t; - -/*******************Util Macros for Context Carrier Structures*****************/ - -/*Checks if ctr_link_cx is sane!*/ -#define IS_CTR_LINK_CX_SANE(ctr_link_cx) \ - do { \ - if (ctr_link_cx) { \ - if (ctr_link_cx->pargfid) \ - GF_ASSERT(*(ctr_link_cx->pargfid)); \ - GF_ASSERT(ctr_link_cx->basename); \ - }; \ - } while (0) - -/*Clear and fill the ctr_link_context with values*/ -#define FILL_CTR_LINK_CX(ctr_link_cx, _pargfid, _basename, label) \ - do { \ - GF_VALIDATE_OR_GOTO("ctr", ctr_link_cx, label); \ - GF_VALIDATE_OR_GOTO("ctr", _pargfid, label); \ - GF_VALIDATE_OR_GOTO("ctr", _basename, label); \ - memset(ctr_link_cx, 0, sizeof(*ctr_link_cx)); \ - ctr_link_cx->pargfid = &_pargfid; \ - ctr_link_cx->basename = _basename; \ - } while (0) - -#define NEW_LINK_CX(ctr_inode_cx) ctr_inode_cx->new_link_cx - -#define OLD_LINK_CX(ctr_inode_cx) ctr_inode_cx->old_link_cx - -/*Checks if ctr_inode_cx is sane!*/ -#define IS_CTR_INODE_CX_SANE(ctr_inode_cx) \ - do { \ - GF_ASSERT(ctr_inode_cx); \ - GF_ASSERT(ctr_inode_cx->gfid); \ - GF_ASSERT(*(ctr_inode_cx->gfid)); \ - GF_ASSERT(ctr_inode_cx->fop_type != GFDB_FOP_INVALID_OP); \ - GF_ASSERT(ctr_inode_cx->fop_path != GFDB_FOP_INVALID); \ - IS_CTR_LINK_CX_SANE(NEW_LINK_CX(ctr_inode_cx)); \ - IS_CTR_LINK_CX_SANE(OLD_LINK_CX(ctr_inode_cx)); \ - } while (0) - -/*Clear and fill the ctr_inode_context with values*/ -#define FILL_CTR_INODE_CONTEXT(ctr_inode_cx, _ia_type, _gfid, _new_link_cx, \ - _old_link_cx, _fop_type, _fop_path) \ - do { \ - GF_ASSERT(ctr_inode_cx); \ - GF_ASSERT(_gfid); \ - GF_ASSERT(_fop_type != GFDB_FOP_INVALID_OP); \ - GF_ASSERT(_fop_path != GFDB_FOP_INVALID); \ - memset(ctr_inode_cx, 0, sizeof(*ctr_inode_cx)); \ - ctr_inode_cx->ia_type = _ia_type; \ - ctr_inode_cx->gfid = &_gfid; \ - IS_CTR_LINK_CX_SANE(NEW_LINK_CX(ctr_inode_cx)); \ - if (_new_link_cx) \ - NEW_LINK_CX(ctr_inode_cx) = _new_link_cx; \ - IS_CTR_LINK_CX_SANE(OLD_LINK_CX(ctr_inode_cx)); \ - if (_old_link_cx) \ - OLD_LINK_CX(ctr_inode_cx) = _old_link_cx; \ - ctr_inode_cx->fop_type = _fop_type; \ - ctr_inode_cx->fop_path = _fop_path; \ - } while (0) - -/****************************************************************************** - * - * Util functions or macros used by - * insert wind and insert unwind - * - * ****************************************************************************/ -/* Free ctr frame local */ -static inline void -ctr_free_frame_local(call_frame_t *frame) -{ - if (frame) { - free_ctr_local((gf_ctr_local_t *)frame->local); - frame->local = NULL; - } -} - -/* Setting GF_REQUEST_LINK_COUNT_XDATA in dict - * that has to be sent to POSIX Xlator to send - * link count in unwind path. - * return 0 for success with not creation of dict - * return 1 for success with creation of dict - * return -1 for failure. - * */ -static inline int -set_posix_link_request(xlator_t *this, dict_t **xdata) -{ - int ret = -1; - gf_boolean_t is_created = _gf_false; - - GF_VALIDATE_OR_GOTO("ctr", this, out); - GF_VALIDATE_OR_GOTO(this->name, xdata, out); - - /*create xdata if NULL*/ - if (!*xdata) { - *xdata = dict_new(); - is_created = _gf_true; - ret = 1; - } else { - ret = 0; - } - - if (!*xdata) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_XDATA_NULL, - "xdata is NULL :Cannot send " - "GF_REQUEST_LINK_COUNT_XDATA to posix"); - ret = -1; - goto out; - } - - ret = dict_set_int32(*xdata, GF_REQUEST_LINK_COUNT_XDATA, 1); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_SET_CTR_RESPONSE_LINK_COUNT_XDATA_FAILED, - "Failed setting GF_REQUEST_LINK_COUNT_XDATA"); - ret = -1; - goto out; - } - ret = 0; -out: - if (ret == -1) { - if (*xdata && is_created) { - dict_unref(*xdata); - } - } - return ret; -} - -/* - * If a bitrot fop - * */ -#define BITROT_FOP(frame) \ - (frame->root->pid == GF_CLIENT_PID_BITD || \ - frame->root->pid == GF_CLIENT_PID_SCRUB) - -/* - * If a rebalancer fop - * */ -#define REBALANCE_FOP(frame) (frame->root->pid == GF_CLIENT_PID_DEFRAG) - -/* - * If its a tiering rebalancer fop - * */ -#define TIER_REBALANCE_FOP(frame) \ - (frame->root->pid == GF_CLIENT_PID_TIER_DEFRAG) - -/* - * If its a AFR SELF HEAL - * */ -#define AFR_SELF_HEAL_FOP(frame) (frame->root->pid == GF_CLIENT_PID_SELF_HEALD) - -/* - * if a rebalancer fop goto - * */ -#define CTR_IF_REBALANCE_FOP_THEN_GOTO(frame, label) \ - do { \ - if (REBALANCE_FOP(frame)) \ - goto label; \ - } while (0) - -/* - * Internal fop - * - * */ -static inline gf_boolean_t -is_internal_fop(call_frame_t *frame, dict_t *xdata) -{ - gf_boolean_t ret = _gf_false; - - GF_ASSERT(frame); - GF_ASSERT(frame->root); - - if (AFR_SELF_HEAL_FOP(frame)) { - ret = _gf_true; - } - if (BITROT_FOP(frame)) { - ret = _gf_true; - } - if (REBALANCE_FOP(frame) || TIER_REBALANCE_FOP(frame)) { - ret = _gf_true; - if (xdata && dict_get(xdata, CTR_ATTACH_TIER_LOOKUP)) { - ret = _gf_false; - } - } - if (xdata && dict_get(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) { - ret = _gf_true; - } - - return ret; -} - -#define CTR_IF_INTERNAL_FOP_THEN_GOTO(frame, dict, label) \ - do { \ - if (is_internal_fop(frame, dict)) \ - goto label; \ - } while (0) - -/* if fop has failed exit */ -#define CTR_IF_FOP_FAILED_THEN_GOTO(this, op_ret, op_errno, label) \ - do { \ - if (op_ret == -1) { \ - gf_msg_trace(this->name, 0, "Failed fop with %s", \ - strerror(op_errno)); \ - goto label; \ - }; \ - } while (0) - -/* - * IS CTR Xlator is disabled then goto to label - * */ -#define CTR_IS_DISABLED_THEN_GOTO(this, label) \ - do { \ - gf_ctr_private_t *_priv = NULL; \ - GF_ASSERT(this); \ - GF_ASSERT(this->private); \ - _priv = this->private; \ - if (!_priv->_db_conn) \ - goto label; \ - } while (0) - -/* - * IS CTR record metadata heat is disabled then goto to label - * */ -#define CTR_RECORD_METADATA_HEAT_IS_DISABLED_THEN_GOTO(this, label) \ - do { \ - gf_ctr_private_t *_priv = NULL; \ - GF_ASSERT(this); \ - GF_ASSERT(this->private); \ - _priv = this->private; \ - if (!_priv->ctr_record_metadata_heat) \ - goto label; \ - } while (0) - -int -fill_db_record_for_unwind(xlator_t *this, gf_ctr_local_t *ctr_local, - gfdb_fop_type_t fop_type, gfdb_fop_path_t fop_path); - -int -fill_db_record_for_wind(xlator_t *this, gf_ctr_local_t *ctr_local, - gf_ctr_inode_context_t *ctr_inode_cx); - -/******************************************************************************* - * CTR INSERT WIND - * ***************************************************************************** - * Function used to insert/update record into the database during a wind fop - * This function creates ctr_local structure into the frame of the fop - * call. - * ****************************************************************************/ - -static inline int -ctr_insert_wind(call_frame_t *frame, xlator_t *this, - gf_ctr_inode_context_t *ctr_inode_cx) -{ - int ret = -1; - gf_ctr_private_t *_priv = NULL; - gf_ctr_local_t *ctr_local = NULL; - - GF_ASSERT(frame); - GF_ASSERT(frame->root); - GF_ASSERT(this); - IS_CTR_INODE_CX_SANE(ctr_inode_cx); - - _priv = this->private; - GF_ASSERT(_priv); - - GF_ASSERT(_priv->_db_conn); - - /*If record_wind option of CTR is on record wind for - * regular files only*/ - if (_priv->ctr_record_wind && ctr_inode_cx->ia_type != IA_IFDIR) { - frame->local = init_ctr_local_t(this); - if (!frame->local) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_CREATE_CTR_LOCAL_ERROR_WIND, - "WIND: Error while creating ctr local"); - goto out; - }; - ctr_local = frame->local; - ctr_local->client_pid = frame->root->pid; - ctr_local->is_internal_fop = ctr_inode_cx->is_internal_fop; - - /* Decide whether to record counters or not */ - CTR_DB_REC(ctr_local).do_record_counters = _gf_false; - /* If record counter is enabled */ - if (_priv->ctr_record_counter) { - /* If not a internal fop */ - if (!(ctr_local->is_internal_fop)) { - /* If its a metadata fop AND - * record metadata heat - * OR - * its NOT a metadata fop */ - if ((ctr_inode_cx->is_metadata_fop && - _priv->ctr_record_metadata_heat) || - (!ctr_inode_cx->is_metadata_fop)) { - CTR_DB_REC(ctr_local).do_record_counters = _gf_true; - } - } - } - - /* Decide whether to record times or not - * For non internal FOPS record times as usual*/ - CTR_DB_REC(ctr_local).do_record_times = _gf_false; - if (!ctr_local->is_internal_fop) { - /* If its a metadata fop AND - * record metadata heat - * OR - * its NOT a metadata fop */ - if ((ctr_inode_cx->is_metadata_fop && - _priv->ctr_record_metadata_heat) || - (!ctr_inode_cx->is_metadata_fop)) { - CTR_DB_REC(ctr_local).do_record_times = - (_priv->ctr_record_wind || _priv->ctr_record_unwind); - } - } - /* when its a internal FOPS*/ - else { - /* Record times only for create - * i.e when the inode is created */ - CTR_DB_REC(ctr_local).do_record_times = (isdentrycreatefop( - ctr_inode_cx->fop_type)) - ? _gf_true - : _gf_false; - } - - /*Fill the db record for insertion*/ - ret = fill_db_record_for_wind(this, ctr_local, ctr_inode_cx); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_FILL_CTR_LOCAL_ERROR_WIND, - "WIND: Error filling ctr local"); - goto out; - } - - /*Insert the db record*/ - ret = insert_record(_priv->_db_conn, &ctr_local->gfdb_db_record); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_INSERT_RECORD_WIND_FAILED, - "WIND: Inserting of record failed!"); - goto out; - } - } - ret = 0; -out: - - if (ret) { - free_ctr_local(ctr_local); - frame->local = NULL; - } - - return ret; -} - -/******************************************************************************* - * CTR INSERT UNWIND - * ***************************************************************************** - * Function used to insert/update record into the database during a unwind fop - * This function destroys ctr_local structure into the frame of the fop - * call at the end. - * ****************************************************************************/ -static inline int -ctr_insert_unwind(call_frame_t *frame, xlator_t *this, gfdb_fop_type_t fop_type, - gfdb_fop_path_t fop_path) -{ - int ret = -1; - gf_ctr_private_t *_priv = NULL; - gf_ctr_local_t *ctr_local = NULL; - - GF_ASSERT(frame); - GF_ASSERT(this); - - _priv = this->private; - GF_ASSERT(_priv); - - GF_ASSERT(_priv->_db_conn); - - ctr_local = frame->local; - - if (ctr_local && (_priv->ctr_record_unwind || isdentryfop(fop_type)) && - (ctr_local->ia_inode_type != IA_IFDIR)) { - CTR_DB_REC(ctr_local).do_record_uwind_time = _priv->ctr_record_unwind; - - ret = fill_db_record_for_unwind(this, ctr_local, fop_type, fop_path); - if (ret == -1) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND, - "UNWIND: Error filling ctr local"); - goto out; - } - - ret = insert_record(_priv->_db_conn, &ctr_local->gfdb_db_record); - if (ret == -1) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND, - "UNWIND: Error filling ctr local"); - goto out; - } - } - ret = 0; -out: - return ret; -} - -/****************************************************************************** - * Delete file/flink record/s from db - * ****************************************************************************/ -static inline int -ctr_delete_hard_link_from_db(xlator_t *this, uuid_t gfid, uuid_t pargfid, - char *basename, gfdb_fop_type_t fop_type, - gfdb_fop_path_t fop_path) -{ - int ret = -1; - gfdb_db_record_t gfdb_db_record; - gf_ctr_private_t *_priv = NULL; - - _priv = this->private; - GF_VALIDATE_OR_GOTO(this->name, _priv, out); - GF_VALIDATE_OR_GOTO(this->name, (!gf_uuid_is_null(gfid)), out); - GF_VALIDATE_OR_GOTO(this->name, (!gf_uuid_is_null(pargfid)), out); - GF_VALIDATE_OR_GOTO(this->name, (fop_type == GFDB_FOP_DENTRY_WRITE), out); - GF_VALIDATE_OR_GOTO( - this->name, (fop_path == GFDB_FOP_UNDEL || GFDB_FOP_UNDEL_ALL), out); - - /* Set gfdb_db_record to 0 */ - memset(&gfdb_db_record, 0, sizeof(gfdb_db_record)); - - /* Copy basename */ - if (snprintf(gfdb_db_record.file_name, GF_NAME_MAX, "%s", basename) >= - GF_NAME_MAX) - goto out; - - /* Copy gfid into db record */ - gf_uuid_copy(gfdb_db_record.gfid, gfid); - - /* Copy pargid into db record */ - gf_uuid_copy(gfdb_db_record.pargfid, pargfid); - - gfdb_db_record.gfdb_fop_path = fop_path; - gfdb_db_record.gfdb_fop_type = fop_type; - - /*send delete request to db*/ - ret = insert_record(_priv->_db_conn, &gfdb_db_record); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_INSERT_RECORD_WIND_FAILED, - "Failed to delete record. %s", basename); - goto out; - } - - ret = 0; -out: - return ret; -} - -/******************************* Hard link function ***************************/ - -static inline gf_boolean_t -__is_inode_expired(ctr_xlator_ctx_t *ctr_xlator_ctx, gf_ctr_private_t *_priv, - gfdb_time_t *current_time) -{ - gf_boolean_t ret = _gf_false; - uint64_t time_diff = 0; - - GF_ASSERT(ctr_xlator_ctx); - GF_ASSERT(_priv); - GF_ASSERT(current_time); - - time_diff = current_time->tv_sec - ctr_xlator_ctx->inode_heal_period; - - ret = (time_diff >= _priv->ctr_lookupheal_inode_timeout) ? _gf_true - : _gf_false; - return ret; -} - -static inline gf_boolean_t -__is_hardlink_expired(ctr_hard_link_t *ctr_hard_link, gf_ctr_private_t *_priv, - gfdb_time_t *current_time) -{ - gf_boolean_t ret = _gf_false; - uint64_t time_diff = 0; - - GF_ASSERT(ctr_hard_link); - GF_ASSERT(_priv); - GF_ASSERT(current_time); - - time_diff = current_time->tv_sec - ctr_hard_link->hardlink_heal_period; - - ret = ret || (time_diff >= _priv->ctr_lookupheal_link_timeout) ? _gf_true - : _gf_false; - - return ret; -} - -/* Return values of heal*/ -typedef enum ctr_heal_ret_val { - CTR_CTX_ERROR = -1, - /* No healing required */ - CTR_TRY_NO_HEAL = 0, - /* Try healing hard link */ - CTR_TRY_HARDLINK_HEAL = 1, - /* Try healing inode */ - CTR_TRY_INODE_HEAL = 2, -} ctr_heal_ret_val_t; - -/** - * @brief Function to add hard link to the inode context variable. - * The inode context maintainences a in-memory list. This is used - * smart healing of database. - * @param frame of the FOP - * @param this is the Xlator instant - * @param inode - * @return Return ctr_heal_ret_val_t - */ - -static inline ctr_heal_ret_val_t -add_hard_link_ctx(call_frame_t *frame, xlator_t *this, inode_t *inode) -{ - ctr_heal_ret_val_t ret_val = CTR_TRY_NO_HEAL; - int ret = -1; - gf_ctr_local_t *ctr_local = NULL; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - ctr_hard_link_t *ctr_hard_link = NULL; - gf_ctr_private_t *_priv = NULL; - gfdb_time_t current_time = {0}; - - GF_ASSERT(frame); - GF_ASSERT(this); - GF_ASSERT(inode); - GF_ASSERT(this->private); - - _priv = this->private; - - ctr_local = frame->local; - if (!ctr_local) { - goto out; - } - - ctr_xlator_ctx = init_ctr_xlator_ctx(this, inode); - if (!ctr_xlator_ctx) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_ACCESS_CTR_INODE_CONTEXT_FAILED, - "Failed accessing ctr inode context"); - goto out; - } - - LOCK(&ctr_xlator_ctx->lock); - - /* Check if the hard link already exists - * in the ctr inode context*/ - ctr_hard_link = ctr_search_hard_link_ctx(this, ctr_xlator_ctx, - CTR_DB_REC(ctr_local).pargfid, - CTR_DB_REC(ctr_local).file_name); - /* if there then ignore */ - if (ctr_hard_link) { - ret = gettimeofday(¤t_time, NULL); - if (ret == -1) { - gf_log(this->name, GF_LOG_ERROR, "Failed to get current time"); - ret_val = CTR_CTX_ERROR; - goto unlock; - } - - if (__is_hardlink_expired(ctr_hard_link, _priv, ¤t_time)) { - ctr_hard_link->hardlink_heal_period = current_time.tv_sec; - ret_val = ret_val | CTR_TRY_HARDLINK_HEAL; - } - - if (__is_inode_expired(ctr_xlator_ctx, _priv, ¤t_time)) { - ctr_xlator_ctx->inode_heal_period = current_time.tv_sec; - ret_val = ret_val | CTR_TRY_INODE_HEAL; - } - - goto unlock; - } - - /* Add the hard link to the list*/ - ret = ctr_add_hard_link(this, ctr_xlator_ctx, CTR_DB_REC(ctr_local).pargfid, - CTR_DB_REC(ctr_local).file_name); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_ADD_HARDLINK_TO_CTR_INODE_CONTEXT_FAILED, - "Failed to add hardlink to the ctr inode context"); - ret_val = CTR_CTX_ERROR; - goto unlock; - } - - ret_val = CTR_TRY_NO_HEAL; -unlock: - UNLOCK(&ctr_xlator_ctx->lock); -out: - return ret_val; -} - -static inline int -delete_hard_link_ctx(call_frame_t *frame, xlator_t *this, inode_t *inode) -{ - int ret = -1; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - gf_ctr_local_t *ctr_local = NULL; - - GF_ASSERT(frame); - GF_ASSERT(this); - GF_ASSERT(inode); - - ctr_local = frame->local; - if (!ctr_local) { - goto out; - } - - ctr_xlator_ctx = get_ctr_xlator_ctx(this, inode); - if (!ctr_xlator_ctx) { - /* Since there is no ctr inode context so nothing more to do */ - ret = 0; - goto out; - } - - ret = ctr_delete_hard_link(this, ctr_xlator_ctx, - CTR_DB_REC(ctr_local).pargfid, - CTR_DB_REC(ctr_local).file_name); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_DELETE_HARDLINK_FAILED, - "Failed to delete hard link"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -static inline int -update_hard_link_ctx(call_frame_t *frame, xlator_t *this, inode_t *inode) -{ - int ret = -1; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - gf_ctr_local_t *ctr_local = NULL; - - GF_ASSERT(frame); - GF_ASSERT(this); - GF_ASSERT(inode); - - ctr_local = frame->local; - if (!ctr_local) { - goto out; - } - - ctr_xlator_ctx = init_ctr_xlator_ctx(this, inode); - if (!ctr_xlator_ctx) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_ACCESS_CTR_INODE_CONTEXT_FAILED, - "Failed accessing ctr inode context"); - goto out; - } - - ret = ctr_update_hard_link( - this, ctr_xlator_ctx, CTR_DB_REC(ctr_local).pargfid, - CTR_DB_REC(ctr_local).file_name, CTR_DB_REC(ctr_local).old_pargfid, - CTR_DB_REC(ctr_local).old_file_name); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_DELETE_HARDLINK_FAILED, - "Failed to delete hard link"); - goto out; - } - - ret = 0; - -out: - return ret; -} - -/****************************************************************************** - * - * CTR xlator init related functions - * - * - * ****************************************************************************/ -int -extract_db_params(xlator_t *this, dict_t *params_dict, gfdb_db_type_t db_type); - -int -extract_ctr_options(xlator_t *this, gf_ctr_private_t *_priv); - -#endif diff --git a/xlators/features/changetimerecorder/src/ctr-messages.h b/xlators/features/changetimerecorder/src/ctr-messages.h deleted file mode 100644 index 105d2265430..00000000000 --- a/xlators/features/changetimerecorder/src/ctr-messages.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. - */ - -#ifndef _CTR_MESSAGES_H_ -#define _CTR_MESSAGES_H_ - -#include "glfs-message-id.h" - -/* To add new message IDs, append new identifiers at the end of the list. - * - * Never remove a message ID. If it's not used anymore, you can rename it or - * leave it as it is, but not delete it. This is to prevent reutilization of - * IDs by other messages. - * - * The component name must match one of the entries defined in - * glfs-message-id.h. - */ - -GLFS_MSGID( - CTR, CTR_MSG_CREATE_CTR_LOCAL_ERROR_WIND, - CTR_MSG_FILL_CTR_LOCAL_ERROR_UNWIND, CTR_MSG_FILL_CTR_LOCAL_ERROR_WIND, - CTR_MSG_INSERT_LINK_WIND_FAILED, CTR_MSG_INSERT_WRITEV_WIND_FAILED, - CTR_MSG_INSERT_WRITEV_UNWIND_FAILED, CTR_MSG_INSERT_SETATTR_WIND_FAILED, - CTR_MSG_INSERT_SETATTR_UNWIND_FAILED, - CTR_MSG_INSERT_FREMOVEXATTR_UNWIND_FAILED, - CTR_MSG_INSERT_FREMOVEXATTR_WIND_FAILED, - CTR_MSG_INSERT_REMOVEXATTR_WIND_FAILED, - CTR_MSG_INSERT_REMOVEXATTR_UNWIND_FAILED, - CTR_MSG_INSERT_TRUNCATE_WIND_FAILED, CTR_MSG_INSERT_TRUNCATE_UNWIND_FAILED, - CTR_MSG_INSERT_FTRUNCATE_UNWIND_FAILED, - CTR_MSG_INSERT_FTRUNCATE_WIND_FAILED, CTR_MSG_INSERT_RENAME_WIND_FAILED, - CTR_MSG_INSERT_RENAME_UNWIND_FAILED, - CTR_MSG_ACCESS_CTR_INODE_CONTEXT_FAILED, CTR_MSG_ADD_HARDLINK_FAILED, - CTR_MSG_DELETE_HARDLINK_FAILED, CTR_MSG_UPDATE_HARDLINK_FAILED, - CTR_MSG_GET_CTR_RESPONSE_LINK_COUNT_XDATA_FAILED, - CTR_MSG_SET_CTR_RESPONSE_LINK_COUNT_XDATA_FAILED, - CTR_MSG_INSERT_UNLINK_UNWIND_FAILED, CTR_MSG_INSERT_UNLINK_WIND_FAILED, - CTR_MSG_XDATA_NULL, CTR_MSG_INSERT_FSYNC_WIND_FAILED, - CTR_MSG_INSERT_FSYNC_UNWIND_FAILED, CTR_MSG_INSERT_MKNOD_UNWIND_FAILED, - CTR_MSG_INSERT_MKNOD_WIND_FAILED, CTR_MSG_INSERT_CREATE_WIND_FAILED, - CTR_MSG_INSERT_CREATE_UNWIND_FAILED, CTR_MSG_INSERT_RECORD_WIND_FAILED, - CTR_MSG_INSERT_READV_WIND_FAILED, CTR_MSG_GET_GFID_FROM_DICT_FAILED, - CTR_MSG_SET, CTR_MSG_FATAL_ERROR, CTR_MSG_DANGLING_VOLUME, - CTR_MSG_CALLOC_FAILED, CTR_MSG_EXTRACT_CTR_XLATOR_OPTIONS_FAILED, - CTR_MSG_INIT_DB_PARAMS_FAILED, CTR_MSG_CREATE_LOCAL_MEMORY_POOL_FAILED, - CTR_MSG_MEM_ACC_INIT_FAILED, CTR_MSG_CLOSE_DB_CONN_FAILED, - CTR_MSG_FILL_UNWIND_TIME_REC_ERROR, CTR_MSG_WRONG_FOP_PATH, - CTR_MSG_CONSTRUCT_DB_PATH_FAILED, CTR_MSG_SET_VALUE_TO_SQL_PARAM_FAILED, - CTR_MSG_XLATOR_DISABLED, CTR_MSG_HARDLINK_MISSING_IN_LIST, - CTR_MSG_ADD_HARDLINK_TO_LIST_FAILED, CTR_MSG_INIT_LOCK_FAILED, - CTR_MSG_COPY_FAILED, CTR_MSG_EXTRACT_DB_PARAM_OPTIONS_FAILED, - CTR_MSG_ADD_HARDLINK_TO_CTR_INODE_CONTEXT_FAILED, CTR_MSG_NULL_LOCAL); - -#endif /* !_CTR_MESSAGES_H_ */ diff --git a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c deleted file mode 100644 index b4afe74a31b..00000000000 --- a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#include "ctr-xlator-ctx.h" -#include "ctr-messages.h" -#include <time.h> -#include <sys/time.h> - -#define IS_THE_ONLY_HARDLINK(ctr_hard_link) \ - (ctr_hard_link->list.next == ctr_hard_link->list.prev) - -static void -fini_ctr_hard_link(ctr_hard_link_t **ctr_hard_link) -{ - GF_ASSERT(ctr_hard_link); - - if (*ctr_hard_link) - return; - GF_FREE((*ctr_hard_link)->base_name); - GF_FREE(*ctr_hard_link); - *ctr_hard_link = NULL; -} - -/* Please lock the ctr_xlator_ctx before using this function */ -ctr_hard_link_t * -ctr_search_hard_link_ctx(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name) -{ - ctr_hard_link_t *_hard_link = NULL; - ctr_hard_link_t *searched_hardlink = NULL; - - GF_ASSERT(this); - GF_ASSERT(ctr_xlator_ctx); - - if (pgfid == NULL || base_name == NULL) - goto out; - - /*linear search*/ - list_for_each_entry(_hard_link, &ctr_xlator_ctx->hardlink_list, list) - { - if (gf_uuid_compare(_hard_link->pgfid, pgfid) == 0 && - _hard_link->base_name && - strcmp(_hard_link->base_name, base_name) == 0) { - searched_hardlink = _hard_link; - break; - } - } - -out: - return searched_hardlink; -} - -/* Please lock the ctr_xlator_ctx before using this function */ -int -ctr_add_hard_link(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name) -{ - int ret = -1; - ctr_hard_link_t *ctr_hard_link = NULL; - struct timeval current_time = {0}; - - GF_ASSERT(this); - GF_ASSERT(ctr_xlator_ctx); - - if (pgfid == NULL || base_name == NULL) - goto out; - - ctr_hard_link = GF_CALLOC(1, sizeof(*ctr_hard_link), gf_ctr_mt_hard_link_t); - if (!ctr_hard_link) { - gf_msg(this->name, GF_LOG_ERROR, ENOMEM, CTR_MSG_CALLOC_FAILED, - "Failed allocating " - "ctr_hard_link"); - goto out; - } - - /*Initialize the ctr_hard_link object and - * Assign the values : parent GFID and basename*/ - INIT_LIST_HEAD(&ctr_hard_link->list); - gf_uuid_copy(ctr_hard_link->pgfid, pgfid); - ret = gf_asprintf(&ctr_hard_link->base_name, "%s", base_name); - if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_COPY_FAILED, - "Failed copying basename" - "to ctr_hard_link"); - goto error; - } - - ret = gettimeofday(¤t_time, NULL); - if (ret == -1) { - gf_log(this->name, GF_LOG_ERROR, "Failed to get current time"); - goto error; - } - - /*Add the hard link to the list*/ - list_add_tail(&ctr_hard_link->list, &ctr_xlator_ctx->hardlink_list); - - ctr_hard_link->hardlink_heal_period = current_time.tv_sec; - - /*aal izz well!*/ - ret = 0; - goto out; -error: - GF_FREE(ctr_hard_link); -out: - return ret; -} - -static void -__delete_hard_link_from_list(ctr_hard_link_t **ctr_hard_link) -{ - GF_ASSERT(ctr_hard_link); - GF_ASSERT(*ctr_hard_link); - - /*Remove hard link from list*/ - list_del(&(*ctr_hard_link)->list); - fini_ctr_hard_link(ctr_hard_link); -} - -int -ctr_delete_hard_link(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name) -{ - int ret = -1; - ctr_hard_link_t *ctr_hard_link = NULL; - - GF_ASSERT(this); - GF_ASSERT(ctr_xlator_ctx); - - LOCK(&ctr_xlator_ctx->lock); - - /*Check if the hard link is present */ - ctr_hard_link = ctr_search_hard_link_ctx(this, ctr_xlator_ctx, pgfid, - base_name); - if (!ctr_hard_link) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_HARDLINK_MISSING_IN_LIST, - "Hard link doesn't exist in the list"); - goto out; - } - - __delete_hard_link_from_list(&ctr_hard_link); - ctr_hard_link = NULL; - - ret = 0; -out: - UNLOCK(&ctr_xlator_ctx->lock); - - return ret; -} - -int -ctr_update_hard_link(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name, uuid_t old_pgfid, - const char *old_base_name) -{ - int ret = -1; - ctr_hard_link_t *ctr_hard_link = NULL; - struct timeval current_time = {0}; - - GF_ASSERT(this); - GF_ASSERT(ctr_xlator_ctx); - - LOCK(&ctr_xlator_ctx->lock); - - /*Check if the hard link is present */ - ctr_hard_link = ctr_search_hard_link_ctx(this, ctr_xlator_ctx, old_pgfid, - old_base_name); - if (!ctr_hard_link) { - gf_msg_trace(this->name, 0, - "Hard link doesn't exist" - " in the list"); - /* Since the hard link is not present in the list - * we add it to the list */ - ret = ctr_add_hard_link(this, ctr_xlator_ctx, pgfid, base_name); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, 0, - CTR_MSG_ADD_HARDLINK_TO_LIST_FAILED, - "Failed adding hard link to the list"); - goto out; - } - ret = 0; - goto out; - } - - /* update the hard link */ - gf_uuid_copy(ctr_hard_link->pgfid, pgfid); - GF_FREE(ctr_hard_link->base_name); - ret = gf_asprintf(&ctr_hard_link->base_name, "%s", base_name); - if (ret < 0) { - gf_msg(this->name, GF_LOG_ERROR, 0, CTR_MSG_COPY_FAILED, - "Failed copying basename" - "to ctr_hard_link"); - /* delete the corrupted entry */ - __delete_hard_link_from_list(&ctr_hard_link); - ctr_hard_link = NULL; - goto out; - } - - ret = gettimeofday(¤t_time, NULL); - if (ret == -1) { - gf_log(this->name, GF_LOG_ERROR, "Failed to get current time"); - ctr_hard_link->hardlink_heal_period = 0; - } else { - ctr_hard_link->hardlink_heal_period = current_time.tv_sec; - } - - ret = 0; - -out: - UNLOCK(&ctr_xlator_ctx->lock); - - return ret; -} - -/* Delete all hardlinks */ -static int -ctr_delete_all_hard_link(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx) -{ - int ret = -1; - ctr_hard_link_t *ctr_hard_link = NULL; - ctr_hard_link_t *tmp = NULL; - - GF_ASSERT(ctr_xlator_ctx); - - LOCK(&ctr_xlator_ctx->lock); - - list_for_each_entry_safe(ctr_hard_link, tmp, &ctr_xlator_ctx->hardlink_list, - list) - { - /*Remove hard link from list*/ - __delete_hard_link_from_list(&ctr_hard_link); - ctr_hard_link = NULL; - } - - UNLOCK(&ctr_xlator_ctx->lock); - - ret = 0; - - return ret; -} - -/* Please lock the inode before using this function */ -static ctr_xlator_ctx_t * -__get_ctr_xlator_ctx(xlator_t *this, inode_t *inode) -{ - int ret = 0; - uint64_t _addr = 0; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - - GF_ASSERT(this); - GF_ASSERT(inode); - - ret = __inode_ctx_get(inode, this, &_addr); - if (ret < 0) - _addr = 0; - if (_addr != 0) { - ctr_xlator_ctx = (ctr_xlator_ctx_t *)(long)_addr; - } - - return ctr_xlator_ctx; -} - -ctr_xlator_ctx_t * -init_ctr_xlator_ctx(xlator_t *this, inode_t *inode) -{ - int ret = -1; - uint64_t _addr = 0; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - struct timeval current_time = {0}; - - GF_ASSERT(this); - GF_ASSERT(inode); - - LOCK(&inode->lock); - { - ctr_xlator_ctx = __get_ctr_xlator_ctx(this, inode); - if (ctr_xlator_ctx) { - ret = 0; - goto out; - } - ctr_xlator_ctx = GF_CALLOC(1, sizeof(*ctr_xlator_ctx), - gf_ctr_mt_xlator_ctx); - if (!ctr_xlator_ctx) - goto out; - - ret = LOCK_INIT(&ctr_xlator_ctx->lock); - if (ret) { - gf_msg(this->name, GF_LOG_ERROR, ret, CTR_MSG_INIT_LOCK_FAILED, - "Failed init lock %s", strerror(ret)); - goto out; - } - _addr = (uint64_t)ctr_xlator_ctx; - - ret = __inode_ctx_set(inode, this, &_addr); - if (ret) { - goto out; - } - - INIT_LIST_HEAD(&ctr_xlator_ctx->hardlink_list); - - ret = gettimeofday(¤t_time, NULL); - if (ret == -1) { - gf_log(this->name, GF_LOG_ERROR, "Failed to get current time"); - goto out; - } - - ctr_xlator_ctx->inode_heal_period = current_time.tv_sec; - } - ret = 0; -out: - if (ret) { - GF_FREE(ctr_xlator_ctx); - ctr_xlator_ctx = NULL; - } - - UNLOCK(&inode->lock); - - return ctr_xlator_ctx; -} - -void -fini_ctr_xlator_ctx(xlator_t *this, inode_t *inode) -{ - int ret = 0; - uint64_t _addr = 0; - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - - inode_ctx_del(inode, this, &_addr); - if (!_addr) - return; - - ctr_xlator_ctx = (ctr_xlator_ctx_t *)(long)_addr; - - ret = ctr_delete_all_hard_link(this, ctr_xlator_ctx); - if (ret) { - gf_msg(this->name, GF_LOG_WARNING, 0, CTR_MSG_DELETE_HARDLINK_FAILED, - "Failed deleting all " - "hard links from inode context"); - } - - LOCK_DESTROY(&ctr_xlator_ctx->lock); - - GF_FREE(ctr_xlator_ctx); -} - -ctr_xlator_ctx_t * -get_ctr_xlator_ctx(xlator_t *this, inode_t *inode) -{ - ctr_xlator_ctx_t *ctr_xlator_ctx = NULL; - - LOCK(&inode->lock); - ctr_xlator_ctx = __get_ctr_xlator_ctx(this, inode); - UNLOCK(&inode->lock); - - return ctr_xlator_ctx; -} diff --git a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h b/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h deleted file mode 100644 index 584d3b79ba4..00000000000 --- a/xlators/features/changetimerecorder/src/ctr-xlator-ctx.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#ifndef __CTR_XLATOR_CTX_H -#define __CTR_XLATOR_CTX_H - -#include "xlator.h" -#include "ctr_mem_types.h" -#include "iatt.h" -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "locking.h" -#include "common-utils.h" -#include <time.h> -#include <sys/time.h> - -typedef struct ctr_hard_link { - uuid_t pgfid; - char *base_name; - /* Hardlink expiry : Defines the expiry period after which a - * database heal is attempted. */ - uint64_t hardlink_heal_period; - struct list_head list; -} ctr_hard_link_t; - -typedef struct ctr_xlator_ctx { - /* This represents the looked up hardlinks - * NOTE: This doesn't represent all physical hardlinks of the inode*/ - struct list_head hardlink_list; - uint64_t inode_heal_period; - gf_lock_t lock; -} ctr_xlator_ctx_t; - -ctr_hard_link_t * -ctr_search_hard_link_ctx(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name); - -int -ctr_add_hard_link(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name); - -int -ctr_delete_hard_link(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name); - -int -ctr_update_hard_link(xlator_t *this, ctr_xlator_ctx_t *ctr_xlator_ctx, - uuid_t pgfid, const char *base_name, uuid_t old_pgfid, - const char *old_base_name); - -ctr_xlator_ctx_t * -get_ctr_xlator_ctx(xlator_t *this, inode_t *inode); - -ctr_xlator_ctx_t * -init_ctr_xlator_ctx(xlator_t *this, inode_t *inode); - -void -fini_ctr_xlator_ctx(xlator_t *this, inode_t *inode); - -#endif diff --git a/xlators/features/changetimerecorder/src/ctr_mem_types.h b/xlators/features/changetimerecorder/src/ctr_mem_types.h deleted file mode 100644 index 7b8f531ddec..00000000000 --- a/xlators/features/changetimerecorder/src/ctr_mem_types.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - Copyright (c) 2008-2015 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#ifndef __CTR_MEM_TYPES_H__ -#define __CTR_MEM_TYPES_H__ - -#include "gfdb_mem-types.h" - -enum gf_ctr_mem_types_ { - gf_ctr_mt_private_t = gfdb_mt_end + 1, - gf_ctr_mt_xlator_ctx, - gf_ctr_mt_hard_link_t, - gf_ctr_mt_end -}; -#endif diff --git a/xlators/features/cloudsync/src/Makefile.am b/xlators/features/cloudsync/src/Makefile.am index 0c3966c968b..e2a277e372b 100644 --- a/xlators/features/cloudsync/src/Makefile.am +++ b/xlators/features/cloudsync/src/Makefile.am @@ -21,9 +21,9 @@ cloudsync_la_SOURCES = $(cloudsync_sources) $(cloudsynccommon_sources) nodist_cloudsync_la_SOURCES = cloudsync-autogen-fops.c cloudsync-autogen-fops.h BUILT_SOURCES = cloudsync-autogen-fops.h -cloudsync_la_LDFLAGS = $(LIB_DL) -module $(GF_XLATOR_DEFAULT_LDFLAGS) +cloudsync_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) -cloudsync_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la +cloudsync_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(LIB_DL) AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src \ -DCS_PLUGINDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/cloudsync-plugins\" diff --git a/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.c b/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.c index 6bb68cd170c..ee63f983980 100644 --- a/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.c +++ b/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.c @@ -20,11 +20,11 @@ #include <dlfcn.h> -#include "glusterfs.h" -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "cloudsync.h" #include "cloudsync-common.h" -#include "call-stub.h" +#include <glusterfs/call-stub.h> #pragma generate diff --git a/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.h b/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.h index 2db2a9c88c7..d922c77d8aa 100644 --- a/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.h +++ b/xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.h @@ -15,7 +15,7 @@ #ifndef _CLOUDSYNC_AUTOGEN_FOPS_H #define _CLOUDSYNC_AUTOGEN_FOPS_H -#include "xlator.h" +#include <glusterfs/xlator.h> #include "cloudsync.h" #include "cloudsync-common.h" diff --git a/xlators/features/cloudsync/src/cloudsync-common.c b/xlators/features/cloudsync/src/cloudsync-common.c index aee1f06a82a..445a31b90e7 100644 --- a/xlators/features/cloudsync/src/cloudsync-common.c +++ b/xlators/features/cloudsync/src/cloudsync-common.c @@ -11,6 +11,20 @@ #include "cloudsync-common.h" void +cs_xattrinfo_wipe(cs_local_t *local) +{ + if (local->xattrinfo.lxattr) { + if (local->xattrinfo.lxattr->file_path) + GF_FREE(local->xattrinfo.lxattr->file_path); + + if (local->xattrinfo.lxattr->volname) + GF_FREE(local->xattrinfo.lxattr->volname); + + GF_FREE(local->xattrinfo.lxattr); + } +} + +void cs_local_wipe(xlator_t *this, cs_local_t *local) { if (!local) @@ -40,5 +54,7 @@ cs_local_wipe(xlator_t *this, cs_local_t *local) if (local->remotepath) GF_FREE(local->remotepath); + cs_xattrinfo_wipe(local); + mem_put(local); } diff --git a/xlators/features/cloudsync/src/cloudsync-common.h b/xlators/features/cloudsync/src/cloudsync-common.h index 0be6a446456..11d233460a4 100644 --- a/xlators/features/cloudsync/src/cloudsync-common.h +++ b/xlators/features/cloudsync/src/cloudsync-common.h @@ -10,13 +10,27 @@ #ifndef _CLOUDSYNC_COMMON_H #define _CLOUDSYNC_COMMON_H -#include "glusterfs.h" -#include "call-stub.h" -#include "xlator.h" -#include "syncop.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/call-stub.h> +#include <glusterfs/xlator.h> +#include <glusterfs/syncop.h> +#include <glusterfs/compat-errno.h> #include "cloudsync-mem-types.h" #include "cloudsync-messages.h" +typedef struct cs_loc_xattr { + char *file_path; + uuid_t uuid; + uuid_t gfid; + char *volname; +} cs_loc_xattr_t; + +typedef struct cs_size_xattr { + uint64_t size; + uint64_t blksize; + uint64_t blocks; +} cs_size_xattr_t; + typedef struct cs_local { loc_t loc; fd_t *fd; @@ -34,10 +48,25 @@ typedef struct cs_local { int call_cnt; inode_t *inode; char *remotepath; + + struct { + /* offset, flags and size are the information needed + * by read fop for remote read operation. These will be + * populated in cloudsync read fop, before being passed + * on to the plugin performing remote read. + */ + off_t offset; + uint32_t flags; + size_t size; + cs_loc_xattr_t *lxattr; + } xattrinfo; + } cs_local_t; typedef int (*fop_download_t)(call_frame_t *frame, void *config); +typedef int (*fop_remote_read_t)(call_frame_t *, void *); + typedef void *(*store_init)(xlator_t *this); typedef int (*store_reconfigure)(xlator_t *this, dict_t *options); @@ -48,6 +77,7 @@ struct cs_remote_stores { char *name; /* store name */ void *config; /* store related information */ fop_download_t dlfop; /* store specific download function */ + fop_remote_read_t rdfop; /* store specific read function */ store_init init; /* store init to initialize store config */ store_reconfigure reconfigure; /* reconfigure store config */ store_fini fini; @@ -59,11 +89,15 @@ typedef struct cs_private { struct cs_remote_stores *stores; gf_boolean_t abortdl; pthread_spinlock_t lock; + gf_boolean_t remote_read; } cs_private_t; void cs_local_wipe(xlator_t *this, cs_local_t *local); +void +cs_xattrinfo_wipe(cs_local_t *local); + #define CS_STACK_UNWIND(fop, frame, params...) \ do { \ cs_local_t *__local = NULL; \ @@ -90,6 +124,7 @@ cs_local_wipe(xlator_t *this, cs_local_t *local); typedef struct store_methods { int (*fop_download)(call_frame_t *frame, void *config); + int (*fop_remote_read)(call_frame_t *, void *); /* return type should be the store config */ void *(*fop_init)(xlator_t *this); int (*fop_reconfigure)(xlator_t *this, dict_t *options); diff --git a/xlators/features/cloudsync/src/cloudsync-fops-c.py b/xlators/features/cloudsync/src/cloudsync-fops-c.py index fdaa1432a6c..c27df97ae58 100644..100755 --- a/xlators/features/cloudsync/src/cloudsync-fops-c.py +++ b/xlators/features/cloudsync/src/cloudsync-fops-c.py @@ -14,7 +14,7 @@ int32_t cs_@NAME@ (call_frame_t *frame, xlator_t *this, @LONG_ARGS@) { - int op_errno = -1; + int op_errno = EINVAL ; cs_local_t *local = NULL; int ret = 0; cs_inode_ctx_t *ctx = NULL; @@ -35,11 +35,19 @@ cs_@NAME@ (call_frame_t *frame, xlator_t *this, __cs_inode_ctx_get (this, fd->inode, &ctx); if (ctx) - state = __cs_get_file_state (this, fd->inode, ctx); + state = __cs_get_file_state (fd->inode, ctx); else state = GF_CS_LOCAL; - local->xattr_req = xdata ? dict_ref (xdata) : (xdata = dict_new ()); + xdata = xdata ? dict_ref (xdata) : dict_new (); + + if (!xdata) { + gf_msg (this->name, GF_LOG_ERROR, 0, 0, "insufficient memory"); + op_errno = ENOMEM; + goto err; + } + + local->xattr_req = xdata; ret = dict_set_uint32 (local->xattr_req, GF_CS_OBJECT_STATUS, 1); if (ret) { @@ -137,15 +145,15 @@ cs_@NAME@_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } else { __cs_inode_ctx_update (this, fd->inode, val); gf_msg (this->name, GF_LOG_INFO, 0, 0, - " state = %ld", val); + " state = %" PRIu64, val); if (local->call_cnt == 1 && (val == GF_CS_REMOTE || val == GF_CS_DOWNLOADING)) { gf_msg (this->name, GF_LOG_INFO, 0, 0, " will repair and download " - "the file, current state : %ld", - val); + "the file, current state : %" + PRIu64, val); goto repair; } else { gf_msg (this->name, GF_LOG_ERROR, 0, 0, @@ -187,19 +195,29 @@ int32_t cs_@NAME@ (call_frame_t *frame, xlator_t *this, @LONG_ARGS@) { + int op_errno = EINVAL; cs_local_t *local = NULL; int ret = 0; local = cs_local_init (this, frame, loc, NULL, GF_FOP_@UPNAME@); if (!local) { gf_msg (this->name, GF_LOG_ERROR, 0, 0, "local is NULL"); + op_errno = ENOMEM; goto err; } if (loc->inode->ia_type == IA_IFDIR) goto wind; - local->xattr_req = xdata ? dict_ref (xdata) : dict_new (); + xdata = xdata ? dict_ref (xdata) : dict_new (); + + if (!xdata) { + gf_msg (this->name, GF_LOG_ERROR, 0, 0, "insufficient memory"); + op_errno = ENOMEM; + goto err; + } + + local->xattr_req = xdata; ret = dict_set_uint32 (local->xattr_req, GF_CS_OBJECT_STATUS, 1); if (ret) { @@ -215,7 +233,7 @@ wind: return 0; err: - CS_STACK_UNWIND (@NAME@, frame, -1, errno, @CBK_ERROR_ARGS@); + CS_STACK_UNWIND (@NAME@, frame, -1, op_errno, @CBK_ERROR_ARGS@); return 0; } @@ -274,7 +292,7 @@ fd_ops = ['readv', 'writev', 'flush', 'fsync', 'fsyncdir', 'ftruncate', # These are the current actual lists used to generate the code # The following list contains fops which are fd based that modifies data -fd_data_modify_op_fop_template = ['readv', 'writev', 'flush', 'fsync', +fd_data_modify_op_fop_template = ['writev', 'flush', 'fsync', 'ftruncate', 'rchecksum', 'fallocate', 'discard', 'zerofill', 'seek'] @@ -284,8 +302,8 @@ loc_stat_op_fop_template = ['lookup', 'stat', 'discover', 'access', 'setattr', 'getattr'] # These fops need a separate implementation -special_fops = ['readdirp', 'statfs', 'setxattr', 'unlink', 'getxattr', - 'truncate', 'fstat'] +special_fops = ['statfs', 'setxattr', 'unlink', 'getxattr', + 'truncate', 'fstat', 'readv', 'readdirp'] def gen_defaults(): for name in ops: diff --git a/xlators/features/cloudsync/src/cloudsync-fops-h.py b/xlators/features/cloudsync/src/cloudsync-fops-h.py index faa2de651a7..faa2de651a7 100644..100755 --- a/xlators/features/cloudsync/src/cloudsync-fops-h.py +++ b/xlators/features/cloudsync/src/cloudsync-fops-h.py diff --git a/xlators/features/cloudsync/src/cloudsync-mem-types.h b/xlators/features/cloudsync/src/cloudsync-mem-types.h index 46d4f3aa2a1..220346405d0 100644 --- a/xlators/features/cloudsync/src/cloudsync-mem-types.h +++ b/xlators/features/cloudsync/src/cloudsync-mem-types.h @@ -11,11 +11,12 @@ #ifndef __CLOUDSYNC_MEM_TYPES_H__ #define __CLOUDSYNC_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum cs_mem_types_ { gf_cs_mt_cs_private_t = gf_common_mt_end + 1, gf_cs_mt_cs_remote_stores_t, gf_cs_mt_cs_inode_ctx_t, + gf_cs_mt_cs_lxattr_t, gf_cs_mt_end }; #endif /* __CLOUDSYNC_MEM_TYPES_H__ */ diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am b/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am index 4deefb651eb..fb6b0580c6d 100644 --- a/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am @@ -2,6 +2,10 @@ if BUILD_AMAZONS3_PLUGIN AMAZONS3_DIR = cloudsyncs3 endif -SUBDIRS = ${AMAZONS3_DIR} +if BUILD_CVLT_PLUGIN + CVLT_DIR = cvlt +endif + +SUBDIRS = ${AMAZONS3_DIR} ${CVLT_DIR} CLEANFILES = diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3-mem-types.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3-mem-types.h index 0aaab1fe955..7ccfcc9f4b6 100644 --- a/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3-mem-types.h +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3-mem-types.h @@ -11,7 +11,7 @@ #ifndef __LIBAWS_MEM_TYPES_H__ #define __LIBAWS_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum libaws_mem_types_ { gf_libaws_mt_aws_private_t = gf_common_mt_end + 1, gf_libaws_mt_end diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.c b/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.c index dad29fc0e4f..23c3599825a 100644 --- a/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.c +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.c @@ -15,8 +15,8 @@ #include <openssl/buffer.h> #include <openssl/crypto.h> #include <curl/curl.h> -#include "xlator.h" -#include "glusterfs.h" +#include <glusterfs/xlator.h> +#include <glusterfs/glusterfs.h> #include "libcloudsyncs3.h" #include "cloudsync-common.h" @@ -237,7 +237,7 @@ aws_form_request(char *resource, char **date, char *reqtype, char *bucketid, int date_len = -1; int res_len = -1; - ctime = time(NULL); + ctime = gf_time(); gtime = gmtime(&ctime); date_len = strftime(httpdate, sizeof(httpdate), @@ -454,6 +454,8 @@ aws_download_s3(call_frame_t *frame, void *config) }; aws_private_t *priv = NULL; + this = frame->this; + local = frame->local; priv = (aws_private_t *)config; diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.h index b1a95f8cbf9..85ae669486b 100644 --- a/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.h +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.h @@ -10,10 +10,10 @@ #ifndef _LIBAWS_H #define _LIBAWS_H -#include "glusterfs.h" -#include "call-stub.h" -#include "xlator.h" -#include "syncop.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/call-stub.h> +#include <glusterfs/xlator.h> +#include <glusterfs/syncop.h> #include <curl/curl.h> #include "cloudsync-common.h" #include "libcloudsyncs3-mem-types.h" diff --git a/xlators/features/changetimerecorder/Makefile.am b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile.am index a985f42a877..a985f42a877 100644 --- a/xlators/features/changetimerecorder/Makefile.am +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile.am diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am new file mode 100644 index 00000000000..b512464f157 --- /dev/null +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am @@ -0,0 +1,12 @@ +csp_LTLIBRARIES = cloudsynccvlt.la +cspdir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/cloudsync-plugins + +cloudsynccvlt_la_SOURCES = libcvlt.c $(top_srcdir)/xlators/features/cloudsync/src/cloudsync-common.c +cloudsynccvlt_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la +cloudsynccvlt_la_LDFLAGS = -module -avoid-version -export-symbols $(top_srcdir)/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym +AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src +noinst_HEADERS = archivestore.h libcvlt.h libcvlt-mem-types.h cvlt-messages.h +AM_CFLAGS = -Wall -fno-strict-aliasing $(GF_CFLAGS) -I$(top_srcdir)/xlators/features/cloudsync/src +CLEANFILES = + +EXTRA_DIST = libcloudsynccvlt.sym diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h new file mode 100644 index 00000000000..7230ef77337 --- /dev/null +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h @@ -0,0 +1,203 @@ +/* + Copyright (c) 2018 Commvault Systems, Inc. <http://www.commvault.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __ARCHIVESTORE_H__ +#define __ARCHIVESTORE_H__ + +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <dlfcn.h> +#include <uuid/uuid.h> + +#define CS_XATTR_ARCHIVE_UUID "trusted.cloudsync.uuid" +#define CS_XATTR_PRODUCT_ID "trusted.cloudsync.product-id" +#define CS_XATTR_STORE_ID "trusted.cloudsync.store-id" + +struct _archstore_methods; +typedef struct _archstore_methods archstore_methods_t; + +struct _archstore_desc { + void *priv; /* Private field for store mgmt. */ + /* To be used only by archive store*/ +}; +typedef struct _archstore_desc archstore_desc_t; + +struct _archstore_info { + char *id; /* Identifier for the archivestore */ + uint32_t idlen; /* Length of identifier string */ + char *prod; /* Name of the data mgmt. product */ + uint32_t prodlen; /* Length of the product string */ +}; +typedef struct _archstore_info archstore_info_t; + +struct _archstore_fileinfo { + uuid_t uuid; /* uuid of the file */ + char *path; /* file path */ + uint32_t pathlength; /* length of file path */ +}; +typedef struct _archstore_fileinfo archstore_fileinfo_t; + +struct _app_callback_info { + archstore_info_t *src_archstore; + archstore_fileinfo_t *src_archfile; + archstore_info_t *dest_archstore; + archstore_fileinfo_t *dest_archfile; +}; +typedef struct _app_callback_info app_callback_info_t; + +typedef void (*app_callback_t)(archstore_desc_t *, app_callback_info_t *, + void *, int64_t, int32_t); + +enum _archstore_scan_type { FULL = 1, INCREMENTAL = 2 }; +typedef enum _archstore_scan_type archstore_scan_type_t; + +typedef int32_t archstore_errno_t; + +/* + * Initialize archive store. + * arg1 pointer to structure containing archive store information + * arg2 error number if any generated during the initialization + * arg3 name of the log file + */ +typedef int32_t (*init_archstore_t)(archstore_desc_t *, archstore_errno_t *, + const char *); + +/* + * Clean up archive store. + * arg1 pointer to structure containing archive store information + * arg2 error number if any generated during the cleanup + */ +typedef int32_t (*term_archstore_t)(archstore_desc_t *, archstore_errno_t *); + +/* + * Read the contents of the file from archive store + * arg1 pointer to structure containing archive store description + * arg2 pointer to structure containing archive store information + * arg3 pointer to structure containing information about file to be read + * arg4 offset in the file from which data should be read + * arg5 buffer where the data should be read + * arg6 number of bytes of data to be read + * arg7 error number if any generated during the read from file + * arg8 callback handler to be invoked after the data is read + * arg9 cookie to be passed when callback is invoked + */ +typedef int32_t (*read_archstore_t)(archstore_desc_t *, archstore_info_t *, + archstore_fileinfo_t *, off_t, char *, + size_t, archstore_errno_t *, app_callback_t, + void *); + +/* + * Restore the contents of the file from archive store + * This is basically in-place restore + * arg1 pointer to structure containing archive store description + * arg2 pointer to structure containing archive store information + * arg3 pointer to structure containing information about file to be restored + * arg4 error number if any generated during the file restore + * arg5 callback to be invoked after the file is restored + * arg6 cookie to be passed when callback is invoked + */ +typedef int32_t (*recall_archstore_t)(archstore_desc_t *, archstore_info_t *, + archstore_fileinfo_t *, + archstore_errno_t *, app_callback_t, + void *); + +/* + * Restore the contents of the file from archive store to a different store + * This is basically out-of-place restore + * arg1 pointer to structure containing archive store description + * arg2 pointer to structure containing source archive store information + * arg3 pointer to structure containing information about file to be restored + * arg4 pointer to structure containing destination archive store information + * arg5 pointer to structure containing information about the location to + which the file will be restored + * arg6 error number if any generated during the file restore + * arg7 callback to be invoked after the file is restored + * arg8 cookie to be passed when callback is invoked + */ +typedef int32_t (*restore_archstore_t)(archstore_desc_t *, archstore_info_t *, + archstore_fileinfo_t *, + archstore_info_t *, + archstore_fileinfo_t *, + archstore_errno_t *, app_callback_t, + void *); + +/* + * Archive the contents of the file to archive store + * arg1 pointer to structure containing archive store description + * arg2 pointer to structure containing source archive store information + * arg3 pointer to structure containing information about files to be archived + * arg4 pointer to structure containing destination archive store information + * arg5 pointer to structure containing information about files that failed + * to be archived + * arg6 error number if any generated during the file archival + * arg7 callback to be invoked after the file is archived + * arg8 cookie to be passed when callback is invoked + */ +typedef int32_t (*archive_archstore_t)(archstore_desc_t *, archstore_info_t *, + archstore_fileinfo_t *, + archstore_info_t *, + archstore_fileinfo_t *, + archstore_errno_t *, app_callback_t, + void *); + +/* + * Backup list of files provided in the input file + * arg1 pointer to structure containing archive store description + * arg2 pointer to structure containing source archive store information + * arg3 pointer to structure containing information about files to be backed up + * arg4 pointer to structure containing destination archive store information + * arg5 pointer to structure containing information about files that failed + * to be backed up + * arg6 error number if any generated during the file archival + * arg7 callback to be invoked after the file is archived + * arg8 cookie to be passed when callback is invoked + */ +typedef int32_t (*backup_archstore_t)(archstore_desc_t *, archstore_info_t *, + archstore_fileinfo_t *, + archstore_info_t *, + archstore_fileinfo_t *, + archstore_errno_t *, app_callback_t, + void *); + +/* + * Scan the contents of a store and determine the files which need to be + * backed up. + * arg1 pointer to structure containing archive store description + * arg2 pointer to structure containing archive store information + * arg3 type of scan whether full or incremental + * arg4 path to file that contains list of files to be backed up + * arg5 error number if any generated during scan operation + */ +typedef int32_t (*scan_archstore_t)(archstore_desc_t *, archstore_info_t *, + archstore_scan_type_t, char *, + archstore_errno_t *); + +struct _archstore_methods { + init_archstore_t init; + term_archstore_t fini; + backup_archstore_t backup; + archive_archstore_t archive; + scan_archstore_t scan; + restore_archstore_t restore; + recall_archstore_t recall; + read_archstore_t read; +}; + +typedef int (*get_archstore_methods_t)(archstore_methods_t *); + +/* + * Single function that will be invoked by applications for extracting + * the function pointers to all data management functions. + */ +int32_t +get_archstore_methods(archstore_methods_t *); + +#endif /* End of __ARCHIVESTORE_H__ */ diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h new file mode 100644 index 00000000000..57c9aa77da0 --- /dev/null +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h @@ -0,0 +1,30 @@ +/* + Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. + */ + +#ifndef _CVLT_MESSAGES_H_ +#define _CVLT_MESSAGES_H_ + +#include <glusterfs/glfs-message-id.h> + +/* To add new message IDs, append new identifiers at the end of the list. + * + * Never remove a message ID. If it's not used anymore, you can rename it or + * leave it as it is, but not delete it. This is to prevent reutilization of + * IDs by other messages. + * + * The component name must match one of the entries defined in + * glfs-message-id.h. + */ + +GLFS_MSGID(CVLT, CVLT_EXTRACTION_FAILED, CVLT_FREE, + CVLT_RESOURCE_ALLOCATION_FAILED, CVLT_RESTORE_FAILED, + CVLT_READ_FAILED, CVLT_NO_MEMORY, CVLT_DLOPEN_FAILED); + +#endif /* !_CVLT_MESSAGES_H_ */ diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym new file mode 100644 index 00000000000..0bc273670d5 --- /dev/null +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym @@ -0,0 +1 @@ +store_ops diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h new file mode 100644 index 00000000000..c24fab8bfe7 --- /dev/null +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018 Commvault Systems, Inc. <http://www.commvault.com> + * This file is part of GlusterFS. + * + * This file is licensed to you under your choice of the GNU Lesser + * General Public License, version 3 or any later version (LGPLv3 or + * later), or the GNU General Public License, version 2 (GPLv2), in all + * cases as published by the Free Software Foundation. + */ + +#ifndef __LIBCVLT_MEM_TYPES_H__ +#define __LIBCVLT_MEM_TYPES_H__ + +#include <glusterfs/mem-types.h> +enum libcvlt_mem_types_ { + gf_libcvlt_mt_cvlt_private_t = gf_common_mt_end + 1, + gf_libcvlt_mt_end +}; +#endif /* __LIBCVLT_MEM_TYPES_H__ */ diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c new file mode 100644 index 00000000000..5b7272bb448 --- /dev/null +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c @@ -0,0 +1,842 @@ +#include <stdlib.h> +#include <glusterfs/xlator.h> +#include <glusterfs/glusterfs.h> +#include "libcvlt.h" +#include "cloudsync-common.h" +#include "cvlt-messages.h" + +#define LIBARCHIVE_SO "libopenarchive.so" +#define ALIGN_SIZE 4096 +#define CVLT_TRAILER "cvltv1" + +store_methods_t store_ops = { + .fop_download = cvlt_download, + .fop_init = cvlt_init, + .fop_reconfigure = cvlt_reconfigure, + .fop_fini = cvlt_fini, + .fop_remote_read = cvlt_read, +}; + +static const int32_t num_req = 32; +static const int32_t num_iatt = 32; +static char *plugin = "cvlt_cloudSync"; + +int32_t +mem_acct_init(xlator_t *this) +{ + int ret = -1; + + if (!this) + return ret; + + ret = xlator_mem_acct_init(this, gf_libcvlt_mt_end + 1); + + if (ret != 0) { + return ret; + } + + return ret; +} + +static void +cvlt_free_resources(archive_t *arch) +{ + /* + * We will release all the resources that were allocated by the xlator. + * Check whether there are any buffers which have not been released + * back to a mempool. + */ + + if (arch->handle) { + dlclose(arch->handle); + } + + if (arch->iobuf_pool) { + iobuf_pool_destroy(arch->iobuf_pool); + } + + if (arch->req_pool) { + mem_pool_destroy(arch->req_pool); + arch->req_pool = NULL; + } + + return; +} + +static int32_t +cvlt_extract_store_fops(xlator_t *this, archive_t *arch) +{ + int32_t op_ret = -1; + get_archstore_methods_t get_archstore_methods; + + /* + * libopenarchive.so defines methods for performing data management + * operations. We will extract the methods from library and these + * methods will be invoked for moving data between glusterfs volume + * and the data management product. + */ + + VALIDATE_OR_GOTO(arch, err); + + arch->handle = dlopen(LIBARCHIVE_SO, RTLD_NOW); + if (!arch->handle) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_DLOPEN_FAILED, + " failed to open %s ", LIBARCHIVE_SO); + return op_ret; + } + + dlerror(); /* Clear any existing error */ + + get_archstore_methods = dlsym(arch->handle, "get_archstore_methods"); + if (!get_archstore_methods) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " Error extracting get_archstore_methods()"); + dlclose(arch->handle); + arch->handle = NULL; + return op_ret; + } + + op_ret = get_archstore_methods(&(arch->fops)); + if (op_ret) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " Failed to extract methods in get_archstore_methods"); + dlclose(arch->handle); + arch->handle = NULL; + return op_ret; + } + +err: + return op_ret; +} + +static int32_t +cvlt_alloc_resources(xlator_t *this, archive_t *arch, int num_req, int num_iatt) +{ + /* + * Initialize information about all the memory pools that will be + * used by this xlator. + */ + arch->nreqs = 0; + + arch->req_pool = NULL; + + arch->handle = NULL; + arch->xl = this; + + arch->req_pool = mem_pool_new(cvlt_request_t, num_req); + if (!arch->req_pool) { + goto err; + } + + arch->iobuf_pool = iobuf_pool_new(); + if (!arch->iobuf_pool) { + goto err; + } + + if (cvlt_extract_store_fops(this, arch)) { + goto err; + } + + return 0; + +err: + + return -1; +} + +static void +cvlt_req_init(cvlt_request_t *req) +{ + sem_init(&(req->sem), 0, 0); + + return; +} + +static void +cvlt_req_destroy(cvlt_request_t *req) +{ + if (req->iobuf) { + iobuf_unref(req->iobuf); + } + + if (req->iobref) { + iobref_unref(req->iobref); + } + + sem_destroy(&(req->sem)); + + return; +} + +static cvlt_request_t * +cvlt_alloc_req(archive_t *arch) +{ + cvlt_request_t *reqptr = NULL; + + if (!arch) { + goto err; + } + + if (arch->req_pool) { + reqptr = mem_get0(arch->req_pool); + if (reqptr) { + cvlt_req_init(reqptr); + } + } + + if (reqptr) { + LOCK(&(arch->lock)); + arch->nreqs++; + UNLOCK(&(arch->lock)); + } + +err: + return reqptr; +} + +static int32_t +cvlt_free_req(archive_t *arch, cvlt_request_t *reqptr) +{ + if (!reqptr) { + goto err; + } + + if (!arch) { + goto err; + } + + if (arch->req_pool) { + /* + * Free the request resources if they exist. + */ + + cvlt_req_destroy(reqptr); + mem_put(reqptr); + + LOCK(&(arch->lock)); + arch->nreqs--; + UNLOCK(&(arch->lock)); + } + + return 0; + +err: + return -1; +} + +static int32_t +cvlt_init_xlator(xlator_t *this, archive_t *arch, int num_req, int num_iatt) +{ + int32_t ret = -1; + int32_t errnum = -1; + int32_t locked = 0; + + /* + * Perform all the initializations needed for brining up the xlator. + */ + if (!arch) { + goto err; + } + + LOCK_INIT(&(arch->lock)); + LOCK(&(arch->lock)); + + locked = 1; + + ret = cvlt_alloc_resources(this, arch, num_req, num_iatt); + + if (ret) { + goto err; + } + + /* + * Now that the fops have been extracted initialize the store + */ + ret = arch->fops.init(&(arch->descinfo), &errnum, plugin); + if (ret) { + goto err; + } + + UNLOCK(&(arch->lock)); + locked = 0; + ret = 0; + + return ret; + +err: + if (arch) { + cvlt_free_resources(arch); + + if (locked) { + UNLOCK(&(arch->lock)); + } + } + + return ret; +} + +static int32_t +cvlt_term_xlator(archive_t *arch) +{ + int32_t errnum = -1; + + if (!arch) { + goto err; + } + + LOCK(&(arch->lock)); + + /* + * Release the resources that have been allocated inside store + */ + arch->fops.fini(&(arch->descinfo), &errnum); + + cvlt_free_resources(arch); + + UNLOCK(&(arch->lock)); + + GF_FREE(arch); + + return 0; + +err: + return -1; +} + +static int32_t +cvlt_init_store_info(archive_t *priv, archstore_info_t *store_info) +{ + if (!store_info) { + return -1; + } + + store_info->prod = priv->product_id; + store_info->prodlen = strlen(priv->product_id); + + store_info->id = priv->store_id; + store_info->idlen = strlen(priv->store_id); + + return 0; +} + +static int32_t +cvlt_init_file_info(cs_loc_xattr_t *xattr, archstore_fileinfo_t *file_info) +{ + if (!xattr || !file_info) { + return -1; + } + + gf_uuid_copy(file_info->uuid, xattr->uuid); + file_info->path = xattr->file_path; + file_info->pathlength = strlen(xattr->file_path); + + return 0; +} + +static int32_t +cvlt_init_gluster_store_info(cs_loc_xattr_t *xattr, + archstore_info_t *store_info) +{ + static char *product = "glusterfs"; + + if (!xattr || !store_info) { + return -1; + } + + store_info->prod = product; + store_info->prodlen = strlen(product); + + store_info->id = xattr->volname; + store_info->idlen = strlen(xattr->volname); + + return 0; +} + +static int32_t +cvlt_init_gluster_file_info(cs_loc_xattr_t *xattr, + archstore_fileinfo_t *file_info) +{ + if (!xattr || !file_info) { + return -1; + } + + gf_uuid_copy(file_info->uuid, xattr->gfid); + file_info->path = xattr->file_path; + file_info->pathlength = strlen(xattr->file_path); + + return 0; +} + +static void +cvlt_copy_stat_info(struct iatt *buf, cs_size_xattr_t *xattrs) +{ + /* + * If the file was archived then the reported size will not be a + * correct one. We need to fix this. + */ + if (buf && xattrs) { + buf->ia_size = xattrs->size; + buf->ia_blksize = xattrs->blksize; + buf->ia_blocks = xattrs->blocks; + } + + return; +} + +static void +cvlt_readv_complete(archstore_desc_t *desc, app_callback_info_t *cbkinfo, + void *cookie, int64_t op_ret, int32_t op_errno) +{ + struct iovec iov; + xlator_t *this = NULL; + struct iatt postbuf = { + 0, + }; + call_frame_t *frame = NULL; + cvlt_request_t *req = (cvlt_request_t *)cookie; + cs_local_t *local = NULL; + cs_private_t *cspriv = NULL; + archive_t *priv = NULL; + + frame = req->frame; + this = frame->this; + local = frame->local; + + cspriv = this->private; + priv = (archive_t *)cspriv->stores->config; + + if (strcmp(priv->trailer, CVLT_TRAILER)) { + op_ret = -1; + op_errno = EINVAL; + goto out; + } + + gf_msg_debug(plugin, 0, + " Read callback invoked offset:%" PRIu64 "bytes: %" PRIu64 + " op : %d ret : %" PRId64 " errno : %d", + req->offset, req->bytes, req->op_type, op_ret, op_errno); + + if (op_ret < 0) { + goto out; + } + + req->iobref = iobref_new(); + if (!req->iobref) { + op_ret = -1; + op_errno = ENOMEM; + goto out; + } + + iobref_add(req->iobref, req->iobuf); + iov.iov_base = iobuf_ptr(req->iobuf); + iov.iov_len = op_ret; + + cvlt_copy_stat_info(&postbuf, &(req->szxattr)); + + /* + * Hack to notify higher layers of EOF. + */ + if (!postbuf.ia_size || (req->offset + iov.iov_len >= postbuf.ia_size)) { + gf_msg_debug(plugin, 0, " signalling end-of-file for uuid=%s", + uuid_utoa(req->file_info.uuid)); + op_errno = ENOENT; + } + +out: + + STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, &iov, 1, &postbuf, + req->iobref, local->xattr_rsp); + + cvlt_free_req(priv, req); + + return; +} + +static void +cvlt_download_complete(archstore_desc_t *store, app_callback_info_t *cbk_info, + void *cookie, int64_t ret, int errcode) +{ + cvlt_request_t *req = (cvlt_request_t *)cookie; + + gf_msg_debug(plugin, 0, + " Download callback invoked ret : %" PRId64 " errno : %d", + ret, errcode); + + req->op_ret = ret; + req->op_errno = errcode; + sem_post(&(req->sem)); + + return; +} + +void * +cvlt_init(xlator_t *this) +{ + int ret = 0; + archive_t *priv = NULL; + + if (!this->children || this->children->next) { + gf_msg(plugin, GF_LOG_ERROR, ENOMEM, 0, + "should have exactly one child"); + ret = -1; + goto out; + } + + if (!this->parents) { + gf_msg(plugin, GF_LOG_ERROR, ENOMEM, 0, + "dangling volume. check volfile"); + ret = -1; + goto out; + } + + priv = GF_CALLOC(1, sizeof(archive_t), gf_libcvlt_mt_cvlt_private_t); + if (!priv) { + ret = -1; + goto out; + } + + priv->trailer = CVLT_TRAILER; + if (cvlt_init_xlator(this, priv, num_req, num_iatt)) { + gf_msg(plugin, GF_LOG_ERROR, ENOMEM, 0, "xlator init failed"); + ret = -1; + goto out; + } + + GF_OPTION_INIT("cloudsync-store-id", priv->store_id, str, out); + GF_OPTION_INIT("cloudsync-product-id", priv->product_id, str, out); + + gf_msg(plugin, GF_LOG_INFO, 0, 0, + "store id is : %s " + "product id is : %s.", + priv->store_id, priv->product_id); +out: + if (ret == -1) { + cvlt_term_xlator(priv); + return (NULL); + } + return priv; +} + +int +cvlt_reconfigure(xlator_t *this, dict_t *options) +{ + cs_private_t *cspriv = NULL; + archive_t *priv = NULL; + + cspriv = this->private; + priv = (archive_t *)cspriv->stores->config; + + if (strcmp(priv->trailer, CVLT_TRAILER)) + goto out; + + GF_OPTION_RECONF("cloudsync-store-id", priv->store_id, options, str, out); + + GF_OPTION_RECONF("cloudsync-product-id", priv->product_id, options, str, + out); + gf_msg_debug(plugin, 0, + "store id is : %s " + "product id is : %s.", + priv->store_id, priv->product_id); + return 0; +out: + return -1; +} + +void +cvlt_fini(void *config) +{ + archive_t *priv = NULL; + + priv = (archive_t *)config; + + if (strcmp(priv->trailer, CVLT_TRAILER)) + return; + + cvlt_term_xlator(priv); + gf_msg(plugin, GF_LOG_INFO, 0, CVLT_FREE, " released xlator resources"); + return; +} + +int +cvlt_download(call_frame_t *frame, void *config) +{ + archive_t *parch = NULL; + cs_local_t *local = frame->local; + cs_loc_xattr_t *locxattr = local->xattrinfo.lxattr; + cvlt_request_t *req = NULL; + archstore_info_t dest_storeinfo; + archstore_fileinfo_t dest_fileinfo; + int32_t op_ret, op_errno; + + parch = (archive_t *)config; + + if (strcmp(parch->trailer, CVLT_TRAILER)) { + op_ret = -1; + op_errno = EINVAL; + goto err; + } + + gf_msg_debug(plugin, 0, " download invoked for uuid = %s gfid=%s ", + locxattr->uuid, uuid_utoa(locxattr->gfid)); + + if (!(parch->fops.restore)) { + op_errno = ELIBBAD; + goto err; + } + + /* + * Download needs to be processed. Allocate a request. + */ + req = cvlt_alloc_req(parch); + + if (!req) { + gf_msg(plugin, GF_LOG_ERROR, ENOMEM, CVLT_RESOURCE_ALLOCATION_FAILED, + " failed to allocated request for gfid=%s", + uuid_utoa(locxattr->gfid)); + op_errno = ENOMEM; + goto err; + } + + /* + * Initialize the request object. + */ + req->op_type = CVLT_RESTORE_OP; + req->frame = frame; + + /* + * The file is currently residing inside a data management store. + * To restore the file contents we need to provide the information + * about data management store. + */ + op_ret = cvlt_init_store_info(parch, &(req->store_info)); + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " failed to extract store info for gfid=%s", + uuid_utoa(locxattr->gfid)); + goto err; + } + + op_ret = cvlt_init_file_info(locxattr, &(req->file_info)); + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " failed to extract file info for gfid=%s", + uuid_utoa(locxattr->gfid)); + goto err; + } + + /* + * We need to perform in-place restore of the file from data management + * store to gusterfs volume. + */ + op_ret = cvlt_init_gluster_store_info(locxattr, &dest_storeinfo); + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " failed to extract destination store info for gfid=%s", + uuid_utoa(locxattr->gfid)); + goto err; + } + + op_ret = cvlt_init_gluster_file_info(locxattr, &dest_fileinfo); + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " failed to extract file info for gfid=%s", + uuid_utoa(locxattr->gfid)); + goto err; + } + + /* + * Submit the restore request. + */ + op_ret = parch->fops.restore(&(parch->descinfo), &(req->store_info), + &(req->file_info), &dest_storeinfo, + &dest_fileinfo, &op_errno, + cvlt_download_complete, req); + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_RESTORE_FAILED, + " failed to restore file gfid=%s from data management store", + uuid_utoa(locxattr->gfid)); + goto err; + } + + /* + * Wait for the restore to complete. + */ + sem_wait(&(req->sem)); + + if (req->op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_RESTORE_FAILED, + " restored failed for gfid=%s", uuid_utoa(locxattr->gfid)); + goto err; + } + + if (req) { + cvlt_free_req(parch, req); + } + + return 0; + +err: + + if (req) { + cvlt_free_req(parch, req); + } + + return -1; +} + +int +cvlt_read(call_frame_t *frame, void *config) +{ + int32_t op_ret = -1; + int32_t op_errno = 0; + archive_t *parch = NULL; + cvlt_request_t *req = NULL; + struct iovec iov = { + 0, + }; + struct iobref *iobref; + size_t size = 0; + off_t off = 0; + + cs_local_t *local = frame->local; + cs_loc_xattr_t *locxattr = local->xattrinfo.lxattr; + + size = local->xattrinfo.size; + off = local->xattrinfo.offset; + + parch = (archive_t *)config; + + if (strcmp(parch->trailer, CVLT_TRAILER)) { + op_ret = -1; + op_errno = EINVAL; + goto err; + } + + gf_msg_debug(plugin, 0, + " read invoked for gfid = %s offset = %" PRIu64 + " file_size = %" PRIu64, + uuid_utoa(locxattr->gfid), off, local->stbuf.ia_size); + + if (off >= local->stbuf.ia_size) { + /* + * Hack to notify higher layers of EOF. + */ + + op_errno = ENOENT; + op_ret = 0; + + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_READ_FAILED, + " reporting end-of-file for gfid=%s", uuid_utoa(locxattr->gfid)); + + goto err; + } + + if (!size) { + op_errno = EINVAL; + + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_READ_FAILED, + " zero size read attempted on gfid=%s", + uuid_utoa(locxattr->gfid)); + goto err; + } + + if (!(parch->fops.read)) { + op_errno = ELIBBAD; + goto err; + } + + /* + * The read request need to be processed. Allocate a request. + */ + req = cvlt_alloc_req(parch); + + if (!req) { + gf_msg(plugin, GF_LOG_ERROR, ENOMEM, CVLT_NO_MEMORY, + " failed to allocated request for gfid=%s", + uuid_utoa(locxattr->gfid)); + op_errno = ENOMEM; + goto err; + } + + req->iobuf = iobuf_get_page_aligned(parch->iobuf_pool, size, ALIGN_SIZE); + if (!req->iobuf) { + op_errno = ENOMEM; + goto err; + } + + /* + * Initialize the request object. + */ + req->op_type = CVLT_READ_OP; + req->offset = off; + req->bytes = size; + req->frame = frame; + req->szxattr.size = local->stbuf.ia_size; + req->szxattr.blocks = local->stbuf.ia_blocks; + req->szxattr.blksize = local->stbuf.ia_blksize; + + /* + * The file is currently residing inside a data management store. + * To read the file contents we need to provide the information + * about data management store. + */ + op_ret = cvlt_init_store_info(parch, &(req->store_info)); + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " failed to extract store info for gfid=%s" + " offset=%" PRIu64 " size=%" GF_PRI_SIZET + ", " + " buf=%p", + uuid_utoa(locxattr->gfid), off, size, req->iobuf->ptr); + goto err; + } + + op_ret = cvlt_init_file_info(locxattr, &(req->file_info)); + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " failed to extract file info for gfid=%s" + " offset=%" PRIu64 " size=%" GF_PRI_SIZET + ", " + " buf=%p", + uuid_utoa(locxattr->gfid), off, size, req->iobuf->ptr); + goto err; + } + + /* + * Submit the read request. + */ + op_ret = parch->fops.read(&(parch->descinfo), &(req->store_info), + &(req->file_info), off, req->iobuf->ptr, size, + &op_errno, cvlt_readv_complete, req); + + if (op_ret < 0) { + gf_msg(plugin, GF_LOG_ERROR, 0, CVLT_EXTRACTION_FAILED, + " read failed on gfid=%s" + " offset=%" PRIu64 " size=%" GF_PRI_SIZET + ", " + " buf=%p", + uuid_utoa(locxattr->gfid), off, size, req->iobuf->ptr); + goto err; + } + + return 0; + +err: + + iobref = iobref_new(); + gf_msg_debug(plugin, 0, " read unwinding stack op_ret = %d, op_errno = %d", + op_ret, op_errno); + + STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, &iov, 1, + &(local->stbuf), iobref, local->xattr_rsp); + + if (iobref) { + iobref_unref(iobref); + } + + if (req) { + cvlt_free_req(parch, req); + } + + return 0; +} diff --git a/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h new file mode 100644 index 00000000000..c45ac948f6c --- /dev/null +++ b/xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h @@ -0,0 +1,84 @@ +/* + Copyright (c) 2018 Commvault Systems, Inc. <http://www.commvault.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ +#ifndef _LIBCVLT_H +#define _LIBCVLT_H + +#include <semaphore.h> +#include <glusterfs/xlator.h> +#include <glusterfs/glusterfs.h> +#include <glusterfs/call-stub.h> +#include <glusterfs/syncop.h> +#include <glusterfs/compat-errno.h> +#include "cloudsync-common.h" +#include "libcvlt-mem-types.h" +#include "archivestore.h" + +enum _cvlt_op { + CVLT_READ_OP = 1, + CVLT_WRITE_OP = 2, + CVLT_RESTORE_OP = 3, + CVLT_ARCHIVE_OP = 4, + CVLT_LOOKUP_OP = 5, + CVLT_XATTR_OP = 6, + CVLT_STAT_OP = 7, + CVLT_FSTAT_op = 8, + CVLT_UNDEF_OP = 127 +}; +typedef enum _cvlt_op cvlt_op_t; + +struct _archive; +struct _cvlt_request { + uint64_t offset; + uint64_t bytes; + struct iobuf *iobuf; + struct iobref *iobref; + call_frame_t *frame; + cvlt_op_t op_type; + int32_t op_ret; + int32_t op_errno; + xlator_t *this; + sem_t sem; + archstore_info_t store_info; + archstore_fileinfo_t file_info; + cs_size_xattr_t szxattr; +}; +typedef struct _cvlt_request cvlt_request_t; + +struct _archive { + gf_lock_t lock; /* lock for controlling access */ + xlator_t *xl; /* xlator */ + void *handle; /* handle returned from dlopen */ + int32_t nreqs; /* num requests active */ + struct mem_pool *req_pool; /* pool for requests */ + struct iobuf_pool *iobuf_pool; /* iobuff pool */ + archstore_desc_t descinfo; /* Archive store descriptor info */ + archstore_methods_t fops; /* function pointers */ + char *product_id; + char *store_id; + char *trailer; +}; +typedef struct _archive archive_t; + +void * +cvlt_init(xlator_t *); + +int +cvlt_reconfigure(xlator_t *, dict_t *); + +void +cvlt_fini(void *); + +int +cvlt_download(call_frame_t *, void *); + +int +cvlt_read(call_frame_t *, void *); + +#endif diff --git a/xlators/features/cloudsync/src/cloudsync.c b/xlators/features/cloudsync/src/cloudsync.c index cb2cefa4d01..7f0b9e563b8 100644 --- a/xlators/features/cloudsync/src/cloudsync.c +++ b/xlators/features/cloudsync/src/cloudsync.c @@ -8,17 +8,18 @@ * cases as published by the Free Software Foundation. */ -#include "glusterfs.h" -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "cloudsync.h" #include "cloudsync-common.h" -#include "call-stub.h" +#include <glusterfs/call-stub.h> #include "cloudsync-autogen-fops.h" +#include <string.h> #include <dlfcn.h> -void +static void cs_cleanup_private(cs_private_t *priv) { if (priv) { @@ -34,11 +35,15 @@ cs_cleanup_private(cs_private_t *priv) return; } -struct cs_plugin plugins[] = { +static struct cs_plugin plugins[] = { {.name = "cloudsyncs3", .library = "cloudsyncs3.so", .description = "cloudsync s3 store."}, - +#if defined(__linux__) + {.name = "cvlt", + .library = "cloudsynccvlt.so", + .description = "Commvault content store."}, +#endif {.name = NULL}, }; @@ -72,12 +77,14 @@ cs_init(xlator_t *this) this->private = priv; + GF_OPTION_INIT("cloudsync-remote-read", priv->remote_read, bool, out); + /* temp workaround. Should be configurable through glusterd*/ per_vol = _gf_true; if (per_vol) { - if (dict_get_str(this->options, "cloudsync-storetype", &temp_str) == - 0) { + if (dict_get_str_sizen(this->options, "cloudsync-storetype", + &temp_str) == 0) { for (index = 0; plugins[index].name; index++) { if (!strcmp(temp_str, plugins[index].name)) { libname = plugins[index].library; @@ -135,6 +142,18 @@ cs_init(xlator_t *this) (void)dlerror(); + if (priv->remote_read) { + priv->stores->rdfop = store_methods->fop_remote_read; + if (!priv->stores->rdfop) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "failed to get" + " read fop %s", + dlerror()); + ret = -1; + goto out; + } + } + priv->stores->dlfop = store_methods->fop_download; if (!priv->stores->dlfop) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, @@ -181,8 +200,10 @@ cs_init(xlator_t *this) out: if (ret == -1) { - if (this->local_pool) + if (this->local_pool) { mem_pool_destroy(this->local_pool); + this->local_pool = NULL; + } cs_cleanup_private(priv); @@ -196,6 +217,22 @@ out: return ret; } +int +cs_forget(xlator_t *this, inode_t *inode) +{ + uint64_t ctx_int = 0; + cs_inode_ctx_t *ctx = NULL; + + inode_ctx_del(inode, this, &ctx_int); + if (!ctx_int) + return 0; + + ctx = (cs_inode_ctx_t *)(uintptr_t)ctx_int; + + GF_FREE(ctx); + return 0; +} + void cs_fini(xlator_t *this) { @@ -217,6 +254,9 @@ cs_reconfigure(xlator_t *this, dict_t *options) goto out; } + GF_OPTION_RECONF("cloudsync-remote-read", priv->remote_read, options, bool, + out); + /* needed only for per volume configuration*/ ret = priv->stores->reconfigure(this, options); @@ -242,32 +282,6 @@ out: } int32_t -cs_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, - dict_t *xdata) -{ - gf_dirent_t *tmp = NULL; - char *sxattr = NULL; - uint64_t ia_size = 0; - int ret = 0; - - list_for_each_entry(tmp, &entries->list, list) - { - ret = dict_get_str(tmp->dict, GF_CS_OBJECT_SIZE, &sxattr); - if (ret) { - gf_msg_trace(this->name, 0, "size xattr found"); - continue; - } - - ia_size = atoll(sxattr); - tmp->d_stat.ia_size = ia_size; - } - - STACK_UNWIND_STRICT(readdirp, frame, op_ret, op_errno, entries, xdata); - return 0; -} - -int32_t cs_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *xdata) { @@ -277,16 +291,23 @@ cs_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, if (!xdata) { xdata = dict_new(); if (!xdata) { + gf_msg(this->name, GF_LOG_ERROR, 0, ENOMEM, + "failed to create " + "dict"); goto err; } } - ret = dict_set_int32(xdata, GF_CS_OBJECT_SIZE, 1); + ret = dict_set_uint32(xdata, GF_CS_OBJECT_STATUS, 1); if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "dict_set failed key:" + " %s", + GF_CS_OBJECT_STATUS); goto err; } - STACK_WIND(frame, cs_readdirp_cbk, FIRST_CHILD(this), + STACK_WIND(frame, default_readdirp_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, fd, size, off, xdata); return 0; err: @@ -305,7 +326,6 @@ cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, local = frame->local; - /* Do we need lock here? */ local->call_cnt++; if (op_ret == -1) { @@ -320,13 +340,13 @@ cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto unwind; } else { __cs_inode_ctx_update(this, local->loc.inode, val); - gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %ld", val); + gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %" PRIu64, val); if (local->call_cnt == 1 && (val == GF_CS_REMOTE || val == GF_CS_DOWNLOADING)) { gf_msg(this->name, GF_LOG_WARNING, 0, 0, "will repair and download " - "the file, current state : %ld", + "the file, current state : %" PRIu64, val); goto repair; } else { @@ -368,7 +388,6 @@ int32_t cs_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata) { - int op_errno = -1; cs_local_t *local = NULL; int ret = 0; cs_inode_ctx_t *ctx = NULL; @@ -381,14 +400,13 @@ cs_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, local = cs_local_init(this, frame, loc, NULL, GF_FOP_TRUNCATE); if (!local) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "local init failed"); - op_errno = ENOMEM; goto err; } __cs_inode_ctx_get(this, loc->inode, &ctx); if (ctx) - state = __cs_get_file_state(this, loc->inode, ctx); + state = __cs_get_file_state(loc->inode, ctx); else state = GF_CS_LOCAL; @@ -407,7 +425,6 @@ cs_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, xdata); if (!local->stub) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory"); - op_errno = ENOMEM; goto err; } @@ -419,14 +436,13 @@ cs_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, local->call_cnt++; ret = locate_and_execute(frame); if (ret) { - op_errno = ENOMEM; goto err; } } return 0; err: - CS_STACK_UNWIND(truncate, frame, -1, op_errno, NULL, NULL, NULL); + CS_STACK_UNWIND(truncate, frame, -1, ENOMEM, NULL, NULL, NULL); return 0; } @@ -498,7 +514,7 @@ cs_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, local->xattr_req = xdata ? dict_ref(xdata) : (xdata = dict_new()); - tmp = dict_get(dict, GF_CS_OBJECT_UPLOAD_COMPLETE); + tmp = dict_get_sizen(dict, GF_CS_OBJECT_UPLOAD_COMPLETE); if (tmp) { /* Value of key should be the atime */ local->stub = fop_setxattr_stub(frame, cs_resume_setxattr, loc, dict, @@ -665,7 +681,7 @@ cs_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, if (op_ret == 0) { ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val); if (!ret) { - gf_msg_debug(this->name, 0, "state %ld", val); + gf_msg_debug(this->name, 0, "state %" PRIu64, val); ret = __cs_inode_ctx_update(this, fd->inode, val); if (ret) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx update failed"); @@ -831,7 +847,7 @@ out: return 0; } -void * +int cs_download_task(void *arg) { call_frame_t *frame = NULL; @@ -842,7 +858,6 @@ cs_download_task(void *arg) fd_t *fd = NULL; cs_local_t *local = NULL; dict_t *dict = NULL; - int *retval = NULL; frame = (call_frame_t *)arg; @@ -850,13 +865,6 @@ cs_download_task(void *arg) priv = this->private; - retval = GF_CALLOC(1, sizeof(int), gf_common_mt_int); - if (!retval) { - gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory"); - ret = -1; - goto out; - } - if (!priv->stores) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "No remote store " @@ -915,7 +923,8 @@ cs_download_task(void *arg) local->remotepath); /*using dlfd as it is anonymous and have RDWR flag*/ - ret = syncop_ftruncate(FIRST_CHILD(this), local->dlfd, 0, NULL, NULL); + ret = syncop_ftruncate(FIRST_CHILD(this), local->dlfd, 0, NULL, NULL, + NULL, NULL); if (ret) { gf_msg(this->name, GF_LOG_ERROR, 0, -ret, "ftruncate failed"); } else { @@ -971,20 +980,13 @@ out: local->dlfd = NULL; } - if (retval) { - *retval = ret; - pthread_exit(retval); - } else { - pthread_exit(&ret); - } + return ret; } int cs_download(call_frame_t *frame) { - int *retval = NULL; int ret = 0; - pthread_t dthread; cs_local_t *local = NULL; xlator_t *this = NULL; @@ -999,16 +1001,404 @@ cs_download(call_frame_t *frame) goto out; } - ret = gf_thread_create(&dthread, NULL, &cs_download_task, (void *)frame, - "downloadthread"); + ret = cs_download_task((void *)frame); +out: + return ret; +} + +int +cs_set_xattr_req(call_frame_t *frame) +{ + cs_local_t *local = NULL; + GF_UNUSED int ret = 0; + + local = frame->local; + + /* When remote reads are performed (i.e. reads on remote store), + * there needs to be a way to associate a file on gluster volume + * with its correspnding file on the remote store. In order to do + * that, a unique key can be maintained as an xattr + * (GF_CS_XATTR_ARCHIVE_UUID)on the stub file on gluster bricks. + * This xattr should be provided to the plugin to + * perform the read fop on the correct file. This assumes that the file + * hierarchy and name need not be the same on remote store as that of + * the gluster volume. + */ + ret = dict_set_sizen_str_sizen(local->xattr_req, GF_CS_XATTR_ARCHIVE_UUID, + "1"); + + return 0; +} + +int +cs_update_xattrs(call_frame_t *frame, dict_t *xdata) +{ + cs_local_t *local = NULL; + xlator_t *this = NULL; + int size = -1; + GF_UNUSED int ret = 0; + + local = frame->local; + this = frame->this; + + local->xattrinfo.lxattr = GF_CALLOC(1, sizeof(cs_loc_xattr_t), + gf_cs_mt_cs_lxattr_t); + if (!local->xattrinfo.lxattr) { + local->op_ret = -1; + local->op_errno = ENOMEM; + goto err; + } + + gf_uuid_copy(local->xattrinfo.lxattr->gfid, local->loc.gfid); + + if (local->remotepath) { + local->xattrinfo.lxattr->file_path = gf_strdup(local->remotepath); + if (!local->xattrinfo.lxattr->file_path) { + local->op_ret = -1; + local->op_errno = ENOMEM; + goto err; + } + } - pthread_join(dthread, (void **)&retval); + ret = dict_get_gfuuid(xdata, GF_CS_XATTR_ARCHIVE_UUID, + &(local->xattrinfo.lxattr->uuid)); - ret = *retval; + if (ret) { + gf_uuid_clear(local->xattrinfo.lxattr->uuid); + } + size = strlen(this->name) - strlen("-cloudsync") + 1; + local->xattrinfo.lxattr->volname = GF_CALLOC(1, size, gf_common_mt_char); + if (!local->xattrinfo.lxattr->volname) { + local->op_ret = -1; + local->op_errno = ENOMEM; + goto err; + } + strncpy(local->xattrinfo.lxattr->volname, this->name, size - 1); + local->xattrinfo.lxattr->volname[size - 1] = '\0'; + + return 0; +err: + cs_xattrinfo_wipe(local); + return -1; +} + +int +cs_serve_readv(call_frame_t *frame, off_t offset, size_t size, uint32_t flags) +{ + xlator_t *this = NULL; + cs_private_t *priv = NULL; + int ret = -1; + fd_t *fd = NULL; + cs_local_t *local = NULL; + + local = frame->local; + this = frame->this; + priv = this->private; + + if (!local->remotepath) { + ret = -1; + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "remote path not" + " available. Check posix logs to resolve"); + goto out; + } + + if (!priv->stores) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "No remote store " + "plugins found"); + ret = -1; + goto out; + } + + if (local->fd) { + fd = fd_anonymous(local->fd->inode); + } else { + fd = fd_anonymous(local->loc.inode); + } + + local->xattrinfo.size = size; + local->xattrinfo.offset = offset; + local->xattrinfo.flags = flags; + + if (!fd) { + gf_msg("CS", GF_LOG_ERROR, 0, 0, "fd creation failed"); + ret = -1; + goto out; + } + + local->dlfd = fd; + local->dloffset = offset; + + /*this calling method is for per volume setting */ + ret = priv->stores->rdfop(frame, priv->stores->config); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "read failed" + ", remotepath: %s", + local->remotepath); + ret = -1; + goto out; + } else { + gf_msg(this->name, GF_LOG_INFO, 0, 0, + "read success, path" + " : %s", + local->remotepath); + } out: - if (retval) - GF_FREE(retval); + if (fd) { + fd_unref(fd); + local->dlfd = NULL; + } + return ret; +} + +int32_t +cs_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iovec *vector, int32_t count, + struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) +{ + cs_local_t *local = NULL; + int ret = 0; + uint64_t val = 0; + fd_t *fd = NULL; + + local = frame->local; + fd = local->fd; + + local->call_cnt++; + + if (op_ret == -1) { + ret = dict_get_uint64(xdata, GF_CS_OBJECT_STATUS, &val); + if (ret == 0) { + if (val == GF_CS_ERROR) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "could not get file state, unwinding"); + op_ret = -1; + op_errno = EIO; + goto unwind; + } else { + __cs_inode_ctx_update(this, fd->inode, val); + gf_msg(this->name, GF_LOG_INFO, 0, 0, " state = %" PRIu64, val); + + if (local->call_cnt == 1 && + (val == GF_CS_REMOTE || val == GF_CS_DOWNLOADING)) { + gf_msg(this->name, GF_LOG_INFO, 0, 0, + " will read from remote : %" PRIu64, val); + goto repair; + } else { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "second readv, Unwinding"); + goto unwind; + } + } + } else { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "file state " + "could not be figured, unwinding"); + goto unwind; + } + } else { + /* successful readv => file is local */ + __cs_inode_ctx_update(this, fd->inode, GF_CS_LOCAL); + gf_msg(this->name, GF_LOG_INFO, 0, 0, + "state : GF_CS_LOCAL" + ", readv successful"); + + goto unwind; + } + +repair: + ret = locate_and_execute(frame); + if (ret) { + goto unwind; + } + + return 0; + +unwind: + CS_STACK_UNWIND(readv, frame, op_ret, op_errno, vector, count, stbuf, + iobref, xdata); + + return 0; +} + +int32_t +cs_resume_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata) +{ + int ret = 0; + + ret = cs_resume_postprocess(this, frame, fd->inode); + if (ret) { + goto unwind; + } + + cs_inodelk_unlock(frame); + + STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata); + + return 0; + +unwind: + cs_inodelk_unlock(frame); + + cs_common_cbk(frame); + + return 0; +} + +int32_t +cs_resume_remote_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t offset, uint32_t flags, dict_t *xdata) +{ + int ret = 0; + cs_local_t *local = NULL; + gf_cs_obj_state state = -1; + cs_inode_ctx_t *ctx = NULL; + + cs_inodelk_unlock(frame); + + local = frame->local; + if (!local) { + ret = -1; + goto unwind; + } + + __cs_inode_ctx_get(this, fd->inode, &ctx); + + state = __cs_get_file_state(fd->inode, ctx); + if (state == GF_CS_ERROR) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "status is GF_CS_ERROR." + " Aborting readv"); + local->op_ret = -1; + local->op_errno = EREMOTE; + ret = -1; + goto unwind; + } + + /* Serve readv from remote store only if it is remote. */ + gf_msg_debug(this->name, 0, "status of file %s is %d", + local->remotepath ? local->remotepath : "", state); + + /* We will reach this condition if local inode ctx had REMOTE + * state when the control was in cs_readv but after stat + * we got an updated state saying that the file is LOCAL. + */ + if (state == GF_CS_LOCAL) { + STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, + xdata); + } else if (state == GF_CS_REMOTE) { + ret = cs_resume_remote_readv_postprocess(this, frame, fd->inode, offset, + size, flags); + /* Failed to submit the remote readv fop to plugin */ + if (ret) { + local->op_ret = -1; + local->op_errno = EREMOTE; + goto unwind; + } + /* When the file is in any other intermediate state, + * we should not perform remote reads. + */ + } else { + local->op_ret = -1; + local->op_errno = EINVAL; + goto unwind; + } + + return 0; + +unwind: + cs_common_cbk(frame); + + return 0; +} + +int32_t +cs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata) +{ + int op_errno = ENOMEM; + cs_local_t *local = NULL; + int ret = 0; + cs_inode_ctx_t *ctx = NULL; + gf_cs_obj_state state = -1; + cs_private_t *priv = NULL; + + VALIDATE_OR_GOTO(frame, err); + VALIDATE_OR_GOTO(this, err); + VALIDATE_OR_GOTO(fd, err); + + priv = this->private; + + local = cs_local_init(this, frame, NULL, fd, GF_FOP_READ); + if (!local) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, "local init failed"); + goto err; + } + + __cs_inode_ctx_get(this, fd->inode, &ctx); + + if (ctx) + state = __cs_get_file_state(fd->inode, ctx); + else + state = GF_CS_LOCAL; + + local->xattr_req = xdata ? dict_ref(xdata) : (xdata = dict_new()); + + ret = dict_set_uint32(local->xattr_req, GF_CS_OBJECT_STATUS, 1); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, + "dict_set failed key:" + " %s", + GF_CS_OBJECT_STATUS); + goto err; + } + + if (priv->remote_read) { + local->stub = fop_readv_stub(frame, cs_resume_remote_readv, fd, size, + offset, flags, xdata); + } else { + local->stub = fop_readv_stub(frame, cs_resume_readv, fd, size, offset, + flags, xdata); + } + if (!local->stub) { + gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insufficient memory"); + goto err; + } + + if (state == GF_CS_LOCAL) { + STACK_WIND(frame, cs_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, + xdata); + } else { + local->call_cnt++; + ret = locate_and_execute(frame); + if (ret) { + goto err; + } + } + + return 0; + +err: + CS_STACK_UNWIND(readv, frame, -1, op_errno, NULL, -1, NULL, NULL, NULL); + + return 0; +} + +int +cs_resume_remote_readv_postprocess(xlator_t *this, call_frame_t *frame, + inode_t *inode, off_t offset, size_t size, + uint32_t flags) +{ + int ret = 0; + + ret = cs_serve_readv(frame, offset, size, flags); return ret; } @@ -1058,7 +1448,7 @@ cs_stat_check_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, goto err; } else { ret = __cs_inode_ctx_update(this, inode, val); - gf_msg_debug(this->name, 0, "status : %lu", val); + gf_msg_debug(this->name, 0, "status : %" PRIu64, val); if (ret) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "ctx update failed"); local->op_ret = -1; @@ -1073,7 +1463,7 @@ cs_stat_check_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, goto err; } - ret = dict_get_str(xdata, GF_CS_OBJECT_REMOTE, &filepath); + ret = dict_get_str_sizen(xdata, GF_CS_OBJECT_REMOTE, &filepath); if (filepath) { gf_msg_debug(this->name, 0, "filepath returned %s", filepath); local->remotepath = gf_strdup(filepath); @@ -1086,6 +1476,10 @@ cs_stat_check_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, gf_msg_debug(this->name, 0, "NULL filepath"); } + ret = cs_update_xattrs(frame, xdata); + if (ret) + goto err; + local->op_ret = 0; local->xattr_rsp = dict_ref(xdata); memcpy(&local->stbuf, stbuf, sizeof(struct iatt)); @@ -1120,6 +1514,8 @@ cs_do_stat_check(call_frame_t *main_frame) goto err; } + cs_set_xattr_req(main_frame); + if (local->fd) { STACK_WIND(main_frame, cs_stat_check_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fstat, local->fd, local->xattr_req); @@ -1176,6 +1572,10 @@ cs_common_cbk(call_frame_t *frame) NULL, NULL, NULL); break; + case GF_FOP_TRUNCATE: + CS_STACK_UNWIND(truncate, frame, local->op_ret, local->op_errno, + NULL, NULL, NULL); + break; default: break; } @@ -1262,14 +1662,14 @@ cs_blocking_inodelk(call_frame_t *parent_frame) }; int ret = 0; + this = parent_frame->this; + lock_frame = cs_lock_frame(parent_frame); if (!lock_frame) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "insuffcient memory"); goto err; } - this = parent_frame->this; - lock_local = cs_local_init(this, lock_frame, NULL, NULL, 0); if (!lock_local) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "local init failed"); @@ -1353,7 +1753,7 @@ cs_resume_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, __cs_inode_ctx_get(this, loc->inode, &ctx); - state = __cs_get_file_state(this, loc->inode, ctx); + state = __cs_get_file_state(loc->inode, ctx); if (state == GF_CS_ERROR) { /* file is already remote */ @@ -1395,7 +1795,7 @@ unwind: } gf_cs_obj_state -__cs_get_file_state(xlator_t *this, inode_t *inode, cs_inode_ctx_t *ctx) +__cs_get_file_state(inode_t *inode, cs_inode_ctx_t *ctx) { gf_cs_obj_state state = -1; @@ -1426,7 +1826,7 @@ __cs_inode_ctx_get(xlator_t *this, inode_t *inode, cs_inode_ctx_t **ctx) if (ret) *ctx = NULL; else - *ctx = (cs_inode_ctx_t *)ctxint; + *ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint; return; } @@ -1451,7 +1851,7 @@ __cs_inode_ctx_update(xlator_t *this, inode_t *inode, uint64_t val) ctx->state = val; - ctxint = (uint64_t)ctx; + ctxint = (uint64_t)(uintptr_t)ctx; ret = __inode_ctx_set(inode, this, &ctxint); if (ret) { @@ -1459,7 +1859,7 @@ __cs_inode_ctx_update(xlator_t *this, inode_t *inode, uint64_t val) goto out; } } else { - ctx = (cs_inode_ctx_t *)ctxint; + ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint; ctx->state = val; } @@ -1482,7 +1882,7 @@ cs_inode_ctx_reset(xlator_t *this, inode_t *inode) return 0; } - ctx = (cs_inode_ctx_t *)ctxint; + ctx = (cs_inode_ctx_t *)(uintptr_t)ctxint; GF_FREE(ctx); return 0; @@ -1504,7 +1904,7 @@ cs_resume_postprocess(xlator_t *this, call_frame_t *frame, inode_t *inode) __cs_inode_ctx_get(this, inode, &ctx); - state = __cs_get_file_state(this, inode, ctx); + state = __cs_get_file_state(inode, ctx); if (state == GF_CS_ERROR) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "status is GF_CS_ERROR." @@ -1531,6 +1931,7 @@ cs_resume_postprocess(xlator_t *this, call_frame_t *frame, inode_t *inode) out: return ret; } + int32_t cs_fdctx_to_dict(xlator_t *this, fd_t *fd, dict_t *dict) { @@ -1626,7 +2027,9 @@ struct xlator_fops cs_fops = { .zerofill = cs_zerofill, }; -struct xlator_cbks cs_cbks = {}; +struct xlator_cbks cs_cbks = { + .forget = cs_forget, +}; struct xlator_dumpops cs_dumpops = { .fdctx_to_dict = cs_fdctx_to_dict, @@ -1646,6 +2049,15 @@ struct volume_options cs_options[] = { {.key = {"cloudsync-storetype"}, .type = GF_OPTION_TYPE_STR, .description = "Defines which remote store is enabled"}, + {.key = {"cloudsync-remote-read"}, + .type = GF_OPTION_TYPE_BOOL, + .description = "Defines a remote read fop when on"}, + {.key = {"cloudsync-store-id"}, + .type = GF_OPTION_TYPE_STR, + .description = "Defines a volume wide store id"}, + {.key = {"cloudsync-product-id"}, + .type = GF_OPTION_TYPE_STR, + .description = "Defines a volume wide product id"}, {.key = {NULL}}, }; diff --git a/xlators/features/cloudsync/src/cloudsync.h b/xlators/features/cloudsync/src/cloudsync.h index 7c70c744d2b..d24141978d6 100644 --- a/xlators/features/cloudsync/src/cloudsync.h +++ b/xlators/features/cloudsync/src/cloudsync.h @@ -11,14 +11,15 @@ #ifndef __CLOUDSYNC_H__ #define __CLOUDSYNC_H__ -#include "glusterfs.h" -#include "xlator.h" -#include "defaults.h" -#include "syncop.h" -#include "call-stub.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/syncop.h> +#include <glusterfs/call-stub.h> #include "cloudsync-common.h" #include "cloudsync-autogen-fops.h" +#define ALIGN_SIZE 4096 #define CS_LOCK_DOMAIN "cs.protect.file.stat" typedef struct cs_dlstore { off_t off; @@ -29,6 +30,7 @@ typedef struct cs_dlstore { } cs_dlstore; typedef struct cs_inode_ctx { + cs_loc_xattr_t locxattr; gf_cs_obj_state state; } cs_inode_ctx_t; @@ -85,7 +87,7 @@ void __cs_inode_ctx_get(xlator_t *this, inode_t *inode, cs_inode_ctx_t **ctx); gf_cs_obj_state -__cs_get_file_state(xlator_t *this, inode_t *inode, cs_inode_ctx_t *ctx); +__cs_get_file_state(inode_t *inode, cs_inode_ctx_t *ctx); int cs_inodelk_unlock(call_frame_t *main_frame); @@ -100,4 +102,22 @@ cs_truncate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t cs_resume_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xattr_req); + +int32_t +cs_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iovec *vector, int32_t count, + struct iatt *stbuf, struct iobref *iobref, dict_t *xdata); +int32_t +cs_resume_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata); +int32_t +cs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata); + +int +cs_resume_remote_readv_postprocess(xlator_t *this, call_frame_t *frame, + inode_t *inode, off_t offset, size_t size, + uint32_t flags); +int +cs_serve_readv(call_frame_t *frame, off_t offset, size_t size, uint32_t flags); #endif /* __CLOUDSYNC_H__ */ diff --git a/xlators/features/compress/src/cdc-helper.c b/xlators/features/compress/src/cdc-helper.c index 71f446d51cd..f973ff56cf5 100644 --- a/xlators/features/compress/src/cdc-helper.c +++ b/xlators/features/compress/src/cdc-helper.c @@ -8,9 +8,9 @@ cases as published by the Free Software Foundation. */ -#include "glusterfs.h" -#include "logging.h" -#include "syscall.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/syscall.h> #include "cdc.h" #include "cdc-mem-types.h" diff --git a/xlators/features/compress/src/cdc-mem-types.h b/xlators/features/compress/src/cdc-mem-types.h index 56a5a05ee8c..928afdd2efe 100644 --- a/xlators/features/compress/src/cdc-mem-types.h +++ b/xlators/features/compress/src/cdc-mem-types.h @@ -11,7 +11,7 @@ #ifndef __CDC_MEM_TYPES_H #define __CDC_MEM_TYPES_H -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_cdc_mem_types { gf_cdc_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/compress/src/cdc.c b/xlators/features/compress/src/cdc.c index 25ea6dc1846..b0b51e914ed 100644 --- a/xlators/features/compress/src/cdc.c +++ b/xlators/features/compress/src/cdc.c @@ -10,9 +10,9 @@ #include <sys/uio.h> -#include "xlator.h" -#include "defaults.h" -#include "logging.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/logging.h> #include "cdc.h" #include "cdc-mem-types.h" @@ -118,8 +118,8 @@ cdc_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, }; size_t isize = 0; - GF_VALIDATE_OR_GOTO("cdc", this, default_out); - GF_VALIDATE_OR_GOTO(this->name, frame, default_out); + GF_VALIDATE_OR_GOTO("cdc", this, err); + GF_VALIDATE_OR_GOTO(this->name, frame, err); priv = this->private; @@ -167,6 +167,9 @@ default_out: FIRST_CHILD(this)->fops->writev, fd, vector, count, offset, flags, iobref, xdata); return 0; +err: + STACK_UNWIND_STRICT(writev, frame, -1, EINVAL, NULL, NULL, NULL); + return 0; } int32_t @@ -331,3 +334,15 @@ struct volume_options options[] = { "to disk as a gzip file."}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .mem_acct_init = mem_acct_init, + .op_version = {GD_OP_VERSION_3_9_0}, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "cdc", + .category = GF_TECH_PREVIEW, +}; diff --git a/xlators/features/compress/src/cdc.h b/xlators/features/compress/src/cdc.h index 764f2028c75..cb87b06a989 100644 --- a/xlators/features/compress/src/cdc.h +++ b/xlators/features/compress/src/cdc.h @@ -15,7 +15,7 @@ #include "zlib.h" #endif -#include "xlator.h" +#include <glusterfs/xlator.h> #ifndef MAX_IOVEC #define MAX_IOVEC 16 diff --git a/xlators/features/gfid-access/src/gfid-access-mem-types.h b/xlators/features/gfid-access/src/gfid-access-mem-types.h index ee7fd794da8..1c4d0b93de2 100644 --- a/xlators/features/gfid-access/src/gfid-access-mem-types.h +++ b/xlators/features/gfid-access/src/gfid-access-mem-types.h @@ -11,7 +11,7 @@ #ifndef _GFID_ACCESS_MEM_TYPES_H #define _GFID_ACCESS_MEM_TYPES_H -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_changelog_mem_types { gf_gfid_access_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/gfid-access/src/gfid-access.c b/xlators/features/gfid-access/src/gfid-access.c index 7280d9ce416..3fea5672a21 100644 --- a/xlators/features/gfid-access/src/gfid-access.c +++ b/xlators/features/gfid-access/src/gfid-access.c @@ -8,9 +8,9 @@ cases as published by the Free Software Foundation. */ #include "gfid-access.h" -#include "inode.h" -#include "byte-order.h" -#include "statedump.h" +#include <glusterfs/inode.h> +#include <glusterfs/byte-order.h> +#include <glusterfs/statedump.h> int ga_valid_inode_loc_copy(loc_t *dst, loc_t *src, xlator_t *this) @@ -35,7 +35,7 @@ ga_valid_inode_loc_copy(loc_t *dst, loc_t *src, xlator_t *this) goto out; } inode_unref(dst->parent); - dst->parent = inode_ref((inode_t *)value); + dst->parent = inode_ref((inode_t *)(uintptr_t)value); gf_uuid_copy(dst->pargfid, dst->parent->gfid); } @@ -46,7 +46,7 @@ ga_valid_inode_loc_copy(loc_t *dst, loc_t *src, xlator_t *this) goto out; } inode_unref(dst->inode); - dst->inode = inode_ref((inode_t *)value); + dst->inode = inode_ref((inode_t *)(uintptr_t)value); gf_uuid_copy(dst->gfid, dst->inode->gfid); } out: @@ -284,7 +284,7 @@ ga_fill_tmp_loc(loc_t *loc, xlator_t *this, uuid_t gfid, char *bname, parent = loc->inode; ret = inode_ctx_get(loc->inode, this, &value); if (!ret) { - parent = (void *)value; + parent = (void *)(uintptr_t)value; if (gf_uuid_is_null(parent->gfid)) parent = loc->inode; } @@ -327,10 +327,8 @@ out: static gf_boolean_t __is_gfid_access_dir(uuid_t gfid) { - uuid_t aux_gfid; - - memset(aux_gfid, 0, 16); - aux_gfid[15] = GF_AUX_GFID; + static uuid_t aux_gfid = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, GF_AUX_GFID}; if (gf_uuid_compare(gfid, aux_gfid) == 0) return _gf_true; @@ -349,7 +347,7 @@ ga_forget(xlator_t *this, inode_t *inode) if (ret) goto out; - tmp_inode = (void *)value; + tmp_inode = (void *)(uintptr_t)value; inode_unref(tmp_inode); out: @@ -448,14 +446,6 @@ ga_new_entry(call_frame_t *frame, xlator_t *this, loc_t *loc, data_t *data, 0, }; - args = ga_newfile_parse_args(this, data); - if (!args) - goto out; - - ret = gf_uuid_parse(args->gfid, gfid); - if (ret) - goto out; - if (!xdata) { xdata = dict_new(); } else { @@ -467,6 +457,14 @@ ga_new_entry(call_frame_t *frame, xlator_t *this, loc_t *loc, data_t *data, goto out; } + args = ga_newfile_parse_args(this, data); + if (!args) + goto out; + + ret = gf_uuid_parse(args->gfid, gfid); + if (ret) + goto out; + ret = ga_fill_tmp_loc(loc, this, gfid, args->bname, xdata, &tmp_loc); if (ret) goto out; @@ -685,7 +683,7 @@ ga_virtual_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, inode = true_inode; } - ret = inode_ctx_put(cbk_inode, this, (uint64_t)inode); + ret = inode_ctx_put(cbk_inode, this, (uint64_t)(uintptr_t)inode); if (ret) { gf_log(this->name, GF_LOG_WARNING, "failed to set the inode ctx with" @@ -830,7 +828,7 @@ ga_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) if (ret) goto wind; - inode = (inode_t *)value; + inode = (inode_t *)(uintptr_t)value; ret = loc_copy_overload_parent(&tmp_loc, loc, inode); if (ret) @@ -859,7 +857,7 @@ ga_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) if (ret) goto err; - inode = (void *)value; + inode = (void *)(uintptr_t)value; /* valid inode, already looked up, work on that */ if (inode->ia_type) @@ -1363,7 +1361,7 @@ ga_dump_inodectx(xlator_t *this, inode_t *inode) ret = inode_ctx_get(inode, this, &value); if (ret == 0) { - tmp_inode = (void *)value; + tmp_inode = (void *)(uintptr_t)value; gf_proc_dump_build_key(key_prefix, this->name, "inode"); gf_proc_dump_add_section("%s", key_prefix); gf_proc_dump_write("real-gfid", "%s", uuid_utoa(tmp_inode->gfid)); @@ -1408,3 +1406,15 @@ struct volume_options options[] = { /* This translator doesn't take any options, or provide any options */ {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .mem_acct_init = mem_acct_init, + .op_version = {1}, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "gfid-access", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/gfid-access/src/gfid-access.h b/xlators/features/gfid-access/src/gfid-access.h index 68ebe539564..b1e255e56c0 100644 --- a/xlators/features/gfid-access/src/gfid-access.h +++ b/xlators/features/gfid-access/src/gfid-access.h @@ -10,11 +10,11 @@ #ifndef __GFID_ACCESS_H__ #define __GFID_ACCESS_H__ -#include "glusterfs.h" -#include "logging.h" -#include "dict.h" -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "gfid-access-mem-types.h" #define UUID_CANONICAL_FORM_LEN 36 diff --git a/xlators/features/glupy/Makefile.am b/xlators/features/glupy/Makefile.am deleted file mode 100644 index 060429ecf0f..00000000000 --- a/xlators/features/glupy/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIRS = src examples - -CLEANFILES = diff --git a/xlators/features/glupy/doc/README.md b/xlators/features/glupy/doc/README.md deleted file mode 100644 index 4b8b863ef39..00000000000 --- a/xlators/features/glupy/doc/README.md +++ /dev/null @@ -1,44 +0,0 @@ -This is just the very start for a GlusterFS[1] meta-translator that will -allow translator code to be written in Python. It's based on the standard -Python embedding (not extending) techniques, plus a dash of the ctypes module. -The interface is a pretty minimal adaptation of the dispatches and callbacks -from the C API[2] to Python, as follows: - -* Dispatch functions and callbacks must be defined on an "xlator" class - derived from gluster.Translator so that they'll be auto-registered with - the C translator during initialization. - -* For each dispatch or callback function you want to intercept, you define a - Python function using the xxx\_fop\_t or xxx\_cbk\_t decorator. - -* The arguments for each operation are different, so you'll need to refer to - the C API. GlusterFS-specific types are used (though only loc\_t is fully - defined so far) and type correctness is enforced by ctypes. - -* If you do intercept a dispatch function, it is your responsibility to call - xxx\_wind (like STACK\_WIND in the C API but operation-specific) to pass - the request to the next translator. If you do not intercept a function, it - will default the same way as for C (pass through to the same operation with - the same arguments on the first child translator). - -* If you intercept a callback function, it is your responsibility to call - xxx\_unwind (like STACK\_UNWIND\_STRICT in the C API) to pass the request back - to the caller. - -So far only the lookup and create operations are handled this way, to support -the "negative lookup" example. Now that the basic infrastructure is in place, -adding more functions should be very quick, though with that much boilerplate I -might pause to write a code generator. I also plan to add structure -definitions and interfaces for some of the utility functions in libglusterfs -(especially those having to do with inode and fd context) in the fairly near -future. Note that you can also use ctypes to get at anything not explicitly -exposed to Python already. - -_If you're coming here because of the Linux Journal article, please note that -the code has evolved since that was written. The version that matches the -article is here:_ - -https://github.com/jdarcy/glupy/tree/4bbae91ba459ea46ef32f2966562492e4ca9187a - -[1] http://www.gluster.org -[2] http://pl.atyp.us/hekafs.org/dist/xlator_api_2.html diff --git a/xlators/features/glupy/doc/TESTING b/xlators/features/glupy/doc/TESTING deleted file mode 100644 index e05f17f498f..00000000000 --- a/xlators/features/glupy/doc/TESTING +++ /dev/null @@ -1,9 +0,0 @@ -Loading a translator written in Python using the glupy meta translator -------------------------------------------------------------------------------- -'test.vol' is a simple volfile with the debug-trace Python translator on top -of a brick. The volfile can be mounted using the following command. - -$ glusterfs --debug -f test.vol /path/to/mntpt - -If then file operations are performed on the newly mounted file system, log -output would be printed by the Python translator on the standard output. diff --git a/xlators/features/glupy/doc/test.vol b/xlators/features/glupy/doc/test.vol deleted file mode 100644 index 0751a488c1f..00000000000 --- a/xlators/features/glupy/doc/test.vol +++ /dev/null @@ -1,10 +0,0 @@ -volume vol-posix - type storage/posix - option directory /path/to/brick -end-volume - -volume vol-glupy - type features/glupy - option module-name debug-trace - subvolumes vol-posix -end-volume diff --git a/xlators/features/glupy/examples/Makefile.am b/xlators/features/glupy/examples/Makefile.am deleted file mode 100644 index c26abeaafb6..00000000000 --- a/xlators/features/glupy/examples/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features - -glupyexamplesdir = $(xlatordir)/glupy - -glupyexamples_PYTHON = negative.py helloworld.py debug-trace.py diff --git a/xlators/features/glupy/examples/debug-trace.py b/xlators/features/glupy/examples/debug-trace.py deleted file mode 100644 index 6e012f6c547..00000000000 --- a/xlators/features/glupy/examples/debug-trace.py +++ /dev/null @@ -1,777 +0,0 @@ - -from __future__ import print_function -import sys -import stat -from uuid import UUID -from time import strftime, localtime -from gluster.glupy import * - -# This translator was written primarily to test the fop entry point definitions -# and structure definitions in 'glupy.py'. - -# It is similar to the C language debug-trace translator, which logs the -# arguments passed to the fops and their corresponding cbk functions. - -dl.get_id.restype = c_long -dl.get_id.argtypes = [ POINTER(call_frame_t) ] - -dl.get_rootunique.restype = c_uint64 -dl.get_rootunique.argtypes = [ POINTER(call_frame_t) ] - -def uuid2str (gfid): - return str(UUID(''.join(map("{0:02x}".format, gfid)))) - - -def st_mode_from_ia (prot, filetype): - st_mode = 0 - type_bit = 0 - prot_bit = 0 - - if filetype == IA_IFREG: - type_bit = stat.S_IFREG - elif filetype == IA_IFDIR: - type_bit = stat.S_IFDIR - elif filetype == IA_IFLNK: - type_bit = stat.S_IFLNK - elif filetype == IA_IFBLK: - type_bit = stat.S_IFBLK - elif filetype == IA_IFCHR: - type_bit = stat.S_IFCHR - elif filetype == IA_IFIFO: - type_bit = stat.S_IFIFO - elif filetype == IA_IFSOCK: - type_bit = stat.S_IFSOCK - elif filetype == IA_INVAL: - pass - - - if prot.suid: - prot_bit |= stat.S_ISUID - if prot.sgid: - prot_bit |= stat.S_ISGID - if prot.sticky: - prot_bit |= stat.S_ISVTX - - if prot.owner.read: - prot_bit |= stat.S_IRUSR - if prot.owner.write: - prot_bit |= stat.S_IWUSR - if prot.owner.execn: - prot_bit |= stat.S_IXUSR - - if prot.group.read: - prot_bit |= stat.S_IRGRP - if prot.group.write: - prot_bit |= stat.S_IWGRP - if prot.group.execn: - prot_bit |= stat.S_IXGRP - - if prot.other.read: - prot_bit |= stat.S_IROTH - if prot.other.write: - prot_bit |= stat.S_IWOTH - if prot.other.execn: - prot_bit |= stat.S_IXOTH - - st_mode = (type_bit | prot_bit) - - return st_mode - - -def trace_stat2str (buf): - gfid = uuid2str(buf.contents.ia_gfid) - mode = st_mode_from_ia(buf.contents.ia_prot, buf.contents.ia_type) - atime_buf = strftime("[%b %d %H:%M:%S]", - localtime(buf.contents.ia_atime)) - mtime_buf = strftime("[%b %d %H:%M:%S]", - localtime(buf.contents.ia_mtime)) - ctime_buf = strftime("[%b %d %H:%M:%S]", - localtime(buf.contents.ia_ctime)) - return ("(gfid={0:s}, ino={1:d}, mode={2:o}, nlink={3:d}, uid ={4:d}, "+ - "gid ={5:d}, size={6:d}, blocks={7:d}, atime={8:s}, mtime={9:s}, "+ - "ctime={10:s})").format(gfid, buf.contents.ia_no, mode, - buf.contents.ia_nlink, - buf.contents.ia_uid, - buf.contents.ia_gid, - buf.contents.ia_size, - buf.contents.ia_blocks, - atime_buf, mtime_buf, - ctime_buf) - -class xlator(Translator): - - def __init__(self, c_this): - Translator.__init__(self, c_this) - self.gfids = {} - - def lookup_fop(self, frame, this, loc, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.gfid) - print(("GLUPY TRACE LOOKUP FOP- {0:d}: gfid={1:s}; " + - "path={2:s}").format(unique, gfid, loc.contents.path)) - self.gfids[key] = gfid - dl.wind_lookup(frame, POINTER(xlator_t)(), loc, xdata) - return 0 - - def lookup_cbk(self, frame, cookie, this, op_ret, op_errno, - inode, buf, xdata, postparent): - unique =dl.get_rootunique(frame) - key =dl.get_id(frame) - if op_ret == 0: - gfid = uuid2str(buf.contents.ia_gfid) - statstr = trace_stat2str(buf) - postparentstr = trace_stat2str(postparent) - print(("GLUPY TRACE LOOKUP CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; *buf={3:s}; " + - "*postparent={4:s}").format(unique, gfid, - op_ret, statstr, - postparentstr)) - else: - gfid = self.gfids[key] - print(("GLUPY TRACE LOOKUP CBK - {0:d}: gfid={1:s};" + - " op_ret={2:d}; op_errno={3:d}").format(unique, - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_lookup(frame, cookie, this, op_ret, op_errno, - inode, buf, xdata, postparent) - return 0 - - def create_fop(self, frame, this, loc, flags, mode, umask, fd, - xdata): - unique = dl.get_rootunique(frame) - gfid = uuid2str(loc.contents.gfid) - print(("GLUPY TRACE CREATE FOP- {0:d}: gfid={1:s}; path={2:s}; " + - "fd={3:s}; flags=0{4:o}; mode=0{5:o}; " + - "umask=0{6:o}").format(unique, gfid, loc.contents.path, - fd, flags, mode, umask)) - dl.wind_create(frame, POINTER(xlator_t)(), loc, flags, mode, - umask, fd, xdata) - return 0 - - def create_cbk(self, frame, cookie, this, op_ret, op_errno, fd, - inode, buf, preparent, postparent, xdata): - unique = dl.get_rootunique(frame) - if op_ret >= 0: - gfid = uuid2str(inode.contents.gfid) - statstr = trace_stat2str(buf) - preparentstr = trace_stat2str(preparent) - postparentstr = trace_stat2str(postparent) - print(("GLUPY TRACE CREATE CBK- {0:d}: gfid={1:s};" + - " op_ret={2:d}; fd={3:s}; *stbuf={4:s}; " + - "*preparent={5:s};" + - " *postparent={6:s}").format(unique, gfid, op_ret, - fd, statstr, - preparentstr, - postparentstr)) - else: - print(("GLUPY TRACE CREATE CBK- {0:d}: op_ret={1:d}; " + - "op_errno={2:d}").format(unique, op_ret, op_errno)) - dl.unwind_create(frame, cookie, this, op_ret, op_errno, fd, - inode, buf, preparent, postparent, xdata) - return 0 - - def open_fop(self, frame, this, loc, flags, fd, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE OPEN FOP- {0:d}: gfid={1:s}; path={2:s}; "+ - "flags={3:d}; fd={4:s}").format(unique, gfid, - loc.contents.path, flags, - fd)) - self.gfids[key] = gfid - dl.wind_open(frame, POINTER(xlator_t)(), loc, flags, fd, xdata) - return 0 - - def open_cbk(self, frame, cookie, this, op_ret, op_errno, fd, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE OPEN CBK- {0:d}: gfid={1:s}; op_ret={2:d}; " - "op_errno={3:d}; *fd={4:s}").format(unique, gfid, - op_ret, op_errno, fd)) - del self.gfids[key] - dl.unwind_open(frame, cookie, this, op_ret, op_errno, fd, - xdata) - return 0 - - def readv_fop(self, frame, this, fd, size, offset, flags, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(fd.contents.inode.contents.gfid) - print(("GLUPY TRACE READV FOP- {0:d}: gfid={1:s}; "+ - "fd={2:s}; size ={3:d}; offset={4:d}; " + - "flags=0{5:x}").format(unique, gfid, fd, size, offset, - flags)) - self.gfids[key] = gfid - dl.wind_readv (frame, POINTER(xlator_t)(), fd, size, offset, - flags, xdata) - return 0 - - def readv_cbk(self, frame, cookie, this, op_ret, op_errno, vector, - count, buf, iobref, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret >= 0: - statstr = trace_stat2str(buf) - print(("GLUPY TRACE READV CBK- {0:d}: gfid={1:s}, "+ - "op_ret={2:d}; *buf={3:s};").format(unique, gfid, - op_ret, - statstr)) - - else: - print(("GLUPY TRACE READV CBK- {0:d}: gfid={1:s}, "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_readv (frame, cookie, this, op_ret, op_errno, - vector, count, buf, iobref, xdata) - return 0 - - def writev_fop(self, frame, this, fd, vector, count, offset, flags, - iobref, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(fd.contents.inode.contents.gfid) - print(("GLUPY TRACE WRITEV FOP- {0:d}: gfid={1:s}; " + - "fd={2:s}; count={3:d}; offset={4:d}; " + - "flags=0{5:x}").format(unique, gfid, fd, count, offset, - flags)) - self.gfids[key] = gfid - dl.wind_writev(frame, POINTER(xlator_t)(), fd, vector, count, - offset, flags, iobref, xdata) - return 0 - - def writev_cbk(self, frame, cookie, this, op_ret, op_errno, prebuf, - postbuf, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - if op_ret >= 0: - preopstr = trace_stat2str(prebuf) - postopstr = trace_stat2str(postbuf) - print(("GLUPY TRACE WRITEV CBK- {0:d}: op_ret={1:d}; " + - "*prebuf={2:s}; " + - "*postbuf={3:s}").format(unique, op_ret, preopstr, - postopstr)) - else: - gfid = self.gfids[key] - print(("GLUPY TRACE WRITEV CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_writev (frame, cookie, this, op_ret, op_errno, - prebuf, postbuf, xdata) - return 0 - - def opendir_fop(self, frame, this, loc, fd, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE OPENDIR FOP- {0:d}: gfid={1:s}; path={2:s}; "+ - "fd={3:s}").format(unique, gfid, loc.contents.path, fd)) - self.gfids[key] = gfid - dl.wind_opendir(frame, POINTER(xlator_t)(), loc, fd, xdata) - return 0 - - def opendir_cbk(self, frame, cookie, this, op_ret, op_errno, fd, - xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE OPENDIR CBK- {0:d}: gfid={1:s}; op_ret={2:d};"+ - " op_errno={3:d}; fd={4:s}").format(unique, gfid, op_ret, - op_errno, fd)) - del self.gfids[key] - dl.unwind_opendir(frame, cookie, this, op_ret, op_errno, - fd, xdata) - return 0 - - def readdir_fop(self, frame, this, fd, size, offset, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(fd.contents.inode.contents.gfid) - print(("GLUPY TRACE READDIR FOP- {0:d}: gfid={1:s}; fd={2:s}; " + - "size={3:d}; offset={4:d}").format(unique, gfid, fd, size, - offset)) - self.gfids[key] = gfid - dl.wind_readdir(frame, POINTER(xlator_t)(), fd, size, offset, - xdata) - return 0 - - def readdir_cbk(self, frame, cookie, this, op_ret, op_errno, buf, - xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE READDIR CBK- {0:d}: gfid={1:s}; op_ret={2:d};"+ - " op_errno={3:d}").format(unique, gfid, op_ret, op_errno)) - del self.gfids[key] - dl.unwind_readdir(frame, cookie, this, op_ret, op_errno, buf, - xdata) - return 0 - - def readdirp_fop(self, frame, this, fd, size, offset, dictionary): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(fd.contents.inode.contents.gfid) - print(("GLUPY TRACE READDIRP FOP- {0:d}: gfid={1:s}; fd={2:s}; "+ - " size={3:d}; offset={4:d}").format(unique, gfid, fd, size, - offset)) - self.gfids[key] = gfid - dl.wind_readdirp(frame, POINTER(xlator_t)(), fd, size, offset, - dictionary) - return 0 - - def readdirp_cbk(self, frame, cookie, this, op_ret, op_errno, buf, - xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE READDIRP CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, gfid, - op_ret, op_errno)) - del self.gfids[key] - dl.unwind_readdirp(frame, cookie, this, op_ret, op_errno, buf, - xdata) - return 0 - - def mkdir_fop(self, frame, this, loc, mode, umask, xdata): - unique = dl.get_rootunique(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE MKDIR FOP- {0:d}: gfid={1:s}; path={2:s}; " + - "mode={3:d}; umask=0{4:o}").format(unique, gfid, - loc.contents.path, mode, - umask)) - dl.wind_mkdir(frame, POINTER(xlator_t)(), loc, mode, umask, - xdata) - return 0 - - def mkdir_cbk(self, frame, cookie, this, op_ret, op_errno, inode, buf, - preparent, postparent, xdata): - unique = dl.get_rootunique(frame) - if op_ret == 0: - gfid = uuid2str(inode.contents.gfid) - statstr = trace_stat2str(buf) - preparentstr = trace_stat2str(preparent) - postparentstr = trace_stat2str(postparent) - print(("GLUPY TRACE MKDIR CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; *stbuf={3:s}; *prebuf={4:s}; "+ - "*postbuf={5:s} ").format(unique, gfid, op_ret, - statstr, - preparentstr, - postparentstr)) - else: - print(("GLUPY TRACE MKDIR CBK- {0:d}: op_ret={1:d}; "+ - "op_errno={2:d}").format(unique, op_ret, op_errno)) - dl.unwind_mkdir(frame, cookie, this, op_ret, op_errno, inode, - buf, preparent, postparent, xdata) - return 0 - - def rmdir_fop(self, frame, this, loc, flags, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE RMDIR FOP- {0:d}: gfid={1:s}; path={2:s}; "+ - "flags={3:d}").format(unique, gfid, loc.contents.path, - flags)) - self.gfids[key] = gfid - dl.wind_rmdir(frame, POINTER(xlator_t)(), loc, flags, xdata) - return 0 - - def rmdir_cbk(self, frame, cookie, this, op_ret, op_errno, preparent, - postparent, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret == 0: - preparentstr = trace_stat2str(preparent) - postparentstr = trace_stat2str(postparent) - print(("GLUPY TRACE RMDIR CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; *prebuf={3:s}; "+ - "*postbuf={4:s}").format(unique, gfid, op_ret, - preparentstr, - postparentstr)) - else: - print(("GLUPY TRACE RMDIR CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_rmdir(frame, cookie, this, op_ret, op_errno, - preparent, postparent, xdata) - return 0 - - def stat_fop(self, frame, this, loc, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE STAT FOP- {0:d}: gfid={1:s}; " + - " path={2:s}").format(unique, gfid, loc.contents.path)) - self.gfids[key] = gfid - dl.wind_stat(frame, POINTER(xlator_t)(), loc, xdata) - return 0 - - def stat_cbk(self, frame, cookie, this, op_ret, op_errno, buf, - xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret == 0: - statstr = trace_stat2str(buf) - print(("GLUPY TRACE STAT CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; *buf={3:s};").format(unique, - gfid, - op_ret, - statstr)) - else: - print(("GLUPY TRACE STAT CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_stat(frame, cookie, this, op_ret, op_errno, - buf, xdata) - return 0 - - def fstat_fop(self, frame, this, fd, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(fd.contents.inode.contents.gfid) - print(("GLUPY TRACE FSTAT FOP- {0:d}: gfid={1:s}; " + - "fd={2:s}").format(unique, gfid, fd)) - self.gfids[key] = gfid - dl.wind_fstat(frame, POINTER(xlator_t)(), fd, xdata) - return 0 - - def fstat_cbk(self, frame, cookie, this, op_ret, op_errno, buf, - xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret == 0: - statstr = trace_stat2str(buf) - print(("GLUPY TRACE FSTAT CBK- {0:d}: gfid={1:s} "+ - " op_ret={2:d}; *buf={3:s}").format(unique, - gfid, - op_ret, - statstr)) - else: - print(("GLUPY TRACE FSTAT CBK- {0:d}: gfid={1:s} "+ - "op_ret={2:d}; op_errno={3:d}").format(unique. - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_fstat(frame, cookie, this, op_ret, op_errno, - buf, xdata) - return 0 - - def statfs_fop(self, frame, this, loc, xdata): - unique = dl.get_rootunique(frame) - if loc.contents.inode: - gfid = uuid2str(loc.contents.inode.contents.gfid) - else: - gfid = "0" - print(("GLUPY TRACE STATFS FOP- {0:d}: gfid={1:s}; "+ - "path={2:s}").format(unique, gfid, loc.contents.path)) - dl.wind_statfs(frame, POINTER(xlator_t)(), loc, xdata) - return 0 - - def statfs_cbk(self, frame, cookie, this, op_ret, op_errno, buf, - xdata): - unique = dl.get_rootunique(frame) - if op_ret == 0: - #TBD: print buf (pointer to an iovec type object) - print(("GLUPY TRACE STATFS CBK {0:d}: "+ - "op_ret={1:d}").format(unique, op_ret)) - else: - print(("GLUPY TRACE STATFS CBK- {0:d}"+ - "op_ret={1:d}; op_errno={2:d}").format(unique, - op_ret, - op_errno)) - dl.unwind_statfs(frame, cookie, this, op_ret, op_errno, - buf, xdata) - return 0 - - def getxattr_fop(self, frame, this, loc, name, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE GETXATTR FOP- {0:d}: gfid={1:s}; path={2:s};"+ - " name={3:s}").format(unique, gfid, loc.contents.path, - name)) - self.gfids[key]=gfid - dl.wind_getxattr(frame, POINTER(xlator_t)(), loc, name, xdata) - return 0 - - def getxattr_cbk(self, frame, cookie, this, op_ret, op_errno, - dictionary, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE GETXATTR CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}; "+ - " dictionary={4:s}").format(unique, gfid, op_ret, op_errno, - dictionary)) - del self.gfids[key] - dl.unwind_getxattr(frame, cookie, this, op_ret, op_errno, - dictionary, xdata) - return 0 - - def fgetxattr_fop(self, frame, this, fd, name, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(fd.contents.inode.contents.gfid) - print(("GLUPY TRACE FGETXATTR FOP- {0:d}: gfid={1:s}; fd={2:s}; "+ - "name={3:s}").format(unique, gfid, fd, name)) - self.gfids[key] = gfid - dl.wind_fgetxattr(frame, POINTER(xlator_t)(), fd, name, xdata) - return 0 - - def fgetxattr_cbk(self, frame, cookie, this, op_ret, op_errno, - dictionary, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE FGETXATTR CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d};"+ - " dictionary={4:s}").format(unique, gfid, op_ret, - op_errno, dictionary)) - del self.gfids[key] - dl.unwind_fgetxattr(frame, cookie, this, op_ret, op_errno, - dictionary, xdata) - return 0 - - def setxattr_fop(self, frame, this, loc, dictionary, flags, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE SETXATTR FOP- {0:d}: gfid={1:s}; path={2:s};"+ - " flags={3:d}").format(unique, gfid, loc.contents.path, - flags)) - self.gfids[key] = gfid - dl.wind_setxattr(frame, POINTER(xlator_t)(), loc, dictionary, - flags, xdata) - return 0 - - def setxattr_cbk(self, frame, cookie, this, op_ret, op_errno, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE SETXATTR CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, gfid, - op_ret, op_errno)) - del self.gfids[key] - dl.unwind_setxattr(frame, cookie, this, op_ret, op_errno, - xdata) - return 0 - - def fsetxattr_fop(self, frame, this, fd, dictionary, flags, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(fd.contents.inode.contents.gfid) - print(("GLUPY TRACE FSETXATTR FOP- {0:d}: gfid={1:s}; fd={2:p}; "+ - "flags={3:d}").format(unique, gfid, fd, flags)) - self.gfids[key] = gfid - dl.wind_fsetxattr(frame, POINTER(xlator_t)(), fd, dictionary, - flags, xdata) - return 0 - - def fsetxattr_cbk(self, frame, cookie, this, op_ret, op_errno, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE FSETXATTR CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, gfid, - op_ret, op_errno)) - del self.gfids[key] - dl.unwind_fsetxattr(frame, cookie, this, op_ret, op_errno, - xdata) - return 0 - - def removexattr_fop(self, frame, this, loc, name, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE REMOVEXATTR FOP- {0:d}: gfid={1:s}; "+ - "path={2:s}; name={3:s}").format(unique, gfid, - loc.contents.path, - name)) - self.gfids[key] = gfid - dl.wind_removexattr(frame, POINTER(xlator_t)(), loc, name, - xdata) - return 0 - - def removexattr_cbk(self, frame, cookie, this, op_ret, op_errno, - xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - print(("GLUPY TRACE REMOVEXATTR CBK- {0:d}: gfid={1:s} "+ - " op_ret={2:d}; op_errno={3:d}").format(unique, gfid, - op_ret, op_errno)) - del self.gfids[key] - dl.unwind_removexattr(frame, cookie, this, op_ret, op_errno, - xdata) - return 0 - - def link_fop(self, frame, this, oldloc, newloc, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - if (newloc.contents.inode): - newgfid = uuid2str(newloc.contents.inode.contents.gfid) - else: - newgfid = "0" - oldgfid = uuid2str(oldloc.contents.inode.contents.gfid) - print(("GLUPY TRACE LINK FOP-{0:d}: oldgfid={1:s}; oldpath={2:s};"+ - "newgfid={3:s};"+ - "newpath={4:s}").format(unique, oldgfid, - oldloc.contents.path, - newgfid, - newloc.contents.path)) - self.gfids[key] = oldgfid - dl.wind_link(frame, POINTER(xlator_t)(), oldloc, newloc, - xdata) - return 0 - - def link_cbk(self, frame, cookie, this, op_ret, op_errno, inode, buf, - preparent, postparent, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret == 0: - statstr = trace_stat2str(buf) - preparentstr = trace_stat2str(preparent) - postparentstr = trace_stat2str(postparent) - print(("GLUPY TRACE LINK CBK- {0:d}: op_ret={1:d} "+ - "*stbuf={2:s}; *prebuf={3:s}; "+ - "*postbuf={4:s} ").format(unique, op_ret, statstr, - preparentstr, - postparentstr)) - else: - print(("GLUPY TRACE LINK CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; "+ - "op_errno={3:d}").format(unique, gfid, - op_ret, op_errno)) - del self.gfids[key] - dl.unwind_link(frame, cookie, this, op_ret, op_errno, inode, - buf, preparent, postparent, xdata) - return 0 - - def unlink_fop(self, frame, this, loc, xflag, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE UNLINK FOP- {0:d}; gfid={1:s}; path={2:s}; "+ - "flag={3:d}").format(unique, gfid, loc.contents.path, - xflag)) - self.gfids[key] = gfid - dl.wind_unlink(frame, POINTER(xlator_t)(), loc, xflag, - xdata) - return 0 - - def unlink_cbk(self, frame, cookie, this, op_ret, op_errno, - preparent, postparent, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret == 0: - preparentstr = trace_stat2str(preparent) - postparentstr = trace_stat2str(postparent) - print(("GLUPY TRACE UNLINK CBK- {0:d}: gfid ={1:s}; "+ - "op_ret={2:d}; *prebuf={3:s}; "+ - "*postbuf={4:s} ").format(unique, gfid, op_ret, - preparentstr, - postparentstr)) - else: - print(("GLUPY TRACE UNLINK CBK: {0:d}: gfid ={1:s}; "+ - "op_ret={2:d}; "+ - "op_errno={3:d}").format(unique, gfid, op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_unlink(frame, cookie, this, op_ret, op_errno, - preparent, postparent, xdata) - return 0 - - def readlink_fop(self, frame, this, loc, size, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE READLINK FOP- {0:d}: gfid={1:s}; path={2:s};"+ - " size={3:d}").format(unique, gfid, loc.contents.path, - size)) - self.gfids[key] = gfid - dl.wind_readlink(frame, POINTER(xlator_t)(), loc, size, - xdata) - return 0 - - def readlink_cbk(self, frame, cookie, this, op_ret, op_errno, - buf, stbuf, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret == 0: - statstr = trace_stat2str(stbuf) - print(("GLUPY TRACE READLINK CBK- {0:d}: gfid={1:s} "+ - " op_ret={2:d}; op_errno={3:d}; *prebuf={4:s}; "+ - "*postbuf={5:s} ").format(unique, gfid, - op_ret, op_errno, - buf, statstr)) - else: - print(("GLUPY TRACE READLINK CBK- {0:d}: gfid={1:s} "+ - " op_ret={2:d}; op_errno={3:d}").format(unique, - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_readlink(frame, cookie, this, op_ret, op_errno, buf, - stbuf, xdata) - return 0 - - def symlink_fop(self, frame, this, linkpath, loc, umask, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = uuid2str(loc.contents.inode.contents.gfid) - print(("GLUPY TRACE SYMLINK FOP- {0:d}: gfid={1:s}; "+ - "linkpath={2:s}; path={3:s};"+ - "umask=0{4:o}").format(unique, gfid, linkpath, - loc.contents.path, umask)) - self.gfids[key] = gfid - dl.wind_symlink(frame, POINTER(xlator_t)(), linkpath, loc, - umask, xdata) - return 0 - - def symlink_cbk(self, frame, cookie, this, op_ret, op_errno, - inode, buf, preparent, postparent, xdata): - unique = dl.get_rootunique(frame) - key = dl.get_id(frame) - gfid = self.gfids[key] - if op_ret == 0: - statstr = trace_stat2str(buf) - preparentstr = trace_stat2str(preparent) - postparentstr = trace_stat2str(postparent) - print(("GLUPY TRACE SYMLINK CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; *stbuf={3:s}; *preparent={4:s}; "+ - "*postparent={5:s}").format(unique, gfid, - op_ret, statstr, - preparentstr, - postparentstr)) - else: - print(("GLUPY TRACE SYMLINK CBK- {0:d}: gfid={1:s}; "+ - "op_ret={2:d}; op_errno={3:d}").format(unique, - gfid, - op_ret, - op_errno)) - del self.gfids[key] - dl.unwind_symlink(frame, cookie, this, op_ret, op_errno, - inode, buf, preparent, postparent, xdata) - return 0 diff --git a/xlators/features/glupy/examples/helloworld.py b/xlators/features/glupy/examples/helloworld.py deleted file mode 100644 index 282f9207949..00000000000 --- a/xlators/features/glupy/examples/helloworld.py +++ /dev/null @@ -1,21 +0,0 @@ - -from __future__ import print_function -import sys -from gluster.glupy import * - -class xlator (Translator): - - def __init__(self, c_this): - Translator.__init__(self, c_this) - - def lookup_fop(self, frame, this, loc, xdata): - print("Python xlator: Hello!") - dl.wind_lookup(frame, POINTER(xlator_t)(), loc, xdata) - return 0 - - def lookup_cbk(self, frame, cookie, this, op_ret, op_errno, inode, buf, - xdata, postparent): - print("Python xlator: Hello again!") - dl.unwind_lookup(frame, cookie, this, op_ret, op_errno, inode, buf, - xdata, postparent) - return 0 diff --git a/xlators/features/glupy/examples/negative.py b/xlators/features/glupy/examples/negative.py deleted file mode 100644 index e04b16aa553..00000000000 --- a/xlators/features/glupy/examples/negative.py +++ /dev/null @@ -1,93 +0,0 @@ - -from __future__ import print_function -import sys -from uuid import UUID -from gluster.glupy import * - -# Negative-lookup-caching example. If a file wasn't there the last time we -# looked, it's probably still not there. This translator keeps track of -# those failed lookups for us, and returns ENOENT without needing to pass the -# call any further for repeated requests. - -# If we were doing this for real, we'd need separate caches for each xlator -# instance. The easiest way to do this would be to have xlator.__init__ -# "register" each instance in a module-global dict, with the key as the C -# translator address and the value as the xlator object itself. For testing -# and teaching, it's sufficient just to have one cache. The keys are parent -# GFIDs, and the entries are lists of names within that parent that we know -# don't exist. -cache = {} - -# TBD: we need a better way of handling per-request data (frame->local in C). -dl.get_id.restype = c_long -dl.get_id.argtypes = [ POINTER(call_frame_t) ] - -def uuid2str (gfid): - return str(UUID(''.join(map("{0:02x}".format, gfid)))) - -class xlator (Translator): - - def __init__ (self, c_this): - self.requests = {} - Translator.__init__(self, c_this) - - def lookup_fop (self, frame, this, loc, xdata): - pargfid = uuid2str(loc.contents.pargfid) - print("lookup FOP: %s:%s" % (pargfid, loc.contents.name)) - # Check the cache. - if pargfid in cache: - if loc.contents.name in cache[pargfid]: - print("short-circuiting for %s:%s" % (pargfid, - loc.contents.name)) - dl.unwind_lookup(frame, 0, this, -1, 2, None, None, None, None) - return 0 - key = dl.get_id(frame) - self.requests[key] = (pargfid, loc.contents.name[:]) - # TBD: get real child xl from init, pass it here - dl.wind_lookup(frame, POINTER(xlator_t)(), loc, xdata) - return 0 - - def lookup_cbk (self, frame, cookie, this, op_ret, op_errno, inode, buf, - xdata, postparent): - print("lookup CBK: %d (%d)" % (op_ret, op_errno)) - key = dl.get_id(frame) - pargfid, name = self.requests[key] - # Update the cache. - if op_ret == 0: - print("found %s, removing from cache" % name) - if pargfid in cache: - cache[pargfid].discard(name) - elif op_errno == 2: # ENOENT - print("failed to find %s, adding to cache" % name) - if pargfid in cache: - cache[pargfid].add(name) - else: - cache[pargfid] = {name} - del self.requests[key] - dl.unwind_lookup(frame, cookie, this, op_ret, op_errno, - inode, buf, xdata, postparent) - return 0 - - def create_fop (self, frame, this, loc, flags, mode, umask, fd, xdata): - pargfid = uuid2str(loc.contents.pargfid) - print("create FOP: %s:%s" % (pargfid, loc.contents.name)) - key = dl.get_id(frame) - self.requests[key] = (pargfid, loc.contents.name[:]) - # TBD: get real child xl from init, pass it here - dl.wind_create(frame, POINTER(xlator_t)(), loc, flags, mode, umask, fd, xdata) - return 0 - - def create_cbk (self, frame, cookie, this, op_ret, op_errno, fd, inode, - buf, preparent, postparent, xdata): - print("create CBK: %d (%d)" % (op_ret, op_errno)) - key = dl.get_id(frame) - pargfid, name = self.requests[key] - # Update the cache. - if op_ret == 0: - print("created %s, removing from cache" % name) - if pargfid in cache: - cache[pargfid].discard(name) - del self.requests[key] - dl.unwind_create(frame, cookie, this, op_ret, op_errno, fd, inode, buf, - preparent, postparent, xdata) - return 0 diff --git a/xlators/features/glupy/src/Makefile.am b/xlators/features/glupy/src/Makefile.am deleted file mode 100644 index 817b0d00f61..00000000000 --- a/xlators/features/glupy/src/Makefile.am +++ /dev/null @@ -1,36 +0,0 @@ -xlator_LTLIBRARIES = glupy.la - -# Ensure GLUSTER_PYTHON_PATH is passed to glupy.so -xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features -glupydir = $(xlatordir)/glupy - -AM_CPPFLAGS = $(GF_CPPFLAGS) \ - -I$(top_srcdir)/libglusterfs/src \ - -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src - -AM_CFLAGS = -Wall -fno-strict-aliasing \ - -DGLUSTER_PYTHON_PATH=\"$(glupydir)\" \ - -DPATH_GLUSTERFS_GLUPY_MODULE=\"${xlatordir}/glupy${shrext_cmds}\" \ - $(GF_CFLAGS) $(PYTHON_CFLAGS) - -# Flags to build glupy.so with -glupy_la_LDFLAGS = -module -nostartfiles \ - -export-symbols $(top_srcdir)/xlators/features/glupy/src/glupy.sym \ - $(GF_XLATOR_LDFLAGS) $(PYTHON_LIBS) - -glupy_la_SOURCES = glupy.c -glupy_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ - -lpthread $(LIB_DL) - -noinst_HEADERS = glupy.h - -# Install __init__.py into the Python site-packages area -pyglupydir = @BUILD_PYTHON_SITE_PACKAGES@/gluster -pyglupy_PYTHON = __init__.py - -# Install glupy/__init_-.py into the Python site-packages area -SUBDIRS = glupy - -CLEANFILES = - -EXTRA_DIST = glupy.sym diff --git a/xlators/features/glupy/src/__init__.py.in b/xlators/features/glupy/src/__init__.py.in deleted file mode 100644 index 3a28658e401..00000000000 --- a/xlators/features/glupy/src/__init__.py.in +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/python3 - -from pkgutil import extend_path -__path__ = extend_path(__path__, __name__) diff --git a/xlators/features/glupy/src/glupy.c b/xlators/features/glupy/src/glupy.c deleted file mode 100644 index d1a111eab4a..00000000000 --- a/xlators/features/glupy/src/glupy.c +++ /dev/null @@ -1,2446 +0,0 @@ -/* - Copyright (c) 2006-2014 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#include <ctype.h> -#include <dlfcn.h> -#include <sys/uio.h> -#include <Python.h> - -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "defaults.h" - -#include "glupy.h" - -/* UTILITY FUNCTIONS FOR FOP-SPECIFIC CODE */ - -pthread_key_t gil_init_key; - -PyGILState_STATE -glupy_enter(void) -{ - if (!pthread_getspecific(gil_init_key)) { - PyEval_ReleaseLock(); - (void)pthread_setspecific(gil_init_key, (void *)1); - } - - return PyGILState_Ensure(); -} - -void -glupy_leave(PyGILState_STATE gstate) -{ - PyGILState_Release(gstate); -} - -/* FOP: LOOKUP */ - -int32_t -glupy_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *xdata, struct iatt *postparent) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_LOOKUP]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_lookup_cbk_t)(priv->cbks[GLUPY_LOOKUP]))( - frame, cookie, this, op_ret, op_errno, inode, buf, xdata, postparent); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, buf, xdata, - postparent); - return 0; -} - -int32_t -glupy_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_LOOKUP]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_lookup_t)(priv->fops[GLUPY_LOOKUP]))(frame, this, loc, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_lookup_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, loc, xdata); - return 0; -} - -void -wind_lookup(call_frame_t *frame, xlator_t *xl, loc_t *loc, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_lookup_cbk, xl, xl->fops->lookup, loc, xdata); -} - -void -unwind_lookup(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *xdata, - struct iatt *postparent) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, buf, xdata, - postparent); -} - -void -set_lookup_fop(long py_this, fop_lookup_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_LOOKUP] = (long)fop; -} - -void -set_lookup_cbk(long py_this, fop_lookup_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_LOOKUP] = (long)cbk; -} - -/* FOP: CREATE */ - -int32_t -glupy_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, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_CREATE]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_create_cbk_t)(priv->cbks[GLUPY_CREATE]))( - frame, cookie, this, op_ret, op_errno, fd, inode, buf, preparent, - postparent, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(create, frame, op_ret, op_errno, fd, inode, buf, - preparent, postparent, xdata); - return 0; -} - -int32_t -glupy_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, - mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_CREATE]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_create_t)(priv->fops[GLUPY_CREATE]))(frame, this, loc, flags, - mode, umask, fd, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_create_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, fd, - xdata); - return 0; -} - -void -wind_create(call_frame_t *frame, xlator_t *xl, loc_t *loc, int32_t flags, - mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_create_cbk, xl, xl->fops->create, loc, flags, mode, - umask, fd, xdata); -} - -void -unwind_create(call_frame_t *frame, long 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, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(create, frame, op_ret, op_errno, fd, inode, buf, - preparent, postparent, xdata); -} - -void -set_create_fop(long py_this, fop_create_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_CREATE] = (long)fop; -} - -void -set_create_cbk(long py_this, fop_create_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_CREATE] = (long)cbk; -} - -/* FOP: OPEN */ - -int32_t -glupy_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_OPEN]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_open_cbk_t)(priv->cbks[GLUPY_OPEN]))( - frame, cookie, this, op_ret, op_errno, fd, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(open, frame, op_ret, op_errno, fd, xdata); - return 0; -} - -int32_t -glupy_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, - fd_t *fd, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_OPEN]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_open_t)(priv->fops[GLUPY_OPEN]))(frame, this, loc, flags, fd, - xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_open_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->open, loc, flags, fd, xdata); - return 0; -} - -void -wind_open(call_frame_t *frame, xlator_t *xl, loc_t *loc, int32_t flags, - fd_t *fd, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_open_cbk, xl, xl->fops->open, loc, flags, fd, - xdata); -} - -void -unwind_open(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, fd_t *fd, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(open, frame, op_ret, op_errno, fd, xdata); -} - -void -set_open_fop(long py_this, fop_open_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - priv->fops[GLUPY_OPEN] = (long)fop; -} - -void -set_open_cbk(long py_this, fop_open_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - priv->cbks[GLUPY_OPEN] = (long)cbk; -} - -/* FOP: READV */ - -int32_t -glupy_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iovec *vector, - int32_t count, struct iatt *stbuf, struct iobref *iobref, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_READV]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_readv_cbk_t)(priv->cbks[GLUPY_READV]))( - frame, cookie, this, op_ret, op_errno, vector, count, stbuf, iobref, - xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, vector, count, stbuf, - iobref, xdata); - return 0; -} - -int32_t -glupy_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - off_t offset, uint32_t flags, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_READV]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_readv_t)(priv->fops[GLUPY_READV]))(frame, this, fd, size, - offset, flags, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_readv_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata); - return 0; -} - -void -wind_readv(call_frame_t *frame, xlator_t *xl, fd_t *fd, size_t size, - off_t offset, uint32_t flags, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_readv_cbk, xl, xl->fops->readv, fd, size, offset, - flags, xdata); -} - -void -unwind_readv(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct iovec *vector, int32_t count, - struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, vector, count, stbuf, - iobref, xdata); -} - -void -set_readv_fop(long py_this, fop_readv_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - priv->fops[GLUPY_READV] = (long)fop; -} - -void -set_readv_cbk(long py_this, fop_readv_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - priv->cbks[GLUPY_READV] = (long)cbk; -} - -/* FOP: WRITEV */ - -int32_t -glupy_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, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_WRITEV]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_writev_cbk_t)(priv->cbks[GLUPY_WRITEV]))( - frame, cookie, this, op_ret, op_errno, prebuf, postbuf, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(writev, frame, op_ret, op_errno, prebuf, postbuf, - xdata); - return 0; -} - -int32_t -glupy_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iovec *vector, int32_t count, off_t offset, uint32_t flags, - struct iobref *iobref, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_WRITEV]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_writev_t)(priv->fops[GLUPY_WRITEV]))( - frame, this, fd, vector, count, offset, flags, iobref, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_writev_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->writev, fd, vector, count, offset, - flags, iobref, xdata); - return 0; -} - -void -wind_writev(call_frame_t *frame, xlator_t *xl, fd_t *fd, struct iovec *vector, - int32_t count, off_t offset, uint32_t flags, struct iobref *iobref, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_writev_cbk, xl, xl->fops->writev, fd, vector, count, - offset, flags, iobref, xdata); -} - -void -unwind_writev(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, - dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(writev, frame, op_ret, op_errno, prebuf, postbuf, - xdata); -} - -void -set_writev_fop(long py_this, fop_writev_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - priv->fops[GLUPY_WRITEV] = (long)fop; -} - -void -set_writev_cbk(long py_this, fop_writev_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - priv->cbks[GLUPY_WRITEV] = (long)cbk; -} - -/* FOP: OPENDIR */ - -int32_t -glupy_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_OPENDIR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_opendir_cbk_t)(priv->cbks[GLUPY_OPENDIR]))( - frame, cookie, this, op_ret, op_errno, fd, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(opendir, frame, op_ret, op_errno, fd, xdata); - return 0; -} - -int32_t -glupy_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_OPENDIR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_opendir_t)(priv->fops[GLUPY_OPENDIR]))(frame, this, loc, fd, - xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_opendir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); - return 0; -} - -void -wind_opendir(call_frame_t *frame, xlator_t *xl, loc_t *loc, fd_t *fd, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_opendir_cbk, xl, xl->fops->opendir, loc, fd, xdata); -} - -void -unwind_opendir(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, fd_t *fd, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(opendir, frame, op_ret, op_errno, fd, xdata); -} - -void -set_opendir_fop(long py_this, fop_opendir_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_OPENDIR] = (long)fop; -} - -void -set_opendir_cbk(long py_this, fop_opendir_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_OPENDIR] = (long)cbk; -} - -/* FOP: READDIR */ - -int32_t -glupy_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_READDIR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_readdir_cbk_t)(priv->cbks[GLUPY_READDIR]))( - frame, cookie, this, op_ret, op_errno, entries, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(readdir, frame, op_ret, op_errno, entries, xdata); - return 0; -} - -int32_t -glupy_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - off_t offset, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_READDIR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_readdir_t)(priv->fops[GLUPY_READDIR]))(frame, this, fd, size, - offset, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_readdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdir, fd, size, offset, xdata); - return 0; -} - -void -wind_readdir(call_frame_t *frame, xlator_t *xl, fd_t *fd, size_t size, - off_t offset, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_readdir_cbk, xl, xl->fops->readdir, fd, size, - offset, xdata); -} - -void -unwind_readdir(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, gf_dirent_t *entries, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(readdir, frame, op_ret, op_errno, entries, xdata); -} - -void -set_readdir_fop(long py_this, fop_readdir_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_READDIR] = (long)fop; -} - -void -set_readdir_cbk(long py_this, fop_readdir_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_READDIR] = (long)cbk; -} - -/* FOP: READDIRP */ - -int32_t -glupy_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_READDIRP]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_readdirp_cbk_t)(priv->cbks[GLUPY_READDIRP]))( - frame, cookie, this, op_ret, op_errno, entries, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(readdirp, frame, op_ret, op_errno, entries, xdata); - return 0; -} - -int32_t -glupy_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - off_t offset, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_READDIRP]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_readdirp_t)(priv->fops[GLUPY_READDIRP]))(frame, this, fd, size, - offset, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_readdirp_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdirp, fd, size, offset, xdata); - return 0; -} - -void -wind_readdirp(call_frame_t *frame, xlator_t *xl, fd_t *fd, size_t size, - off_t offset, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_readdirp_cbk, xl, xl->fops->readdirp, fd, size, - offset, xdata); -} - -void -unwind_readdirp(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, - dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(readdirp, frame, op_ret, op_errno, entries, xdata); -} - -void -set_readdirp_fop(long py_this, fop_readdirp_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_READDIRP] = (long)fop; -} - -void -set_readdirp_cbk(long py_this, fop_readdirp_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_READDIRP] = (long)cbk; -} - -/* FOP:STAT */ - -int32_t -glupy_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *buf, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_STAT]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_stat_cbk_t)(priv->cbks[GLUPY_STAT]))( - frame, cookie, this, op_ret, op_errno, buf, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(stat, frame, op_ret, op_errno, buf, xdata); - return 0; -} - -int32_t -glupy_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_STAT]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_stat_t)(priv->fops[GLUPY_STAT]))(frame, this, loc, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_stat_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->stat, loc, xdata); - return 0; -} - -void -wind_stat(call_frame_t *frame, xlator_t *xl, loc_t *loc, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_stat_cbk, xl, xl->fops->stat, loc, xdata); -} - -void -unwind_stat(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct iatt *buf, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(stat, frame, op_ret, op_errno, buf, xdata); -} - -void -set_stat_fop(long py_this, fop_stat_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_STAT] = (long)fop; -} - -void -set_stat_cbk(long py_this, fop_stat_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_STAT] = (long)cbk; -} - -/* FOP: FSTAT */ - -int32_t -glupy_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *buf, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_FSTAT]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_fstat_cbk_t)(priv->cbks[GLUPY_FSTAT]))( - frame, cookie, this, op_ret, op_errno, buf, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(fstat, frame, op_ret, op_errno, buf, xdata); - return 0; -} - -int32_t -glupy_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_FSTAT]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_fstat_t)(priv->fops[GLUPY_FSTAT]))(frame, this, fd, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_fstat_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fstat, fd, xdata); - return 0; -} - -void -wind_fstat(call_frame_t *frame, xlator_t *xl, fd_t *fd, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_fstat_cbk, xl, xl->fops->fstat, fd, xdata); -} - -void -unwind_fstat(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct iatt *buf, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(fstat, frame, op_ret, op_errno, buf, xdata); -} - -void -set_fstat_fop(long py_this, fop_fstat_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_FSTAT] = (long)fop; -} - -void -set_fstat_cbk(long py_this, fop_fstat_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_FSTAT] = (long)cbk; -} - -/* FOP:STATFS */ - -int32_t -glupy_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct statvfs *buf, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_STATFS]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_statfs_cbk_t)(priv->cbks[GLUPY_STATFS]))( - frame, cookie, this, op_ret, op_errno, buf, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(statfs, frame, op_ret, op_errno, buf, xdata); - return 0; -} - -int32_t -glupy_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_STATFS]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_statfs_t)(priv->fops[GLUPY_STATFS]))(frame, this, loc, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_statfs_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->statfs, loc, xdata); - return 0; -} - -void -wind_statfs(call_frame_t *frame, xlator_t *xl, loc_t *loc, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_statfs_cbk, xl, xl->fops->statfs, loc, xdata); -} - -void -unwind_statfs(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct statvfs *buf, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(statfs, frame, op_ret, op_errno, buf, xdata); -} - -void -set_statfs_fop(long py_this, fop_statfs_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_STATFS] = (long)fop; -} - -void -set_statfs_cbk(long py_this, fop_statfs_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_STATFS] = (long)cbk; -} - -/* FOP: SETXATTR */ - -int32_t -glupy_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_SETXATTR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_setxattr_cbk_t)(priv->cbks[GLUPY_SETXATTR]))( - frame, cookie, this, op_ret, op_errno, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(setxattr, frame, op_ret, op_errno, xdata); - return 0; -} - -int32_t -glupy_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, - int32_t flags, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_SETXATTR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_setxattr_t)(priv->fops[GLUPY_SETXATTR]))(frame, this, loc, dict, - flags, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_setxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); - return 0; -} - -void -wind_setxattr(call_frame_t *frame, xlator_t *xl, loc_t *loc, dict_t *dict, - int32_t flags, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_setxattr_cbk, xl, xl->fops->setxattr, loc, dict, - flags, xdata); -} - -void -unwind_setxattr(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(setxattr, frame, op_ret, op_errno, xdata); -} - -void -set_setxattr_fop(long py_this, fop_setxattr_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_SETXATTR] = (long)fop; -} - -void -set_setxattr_cbk(long py_this, fop_setxattr_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_SETXATTR] = (long)cbk; -} - -/* FOP: GETXATTR */ - -int32_t -glupy_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_GETXATTR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_getxattr_cbk_t)(priv->cbks[GLUPY_GETXATTR]))( - frame, cookie, this, op_ret, op_errno, dict, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, dict, xdata); - return 0; -} - -int32_t -glupy_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_GETXATTR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_getxattr_t)(priv->fops[GLUPY_GETXATTR]))(frame, this, loc, name, - xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_getxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, loc, name, xdata); - return 0; -} - -void -wind_getxattr(call_frame_t *frame, xlator_t *xl, loc_t *loc, const char *name, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_getxattr_cbk, xl, xl->fops->getxattr, loc, name, - xdata); -} - -void -unwind_getxattr(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, dict, xdata); -} - -void -set_getxattr_fop(long py_this, fop_getxattr_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_GETXATTR] = (long)fop; -} - -void -set_getxattr_cbk(long py_this, fop_getxattr_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_GETXATTR] = (long)cbk; -} - -/* FOP: FSETXATTR */ - -int32_t -glupy_fsetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_FSETXATTR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_fsetxattr_cbk_t)(priv->cbks[GLUPY_FSETXATTR]))( - frame, cookie, this, op_ret, op_errno, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(fsetxattr, frame, op_ret, op_errno, xdata); - return 0; -} - -int32_t -glupy_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, - int32_t flags, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_FSETXATTR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_fsetxattr_t)(priv->fops[GLUPY_FSETXATTR]))(frame, this, fd, - dict, flags, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_fsetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); - return 0; -} - -void -wind_fsetxattr(call_frame_t *frame, xlator_t *xl, fd_t *fd, dict_t *dict, - int32_t flags, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_fsetxattr_cbk, xl, xl->fops->fsetxattr, fd, dict, - flags, xdata); -} - -void -unwind_fsetxattr(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(fsetxattr, frame, op_ret, op_errno, xdata); -} - -void -set_fsetxattr_fop(long py_this, fop_fsetxattr_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_FSETXATTR] = (long)fop; -} - -void -set_fsetxattr_cbk(long py_this, fop_fsetxattr_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_FSETXATTR] = (long)cbk; -} - -/* FOP: FGETXATTR */ - -int32_t -glupy_fgetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_FGETXATTR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_fgetxattr_cbk_t)(priv->cbks[GLUPY_FGETXATTR]))( - frame, cookie, this, op_ret, op_errno, dict, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(fgetxattr, frame, op_ret, op_errno, dict, xdata); - return 0; -} - -int32_t -glupy_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_FGETXATTR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_fgetxattr_t)(priv->fops[GLUPY_FGETXATTR]))(frame, this, fd, - name, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_fgetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata); - return 0; -} - -void -wind_fgetxattr(call_frame_t *frame, xlator_t *xl, fd_t *fd, const char *name, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_fgetxattr_cbk, xl, xl->fops->fgetxattr, fd, name, - xdata); -} - -void -unwind_fgetxattr(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(fgetxattr, frame, op_ret, op_errno, dict, xdata); -} - -void -set_fgetxattr_fop(long py_this, fop_fgetxattr_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_FGETXATTR] = (long)fop; -} - -void -set_fgetxattr_cbk(long py_this, fop_fgetxattr_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_FGETXATTR] = (long)cbk; -} - -/* FOP:REMOVEXATTR */ - -int32_t -glupy_removexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_REMOVEXATTR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_removexattr_cbk_t)(priv->cbks[GLUPY_REMOVEXATTR]))( - frame, cookie, this, op_ret, op_errno, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(removexattr, frame, op_ret, op_errno, xdata); - return 0; -} - -int32_t -glupy_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_REMOVEXATTR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_removexattr_t)(priv->fops[GLUPY_REMOVEXATTR]))(frame, this, loc, - name, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_removexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); - return 0; -} - -void -wind_removexattr(call_frame_t *frame, xlator_t *xl, loc_t *loc, - const char *name, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_removexattr_cbk, xl, xl->fops->removexattr, loc, - name, xdata); -} - -void -unwind_removexattr(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(removexattr, frame, op_ret, op_errno, xdata); -} - -void -set_removexattr_fop(long py_this, fop_removexattr_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_REMOVEXATTR] = (long)fop; -} - -void -set_removexattr_cbk(long py_this, fop_removexattr_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_REMOVEXATTR] = (long)cbk; -} - -/* FOP:FREMOVEXATTR */ - -int32_t -glupy_fremovexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_FREMOVEXATTR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_fremovexattr_cbk_t)(priv->cbks[GLUPY_FREMOVEXATTR]))( - frame, cookie, this, op_ret, op_errno, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(fremovexattr, frame, op_ret, op_errno, xdata); - return 0; -} - -int32_t -glupy_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_FREMOVEXATTR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_fremovexattr_t)(priv->fops[GLUPY_FREMOVEXATTR]))( - frame, this, fd, name, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_fremovexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); - return 0; -} - -void -wind_fremovexattr(call_frame_t *frame, xlator_t *xl, fd_t *fd, const char *name, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_fremovexattr_cbk, xl, xl->fops->fremovexattr, fd, - name, xdata); -} - -void -unwind_fremovexattr(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(fremovexattr, frame, op_ret, op_errno, xdata); -} - -void -set_fremovexattr_fop(long py_this, fop_fremovexattr_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_FREMOVEXATTR] = (long)fop; -} - -void -set_fremovexattr_cbk(long py_this, fop_fremovexattr_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_FREMOVEXATTR] = (long)cbk; -} - -/* FOP: LINK*/ -int32_t -glupy_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, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_LINK]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_link_cbk_t)(priv->cbks[GLUPY_LINK]))( - frame, cookie, this, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(link, frame, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); - return 0; -} - -int32_t -glupy_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_LINK]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_link_t)(priv->fops[GLUPY_LINK]))(frame, this, oldloc, newloc, - xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_link_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); - return 0; -} - -void -wind_link(call_frame_t *frame, xlator_t *xl, loc_t *oldloc, loc_t *newloc, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_link_cbk, xl, xl->fops->link, oldloc, newloc, - xdata); -} - -void -unwind_link(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, inode_t *inode, struct iatt *buf, - struct iatt *preparent, struct iatt *postparent, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(link, frame, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); -} - -void -set_link_fop(long py_this, fop_link_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_LINK] = (long)fop; -} - -void -set_link_cbk(long py_this, fop_link_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_LINK] = (long)cbk; -} - -/* FOP: SYMLINK*/ -int32_t -glupy_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, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_SYMLINK]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_symlink_cbk_t)(priv->cbks[GLUPY_SYMLINK]))( - frame, cookie, this, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(symlink, frame, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); - return 0; -} - -int32_t -glupy_symlink(call_frame_t *frame, xlator_t *this, const char *linkname, - loc_t *loc, mode_t umask, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_SYMLINK]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_symlink_t)(priv->fops[GLUPY_SYMLINK]))(frame, this, linkname, - loc, umask, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_symlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->symlink, linkname, loc, umask, xdata); - return 0; -} - -void -wind_symlink(call_frame_t *frame, xlator_t *xl, const char *linkname, - loc_t *loc, mode_t umask, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_symlink_cbk, xl, xl->fops->symlink, linkname, loc, - umask, xdata); -} - -void -unwind_symlink(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, inode_t *inode, struct iatt *buf, - struct iatt *preparent, struct iatt *postparent, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(symlink, frame, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); -} - -void -set_symlink_fop(long py_this, fop_symlink_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_SYMLINK] = (long)fop; -} - -void -set_symlink_cbk(long py_this, fop_symlink_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_SYMLINK] = (long)cbk; -} - -/* FOP: READLINK */ -int32_t -glupy_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, const char *path, - struct iatt *buf, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_READLINK]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_readlink_cbk_t)(priv->cbks[GLUPY_READLINK]))( - frame, cookie, this, op_ret, op_errno, path, buf, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(readlink, frame, op_ret, op_errno, path, buf, xdata); - return 0; -} - -int32_t -glupy_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_READLINK]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_readlink_t)(priv->fops[GLUPY_READLINK]))(frame, this, loc, size, - xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_readlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readlink, loc, size, xdata); - return 0; -} - -void -wind_readlink(call_frame_t *frame, xlator_t *xl, loc_t *loc, size_t size, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_readlink_cbk, xl, xl->fops->readlink, loc, size, - xdata); -} - -void -unwind_readlink(call_frame_t *frame, long cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, const char *path, - struct iatt *buf, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(readlink, frame, op_ret, op_errno, path, buf, xdata); -} - -void -set_readlink_fop(long py_this, fop_readlink_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_READLINK] = (long)fop; -} - -void -set_readlink_cbk(long py_this, fop_readlink_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_READLINK] = (long)cbk; -} - -/* FOP: UNLINK */ - -int32_t -glupy_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, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_UNLINK]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_unlink_cbk_t)(priv->cbks[GLUPY_UNLINK]))( - frame, cookie, this, op_ret, op_errno, preparent, postparent, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(unlink, frame, op_ret, op_errno, preparent, postparent, - xdata); - return 0; -} - -int32_t -glupy_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflags, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_UNLINK]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_unlink_t)(priv->fops[GLUPY_UNLINK]))(frame, this, loc, xflags, - xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_unlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, loc, xflags, xdata); - return 0; -} - -void -wind_unlink(call_frame_t *frame, xlator_t *xl, loc_t *loc, int xflags, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_unlink_cbk, xl, xl->fops->unlink, loc, xflags, - xdata); -} - -void -unwind_unlink(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct iatt *preparent, struct iatt *postparent, - dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(unlink, frame, op_ret, op_errno, preparent, postparent, - xdata); -} - -void -set_unlink_fop(long py_this, fop_unlink_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_UNLINK] = (long)fop; -} - -void -set_unlink_cbk(long py_this, fop_unlink_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_UNLINK] = (long)cbk; -} - -/* FOP: MKDIR */ - -int32_t -glupy_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, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_MKDIR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_mkdir_cbk_t)(priv->cbks[GLUPY_MKDIR]))( - frame, cookie, this, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(mkdir, frame, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); - return 0; -} - -int32_t -glupy_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, - mode_t umask, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_MKDIR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_mkdir_t)(priv->fops[GLUPY_MKDIR]))(frame, this, loc, mode, - umask, xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_mkdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); - return 0; -} - -void -wind_mkdir(call_frame_t *frame, xlator_t *xl, loc_t *loc, mode_t mode, - mode_t umask, dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_mkdir_cbk, xl, xl->fops->mkdir, loc, mode, umask, - xdata); -} - -void -unwind_mkdir(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, inode_t *inode, struct iatt *buf, - struct iatt *preparent, struct iatt *postparent, dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(mkdir, frame, op_ret, op_errno, inode, buf, preparent, - postparent, xdata); -} - -void -set_mkdir_fop(long py_this, fop_mkdir_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_MKDIR] = (long)fop; -} - -void -set_mkdir_cbk(long py_this, fop_mkdir_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_MKDIR] = (long)cbk; -} - -/* FOP: RMDIR */ - -int32_t -glupy_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, dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - - if (!priv->cbks[GLUPY_RMDIR]) { - goto unwind; - } - - gstate = glupy_enter(); - ret = ((fop_rmdir_cbk_t)(priv->cbks[GLUPY_RMDIR]))( - frame, cookie, this, op_ret, op_errno, preparent, postparent, xdata); - glupy_leave(gstate); - - return ret; - -unwind: - frame->local = NULL; - STACK_UNWIND_STRICT(rmdir, frame, op_ret, op_errno, preparent, postparent, - xdata); - return 0; -} - -int32_t -glupy_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflags, - dict_t *xdata) -{ - glupy_private_t *priv = this->private; - PyGILState_STATE gstate; - int32_t ret; - static long next_id = 0; - - if (!priv->fops[GLUPY_RMDIR]) { - goto wind; - } - - gstate = glupy_enter(); - frame->local = (void *)++next_id; - ret = ((fop_rmdir_t)(priv->fops[GLUPY_RMDIR]))(frame, this, loc, xflags, - xdata); - glupy_leave(gstate); - - return ret; - -wind: - STACK_WIND(frame, glupy_rmdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rmdir, loc, xflags, xdata); - return 0; -} - -void -wind_rmdir(call_frame_t *frame, xlator_t *xl, loc_t *loc, int xflags, - dict_t *xdata) -{ - xlator_t *this = THIS; - - if (!xl || (xl == this)) { - xl = FIRST_CHILD(this); - } - - STACK_WIND(frame, glupy_rmdir_cbk, xl, xl->fops->rmdir, loc, xflags, xdata); -} - -void -unwind_rmdir(call_frame_t *frame, long cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno, struct iatt *preparent, struct iatt *postparent, - dict_t *xdata) -{ - frame->local = NULL; - STACK_UNWIND_STRICT(rmdir, frame, op_ret, op_errno, preparent, postparent, - xdata); -} - -void -set_rmdir_fop(long py_this, fop_rmdir_t fop) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->fops[GLUPY_RMDIR] = (long)fop; -} - -void -set_rmdir_cbk(long py_this, fop_rmdir_cbk_t cbk) -{ - glupy_private_t *priv = ((xlator_t *)py_this)->private; - - priv->cbks[GLUPY_RMDIR] = (long)cbk; -} - -/* NON-FOP-SPECIFIC CODE */ - -long -get_id(call_frame_t *frame) -{ - return (long)(frame->local); -} - -uint64_t -get_rootunique(call_frame_t *frame) -{ - return frame->root->unique; -} - -int32_t -mem_acct_init(xlator_t *this) -{ - int ret = -1; - - if (!this) - return ret; - - ret = xlator_mem_acct_init(this, gf_glupy_mt_end); - - if (ret != 0) { - gf_log(this->name, GF_LOG_ERROR, - "Memory accounting init" - " failed"); - return ret; - } - - return ret; -} - -static void -py_error_log(const char *name, PyObject *pystr) -{ -#if PY_MAJOR_VERSION > 2 - char scr[256]; - if (PyUnicode_Check(pystr)) { - PyObject *tmp = PyUnicode_AsEncodedString(pystr, "UTF-8", "strict"); - if (tmp != NULL) { - strncpy(scr, PyBytes_AS_STRING(pystr), sizeof(scr)); - Py_DECREF(tmp); - } else { - strncpy(scr, "string encoding error", sizeof(scr)); - } - } else if (PyBytes_Check(pystr)) { - strncpy(scr, PyBytes_AS_STRING(pystr), sizeof(scr)); - } else { - strncpy(scr, "string encoding error", sizeof(scr)); - } - gf_log(name, GF_LOG_ERROR, "Python error: %s", scr); -#else - gf_log(name, GF_LOG_ERROR, "Python error: %s", PyString_AsString(pystr)); -#endif -} - -static PyObject * -encode(const char *str) -{ -#if PY_MAJOR_VERSION > 2 - return PyUnicode_FromString(str); -#else - return PyString_FromString(str); -#endif -} - -int32_t -init(xlator_t *this) -{ - glupy_private_t *priv = NULL; - char *module_name = NULL; - PyObject *py_mod_name = NULL; - PyObject *py_init_func = NULL; - PyObject *py_args = NULL; - PyObject *syspath = NULL; - PyObject *path = NULL; - PyObject *error_type = NULL; - PyObject *error_msg = NULL; - PyObject *error_bt = NULL; - static gf_boolean_t py_inited = _gf_false; - void *err_cleanup = &&err_return; - char libpython[16]; - - if (dict_get_str(this->options, "module-name", &module_name) != 0) { - gf_log(this->name, GF_LOG_ERROR, "missing module-name"); - return -1; - } - - priv = GF_CALLOC(1, sizeof(glupy_private_t), gf_glupy_mt_priv); - if (!priv) { - goto *err_cleanup; - } - this->private = priv; - err_cleanup = &&err_free_priv; - - if (!py_inited) { - /* FIXME: - * This hack is necessary because glusterfs (rightly) loads - * glupy.so with RTLD_LOCAL but glupy needs libpython to be - * loaded with RTLD_GLOBAL even though glupy is correctly - * linked with libpython. - * This is needed because one of the internal modules of - * python 2.x (lib-dynload/_struct.so) does not explicitly - * link with libpython. - */ - snprintf(libpython, sizeof(libpython), "libpython%d.%d.so", - PY_MAJOR_VERSION, PY_MINOR_VERSION); - if (!dlopen(libpython, RTLD_NOW | RTLD_GLOBAL)) { - gf_msg(this->name, GF_LOG_WARNING, 0, LG_MSG_DLOPEN_FAILED, - "dlopen(%s) failed: %s", libpython, dlerror()); - } - - /* - * This must be done before Py_Initialize(), - * because it will duplicate the environment, - * and fail to see later environment updates. - */ - setenv("PATH_GLUSTERFS_GLUPY_MODULE", PATH_GLUSTERFS_GLUPY_MODULE, 1); - - Py_Initialize(); - PyEval_InitThreads(); - - (void)pthread_key_create(&gil_init_key, NULL); - (void)pthread_setspecific(gil_init_key, (void *)1); - - /* PyEval_InitThreads takes this "for" us. No thanks. */ - PyEval_ReleaseLock(); - py_inited = _gf_true; - } - - /* Adjust python's path */ - syspath = PySys_GetObject("path"); - path = encode(GLUSTER_PYTHON_PATH); - PyList_Append(syspath, path); - Py_DECREF(path); - - py_mod_name = encode(module_name); - if (!py_mod_name) { - gf_log(this->name, GF_LOG_ERROR, "could not create name"); - if (PyErr_Occurred()) { - PyErr_Fetch(&error_type, &error_msg, &error_bt); - py_error_log(this->name, error_msg); - } - goto *err_cleanup; - } - - gf_log(this->name, GF_LOG_DEBUG, "py_mod_name = %s", module_name); - priv->py_module = PyImport_Import(py_mod_name); - Py_DECREF(py_mod_name); - if (!priv->py_module) { - gf_log(this->name, GF_LOG_ERROR, "Python import of %s failed", - module_name); - if (PyErr_Occurred()) { - PyErr_Fetch(&error_type, &error_msg, &error_bt); - py_error_log(this->name, error_msg); - } - goto *err_cleanup; - } - gf_log(this->name, GF_LOG_INFO, "Import of %s succeeded", module_name); - err_cleanup = &&err_deref_module; - - py_init_func = PyObject_GetAttrString(priv->py_module, "xlator"); - if (!py_init_func || !PyCallable_Check(py_init_func)) { - gf_log(this->name, GF_LOG_ERROR, "missing init func"); - if (PyErr_Occurred()) { - PyErr_Fetch(&error_type, &error_msg, &error_bt); - py_error_log(this->name, error_msg); - } - goto *err_cleanup; - } - err_cleanup = &&err_deref_init; - - py_args = PyTuple_New(1); - if (!py_args) { - gf_log(this->name, GF_LOG_ERROR, "could not create args"); - if (PyErr_Occurred()) { - PyErr_Fetch(&error_type, &error_msg, &error_bt); - py_error_log(this->name, error_msg); - } - goto *err_cleanup; - } - PyTuple_SetItem(py_args, 0, PyLong_FromLong((long)this)); - - /* TBD: pass in list of children */ - priv->py_xlator = PyObject_CallObject(py_init_func, py_args); - Py_DECREF(py_args); - if (!priv->py_xlator) { - gf_log(this->name, GF_LOG_ERROR, "Python init failed"); - if (PyErr_Occurred()) { - PyErr_Fetch(&error_type, &error_msg, &error_bt); - py_error_log(this->name, error_msg); - } - goto *err_cleanup; - } - gf_log(this->name, GF_LOG_DEBUG, "init returned %p", priv->py_xlator); - - return 0; - -err_deref_init: - Py_DECREF(py_init_func); -err_deref_module: - Py_DECREF(priv->py_module); -err_free_priv: - GF_FREE(priv); -err_return: - return -1; -} - -void -fini(xlator_t *this) -{ - glupy_private_t *priv = this->private; - - if (!priv) - return; - Py_DECREF(priv->py_xlator); - Py_DECREF(priv->py_module); - this->private = NULL; - GF_FREE(priv); - - return; -} - -struct xlator_fops fops = {.lookup = glupy_lookup, - .create = glupy_create, - .open = glupy_open, - .readv = glupy_readv, - .writev = glupy_writev, - .opendir = glupy_opendir, - .readdir = glupy_readdir, - .stat = glupy_stat, - .fstat = glupy_fstat, - .setxattr = glupy_setxattr, - .getxattr = glupy_getxattr, - .fsetxattr = glupy_fsetxattr, - .fgetxattr = glupy_fgetxattr, - .removexattr = glupy_removexattr, - .fremovexattr = glupy_fremovexattr, - .link = glupy_link, - .unlink = glupy_unlink, - .readlink = glupy_readlink, - .symlink = glupy_symlink, - .mkdir = glupy_mkdir, - .rmdir = glupy_rmdir, - .statfs = glupy_statfs, - .readdirp = glupy_readdirp}; - -struct xlator_cbks cbks = {}; - -struct volume_options options[] = { - {.key = {NULL}}, -}; diff --git a/xlators/features/glupy/src/glupy.h b/xlators/features/glupy/src/glupy.h deleted file mode 100644 index 851b02154d2..00000000000 --- a/xlators/features/glupy/src/glupy.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright (c) 2006-2014 Red Hat, Inc. <http://www.redhat.com> - This file is part of GlusterFS. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - -#ifndef __GLUPY_H__ -#define __GLUPY_H__ - -#include "mem-types.h" - -enum { - GLUPY_LOOKUP = 0, - GLUPY_CREATE, - GLUPY_OPEN, - GLUPY_READV, - GLUPY_WRITEV, - GLUPY_OPENDIR, - GLUPY_READDIR, - GLUPY_READDIRP, - GLUPY_STAT, - GLUPY_FSTAT, - GLUPY_STATFS, - GLUPY_SETXATTR, - GLUPY_GETXATTR, - GLUPY_FSETXATTR, - GLUPY_FGETXATTR, - GLUPY_REMOVEXATTR, - GLUPY_FREMOVEXATTR, - GLUPY_LINK, - GLUPY_UNLINK, - GLUPY_READLINK, - GLUPY_SYMLINK, - GLUPY_MKNOD, - GLUPY_MKDIR, - GLUPY_RMDIR, - GLUPY_N_FUNCS -}; - -typedef struct { - PyObject *py_module; - PyObject *py_xlator; - long fops[GLUPY_N_FUNCS]; - long cbks[GLUPY_N_FUNCS]; -} glupy_private_t; - -enum gf_glupy_mem_types_ { - gf_glupy_mt_priv = gf_common_mt_end + 1, - gf_glupy_mt_end -}; - -#endif /* __GLUPY_H__ */ diff --git a/xlators/features/glupy/src/glupy.sym b/xlators/features/glupy/src/glupy.sym deleted file mode 100644 index 55d9a300108..00000000000 --- a/xlators/features/glupy/src/glupy.sym +++ /dev/null @@ -1,101 +0,0 @@ -init -fini -fops -cbks -options -notify -mem_acct_init -reconfigure -dumpops -set_lookup_fop -set_lookup_cbk -set_create_fop -set_create_cbk -set_open_fop -set_open_cbk -set_readv_fop -set_readv_cbk -set_writev_fop -set_writev_cbk -set_opendir_fop -set_opendir_cbk -set_readdir_fop -set_readdir_cbk -set_readdirp_fop -set_readdirp_cbk -set_stat_fop -set_stat_cbk -set_fstat_fop -set_fstat_cbk -set_statfs_fop -set_statfs_cbk -set_setxattr_fop -set_setxattr_cbk -set_getxattr_fop -set_getxattr_cbk -set_fsetxattr_fop -set_fsetxattr_cbk -set_fgetxattr_fop -set_fgetxattr_cbk -set_removexattr_fop -set_removexattr_cbk -set_fremovexattr_fop -set_fremovexattr_cbk -set_link_fop -set_link_cbk -set_symlink_fop -set_symlink_cbk -set_readlink_fop -set_readlink_cbk -set_unlink_fop -set_unlink_cbk -set_mkdir_fop -set_mkdir_cbk -set_rmdir_fop -set_rmdir_cbk -wind_lookup -wind_create -wind_open -wind_readv -wind_writev -wind_opendir -wind_readdir -wind_readdirp -wind_stat -wind_fstat -wind_statfs -wind_setxattr -wind_getxattr -wind_fsetxattr -wind_fgetxattr -wind_removexattr -wind_fremovexattr -wind_link -wind_symlink -wind_readlink -wind_unlink -wind_mkdir -wind_rmdir -unwind_lookup -unwind_create -unwind_open -unwind_readv -unwind_writev -unwind_opendir -unwind_readdir -unwind_readdirp -unwind_stat -unwind_fstat -unwind_statfs -unwind_setxattr -unwind_getxattr -unwind_fsetxattr -unwind_fgetxattr -unwind_removexattr -unwind_fremovexattr -unwind_link -unwind_symlink -unwind_readlink -unwind_unlink -unwind_mkdir -unwind_rmdir diff --git a/xlators/features/glupy/src/glupy/Makefile.am b/xlators/features/glupy/src/glupy/Makefile.am deleted file mode 100644 index 573d2da12e1..00000000000 --- a/xlators/features/glupy/src/glupy/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -# Install __init__.py into the Python site-packages area -pyglupydir = @BUILD_PYTHON_SITE_PACKAGES@/gluster/glupy -pyglupy_PYTHON = __init__.py - -CLEANFILES = diff --git a/xlators/features/glupy/src/glupy/__init__.py b/xlators/features/glupy/src/glupy/__init__.py deleted file mode 100644 index 576fbdb9945..00000000000 --- a/xlators/features/glupy/src/glupy/__init__.py +++ /dev/null @@ -1,852 +0,0 @@ -## -## Copyright (c) 2006-2014 Red Hat, Inc. <http://www.redhat.com> -## This file is part of GlusterFS. -## -## This file is licensed to you under your choice of the GNU Lesser -## General Public License, version 3 or any later version (LGPLv3 or -## later), or the GNU General Public License, version 2 (GPLv2), in all -## cases as published by the Free Software Foundation. -## - -import sys -import os -from ctypes import * - -dl = CDLL(os.getenv("PATH_GLUSTERFS_GLUPY_MODULE", ""), RTLD_GLOBAL) - - -class call_frame_t (Structure): - pass - -class dev_t (Structure): - pass - - -class dict_t (Structure): - pass - - -class gf_dirent_t (Structure): - pass - - -class iobref_t (Structure): - pass - - -class iovec_t (Structure): - pass - - -class list_head (Structure): - pass - -list_head._fields_ = [ - ("next", POINTER(list_head)), - ("prev", POINTER(list_head)) - ] - - -class rwxperm_t (Structure): - _fields_ = [ - ("read", c_uint8, 1), - ("write", c_uint8, 1), - ("execn", c_uint8, 1) - ] - - -class statvfs_t (Structure): - pass - - -class xlator_t (Structure): - pass - - -class ia_prot_t (Structure): - _fields_ = [ - ("suid", c_uint8, 1), - ("sgid", c_uint8, 1), - ("sticky", c_uint8, 1), - ("owner", rwxperm_t), - ("group", rwxperm_t), - ("other", rwxperm_t) - ] - -# For checking file type. -(IA_INVAL, IA_IFREG, IA_IFDIR, IA_IFLNK, IA_IFBLK, IA_IFCHR, IA_IFIFO, - IA_IFSOCK) = range(8) - - -class iatt_t (Structure): - _fields_ = [ - ("ia_no", c_uint64), - ("ia_gfid", c_ubyte * 16), - ("ia_dev", c_uint64), - ("ia_type", c_uint), - ("ia_prot", ia_prot_t), - ("ia_nlink", c_uint32), - ("ia_uid", c_uint32), - ("ia_gid", c_uint32), - ("ia_rdev", c_uint64), - ("ia_size", c_uint64), - ("ia_blksize", c_uint32), - ("ia_blocks", c_uint64), - ("ia_atime", c_uint32 ), - ("ia_atime_nsec", c_uint32), - ("ia_mtime", c_uint32), - ("ia_mtime_nsec", c_uint32), - ("ia_ctime", c_uint32), - ("ia_ctime_nsec", c_uint32) - ] - - -class mem_pool (Structure): - _fields_ = [ - ("list", list_head), - ("hot_count", c_int), - ("cold_count", c_int), - ("lock", c_void_p), - ("padded_sizeof_type", c_ulong), - ("pool", c_void_p), - ("pool_end", c_void_p), - ("real_sizeof_type", c_int), - ("alloc_count", c_uint64), - ("pool_misses", c_uint64), - ("max_alloc", c_int), - ("curr_stdalloc", c_int), - ("max_stdalloc", c_int), - ("name", c_char_p), - ("global_list", list_head) - ] - - -class U_ctx_key_inode (Union): - _fields_ = [ - ("key", c_uint64), - ("xl_key", POINTER(xlator_t)) - ] - - -class U_ctx_value1 (Union): - _fields_ = [ - ("value1", c_uint64), - ("ptr1", c_void_p) - ] - - -class U_ctx_value2 (Union): - _fields_ = [ - ("value2", c_uint64), - ("ptr2", c_void_p) - ] - -class inode_ctx (Structure): - _anonymous_ = ("u_key", "u_value1", "u_value2",) - _fields_ = [ - ("u_key", U_ctx_key_inode), - ("u_value1", U_ctx_value1), - ("u_value2", U_ctx_value2) - ] - -class inode_t (Structure): - pass - -class inode_table_t (Structure): - _fields_ = [ - ("lock", c_void_p), - ("hashsize", c_size_t), - ("name", c_char_p), - ("root", POINTER(inode_t)), - ("xl", POINTER(xlator_t)), - ("lru_limit", c_uint32), - ("inode_hash", POINTER(list_head)), - ("name_hash", POINTER(list_head)), - ("active", list_head), - ("active_size", c_uint32), - ("lru", list_head), - ("lru_size", c_uint32), - ("purge", list_head), - ("purge_size", c_uint32), - ("inode_pool", POINTER(mem_pool)), - ("dentry_pool", POINTER(mem_pool)), - ("fd_mem_pool", POINTER(mem_pool)) - ] - -inode_t._fields_ = [ - ("table", POINTER(inode_table_t)), - ("gfid", c_ubyte * 16), - ("lock", c_void_p), - ("nlookup", c_uint64), - ("fd_count", c_uint32), - ("ref", c_uint32), - ("ia_type", c_uint), - ("fd_list", list_head), - ("dentry_list", list_head), - ("hashv", list_head), - ("listv", list_head), - ("ctx", POINTER(inode_ctx)) - ] - - - -class U_ctx_key_fd (Union): - _fields_ = [ - ("key", c_uint64), - ("xl_key", c_void_p) - ] - -class fd_lk_ctx (Structure): - _fields_ = [ - ("lk_list", list_head), - ("ref", c_int), - ("lock", c_void_p) - ] - -class fd_ctx (Structure): - _anonymous_ = ("u_key", "u_value1") - _fields_ = [ - ("u_key", U_ctx_key_fd), - ("u_value1", U_ctx_value1) - ] - -class fd_t (Structure): - _fields_ = [ - ("pid", c_uint64), - ("flags", c_int32), - ("refcount", c_int32), - ("inode_list", list_head), - ("inode", POINTER(inode_t)), - ("lock", c_void_p), - ("ctx", POINTER(fd_ctx)), - ("xl_count", c_int), - ("lk_ctx", POINTER(fd_lk_ctx)), - ("anonymous", c_uint) - ] - -class loc_t (Structure): - _fields_ = [ - ("path", c_char_p), - ("name", c_char_p), - ("inode", POINTER(inode_t)), - ("parent", POINTER(inode_t)), - ("gfid", c_ubyte * 16), - ("pargfid", c_ubyte * 16), - ] - - - -def _init_op (a_class, fop, cbk, wind, unwind): - # Decorators, used by translators. We could pass the signatures as - # parameters, but it's actually kind of nice to keep them around for - # inspection. - a_class.fop_type = CFUNCTYPE(*a_class.fop_sig) - a_class.cbk_type = CFUNCTYPE(*a_class.cbk_sig) - # Dispatch-function registration. - fop.restype = None - fop.argtypes = [ c_long, a_class.fop_type ] - # Callback-function registration. - cbk.restype = None - cbk.argtypes = [ c_long, a_class.cbk_type ] - # STACK_WIND function. - wind.restype = None - wind.argtypes = list(a_class.fop_sig[1:]) - # STACK_UNWIND function. - unwind.restype = None - unwind.argtypes = list(a_class.cbk_sig[1:]) - -class OpLookup: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(inode_t), POINTER(iatt_t), - POINTER(dict_t), POINTER(iatt_t)) -_init_op (OpLookup, dl.set_lookup_fop, dl.set_lookup_cbk, - dl.wind_lookup, dl.unwind_lookup) - -class OpCreate: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_int, c_uint, c_uint, POINTER(fd_t), - POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(fd_t), POINTER(inode_t), - POINTER(iatt_t), POINTER(iatt_t), POINTER(iatt_t), - POINTER(dict_t)) -_init_op (OpCreate, dl.set_create_fop, dl.set_create_cbk, - dl.wind_create, dl.unwind_create) - -class OpOpen: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_int, POINTER(fd_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(fd_t), POINTER(dict_t)) -_init_op (OpOpen, dl.set_open_fop, dl.set_open_cbk, - dl.wind_open, dl.unwind_open) - -class OpReadv: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), c_size_t, c_long, c_uint32, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(iovec_t), c_int, POINTER(iatt_t), - POINTER(iobref_t), POINTER(dict_t)) -_init_op (OpReadv, dl.set_readv_fop, dl.set_readv_cbk, - dl.wind_readv, dl.unwind_readv) -class OpWritev: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), POINTER(iovec_t), c_int, c_long, c_uint32, - POINTER(iobref_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(iatt_t), POINTER(iatt_t), - POINTER(dict_t)) -_init_op (OpWritev, dl.set_writev_fop, dl.set_writev_cbk, - dl.wind_writev, dl.unwind_writev) - -class OpOpendir: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), POINTER(fd_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(fd_t), POINTER(dict_t)) -_init_op (OpOpendir, dl.set_opendir_fop, dl.set_opendir_cbk, - dl.wind_opendir, dl.unwind_opendir) - -class OpReaddir: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), c_size_t, c_long, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(gf_dirent_t), POINTER(dict_t)) -_init_op (OpReaddir, dl.set_readdir_fop, dl.set_readdir_cbk, - dl.wind_readdir, dl.unwind_readdir) - -class OpReaddirp: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), c_size_t, c_long, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(gf_dirent_t), POINTER(dict_t)) -_init_op (OpReaddirp, dl.set_readdirp_fop, dl.set_readdirp_cbk, - dl.wind_readdirp, dl.unwind_readdirp) - -class OpStat: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(iatt_t), POINTER(dict_t)) -_init_op (OpStat, dl.set_stat_fop, dl.set_stat_cbk, - dl.wind_stat, dl.unwind_stat) - -class OpFstat: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(iatt_t), POINTER(dict_t)) -_init_op (OpFstat, dl.set_fstat_fop, dl.set_fstat_cbk, - dl.wind_fstat, dl.unwind_fstat) - -class OpStatfs: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(statvfs_t), POINTER(dict_t)) -_init_op (OpStatfs, dl.set_statfs_fop, dl.set_statfs_cbk, - dl.wind_statfs, dl.unwind_statfs) - - -class OpSetxattr: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), POINTER(dict_t), c_int32, - POINTER (dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(dict_t)) -_init_op (OpSetxattr, dl.set_setxattr_fop, dl.set_setxattr_cbk, - dl.wind_setxattr, dl.unwind_setxattr) - -class OpGetxattr: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_char_p, POINTER (dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(dict_t), POINTER(dict_t)) -_init_op (OpGetxattr, dl.set_getxattr_fop, dl.set_getxattr_cbk, - dl.wind_getxattr, dl.unwind_getxattr) - -class OpFsetxattr: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), POINTER(dict_t), c_int32, - POINTER (dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(dict_t)) -_init_op (OpFsetxattr, dl.set_fsetxattr_fop, dl.set_fsetxattr_cbk, - dl.wind_fsetxattr, dl.unwind_fsetxattr) - -class OpFgetxattr: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), c_char_p, POINTER (dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(dict_t), POINTER(dict_t)) -_init_op (OpFgetxattr, dl.set_fgetxattr_fop, dl.set_fgetxattr_cbk, - dl.wind_fgetxattr, dl.unwind_fgetxattr) - -class OpRemovexattr: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_char_p, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(dict_t)) -_init_op (OpRemovexattr, dl.set_removexattr_fop, dl.set_removexattr_cbk, - dl.wind_removexattr, dl.unwind_removexattr) - - -class OpFremovexattr: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(fd_t), c_char_p, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(dict_t)) -_init_op (OpFremovexattr, dl.set_fremovexattr_fop, dl.set_fremovexattr_cbk, - dl.wind_fremovexattr, dl.unwind_fremovexattr) - -class OpLink: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), POINTER(loc_t), POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(inode_t), POINTER(iatt_t), - POINTER(iatt_t), POINTER(iatt_t), POINTER(dict_t)) -_init_op (OpLink, dl.set_link_fop, dl.set_link_cbk, - dl.wind_link, dl.unwind_link) - -class OpSymlink: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - c_char_p, POINTER(loc_t), c_uint, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(inode_t), POINTER(iatt_t), - POINTER(iatt_t), POINTER(iatt_t), POINTER(dict_t)) -_init_op (OpSymlink, dl.set_symlink_fop, dl.set_symlink_cbk, - dl.wind_symlink, dl.unwind_symlink) - -class OpUnlink: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_int, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(iatt_t), POINTER(iatt_t), - POINTER(dict_t)) -_init_op (OpUnlink, dl.set_unlink_fop, dl.set_unlink_cbk, - dl.wind_unlink, dl.unwind_unlink) - -class OpReadlink: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_size_t, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, c_char_p, POINTER(iatt_t), POINTER(dict_t)) -_init_op (OpReadlink, dl.set_readlink_fop, dl.set_readlink_cbk, - dl.wind_readlink, dl.unwind_readlink) - -class OpMkdir: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_uint, c_uint, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(inode_t), POINTER(iatt_t), - POINTER(iatt_t), POINTER(iatt_t), POINTER(dict_t)) -_init_op (OpMkdir, dl.set_mkdir_fop, dl.set_mkdir_cbk, - dl.wind_mkdir, dl.unwind_mkdir) - -class OpRmdir: - fop_sig = (c_int, POINTER(call_frame_t), POINTER(xlator_t), - POINTER(loc_t), c_int, POINTER(dict_t)) - cbk_sig = (c_int, POINTER(call_frame_t), c_long, POINTER(xlator_t), - c_int, c_int, POINTER(iatt_t), POINTER(iatt_t), - POINTER(dict_t)) -_init_op (OpRmdir, dl.set_rmdir_fop, dl.set_rmdir_cbk, - dl.wind_rmdir, dl.unwind_rmdir) - - -class Translator: - def __init__ (self, c_this): - # This is only here to keep references to the stubs we create, - # because ctypes doesn't and glupy.so can't because it doesn't - # get a pointer to the actual Python object. It's a dictionary - # instead of a list in case we ever allow changing fops/cbks - # after initialization and need to look them up. - self.stub_refs = {} - funcs = dir(self.__class__) - if "lookup_fop" in funcs: - @OpLookup.fop_type - def stub (frame, this, loc, xdata, s=self): - return s.lookup_fop (frame, this, loc, xdata) - self.stub_refs["lookup_fop"] = stub - dl.set_lookup_fop(c_this, stub) - if "lookup_cbk" in funcs: - @OpLookup.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, inode, - buf, xdata, postparent, s=self): - return s.lookup_cbk(frame, cookie, this, op_ret, - op_errno, inode, buf, xdata, - postparent) - self.stub_refs["lookup_cbk"] = stub - dl.set_lookup_cbk(c_this, stub) - if "create_fop" in funcs: - @OpCreate.fop_type - def stub (frame, this, loc, flags, mode, umask, fd, - xdata, s=self): - return s.create_fop (frame, this, loc, flags, - mode, umask, fd, xdata) - self.stub_refs["create_fop"] = stub - dl.set_create_fop(c_this, stub) - if "create_cbk" in funcs: - @OpCreate.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, fd, - inode, buf, preparent, postparent, xdata, - s=self): - return s.create_cbk (frame, cookie, this, - op_ret, op_errno, fd, - inode, buf, preparent, - postparent, xdata) - self.stub_refs["create_cbk"] = stub - dl.set_create_cbk(c_this, stub) - if "open_fop" in funcs: - @OpOpen.fop_type - def stub (frame, this, loc, flags, fd, - xdata, s=self): - return s.open_fop (frame, this, loc, flags, - fd, xdata) - self.stub_refs["open_fop"] = stub - dl.set_open_fop(c_this, stub) - if "open_cbk" in funcs: - @OpOpen.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, fd, - xdata, s=self): - return s.open_cbk (frame, cookie, this, - op_ret, op_errno, fd, - xdata) - self.stub_refs["open_cbk"] = stub - dl.set_open_cbk(c_this, stub) - if "readv_fop" in funcs: - @OpReadv.fop_type - def stub (frame, this, fd, size, offset, flags, - xdata, s=self): - return s.readv_fop (frame, this, fd, size, - offset, flags, xdata) - self.stub_refs["readv_fop"] = stub - dl.set_readv_fop(c_this, stub) - if "readv_cbk" in funcs: - @OpReadv.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - vector, count, stbuf, iobref, xdata, - s=self): - return s.readv_cbk (frame, cookie, this, - op_ret, op_errno, vector, - count, stbuf, iobref, - xdata) - self.stub_refs["readv_cbk"] = stub - dl.set_readv_cbk(c_this, stub) - if "writev_fop" in funcs: - @OpWritev.fop_type - def stub (frame, this, fd, vector, count, - offset, flags, iobref, xdata, s=self): - return s.writev_fop (frame, this, fd, vector, - count, offset, flags, - iobref, xdata) - self.stub_refs["writev_fop"] = stub - dl.set_writev_fop(c_this, stub) - if "writev_cbk" in funcs: - @OpWritev.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - prebuf, postbuf, xdata, s=self): - return s.writev_cbk (frame, cookie, this, - op_ret, op_errno, prebuf, - postbuf, xdata) - self.stub_refs["writev_cbk"] = stub - dl.set_writev_cbk(c_this, stub) - if "opendir_fop" in funcs: - @OpOpendir.fop_type - def stub (frame, this, loc, fd, xdata, s=self): - return s.opendir_fop (frame, this, loc, fd, - xdata) - self.stub_refs["opendir_fop"] = stub - dl.set_opendir_fop(c_this, stub) - if "opendir_cbk" in funcs: - @OpOpendir.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, fd, - xdata, s=self): - return s.opendir_cbk(frame, cookie, this, - op_ret, op_errno, fd, - xdata) - self.stub_refs["opendir_cbk"] = stub - dl.set_opendir_cbk(c_this, stub) - if "readdir_fop" in funcs: - @OpReaddir.fop_type - def stub (frame, this, fd, size, offset, xdata, s=self): - return s.readdir_fop (frame, this, fd, size, - offset, xdata) - self.stub_refs["readdir_fop"] = stub - dl.set_readdir_fop(c_this, stub) - if "readdir_cbk" in funcs: - @OpReaddir.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - entries, xdata, s=self): - return s.readdir_cbk(frame, cookie, this, - op_ret, op_errno, entries, - xdata) - self.stub_refs["readdir_cbk"] = stub - dl.set_readdir_cbk(c_this, stub) - if "readdirp_fop" in funcs: - @OpReaddirp.fop_type - def stub (frame, this, fd, size, offset, xdata, s=self): - return s.readdirp_fop (frame, this, fd, size, - offset, xdata) - self.stub_refs["readdirp_fop"] = stub - dl.set_readdirp_fop(c_this, stub) - if "readdirp_cbk" in funcs: - @OpReaddirp.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - entries, xdata, s=self): - return s.readdirp_cbk (frame, cookie, this, - op_ret, op_errno, - entries, xdata) - self.stub_refs["readdirp_cbk"] = stub - dl.set_readdirp_cbk(c_this, stub) - if "stat_fop" in funcs: - @OpStat.fop_type - def stub (frame, this, loc, xdata, s=self): - return s.stat_fop (frame, this, loc, xdata) - self.stub_refs["stat_fop"] = stub - dl.set_stat_fop(c_this, stub) - if "stat_cbk" in funcs: - @OpStat.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, buf, - xdata, s=self): - return s.stat_cbk(frame, cookie, this, op_ret, - op_errno, buf, xdata) - self.stub_refs["stat_cbk"] = stub - dl.set_stat_cbk(c_this, stub) - if "fstat_fop" in funcs: - @OpFstat.fop_type - def stub (frame, this, fd, xdata, s=self): - return s.fstat_fop (frame, this, fd, xdata) - self.stub_refs["fstat_fop"] = stub - dl.set_fstat_fop(c_this, stub) - if "fstat_cbk" in funcs: - @OpFstat.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, buf, - xdata, s=self): - return s.fstat_cbk(frame, cookie, this, op_ret, - op_errno, buf, xdata) - self.stub_refs["fstat_cbk"] = stub - dl.set_fstat_cbk(c_this, stub) - if "statfs_fop" in funcs: - @OpStatfs.fop_type - def stub (frame, this, loc, xdata, s=self): - return s.statfs_fop (frame, this, loc, xdata) - self.stub_refs["statfs_fop"] = stub - dl.set_statfs_fop(c_this, stub) - if "statfs_cbk" in funcs: - @OpStatfs.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, buf, - xdata, s=self): - return s.statfs_cbk (frame, cookie, this, - op_ret, op_errno, buf, - xdata) - self.stub_refs["statfs_cbk"] = stub - dl.set_statfs_cbk(c_this, stub) - if "setxattr_fop" in funcs: - @OpSetxattr.fop_type - def stub (frame, this, loc, dictionary, flags, xdata, - s=self): - return s.setxattr_fop (frame, this, loc, - dictionary, flags, - xdata) - self.stub_refs["setxattr_fop"] = stub - dl.set_setxattr_fop(c_this, stub) - if "setxattr_cbk" in funcs: - @OpSetxattr.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, xdata, - s=self): - return s.setxattr_cbk(frame, cookie, this, - op_ret, op_errno, xdata) - self.stub_refs["setxattr_cbk"] = stub - dl.set_setxattr_cbk(c_this, stub) - if "getxattr_fop" in funcs: - @OpGetxattr.fop_type - def stub (frame, this, loc, name, xdata, s=self): - return s.getxattr_fop (frame, this, loc, name, - xdata) - self.stub_refs["getxattr_fop"] = stub - dl.set_getxattr_fop(c_this, stub) - if "getxattr_cbk" in funcs: - @OpGetxattr.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - dictionary, xdata, s=self): - return s.getxattr_cbk(frame, cookie, this, - op_ret, op_errno, - dictionary, xdata) - self.stub_refs["getxattr_cbk"] = stub - dl.set_getxattr_cbk(c_this, stub) - if "fsetxattr_fop" in funcs: - @OpFsetxattr.fop_type - def stub (frame, this, fd, dictionary, flags, xdata, - s=self): - return s.fsetxattr_fop (frame, this, fd, - dictionary, flags, - xdata) - self.stub_refs["fsetxattr_fop"] = stub - dl.set_fsetxattr_fop(c_this, stub) - if "fsetxattr_cbk" in funcs: - @OpFsetxattr.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, xdata, - s=self): - return s.fsetxattr_cbk(frame, cookie, this, - op_ret, op_errno, xdata) - self.stub_refs["fsetxattr_cbk"] = stub - dl.set_fsetxattr_cbk(c_this, stub) - if "fgetxattr_fop" in funcs: - @OpFgetxattr.fop_type - def stub (frame, this, fd, name, xdata, s=self): - return s.fgetxattr_fop (frame, this, fd, name, - xdata) - self.stub_refs["fgetxattr_fop"] = stub - dl.set_fgetxattr_fop(c_this, stub) - if "fgetxattr_cbk" in funcs: - @OpFgetxattr.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - dictionary, xdata, s=self): - return s.fgetxattr_cbk(frame, cookie, this, - op_ret, op_errno, - dictionary, xdata) - self.stub_refs["fgetxattr_cbk"] = stub - dl.set_fgetxattr_cbk(c_this, stub) - if "removexattr_fop" in funcs: - @OpRemovexattr.fop_type - def stub (frame, this, loc, name, xdata, s=self): - return s.removexattr_fop (frame, this, loc, - name, xdata) - self.stub_refs["removexattr_fop"] = stub - dl.set_removexattr_fop(c_this, stub) - if "removexattr_cbk" in funcs: - @OpRemovexattr.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - xdata, s=self): - return s.removexattr_cbk(frame, cookie, this, - op_ret, op_errno, - xdata) - self.stub_refs["removexattr_cbk"] = stub - dl.set_removexattr_cbk(c_this, stub) - if "fremovexattr_fop" in funcs: - @OpFremovexattr.fop_type - def stub (frame, this, fd, name, xdata, s=self): - return s.fremovexattr_fop (frame, this, fd, - name, xdata) - self.stub_refs["fremovexattr_fop"] = stub - dl.set_fremovexattr_fop(c_this, stub) - if "fremovexattr_cbk" in funcs: - @OpFremovexattr.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - xdata, s=self): - return s.fremovexattr_cbk(frame, cookie, this, - op_ret, op_errno, - xdata) - self.stub_refs["fremovexattr_cbk"] = stub - dl.set_fremovexattr_cbk(c_this, stub) - if "link_fop" in funcs: - @OpLink.fop_type - def stub (frame, this, oldloc, newloc, - xdata, s=self): - return s.link_fop (frame, this, oldloc, - newloc, xdata) - self.stub_refs["link_fop"] = stub - dl.set_link_fop(c_this, stub) - if "link_cbk" in funcs: - @OpLink.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - inode, buf, preparent, postparent, xdata, - s=self): - return s.link_cbk (frame, cookie, this, - op_ret, op_errno, inode, - buf, preparent, - postparent, xdata) - self.stub_refs["link_cbk"] = stub - dl.set_link_cbk(c_this, stub) - if "symlink_fop" in funcs: - @OpSymlink.fop_type - def stub (frame, this, linkname, loc, - umask, xdata, s=self): - return s.symlink_fop (frame, this, linkname, - loc, umask, xdata) - self.stub_refs["symlink_fop"] = stub - dl.set_symlink_fop(c_this, stub) - if "symlink_cbk" in funcs: - @OpSymlink.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - inode, buf, preparent, postparent, xdata, - s=self): - return s.symlink_cbk (frame, cookie, this, - op_ret, op_errno, inode, - buf, preparent, - postparent, xdata) - self.stub_refs["symlink_cbk"] = stub - dl.set_symlink_cbk(c_this, stub) - if "unlink_fop" in funcs: - @OpUnlink.fop_type - def stub (frame, this, loc, xflags, - xdata, s=self): - return s.unlink_fop (frame, this, loc, - xflags, xdata) - self.stub_refs["unlink_fop"] = stub - dl.set_unlink_fop(c_this, stub) - if "unlink_cbk" in funcs: - @OpUnlink.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - preparent, postparent, xdata, s=self): - return s.unlink_cbk (frame, cookie, this, - op_ret, op_errno, - preparent, postparent, - xdata) - self.stub_refs["unlink_cbk"] = stub - dl.set_unlink_cbk(c_this, stub) - if "readlink_fop" in funcs: - @OpReadlink.fop_type - def stub (frame, this, loc, size, - xdata, s=self): - return s.readlink_fop (frame, this, loc, - size, xdata) - self.stub_refs["readlink_fop"] = stub - dl.set_readlink_fop(c_this, stub) - if "readlink_cbk" in funcs: - @OpReadlink.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - path, buf, xdata, s=self): - return s.readlink_cbk (frame, cookie, this, - op_ret, op_errno, - path, buf, xdata) - self.stub_refs["readlink_cbk"] = stub - dl.set_readlink_cbk(c_this, stub) - if "mkdir_fop" in funcs: - @OpMkdir.fop_type - def stub (frame, this, loc, mode, umask, xdata, - s=self): - return s.mkdir_fop (frame, this, loc, mode, - umask, xdata) - self.stub_refs["mkdir_fop"] = stub - dl.set_mkdir_fop(c_this, stub) - if "mkdir_cbk" in funcs: - @OpMkdir.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, inode, - buf, preparent, postparent, xdata, s=self): - return s.mkdir_cbk (frame, cookie, this, - op_ret, op_errno, inode, - buf, preparent, - postparent, xdata) - self.stub_refs["mkdir_cbk"] = stub - dl.set_mkdir_cbk(c_this, stub) - if "rmdir_fop" in funcs: - @OpRmdir.fop_type - def stub (frame, this, loc, xflags, - xdata, s=self): - return s.rmdir_fop (frame, this, loc, - xflags, xdata) - self.stub_refs["rmdir_fop"] = stub - dl.set_rmdir_fop(c_this, stub) - if "rmdir_cbk" in funcs: - @OpRmdir.cbk_type - def stub (frame, cookie, this, op_ret, op_errno, - preparent, postparent, xdata, s=self): - return s.rmdir_cbk (frame, cookie, this, - op_ret, op_errno, - preparent, postparent, - xdata) - self.stub_refs["rmdir_cbk"] = stub - dl.set_rmdir_cbk(c_this, stub) diff --git a/xlators/features/glupy/src/setup.py.in b/xlators/features/glupy/src/setup.py.in deleted file mode 100644 index 611e9695f76..00000000000 --- a/xlators/features/glupy/src/setup.py.in +++ /dev/null @@ -1,24 +0,0 @@ -from distutils.core import setup - -DESC = """GlusterFS is a distributed file-system capable of scaling to -several petabytes. It aggregates various storage bricks over Infiniband -RDMA or TCP/IP interconnect into one large parallel network file system. -GlusterFS is one of the most sophisticated file systems in terms of -features and extensibility. It borrows a powerful concept called -Translators from GNU Hurd kernel. Much of the code in GlusterFS is in -user space and easily manageable. - -This package contains Glupy, the Python translator interface for GlusterFS.""" - -setup( - name='glusterfs-glupy', - version='@PACKAGE_VERSION@', - description='Glupy is the Python translator interface for GlusterFS', - long_description=DESC, - author='Gluster Community', - author_email='gluster-devel@gluster.org', - license='LGPLv3', - url='http://gluster.org/', - package_dir={'gluster':''}, - packages=['gluster'] -) diff --git a/xlators/features/index/src/index-mem-types.h b/xlators/features/index/src/index-mem-types.h index f5d456e84be..58833d0ec9b 100644 --- a/xlators/features/index/src/index-mem-types.h +++ b/xlators/features/index/src/index-mem-types.h @@ -8,16 +8,16 @@ cases as published by the Free Software Foundation. */ -#ifndef __QUIESCE_MEM_TYPES_H__ -#define __QUIESCE_MEM_TYPES_H__ +#ifndef __INDEX_MEM_TYPES_H__ +#define __INDEX_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_index_mem_types_ { gf_index_mt_priv_t = gf_common_mt_end + 1, - gf_index_inode_ctx_t = gf_common_mt_end + 2, - gf_index_fd_ctx_t = gf_common_mt_end + 3, - gf_index_mt_local_t = gf_common_mt_end + 4, + gf_index_inode_ctx_t, + gf_index_fd_ctx_t, + gf_index_mt_local_t, gf_index_mt_end }; #endif diff --git a/xlators/features/index/src/index-messages.h b/xlators/features/index/src/index-messages.h index 3495fb080f0..364f17cd34e 100644 --- a/xlators/features/index/src/index-messages.h +++ b/xlators/features/index/src/index-messages.h @@ -11,7 +11,7 @@ #ifndef _INDEX_MESSAGES_H_ #define _INDEX_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/index/src/index.c b/xlators/features/index/src/index.c index f3b12595631..4abb2c73ce5 100644 --- a/xlators/features/index/src/index.c +++ b/xlators/features/index/src/index.c @@ -8,11 +8,11 @@ cases as published by the Free Software Foundation. */ #include "index.h" -#include "options.h" +#include <glusterfs/options.h> #include "glusterfs3-xdr.h" -#include "syscall.h" -#include "syncop.h" -#include "common-utils.h" +#include <glusterfs/syscall.h> +#include <glusterfs/syncop.h> +#include <glusterfs/common-utils.h> #include "index-messages.h" #include <ftw.h> #include <libgen.h> /* for dirname() */ @@ -77,7 +77,7 @@ __index_inode_ctx_get(inode_t *inode, xlator_t *this, index_inode_ctx_t **ctx) } INIT_LIST_HEAD(&ictx->callstubs); - ret = __inode_ctx_put(inode, this, (uint64_t)ictx); + ret = __inode_ctx_put(inode, this, (uint64_t)(uintptr_t)ictx); if (ret) { GF_FREE(ictx); ictx = NULL; @@ -187,6 +187,7 @@ worker_enqueue(xlator_t *this, call_stub_t *stub) pthread_mutex_lock(&priv->mutex); { __index_enqueue(&priv->callstubs, stub); + GF_ATOMIC_INC(priv->stub_cnt); pthread_cond_signal(&priv->cond); } pthread_mutex_unlock(&priv->mutex); @@ -220,11 +221,18 @@ index_worker(void *data) } if (!bye) stub = __index_dequeue(&priv->callstubs); + if (bye) { + priv->curr_count--; + if (priv->curr_count == 0) + pthread_cond_broadcast(&priv->cond); + } } pthread_mutex_unlock(&priv->mutex); - if (stub) /* guard against spurious wakeups */ + if (stub) { /* guard against spurious wakeups */ call_resume(stub); + GF_ATOMIC_DEC(priv->stub_cnt); + } stub = NULL; if (bye) break; @@ -1520,6 +1528,8 @@ index_save_pargfid_for_entry_changes(xlator_t *this, loc_t *loc, char *path) int ret = 0; priv = this->private; + if (!loc) + return -1; if (gf_uuid_compare(loc->pargfid, priv->internal_vgfid[ENTRY_CHANGES])) return 0; @@ -1575,8 +1585,15 @@ index_lookup_wrapper(call_frame_t *frame, xlator_t *this, loc_t *loc, op_errno = -ret; goto done; } - strcat(path, "/"); - strcat(path, (char *)loc->name); + ret = snprintf(path + strlen(path), PATH_MAX - strlen(path), "/%s", + loc->name); + + if ((ret < 0) || (ret > (PATH_MAX - strlen(path)))) { + op_errno = EINVAL; + op_ret = -1; + goto done; + } + } else if (index_is_virtual_gfid(priv, loc->gfid)) { subdir = index_get_subdir_from_vgfid(priv, loc->gfid); make_index_dir_path(priv->index_basepath, subdir, path, sizeof(path)); @@ -1643,8 +1660,8 @@ index_lookup_wrapper(call_frame_t *frame, xlator_t *this, loc_t *loc, stbuf.ia_ino = -1; op_ret = 0; done: - STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, loc->inode, &stbuf, - xattr, &postparent); + STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, + loc ? loc->inode : NULL, &stbuf, xattr, &postparent); if (xattr) dict_unref(xattr); loc_wipe(&iloc); @@ -1668,21 +1685,25 @@ index_get_gfid_type(void *opaque) loc_wipe(&loc); - entry->d_type = IA_INVAL; + entry->d_type = gf_d_type_from_ia_type(IA_INVAL); + entry->d_stat.ia_type = IA_INVAL; if (gf_uuid_parse(entry->d_name, loc.gfid)) continue; loc.inode = inode_find(args->parent->table, loc.gfid); if (loc.inode) { - entry->d_type = loc.inode->ia_type; + entry->d_stat.ia_type = loc.inode->ia_type; + entry->d_type = gf_d_type_from_ia_type(loc.inode->ia_type); continue; } loc.inode = inode_new(args->parent->table); if (!loc.inode) continue; ret = syncop_lookup(FIRST_CHILD(this), &loc, &iatt, 0, 0, 0); - if (ret == 0) - entry->d_type = iatt.ia_type; + if (ret == 0) { + entry->d_type = gf_d_type_from_ia_type(iatt.ia_type); + entry->d_stat = iatt; + } } loc_wipe(&loc); @@ -2083,7 +2104,7 @@ index_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) worker_enqueue(this, stub); return 0; normal: - ret = dict_get_str(xattr_req, "link-count", &flag); + ret = dict_get_str_sizen(xattr_req, "link-count", &flag); if ((ret == 0) && (strcmp(flag, GF_XATTROP_INDEX_COUNT) == 0)) { STACK_WIND(frame, index_lookup_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, loc, xattr_req); @@ -2399,6 +2420,7 @@ init(xlator_t *this) gf_uuid_generate(priv->internal_vgfid[i]); INIT_LIST_HEAD(&priv->callstubs); + GF_ATOMIC_INIT(priv->stub_cnt, 0); this->local_pool = mem_pool_new(index_local_t, 64); if (!this->local_pool) { @@ -2427,6 +2449,7 @@ init(xlator_t *this) index_set_link_count(priv, count, XATTROP); priv->down = _gf_false; + priv->curr_count = 0; ret = gf_thread_create(&priv->thread, &w_attr, index_worker, this, "idxwrker"); if (ret) { @@ -2435,7 +2458,7 @@ init(xlator_t *this) "Failed to create worker thread, aborting"); goto out; } - + priv->curr_count++; ret = 0; out: GF_FREE(tmp); @@ -2455,6 +2478,7 @@ out: GF_FREE(priv); this->private = NULL; mem_pool_destroy(this->local_pool); + this->local_pool = NULL; } if (attr_inited) @@ -2553,6 +2577,11 @@ notify(xlator_t *this, int event, void *data, ...) { int ret = 0; index_priv_t *priv = NULL; + uint64_t stub_cnt = 0; + xlator_t *victim = data; + struct timespec sleep_till = { + 0, + }; if (!this) return 0; @@ -2561,6 +2590,39 @@ notify(xlator_t *this, int event, void *data, ...) if (!priv) return 0; + if ((event == GF_EVENT_PARENT_DOWN) && victim->cleanup_starting) { + stub_cnt = GF_ATOMIC_GET(priv->stub_cnt); + timespec_now_realtime(&sleep_till); + sleep_till.tv_sec += 1; + + /* Wait for draining stub from queue before notify PARENT_DOWN */ + pthread_mutex_lock(&priv->mutex); + { + while (stub_cnt) { + (void)pthread_cond_timedwait(&priv->cond, &priv->mutex, + &sleep_till); + stub_cnt = GF_ATOMIC_GET(priv->stub_cnt); + } + } + pthread_mutex_unlock(&priv->mutex); + gf_log(this->name, GF_LOG_INFO, + "Notify GF_EVENT_PARENT_DOWN for brick %s", victim->name); + } + + if ((event == GF_EVENT_CHILD_DOWN) && victim->cleanup_starting) { + pthread_mutex_lock(&priv->mutex); + { + priv->down = _gf_true; + pthread_cond_broadcast(&priv->cond); + while (priv->curr_count) + pthread_cond_wait(&priv->cond, &priv->mutex); + } + pthread_mutex_unlock(&priv->mutex); + + gf_log(this->name, GF_LOG_INFO, + "Notify GF_EVENT_CHILD_DOWN for brick %s", victim->name); + } + ret = default_notify(this, event, data); return ret; } @@ -2604,3 +2666,17 @@ struct volume_options options[] = { .default_value = "trusted.afr.{{ volume.name }}"}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .dumpops = &dumpops, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "index", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/index/src/index.h b/xlators/features/index/src/index.h index f1e0293b794..a2b6e6e2570 100644 --- a/xlators/features/index/src/index.h +++ b/xlators/features/index/src/index.h @@ -11,11 +11,11 @@ #ifndef __INDEX_H__ #define __INDEX_H__ -#include "xlator.h" -#include "call-stub.h" -#include "defaults.h" -#include "byte-order.h" -#include "common-utils.h" +#include <glusterfs/xlator.h> +#include <glusterfs/call-stub.h> +#include <glusterfs/defaults.h> +#include <glusterfs/byte-order.h> +#include <glusterfs/common-utils.h> #include "index-mem-types.h" #define INDEX_THREAD_STACK_SIZE ((size_t)(1024 * 1024)) @@ -58,6 +58,8 @@ typedef struct index_priv { int64_t pending_count; pthread_t thread; gf_boolean_t down; + gf_atomic_t stub_cnt; + int32_t curr_count; } index_priv_t; typedef struct index_local { diff --git a/xlators/features/leases/src/leases-internal.c b/xlators/features/leases/src/leases-internal.c index 8699b99d291..56dee244281 100644 --- a/xlators/features/leases/src/leases-internal.c +++ b/xlators/features/leases/src/leases-internal.c @@ -73,7 +73,7 @@ out: * timeout value(in seconds) set as an option to this xlator. * -1 error case */ -int32_t +static int32_t get_recall_lease_timeout(xlator_t *this) { leases_private_t *priv = NULL; @@ -356,9 +356,8 @@ out: static lease_inode_t * new_lease_inode(inode_t *inode) { - lease_inode_t *l_inode = NULL; - - l_inode = GF_CALLOC(1, sizeof(*l_inode), gf_leases_mt_lease_inode_t); + lease_inode_t *l_inode = GF_MALLOC(sizeof(*l_inode), + gf_leases_mt_lease_inode_t); if (!l_inode) goto out; @@ -379,9 +378,8 @@ __destroy_lease_inode(lease_inode_t *l_inode) static lease_client_t * new_lease_client(const char *client_uid) { - lease_client_t *clnt = NULL; - - clnt = GF_CALLOC(1, sizeof(*clnt), gf_leases_mt_lease_client_t); + lease_client_t *clnt = GF_MALLOC(sizeof(*clnt), + gf_leases_mt_lease_client_t); if (!clnt) goto out; @@ -448,29 +446,29 @@ out: static int add_inode_to_client_list(xlator_t *this, inode_t *inode, const char *client_uid) { - int ret = 0; - leases_private_t *priv = NULL; + leases_private_t *priv = this->private; lease_client_t *clnt = NULL; - lease_inode_t *lease_inode = NULL; - priv = this->private; + lease_inode_t *lease_inode = new_lease_inode(inode); + if (!lease_inode) + return -ENOMEM; + pthread_mutex_lock(&priv->mutex); { clnt = __get_or_new_lease_client(this, priv, client_uid); - GF_CHECK_ALLOC(clnt, ret, out); - - lease_inode = new_lease_inode(inode); - GF_CHECK_ALLOC(lease_inode, ret, out); - + if (!clnt) { + pthread_mutex_unlock(&priv->mutex); + __destroy_lease_inode(lease_inode); + return -ENOMEM; + } list_add_tail(&clnt->inode_list, &lease_inode->list); - gf_msg_debug(this->name, 0, - "Added a new inode:%p to the client(%s) " - "cleanup list, gfid(%s)", - inode, client_uid, uuid_utoa(inode->gfid)); } -out: pthread_mutex_unlock(&priv->mutex); - return ret; + gf_msg_debug(this->name, 0, + "Added a new inode:%p to the client(%s) " + "cleanup list, gfid(%s)", + inode, client_uid, uuid_utoa(inode->gfid)); + return 0; } /* Add lease entry to the corresponding client entry. @@ -587,15 +585,17 @@ remove_from_clnt_list(xlator_t *this, const char *client_uid, inode_t *inode) { clnt = __get_lease_client(this, priv, client_uid); if (!clnt) { + pthread_mutex_unlock(&priv->mutex); gf_msg(this->name, GF_LOG_ERROR, 0, LEASE_MSG_CLNT_NOTFOUND, "There is no client entry found in the cleanup list"); - pthread_mutex_unlock(&priv->mutex); goto out; } ret = __remove_inode_from_clnt_list(this, clnt, inode); if (ret) { + pthread_mutex_unlock(&priv->mutex); gf_msg(this->name, GF_LOG_ERROR, 0, LEASE_MSG_INODE_NOTFOUND, "There is no inode entry found in the cleanup list"); + goto out; } } pthread_mutex_unlock(&priv->mutex); @@ -854,20 +854,20 @@ recall_lease_timer_handler(struct gf_tw_timer_list *timer, void *data, priv = timer_data->this->private; inode = timer_data->inode; + lease_inode = new_lease_inode(inode); + if (!lease_inode) { + errno = ENOMEM; + goto out; + } pthread_mutex_lock(&priv->mutex); { - lease_inode = new_lease_inode(inode); - if (!lease_inode) { - errno = ENOMEM; - goto out; - } list_add_tail(&lease_inode->list, &priv->recall_list); pthread_cond_broadcast(&priv->cond); } + pthread_mutex_unlock(&priv->mutex); out: /* unref the inode_ref taken by timer_data in __recall_lease */ inode_unref(timer_data->inode); - pthread_mutex_unlock(&priv->mutex); GF_FREE(timer); } @@ -887,6 +887,7 @@ __recall_lease(xlator_t *this, lease_inode_ctx_t *lease_ctx) struct gf_tw_timer_list *timer = NULL; leases_private_t *priv = NULL; lease_timer_data_t *timer_data = NULL; + time_t recall_time; if (lease_ctx->recall_in_progress) { gf_msg_debug(this->name, 0, @@ -896,6 +897,7 @@ __recall_lease(xlator_t *this, lease_inode_ctx_t *lease_ctx) } priv = this->private; + recall_time = gf_time(); list_for_each_entry_safe(lease_entry, tmp, &lease_ctx->lease_id_list, lease_id_list) { @@ -919,9 +921,9 @@ __recall_lease(xlator_t *this, lease_inode_ctx_t *lease_ctx) } lease_ctx->recall_in_progress = _gf_true; - lease_entry->recall_time = time(NULL); + lease_entry->recall_time = recall_time; } - timer = GF_CALLOC(1, sizeof(*timer), gf_common_mt_tw_timer_list); + timer = GF_MALLOC(sizeof(*timer), gf_common_mt_tw_timer_list); if (!timer) { goto out; } @@ -1146,12 +1148,13 @@ check_lease_conflict(call_frame_t *frame, inode_t *inode, const char *lease_id, pthread_mutex_lock(&lease_ctx->lock); { if (lease_ctx->lease_type == NONE) { + pthread_mutex_unlock(&lease_ctx->lock); gf_msg_debug(frame->this->name, 0, "No leases found continuing with the" " fop:%s", gf_fop_list[frame->root->op]); ret = WIND_FOP; - goto unlock; + goto out; } conflicts = __check_lease_conflict(frame, lease_ctx, lease_id, is_write_fop); @@ -1178,7 +1181,6 @@ check_lease_conflict(call_frame_t *frame, inode_t *inode, const char *lease_id, } } } -unlock: pthread_mutex_unlock(&lease_ctx->lock); out: return ret; @@ -1355,6 +1357,7 @@ expired_recall_cleanup(void *data) lease_inode_t *tmp = NULL; leases_private_t *priv = NULL; xlator_t *this = NULL; + time_t time_now; GF_VALIDATE_OR_GOTO("leases", data, out); @@ -1364,6 +1367,7 @@ expired_recall_cleanup(void *data) gf_msg_debug(this->name, 0, "Started the expired_recall_cleanup thread"); while (1) { + time_now = gf_time(); pthread_mutex_lock(&priv->mutex); { if (priv->fini) { @@ -1372,7 +1376,7 @@ expired_recall_cleanup(void *data) } INIT_LIST_HEAD(&recall_cleanup_list); if (list_empty(&priv->recall_list)) { - sleep_till.tv_sec = time(NULL) + 600; + sleep_till.tv_sec = time_now + 600; pthread_cond_timedwait(&priv->cond, &priv->mutex, &sleep_till); } if (!list_empty(&priv->recall_list)) { diff --git a/xlators/features/leases/src/leases-mem-types.h b/xlators/features/leases/src/leases-mem-types.h index 59d3cbaf0b3..25664b44156 100644 --- a/xlators/features/leases/src/leases-mem-types.h +++ b/xlators/features/leases/src/leases-mem-types.h @@ -11,11 +11,10 @@ #ifndef __LEASES_MEM_TYPES_H__ #define __LEASES_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_leases_mem_types_ { - gf_leases_mt_conf_t = gf_common_mt_end + 1, - gf_leases_mt_private_t, + gf_leases_mt_private_t = gf_common_mt_end + 1, gf_leases_mt_lease_client_t, gf_leases_mt_lease_inode_t, gf_leases_mt_fd_ctx_t, diff --git a/xlators/features/leases/src/leases-messages.h b/xlators/features/leases/src/leases-messages.h index 81a517f63cd..da696b832de 100644 --- a/xlators/features/leases/src/leases-messages.h +++ b/xlators/features/leases/src/leases-messages.h @@ -11,7 +11,7 @@ #ifndef _LEASES_MESSAGES_H_ #define _LEASES_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/leases/src/leases.c b/xlators/features/leases/src/leases.c index be0f48fd2a2..04bee50ba3f 100644 --- a/xlators/features/leases/src/leases.c +++ b/xlators/features/leases/src/leases.c @@ -35,6 +35,7 @@ leases_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, char *lease_id = NULL; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); fd_ctx = GF_CALLOC(1, sizeof(*fd_ctx), gf_leases_mt_fd_ctx_t); if (!fd_ctx) { @@ -55,7 +56,7 @@ leases_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, else memset(fd_ctx->lease_id, 0, LEASE_ID_SIZE); - ret = fd_ctx_set(fd, this, (uint64_t)fd_ctx); + ret = fd_ctx_set(fd, this, (uint64_t)(uintptr_t)fd_ctx); if (ret) { op_errno = ENOMEM; goto err; @@ -109,6 +110,7 @@ leases_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -157,6 +159,7 @@ leases_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -202,6 +205,7 @@ leases_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS_LK(cmd, flock->l_type, fd->flags); @@ -240,6 +244,7 @@ leases_lease(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t op_ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); ret = process_lease_req(frame, this, loc->inode, lease); if (ret < 0) { @@ -282,6 +287,7 @@ leases_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, 0); @@ -328,6 +334,7 @@ leases_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, 0); @@ -376,6 +383,7 @@ leases_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); /* should the lease be also checked for newloc */ GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); @@ -424,6 +432,7 @@ leases_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, 0); @@ -470,6 +479,7 @@ leases_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, 0); @@ -516,6 +526,7 @@ leases_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, flags); @@ -563,6 +574,7 @@ leases_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -607,6 +619,7 @@ leases_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, 0); /* TODO:fd->flags?*/ @@ -652,6 +665,7 @@ leases_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -697,6 +711,7 @@ leases_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -744,6 +759,7 @@ leases_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -789,6 +805,7 @@ leases_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, int ret = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -834,6 +851,7 @@ leases_flush(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) uint64_t ctx = 0; EXIT_IF_LEASES_OFF(this, out); + EXIT_IF_INTERNAL_FOP(frame, xdata, out); GET_LEASE_ID(xdata, lease_id, frame->root->client->client_uid); GET_FLAGS(frame->root->op, fd->flags); @@ -1000,14 +1018,14 @@ out: return ret; } -int +void fini(xlator_t *this) { leases_private_t *priv = NULL; priv = this->private; if (!priv) { - return 0; + return; } this->private = NULL; @@ -1019,12 +1037,12 @@ fini(xlator_t *this) priv->inited_recall_thr = _gf_false; } - GF_FREE(priv); - if (this->ctx->tw) { + if (priv->timer_wheel) { glusterfs_ctx_tw_put(this->ctx); - this->ctx->tw = NULL; } - return 0; + + GF_FREE(priv); + return; } static int @@ -1135,3 +1153,16 @@ struct volume_options options[] = { " will be forcefully purged by the server."}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "leases", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/leases/src/leases.h b/xlators/features/leases/src/leases.h index 6ac712b0bb0..a6e8a6824cc 100644 --- a/xlators/features/leases/src/leases.h +++ b/xlators/features/leases/src/leases.h @@ -16,15 +16,15 @@ #include "config.h" #endif -#include "common-utils.h" -#include "glusterfs.h" -#include "xlator.h" -#include "call-stub.h" -#include "logging.h" -#include "client_t.h" -#include "lkowner.h" -#include "locking.h" -#include "upcall-utils.h" +#include <glusterfs/common-utils.h> +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/call-stub.h> +#include <glusterfs/logging.h> +#include <glusterfs/client_t.h> +#include <glusterfs/lkowner.h> +#include <glusterfs/locking.h> +#include <glusterfs/upcall-utils.h> #include "timer-wheel.h" #include "leases-mem-types.h" #include "leases-messages.h" @@ -45,6 +45,14 @@ goto label; \ } while (0) +#define EXIT_IF_INTERNAL_FOP(frame, xdata, label) \ + do { \ + if (frame->root->pid < 0) \ + goto label; \ + if (xdata && dict_get(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) \ + goto label; \ + } while (0) + #define GET_LEASE_ID(xdata, lease_id, client_uid) \ do { \ int ret_val = -1; \ @@ -144,17 +152,19 @@ } while (0) struct _leases_private { - gf_boolean_t leases_enabled; - int32_t recall_lease_timeout; struct list_head client_list; struct list_head recall_list; struct tvec_base *timer_wheel; /* timer wheel where the recall request is qued and waits for unlock/expiry */ - gf_boolean_t fini; pthread_t recall_thr; - gf_boolean_t inited_recall_thr; pthread_mutex_t mutex; pthread_cond_t cond; + int32_t recall_lease_timeout; + gf_boolean_t inited_recall_thr; + gf_boolean_t fini; + gf_boolean_t leases_enabled; + + char _pad[1]; /* manual padding */ }; typedef struct _leases_private leases_private_t; @@ -181,18 +191,20 @@ typedef struct _lease_fd_ctx lease_fd_ctx_t; struct _lease_inode_ctx { struct list_head lease_id_list; /* clients that have taken leases */ int lease_type_cnt[GF_LEASE_MAX_TYPE + 1]; + uint64_t lease_cnt; /* Total number of leases on this inode */ + uint64_t openfd_cnt; /* number of fds open */ + struct list_head blocked_list; /* List of fops blocked until the + lease recall is complete */ + inode_t *inode; /* this represents the inode on which the + lock was taken, required mainly during + disconnect cleanup */ + struct gf_tw_timer_list *timer; + pthread_mutex_t lock; int lease_type; /* Types of leases acquired */ - uint64_t lease_cnt; /* Total number of leases on this inode */ - uint64_t openfd_cnt; /* number of fds open */ gf_boolean_t recall_in_progress; /* if lease recall is sent on this inode */ gf_boolean_t blocked_fops_resuming; /* if blocked fops are being resumed */ - struct list_head blocked_list; /* List of fops blocked until the - lease recall is complete */ - inode_t *inode; /* this represents the inode on which the - lock was taken, required mainly during - disconnect cleanup */ - struct gf_tw_timer_list *timer; - pthread_mutex_t lock; + + char _pad[2]; /* manual padding */ }; typedef struct _lease_inode_ctx lease_inode_ctx_t; @@ -202,11 +214,12 @@ struct _lease_id_entry { char *client_uid; /* uid of the client that has taken the lease */ int lease_type_cnt[GF_LEASE_MAX_TYPE + 1]; /* count of each lease type */ - int lease_type; /* Union of all the leases taken - under the given lease id */ uint64_t lease_cnt; /* Number of leases taken under the given lease id */ time_t recall_time; /* time @ which recall was sent */ + int lease_type; /* Union of all the leases taken + under the given lease id */ + char _pad[4]; /* manual padding */ }; typedef struct _lease_id_entry lease_id_entry_t; @@ -226,9 +239,6 @@ typedef struct __lease_timer_data lease_timer_data_t; gf_boolean_t is_leases_enabled(xlator_t *this); -int32_t -get_recall_lease_timeout(xlator_t *this); - lease_inode_ctx_t * lease_ctx_get(inode_t *inode, xlator_t *this); diff --git a/xlators/features/locks/src/clear.c b/xlators/features/locks/src/clear.c index 0966ee753d6..ab1eac68a53 100644 --- a/xlators/features/locks/src/clear.c +++ b/xlators/features/locks/src/clear.c @@ -12,17 +12,23 @@ #include <limits.h> #include <pthread.h> -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> #include "locks.h" #include "common.h" -#include "statedump.h" +#include <glusterfs/statedump.h> #include "clear.h" +const char *clrlk_type_names[CLRLK_TYPE_MAX] = { + [CLRLK_INODE] = "inode", + [CLRLK_ENTRY] = "entry", + [CLRLK_POSIX] = "posix", +}; + int clrlk_get_kind(char *kind) { @@ -175,9 +181,9 @@ clrlk_clear_posixlk(xlator_t *this, pl_inode_t *pl_inode, clrlk_args *args, if (plock->blocked) { bcount++; pl_trace_out(this, plock->frame, NULL, NULL, F_SETLKW, - &plock->user_flock, -1, EAGAIN, NULL); + &plock->user_flock, -1, EINTR, NULL); - STACK_UNWIND_STRICT(lk, plock->frame, -1, EAGAIN, + STACK_UNWIND_STRICT(lk, plock->frame, -1, EINTR, &plock->user_flock, NULL); } else { @@ -254,14 +260,16 @@ blkd: } pthread_mutex_unlock(&pl_inode->mutex); - list_for_each_entry_safe(ilock, tmp, &released, blocked_locks) - { - list_del_init(&ilock->blocked_locks); - pl_trace_out(this, ilock->frame, NULL, NULL, F_SETLKW, - &ilock->user_flock, -1, EAGAIN, ilock->volume); - STACK_UNWIND_STRICT(inodelk, ilock->frame, -1, EAGAIN, NULL); - // No need to take lock as the locks are only in one list - __pl_inodelk_unref(ilock); + if (!list_empty(&released)) { + list_for_each_entry_safe(ilock, tmp, &released, blocked_locks) + { + list_del_init(&ilock->blocked_locks); + pl_trace_out(this, ilock->frame, NULL, NULL, F_SETLKW, + &ilock->user_flock, -1, EAGAIN, ilock->volume); + STACK_UNWIND_STRICT(inodelk, ilock->frame, -1, EAGAIN, NULL); + // No need to take lock as the locks are only in one list + __pl_inodelk_unref(ilock); + } } if (!(args->kind & CLRLK_GRANTED)) { @@ -357,15 +365,17 @@ blkd: } pthread_mutex_unlock(&pl_inode->mutex); - list_for_each_entry_safe(elock, tmp, &released, blocked_locks) - { - list_del_init(&elock->blocked_locks); - entrylk_trace_out(this, elock->frame, elock->volume, NULL, NULL, - elock->basename, ENTRYLK_LOCK, elock->type, -1, - EAGAIN); - STACK_UNWIND_STRICT(entrylk, elock->frame, -1, EAGAIN, NULL); + if (!list_empty(&released)) { + list_for_each_entry_safe(elock, tmp, &released, blocked_locks) + { + list_del_init(&elock->blocked_locks); + entrylk_trace_out(this, elock->frame, elock->volume, NULL, NULL, + elock->basename, ENTRYLK_LOCK, elock->type, -1, + EAGAIN); + STACK_UNWIND_STRICT(entrylk, elock->frame, -1, EAGAIN, NULL); - __pl_entrylk_unref(elock); + __pl_entrylk_unref(elock); + } } if (!(args->kind & CLRLK_GRANTED)) { diff --git a/xlators/features/locks/src/clear.h b/xlators/features/locks/src/clear.h index 08662746f98..bc118cb1b81 100644 --- a/xlators/features/locks/src/clear.h +++ b/xlators/features/locks/src/clear.h @@ -10,9 +10,9 @@ #ifndef __CLEAR_H__ #define __CLEAR_H__ -#include "compat-errno.h" -#include "stack.h" -#include "call-stub.h" +#include <glusterfs/compat-errno.h> +#include <glusterfs/stack.h> +#include <glusterfs/call-stub.h> #include "locks.h" typedef enum { @@ -22,6 +22,8 @@ typedef enum { CLRLK_TYPE_MAX } clrlk_type; +extern const char *clrlk_type_names[]; + typedef enum { CLRLK_BLOCKED = 1, CLRLK_GRANTED, diff --git a/xlators/features/locks/src/common.c b/xlators/features/locks/src/common.c index a953e0d1a4a..a2c6be93e03 100644 --- a/xlators/features/locks/src/common.c +++ b/xlators/features/locks/src/common.c @@ -12,11 +12,10 @@ #include <limits.h> #include <pthread.h> -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/logging.h> +#include <glusterfs/syncop.h> #include "locks.h" #include "common.h" @@ -213,13 +212,11 @@ void pl_trace_in(xlator_t *this, call_frame_t *frame, fd_t *fd, loc_t *loc, int cmd, struct gf_flock *flock, const char *domain) { - posix_locks_private_t *priv = NULL; + posix_locks_private_t *priv = this->private; char pl_locker[256]; char pl_lockee[256]; char pl_lock[256]; - priv = this->private; - if (!priv->trace) return; @@ -291,13 +288,11 @@ pl_trace_block(xlator_t *this, call_frame_t *frame, fd_t *fd, loc_t *loc, int cmd, struct gf_flock *flock, const char *domain) { - posix_locks_private_t *priv = NULL; + posix_locks_private_t *priv = this->private; char pl_locker[256]; char pl_lockee[256]; char pl_lock[256]; - priv = this->private; - if (!priv->trace) return; @@ -326,7 +321,7 @@ pl_trace_flush(xlator_t *this, call_frame_t *frame, fd_t *fd) if (!priv->trace) return; - pl_inode = pl_inode_get(this, fd->inode); + pl_inode = pl_inode_get(this, fd->inode, NULL); if (pl_inode && __pl_inode_is_empty(pl_inode)) return; @@ -362,7 +357,9 @@ pl_update_refkeeper(xlator_t *this, inode_t *inode) int need_unref = 0; int need_ref = 0; - pl_inode = pl_inode_get(this, inode); + pl_inode = pl_inode_get(this, inode, NULL); + if (!pl_inode) + return; pthread_mutex_lock(&pl_inode->mutex); { @@ -387,8 +384,51 @@ pl_update_refkeeper(xlator_t *this, inode_t *inode) inode_ref(inode); } +/* Get lock enforcement info from disk */ +int +pl_fetch_mlock_info_from_disk(xlator_t *this, pl_inode_t *pl_inode, + pl_local_t *local) +{ + dict_t *xdata_rsp = NULL; + int ret = 0; + int op_ret = 0; + + if (!local) { + return -1; + } + + if (local->fd) { + op_ret = syncop_fgetxattr(this, local->fd, &xdata_rsp, + GF_ENFORCE_MANDATORY_LOCK, NULL, NULL); + } else { + op_ret = syncop_getxattr(this, &local->loc[0], &xdata_rsp, + GF_ENFORCE_MANDATORY_LOCK, NULL, NULL); + } + + pthread_mutex_lock(&pl_inode->mutex); + { + if (op_ret >= 0) { + pl_inode->mlock_enforced = _gf_true; + pl_inode->check_mlock_info = _gf_false; + } else { + gf_msg(this->name, GF_LOG_WARNING, -op_ret, 0, + "getxattr failed with %d", op_ret); + pl_inode->mlock_enforced = _gf_false; + + if (-op_ret == ENODATA) { + pl_inode->check_mlock_info = _gf_false; + } else { + pl_inode->check_mlock_info = _gf_true; + } + } + } + pthread_mutex_unlock(&pl_inode->mutex); + + return ret; +} + pl_inode_t * -pl_inode_get(xlator_t *this, inode_t *inode) +pl_inode_get(xlator_t *this, inode_t *inode, pl_local_t *local) { uint64_t tmp_pl_inode = 0; pl_inode_t *pl_inode = NULL; @@ -401,6 +441,7 @@ pl_inode_get(xlator_t *this, inode_t *inode) pl_inode = (pl_inode_t *)(long)tmp_pl_inode; goto unlock; } + pl_inode = GF_CALLOC(1, sizeof(*pl_inode), gf_locks_mt_pl_inode_t); if (!pl_inode) { goto unlock; @@ -409,6 +450,7 @@ pl_inode_get(xlator_t *this, inode_t *inode) gf_log(this->name, GF_LOG_TRACE, "Allocating new pl inode"); pthread_mutex_init(&pl_inode->mutex, NULL); + pthread_cond_init(&pl_inode->check_fop_wind_count, 0); INIT_LIST_HEAD(&pl_inode->dom_list); INIT_LIST_HEAD(&pl_inode->ext_list); @@ -418,8 +460,16 @@ pl_inode_get(xlator_t *this, inode_t *inode) INIT_LIST_HEAD(&pl_inode->blocked_calls); INIT_LIST_HEAD(&pl_inode->metalk_list); INIT_LIST_HEAD(&pl_inode->queued_locks); + INIT_LIST_HEAD(&pl_inode->waiting); gf_uuid_copy(pl_inode->gfid, inode->gfid); + pl_inode->check_mlock_info = _gf_true; + pl_inode->mlock_enforced = _gf_false; + + /* -2 means never looked up. -1 means something went wrong and link + * tracking is disabled. */ + pl_inode->links = -2; + ret = __inode_ctx_put(inode, this, (uint64_t)(long)(pl_inode)); if (ret) { pthread_mutex_destroy(&pl_inode->mutex); @@ -431,13 +481,23 @@ pl_inode_get(xlator_t *this, inode_t *inode) unlock: UNLOCK(&inode->lock); + if ((pl_inode != NULL) && pl_is_mandatory_locking_enabled(pl_inode) && + pl_inode->check_mlock_info && local) { + /* Note: The lock enforcement information per file can be stored in the + attribute flag of stat(x) in posix. With that there won't be a need + for doing getxattr post a reboot + */ + pl_fetch_mlock_info_from_disk(this, pl_inode, local); + } + return pl_inode; } /* Create a new posix_lock_t */ posix_lock_t * new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid, - gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int blocking) + gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int blocking, + int32_t *op_errno) { posix_lock_t *lock = NULL; @@ -445,8 +505,14 @@ new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid, GF_VALIDATE_OR_GOTO("posix-locks", client, out); GF_VALIDATE_OR_GOTO("posix-locks", fd, out); + if (!pl_is_lk_owner_valid(owner, client)) { + *op_errno = EINVAL; + goto out; + } + lock = GF_CALLOC(1, sizeof(posix_lock_t), gf_locks_mt_posix_lock_t); if (!lock) { + *op_errno = ENOMEM; goto out; } @@ -464,6 +530,7 @@ new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid, if (lock->client_uid == NULL) { GF_FREE(lock); lock = NULL; + *op_errno = ENOMEM; goto out; } @@ -538,13 +605,11 @@ static void __insert_lock(pl_inode_t *pl_inode, posix_lock_t *lock) { if (lock->blocked) - gettimeofday(&lock->blkd_time, NULL); + lock->blkd_time = gf_time(); else - gettimeofday(&lock->granted_time, NULL); + lock->granted_time = gf_time(); list_add_tail(&lock->list, &pl_inode->ext_list); - - return; } /* Return true if the locks overlap, false otherwise */ @@ -900,7 +965,7 @@ grant_blocked_locks(xlator_t *this, pl_inode_t *pl_inode) struct list_head granted_list; posix_lock_t *tmp = NULL; posix_lock_t *lock = NULL; - + pl_local_t *local = NULL; INIT_LIST_HEAD(&granted_list); pthread_mutex_lock(&pl_inode->mutex); @@ -915,9 +980,9 @@ grant_blocked_locks(xlator_t *this, pl_inode_t *pl_inode) pl_trace_out(this, lock->frame, NULL, NULL, F_SETLKW, &lock->user_flock, 0, 0, NULL); - - STACK_UNWIND_STRICT(lk, lock->frame, 0, 0, &lock->user_flock, NULL); - + local = lock->frame->local; + PL_STACK_UNWIND_AND_FREE(local, lk, lock->frame, 0, 0, + &lock->user_flock, NULL); __destroy_lock(lock); } @@ -932,10 +997,12 @@ pl_send_prelock_unlock(xlator_t *this, pl_inode_t *pl_inode, 0, }; posix_lock_t *unlock_lock = NULL; + int32_t op_errno = 0; struct list_head granted_list; posix_lock_t *tmp = NULL; posix_lock_t *lock = NULL; + pl_local_t *local = NULL; int ret = -1; @@ -949,7 +1016,7 @@ pl_send_prelock_unlock(xlator_t *this, pl_inode_t *pl_inode, unlock_lock = new_posix_lock(&flock, old_lock->client, old_lock->client_pid, &old_lock->owner, old_lock->fd, - old_lock->lk_flags, 0); + old_lock->lk_flags, 0, &op_errno); GF_VALIDATE_OR_GOTO(this->name, unlock_lock, out); ret = 0; @@ -963,9 +1030,9 @@ pl_send_prelock_unlock(xlator_t *this, pl_inode_t *pl_inode, pl_trace_out(this, lock->frame, NULL, NULL, F_SETLKW, &lock->user_flock, 0, 0, NULL); - - STACK_UNWIND_STRICT(lk, lock->frame, 0, 0, &lock->user_flock, NULL); - + local = lock->frame->local; + PL_STACK_UNWIND_AND_FREE(local, lk, lock->frame, 0, 0, + &lock->user_flock, NULL); __destroy_lock(lock); } @@ -1000,7 +1067,7 @@ pl_setlk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, if (__is_lock_grantable(pl_inode, lock)) { if (pl_metalock_is_active(pl_inode)) { - __pl_queue_lock(pl_inode, lock, can_block); + __pl_queue_lock(pl_inode, lock); pthread_mutex_unlock(&pl_inode->mutex); ret = -2; goto out; @@ -1013,7 +1080,7 @@ pl_setlk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, __insert_and_merge(pl_inode, lock); } else if (can_block) { if (pl_metalock_is_active(pl_inode)) { - __pl_queue_lock(pl_inode, lock, can_block); + __pl_queue_lock(pl_inode, lock); pthread_mutex_unlock(&pl_inode->mutex); ret = -2; goto out; @@ -1024,6 +1091,10 @@ pl_setlk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, lkowner_utoa(&lock->owner), lock->user_flock.l_start, lock->user_flock.l_len); + + pl_trace_block(this, lock->frame, NULL, NULL, F_SETLKW, + &lock->user_flock, NULL); + lock->blocked = 1; __insert_lock(pl_inode, lock); ret = -1; @@ -1050,10 +1121,7 @@ out: posix_lock_t * pl_getlk(pl_inode_t *pl_inode, posix_lock_t *lock) { - posix_lock_t *conf = NULL; - - conf = first_conflicting_overlap(pl_inode, lock); - + posix_lock_t *conf = first_conflicting_overlap(pl_inode, lock); if (conf == NULL) { lock->fl_type = F_UNLCK; return lock; @@ -1075,3 +1143,449 @@ pl_does_monkey_want_stuck_lock() return _gf_true; return _gf_false; } + +int +pl_lock_preempt(pl_inode_t *pl_inode, posix_lock_t *reqlock) +{ + posix_lock_t *lock = NULL; + posix_lock_t *i = NULL; + pl_rw_req_t *rw = NULL; + pl_rw_req_t *itr = NULL; + struct list_head unwind_blist = { + 0, + }; + struct list_head unwind_rw_list = { + 0, + }; + int ret = 0; + + INIT_LIST_HEAD(&unwind_blist); + INIT_LIST_HEAD(&unwind_rw_list); + + pthread_mutex_lock(&pl_inode->mutex); + { + /* + - go through the lock list + - remove all locks from different owners + - same owner locks will be added or substracted based on + the new request + - add the new lock + */ + list_for_each_entry_safe(lock, i, &pl_inode->ext_list, list) + { + if (lock->blocked) { + list_del_init(&lock->list); + list_add(&lock->list, &unwind_blist); + continue; + } + + if (locks_overlap(lock, reqlock)) { + if (same_owner(lock, reqlock)) + continue; + + /* remove conflicting locks */ + list_del_init(&lock->list); + __delete_lock(lock); + __destroy_lock(lock); + } + } + + __insert_and_merge(pl_inode, reqlock); + + list_for_each_entry_safe(rw, itr, &pl_inode->rw_list, list) + { + list_del_init(&rw->list); + list_add(&rw->list, &unwind_rw_list); + } + } + pthread_mutex_unlock(&pl_inode->mutex); + + /* unwind blocked locks */ + list_for_each_entry_safe(lock, i, &unwind_blist, list) + { + PL_STACK_UNWIND_AND_FREE(((pl_local_t *)lock->frame->local), lk, + lock->frame, -1, EBUSY, &lock->user_flock, + NULL); + __destroy_lock(lock); + } + + /* unwind blocked IOs */ + list_for_each_entry_safe(rw, itr, &unwind_rw_list, list) + { + pl_clean_local(rw->stub->frame->local); + call_unwind_error(rw->stub, -1, EBUSY); + } + + return ret; +} + +/* Return true in case we need to ensure mandatory-locking + * semantics under different modes. + */ +gf_boolean_t +pl_is_mandatory_locking_enabled(pl_inode_t *pl_inode) +{ + posix_locks_private_t *priv = THIS->private; + + if (priv->mandatory_mode == MLK_FILE_BASED && pl_inode->mandatory) + return _gf_true; + else if (priv->mandatory_mode == MLK_FORCED || + priv->mandatory_mode == MLK_OPTIMAL) + return _gf_true; + + return _gf_false; +} + +void +pl_clean_local(pl_local_t *local) +{ + if (!local) + return; + + if (local->inodelk_dom_count_req) + data_unref(local->inodelk_dom_count_req); + loc_wipe(&local->loc[0]); + loc_wipe(&local->loc[1]); + if (local->fd) + fd_unref(local->fd); + if (local->inode) + inode_unref(local->inode); + mem_put(local); +} + +/* +TODO: detach local initialization from PL_LOCAL_GET_REQUESTS and add it here +*/ +int +pl_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd) +{ + pl_local_t *local = NULL; + + if (!loc && !fd) { + return -1; + } + + if (!frame->local) { + local = mem_get0(this->local_pool); + if (!local) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, 0, + "mem allocation failed"); + return -1; + } + + local->inode = (loc ? inode_ref(loc->inode) : inode_ref(fd->inode)); + + frame->local = local; + } + + return 0; +} + +gf_boolean_t +pl_is_lk_owner_valid(gf_lkowner_t *owner, client_t *client) +{ + if (client && (client->opversion < GD_OP_VERSION_7_0)) { + return _gf_true; + } + + if (is_lk_owner_null(owner)) { + return _gf_false; + } + return _gf_true; +} + +static int32_t +pl_inode_from_loc(loc_t *loc, inode_t **pinode) +{ + inode_t *inode = NULL; + int32_t error = 0; + + if (loc->inode != NULL) { + inode = inode_ref(loc->inode); + goto done; + } + + if (loc->parent == NULL) { + error = EINVAL; + goto done; + } + + if (!gf_uuid_is_null(loc->gfid)) { + inode = inode_find(loc->parent->table, loc->gfid); + if (inode != NULL) { + goto done; + } + } + + if (loc->name == NULL) { + error = EINVAL; + goto done; + } + + inode = inode_grep(loc->parent->table, loc->parent, loc->name); + if (inode == NULL) { + /* We haven't found any inode. This means that the file doesn't exist + * or that even if it exists, we don't have any knowledge about it, so + * we don't have locks on it either, which is fine for our purposes. */ + goto done; + } + +done: + *pinode = inode; + + return error; +} + +static gf_boolean_t +pl_inode_has_owners(xlator_t *xl, client_t *client, pl_inode_t *pl_inode, + struct timespec *now, struct list_head *contend) +{ + pl_dom_list_t *dom; + pl_inode_lock_t *lock; + gf_boolean_t has_owners = _gf_false; + + list_for_each_entry(dom, &pl_inode->dom_list, inode_list) + { + list_for_each_entry(lock, &dom->inodelk_list, list) + { + /* If the lock belongs to the same client, we assume it's related + * to the same operation, so we allow the removal to continue. */ + if (lock->client == client) { + continue; + } + /* If the lock belongs to an internal process, we don't block the + * removal. */ + if (lock->client_pid < 0) { + continue; + } + if (contend == NULL) { + return _gf_true; + } + has_owners = _gf_true; + inodelk_contention_notify_check(xl, lock, now, contend); + } + } + + return has_owners; +} + +int32_t +pl_inode_remove_prepare(xlator_t *xl, call_frame_t *frame, loc_t *loc, + pl_inode_t **ppl_inode, struct list_head *contend) +{ + struct timespec now; + inode_t *inode; + pl_inode_t *pl_inode; + int32_t error; + + pl_inode = NULL; + + error = pl_inode_from_loc(loc, &inode); + if ((error != 0) || (inode == NULL)) { + goto done; + } + + pl_inode = pl_inode_get(xl, inode, NULL); + if (pl_inode == NULL) { + inode_unref(inode); + error = ENOMEM; + goto done; + } + + /* pl_inode_from_loc() already increments ref count for inode, so + * we only assign here our reference. */ + pl_inode->inode = inode; + + timespec_now(&now); + + pthread_mutex_lock(&pl_inode->mutex); + + if (pl_inode->removed) { + error = ESTALE; + goto unlock; + } + + if (pl_inode_has_owners(xl, frame->root->client, pl_inode, &now, contend)) { + error = -1; + /* We skip the unlock here because the caller must create a stub when + * we return -1 and do a call to pl_inode_remove_complete(), which + * assumes the lock is still acquired and will release it once + * everything else is prepared. */ + goto done; + } + + pl_inode->is_locked = _gf_true; + pl_inode->remove_running++; + +unlock: + pthread_mutex_unlock(&pl_inode->mutex); + +done: + *ppl_inode = pl_inode; + + return error; +} + +int32_t +pl_inode_remove_complete(xlator_t *xl, pl_inode_t *pl_inode, call_stub_t *stub, + struct list_head *contend) +{ + pl_inode_lock_t *lock; + int32_t error = -1; + + if (stub != NULL) { + list_add_tail(&stub->list, &pl_inode->waiting); + pl_inode->is_locked = _gf_true; + } else { + error = ENOMEM; + + while (!list_empty(contend)) { + lock = list_first_entry(contend, pl_inode_lock_t, list); + list_del_init(&lock->list); + __pl_inodelk_unref(lock); + } + } + + pthread_mutex_unlock(&pl_inode->mutex); + + if (error < 0) { + inodelk_contention_notify(xl, contend); + } + + inode_unref(pl_inode->inode); + + return error; +} + +void +pl_inode_remove_wake(struct list_head *list) +{ + call_stub_t *stub; + + while (!list_empty(list)) { + stub = list_first_entry(list, call_stub_t, list); + list_del_init(&stub->list); + + call_resume(stub); + } +} + +void +pl_inode_remove_cbk(xlator_t *xl, pl_inode_t *pl_inode, int32_t error) +{ + struct list_head contend, granted; + struct timespec now; + pl_dom_list_t *dom; + + if (pl_inode == NULL) { + return; + } + + INIT_LIST_HEAD(&contend); + INIT_LIST_HEAD(&granted); + timespec_now(&now); + + pthread_mutex_lock(&pl_inode->mutex); + + if (error == 0) { + if (pl_inode->links >= 0) { + pl_inode->links--; + } + if (pl_inode->links == 0) { + pl_inode->removed = _gf_true; + } + } + + pl_inode->remove_running--; + + if ((pl_inode->remove_running == 0) && list_empty(&pl_inode->waiting)) { + pl_inode->is_locked = _gf_false; + + list_for_each_entry(dom, &pl_inode->dom_list, inode_list) + { + __grant_blocked_inode_locks(xl, pl_inode, &granted, dom, &now, + &contend); + } + } + + pthread_mutex_unlock(&pl_inode->mutex); + + unwind_granted_inodes(xl, pl_inode, &granted); + + inodelk_contention_notify(xl, &contend); + + inode_unref(pl_inode->inode); +} + +void +pl_inode_remove_unlocked(xlator_t *xl, pl_inode_t *pl_inode, + struct list_head *list) +{ + call_stub_t *stub, *tmp; + + if (!pl_inode->is_locked) { + return; + } + + list_for_each_entry_safe(stub, tmp, &pl_inode->waiting, list) + { + if (!pl_inode_has_owners(xl, stub->frame->root->client, pl_inode, NULL, + NULL)) { + list_move_tail(&stub->list, list); + } + } +} + +/* This function determines if an inodelk attempt can be done now or it needs + * to wait. + * + * Possible return values: + * < 0: An error occurred. Currently only -ESTALE can be returned if the + * inode has been deleted previously by unlink/rmdir/rename + * = 0: The lock can be attempted. + * > 0: The lock needs to wait because a conflicting remove operation is + * ongoing. + */ +int32_t +pl_inode_remove_inodelk(pl_inode_t *pl_inode, pl_inode_lock_t *lock) +{ + pl_dom_list_t *dom; + pl_inode_lock_t *ilock; + + /* If the inode has been deleted, we won't allow any lock. */ + if (pl_inode->removed) { + return -ESTALE; + } + + /* We only synchronize with locks made for regular operations coming from + * the user. Locks done for internal purposes are hard to control and could + * lead to long delays or deadlocks quite easily. */ + if (lock->client_pid < 0) { + return 0; + } + if (!pl_inode->is_locked) { + return 0; + } + if (pl_inode->remove_running > 0) { + return 1; + } + + list_for_each_entry(dom, &pl_inode->dom_list, inode_list) + { + list_for_each_entry(ilock, &dom->inodelk_list, list) + { + /* If a lock from the same client is already granted, we allow this + * one to continue. This is necessary to prevent deadlocks when + * multiple locks are taken for the same operation. + * + * On the other side it's unlikely that the same client sends + * completely unrelated locks for the same inode. + */ + if (ilock->client == lock->client) { + return 0; + } + } + } + + return 1; +} diff --git a/xlators/features/locks/src/common.h b/xlators/features/locks/src/common.h index c3d0e361933..281223bf3b8 100644 --- a/xlators/features/locks/src/common.h +++ b/xlators/features/locks/src/common.h @@ -10,7 +10,6 @@ #ifndef __COMMON_H__ #define __COMMON_H__ -#include "lkowner.h" /*dump locks format strings */ #define RANGE_FMT "type=%s, whence=%hd, start=%llu, len=%llu" #define ENTRY_FMT "type=%s on basename=%s" @@ -32,12 +31,34 @@ #define SET_FLOCK_PID(flock, lock) ((flock)->l_pid = lock->client_pid) +#define PL_STACK_UNWIND_AND_FREE(__local, fop, frame, op_ret, params...) \ + do { \ + frame->local = NULL; \ + STACK_UNWIND_STRICT(fop, frame, op_ret, params); \ + if (__local) { \ + if (__local->inodelk_dom_count_req) \ + data_unref(__local->inodelk_dom_count_req); \ + loc_wipe(&__local->loc[0]); \ + loc_wipe(&__local->loc[1]); \ + if (__local->fd) \ + fd_unref(__local->fd); \ + if (__local->inode) \ + inode_unref(__local->inode); \ + if (__local->xdata) { \ + dict_unref(__local->xdata); \ + __local->xdata = NULL; \ + } \ + mem_put(__local); \ + } \ + } while (0) + posix_lock_t * new_posix_lock(struct gf_flock *flock, client_t *client, pid_t client_pid, - gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int can_block); + gf_lkowner_t *owner, fd_t *fd, uint32_t lk_flags, int blocking, + int32_t *op_errno); pl_inode_t * -pl_inode_get(xlator_t *this, inode_t *inode); +pl_inode_get(xlator_t *this, inode_t *inode, pl_local_t *local); posix_lock_t * pl_getlk(pl_inode_t *inode, posix_lock_t *lock); @@ -45,6 +66,9 @@ pl_getlk(pl_inode_t *inode, posix_lock_t *lock); int pl_setlk(xlator_t *this, pl_inode_t *inode, posix_lock_t *lock, int can_block); +int +pl_lock_preempt(pl_inode_t *pl_inode, posix_lock_t *reqlock); + void grant_blocked_locks(xlator_t *this, pl_inode_t *inode); @@ -81,6 +105,15 @@ void __pl_inodelk_unref(pl_inode_lock_t *lock); void +__grant_blocked_inode_locks(xlator_t *this, pl_inode_t *pl_inode, + struct list_head *granted, pl_dom_list_t *dom, + struct timespec *now, struct list_head *contend); + +void +unwind_granted_inodes(xlator_t *this, pl_inode_t *pl_inode, + struct list_head *granted); + +void grant_blocked_entry_locks(xlator_t *this, pl_inode_t *pl_inode, pl_dom_list_t *dom, struct timespec *now, struct list_head *contend); @@ -177,9 +210,53 @@ __pl_entrylk_unref(pl_entry_lock_t *lock); int pl_metalock_is_active(pl_inode_t *pl_inode); -int -__pl_queue_lock(pl_inode_t *pl_inode, posix_lock_t *reqlock, int can_block); +void +__pl_queue_lock(pl_inode_t *pl_inode, posix_lock_t *reqlock); + +void +inodelk_contention_notify_check(xlator_t *xl, pl_inode_lock_t *lock, + struct timespec *now, + struct list_head *contend); + +void +entrylk_contention_notify_check(xlator_t *xl, pl_entry_lock_t *lock, + struct timespec *now, + struct list_head *contend); gf_boolean_t pl_does_monkey_want_stuck_lock(); + +gf_boolean_t +pl_is_mandatory_locking_enabled(pl_inode_t *pl_inode); + +void +pl_clean_local(pl_local_t *local); + +int +pl_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd); + +gf_boolean_t +pl_is_lk_owner_valid(gf_lkowner_t *owner, client_t *client); + +int32_t +pl_inode_remove_prepare(xlator_t *xl, call_frame_t *frame, loc_t *loc, + pl_inode_t **ppl_inode, struct list_head *contend); + +int32_t +pl_inode_remove_complete(xlator_t *xl, pl_inode_t *pl_inode, call_stub_t *stub, + struct list_head *contend); + +void +pl_inode_remove_wake(struct list_head *list); + +void +pl_inode_remove_cbk(xlator_t *xl, pl_inode_t *pl_inode, int32_t error); + +void +pl_inode_remove_unlocked(xlator_t *xl, pl_inode_t *pl_inode, + struct list_head *list); + +int32_t +pl_inode_remove_inodelk(pl_inode_t *pl_inode, pl_inode_lock_t *lock); + #endif /* __COMMON_H__ */ diff --git a/xlators/features/locks/src/entrylk.c b/xlators/features/locks/src/entrylk.c index ea78f92d200..fd772c850dd 100644 --- a/xlators/features/locks/src/entrylk.c +++ b/xlators/features/locks/src/entrylk.c @@ -7,13 +7,13 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" -#include "list.h" -#include "upcall-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> +#include <glusterfs/list.h> +#include <glusterfs/upcall-utils.h> #include "locks.h" #include "clear.h" @@ -39,13 +39,20 @@ __pl_entrylk_ref(pl_entry_lock_t *lock) static pl_entry_lock_t * new_entrylk_lock(pl_inode_t *pinode, const char *basename, entrylk_type type, - const char *domain, call_frame_t *frame, char *conn_id) + const char *domain, call_frame_t *frame, char *conn_id, + int32_t *op_errno) { pl_entry_lock_t *newlock = NULL; + if (!pl_is_lk_owner_valid(&frame->root->lk_owner, frame->root->client)) { + *op_errno = EINVAL; + goto out; + } + newlock = GF_CALLOC(1, sizeof(pl_entry_lock_t), gf_locks_mt_pl_entry_lock_t); if (!newlock) { + *op_errno = ENOMEM; goto out; } @@ -114,8 +121,6 @@ __stale_entrylk(xlator_t *this, pl_entry_lock_t *candidate_lock, pl_entry_lock_t *requested_lock, time_t *lock_age_sec) { posix_locks_private_t *priv = NULL; - struct timeval curr; - gettimeofday(&curr, NULL); priv = this->private; @@ -123,7 +128,7 @@ __stale_entrylk(xlator_t *this, pl_entry_lock_t *candidate_lock, * chance? Or just the locks we are attempting to acquire? */ if (names_conflict(candidate_lock->basename, requested_lock->basename)) { - *lock_age_sec = curr.tv_sec - candidate_lock->granted_time.tv_sec; + *lock_age_sec = gf_time() - candidate_lock->granted_time; if (*lock_age_sec > priv->revocation_secs) return _gf_true; } @@ -197,9 +202,9 @@ out: return revoke_lock; } -static gf_boolean_t -__entrylk_needs_contention_notify(xlator_t *this, pl_entry_lock_t *lock, - struct timespec *now) +void +entrylk_contention_notify_check(xlator_t *this, pl_entry_lock_t *lock, + struct timespec *now, struct list_head *contend) { posix_locks_private_t *priv; int64_t elapsed; @@ -209,7 +214,7 @@ __entrylk_needs_contention_notify(xlator_t *this, pl_entry_lock_t *lock, /* If this lock is in a list, it means that we are about to send a * notification for it, so no need to do anything else. */ if (!list_empty(&lock->contend)) { - return _gf_false; + return; } elapsed = now->tv_sec; @@ -218,7 +223,7 @@ __entrylk_needs_contention_notify(xlator_t *this, pl_entry_lock_t *lock, elapsed--; } if (elapsed < priv->notify_contention_delay) { - return _gf_false; + return; } /* All contention notifications will be sent outside of the locked @@ -231,7 +236,7 @@ __entrylk_needs_contention_notify(xlator_t *this, pl_entry_lock_t *lock, lock->contention_time = *now; - return _gf_true; + list_add_tail(&lock->contend, contend); } void @@ -325,9 +330,7 @@ __entrylk_grantable(xlator_t *this, pl_dom_list_t *dom, pl_entry_lock_t *lock, break; } } - if (__entrylk_needs_contention_notify(this, tmp, now)) { - list_add_tail(&tmp->contend, contend); - } + entrylk_contention_notify_check(this, tmp, now, contend); } } @@ -539,19 +542,17 @@ static int __lock_blocked_add(xlator_t *this, pl_inode_t *pinode, pl_dom_list_t *dom, pl_entry_lock_t *lock, int nonblock) { - struct timeval now; - - gettimeofday(&now, NULL); - if (nonblock) goto out; - lock->blkd_time = now; + lock->blkd_time = gf_time(); list_add_tail(&lock->blocked_locks, &dom->blocked_entrylks); gf_msg_trace(this->name, 0, "Blocking lock: {pinode=%p, basename=%s}", pinode, lock->basename); + entrylk_trace_block(this, lock->frame, NULL, NULL, NULL, lock->basename, + ENTRYLK_LOCK, lock->type); out: return -EAGAIN; } @@ -605,7 +606,7 @@ __lock_entrylk(xlator_t *this, pl_inode_t *pinode, pl_entry_lock_t *lock, } __pl_entrylk_ref(lock); - gettimeofday(&lock->granted_time, NULL); + lock->granted_time = gf_time(); list_add(&lock->domain_list, &dom->entrylk_list); ret = 0; @@ -644,11 +645,10 @@ int32_t check_entrylk_on_basename(xlator_t *this, inode_t *parent, char *basename) { int32_t entrylk = 0; - pl_inode_t *pinode = 0; pl_dom_list_t *dom = NULL; pl_entry_lock_t *conf = NULL; - pinode = pl_inode_get(this, parent); + pl_inode_t *pinode = pl_inode_get(this, parent, NULL); if (!pinode) goto out; pthread_mutex_lock(&pinode->mutex); @@ -689,10 +689,9 @@ __grant_blocked_entry_locks(xlator_t *this, pl_inode_t *pl_inode, bl_ret = __lock_entrylk(bl->this, pl_inode, bl, 0, dom, now, contend); if (bl_ret == 0) { - list_add(&bl->blocked_locks, granted); + list_add_tail(&bl->blocked_locks, granted); } } - return; } /* Grants locks if possible which are blocked on a lock */ @@ -770,7 +769,7 @@ pl_common_entrylk(call_frame_t *frame, xlator_t *this, const char *volume, if (xdata) dict_ret = dict_get_str(xdata, "connection-id", &conn_id); - pinode = pl_inode_get(this, inode); + pinode = pl_inode_get(this, inode, NULL); if (!pinode) { op_errno = ENOMEM; goto out; @@ -794,10 +793,9 @@ pl_common_entrylk(call_frame_t *frame, xlator_t *this, const char *volume, entrylk_trace_in(this, frame, volume, fd, loc, basename, cmd, type); reqlock = new_entrylk_lock(pinode, basename, type, dom->domain, frame, - conn_id); + conn_id, &op_errno); if (!reqlock) { op_ret = -1; - op_errno = ENOMEM; goto unwind; } @@ -933,8 +931,6 @@ out: op_ret, op_errno); unwind: STACK_UNWIND_STRICT(entrylk, frame, op_ret, op_errno, NULL); - } else { - entrylk_trace_block(this, frame, volume, fd, loc, basename, cmd, type); } if (pcontend != NULL) { @@ -1072,32 +1068,36 @@ pl_entrylk_client_cleanup(xlator_t *this, pl_ctx_t *ctx) } pthread_mutex_unlock(&ctx->lock); - list_for_each_entry_safe(l, tmp, &unwind, client_list) - { - list_del_init(&l->client_list); + if (!list_empty(&unwind)) { + list_for_each_entry_safe(l, tmp, &unwind, client_list) + { + list_del_init(&l->client_list); - if (l->frame) - STACK_UNWIND_STRICT(entrylk, l->frame, -1, EAGAIN, NULL); - list_add_tail(&l->client_list, &released); + if (l->frame) + STACK_UNWIND_STRICT(entrylk, l->frame, -1, EAGAIN, NULL); + list_add_tail(&l->client_list, &released); + } } - list_for_each_entry_safe(l, tmp, &released, client_list) - { - list_del_init(&l->client_list); + if (!list_empty(&released)) { + list_for_each_entry_safe(l, tmp, &released, client_list) + { + list_del_init(&l->client_list); - pinode = l->pinode; + pinode = l->pinode; - dom = get_domain(pinode, l->volume); + dom = get_domain(pinode, l->volume); - grant_blocked_entry_locks(this, pinode, dom, &now, pcontend); + grant_blocked_entry_locks(this, pinode, dom, &now, pcontend); - pthread_mutex_lock(&pinode->mutex); - { - __pl_entrylk_unref(l); - } - pthread_mutex_unlock(&pinode->mutex); + pthread_mutex_lock(&pinode->mutex); + { + __pl_entrylk_unref(l); + } + pthread_mutex_unlock(&pinode->mutex); - inode_unref(pinode->inode); + inode_unref(pinode->inode); + } } if (pcontend != NULL) { diff --git a/xlators/features/locks/src/inodelk.c b/xlators/features/locks/src/inodelk.c index eff58a79569..d4e51d6e0a1 100644 --- a/xlators/features/locks/src/inodelk.c +++ b/xlators/features/locks/src/inodelk.c @@ -7,18 +7,16 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" -#include "list.h" -#include "upcall-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/dict.h> +#include <glusterfs/logging.h> +#include <glusterfs/list.h> +#include <glusterfs/upcall-utils.h> #include "locks.h" #include "clear.h" #include "common.h" -#include "pl-messages.h" void __delete_inode_lock(pl_inode_lock_t *lock) @@ -142,15 +140,13 @@ __stale_inodelk(xlator_t *this, pl_inode_lock_t *candidate_lock, pl_inode_lock_t *requested_lock, time_t *lock_age_sec) { posix_locks_private_t *priv = NULL; - struct timeval curr; priv = this->private; - gettimeofday(&curr, NULL); /* Question: Should we just prune them all given the * chance? Or just the locks we are attempting to acquire? */ if (inodelk_conflict(candidate_lock, requested_lock)) { - *lock_age_sec = curr.tv_sec - candidate_lock->granted_time.tv_sec; + *lock_age_sec = gf_time() - candidate_lock->granted_time; if (*lock_age_sec > priv->revocation_secs) return _gf_true; } @@ -231,9 +227,9 @@ out: return revoke_lock; } -static gf_boolean_t -__inodelk_needs_contention_notify(xlator_t *this, pl_inode_lock_t *lock, - struct timespec *now) +void +inodelk_contention_notify_check(xlator_t *this, pl_inode_lock_t *lock, + struct timespec *now, struct list_head *contend) { posix_locks_private_t *priv; int64_t elapsed; @@ -243,7 +239,7 @@ __inodelk_needs_contention_notify(xlator_t *this, pl_inode_lock_t *lock, /* If this lock is in a list, it means that we are about to send a * notification for it, so no need to do anything else. */ if (!list_empty(&lock->contend)) { - return _gf_false; + return; } elapsed = now->tv_sec; @@ -252,7 +248,7 @@ __inodelk_needs_contention_notify(xlator_t *this, pl_inode_lock_t *lock, elapsed--; } if (elapsed < priv->notify_contention_delay) { - return _gf_false; + return; } /* All contention notifications will be sent outside of the locked @@ -265,7 +261,7 @@ __inodelk_needs_contention_notify(xlator_t *this, pl_inode_lock_t *lock, lock->contention_time = *now; - return _gf_true; + list_add_tail(&lock->contend, contend); } void @@ -353,9 +349,7 @@ __inodelk_grantable(xlator_t *this, pl_dom_list_t *dom, pl_inode_lock_t *lock, break; } } - if (__inodelk_needs_contention_notify(this, l, now)) { - list_add_tail(&l->contend, contend); - } + inodelk_contention_notify_check(this, l, now, contend); } } @@ -401,15 +395,11 @@ static int __lock_blocked_add(xlator_t *this, pl_dom_list_t *dom, pl_inode_lock_t *lock, int can_block) { - struct timeval now; - - gettimeofday(&now, NULL); - if (can_block == 0) { goto out; } - lock->blkd_time = now; + lock->blkd_time = gf_time(); list_add_tail(&lock->blocked_locks, &dom->blocked_inodelks); gf_msg_trace(this->name, 0, @@ -420,6 +410,8 @@ __lock_blocked_add(xlator_t *this, pl_dom_list_t *dom, pl_inode_lock_t *lock, lkowner_utoa(&lock->owner), lock->user_flock.l_start, lock->user_flock.l_len); + pl_trace_block(this, lock->frame, NULL, NULL, F_SETLKW, &lock->user_flock, + lock->volume); out: return -EAGAIN; } @@ -433,12 +425,17 @@ __lock_inodelk(xlator_t *this, pl_inode_t *pl_inode, pl_inode_lock_t *lock, struct list_head *contend) { pl_inode_lock_t *conf = NULL; - int ret = -EINVAL; + int ret; - conf = __inodelk_grantable(this, dom, lock, now, contend); - if (conf) { - ret = __lock_blocked_add(this, dom, lock, can_block); - goto out; + ret = pl_inode_remove_inodelk(pl_inode, lock); + if (ret < 0) { + return ret; + } + if (ret == 0) { + conf = __inodelk_grantable(this, dom, lock, now, contend); + } + if ((ret > 0) || (conf != NULL)) { + return __lock_blocked_add(this, dom, lock, can_block); } /* To prevent blocked locks starvation, check if there are any blocked @@ -460,17 +457,13 @@ __lock_inodelk(xlator_t *this, pl_inode_t *pl_inode, pl_inode_lock_t *lock, "starvation"); } - ret = __lock_blocked_add(this, dom, lock, can_block); - goto out; + return __lock_blocked_add(this, dom, lock, can_block); } __pl_inodelk_ref(lock); - gettimeofday(&lock->granted_time, NULL); + lock->granted_time = gf_time(); list_add(&lock->list, &dom->inodelk_list); - ret = 0; - -out: - return ret; + return 0; } /* Return true if the two inodelks have exactly same lock boundaries */ @@ -502,33 +495,36 @@ static pl_inode_lock_t * __inode_unlock_lock(xlator_t *this, pl_inode_lock_t *lock, pl_dom_list_t *dom) { pl_inode_lock_t *conf = NULL; + inode_t *inode = NULL; + + inode = lock->pl_inode->inode; conf = find_matching_inodelk(lock, dom); if (!conf) { gf_log(this->name, GF_LOG_ERROR, " Matching lock not found for unlock %llu-%llu, by %s " - "on %p", + "on %p for gfid:%s", (unsigned long long)lock->fl_start, (unsigned long long)lock->fl_end, lkowner_utoa(&lock->owner), - lock->client); + lock->client, inode ? uuid_utoa(inode->gfid) : "UNKNOWN"); goto out; } __delete_inode_lock(conf); gf_log(this->name, GF_LOG_DEBUG, - " Matching lock found for unlock %llu-%llu, by %s on %p", + " Matching lock found for unlock %llu-%llu, by %s on %p for gfid:%s", (unsigned long long)lock->fl_start, (unsigned long long)lock->fl_end, - lkowner_utoa(&lock->owner), lock->client); + lkowner_utoa(&lock->owner), lock->client, + inode ? uuid_utoa(inode->gfid) : "UNKNOWN"); out: return conf; } -static void +void __grant_blocked_inode_locks(xlator_t *this, pl_inode_t *pl_inode, struct list_head *granted, pl_dom_list_t *dom, struct timespec *now, struct list_head *contend) { - int bl_ret = 0; pl_inode_lock_t *bl = NULL; pl_inode_lock_t *tmp = NULL; @@ -541,52 +537,48 @@ __grant_blocked_inode_locks(xlator_t *this, pl_inode_t *pl_inode, { list_del_init(&bl->blocked_locks); - bl_ret = __lock_inodelk(this, pl_inode, bl, 1, dom, now, contend); + bl->status = __lock_inodelk(this, pl_inode, bl, 1, dom, now, contend); - if (bl_ret == 0) { - list_add(&bl->blocked_locks, granted); + if (bl->status != -EAGAIN) { + list_add_tail(&bl->blocked_locks, granted); } } - return; } -/* Grant all inodelks blocked on a lock */ void -grant_blocked_inode_locks(xlator_t *this, pl_inode_t *pl_inode, - pl_dom_list_t *dom, struct timespec *now, - struct list_head *contend) +unwind_granted_inodes(xlator_t *this, pl_inode_t *pl_inode, + struct list_head *granted) { - struct list_head granted; pl_inode_lock_t *lock; pl_inode_lock_t *tmp; + int32_t op_ret; + int32_t op_errno; - INIT_LIST_HEAD(&granted); - - pthread_mutex_lock(&pl_inode->mutex); + list_for_each_entry_safe(lock, tmp, granted, blocked_locks) { - __grant_blocked_inode_locks(this, pl_inode, &granted, dom, now, - contend); - } - pthread_mutex_unlock(&pl_inode->mutex); - - list_for_each_entry_safe(lock, tmp, &granted, blocked_locks) - { - gf_log(this->name, GF_LOG_TRACE, - "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => Granted", - lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, - lkowner_utoa(&lock->owner), lock->user_flock.l_start, - lock->user_flock.l_len); - + if (lock->status == 0) { + op_ret = 0; + op_errno = 0; + gf_log(this->name, GF_LOG_TRACE, + "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 + " => Granted", + lock->fl_type == F_UNLCK ? "Unlock" : "Lock", + lock->client_pid, lkowner_utoa(&lock->owner), + lock->user_flock.l_start, lock->user_flock.l_len); + } else { + op_ret = -1; + op_errno = -lock->status; + } pl_trace_out(this, lock->frame, NULL, NULL, F_SETLKW, &lock->user_flock, - 0, 0, lock->volume); + op_ret, op_errno, lock->volume); - STACK_UNWIND_STRICT(inodelk, lock->frame, 0, 0, NULL); + STACK_UNWIND_STRICT(inodelk, lock->frame, op_ret, op_errno, NULL); lock->frame = NULL; } pthread_mutex_lock(&pl_inode->mutex); { - list_for_each_entry_safe(lock, tmp, &granted, blocked_locks) + list_for_each_entry_safe(lock, tmp, granted, blocked_locks) { list_del_init(&lock->blocked_locks); __pl_inodelk_unref(lock); @@ -595,6 +587,26 @@ grant_blocked_inode_locks(xlator_t *this, pl_inode_t *pl_inode, pthread_mutex_unlock(&pl_inode->mutex); } +/* Grant all inodelks blocked on a lock */ +void +grant_blocked_inode_locks(xlator_t *this, pl_inode_t *pl_inode, + pl_dom_list_t *dom, struct timespec *now, + struct list_head *contend) +{ + struct list_head granted; + + INIT_LIST_HEAD(&granted); + + pthread_mutex_lock(&pl_inode->mutex); + { + __grant_blocked_inode_locks(this, pl_inode, &granted, dom, now, + contend); + } + pthread_mutex_unlock(&pl_inode->mutex); + + unwind_granted_inodes(this, pl_inode, &granted); +} + static void pl_inodelk_log_cleanup(pl_inode_lock_t *lock) { @@ -656,7 +668,7 @@ pl_inodelk_client_cleanup(xlator_t *this, pl_ctx_t *ctx) * and blocked lists, then this means that a parallel * unlock on another inodelk (L2 say) may have 'granted' * L1 and added it to 'granted' list in - * __grant_blocked_node_locks() (although using the + * __grant_blocked_inode_locks() (although using the * 'blocked_locks' member). In that case, the cleanup * codepath must try and grant other overlapping * blocked inodelks from other clients, now that L1 is @@ -691,31 +703,35 @@ pl_inodelk_client_cleanup(xlator_t *this, pl_ctx_t *ctx) } pthread_mutex_unlock(&ctx->lock); - list_for_each_entry_safe(l, tmp, &unwind, client_list) - { - list_del_init(&l->client_list); + if (!list_empty(&unwind)) { + list_for_each_entry_safe(l, tmp, &unwind, client_list) + { + list_del_init(&l->client_list); - if (l->frame) - STACK_UNWIND_STRICT(inodelk, l->frame, -1, EAGAIN, NULL); - list_add_tail(&l->client_list, &released); + if (l->frame) + STACK_UNWIND_STRICT(inodelk, l->frame, -1, EAGAIN, NULL); + list_add_tail(&l->client_list, &released); + } } - list_for_each_entry_safe(l, tmp, &released, client_list) - { - list_del_init(&l->client_list); + if (!list_empty(&released)) { + list_for_each_entry_safe(l, tmp, &released, client_list) + { + list_del_init(&l->client_list); - pl_inode = l->pl_inode; + pl_inode = l->pl_inode; - dom = get_domain(pl_inode, l->volume); + dom = get_domain(pl_inode, l->volume); - grant_blocked_inode_locks(this, pl_inode, dom, &now, pcontend); + grant_blocked_inode_locks(this, pl_inode, dom, &now, pcontend); - pthread_mutex_lock(&pl_inode->mutex); - { - __pl_inodelk_unref(l); + pthread_mutex_lock(&pl_inode->mutex); + { + __pl_inodelk_unref(l); + } + pthread_mutex_unlock(&pl_inode->mutex); + inode_unref(pl_inode->inode); } - pthread_mutex_unlock(&pl_inode->mutex); - inode_unref(pl_inode->inode); } if (pcontend != NULL) { @@ -737,6 +753,7 @@ pl_inode_setlk(xlator_t *this, pl_ctx_t *ctx, pl_inode_t *pl_inode, gf_boolean_t need_inode_unref = _gf_false; struct list_head *pcontend = NULL; struct list_head contend; + struct list_head wake; struct timespec now = {}; short fl_type; @@ -788,6 +805,8 @@ pl_inode_setlk(xlator_t *this, pl_ctx_t *ctx, pl_inode_t *pl_inode, timespec_now(&now); } + INIT_LIST_HEAD(&wake); + if (ctx) pthread_mutex_lock(&ctx->lock); pthread_mutex_lock(&pl_inode->mutex); @@ -810,18 +829,17 @@ pl_inode_setlk(xlator_t *this, pl_ctx_t *ctx, pl_inode_t *pl_inode, lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, lkowner_utoa(&lock->owner), lock->user_flock.l_start, lock->user_flock.l_len); - if (can_block) + if (can_block) { unref = _gf_false; - /* For all but the case where a non-blocking - * lock attempt fails, the extra ref taken at - * the start of this function must be negated. - */ - else - need_inode_unref = _gf_true; + } } - - if (ctx && (!ret || can_block)) + /* For all but the case where a non-blocking lock attempt fails + * with -EAGAIN, the extra ref taken at the start of this function + * must be negated. */ + need_inode_unref = (ret != 0) && ((ret != -EAGAIN) || !can_block); + if (ctx && !need_inode_unref) { list_add_tail(&lock->client_list, &ctx->inodelk_lockers); + } } else { /* Irrespective of whether unlock succeeds or not, * the extra inode ref that was done at the start of @@ -839,6 +857,8 @@ pl_inode_setlk(xlator_t *this, pl_ctx_t *ctx, pl_inode_t *pl_inode, list_del_init(&retlock->client_list); __pl_inodelk_unref(retlock); + pl_inode_remove_unlocked(this, pl_inode, &wake); + ret = 0; } out: @@ -849,6 +869,8 @@ pl_inode_setlk(xlator_t *this, pl_ctx_t *ctx, pl_inode_t *pl_inode, if (ctx) pthread_mutex_unlock(&ctx->lock); + pl_inode_remove_wake(&wake); + /* The following (extra) unref corresponds to the ref that * was done at the time the lock was granted. */ @@ -869,17 +891,23 @@ pl_inode_setlk(xlator_t *this, pl_ctx_t *ctx, pl_inode_t *pl_inode, } /* Create a new inode_lock_t */ -pl_inode_lock_t * +static pl_inode_lock_t * new_inode_lock(struct gf_flock *flock, client_t *client, pid_t client_pid, call_frame_t *frame, xlator_t *this, const char *volume, - char *conn_id) + char *conn_id, int32_t *op_errno) { pl_inode_lock_t *lock = NULL; + if (!pl_is_lk_owner_valid(&frame->root->lk_owner, frame->root->client)) { + *op_errno = EINVAL; + goto out; + } + lock = GF_CALLOC(1, sizeof(*lock), gf_locks_mt_pl_inode_lock_t); if (!lock) { - return NULL; + *op_errno = ENOMEM; + goto out; } lock->fl_start = flock->l_start; @@ -907,6 +935,7 @@ new_inode_lock(struct gf_flock *flock, client_t *client, pid_t client_pid, INIT_LIST_HEAD(&lock->contend); __pl_inodelk_ref(lock); +out: return lock; } @@ -951,6 +980,7 @@ pl_common_inodelk(call_frame_t *frame, xlator_t *this, const char *volume, int ret = -1; GF_UNUSED int dict_ret = -1; int can_block = 0; + short lock_type = 0; pl_inode_t *pinode = NULL; pl_inode_lock_t *reqlock = NULL; pl_dom_list_t *dom = NULL; @@ -988,7 +1018,7 @@ pl_common_inodelk(call_frame_t *frame, xlator_t *this, const char *volume, } } - pinode = pl_inode_get(this, inode); + pinode = pl_inode_get(this, inode, NULL); if (!pinode) { op_errno = ENOMEM; goto unwind; @@ -1001,11 +1031,10 @@ pl_common_inodelk(call_frame_t *frame, xlator_t *this, const char *volume, } reqlock = new_inode_lock(flock, frame->root->client, frame->root->pid, - frame, this, dom->domain, conn_id); + frame, this, dom->domain, conn_id, &op_errno); if (!reqlock) { op_ret = -1; - op_errno = ENOMEM; goto unwind; } @@ -1016,16 +1045,20 @@ pl_common_inodelk(call_frame_t *frame, xlator_t *this, const char *volume, /* fall through */ case F_SETLK: + lock_type = flock->l_type; memcpy(&reqlock->user_flock, flock, sizeof(struct gf_flock)); ret = pl_inode_setlk(this, ctx, pinode, reqlock, can_block, dom, inode); if (ret < 0) { - if ((can_block) && (F_UNLCK != flock->l_type)) { - pl_trace_block(this, frame, fd, loc, cmd, flock, volume); - goto out; + if (ret == -EAGAIN) { + if (can_block && (F_UNLCK != lock_type)) { + goto out; + } + gf_log(this->name, GF_LOG_TRACE, "returning EAGAIN"); + } else { + gf_log(this->name, GF_LOG_TRACE, "returning %d", ret); } - gf_log(this->name, GF_LOG_TRACE, "returning EAGAIN"); op_errno = -ret; goto unwind; } diff --git a/xlators/features/locks/src/locks-mem-types.h b/xlators/features/locks/src/locks-mem-types.h index 240c1957a42..a76605027b3 100644 --- a/xlators/features/locks/src/locks-mem-types.h +++ b/xlators/features/locks/src/locks-mem-types.h @@ -11,7 +11,7 @@ #ifndef __LOCKS_MEM_TYPES_H__ #define __LOCKS_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_locks_mem_types_ { gf_locks_mt_pl_dom_list_t = gf_common_mt_end + 1, @@ -19,7 +19,6 @@ enum gf_locks_mem_types_ { gf_locks_mt_posix_lock_t, gf_locks_mt_pl_entry_lock_t, gf_locks_mt_pl_inode_lock_t, - gf_locks_mt_truncate_ops, gf_locks_mt_pl_rw_req_t, gf_locks_mt_posix_locks_private_t, gf_locks_mt_pl_fdctx_t, diff --git a/xlators/features/locks/src/locks.h b/xlators/features/locks/src/locks.h index cf2849fc251..c868eb494a2 100644 --- a/xlators/features/locks/src/locks.h +++ b/xlators/features/locks/src/locks.h @@ -10,13 +10,13 @@ #ifndef __POSIX_LOCKS_H__ #define __POSIX_LOCKS_H__ -#include "compat-errno.h" -#include "stack.h" -#include "call-stub.h" +#include <glusterfs/compat-errno.h> +#include <glusterfs/stack.h> +#include <glusterfs/call-stub.h> #include "locks-mem-types.h" -#include "client_t.h" +#include <glusterfs/client_t.h> -#include "lkowner.h" +#include <glusterfs/lkowner.h> typedef enum { MLK_NONE, @@ -30,11 +30,11 @@ struct __pl_fd; struct __posix_lock { struct list_head list; - short fl_type; off_t fl_start; off_t fl_end; uint32_t lk_flags; + short fl_type; short blocked; /* waiting to acquire */ struct gf_flock user_flock; /* the flock supplied by the user */ xlator_t *this; /* required for blocked locks */ @@ -43,9 +43,8 @@ struct __posix_lock { fd_t *fd; call_frame_t *frame; - struct timeval blkd_time; /*time at which lock was queued into blkd list*/ - struct timeval - granted_time; /*time at which lock was queued into active list*/ + time_t blkd_time; /* time at which lock was queued into blkd list */ + time_t granted_time; /* time at which lock was queued into active list */ /* These two together serve to uniquely identify each process across nodes */ @@ -74,7 +73,6 @@ struct __pl_inode_lock { struct list_head contend; /* list of contending locks */ int ref; - short fl_type; off_t fl_start; off_t fl_end; @@ -86,9 +84,9 @@ struct __pl_inode_lock { call_frame_t *frame; - struct timeval blkd_time; /*time at which lock was queued into blkd list*/ - struct timeval - granted_time; /*time at which lock was queued into active list*/ + time_t blkd_time; /* time at which lock was queued into blkd list */ + time_t granted_time; /* time at which lock was queued into active list */ + /*last time at which lock contention was detected and notified*/ struct timespec contention_time; @@ -102,6 +100,10 @@ struct __pl_inode_lock { char *connection_id; /* stores the client connection id */ struct list_head client_list; /* list of all locks from a client */ + short fl_type; + + int32_t status; /* Error code when we try to grant a lock in blocked + state */ }; typedef struct __pl_inode_lock pl_inode_lock_t; @@ -135,11 +137,10 @@ struct __entry_lock { const char *volume; const char *basename; - entrylk_type type; - struct timeval blkd_time; /*time at which lock was queued into blkd list*/ - struct timeval - granted_time; /*time at which lock was queued into active list*/ + time_t blkd_time; /* time at which lock was queued into blkd list */ + time_t granted_time; /* time at which lock was queued into active list */ + /*last time at which lock contention was detected and notified*/ struct timespec contention_time; @@ -150,6 +151,7 @@ struct __entry_lock { char *connection_id; /* stores the client connection id */ struct list_head client_list; /* list of all locks from a client */ + entrylk_type type; }; typedef struct __entry_lock pl_entry_lock_t; @@ -164,13 +166,14 @@ struct __pl_inode { struct list_head rw_list; /* list of waiting r/w requests */ struct list_head reservelk_list; /* list of reservelks */ struct list_head blocked_reservelks; /* list of blocked reservelks */ - struct list_head - blocked_calls; /* List of blocked lock calls while a reserve is held*/ - struct list_head metalk_list; /* Meta lock list */ - /* This is to store the incoming lock - requests while meta lock is enabled */ - struct list_head queued_locks; - int mandatory; /* if mandatory locking is enabled */ + struct list_head blocked_calls; /* List of blocked lock calls while a + reserve is held*/ + struct list_head metalk_list; /* Meta lock list */ + struct list_head queued_locks; /* This is to store the incoming lock + requests while meta lock is enabled */ + struct list_head waiting; /* List of pending fops waiting to unlink/rmdir + the inode. */ + int mandatory; /* if mandatory locking is enabled */ inode_t *refkeeper; /* hold refs on an inode while locks are held to prevent pruning */ @@ -179,6 +182,31 @@ struct __pl_inode { of inode_t as long as there are locks on it */ gf_boolean_t migrated; + + /* Flag to indicate whether to read mlock-enforce xattr from disk */ + gf_boolean_t check_mlock_info; + + /* Mandatory_lock enforce: IO will be allowed if and only if the lkowner has + held the lock. + + Note: An xattr is set on the file to recover this information post + reboot. If client does not want mandatory lock to be enforced, then it + should remove this xattr explicitly + */ + gf_boolean_t mlock_enforced; + /* There are scenarios where mandatory lock is granted but there are IOs + pending at posix level. To avoid this before preempting the previous lock + owner, we wait for all the fops to be unwound. + */ + int fop_wind_count; + pthread_cond_t check_fop_wind_count; + + gf_boolean_t track_fop_wind_count; + + int32_t links; /* Number of hard links the inode has. */ + uint32_t remove_running; /* Number of remove operations running. */ + gf_boolean_t is_locked; /* Regular locks will be blocked. */ + gf_boolean_t removed; /* The inode has been deleted. */ }; typedef struct __pl_inode pl_inode_t; @@ -196,29 +224,33 @@ struct __pl_metalk { typedef struct __pl_metalk pl_meta_lock_t; typedef struct { + char *brickname; + uint32_t revocation_secs; + uint32_t revocation_max_blocked; + uint32_t notify_contention_delay; mlk_mode_t mandatory_mode; /* holds current mandatory locking mode */ gf_boolean_t trace; /* trace lock requests in and out */ - char *brickname; gf_boolean_t monkey_unlocking; - uint32_t revocation_secs; gf_boolean_t revocation_clear_all; - uint32_t revocation_max_blocked; gf_boolean_t notify_contention; - uint32_t notify_contention_delay; + gf_boolean_t mlock_enforced; } posix_locks_private_t; typedef struct { - gf_boolean_t entrylk_count_req; - gf_boolean_t inodelk_count_req; - gf_boolean_t posixlk_count_req; - gf_boolean_t parent_entrylk_req; data_t *inodelk_dom_count_req; dict_t *xdata; loc_t loc[2]; fd_t *fd; + inode_t *inode; off_t offset; glusterfs_fop_t op; + gf_boolean_t entrylk_count_req; + gf_boolean_t inodelk_count_req; + gf_boolean_t posixlk_count_req; + gf_boolean_t parent_entrylk_req; + gf_boolean_t multiple_dom_lk_requests; + int update_mlock_enforced_flag; } pl_local_t; typedef struct { @@ -239,6 +271,15 @@ typedef struct _locks_ctx { struct list_head metalk_list; } pl_ctx_t; +typedef struct _multi_dom_lk_data { + xlator_t *this; + inode_t *inode; + dict_t *xdata_rsp; + gf_boolean_t keep_max; +} multi_dom_lk_data; + +typedef enum { DECREMENT, INCREMENT } pl_count_op_t; + pl_ctx_t * pl_ctx_get(client_t *client, xlator_t *xlator); diff --git a/xlators/features/locks/src/pl-messages.h b/xlators/features/locks/src/pl-messages.h index a99e1bbce43..e2d3d7ca974 100644 --- a/xlators/features/locks/src/pl-messages.h +++ b/xlators/features/locks/src/pl-messages.h @@ -11,7 +11,7 @@ #ifndef _PL_MESSAGES_H_ #define _PL_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c index 917eacee8da..cf0ae4c57dd 100644 --- a/xlators/features/locks/src/posix.c +++ b/xlators/features/locks/src/posix.c @@ -12,19 +12,15 @@ #include <limits.h> #include <pthread.h> -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/compat.h> +#include <glusterfs/logging.h> #include "locks.h" #include "common.h" -#include "statedump.h" +#include <glusterfs/statedump.h> #include "clear.h" -#include "defaults.h" -#include "syncop.h" -#include "pl-messages.h" +#include <glusterfs/defaults.h> +#include <glusterfs/syncop.h> #ifndef LLONG_MAX #define LLONG_MAX LONG_LONG_MAX /* compat with old gcc */ @@ -43,21 +39,6 @@ pl_lockinfo_get_brickname(xlator_t *, inode_t *, int32_t *); static int fetch_pathinfo(xlator_t *, inode_t *, int32_t *, char **); -#define PL_STACK_UNWIND_AND_FREE(__local, fop, frame, op_ret, params...) \ - do { \ - frame->local = NULL; \ - STACK_UNWIND_STRICT(fop, frame, op_ret, params); \ - if (__local) { \ - if (__local->inodelk_dom_count_req) \ - data_unref(__local->inodelk_dom_count_req); \ - loc_wipe(&__local->loc[0]); \ - loc_wipe(&__local->loc[1]); \ - if (__local->fd) \ - fd_unref(__local->fd); \ - mem_put(__local); \ - } \ - } while (0) - /* * The client is always requesting data, but older * servers were not returning it. Newer ones are, so @@ -115,69 +96,156 @@ fetch_pathinfo(xlator_t *, inode_t *, int32_t *, char **); #define PL_LOCAL_GET_REQUESTS(frame, this, xdata, __fd, __loc, __newloc) \ do { \ if (pl_has_xdata_requests(xdata)) { \ - frame->local = mem_get0(this->local_pool); \ + if (!frame->local) \ + frame->local = mem_get0(this->local_pool); \ pl_local_t *__local = frame->local; \ if (__local) { \ if (__fd) { \ __local->fd = fd_ref(__fd); \ + __local->inode = inode_ref(__fd->inode); \ } else { \ if (__loc) \ loc_copy(&__local->loc[0], __loc); \ if (__newloc) \ loc_copy(&__local->loc[1], __newloc); \ + __local->inode = inode_ref(__local->loc[0].inode); \ } \ pl_get_xdata_requests(__local, xdata); \ } \ } \ } while (0) +#define PL_CHECK_LOCK_ENFORCE_KEY(frame, dict, name, this, loc, fd, priv) \ + do { \ + if ((dict && (dict_get(dict, GF_ENFORCE_MANDATORY_LOCK))) || \ + (name && (strcmp(name, GF_ENFORCE_MANDATORY_LOCK) == 0))) { \ + inode_t *__inode = (loc ? loc->inode : fd->inode); \ + pl_inode_t *__pl_inode = pl_inode_get(this, __inode, NULL); \ + if (__pl_inode == NULL) { \ + op_ret = -1; \ + op_errno = ENOMEM; \ + goto unwind; \ + } \ + if (!pl_is_mandatory_locking_enabled(__pl_inode) || \ + !priv->mlock_enforced) { \ + op_ret = -1; \ + gf_msg(this->name, GF_LOG_DEBUG, EINVAL, 0, \ + "option %s would need mandatory lock to be enabled " \ + "and feature.enforce-mandatory-lock option to be set " \ + "to on", \ + GF_ENFORCE_MANDATORY_LOCK); \ + op_errno = EINVAL; \ + goto unwind; \ + } \ + \ + op_ret = pl_local_init(frame, this, loc, fd); \ + if (op_ret) { \ + op_errno = ENOMEM; \ + goto unwind; \ + } \ + \ + ((pl_local_t *)(frame->local))->update_mlock_enforced_flag = 1; \ + } \ + } while (0) + +#define PL_INODE_REMOVE(_fop, _frame, _xl, _loc1, _loc2, _cont, _cbk, \ + _args...) \ + ({ \ + struct list_head contend; \ + pl_inode_t *__pl_inode; \ + call_stub_t *__stub; \ + int32_t __error; \ + INIT_LIST_HEAD(&contend); \ + __error = pl_inode_remove_prepare(_xl, _frame, _loc2 ? _loc2 : _loc1, \ + &__pl_inode, &contend); \ + if (__error < 0) { \ + __stub = fop_##_fop##_stub(_frame, _cont, ##_args); \ + __error = pl_inode_remove_complete(_xl, __pl_inode, __stub, \ + &contend); \ + } else if (__error == 0) { \ + PL_LOCAL_GET_REQUESTS(_frame, _xl, xdata, ((fd_t *)NULL), _loc1, \ + _loc2); \ + STACK_WIND_COOKIE(_frame, _cbk, __pl_inode, FIRST_CHILD(_xl), \ + FIRST_CHILD(_xl)->fops->_fop, ##_args); \ + } \ + __error; \ + }) + gf_boolean_t pl_has_xdata_requests(dict_t *xdata) { - char *reqs[] = {GLUSTERFS_ENTRYLK_COUNT, GLUSTERFS_INODELK_COUNT, - GLUSTERFS_INODELK_DOM_COUNT, GLUSTERFS_POSIXLK_COUNT, - GLUSTERFS_PARENT_ENTRYLK, NULL}; + static char *reqs[] = {GLUSTERFS_ENTRYLK_COUNT, + GLUSTERFS_INODELK_COUNT, + GLUSTERFS_INODELK_DOM_COUNT, + GLUSTERFS_POSIXLK_COUNT, + GLUSTERFS_PARENT_ENTRYLK, + GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS, + NULL}; + static int reqs_size[] = {SLEN(GLUSTERFS_ENTRYLK_COUNT), + SLEN(GLUSTERFS_INODELK_COUNT), + SLEN(GLUSTERFS_INODELK_DOM_COUNT), + SLEN(GLUSTERFS_POSIXLK_COUNT), + SLEN(GLUSTERFS_PARENT_ENTRYLK), + SLEN(GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS), + 0}; int i = 0; if (!xdata) return _gf_false; for (i = 0; reqs[i]; i++) - if (dict_get(xdata, reqs[i])) + if (dict_getn(xdata, reqs[i], reqs_size[i])) return _gf_true; return _gf_false; } +static int +dict_delete_domain_key(dict_t *dict, char *key, data_t *value, void *data) +{ + dict_del(dict, key); + return 0; +} + void pl_get_xdata_requests(pl_local_t *local, dict_t *xdata) { if (!local || !xdata) return; - if (dict_get(xdata, GLUSTERFS_ENTRYLK_COUNT)) { + GF_ASSERT(local->xdata == NULL); + local->xdata = dict_copy_with_ref(xdata, NULL); + + if (dict_get_sizen(xdata, GLUSTERFS_ENTRYLK_COUNT)) { local->entrylk_count_req = 1; - dict_del(xdata, GLUSTERFS_ENTRYLK_COUNT); + dict_del_sizen(xdata, GLUSTERFS_ENTRYLK_COUNT); } - if (dict_get(xdata, GLUSTERFS_INODELK_COUNT)) { + if (dict_get_sizen(xdata, GLUSTERFS_INODELK_COUNT)) { local->inodelk_count_req = 1; - dict_del(xdata, GLUSTERFS_INODELK_COUNT); + dict_del_sizen(xdata, GLUSTERFS_INODELK_COUNT); + } + if (dict_get_sizen(xdata, GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS)) { + local->multiple_dom_lk_requests = 1; + dict_del_sizen(xdata, GLUSTERFS_MULTIPLE_DOM_LK_CNT_REQUESTS); + dict_foreach_fnmatch(xdata, GLUSTERFS_INODELK_DOM_PREFIX "*", + dict_delete_domain_key, NULL); } - local->inodelk_dom_count_req = dict_get(xdata, GLUSTERFS_INODELK_DOM_COUNT); + local->inodelk_dom_count_req = dict_get_sizen(xdata, + GLUSTERFS_INODELK_DOM_COUNT); if (local->inodelk_dom_count_req) { data_ref(local->inodelk_dom_count_req); - dict_del(xdata, GLUSTERFS_INODELK_DOM_COUNT); + dict_del_sizen(xdata, GLUSTERFS_INODELK_DOM_COUNT); } - if (dict_get(xdata, GLUSTERFS_POSIXLK_COUNT)) { + if (dict_get_sizen(xdata, GLUSTERFS_POSIXLK_COUNT)) { local->posixlk_count_req = 1; - dict_del(xdata, GLUSTERFS_POSIXLK_COUNT); + dict_del_sizen(xdata, GLUSTERFS_POSIXLK_COUNT); } - if (dict_get(xdata, GLUSTERFS_PARENT_ENTRYLK)) { + if (dict_get_sizen(xdata, GLUSTERFS_PARENT_ENTRYLK)) { local->parent_entrylk_req = 1; - dict_del(xdata, GLUSTERFS_PARENT_ENTRYLK); + dict_del_sizen(xdata, GLUSTERFS_PARENT_ENTRYLK); } } @@ -187,20 +255,11 @@ pl_needs_xdata_response(pl_local_t *local) if (!local) return _gf_false; - if (local->parent_entrylk_req) - return _gf_true; - - if (local->entrylk_count_req) - return _gf_true; - - if (local->inodelk_dom_count_req) - return _gf_true; - - if (local->inodelk_count_req) + if (local->parent_entrylk_req || local->entrylk_count_req || + local->inodelk_dom_count_req || local->inodelk_count_req || + local->posixlk_count_req || local->multiple_dom_lk_requests) return _gf_true; - if (local->posixlk_count_req) - return _gf_true; return _gf_false; } @@ -221,8 +280,43 @@ pl_get_xdata_rsp_args(pl_local_t *local, char *fop, inode_t **parent, } } -int32_t -__get_posixlk_count(xlator_t *this, pl_inode_t *pl_inode) +static inline int +pl_track_io_fop_count(pl_local_t *local, xlator_t *this, pl_count_op_t op) +{ + pl_inode_t *pl_inode = NULL; + + if (!local) + return -1; + + pl_inode = pl_inode_get(this, local->inode, NULL); + if (!pl_inode) + return -1; + + if (pl_inode->mlock_enforced && pl_inode->track_fop_wind_count) { + pthread_mutex_lock(&pl_inode->mutex); + { + if (op == DECREMENT) { + pl_inode->fop_wind_count--; + /* fop_wind_count can go negative when lock enforcement is + * enabled on unwind path of an IO. Hence the "<" comparision. + */ + if (pl_inode->fop_wind_count <= 0) { + pthread_cond_broadcast(&pl_inode->check_fop_wind_count); + pl_inode->track_fop_wind_count = _gf_false; + pl_inode->fop_wind_count = 0; + } + } else { + pl_inode->fop_wind_count++; + } + } + pthread_mutex_unlock(&pl_inode->mutex); + } + + return 0; +} + +static int32_t +__get_posixlk_count(pl_inode_t *pl_inode) { posix_lock_t *lock = NULL; int32_t count = 0; @@ -237,10 +331,9 @@ get_posixlk_count(xlator_t *this, inode_t *inode) { pl_inode_t *pl_inode = NULL; uint64_t tmp_pl_inode = 0; - int ret = 0; int32_t count = 0; - ret = inode_ctx_get(inode, this, &tmp_pl_inode); + int ret = inode_ctx_get(inode, this, &tmp_pl_inode); if (ret != 0) { goto out; } @@ -249,7 +342,7 @@ get_posixlk_count(xlator_t *this, inode_t *inode) pthread_mutex_lock(&pl_inode->mutex); { - count = __get_posixlk_count(this, pl_inode); + count = __get_posixlk_count(pl_inode); } pthread_mutex_unlock(&pl_inode->mutex); @@ -265,10 +358,10 @@ pl_parent_entrylk_xattr_fill(xlator_t *this, inode_t *parent, char *basename, int32_t maxcount = -1; int ret = -1; - if (!parent || !basename || !strlen(basename)) + if (!parent || !basename) goto out; if (keep_max) { - ret = dict_get_int32(dict, GLUSTERFS_PARENT_ENTRYLK, &maxcount); + ret = dict_get_int32_sizen(dict, GLUSTERFS_PARENT_ENTRYLK, &maxcount); if (ret < 0) gf_msg_debug(this->name, 0, " Failed to fetch the value for key %s", GLUSTERFS_PARENT_ENTRYLK); @@ -277,7 +370,7 @@ pl_parent_entrylk_xattr_fill(xlator_t *this, inode_t *parent, char *basename, if (maxcount >= entrylk) return; out: - ret = dict_set_int32(dict, GLUSTERFS_PARENT_ENTRYLK, entrylk); + ret = dict_set_int32_sizen(dict, GLUSTERFS_PARENT_ENTRYLK, entrylk); if (ret < 0) { gf_msg_debug(this->name, 0, " dict_set failed on key %s", GLUSTERFS_PARENT_ENTRYLK); @@ -293,7 +386,7 @@ pl_entrylk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, int ret = -1; if (keep_max) { - ret = dict_get_int32(dict, GLUSTERFS_ENTRYLK_COUNT, &maxcount); + ret = dict_get_int32_sizen(dict, GLUSTERFS_ENTRYLK_COUNT, &maxcount); if (ret < 0) gf_msg_debug(this->name, 0, " Failed to fetch the value for key %s", GLUSTERFS_ENTRYLK_COUNT); @@ -302,7 +395,7 @@ pl_entrylk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, if (maxcount >= count) return; - ret = dict_set_int32(dict, GLUSTERFS_ENTRYLK_COUNT, count); + ret = dict_set_int32_sizen(dict, GLUSTERFS_ENTRYLK_COUNT, count); if (ret < 0) { gf_msg_debug(this->name, 0, " dict_set failed on key %s", GLUSTERFS_ENTRYLK_COUNT); @@ -318,7 +411,7 @@ pl_inodelk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, int ret = -1; if (keep_max) { - ret = dict_get_int32(dict, GLUSTERFS_INODELK_COUNT, &maxcount); + ret = dict_get_int32_sizen(dict, GLUSTERFS_INODELK_COUNT, &maxcount); if (ret < 0) gf_msg_debug(this->name, 0, " Failed to fetch the value for key %s", GLUSTERFS_INODELK_COUNT); @@ -327,7 +420,7 @@ pl_inodelk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, if (maxcount >= count) return; - ret = dict_set_int32(dict, GLUSTERFS_INODELK_COUNT, count); + ret = dict_set_int32_sizen(dict, GLUSTERFS_INODELK_COUNT, count); if (ret < 0) { gf_msg_debug(this->name, 0, "Failed to set count for " @@ -347,7 +440,7 @@ pl_posixlk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, int ret = -1; if (keep_max) { - ret = dict_get_int32(dict, GLUSTERFS_POSIXLK_COUNT, &maxcount); + ret = dict_get_int32_sizen(dict, GLUSTERFS_POSIXLK_COUNT, &maxcount); if (ret < 0) gf_msg_debug(this->name, 0, " Failed to fetch the value for key %s", GLUSTERFS_POSIXLK_COUNT); @@ -356,7 +449,7 @@ pl_posixlk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, if (maxcount >= count) return; - ret = dict_set_int32(dict, GLUSTERFS_POSIXLK_COUNT, count); + ret = dict_set_int32_sizen(dict, GLUSTERFS_POSIXLK_COUNT, count); if (ret < 0) { gf_msg_debug(this->name, 0, " dict_set failed on key %s", GLUSTERFS_POSIXLK_COUNT); @@ -364,6 +457,80 @@ pl_posixlk_xattr_fill(xlator_t *this, inode_t *inode, dict_t *dict, } void +pl_inodelk_xattr_fill_each(xlator_t *this, inode_t *inode, dict_t *dict, + char *domname, gf_boolean_t keep_max, char *key) +{ + int32_t count = 0; + int32_t maxcount = -1; + int ret = -1; + + if (keep_max) { + ret = dict_get_int32(dict, key, &maxcount); + if (ret < 0) + gf_msg_debug(this->name, 0, " Failed to fetch the value for key %s", + GLUSTERFS_INODELK_COUNT); + } + count = get_inodelk_count(this, inode, domname); + if (maxcount >= count) + return; + + ret = dict_set_int32(dict, key, count); + if (ret < 0) { + gf_msg_debug(this->name, 0, + "Failed to set count for " + "key %s", + key); + } + + return; +} + +static int +pl_inodelk_xattr_fill_multiple(dict_t *this, char *key, data_t *value, + void *data) +{ + multi_dom_lk_data *d = data; + char *tmp_key = NULL; + char *save_ptr = NULL; + + tmp_key = gf_strdup(key); + if (!tmp_key) + return -1; + + strtok_r(tmp_key, ":", &save_ptr); + if (!*save_ptr) { + if (tmp_key) + GF_FREE(tmp_key); + gf_msg(THIS->name, GF_LOG_ERROR, 0, EINVAL, + "Could not tokenize domain string from key %s", key); + return -1; + } + + pl_inodelk_xattr_fill_each(d->this, d->inode, d->xdata_rsp, save_ptr, + d->keep_max, key); + if (tmp_key) + GF_FREE(tmp_key); + + return 0; +} + +void +pl_fill_multiple_dom_lk_requests(xlator_t *this, pl_local_t *local, + inode_t *inode, dict_t *dict, + gf_boolean_t keep_max) +{ + multi_dom_lk_data data; + + data.this = this; + data.inode = inode; + data.xdata_rsp = dict; + data.keep_max = keep_max; + + dict_foreach_fnmatch(local->xdata, GLUSTERFS_INODELK_DOM_PREFIX "*", + pl_inodelk_xattr_fill_multiple, &data); +} + +void pl_set_xdata_response(xlator_t *this, pl_local_t *local, inode_t *parent, inode_t *inode, char *name, dict_t *xdata, gf_boolean_t max_lock) @@ -371,41 +538,28 @@ pl_set_xdata_response(xlator_t *this, pl_local_t *local, inode_t *parent, if (!xdata || !local) return; - if (local->parent_entrylk_req && parent && name && strlen(name)) + if (local->parent_entrylk_req && parent && name && name[0] != '\0') pl_parent_entrylk_xattr_fill(this, parent, name, xdata, max_lock); - if (local->entrylk_count_req && inode) + if (!inode) + return; + + if (local->entrylk_count_req) pl_entrylk_xattr_fill(this, inode, xdata, max_lock); - if (local->inodelk_dom_count_req && inode) + if (local->inodelk_dom_count_req) pl_inodelk_xattr_fill(this, inode, xdata, data_to_str(local->inodelk_dom_count_req), max_lock); - if (local->inodelk_count_req && inode) + if (local->inodelk_count_req) pl_inodelk_xattr_fill(this, inode, xdata, NULL, max_lock); - if (local->posixlk_count_req && inode) + if (local->posixlk_count_req) pl_posixlk_xattr_fill(this, inode, xdata, max_lock); -} - -/* Return true in case we need to ensure mandatory-locking - * semnatics under different modes. - */ -gf_boolean_t -pl_is_mandatory_locking_enabled(pl_inode_t *pl_inode) -{ - posix_locks_private_t *priv = NULL; - - priv = THIS->private; - if (priv->mandatory_mode == MLK_FILE_BASED && pl_inode->mandatory) - return _gf_true; - else if (priv->mandatory_mode == MLK_FORCED || - priv->mandatory_mode == MLK_OPTIMAL) - return _gf_true; - - return _gf_false; + if (local->multiple_dom_lk_requests) + pl_fill_multiple_dom_lk_requests(this, local, inode, xdata, max_lock); } /* Checks whether the region where fop is acting upon conflicts @@ -420,15 +574,19 @@ pl_is_fop_allowed(pl_inode_t *pl_inode, posix_lock_t *region, fd_t *fd, int ret = 0; if (!__rw_allowable(pl_inode, region, op)) { - if ((!fd) || (fd && (fd->flags & O_NONBLOCK))) { + if (pl_inode->mlock_enforced) { + *can_block = _gf_false; + } else if ((!fd) || (fd && (fd->flags & O_NONBLOCK))) { gf_log("locks", GF_LOG_TRACE, "returning EAGAIN" " because fd is O_NONBLOCK"); *can_block = _gf_false; - } else + } else { *can_block = _gf_true; - } else + } + } else { ret = 1; + } return ret; } @@ -436,9 +594,7 @@ pl_is_fop_allowed(pl_inode_t *pl_inode, posix_lock_t *region, fd_t *fd, static pl_fdctx_t * pl_new_fdctx() { - pl_fdctx_t *fdctx = NULL; - - fdctx = GF_CALLOC(1, sizeof(*fdctx), gf_locks_mt_pl_fdctx_t); + pl_fdctx_t *fdctx = GF_MALLOC(sizeof(*fdctx), gf_locks_mt_pl_fdctx_t); GF_VALIDATE_OR_GOTO("posix-locks", fdctx, out); INIT_LIST_HEAD(&fdctx->locks_list); @@ -471,7 +627,9 @@ pl_check_n_create_fdctx(xlator_t *this, fd_t *fd) if (ret != 0) { GF_FREE(fdctx); fdctx = NULL; + UNLOCK(&fd->lock); gf_log(this->name, GF_LOG_DEBUG, "failed to set fd ctx"); + goto out; } } unlock: @@ -486,8 +644,10 @@ pl_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { - STACK_UNWIND_STRICT(discard, frame, op_ret, op_errno, prebuf, postbuf, - xdata); + pl_track_io_fop_count(frame->local, this, DECREMENT); + + PL_STACK_UNWIND(discard, xdata, frame, op_ret, op_errno, prebuf, postbuf, + xdata); return 0; } @@ -495,6 +655,8 @@ int pl_discard_cont(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, size_t len, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, INCREMENT); + STACK_WIND(frame, pl_discard_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->discard, fd, offset, len, xdata); return 0; @@ -504,6 +666,7 @@ int32_t pl_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, size_t len, dict_t *xdata) { + pl_local_t *local = NULL; pl_inode_t *pl_inode = NULL; pl_rw_req_t *rw = NULL; posix_lock_t region = { @@ -520,17 +683,28 @@ pl_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, GF_VALIDATE_OR_GOTO("locks", this, unwind); - pl_inode = pl_inode_get(this, fd->inode); - if (!pl_inode) { + local = mem_get0(this->local_pool); + if (!local) { op_ret = -1; op_errno = ENOMEM; goto unwind; } - enabled = pl_is_mandatory_locking_enabled(pl_inode); + frame->local = local; + local->inode = inode_ref(fd->inode); + local->fd = fd_ref(fd); + + pl_inode = pl_inode_get(this, fd->inode, local); + if (!pl_inode) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } if (frame->root->pid < 0) enabled = _gf_false; + else + enabled = pl_is_mandatory_locking_enabled(pl_inode); if (enabled) { region.fl_start = offset; @@ -544,15 +718,19 @@ pl_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, { allowed = pl_is_fop_allowed(pl_inode, ®ion, fd, GF_FOP_DISCARD, &can_block); - if (allowed == 1) + if (allowed == 1) { + if (pl_inode->mlock_enforced && + pl_inode->track_fop_wind_count) { + pl_inode->fop_wind_count++; + } goto unlock; - else if (!can_block) { + } else if (!can_block) { op_errno = EAGAIN; op_ret = -1; goto unlock; } - rw = GF_CALLOC(1, sizeof(*rw), gf_locks_mt_pl_rw_req_t); + rw = GF_MALLOC(sizeof(*rw), gf_locks_mt_pl_rw_req_t); if (!rw) { op_errno = ENOMEM; op_ret = -1; @@ -581,7 +759,8 @@ pl_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, FIRST_CHILD(this)->fops->discard, fd, offset, len, xdata); unwind: if (op_ret == -1) - STACK_UNWIND_STRICT(discard, frame, op_ret, op_errno, NULL, NULL, NULL); + PL_STACK_UNWIND(discard, xdata, frame, op_ret, op_errno, NULL, NULL, + NULL); return 0; } @@ -591,8 +770,10 @@ pl_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { - STACK_UNWIND_STRICT(zerofill, frame, op_ret, op_errno, prebuf, postbuf, - xdata); + pl_track_io_fop_count(frame->local, this, DECREMENT); + + PL_STACK_UNWIND(zerofill, xdata, frame, op_ret, op_errno, prebuf, postbuf, + xdata); return 0; } @@ -600,6 +781,8 @@ int pl_zerofill_cont(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, off_t len, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, INCREMENT); + STACK_WIND(frame, pl_zerofill_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->zerofill, fd, offset, len, xdata); return 0; @@ -609,6 +792,7 @@ int32_t pl_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, off_t len, dict_t *xdata) { + pl_local_t *local = NULL; pl_inode_t *pl_inode = NULL; pl_rw_req_t *rw = NULL; posix_lock_t region = { @@ -625,17 +809,28 @@ pl_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, GF_VALIDATE_OR_GOTO("locks", this, unwind); - pl_inode = pl_inode_get(this, fd->inode); - if (!pl_inode) { + local = mem_get0(this->local_pool); + if (!local) { op_ret = -1; op_errno = ENOMEM; goto unwind; } - enabled = pl_is_mandatory_locking_enabled(pl_inode); + frame->local = local; + local->inode = inode_ref(fd->inode); + local->fd = fd_ref(fd); + + pl_inode = pl_inode_get(this, fd->inode, local); + if (!pl_inode) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } if (frame->root->pid < 0) enabled = _gf_false; + else + enabled = pl_is_mandatory_locking_enabled(pl_inode); if (enabled) { region.fl_start = offset; @@ -649,15 +844,19 @@ pl_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, { allowed = pl_is_fop_allowed(pl_inode, ®ion, fd, GF_FOP_ZEROFILL, &can_block); - if (allowed == 1) + if (allowed == 1) { + if (pl_inode->mlock_enforced && + pl_inode->track_fop_wind_count) { + pl_inode->fop_wind_count++; + } goto unlock; - else if (!can_block) { + } else if (!can_block) { op_errno = EAGAIN; op_ret = -1; goto unlock; } - rw = GF_CALLOC(1, sizeof(*rw), gf_locks_mt_pl_rw_req_t); + rw = GF_MALLOC(sizeof(*rw), gf_locks_mt_pl_rw_req_t); if (!rw) { op_errno = ENOMEM; op_ret = -1; @@ -686,8 +885,8 @@ pl_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, FIRST_CHILD(this)->fops->zerofill, fd, offset, len, xdata); unwind: if (op_ret == -1) - STACK_UNWIND_STRICT(zerofill, frame, op_ret, op_errno, NULL, NULL, - NULL); + PL_STACK_UNWIND(zerofill, xdata, frame, op_ret, op_errno, NULL, NULL, + NULL); return 0; } @@ -697,24 +896,16 @@ pl_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, dict_t *xdata) { - pl_local_t *local = NULL; - - local = frame->local; - - if (local->op == GF_FOP_TRUNCATE) - loc_wipe(&local->loc[0]); + pl_local_t *local = frame->local; - if (local->xdata) - dict_unref(local->xdata); - if (local->fd) - fd_unref(local->fd); + pl_track_io_fop_count(local, this, DECREMENT); if (local->op == GF_FOP_TRUNCATE) - STACK_UNWIND_STRICT(truncate, frame, op_ret, op_errno, prebuf, postbuf, - xdata); + PL_STACK_UNWIND(truncate, xdata, frame, op_ret, op_errno, prebuf, + postbuf, xdata); else - STACK_UNWIND_STRICT(ftruncate, frame, op_ret, op_errno, prebuf, postbuf, - xdata); + PL_STACK_UNWIND(ftruncate, xdata, frame, op_ret, op_errno, prebuf, + postbuf, xdata); return 0; } @@ -722,6 +913,8 @@ int pl_ftruncate_cont(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, INCREMENT); + STACK_WIND(frame, pl_truncate_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); return 0; @@ -731,6 +924,8 @@ int pl_truncate_cont(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, INCREMENT); + STACK_WIND(frame, pl_truncate_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); return 0; @@ -741,7 +936,7 @@ truncate_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata) { - pl_local_t *local = NULL; + pl_local_t *local = frame->local; inode_t *inode = NULL; pl_inode_t *pl_inode = NULL; pl_rw_req_t *rw = NULL; @@ -756,7 +951,6 @@ truncate_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int allowed = 1; GF_VALIDATE_OR_GOTO("locks", this, unwind); - local = frame->local; if (op_ret != 0) { gf_log(this->name, GF_LOG_ERROR, @@ -770,17 +964,19 @@ truncate_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, else inode = local->fd->inode; - pl_inode = pl_inode_get(this, inode); + local->inode = inode_ref(inode); + + pl_inode = pl_inode_get(this, inode, local); if (!pl_inode) { op_ret = -1; op_errno = ENOMEM; goto unwind; } - enabled = pl_is_mandatory_locking_enabled(pl_inode); - if (frame->root->pid < 0) enabled = _gf_false; + else + enabled = pl_is_mandatory_locking_enabled(pl_inode); if (enabled) { region.fl_start = local->offset; @@ -794,15 +990,19 @@ truncate_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, allowed = pl_is_fop_allowed(pl_inode, ®ion, local->fd, local->op, &can_block); - if (allowed == 1) + if (allowed == 1) { + if (pl_inode->mlock_enforced && + pl_inode->track_fop_wind_count) { + pl_inode->fop_wind_count++; + } goto unlock; - else if (!can_block) { + } else if (!can_block) { op_errno = EAGAIN; op_ret = -1; goto unlock; } - rw = GF_CALLOC(1, sizeof(*rw), gf_locks_mt_pl_rw_req_t); + rw = GF_MALLOC(sizeof(*rw), gf_locks_mt_pl_rw_req_t); if (!rw) { op_errno = ENOMEM; op_ret = -1; @@ -850,25 +1050,19 @@ truncate_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, } unwind: if (op_ret == -1) { - gf_log(this->name, GF_LOG_ERROR, + gf_log(this ? this->name : "locks", GF_LOG_ERROR, "truncate failed with " "ret: %d, error: %s", op_ret, strerror(op_errno)); - if (local->op == GF_FOP_TRUNCATE) - loc_wipe(&local->loc[0]); - if (local->xdata) - dict_unref(local->xdata); - if (local->fd) - fd_unref(local->fd); switch (local->op) { case GF_FOP_TRUNCATE: - STACK_UNWIND_STRICT(truncate, frame, op_ret, op_errno, buf, - NULL, xdata); + PL_STACK_UNWIND(truncate, xdata, frame, op_ret, op_errno, buf, + NULL, xdata); break; case GF_FOP_FTRUNCATE: - STACK_UNWIND_STRICT(ftruncate, frame, op_ret, op_errno, buf, - NULL, xdata); + PL_STACK_UNWIND(ftruncate, xdata, frame, op_ret, op_errno, buf, + NULL, xdata); break; default: break; @@ -900,9 +1094,10 @@ pl_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, STACK_WIND(frame, truncate_stat_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->stat, loc, NULL); ret = 0; + unwind: if (ret == -1) { - gf_log(this->name, GF_LOG_ERROR, + gf_log(this ? this->name : "locks", GF_LOG_ERROR, "truncate on %s failed with" " ret: %d, error: %s", loc->path, -1, strerror(ENOMEM)); @@ -935,7 +1130,7 @@ pl_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, ret = 0; unwind: if (ret == -1) { - gf_log(this->name, GF_LOG_ERROR, + gf_log(this ? this->name : "locks", GF_LOG_ERROR, "ftruncate failed with" " ret: %d, error: %s", -1, strerror(ENOMEM)); @@ -1040,68 +1235,68 @@ pl_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, return 0; } -int32_t -pl_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, - dict_t *xdata) +static int32_t +pl_getxattr_clrlk(xlator_t *this, const char *name, inode_t *inode, + dict_t **dict, int32_t *op_errno) { - int32_t op_errno = EINVAL; - int op_ret = -1; int32_t bcount = 0; int32_t gcount = 0; - char key[PATH_MAX] = { - 0, - }; + char *key = NULL; char *lk_summary = NULL; pl_inode_t *pl_inode = NULL; - dict_t *dict = NULL; clrlk_args args = { 0, }; char *brickname = NULL; + int32_t op_ret = -1; - if (!name) - goto usual; - - if (strncmp(name, GF_XATTR_CLRLK_CMD, SLEN(GF_XATTR_CLRLK_CMD))) - goto usual; + *op_errno = EINVAL; if (clrlk_parse_args(name, &args)) { - op_errno = EINVAL; + *op_errno = EINVAL; goto out; } - dict = dict_new(); - if (!dict) { - op_errno = ENOMEM; + *dict = dict_new(); + if (!*dict) { + *op_errno = ENOMEM; goto out; } - pl_inode = pl_inode_get(this, loc->inode); + pl_inode = pl_inode_get(this, inode, NULL); if (!pl_inode) { - op_errno = ENOMEM; + *op_errno = ENOMEM; goto out; } switch (args.type) { case CLRLK_INODE: case CLRLK_ENTRY: - op_ret = clrlk_clear_lks_in_all_domains( - this, pl_inode, &args, &bcount, &gcount, &op_errno); - if (op_ret) - goto out; + op_ret = clrlk_clear_lks_in_all_domains(this, pl_inode, &args, + &bcount, &gcount, op_errno); break; case CLRLK_POSIX: op_ret = clrlk_clear_posixlk(this, pl_inode, &args, &bcount, - &gcount, &op_errno); - if (op_ret) - goto out; + &gcount, op_errno); break; - case CLRLK_TYPE_MAX: - op_errno = EINVAL; - goto out; + default: + op_ret = -1; + *op_errno = EINVAL; + } + if (op_ret) { + if (args.type >= CLRLK_TYPE_MAX) { + gf_log(this->name, GF_LOG_ERROR, + "clear locks: invalid lock type %d", args.type); + } else { + gf_log(this->name, GF_LOG_ERROR, + "clear locks of type %s failed: %s", + clrlk_type_names[args.type], strerror(*op_errno)); + } + + goto out; } - op_ret = fetch_pathinfo(this, loc->inode, &op_errno, &brickname); + op_ret = fetch_pathinfo(this, inode, op_errno, &brickname); if (op_ret) { gf_log(this->name, GF_LOG_WARNING, "Couldn't get brickname"); } else { @@ -1116,43 +1311,62 @@ pl_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, if (!gcount && !bcount) { if (gf_asprintf(&lk_summary, "No locks cleared.") == -1) { op_ret = -1; - op_errno = ENOMEM; + *op_errno = ENOMEM; goto out; } - } else if (gf_asprintf( - &lk_summary, - "%s: %s blocked locks=%d " - "granted locks=%d", - (brickname == NULL) ? this->name : brickname, - (args.type == CLRLK_INODE) - ? "inode" - : (args.type == CLRLK_ENTRY) - ? "entry" - : (args.type == CLRLK_POSIX) ? "posix" : " ", - bcount, gcount) == -1) { + } else if (gf_asprintf(&lk_summary, + "%s: %s blocked locks=%d " + "granted locks=%d", + (brickname == NULL) ? this->name : brickname, + clrlk_type_names[args.type], bcount, gcount) == -1) { op_ret = -1; - op_errno = ENOMEM; + *op_errno = ENOMEM; goto out; } + gf_log(this->name, GF_LOG_DEBUG, "%s", lk_summary); - if (snprintf(key, sizeof(key), "%s", name) >= sizeof(key)) { + key = gf_strdup(name); + if (!key) { op_ret = -1; goto out; } - if (dict_set_dynstr(dict, key, lk_summary)) { + if (dict_set_dynstr(*dict, key, lk_summary)) { op_ret = -1; - op_errno = ENOMEM; + *op_errno = ENOMEM; goto out; } op_ret = 0; + out: GF_FREE(brickname); - STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, dict, xdata); - GF_FREE(args.opts); - if (op_ret && lk_summary) + GF_FREE(key); + if (op_ret) { GF_FREE(lk_summary); + } + + return op_ret; +} + +int32_t +pl_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, + dict_t *xdata) +{ + int32_t op_errno = EINVAL; + int32_t op_ret = -1; + dict_t *dict = NULL; + + if (!name) + goto usual; + + if (strncmp(name, GF_XATTR_CLRLK_CMD, SLEN(GF_XATTR_CLRLK_CMD))) + goto usual; + + op_ret = pl_getxattr_clrlk(this, name, loc->inode, &dict, &op_errno); + + STACK_UNWIND_STRICT(getxattr, frame, op_ret, op_errno, dict, xdata); + if (dict) dict_unref(dict); return 0; @@ -1218,7 +1432,7 @@ fetch_pathinfo(xlator_t *this, inode_t *inode, int32_t *op_errno, goto out; } - ret = dict_get_str(dict, GF_XATTR_PATHINFO_KEY, brickname); + ret = dict_get_str_sizen(dict, GF_XATTR_PATHINFO_KEY, brickname); if (ret) goto out; @@ -1241,15 +1455,12 @@ out: int pl_lockinfo_get_brickname(xlator_t *this, inode_t *inode, int32_t *op_errno) { - int ret = -1; - posix_locks_private_t *priv = NULL; + posix_locks_private_t *priv = this->private; char *brickname = NULL; char *end = NULL; char *tmp = NULL; - priv = this->private; - - ret = fetch_pathinfo(this, inode, op_errno, &brickname); + int ret = fetch_pathinfo(this, inode, op_errno, &brickname); if (ret) goto out; @@ -1277,12 +1488,10 @@ out: char * pl_lockinfo_key(xlator_t *this, inode_t *inode, int32_t *op_errno) { - posix_locks_private_t *priv = NULL; + posix_locks_private_t *priv = this->private; char *key = NULL; int ret = 0; - priv = this->private; - if (priv->brickname == NULL) { ret = pl_lockinfo_get_brickname(this, inode, op_errno); if (ret < 0) { @@ -1300,14 +1509,13 @@ int32_t pl_fgetxattr_handle_lockinfo(xlator_t *this, fd_t *fd, dict_t *dict, int32_t *op_errno) { - pl_inode_t *pl_inode = NULL; char *key = NULL, *buf = NULL; int32_t op_ret = 0; unsigned long fdnum = 0; int32_t len = 0; dict_t *tmp = NULL; - pl_inode = pl_inode_get(this, fd->inode); + pl_inode_t *pl_inode = pl_inode_get(this, fd->inode, NULL); if (!pl_inode) { gf_log(this->name, GF_LOG_DEBUG, "Could not get inode."); @@ -1347,8 +1555,9 @@ pl_fgetxattr_handle_lockinfo(xlator_t *this, fd_t *fd, dict_t *dict, goto out; } - len = dict_serialized_length(tmp); - if (len < 0) { + op_ret = dict_allocate_and_serialize(tmp, (char **)&buf, + (unsigned int *)&len); + if (op_ret != 0) { *op_errno = -op_ret; op_ret = -1; gf_log(this->name, GF_LOG_WARNING, @@ -1358,24 +1567,6 @@ pl_fgetxattr_handle_lockinfo(xlator_t *this, fd_t *fd, dict_t *dict, goto out; } - buf = GF_CALLOC(1, len, gf_common_mt_char); - if (buf == NULL) { - op_ret = -1; - *op_errno = ENOMEM; - goto out; - } - - op_ret = dict_serialize(tmp, buf); - if (op_ret < 0) { - *op_errno = -op_ret; - op_ret = -1; - gf_log(this->name, GF_LOG_WARNING, - "dict_serialize failed (%s) while handling lockinfo " - "for fd (ptr: %p inode-gfid:%s)", - strerror(*op_errno), fd, uuid_utoa(fd->inode->gfid)); - goto out; - } - op_ret = dict_set_dynptr(dict, GF_XATTR_LOCKINFO_KEY, buf, len); if (op_ret < 0) { *op_errno = -op_ret; @@ -1428,6 +1619,11 @@ pl_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, } goto unwind; + } else if (strncmp(name, GF_XATTR_CLRLK_CMD, SLEN(GF_XATTR_CLRLK_CMD)) == + 0) { + op_ret = pl_getxattr_clrlk(this, name, fd->inode, &dict, &op_errno); + + goto unwind; } else { goto usual; } @@ -1450,14 +1646,11 @@ int32_t pl_migrate_locks(call_frame_t *frame, fd_t *newfd, uint64_t oldfd_num, int32_t *op_errno) { - pl_inode_t *pl_inode = NULL; - uint64_t newfd_num = 0; posix_lock_t *l = NULL; int32_t op_ret = 0; + uint64_t newfd_num = fd_to_fdnum(newfd); - newfd_num = fd_to_fdnum(newfd); - - pl_inode = pl_inode_get(frame->this, newfd->inode); + pl_inode_t *pl_inode = pl_inode_get(frame->this, newfd->inode, NULL); if (pl_inode == NULL) { op_ret = -1; *op_errno = EBADFD; @@ -1486,11 +1679,10 @@ pl_fsetxattr_handle_lockinfo(call_frame_t *frame, fd_t *fd, char *lockinfo_buf, int len, int32_t *op_errno) { int32_t op_ret = -1; - dict_t *lockinfo = NULL; uint64_t oldfd_num = 0; char *key = NULL; - lockinfo = dict_new(); + dict_t *lockinfo = dict_new(); if (lockinfo == NULL) { op_ret = -1; *op_errno = ENOMEM; @@ -1522,7 +1714,7 @@ pl_fsetxattr_handle_lockinfo(call_frame_t *frame, fd_t *fd, char *lockinfo_buf, gf_log(frame->this->name, GF_LOG_WARNING, "migration of locks from oldfd (ptr:%p) to newfd " "(ptr:%p) (inode-gfid:%s)", - (void *)oldfd_num, fd, uuid_utoa(fd->inode->gfid)); + (void *)(uintptr_t)oldfd_num, fd, uuid_utoa(fd->inode->gfid)); goto out; } @@ -1536,6 +1728,27 @@ int32_t pl_fsetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { + pl_local_t *local = NULL; + pl_inode_t *pl_inode = NULL; + + local = frame->local; + if (local && local->update_mlock_enforced_flag && op_ret != -1) { + pl_inode = pl_inode_get(this, local->inode, NULL); + if (!pl_inode) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + + pthread_mutex_lock(&pl_inode->mutex); + { + pl_inode->mlock_enforced = _gf_true; + pl_inode->check_mlock_info = _gf_false; + } + pthread_mutex_unlock(&pl_inode->mutex); + } + +unwind: PL_STACK_UNWIND_FOR_CLIENT(fsetxattr, xdata, frame, op_ret, op_errno, xdata); return 0; @@ -1545,12 +1758,14 @@ int32_t pl_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, int32_t flags, dict_t *xdata) { - int32_t op_ret = 0, op_errno = 0; + int32_t op_errno = 0; void *lockinfo_buf = NULL; int len = 0; + char *name = NULL; + posix_locks_private_t *priv = this->private; - op_ret = dict_get_ptr_and_len(dict, GF_XATTR_LOCKINFO_KEY, &lockinfo_buf, - &len); + int32_t op_ret = dict_get_ptr_and_len(dict, GF_XATTR_LOCKINFO_KEY, + &lockinfo_buf, &len); if (lockinfo_buf == NULL) { goto usual; } @@ -1563,12 +1778,17 @@ pl_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, usual: PL_LOCAL_GET_REQUESTS(frame, this, xdata, fd, NULL, NULL); + + PL_CHECK_LOCK_ENFORCE_KEY(frame, dict, name, this, ((loc_t *)NULL), fd, + priv); + STACK_WIND(frame, pl_fsetxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); return 0; unwind: - STACK_UNWIND_STRICT(fsetxattr, frame, op_ret, op_errno, NULL); + PL_STACK_UNWIND_FOR_CLIENT(fsetxattr, xdata, frame, op_ret, op_errno, NULL); + return 0; } @@ -1616,10 +1836,7 @@ pl_flush_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int pl_flush(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - pl_inode_t *pl_inode = NULL; - - pl_inode = pl_inode_get(this, fd->inode); - + pl_inode_t *pl_inode = pl_inode_get(this, fd->inode, NULL); if (!pl_inode) { gf_log(this->name, GF_LOG_DEBUG, "Could not get inode."); STACK_UNWIND_STRICT(flush, frame, -1, EBADFD, NULL); @@ -1695,14 +1912,18 @@ pl_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, int op_errno = EINVAL; pl_inode_t *pl_inode = NULL; posix_lock_t *l = NULL; - posix_locks_private_t *priv = NULL; - - priv = this->private; + posix_locks_private_t *priv = this->private; GF_VALIDATE_OR_GOTO("locks", this, unwind); op_ret = 0, op_errno = 0; - pl_inode = pl_inode_get(this, fd->inode); + pl_inode = pl_inode_get(this, fd->inode, NULL); + if (!pl_inode) { + gf_msg(this->name, GF_LOG_ERROR, 0, ENOMEM, "Could not get inode"); + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } /* As per design, under forced and file-based mandatory locking modes * it doesn't matter whether inodes's lock list contain advisory or @@ -1777,7 +1998,8 @@ int pl_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, fd, NULL, NULL); + STACK_WIND(frame, pl_create_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, fd, xdata); @@ -1789,6 +2011,8 @@ pl_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iovec *vector, int32_t count, struct iatt *stbuf, struct iobref *iobref, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, DECREMENT); + PL_STACK_UNWIND(readv, xdata, frame, op_ret, op_errno, vector, count, stbuf, iobref, xdata); @@ -1800,6 +2024,8 @@ pl_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, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, DECREMENT); + PL_STACK_UNWIND(writev, xdata, frame, op_ret, op_errno, prebuf, postbuf, xdata); @@ -1822,6 +2048,10 @@ do_blocked_rw(pl_inode_t *pl_inode) if (__rw_allowable(pl_inode, &rw->region, rw->stub->fop)) { list_del_init(&rw->list); list_add_tail(&rw->list, &wind_list); + if (pl_inode->mlock_enforced && + pl_inode->track_fop_wind_count) { + pl_inode->fop_wind_count++; + } } } } @@ -1837,14 +2067,68 @@ do_blocked_rw(pl_inode_t *pl_inode) return; } +/* when mandatory lock is enforced: + If an IO request comes on a region which is out of the boundary of the + granted mandatory lock, it will be rejected. + + Note: There is no IO blocking with mandatory lock enforced as it may be + a stale data from an old client. + */ +gf_boolean_t static within_range(posix_lock_t *existing, posix_lock_t *new) +{ + if (existing->fl_start <= new->fl_start && existing->fl_end >= new->fl_end) + return _gf_true; + + return _gf_false; +} + static int __rw_allowable(pl_inode_t *pl_inode, posix_lock_t *region, glusterfs_fop_t op) { posix_lock_t *l = NULL; - posix_locks_private_t *priv = NULL; + posix_locks_private_t *priv = THIS->private; int ret = 1; - priv = THIS->private; + if (pl_inode->mlock_enforced) { + list_for_each_entry(l, &pl_inode->ext_list, list) + { + /* + with lock enforced (fencing) there should not be any blocking + lock coexisting. + */ + if (same_owner(l, region)) { + /* Should range check be strict for same owner with fencing? */ + if (locks_overlap(l, region)) { + if (within_range(l, region)) { + return 1; + } else { + /* + Should we allow read fop if it does not fit it in the + range? + if (op == GF_FOP_READ && l->fl_type != F_WRLCK) { + return 1; + } + */ + return 0; + } + } + } else { + if (locks_overlap(l, region)) { + /* + with fencing should a read from a different owner be + allowed if the mandatory lock taken is F_RDLCK? + if (op == GF_FOP_READ && l->fl_type != F_WRLCK) { + return 1; + } + */ + return 0; + } + } + } + + /* No lock has been taken by this owner */ + return 0; + } list_for_each_entry(l, &pl_inode->ext_list, list) { @@ -1868,6 +2152,8 @@ int pl_readv_cont(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, INCREMENT); + STACK_WIND(frame, pl_readv_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata); @@ -1878,6 +2164,7 @@ int pl_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) { + pl_local_t *local = NULL; pl_inode_t *pl_inode = NULL; pl_rw_req_t *rw = NULL; posix_lock_t region = { @@ -1894,18 +2181,26 @@ pl_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, GF_VALIDATE_OR_GOTO("locks", this, unwind); - pl_inode = pl_inode_get(this, fd->inode); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, fd, NULL, NULL); + + if (!frame->local) { + frame->local = mem_get0(this->local_pool); + local = frame->local; + local->inode = inode_ref(fd->inode); + local->fd = fd_ref(fd); + } + + pl_inode = pl_inode_get(this, fd->inode, local); if (!pl_inode) { op_ret = -1; op_errno = ENOMEM; goto unwind; } - PL_LOCAL_GET_REQUESTS(frame, this, xdata, fd, NULL, NULL); - enabled = pl_is_mandatory_locking_enabled(pl_inode); - if (frame->root->pid < 0) enabled = _gf_false; + else + enabled = pl_is_mandatory_locking_enabled(pl_inode); if (enabled) { region.fl_start = offset; @@ -1919,15 +2214,19 @@ pl_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, { allowed = pl_is_fop_allowed(pl_inode, ®ion, fd, GF_FOP_READ, &can_block); - if (allowed == 1) + if (allowed == 1) { + if (pl_inode->mlock_enforced && + pl_inode->track_fop_wind_count) { + pl_inode->fop_wind_count++; + } goto unlock; - else if (!can_block) { + } else if (!can_block) { op_errno = EAGAIN; op_ret = -1; goto unlock; } - rw = GF_CALLOC(1, sizeof(*rw), gf_locks_mt_pl_rw_req_t); + rw = GF_MALLOC(sizeof(*rw), gf_locks_mt_pl_rw_req_t); if (!rw) { op_errno = ENOMEM; op_ret = -1; @@ -1958,8 +2257,8 @@ pl_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, } unwind: if (op_ret == -1) - STACK_UNWIND_STRICT(readv, frame, op_ret, op_errno, NULL, 0, NULL, NULL, - NULL); + PL_STACK_UNWIND(readv, xdata, frame, op_ret, op_errno, NULL, 0, NULL, + NULL, NULL); return 0; } @@ -1969,6 +2268,8 @@ pl_writev_cont(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int count, off_t offset, uint32_t flags, struct iobref *iobref, dict_t *xdata) { + pl_track_io_fop_count(frame->local, this, INCREMENT); + STACK_WIND(frame, pl_writev_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, vector, count, offset, flags, iobref, xdata); @@ -1981,6 +2282,7 @@ pl_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t offset, uint32_t flags, struct iobref *iobref, dict_t *xdata) { + pl_local_t *local = NULL; pl_inode_t *pl_inode = NULL; pl_rw_req_t *rw = NULL; posix_lock_t region = { @@ -1997,18 +2299,26 @@ pl_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, GF_VALIDATE_OR_GOTO("locks", this, unwind); - pl_inode = pl_inode_get(this, fd->inode); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, fd, NULL, NULL); + + if (!frame->local) { + frame->local = mem_get0(this->local_pool); + local = frame->local; + local->inode = inode_ref(fd->inode); + local->fd = fd_ref(fd); + } + + pl_inode = pl_inode_get(this, fd->inode, local); if (!pl_inode) { op_ret = -1; op_errno = ENOMEM; goto unwind; } - PL_LOCAL_GET_REQUESTS(frame, this, xdata, fd, NULL, NULL); - enabled = pl_is_mandatory_locking_enabled(pl_inode); - if (frame->root->pid < 0) enabled = _gf_false; + else + enabled = pl_is_mandatory_locking_enabled(pl_inode); if (enabled) { region.fl_start = offset; @@ -2022,15 +2332,24 @@ pl_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, { allowed = pl_is_fop_allowed(pl_inode, ®ion, fd, GF_FOP_WRITE, &can_block); - if (allowed == 1) + if (allowed == 1) { + if (pl_inode->mlock_enforced && + pl_inode->track_fop_wind_count) { + pl_inode->fop_wind_count++; + } goto unlock; - else if (!can_block) { - op_errno = EAGAIN; + } else if (!can_block) { + if (pl_inode->mlock_enforced) { + op_errno = EBUSY; + } else { + op_errno = EAGAIN; + } + op_ret = -1; goto unlock; } - rw = GF_CALLOC(1, sizeof(*rw), gf_locks_mt_pl_rw_req_t); + rw = GF_MALLOC(sizeof(*rw), gf_locks_mt_pl_rw_req_t); if (!rw) { op_errno = ENOMEM; op_ret = -1; @@ -2061,7 +2380,8 @@ pl_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, } unwind: if (op_ret == -1) - STACK_UNWIND_STRICT(writev, frame, op_ret, op_errno, NULL, NULL, NULL); + PL_STACK_UNWIND(writev, xdata, frame, op_ret, op_errno, NULL, NULL, + NULL); return 0; } @@ -2069,29 +2389,25 @@ unwind: static int __fd_has_locks(pl_inode_t *pl_inode, fd_t *fd) { - int found = 0; posix_lock_t *l = NULL; list_for_each_entry(l, &pl_inode->ext_list, list) { if (l->fd_num == fd_to_fdnum(fd)) { - found = 1; - break; + return 1; } } - return found; + return 0; } static posix_lock_t * lock_dup(posix_lock_t *lock) { - posix_lock_t *new_lock = NULL; - - new_lock = new_posix_lock(&lock->user_flock, lock->client, lock->client_pid, - &lock->owner, (fd_t *)lock->fd_num, - lock->lk_flags, lock->blocking); - return new_lock; + int32_t op_errno = 0; + return new_posix_lock(&lock->user_flock, lock->client, lock->client_pid, + &lock->owner, (fd_t *)lock->fd_num, lock->lk_flags, + lock->blocking, &op_errno); } static int @@ -2120,14 +2436,7 @@ __dup_locks_to_fdctx(pl_inode_t *pl_inode, fd_t *fd, pl_fdctx_t *fdctx) static int __copy_locks_to_fdctx(pl_inode_t *pl_inode, fd_t *fd, pl_fdctx_t *fdctx) { - int ret = 0; - - ret = __dup_locks_to_fdctx(pl_inode, fd, fdctx); - if (ret) - goto out; - -out: - return ret; + return __dup_locks_to_fdctx(pl_inode, fd, fdctx); } static void @@ -2198,9 +2507,10 @@ pl_getlk_fd(xlator_t *this, pl_inode_t *pl_inode, fd_t *fd, pthread_mutex_lock(&pl_inode->mutex); { if (!__fd_has_locks(pl_inode, fd)) { + pthread_mutex_unlock(&pl_inode->mutex); gf_log(this->name, GF_LOG_DEBUG, "fd=%p has no active locks", fd); ret = 0; - goto unlock; + goto out; } gf_log(this->name, GF_LOG_DEBUG, "There are active locks on fd"); @@ -2224,15 +2534,17 @@ pl_getlk_fd(xlator_t *this, pl_inode_t *pl_inode, fd_t *fd, "fdctx present -> returning the next lock"); ret = __set_next_lock_fd(fdctx, reqlock); if (ret) { + pthread_mutex_unlock(&pl_inode->mutex); gf_log(this->name, GF_LOG_DEBUG, "could not get next lock of fd"); - goto unlock; + goto out; } } } unlock: pthread_mutex_unlock(&pl_inode->mutex); +out: return ret; } @@ -2245,12 +2557,10 @@ pl_metalock_is_active(pl_inode_t *pl_inode) return 1; } -int -__pl_queue_lock(pl_inode_t *pl_inode, posix_lock_t *reqlock, int can_block) +void +__pl_queue_lock(pl_inode_t *pl_inode, posix_lock_t *reqlock) { list_add_tail(&reqlock->list, &pl_inode->queued_locks); - - return 0; } int @@ -2263,13 +2573,12 @@ pl_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, int can_block = 0; posix_lock_t *reqlock = NULL; posix_lock_t *conf = NULL; - int ret = 0; uint32_t lk_flags = 0; - posix_locks_private_t *priv = NULL; - - priv = this->private; + posix_locks_private_t *priv = this->private; + pl_local_t *local = NULL; + short lock_type = 0; - ret = dict_get_uint32(xdata, GF_LOCK_MODE, &lk_flags); + int ret = dict_get_uint32(xdata, GF_LOCK_MODE, &lk_flags); if (ret == 0) { if (priv->mandatory_mode == MLK_NONE) gf_log(this->name, GF_LOG_DEBUG, @@ -2298,7 +2607,17 @@ pl_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, flock->l_len = labs(flock->l_len); } - pl_inode = pl_inode_get(this, fd->inode); + local = mem_get0(this->local_pool); + if (!local) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } else { + frame->local = local; + local->fd = fd_ref(fd); + } + + pl_inode = pl_inode_get(this, fd->inode, local); if (!pl_inode) { op_ret = -1; op_errno = ENOMEM; @@ -2306,11 +2625,11 @@ pl_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, } reqlock = new_posix_lock(flock, frame->root->client, frame->root->pid, - &frame->root->lk_owner, fd, lk_flags, can_block); + &frame->root->lk_owner, fd, lk_flags, can_block, + &op_errno); if (!reqlock) { op_ret = -1; - op_errno = ENOMEM; goto unwind; } @@ -2402,6 +2721,7 @@ pl_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, case F_SETLK: reqlock->frame = frame; reqlock->this = this; + lock_type = flock->l_type; pthread_mutex_lock(&pl_inode->mutex); { @@ -2423,10 +2743,23 @@ pl_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, goto out; } + if (reqlock->fl_type != F_UNLCK && pl_inode->mlock_enforced) { + ret = pl_lock_preempt(pl_inode, reqlock); + if (ret == -1) { + gf_log(this->name, GF_LOG_ERROR, "lock preempt failed"); + op_ret = -1; + op_errno = EAGAIN; + __destroy_lock(reqlock); + goto out; + } + + pl_trace_block(this, frame, fd, NULL, cmd, flock, NULL); + goto unwind; + } + ret = pl_setlk(this, pl_inode, reqlock, can_block); if (ret == -1) { - if ((can_block) && (F_UNLCK != flock->l_type)) { - pl_trace_block(this, frame, fd, NULL, cmd, flock, NULL); + if ((can_block) && (F_UNLCK != lock_type)) { goto out; } gf_log(this->name, GF_LOG_DEBUG, "returning EAGAIN"); @@ -2448,7 +2781,7 @@ unwind: pl_trace_out(this, frame, fd, NULL, cmd, flock, op_ret, op_errno, NULL); pl_update_refkeeper(this, fd->inode); - STACK_UNWIND_STRICT(lk, frame, op_ret, op_errno, flock, xdata); + PL_STACK_UNWIND(lk, xdata, frame, op_ret, op_errno, flock, xdata); out: return 0; } @@ -2481,7 +2814,9 @@ pl_forget(xlator_t *this, inode_t *inode) INIT_LIST_HEAD(&inodelks_released); INIT_LIST_HEAD(&entrylks_released); - pl_inode = pl_inode_get(this, inode); + pl_inode = pl_inode_get(this, inode, NULL); + if (!pl_inode) + return 0; pthread_mutex_lock(&pl_inode->mutex); { @@ -2553,25 +2888,33 @@ pl_forget(xlator_t *this, inode_t *inode) } pthread_mutex_unlock(&pl_inode->mutex); - list_for_each_entry_safe(ext_l, ext_tmp, &posixlks_released, list) - { - STACK_UNWIND_STRICT(lk, ext_l->frame, -1, 0, &ext_l->user_flock, NULL); - __destroy_lock(ext_l); + if (!list_empty(&posixlks_released)) { + list_for_each_entry_safe(ext_l, ext_tmp, &posixlks_released, list) + { + STACK_UNWIND_STRICT(lk, ext_l->frame, -1, 0, &ext_l->user_flock, + NULL); + __destroy_lock(ext_l); + } } - list_for_each_entry_safe(ino_l, ino_tmp, &inodelks_released, blocked_locks) - { - STACK_UNWIND_STRICT(inodelk, ino_l->frame, -1, 0, NULL); - __pl_inodelk_unref(ino_l); + if (!list_empty(&inodelks_released)) { + list_for_each_entry_safe(ino_l, ino_tmp, &inodelks_released, + blocked_locks) + { + STACK_UNWIND_STRICT(inodelk, ino_l->frame, -1, 0, NULL); + __pl_inodelk_unref(ino_l); + } } - list_for_each_entry_safe(entry_l, entry_tmp, &entrylks_released, - blocked_locks) - { - STACK_UNWIND_STRICT(entrylk, entry_l->frame, -1, 0, NULL); - GF_FREE((char *)entry_l->basename); - GF_FREE(entry_l->connection_id); - GF_FREE(entry_l); + if (!list_empty(&entrylks_released)) { + list_for_each_entry_safe(entry_l, entry_tmp, &entrylks_released, + blocked_locks) + { + STACK_UNWIND_STRICT(entrylk, entry_l->frame, -1, 0, NULL); + GF_FREE((char *)entry_l->basename); + GF_FREE(entry_l->connection_id); + GF_FREE(entry_l); + } } pthread_mutex_destroy(&pl_inode->mutex); @@ -2645,11 +2988,85 @@ out: return ret; } +static int32_t +pl_request_link_count(dict_t **pxdata) +{ + dict_t *xdata; + + xdata = *pxdata; + if (xdata == NULL) { + xdata = dict_new(); + if (xdata == NULL) { + return ENOMEM; + } + } else { + dict_ref(xdata); + } + + if (dict_set_uint32(xdata, GET_LINK_COUNT, 0) != 0) { + dict_unref(xdata); + return ENOMEM; + } + + *pxdata = xdata; + + return 0; +} + +static int32_t +pl_check_link_count(dict_t *xdata) +{ + int32_t count; + + /* In case we are unable to read the link count from xdata, we take a + * conservative approach and return -2, which will prevent the inode from + * being considered deleted. In fact it will cause link tracking for this + * inode to be disabled completely to avoid races. */ + + if (xdata == NULL) { + return -2; + } + + if (dict_get_int32(xdata, GET_LINK_COUNT, &count) != 0) { + return -2; + } + + return count; +} + int32_t pl_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *xdata, struct iatt *postparent) { + pl_inode_t *pl_inode; + + if (op_ret >= 0) { + pl_inode = pl_inode_get(this, inode, NULL); + if (pl_inode == NULL) { + PL_STACK_UNWIND(lookup, xdata, frame, -1, ENOMEM, NULL, NULL, NULL, + NULL); + return 0; + } + + pthread_mutex_lock(&pl_inode->mutex); + + /* We only update the link count if we previously didn't know it. + * Doing it always can lead to races since lookup is not executed + * atomically most of the times. */ + if (pl_inode->links == -2) { + pl_inode->links = pl_check_link_count(xdata); + if (buf->ia_type == IA_IFDIR) { + /* Directories have at least 2 links. To avoid special handling + * for directories, we simply decrement the value here to make + * them equivalent to regular files. */ + pl_inode->links--; + } + } + + pthread_mutex_unlock(&pl_inode->mutex); + } + PL_STACK_UNWIND(lookup, xdata, frame, op_ret, op_errno, inode, buf, xdata, postparent); return 0; @@ -2658,9 +3075,17 @@ pl_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t pl_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); - STACK_WIND(frame, pl_lookup_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, loc, xdata); + int32_t error; + + error = pl_request_link_count(&xdata); + if (error == 0) { + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); + STACK_WIND(frame, pl_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); + dict_unref(xdata); + } else { + STACK_UNWIND_STRICT(lookup, frame, -1, error, NULL, NULL, NULL, NULL); + } return 0; } @@ -2721,9 +3146,8 @@ pl_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, lock_migration_info_t * gf_mig_info_for_lock(posix_lock_t *lock) { - lock_migration_info_t *new = NULL; - - new = GF_CALLOC(1, sizeof(lock_migration_info_t), gf_common_mt_lock_mig); + lock_migration_info_t *new = GF_MALLOC(sizeof(lock_migration_info_t), + gf_common_mt_lock_mig); if (new == NULL) { goto out; } @@ -2751,7 +3175,7 @@ pl_fill_active_locks(pl_inode_t *pl_inode, lock_migration_info_t *lmi) { if (list_empty(&pl_inode->ext_list)) { count = 0; - goto out; + goto unlock; } list_for_each_entry(temp, &pl_inode->ext_list, list) @@ -2761,6 +3185,7 @@ pl_fill_active_locks(pl_inode_t *pl_inode, lock_migration_info_t *lmi) newlock = gf_mig_info_for_lock(temp); if (!newlock) { + pthread_mutex_unlock(&pl_inode->mutex); gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "lock_dup failed"); count = -1; goto out; @@ -2771,8 +3196,9 @@ pl_fill_active_locks(pl_inode_t *pl_inode, lock_migration_info_t *lmi) } } -out: +unlock: pthread_mutex_unlock(&pl_inode->mutex); +out: return count; } @@ -2788,7 +3214,7 @@ pl_getactivelk(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) INIT_LIST_HEAD(&locks.list); - pl_inode = pl_inode_get(this, loc->inode); + pl_inode = pl_inode_get(this, loc->inode, NULL); if (!pl_inode) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "pl_inode_get failed"); @@ -2828,9 +3254,8 @@ __pl_metalk_ref(pl_meta_lock_t *lock) pl_meta_lock_t * new_meta_lock(call_frame_t *frame, xlator_t *this) { - pl_meta_lock_t *lock = NULL; - - lock = GF_CALLOC(1, sizeof(*lock), gf_locks_mt_pl_meta_lock_t); + pl_meta_lock_t *lock = GF_CALLOC(1, sizeof(*lock), + gf_locks_mt_pl_meta_lock_t); if (!lock) { gf_msg(this->name, GF_LOG_ERROR, 0, ENOMEM, @@ -2904,7 +3329,7 @@ pl_metalk(call_frame_t *frame, xlator_t *this, inode_t *inode) pl_meta_lock_t *reqlk = NULL; pl_ctx_t *ctx = NULL; - pl_inode = pl_inode_get(this, inode); + pl_inode = pl_inode_get(this, inode, NULL); if (!pl_inode) { gf_msg(this->name, GF_LOG_ERROR, 0, ENOMEM, "pl_inode mem allocation failedd"); @@ -2934,15 +3359,15 @@ pl_metalk(call_frame_t *frame, xlator_t *this, inode_t *inode) pthread_mutex_lock(&pl_inode->mutex); { if (pl_metalock_is_active(pl_inode)) { - gf_msg(this->name, GF_LOG_WARNING, EINVAL, 0, - "More than one meta-lock can not be granted on" - "the inode"); ret = -1; } } pthread_mutex_unlock(&pl_inode->mutex); if (ret == -1) { + gf_msg(this->name, GF_LOG_WARNING, EINVAL, 0, + "More than one meta-lock cannot be granted on" + " the inode"); goto out; } @@ -2978,9 +3403,8 @@ out: return ret; } -void -__unwind_queued_locks(xlator_t *this, pl_inode_t *pl_inode, - struct list_head *tmp_list) +static void +__unwind_queued_locks(pl_inode_t *pl_inode, struct list_head *tmp_list) { if (list_empty(&pl_inode->queued_locks)) return; @@ -2988,9 +3412,8 @@ __unwind_queued_locks(xlator_t *this, pl_inode_t *pl_inode, list_splice_init(&pl_inode->queued_locks, tmp_list); } -void -__unwind_blocked_locks(xlator_t *this, pl_inode_t *pl_inode, - struct list_head *tmp_list) +static void +__unwind_blocked_locks(pl_inode_t *pl_inode, struct list_head *tmp_list) { posix_lock_t *lock = NULL; posix_lock_t *tmp = NULL; @@ -3038,7 +3461,7 @@ pl_metaunlock(call_frame_t *frame, xlator_t *this, inode_t *inode, dict_t *dict) goto out; } - pl_inode = pl_inode_get(this, inode); + pl_inode = pl_inode_get(this, inode, NULL); if (!pl_inode) { ret = -1; goto out; @@ -3049,12 +3472,12 @@ pl_metaunlock(call_frame_t *frame, xlator_t *this, inode_t *inode, dict_t *dict) pthread_mutex_lock(&pl_inode->mutex); { /* Unwind queued locks regardless of migration status */ - __unwind_queued_locks(this, pl_inode, &tmp_posixlk_list); + __unwind_queued_locks(pl_inode, &tmp_posixlk_list); /* Unwind blocked locks only for successful migration */ - if (dict_get(dict, "status")) { + if (dict_get_sizen(dict, "status")) { /* unwind all blocked locks */ - __unwind_blocked_locks(this, pl_inode, &tmp_posixlk_list); + __unwind_blocked_locks(pl_inode, &tmp_posixlk_list); } /* unlock metalk */ @@ -3081,7 +3504,7 @@ pl_metaunlock(call_frame_t *frame, xlator_t *this, inode_t *inode, dict_t *dict) inode_unref(pl_inode->inode); } - if (dict_get(dict, "status")) + if (dict_get_sizen(dict, "status")) pl_inode->migrated = _gf_true; else pl_inode->migrated = _gf_false; @@ -3110,6 +3533,34 @@ int32_t pl_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { + pl_local_t *local = NULL; + pl_inode_t *pl_inode = NULL; + local = frame->local; + if (local && local->update_mlock_enforced_flag && op_ret != -1) { + pl_inode = pl_inode_get(this, local->inode, NULL); + if (!pl_inode) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + + pthread_mutex_lock(&pl_inode->mutex); + { + while (pl_inode->fop_wind_count > 0) { + gf_msg(this->name, GF_LOG_INFO, 0, 0, + "waiting for existing fops (count %d) to drain for " + "gfid %s", + pl_inode->fop_wind_count, uuid_utoa(pl_inode->gfid)); + pthread_cond_wait(&pl_inode->check_fop_wind_count, + &pl_inode->mutex); + } + pl_inode->mlock_enforced = _gf_true; + pl_inode->check_mlock_info = _gf_false; + } + pthread_mutex_unlock(&pl_inode->mutex); + } + +unwind: PL_STACK_UNWIND_FOR_CLIENT(setxattr, xdata, frame, op_ret, op_errno, xdata); return 0; } @@ -3121,15 +3572,16 @@ pl_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, int op_ret = 0; int op_errno = EINVAL; dict_t *xdata_rsp = NULL; + char *name = NULL; + posix_locks_private_t *priv = this->private; - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); - if (dict_get(dict, GF_META_LOCK_KEY)) { + if (dict_get_sizen(dict, GF_META_LOCK_KEY)) { op_ret = pl_metalk(frame, this, loc->inode); - } else if (dict_get(dict, GF_META_UNLOCK_KEY)) { + } else if (dict_get_sizen(dict, GF_META_UNLOCK_KEY)) { op_ret = pl_metaunlock(frame, this, loc->inode, dict); - } else { goto usual; } @@ -3139,9 +3591,17 @@ pl_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, return 0; usual: + PL_CHECK_LOCK_ENFORCE_KEY(frame, dict, name, this, loc, ((fd_t *)NULL), + priv); + STACK_WIND(frame, pl_setxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); return 0; + +unwind: + PL_STACK_UNWIND_FOR_CLIENT(setxattr, xdata, frame, op_ret, op_errno, xdata); + + return 0; } void @@ -3150,10 +3610,10 @@ pl_dump_lock(char *str, int size, struct gf_flock *flock, gf_lkowner_t *owner, time_t *blkd_time, gf_boolean_t active) { char *type_str = NULL; - char granted[256] = { + char granted[GF_TIMESTR_SIZE] = { 0, }; - char blocked[256] = { + char blocked[GF_TIMESTR_SIZE] = { 0, }; @@ -3204,10 +3664,10 @@ __dump_entrylks(pl_inode_t *pl_inode) { pl_dom_list_t *dom = NULL; pl_entry_lock_t *lock = NULL; - char blocked[256] = { + char blocked[GF_TIMESTR_SIZE] = { 0, }; - char granted[256] = { + char granted[GF_TIMESTR_SIZE] = { 0, }; int count = 0; @@ -3227,10 +3687,10 @@ __dump_entrylks(pl_inode_t *pl_inode) list_for_each_entry(lock, &dom->entrylk_list, domain_list) { - gf_time_fmt(granted, sizeof(granted), lock->granted_time.tv_sec, + gf_time_fmt(granted, sizeof(granted), lock->granted_time, gf_timefmt_FT); gf_proc_dump_build_key(key, k, "entrylk[%d](ACTIVE)", count); - if (lock->blkd_time.tv_sec == 0) { + if (lock->blkd_time == 0) { snprintf(tmp, sizeof(tmp), ENTRY_GRNTD_FMT, lock->type == ENTRYLK_RDLCK ? "ENTRYLK_RDLCK" : "ENTRYLK_WRLCK", @@ -3238,7 +3698,7 @@ __dump_entrylks(pl_inode_t *pl_inode) lkowner_utoa(&lock->owner), lock->client, lock->connection_id, granted); } else { - gf_time_fmt(blocked, sizeof(blocked), lock->blkd_time.tv_sec, + gf_time_fmt(blocked, sizeof(blocked), lock->blkd_time, gf_timefmt_FT); snprintf(tmp, sizeof(tmp), ENTRY_BLKD_GRNTD_FMT, lock->type == ENTRYLK_RDLCK ? "ENTRYLK_RDLCK" @@ -3255,7 +3715,7 @@ __dump_entrylks(pl_inode_t *pl_inode) list_for_each_entry(lock, &dom->blocked_entrylks, blocked_locks) { - gf_time_fmt(blocked, sizeof(blocked), lock->blkd_time.tv_sec, + gf_time_fmt(blocked, sizeof(blocked), lock->blkd_time, gf_timefmt_FT); gf_proc_dump_build_key(key, k, "entrylk[%d](BLOCKED)", count); @@ -3307,9 +3767,8 @@ __dump_inodelks(pl_inode_t *pl_inode) SET_FLOCK_PID(&lock->user_flock, lock); pl_dump_lock(tmp, sizeof(tmp), &lock->user_flock, &lock->owner, - lock->client, lock->connection_id, - &lock->granted_time.tv_sec, &lock->blkd_time.tv_sec, - _gf_true); + lock->client, lock->connection_id, &lock->granted_time, + &lock->blkd_time, _gf_true); gf_proc_dump_write(key, "%s", tmp); count++; @@ -3321,8 +3780,8 @@ __dump_inodelks(pl_inode_t *pl_inode) count); SET_FLOCK_PID(&lock->user_flock, lock); pl_dump_lock(tmp, sizeof(tmp), &lock->user_flock, &lock->owner, - lock->client, lock->connection_id, 0, - &lock->blkd_time.tv_sec, _gf_false); + lock->client, lock->connection_id, 0, &lock->blkd_time, + _gf_false); gf_proc_dump_write(key, "%s", tmp); count++; @@ -3355,9 +3814,8 @@ __dump_posixlks(pl_inode_t *pl_inode) gf_proc_dump_build_key(key, "posixlk", "posixlk[%d](%s)", count, lock->blocked ? "BLOCKED" : "ACTIVE"); pl_dump_lock(tmp, sizeof(tmp), &lock->user_flock, &lock->owner, - lock->client, NULL, &lock->granted_time.tv_sec, - &lock->blkd_time.tv_sec, - (lock->blocked) ? _gf_false : _gf_true); + lock->client, lock->client_uid, &lock->granted_time, + &lock->blkd_time, (lock->blocked) ? _gf_false : _gf_true); gf_proc_dump_write(key, "%s", tmp); count++; @@ -3436,11 +3894,15 @@ unlock: __dump_inodelks(pl_inode); } - count = __get_posixlk_count(this, pl_inode); + count = __get_posixlk_count(pl_inode); if (count) { gf_proc_dump_write("posixlk-count", "%d", count); __dump_posixlks(pl_inode); } + + gf_proc_dump_write("links", "%d", pl_inode->links); + gf_proc_dump_write("removes_pending", "%u", pl_inode->remove_running); + gf_proc_dump_write("removed", "%u", pl_inode->removed); } pthread_mutex_unlock(&pl_inode->mutex); @@ -3549,9 +4011,9 @@ pl_metalk_client_cleanup(xlator_t *this, pl_ctx_t *ctx) * unwind all queued and blocked locks to check * migration status and find the correct * destination */ - __unwind_queued_locks(this, pl_inode, &tmp_posixlk_list); + __unwind_queued_locks(pl_inode, &tmp_posixlk_list); - __unwind_blocked_locks(this, pl_inode, &tmp_posixlk_list); + __unwind_blocked_locks(pl_inode, &tmp_posixlk_list); list_del_init(&meta_lock->list); @@ -3583,10 +4045,7 @@ unlock: static int pl_client_disconnect_cbk(xlator_t *this, client_t *client) { - pl_ctx_t *pl_ctx = NULL; - - pl_ctx = pl_ctx_get(client, this); - + pl_ctx_t *pl_ctx = pl_ctx_get(client, this); if (pl_ctx) { pl_inodelk_client_cleanup(this, pl_ctx); pl_entrylk_client_cleanup(this, pl_ctx); @@ -3623,10 +4082,9 @@ pl_client_destroy_cbk(xlator_t *this, client_t *client) int reconfigure(xlator_t *this, dict_t *options) { - posix_locks_private_t *priv = NULL; + posix_locks_private_t *priv = this->private; int ret = -1; - - priv = this->private; + char *tmp_str = NULL; GF_OPTION_RECONF("trace", priv->trace, options, bool, out); @@ -3648,6 +4106,20 @@ reconfigure(xlator_t *this, dict_t *options) GF_OPTION_RECONF("notify-contention-delay", priv->notify_contention_delay, options, uint32, out); + GF_OPTION_RECONF("mandatory-locking", tmp_str, options, str, out); + + GF_OPTION_RECONF("enforce-mandatory-lock", priv->mlock_enforced, options, + bool, out); + + if (!strcmp(tmp_str, "forced")) + priv->mandatory_mode = MLK_FORCED; + else if (!strcmp(tmp_str, "file")) + priv->mandatory_mode = MLK_FILE_BASED; + else if (!strcmp(tmp_str, "optimal")) + priv->mandatory_mode = MLK_OPTIMAL; + else + priv->mandatory_mode = MLK_NONE; + ret = 0; out: @@ -3695,6 +4167,7 @@ init(xlator_t *this) priv->mandatory_mode = MLK_OPTIMAL; else priv->mandatory_mode = MLK_NONE; + tmp_str = NULL; GF_OPTION_INIT("trace", priv->trace, bool, out); @@ -3714,6 +4187,8 @@ init(xlator_t *this) GF_OPTION_INIT("notify-contention-delay", priv->notify_contention_delay, uint32, out); + GF_OPTION_INIT("enforce-mandatory-lock", priv->mlock_enforced, bool, out); + this->local_pool = mem_pool_new(pl_local_t, 32); if (!this->local_pool) { ret = -1; @@ -3732,19 +4207,21 @@ out: return ret; } -int +void fini(xlator_t *this) { - posix_locks_private_t *priv = NULL; - - priv = this->private; + posix_locks_private_t *priv = this->private; if (!priv) - return 0; + return; this->private = NULL; + if (this->local_pool) { + mem_pool_destroy(this->local_pool); + this->local_pool = NULL; + } GF_FREE(priv->brickname); GF_FREE(priv); - return 0; + return; } int @@ -3771,8 +4248,11 @@ pl_rename_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, struct iatt *postoldparent, struct iatt *prenewparent, struct iatt *postnewparent, dict_t *xdata) { + pl_inode_remove_cbk(this, cookie, op_ret < 0 ? op_errno : 0); + PL_STACK_UNWIND(rename, xdata, frame, op_ret, op_errno, buf, preoldparent, postoldparent, prenewparent, postnewparent, xdata); + return 0; } @@ -3780,19 +4260,23 @@ int32_t pl_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, oldloc, newloc); + int32_t error; + + error = PL_INODE_REMOVE(rename, frame, this, oldloc, newloc, pl_rename, + pl_rename_cbk, oldloc, newloc, xdata); + if (error > 0) { + STACK_UNWIND_STRICT(rename, frame, -1, error, NULL, NULL, NULL, NULL, + NULL, NULL); + } - STACK_WIND(frame, pl_rename_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); return 0; } posix_lock_t * gf_lkmig_info_to_posix_lock(call_frame_t *frame, lock_migration_info_t *lmi) { - posix_lock_t *lock = NULL; - - lock = GF_CALLOC(1, sizeof(posix_lock_t), gf_locks_mt_posix_lock_t); + posix_lock_t *lock = GF_CALLOC(1, sizeof(posix_lock_t), + gf_locks_mt_posix_lock_t); if (!lock) goto out; @@ -3840,6 +4324,7 @@ pl_write_active_locks(call_frame_t *frame, pl_inode_t *pl_inode, /* Just making sure the activelk list is empty. Should not * happen though*/ if (!list_empty(&pl_inode->ext_list)) { + pthread_mutex_unlock(&pl_inode->mutex); gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "invalid locks found"); ret = -1; @@ -3848,6 +4333,7 @@ pl_write_active_locks(call_frame_t *frame, pl_inode_t *pl_inode, /* This list also should not be empty */ if (list_empty(&locklist->list)) { + pthread_mutex_unlock(&pl_inode->mutex); gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "empty lock list"); ret = -1; @@ -3858,6 +4344,7 @@ pl_write_active_locks(call_frame_t *frame, pl_inode_t *pl_inode, { newlock = gf_lkmig_info_to_posix_lock(frame, temp); if (!newlock) { + pthread_mutex_unlock(&pl_inode->mutex); gf_msg(THIS->name, GF_LOG_ERROR, 0, 0, "mem allocation failed for newlock"); @@ -3867,12 +4354,10 @@ pl_write_active_locks(call_frame_t *frame, pl_inode_t *pl_inode, list_add_tail(&newlock->list, &pl_inode->ext_list); } } - -out: /*TODO: What if few lock add failed with ENOMEM. Should the already * added locks be clearted */ pthread_mutex_unlock(&pl_inode->mutex); - +out: return ret; } @@ -3880,12 +4365,11 @@ static int pl_setactivelk(call_frame_t *frame, xlator_t *this, loc_t *loc, lock_migration_info_t *locklist, dict_t *xdata) { - pl_inode_t *pl_inode = NULL; int op_ret = 0; int op_errno = 0; int ret = 0; - pl_inode = pl_inode_get(this, loc->inode); + pl_inode_t *pl_inode = pl_inode_get(this, loc->inode, NULL); if (!pl_inode) { gf_msg(this->name, GF_LOG_ERROR, 0, 0, "pl_inode_get failed"); @@ -3908,8 +4392,11 @@ pl_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, dict_t *xdata) { + pl_inode_remove_cbk(this, cookie, op_ret < 0 ? op_errno : 0); + PL_STACK_UNWIND(unlink, xdata, frame, op_ret, op_errno, preparent, postparent, xdata); + return 0; } @@ -3917,9 +4404,14 @@ int32_t pl_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); - STACK_WIND(frame, pl_unlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); + int32_t error; + + error = PL_INODE_REMOVE(unlink, frame, this, loc, NULL, pl_unlink, + pl_unlink_cbk, loc, xflag, xdata); + if (error > 0) { + STACK_UNWIND_STRICT(unlink, frame, -1, error, NULL, NULL, NULL); + } + return 0; } @@ -3937,7 +4429,7 @@ int pl_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_mkdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); return 0; @@ -3955,7 +4447,7 @@ pl_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int pl_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_stat_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->stat, loc, xdata); return 0; @@ -3975,7 +4467,7 @@ int pl_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_mknod_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, xdata); return 0; @@ -3986,8 +4478,11 @@ pl_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, dict_t *xdata) { + pl_inode_remove_cbk(this, cookie, op_ret < 0 ? op_errno : 0); + PL_STACK_UNWIND_FOR_CLIENT(rmdir, xdata, frame, op_ret, op_errno, preparent, postparent, xdata); + return 0; } @@ -3995,9 +4490,14 @@ int pl_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflags, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); - STACK_WIND(frame, pl_rmdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rmdir, loc, xflags, xdata); + int32_t error; + + error = PL_INODE_REMOVE(rmdir, frame, this, loc, NULL, pl_rmdir, + pl_rmdir_cbk, loc, xflags, xdata); + if (error > 0) { + STACK_UNWIND_STRICT(rmdir, frame, -1, error, NULL, NULL, NULL); + } + return 0; } @@ -4016,7 +4516,7 @@ int pl_symlink(call_frame_t *frame, xlator_t *this, const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_symlink_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->symlink, linkname, loc, umask, xdata); return 0; @@ -4027,6 +4527,19 @@ pl_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, dict_t *xdata) { + pl_inode_t *pl_inode = (pl_inode_t *)cookie; + + if (op_ret >= 0) { + pthread_mutex_lock(&pl_inode->mutex); + + /* TODO: can happen pl_inode->links == 0 ? */ + if (pl_inode->links >= 0) { + pl_inode->links++; + } + + pthread_mutex_unlock(&pl_inode->mutex); + } + PL_STACK_UNWIND_FOR_CLIENT(link, xdata, frame, op_ret, op_errno, inode, buf, preparent, postparent, xdata); return 0; @@ -4036,9 +4549,18 @@ int pl_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, oldloc, newloc); - STACK_WIND(frame, pl_link_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); + pl_inode_t *pl_inode; + + pl_inode = pl_inode_get(this, oldloc->inode, NULL); + if (pl_inode == NULL) { + STACK_UNWIND_STRICT(link, frame, -1, ENOMEM, NULL, NULL, NULL, NULL, + NULL); + return 0; + } + + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), oldloc, newloc); + STACK_WIND_COOKIE(frame, pl_link_cbk, pl_inode, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); return 0; } @@ -4112,7 +4634,7 @@ pl_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int pl_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_statfs_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->statfs, loc, xdata); return 0; @@ -4122,6 +4644,28 @@ int32_t pl_removexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { + pl_local_t *local = NULL; + pl_inode_t *pl_inode = NULL; + + local = frame->local; + if (local && local->update_mlock_enforced_flag && op_ret != -1) { + pl_inode = pl_inode_get(this, local->inode, NULL); + if (!pl_inode) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + + pthread_mutex_lock(&pl_inode->mutex); + { + pl_inode->mlock_enforced = _gf_false; + pl_inode->check_mlock_info = _gf_false; + pl_inode->track_fop_wind_count = _gf_true; + } + pthread_mutex_unlock(&pl_inode->mutex); + } + +unwind: PL_STACK_UNWIND_FOR_CLIENT(removexattr, xdata, frame, op_ret, op_errno, xdata); return 0; @@ -4131,16 +4675,51 @@ int pl_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + int op_ret = 0; + int op_errno = EINVAL; + posix_locks_private_t *priv = this->private; + + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); + + PL_CHECK_LOCK_ENFORCE_KEY(frame, ((dict_t *)NULL), name, this, loc, + ((fd_t *)NULL), priv); + STACK_WIND(frame, pl_removexattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); return 0; + +unwind: + PL_STACK_UNWIND_FOR_CLIENT(removexattr, xdata, frame, op_ret, op_errno, + NULL); + + return 0; } int32_t pl_fremovexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { + pl_local_t *local = NULL; + pl_inode_t *pl_inode = NULL; + + local = frame->local; + if (local && local->update_mlock_enforced_flag && op_ret != -1) { + pl_inode = pl_inode_get(this, local->inode, NULL); + if (!pl_inode) { + op_ret = -1; + op_errno = ENOMEM; + goto unwind; + } + + pthread_mutex_lock(&pl_inode->mutex); + { + pl_inode->mlock_enforced = _gf_false; + pl_inode->check_mlock_info = _gf_false; + } + pthread_mutex_unlock(&pl_inode->mutex); + } + +unwind: PL_STACK_UNWIND_FOR_CLIENT(fremovexattr, xdata, frame, op_ret, op_errno, xdata); return 0; @@ -4150,10 +4729,23 @@ int pl_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata) { + int op_ret = -1; + int op_errno = EINVAL; + posix_locks_private_t *priv = this->private; + PL_LOCAL_GET_REQUESTS(frame, this, xdata, fd, NULL, NULL); + + PL_CHECK_LOCK_ENFORCE_KEY(frame, ((dict_t *)NULL), name, this, + ((loc_t *)NULL), fd, priv); + STACK_WIND(frame, pl_fremovexattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); return 0; + +unwind: + PL_STACK_UNWIND_FOR_CLIENT(fremovexattr, xdata, frame, op_ret, op_errno, + NULL); + return 0; } int32_t @@ -4189,7 +4781,7 @@ int pl_xattrop(call_frame_t *frame, xlator_t *this, loc_t *loc, gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_xattrop_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->xattrop, loc, optype, xattr, xdata); return 0; @@ -4228,7 +4820,7 @@ int pl_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_setattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setattr, loc, stbuf, valid, xdata); return 0; @@ -4289,7 +4881,7 @@ int pl_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_readlink_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->readlink, loc, size, xdata); return 0; @@ -4307,7 +4899,7 @@ int pl_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, dict_t *xdata) { - PL_LOCAL_GET_REQUESTS(frame, this, xdata, NULL, loc, NULL); + PL_LOCAL_GET_REQUESTS(frame, this, xdata, ((fd_t *)NULL), loc, NULL); STACK_WIND(frame, pl_access_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->access, loc, mask, xdata); return 0; @@ -4456,7 +5048,7 @@ struct volume_options options[] = { "be used in conjunction w/ revocation-clear-all."}, {.key = {"notify-contention"}, .type = GF_OPTION_TYPE_BOOL, - .default_value = "no", + .default_value = "yes", .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC, .op_version = {GD_OP_VERSION_4_0_0}, .tags = {"locks", "contention"}, @@ -4479,5 +5071,25 @@ struct volume_options options[] = { "on the same inode. If multiple lock requests are " "received during this period, only one upcall will " "be sent."}, + {.key = {"enforce-mandatory-lock"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .flags = OPT_FLAG_SETTABLE, + .op_version = {GD_OP_VERSION_6_0}, + .description = "option to enable lock enforcement"}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .dumpops = &dumpops, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "locks", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/locks/src/reservelk.c b/xlators/features/locks/src/reservelk.c index 8b080dba030..604691fd887 100644 --- a/xlators/features/locks/src/reservelk.c +++ b/xlators/features/locks/src/reservelk.c @@ -7,12 +7,12 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" -#include "list.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> +#include <glusterfs/list.h> #include "locks.h" #include "common.h" @@ -31,12 +31,10 @@ reservelks_equal(posix_lock_t *l1, posix_lock_t *l2) static posix_lock_t * __reservelk_grantable(pl_inode_t *pl_inode, posix_lock_t *lock) { - xlator_t *this = NULL; + xlator_t *this = THIS; posix_lock_t *l = NULL; posix_lock_t *ret_lock = NULL; - this = THIS; - if (list_empty(&pl_inode->reservelk_list)) { gf_log(this->name, GF_LOG_TRACE, "No reservelks in list"); goto out; @@ -82,10 +80,9 @@ __matching_reservelk(pl_inode_t *pl_inode, posix_lock_t *lock) static int __reservelk_conflict(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock) { - posix_lock_t *conf = NULL; int ret = 0; - conf = __matching_reservelk(pl_inode, lock); + posix_lock_t *conf = __matching_reservelk(pl_inode, lock); if (conf) { gf_log(this->name, GF_LOG_TRACE, "Matching reservelk found"); if (__same_owner_reservelk(lock, conf)) { @@ -104,29 +101,28 @@ __reservelk_conflict(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock) int pl_verify_reservelk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, - int can_block) + const int can_block) { int ret = 0; pthread_mutex_lock(&pl_inode->mutex); { if (__reservelk_conflict(this, pl_inode, lock)) { + lock->blocked = can_block; + list_add_tail(&lock->list, &pl_inode->blocked_calls); + pthread_mutex_unlock(&pl_inode->mutex); gf_log(this->name, GF_LOG_TRACE, "Found conflicting reservelk. Blocking until reservelk is " "unlocked."); - lock->blocked = can_block; - list_add_tail(&lock->list, &pl_inode->blocked_calls); ret = -1; - goto unlock; + goto out; } - - gf_log(this->name, GF_LOG_TRACE, - "no conflicting reservelk found. Call continuing"); - ret = 0; } -unlock: pthread_mutex_unlock(&pl_inode->mutex); - + gf_log(this->name, GF_LOG_TRACE, + "no conflicting reservelk found. Call continuing"); + ret = 0; +out: return ret; } @@ -135,12 +131,11 @@ unlock: */ static int __lock_reservelk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, - int can_block) + const int can_block) { - posix_lock_t *conf = NULL; int ret = -EINVAL; - conf = __reservelk_grantable(pl_inode, lock); + posix_lock_t *conf = __reservelk_grantable(pl_inode, lock); if (conf) { ret = -EAGAIN; if (can_block == 0) @@ -183,9 +178,7 @@ find_matching_reservelk(posix_lock_t *lock, pl_inode_t *pl_inode) static posix_lock_t * __reserve_unlock_lock(xlator_t *this, posix_lock_t *lock, pl_inode_t *pl_inode) { - posix_lock_t *conf = NULL; - - conf = find_matching_reservelk(lock, pl_inode); + posix_lock_t *conf = find_matching_reservelk(lock, pl_inode); if (!conf) { gf_log(this->name, GF_LOG_DEBUG, " Matching lock not found for unlock"); goto out; @@ -319,8 +312,6 @@ grant_blocked_lock_calls(xlator_t *this, pl_inode_t *pl_inode) ret = pl_setlk(this, pl_inode, lock, can_block); if (ret == -1) { if (can_block) { - pl_trace_block(this, lock->frame, fd, NULL, cmd, - &lock->user_flock, NULL); continue; } else { gf_log(this->name, GF_LOG_DEBUG, "returning EAGAIN"); @@ -345,6 +336,7 @@ pl_reserve_unlock(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock) { retlock = __reserve_unlock_lock(this, lock, pl_inode); if (!retlock) { + pthread_mutex_unlock(&pl_inode->mutex); gf_log(this->name, GF_LOG_DEBUG, "Bad Unlock issued on Inode lock"); ret = -EINVAL; goto out; @@ -354,9 +346,8 @@ pl_reserve_unlock(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock) __destroy_lock(retlock); ret = 0; } -out: pthread_mutex_unlock(&pl_inode->mutex); - +out: grant_blocked_reserve_locks(this, pl_inode); grant_blocked_lock_calls(this, pl_inode); @@ -372,19 +363,20 @@ pl_reserve_setlk(xlator_t *this, pl_inode_t *pl_inode, posix_lock_t *lock, pthread_mutex_lock(&pl_inode->mutex); { ret = __lock_reservelk(this, pl_inode, lock, can_block); - if (ret < 0) - gf_log(this->name, GF_LOG_TRACE, - "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => NOK", - lock->fl_type == F_UNLCK ? "Unlock" : "Lock", - lock->client_pid, lkowner_utoa(&lock->owner), - lock->user_flock.l_start, lock->user_flock.l_len); - else - gf_log(this->name, GF_LOG_TRACE, - "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => OK", - lock->fl_type == F_UNLCK ? "Unlock" : "Lock", - lock->client_pid, lkowner_utoa(&lock->owner), lock->fl_start, - lock->fl_end); } pthread_mutex_unlock(&pl_inode->mutex); + + if (ret < 0) + gf_log(this->name, GF_LOG_TRACE, + "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => NOK", + lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, + lkowner_utoa(&lock->owner), lock->user_flock.l_start, + lock->user_flock.l_len); + else + gf_log(this->name, GF_LOG_TRACE, + "%s (pid=%d) (lk-owner=%s) %" PRId64 " - %" PRId64 " => OK", + lock->fl_type == F_UNLCK ? "Unlock" : "Lock", lock->client_pid, + lkowner_utoa(&lock->owner), lock->fl_start, lock->fl_end); + return ret; } diff --git a/xlators/features/locks/tests/unit-test.c b/xlators/features/locks/tests/unit-test.c index c4759bd4a5f..d285b12b5aa 100644 --- a/xlators/features/locks/tests/unit-test.c +++ b/xlators/features/locks/tests/unit-test.c @@ -7,12 +7,12 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" -#include "list.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> +#include <glusterfs/list.h> #include "locks.h" #include "common.h" diff --git a/xlators/features/marker/src/marker-common.c b/xlators/features/marker/src/marker-common.c index 4989efb13d6..9c9047005d6 100644 --- a/xlators/features/marker/src/marker-common.c +++ b/xlators/features/marker/src/marker-common.c @@ -55,10 +55,3 @@ unlock: return ret; } - -int -marker_filter_quota_xattr(dict_t *dict, char *key, data_t *value, void *data) -{ - dict_del(dict, key); - return 0; -} diff --git a/xlators/features/marker/src/marker-common.h b/xlators/features/marker/src/marker-common.h index 449d55b5ef0..7f8cffe7d35 100644 --- a/xlators/features/marker/src/marker-common.h +++ b/xlators/features/marker/src/marker-common.h @@ -10,12 +10,10 @@ #ifndef _MARKER_COMMON_H #define _MARKER_COMMON_H -#include "xlator.h" +#include <glusterfs/xlator.h> #include "marker.h" int32_t marker_force_inode_ctx_get(inode_t *, xlator_t *, marker_inode_ctx_t **); -int -marker_filter_quota_xattr(dict_t *, char *, data_t *, void *); #endif diff --git a/xlators/features/marker/src/marker-mem-types.h b/xlators/features/marker/src/marker-mem-types.h index 7d590d7ec84..aedfdb4a1b7 100644 --- a/xlators/features/marker/src/marker-mem-types.h +++ b/xlators/features/marker/src/marker-mem-types.h @@ -10,9 +10,10 @@ #ifndef __MARKER_MEM_TYPES_H__ #define __MARKER_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_marker_mem_types_ { + /* Those are used by ALLOCATE_OR_GOTO macro */ gf_marker_mt_marker_conf_t = gf_common_mt_end + 1, gf_marker_mt_loc_t, gf_marker_mt_volume_mark, diff --git a/xlators/features/marker/src/marker-quota-helper.c b/xlators/features/marker/src/marker-quota-helper.c index 694493c778c..ecd85d67b2b 100644 --- a/xlators/features/marker/src/marker-quota-helper.c +++ b/xlators/features/marker/src/marker-quota-helper.c @@ -7,7 +7,7 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "locking.h" +#include <glusterfs/locking.h> #include "marker-quota.h" #include "marker-common.h" #include "marker-quota-helper.h" @@ -378,96 +378,3 @@ mq_inode_ctx_new(inode_t *inode, xlator_t *this) { return __mq_inode_ctx_new(inode, this); } - -quota_local_t * -mq_local_new() -{ - quota_local_t *local = NULL; - - local = mem_get0(THIS->local_pool); - if (!local) - goto out; - - local->ref = 1; - LOCK_INIT(&local->lock); - - local->ctx = NULL; - local->contri = NULL; - -out: - return local; -} - -quota_local_t * -mq_local_ref(quota_local_t *local) -{ - LOCK(&local->lock); - { - local->ref++; - } - UNLOCK(&local->lock); - - return local; -} - -int32_t -mq_local_unref(xlator_t *this, quota_local_t *local) -{ - int32_t ref = 0; - if (local == NULL) - goto out; - - QUOTA_SAFE_DECREMENT(&local->lock, local->ref, ref); - - if (ref != 0) - goto out; - - if (local->fd != NULL) - fd_unref(local->fd); - - if (local->contri) - GF_REF_PUT(local->contri); - - if (local->xdata) - dict_unref(local->xdata); - - loc_wipe(&local->loc); - - loc_wipe(&local->parent_loc); - - LOCK_DESTROY(&local->lock); - - mem_put(local); -out: - return 0; -} - -inode_contribution_t * -mq_get_contribution_from_loc(xlator_t *this, loc_t *loc) -{ - int32_t ret = 0; - quota_inode_ctx_t *ctx = NULL; - inode_contribution_t *contribution = NULL; - - ret = mq_inode_ctx_get(loc->inode, this, &ctx); - if (ret < 0) { - gf_log_callingfn(this->name, GF_LOG_WARNING, - "cannot get marker-quota context from inode " - "(gfid:%s, path:%s)", - uuid_utoa(loc->inode->gfid), loc->path); - goto err; - } - - contribution = mq_get_contribution_node(loc->parent, ctx); - if (contribution == NULL) { - gf_log_callingfn(this->name, GF_LOG_WARNING, - "inode (gfid:%s, path:%s) has " - "no contribution towards parent (gfid:%s)", - uuid_utoa(loc->inode->gfid), loc->path, - uuid_utoa(loc->parent->gfid)); - goto err; - } - -err: - return contribution; -} diff --git a/xlators/features/marker/src/marker-quota-helper.h b/xlators/features/marker/src/marker-quota-helper.h index 99723def1b9..d4091dd2180 100644 --- a/xlators/features/marker/src/marker-quota-helper.h +++ b/xlators/features/marker/src/marker-quota-helper.h @@ -57,22 +57,10 @@ mq_delete_contribution_node(dict_t *, char *, inode_contribution_t *); int32_t mq_inode_loc_fill(const char *, inode_t *, loc_t *); -quota_local_t * -mq_local_new(); - -quota_local_t * -mq_local_ref(quota_local_t *); - -int32_t -mq_local_unref(xlator_t *, quota_local_t *); - inode_contribution_t * mq_contri_init(inode_t *inode); inode_contribution_t * mq_get_contribution_node(inode_t *, quota_inode_ctx_t *); -inode_contribution_t * -mq_get_contribution_from_loc(xlator_t *this, loc_t *loc); - #endif diff --git a/xlators/features/marker/src/marker-quota.c b/xlators/features/marker/src/marker-quota.c index c680bc9a475..3de2ea1c92c 100644 --- a/xlators/features/marker/src/marker-quota.c +++ b/xlators/features/marker/src/marker-quota.c @@ -7,16 +7,16 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "dict.h" -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "libxlator.h" -#include "common-utils.h" -#include "byte-order.h" +#include <glusterfs/common-utils.h> +#include <glusterfs/byte-order.h> #include "marker-quota.h" #include "marker-quota-helper.h" -#include "syncop.h" -#include "quota-common-utils.h" +#include <glusterfs/syncop.h> +#include <glusterfs/quota-common-utils.h> int mq_loc_copy(loc_t *dst, loc_t *src) @@ -134,27 +134,14 @@ out: return -1; } -int32_t +static void mq_set_ctx_dirty_status(quota_inode_ctx_t *ctx, gf_boolean_t status) { GF_VALIDATE_OR_GOTO("marker", ctx, out); mq_set_ctx_status(ctx, &ctx->dirty_status, status); - return 0; -out: - return -1; -} - -int32_t -mq_test_and_set_ctx_dirty_status(quota_inode_ctx_t *ctx, gf_boolean_t *status) -{ - GF_VALIDATE_OR_GOTO("marker", ctx, out); - GF_VALIDATE_OR_GOTO("marker", status, out); - - mq_test_and_set_ctx_status(ctx, &ctx->dirty_status, status); - return 0; out: - return -1; + return; } int @@ -286,8 +273,8 @@ out: * This function returns success even is inode-quota xattrs are missing and * hence no healing performed. */ -int32_t -_quota_dict_get_meta(xlator_t *this, dict_t *dict, char *key, +static int32_t +_quota_dict_get_meta(xlator_t *this, dict_t *dict, char *key, const int keylen, quota_meta_t *meta, ia_type_t ia_type, gf_boolean_t add_delta) { @@ -296,7 +283,7 @@ _quota_dict_get_meta(xlator_t *this, dict_t *dict, char *key, priv = this->private; - ret = quota_dict_get_inode_meta(dict, key, meta); + ret = quota_dict_get_inode_meta(dict, key, keylen, meta); if (ret == -2 && (priv->feature_enabled & GF_INODE_QUOTA) == 0) { /* quota_dict_get_inode_meta returns -2 if * inode quota xattrs are not present. @@ -430,13 +417,15 @@ mq_are_xattrs_set(xlator_t *this, loc_t *loc, gf_boolean_t *contri_set, *contri_set = _gf_true; *size_set = _gf_true; if (loc->inode->ia_type == IA_IFDIR) { - ret = quota_dict_get_inode_meta(rsp_dict, size_key, &meta); + ret = quota_dict_get_inode_meta(rsp_dict, size_key, strlen(size_key), + &meta); if (ret < 0 || meta.dir_count == 0) *size_set = _gf_false; } if (!loc_is_root(loc)) { - ret = quota_dict_get_inode_meta(rsp_dict, contri_key, &meta); + ret = quota_dict_get_inode_meta(rsp_dict, contri_key, + strlen(contri_key), &meta); if (ret < 0) *contri_set = _gf_false; } @@ -726,6 +715,7 @@ _mq_get_metadata(xlator_t *this, loc_t *loc, quota_meta_t *contri, char size_key[QUOTA_KEY_MAX] = { 0, }; + int keylen = 0; dict_t *dict = NULL; dict_t *rsp_dict = NULL; struct iatt stbuf = { @@ -745,8 +735,8 @@ _mq_get_metadata(xlator_t *this, loc_t *loc, quota_meta_t *contri, } if (size && loc->inode->ia_type == IA_IFDIR) { - GET_SIZE_KEY(this, size_key, ret); - if (ret < 0) + GET_SIZE_KEY(this, size_key, keylen); + if (keylen < 0) goto out; ret = dict_set_int64(dict, size_key, 0); if (ret < 0) { @@ -775,7 +765,7 @@ _mq_get_metadata(xlator_t *this, loc_t *loc, quota_meta_t *contri, if (size) { if (loc->inode->ia_type == IA_IFDIR) { - ret = quota_dict_get_meta(rsp_dict, size_key, &meta); + ret = quota_dict_get_meta(rsp_dict, size_key, keylen, &meta); if (ret < 0) { gf_log(this->name, GF_LOG_ERROR, "dict_get failed."); goto out; @@ -792,7 +782,8 @@ _mq_get_metadata(xlator_t *this, loc_t *loc, quota_meta_t *contri, } if (contri && !loc_is_root(loc)) { - ret = quota_dict_get_meta(rsp_dict, contri_key, &meta); + ret = quota_dict_get_meta(rsp_dict, contri_key, strlen(contri_key), + &meta); if (ret < 0) { contri->size = 0; contri->file_count = 0; @@ -862,19 +853,6 @@ out: } int32_t -mq_get_size(xlator_t *this, loc_t *loc, quota_meta_t *size) -{ - return _mq_get_metadata(this, loc, NULL, size, 0); -} - -int32_t -mq_get_contri(xlator_t *this, loc_t *loc, quota_meta_t *contri, - uuid_t contri_gfid) -{ - return _mq_get_metadata(this, loc, contri, NULL, contri_gfid); -} - -int32_t mq_get_delta(xlator_t *this, loc_t *loc, quota_meta_t *delta, quota_inode_ctx_t *ctx, inode_contribution_t *contribution) { @@ -1333,19 +1311,6 @@ out: return ret; } -int -mq_create_xattrs_blocking_txn(xlator_t *this, loc_t *loc, struct iatt *buf) -{ - int32_t ret = -1; - - GF_VALIDATE_OR_GOTO("marker", loc, out); - GF_VALIDATE_OR_GOTO("marker", loc->inode, out); - - ret = _mq_create_xattrs_txn(this, loc, buf, _gf_false); -out: - return ret; -} - int32_t mq_reduce_parent_size_task(void *opaque) { @@ -1748,21 +1713,17 @@ mq_initiate_quota_task(void *opaque) } out: - if (dirty) { - if (ret < 0) { - /* On failure clear dirty status flag. - * In the next lookup inspect_directory_xattr - * can set the status flag and fix the - * dirty directory. - * Do the same if the dir was dirty before - * txn - */ - ret = mq_inode_ctx_get(parent_loc.inode, this, &parent_ctx); - if (ret == 0) - mq_set_ctx_dirty_status(parent_ctx, _gf_false); - } else { - ret = mq_mark_dirty(this, &parent_loc, 0); - } + if ((dirty) && (ret < 0)) { + /* On failure clear dirty status flag. + * In the next lookup inspect_directory_xattr + * can set the status flag and fix the + * dirty directory. + * Do the same if the dir was dirty before + * txn + */ + ret = mq_inode_ctx_get(parent_loc.inode, this, &parent_ctx); + if (ret == 0) + mq_set_ctx_dirty_status(parent_ctx, _gf_false); } if (locked) @@ -1876,6 +1837,7 @@ mq_update_dirty_inode_task(void *opaque) char contri_key[QUOTA_KEY_MAX] = { 0, }; + int keylen = 0; GF_ASSERT(opaque); @@ -1889,9 +1851,11 @@ mq_update_dirty_inode_task(void *opaque) if (ret < 0) goto out; - GET_CONTRI_KEY(this, contri_key, loc->gfid, ret); - if (ret < 0) + GET_CONTRI_KEY(this, contri_key, loc->gfid, keylen); + if (keylen < 0) { + ret = keylen; goto out; + } xdata = dict_new(); if (xdata == NULL) { @@ -1958,7 +1922,7 @@ mq_update_dirty_inode_task(void *opaque) continue; memset(&contri, 0, sizeof(contri)); - quota_dict_get_meta(entry->dict, contri_key, &contri); + quota_dict_get_meta(entry->dict, contri_key, keylen, &contri); if (quota_meta_is_null(&contri)) continue; @@ -1970,7 +1934,7 @@ mq_update_dirty_inode_task(void *opaque) /* Inculde for self */ contri_sum.dir_count++; - ret = mq_get_size(this, loc, &size); + ret = _mq_get_metadata(this, loc, NULL, &size, 0); if (ret < 0) goto out; @@ -2039,8 +2003,8 @@ mq_update_dirty_inode_txn(xlator_t *this, loc_t *loc, quota_inode_ctx_t *ctx) GF_VALIDATE_OR_GOTO("marker", loc, out); GF_VALIDATE_OR_GOTO("marker", loc->inode, out); - ret = mq_test_and_set_ctx_dirty_status(ctx, &status); - if (ret < 0 || status == _gf_true) + mq_test_and_set_ctx_status(ctx, &ctx->dirty_status, &status); + if (status == _gf_true) goto out; ret = mq_synctask(this, mq_update_dirty_inode_task, _gf_true, loc); @@ -2054,7 +2018,7 @@ out: int32_t mq_inspect_directory_xattr(xlator_t *this, quota_inode_ctx_t *ctx, inode_contribution_t *contribution, loc_t *loc, - dict_t *dict, struct iatt buf) + dict_t *dict) { int32_t ret = -1; int8_t dirty = -1; @@ -2073,6 +2037,7 @@ mq_inspect_directory_xattr(xlator_t *this, quota_inode_ctx_t *ctx, char size_key[QUOTA_KEY_MAX] = { 0, }; + int keylen = 0; gf_boolean_t status = _gf_false; ret = dict_get_int8(dict, QUOTA_DIRTY_KEY, &dirty); @@ -2084,21 +2049,27 @@ mq_inspect_directory_xattr(xlator_t *this, quota_inode_ctx_t *ctx, dirty = 0; } - GET_SIZE_KEY(this, size_key, ret); - if (ret < 0) + GET_SIZE_KEY(this, size_key, keylen); + if (keylen < 0) { + ret = -1; goto out; - ret = _quota_dict_get_meta(this, dict, size_key, &size, IA_IFDIR, + } + ret = _quota_dict_get_meta(this, dict, size_key, keylen, &size, IA_IFDIR, _gf_false); if (ret < 0) goto create_xattr; + if (!contribution) + goto create_xattr; + if (!loc_is_root(loc)) { - GET_CONTRI_KEY(this, contri_key, contribution->gfid, ret); - if (ret < 0) + GET_CONTRI_KEY(this, contri_key, contribution->gfid, keylen); + if (keylen < 0) { + ret = -1; goto out; - - ret = _quota_dict_get_meta(this, dict, contri_key, &contri, IA_IFDIR, - _gf_false); + } + ret = _quota_dict_get_meta(this, dict, contri_key, keylen, &contri, + IA_IFDIR, _gf_false); if (ret < 0) goto create_xattr; @@ -2151,7 +2122,7 @@ out: int32_t mq_inspect_file_xattr(xlator_t *this, quota_inode_ctx_t *ctx, inode_contribution_t *contribution, loc_t *loc, - dict_t *dict, struct iatt buf) + dict_t *dict, struct iatt *buf) { int32_t ret = -1; quota_meta_t size = { @@ -2166,11 +2137,15 @@ mq_inspect_file_xattr(xlator_t *this, quota_inode_ctx_t *ctx, char contri_key[QUOTA_KEY_MAX] = { 0, }; + int keylen = 0; gf_boolean_t status = _gf_false; + if (!buf || !contribution || !ctx) + goto out; + LOCK(&ctx->lock); { - ctx->size = 512 * buf.ia_blocks; + ctx->size = 512 * buf->ia_blocks; ctx->file_count = 1; ctx->dir_count = 0; @@ -2180,12 +2155,14 @@ mq_inspect_file_xattr(xlator_t *this, quota_inode_ctx_t *ctx, } UNLOCK(&ctx->lock); - GET_CONTRI_KEY(this, contri_key, contribution->gfid, ret); - if (ret < 0) + GET_CONTRI_KEY(this, contri_key, contribution->gfid, keylen); + if (keylen < 0) { + ret = -1; goto out; + } - ret = _quota_dict_get_meta(this, dict, contri_key, &contri, IA_IFREG, - _gf_true); + ret = _quota_dict_get_meta(this, dict, contri_key, keylen, &contri, + IA_IFREG, _gf_true); if (ret < 0) { ret = mq_create_xattrs_txn(this, loc, NULL); } else { @@ -2215,7 +2192,8 @@ out: } int32_t -mq_xattr_state(xlator_t *this, loc_t *origin_loc, dict_t *dict, struct iatt buf) +mq_xattr_state(xlator_t *this, loc_t *origin_loc, dict_t *dict, + struct iatt *buf) { int32_t ret = -1; quota_inode_ctx_t *ctx = NULL; @@ -2224,7 +2202,7 @@ mq_xattr_state(xlator_t *this, loc_t *origin_loc, dict_t *dict, struct iatt buf) }; inode_contribution_t *contribution = NULL; - ret = mq_prevalidate_txn(this, origin_loc, &loc, &ctx, &buf); + ret = mq_prevalidate_txn(this, origin_loc, &loc, &ctx, buf); if (ret < 0 || loc.parent == NULL) goto out; @@ -2239,13 +2217,12 @@ mq_xattr_state(xlator_t *this, loc_t *origin_loc, dict_t *dict, struct iatt buf) ret = -1; goto out; } - if (buf.ia_type == IA_IFDIR) - mq_inspect_directory_xattr(this, ctx, contribution, &loc, dict, - buf); + if (buf->ia_type == IA_IFDIR) + mq_inspect_directory_xattr(this, ctx, contribution, &loc, dict); else mq_inspect_file_xattr(this, ctx, contribution, &loc, dict, buf); } else { - mq_inspect_directory_xattr(this, ctx, 0, &loc, dict, buf); + mq_inspect_directory_xattr(this, ctx, 0, &loc, dict); } out: diff --git a/xlators/features/marker/src/marker-quota.h b/xlators/features/marker/src/marker-quota.h index 7f63e268203..4bbf6878b22 100644 --- a/xlators/features/marker/src/marker-quota.h +++ b/xlators/features/marker/src/marker-quota.h @@ -10,11 +10,11 @@ #ifndef _MARKER_QUOTA_H #define _MARKER_QUOTA_H -#include "xlator.h" +#include <glusterfs/xlator.h> #include "marker-mem-types.h" -#include "refcount.h" -#include "quota-common-utils.h" -#include "call-stub.h" +#include <glusterfs/refcount.h> +#include <glusterfs/quota-common-utils.h> +#include <glusterfs/call-stub.h> #define QUOTA_XATTR_PREFIX "trusted.glusterfs" #define QUOTA_DIRTY_KEY "trusted.glusterfs.quota.dirty" @@ -23,15 +23,6 @@ #define QUOTA_KEY_MAX 512 #define READDIR_BUF 4096 -#define QUOTA_STACK_DESTROY(_frame, _this) \ - do { \ - quota_local_t *_local = NULL; \ - _local = _frame->local; \ - _frame->local = NULL; \ - STACK_DESTROY(_frame->root); \ - mq_local_unref(_this, _local); \ - } while (0) - #define QUOTA_ALLOC(var, type, ret) \ do { \ ret = 0; \ @@ -129,7 +120,7 @@ int32_t mq_req_xattr(xlator_t *, loc_t *, dict_t *, char *, char *); int32_t -mq_xattr_state(xlator_t *, loc_t *, dict_t *, struct iatt); +mq_xattr_state(xlator_t *, loc_t *, dict_t *, struct iatt *); int mq_initiate_quota_txn(xlator_t *, loc_t *, struct iatt *); diff --git a/xlators/features/marker/src/marker.c b/xlators/features/marker/src/marker.c index d3abd4b0b5b..1375ccc498c 100644 --- a/xlators/features/marker/src/marker.c +++ b/xlators/features/marker/src/marker.c @@ -7,17 +7,17 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "libxlator.h" #include "marker.h" #include "marker-mem-types.h" #include "marker-quota.h" #include "marker-quota-helper.h" #include "marker-common.h" -#include "byte-order.h" -#include "syncop.h" -#include "syscall.h" +#include <glusterfs/byte-order.h> +#include <glusterfs/syncop.h> +#include <glusterfs/syscall.h> #include <fnmatch.h> @@ -242,24 +242,19 @@ out: return ret; } -int32_t +void marker_error_handler(xlator_t *this, marker_local_t *local, int32_t op_errno) { - marker_conf_t *priv = NULL; - const char *path = NULL; - - priv = (marker_conf_t *)this->private; - path = local ? (local->loc.path ? local->loc.path - : uuid_utoa(local->loc.gfid)) - : "<nul>"; + marker_conf_t *priv = (marker_conf_t *)this->private; + const char *path = local ? ((local->loc.path) ? local->loc.path + : uuid_utoa(local->loc.gfid)) + : "<nul>"; gf_log(this->name, GF_LOG_CRITICAL, "Indexing gone corrupt at %s (reason: %s)." " Geo-replication slave content needs to be revalidated", path, strerror(op_errno)); sys_unlink(priv->timestamp_file); - - return 0; } int32_t @@ -567,24 +562,21 @@ marker_specific_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { int32_t ret = 0; - int32_t done = 0; + int32_t done = 1; marker_local_t *local = NULL; local = (marker_local_t *)frame->local; if (op_ret == -1 && op_errno == ENOSPC) { marker_error_handler(this, local, op_errno); - done = 1; goto out; } if (local) { if (local->loc.path && strcmp(local->loc.path, "/") == 0) { - done = 1; goto out; } if (__is_root_gfid(local->loc.gfid)) { - done = 1; goto out; } } @@ -595,14 +587,11 @@ marker_specific_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, gf_log(this->name, GF_LOG_DEBUG, "Error occurred " "while traversing to the parent, stopping marker"); - - done = 1; - goto out; } marker_start_setxattr(frame, this); - + done = 0; out: if (done) { marker_setxattr_done(frame); @@ -1521,7 +1510,7 @@ marker_do_rename(call_frame_t *frame, void *cookie, xlator_t *this, char contri_key[QUOTA_KEY_MAX] = { 0, }; - int32_t ret = 0; + int keylen = 0; quota_meta_t contribution = { 0, }; @@ -1543,12 +1532,12 @@ marker_do_rename(call_frame_t *frame, void *cookie, xlator_t *this, goto err; } - GET_CONTRI_KEY(this, contri_key, oplocal->loc.parent->gfid, ret); - if (ret < 0) { + GET_CONTRI_KEY(this, contri_key, oplocal->loc.parent->gfid, keylen); + if (keylen < 0) { local->err = errno ? errno : ENOMEM; goto err; } - quota_dict_get_meta(dict, contri_key, &contribution); + quota_dict_get_meta(dict, contri_key, keylen, &contribution); oplocal->contribution = contribution; STACK_WIND(frame, marker_rename_cbk, FIRST_CHILD(this), @@ -2966,7 +2955,7 @@ unwind: gf_uuid_copy(local->loc.gfid, buf->ia_gfid); if (priv->feature_enabled & GF_QUOTA) { - mq_xattr_state(this, &local->loc, dict, *buf); + mq_xattr_state(this, &local->loc, dict, buf); } out: @@ -3118,7 +3107,7 @@ marker_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, "failed for %s", uuid_utoa(loc.inode->gfid)); - mq_xattr_state(this, &loc, entry->dict, entry->d_stat); + mq_xattr_state(this, &loc, entry->dict, &entry->d_stat); loc_wipe(&loc); ret = marker_key_set_ver(this, entry->dict); @@ -3564,3 +3553,16 @@ struct volume_options options[] = { .flags = OPT_FLAG_NONE, }, {.key = {NULL}}}; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "marker", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/marker/src/marker.h b/xlators/features/marker/src/marker.h index 3b6f4ec8b72..4821094c14b 100644 --- a/xlators/features/marker/src/marker.h +++ b/xlators/features/marker/src/marker.h @@ -11,10 +11,10 @@ #define _MARKER_H #include "marker-quota.h" -#include "xlator.h" -#include "defaults.h" -#include "compat-uuid.h" -#include "call-stub.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/compat-uuid.h> +#include <glusterfs/call-stub.h> #define MARKER_XATTR_PREFIX "trusted.glusterfs" #define XTIME "xtime" diff --git a/xlators/features/metadisp/Makefile.am b/xlators/features/metadisp/Makefile.am new file mode 100644 index 00000000000..a985f42a877 --- /dev/null +++ b/xlators/features/metadisp/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +CLEANFILES = diff --git a/xlators/features/metadisp/src/Makefile.am b/xlators/features/metadisp/src/Makefile.am new file mode 100644 index 00000000000..1520ad8c424 --- /dev/null +++ b/xlators/features/metadisp/src/Makefile.am @@ -0,0 +1,38 @@ +noinst_PYTHON = gen-fops.py + +EXTRA_DIST = fops-tmpl.c + +xlator_LTLIBRARIES = metadisp.la +xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features + +nodist_metadisp_la_SOURCES = fops.c + +BUILT_SOURCES = fops.c + +metadisp_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) + +metadisp_la_SOURCES = metadisp.c \ + metadisp-unlink.c \ + metadisp-stat.c \ + metadisp-lookup.c \ + metadisp-readdir.c \ + metadisp-create.c \ + metadisp-open.c \ + metadisp-fsync.c \ + metadisp-setattr.c \ + backend.c + +metadisp_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la + +noinst_HEADERS = metadisp.h metadisp-fops.h + +AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ + -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src + +AM_CFLAGS = -Wall $(GF_CFLAGS) + +fops.c: fops-tmpl.c $(top_srcdir)/libglusterfs/src/generator.py gen-fops.py + PYTHONPATH=$(top_srcdir)/libglusterfs/src \ + $(PYTHON) $(srcdir)/gen-fops.py $(srcdir)/fops-tmpl.c > $@ + +CLEANFILES = $(nodist_metadisp_la_SOURCES) diff --git a/xlators/features/metadisp/src/backend.c b/xlators/features/metadisp/src/backend.c new file mode 100644 index 00000000000..ee2c25bfaa7 --- /dev/null +++ b/xlators/features/metadisp/src/backend.c @@ -0,0 +1,45 @@ +#define GFID_STR_LEN 37 + +#include "metadisp.h" + +/* + * backend.c + * + * functions responsible for converting user-facing paths to backend-style + * "/$GFID" paths. + */ + +int32_t +build_backend_loc(uuid_t gfid, loc_t *src_loc, loc_t *dst_loc) +{ + static uuid_t root = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + char gfid_buf[GFID_STR_LEN + 1] = { + 0, + }; + char *path = NULL; + + GF_VALIDATE_OR_GOTO("metadisp", src_loc, out); + GF_VALIDATE_OR_GOTO("metadisp", dst_loc, out); + + loc_copy(dst_loc, src_loc); + memcpy(dst_loc->pargfid, root, sizeof(root)); + GF_FREE((char *)dst_loc->path); // we are overwriting path so nuke + // whatever loc_copy gave us + + uuid_utoa_r(gfid, gfid_buf); + + path = GF_CALLOC(GFID_STR_LEN + 1, sizeof(char), + gf_common_mt_char); // freed via loc_wipe + + path[0] = '/'; + strncpy(path + 1, gfid_buf, GFID_STR_LEN); + path[GFID_STR_LEN] = 0; + dst_loc->path = path; + if (src_loc->name) + dst_loc->name = strrchr(dst_loc->path, '/'); + if (dst_loc->name) + dst_loc->name++; + return 0; +out: + return -1; +} diff --git a/xlators/features/metadisp/src/fops-tmpl.c b/xlators/features/metadisp/src/fops-tmpl.c new file mode 100644 index 00000000000..4385b7dd5b7 --- /dev/null +++ b/xlators/features/metadisp/src/fops-tmpl.c @@ -0,0 +1,10 @@ +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <glusterfs/xlator.h> +#include "metadisp.h" +#include "metadisp-fops.h" + +#pragma generate diff --git a/xlators/features/metadisp/src/gen-fops.py b/xlators/features/metadisp/src/gen-fops.py new file mode 100644 index 00000000000..8b5e120fdec --- /dev/null +++ b/xlators/features/metadisp/src/gen-fops.py @@ -0,0 +1,160 @@ +#!/usr/bin/python + +import sys +from generator import fop_subs, generate + +FN_METADATA_CHILD_GENERIC = """ +int32_t +metadisp_@NAME@ (call_frame_t *frame, xlator_t *this, + @LONG_ARGS@) +{ + METADISP_TRACE("@NAME@ metadata"); + STACK_WIND (frame, default_@NAME@_cbk, + METADATA_CHILD(this), METADATA_CHILD(this)->fops->@NAME@, + @SHORT_ARGS@); + return 0; +} +""" + +FN_GENERIC_TEMPLATE = """ +int32_t +metadisp_@NAME@ (call_frame_t *frame, xlator_t *this, + @LONG_ARGS@) +{ + METADISP_TRACE("@NAME@ generic"); + STACK_WIND (frame, default_@NAME@_cbk, + DATA_CHILD(this), DATA_CHILD(this)->fops->@NAME@, + @SHORT_ARGS@); + return 0; +} +""" + +FN_DATAFD_TEMPLATE = """ +int32_t +metadisp_@NAME@ (call_frame_t *frame, xlator_t *this, + @LONG_ARGS@) +{ + METADISP_TRACE("@NAME@ datafd"); + xlator_t *child = NULL; + child = DATA_CHILD(this); + STACK_WIND (frame, default_@NAME@_cbk, + child, child->fops->@NAME@, + @SHORT_ARGS@); + return 0; +} +""" + +FN_DATALOC_TEMPLATE = """ +int32_t +metadisp_@NAME@ (call_frame_t *frame, xlator_t *this, + @LONG_ARGS@) +{ + METADISP_TRACE("@NAME@ dataloc"); + loc_t backend_loc = { + 0, + }; + if (build_backend_loc(loc->gfid, loc, &backend_loc)) { + goto unwind; + } + xlator_t *child = NULL; + child = DATA_CHILD(this); + STACK_WIND (frame, default_@NAME@_cbk, + child, child->fops->@NAME@, + @SHORT_ARGS@); + return 0; + +unwind: + STACK_UNWIND_STRICT(lookup, frame, -1, EINVAL, NULL, NULL, NULL, NULL); + return 0; +} +""" + +FOPS_LINE_TEMPLATE = "\t.@NAME@ = metadisp_@NAME@," + +skipped = [ + "readdir", + "readdirp", + "lookup", + "fsync", + "stat", + "open", + "create", + "unlink", + "setattr", + # TODO: implement "inodelk", +] + + +def gen_fops(): + done = skipped + + # + # these are fops that wind to the DATA_CHILD + # + # NOTE: re-written in order from google doc: + # https://docs.google.com/document/d/1KEwVtSNvDhs4qb63gWx2ulCp5GJjge77NGJk4p_Ms4Q + for name in [ + "writev", + "readv", + "ftruncate", + "zerofill", + "discard", + "seek", + "fstat", + ]: + done = done + [name] + print(generate(FN_DATAFD_TEMPLATE, name, fop_subs)) + + for name in ["truncate"]: + done = done + [name] + print(generate(FN_DATALOC_TEMPLATE, name, fop_subs)) + + # these are fops that operate solely on dentries, folders, + # or extended attributes. Therefore, they must always + # wind to METADATA_CHILD and should never perform + # any path rewriting + # + # NOTE: re-written in order from google doc: + # https://docs.google.com/document/d/1KEwVtSNvDhs4qb63gWx2ulCp5GJjge77NGJk4p_Ms4Q + for name in [ + "mkdir", + "symlink", + "link", + "rename", + "mknod", + "opendir", + # "readdir, # special-cased + # "readdirp, # special-cased + "fsyncdir", + # "setattr", # special-cased + "readlink", + "fentrylk", + "access", + # TODO: these wind to both, + # data for backend-attributes and metadata for the rest + "xattrop", + "setxattr", + "getxattr", + "removexattr", + "fgetxattr", + "fsetxattr", + "fremovexattr", + ]: + + done = done + [name] + print(generate(FN_METADATA_CHILD_GENERIC, name, fop_subs)) + + print("struct xlator_fops fops = {") + for name in done: + print(generate(FOPS_LINE_TEMPLATE, name, fop_subs)) + + print("};") + + +for l in open(sys.argv[1], "r").readlines(): + if l.find("#pragma generate") != -1: + print("/* BEGIN GENERATED CODE - DO NOT MODIFY */") + gen_fops() + print("/* END GENERATED CODE */") + else: + print(l[:-1]) diff --git a/xlators/features/metadisp/src/metadisp-create.c b/xlators/features/metadisp/src/metadisp-create.c new file mode 100644 index 00000000000..f8c9798dd59 --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-create.c @@ -0,0 +1,101 @@ +#include "metadisp.h" +#include <glusterfs/call-stub.h> + +/** + * Create, like stat, is a two-step process. We send a create + * to the METADATA_CHILD, then send another create to the DATA_CHILD. + * + * We do the metadata child first to ensure that the ACLs are enforced. + */ + +int32_t +metadisp_create_dentry_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, + dict_t *xdata) +{ + STACK_UNWIND_STRICT(create, frame, op_ret, op_errno, fd, inode, buf, + preparent, postparent, xdata); + return 0; +} + +int32_t +metadisp_create_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, mode_t mode, mode_t umask, fd_t *fd, + dict_t *xdata) +{ + // create the backend data inode + STACK_WIND(frame, metadisp_create_dentry_cbk, DATA_CHILD(this), + DATA_CHILD(this)->fops->create, loc, flags, mode, umask, fd, + xdata); + return 0; +} + +int32_t +metadisp_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, dict_t *xdata) +{ + METADISP_TRACE("%d %d", op_ret, op_errno); + call_stub_t *stub = cookie; + if (op_ret != 0) { + STACK_UNWIND_STRICT(create, frame, op_ret, op_errno, fd, inode, buf, + preparent, postparent, xdata); + return 0; + } + + if (stub == NULL) { + goto unwind; + } + + if (stub->poison) { + call_stub_destroy(stub); + return 0; + } + + call_resume(stub); + return 0; + +unwind: + STACK_UNWIND_STRICT(create, frame, -1, EINVAL, NULL, NULL, NULL, NULL, NULL, + NULL); + return 0; +} + +int32_t +metadisp_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) +{ + METADISP_TRACE("."); + + loc_t backend_loc = { + 0, + }; + call_stub_t *stub = NULL; + uuid_t *gfid_req = NULL; + + RESOLVE_GFID_REQ(xdata, gfid_req, out); + + if (build_backend_loc(*gfid_req, loc, &backend_loc)) { + goto unwind; + } + + frame->local = loc; + + stub = fop_create_stub(frame, metadisp_create_resume, &backend_loc, flags, + mode, umask, fd, xdata); + + STACK_WIND_COOKIE(frame, metadisp_create_cbk, stub, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->create, loc, flags, mode, + umask, fd, xdata); + return 0; + +unwind: + STACK_UNWIND_STRICT(create, frame, -1, EINVAL, NULL, NULL, NULL, NULL, NULL, + NULL); + return 0; +out: + return -1; +} diff --git a/xlators/features/metadisp/src/metadisp-fops.h b/xlators/features/metadisp/src/metadisp-fops.h new file mode 100644 index 00000000000..56dd427cf34 --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-fops.h @@ -0,0 +1,51 @@ +#ifndef GF_METADISP_FOPS_H_ +#define GF_METADISP_FOPS_H_ + +#include <glusterfs/xlator.h> +#include <glusterfs/dict.h> +#include <glusterfs/glusterfs.h> + +#include <sys/types.h> + +/* fops in here are defined in their own file. Every other fop is just defined + * inline of fops.c */ + +int +metadisp_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *xdata); + +int +metadisp_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *dict); + +int +metadisp_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata); + +int +metadisp_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata); + +int +metadisp_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata); + +int +metadisp_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata); + +int +metadisp_inodelk(call_frame_t *frame, xlator_t *this, const char *volume, + loc_t *loc, int32_t cmd, struct gf_flock *lock, dict_t *xdata); + +int +metadisp_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, + dict_t *xdata); + +int +metadisp_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata); + +int +metadisp_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, dict_t *xdata); + +#endif diff --git a/xlators/features/metadisp/src/metadisp-fsync.c b/xlators/features/metadisp/src/metadisp-fsync.c new file mode 100644 index 00000000000..2e46fa84eac --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-fsync.c @@ -0,0 +1,54 @@ + +#include "metadisp.h" +#include <glusterfs/call-stub.h> + +int32_t +metadisp_fsync_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t flags, dict_t *xdata) +{ + STACK_WIND(frame, default_fsync_cbk, DATA_CHILD(this), + DATA_CHILD(this)->fops->fsync, fd, flags, xdata); + return 0; +} + +int32_t +metadisp_fsync_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + call_stub_t *stub = NULL; + if (cookie) { + stub = cookie; + } + + if (op_ret != 0) { + goto unwind; + } + + if (stub->poison) { + call_stub_destroy(stub); + stub = NULL; + return 0; + } + + call_resume(stub); + return 0; + +unwind: + if (stub) { + call_stub_destroy(stub); + } + STACK_UNWIND_STRICT(fsync, frame, op_ret, op_errno, prebuf, postbuf, xdata); + return 0; +} + +int32_t +metadisp_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, + dict_t *xdata) +{ + call_stub_t *stub = NULL; + stub = fop_fsync_stub(frame, metadisp_fsync_resume, fd, flags, xdata); + STACK_WIND_COOKIE(frame, metadisp_fsync_cbk, stub, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->fsync, fd, flags, xdata); + return 0; +} diff --git a/xlators/features/metadisp/src/metadisp-lookup.c b/xlators/features/metadisp/src/metadisp-lookup.c new file mode 100644 index 00000000000..27d90c9f746 --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-lookup.c @@ -0,0 +1,90 @@ +#include "metadisp.h" +#include <glusterfs/call-stub.h> + +/** + * Lookup, like stat, is a two-step process for grabbing the metadata details + * as well as the data details. + */ + +int32_t +metadisp_backend_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, + struct iatt *postparent) +{ + METADISP_TRACE("backend_lookup_cbk"); + if (op_errno == ENOENT) { + op_errno = ENODATA; + op_ret = -1; + } + STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, buf, xdata, + postparent); + return 0; +} + +int32_t +metadisp_backend_lookup_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) +{ + METADISP_TRACE("backend_lookup_resume"); + loc_t backend_loc = { + 0, + }; + if (build_backend_loc(loc->gfid, loc, &backend_loc)) { + goto unwind; + } + + STACK_WIND(frame, metadisp_backend_lookup_cbk, DATA_CHILD(this), + DATA_CHILD(this)->fops->lookup, &backend_loc, xdata); + return 0; + +unwind: + STACK_UNWIND_STRICT(lookup, frame, -1, EINVAL, NULL, NULL, NULL, NULL); + return 0; +} + +int32_t +metadisp_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, struct iatt *postparent) +{ + METADISP_TRACE("%d %d", op_ret, op_errno); + call_stub_t *stub = NULL; + stub = cookie; + + if (op_ret != 0) { + goto unwind; + } + + if (!IA_ISREG(buf->ia_type)) { + goto unwind; + } else if (!stub) { + op_errno = EINVAL; + goto unwind; + } + + METADISP_TRACE("resuming stub"); + + // memcpy(stub->args.loc.gfid, buf->ia_gfid, sizeof(uuid_t)); + call_resume(stub); + return 0; +unwind: + METADISP_TRACE("unwinding %d %d", op_ret, op_errno); + STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, buf, xdata, + postparent); + if (stub) { + call_stub_destroy(stub); + } + return 0; +} + +int32_t +metadisp_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + METADISP_TRACE("lookup"); + call_stub_t *stub = NULL; + stub = fop_lookup_stub(frame, metadisp_backend_lookup_resume, loc, xdata); + STACK_WIND_COOKIE(frame, metadisp_lookup_cbk, stub, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->lookup, loc, xdata); + return 0; +} diff --git a/xlators/features/metadisp/src/metadisp-open.c b/xlators/features/metadisp/src/metadisp-open.c new file mode 100644 index 00000000000..64814afe636 --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-open.c @@ -0,0 +1,70 @@ +#include <glusterfs/call-stub.h> +#include "metadisp.h" + +int32_t +metadisp_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + METADISP_TRACE("got open results %d %d", op_ret, op_errno); + + call_stub_t *stub = NULL; + if (cookie) { + stub = cookie; + } + + if (op_ret != 0) { + goto unwind; + } + + if (!stub) { + goto unwind; + } + + if (stub->poison) { + call_stub_destroy(stub); + stub = NULL; + return 0; + } + + call_resume(stub); + return 0; + +unwind: + if (stub) { + call_stub_destroy(stub); + } + STACK_UNWIND_STRICT(open, frame, op_ret, op_errno, fd, xdata); + return 0; +} + +int32_t +metadisp_open_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, fd_t *fd, dict_t *xdata) +{ + STACK_WIND_COOKIE(frame, metadisp_open_cbk, NULL, DATA_CHILD(this), + DATA_CHILD(this)->fops->open, loc, flags, fd, xdata); + return 0; +} + +int32_t +metadisp_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata) +{ + call_stub_t *stub = NULL; + loc_t backend_loc = { + 0, + }; + + if (build_backend_loc(loc->gfid, loc, &backend_loc)) { + goto unwind; + } + + stub = fop_open_stub(frame, metadisp_open_resume, &backend_loc, flags, fd, + xdata); + STACK_WIND_COOKIE(frame, metadisp_open_cbk, stub, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->open, loc, flags, fd, xdata); + return 0; +unwind: + STACK_UNWIND_STRICT(open, frame, -1, EINVAL, NULL, NULL); + return 0; +} diff --git a/xlators/features/metadisp/src/metadisp-readdir.c b/xlators/features/metadisp/src/metadisp-readdir.c new file mode 100644 index 00000000000..5f840b1e88f --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-readdir.c @@ -0,0 +1,65 @@ +#include "metadisp.h" + +/** + * With a change to the posix xlator, readdir and readdirp are shockingly + * simple. + * + * The issue with separating the backend data of the files + * with the metadata is that readdirs must now read from multiple sources + * to coalesce the directory entries. + * + * The way we do this is to tell the METADATA_CHILD that when it's + * running readdirp, each file entry should have a stat wound to + * 'stat-source-of-truth'. + * + * see metadisp_stat for how it handles winds _from_posix. + */ + +int32_t +metadisp_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *xdata) +{ + METADISP_TRACE("."); + /* + * Always use readdirp, even if the original was readdir. Why? Because NFS. + * There are multiple translations between Gluster, UNIX, and NFS stat + * structures in that path. One of them uses the type etc. from the stat + * structure, which is only filled in by readdirp. If we use readdir, the + * entries do actually go all the way back to the client and are visible in + * getdents, but then the readdir throws them away because of the + * uninitialized type. + */ + GF_UNUSED int32_t ret; + if (!xdata) { + xdata = dict_new(); + } + + // ret = dict_set_int32 (xdata, "list-xattr", 1); + + // I'm my own source of truth! + ret = dict_set_static_ptr(xdata, "stat-source-of-truth", (void *)this); + + STACK_WIND(frame, default_readdirp_cbk, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->readdirp, fd, size, off, xdata); + + return 0; +} + +int32_t +metadisp_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *xdata) +{ + METADISP_TRACE("."); + if (!xdata) { + xdata = dict_new(); + } + GF_UNUSED int32_t ret; + // ret = dict_set_int32 (xdata, "list-xattr", 1); + + // I'm my own source of truth! + ret = dict_set_static_ptr(xdata, "stat-source-of-truth", (void *)this); + + STACK_WIND(frame, default_readdirp_cbk, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->readdirp, fd, size, off, xdata); + return 0; +} diff --git a/xlators/features/metadisp/src/metadisp-setattr.c b/xlators/features/metadisp/src/metadisp-setattr.c new file mode 100644 index 00000000000..6991cf644f3 --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-setattr.c @@ -0,0 +1,90 @@ +#include "metadisp.h" +#include <glusterfs/call-stub.h> + +int32_t +metadisp_backend_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, + dict_t *xdata) + +{ + METADISP_TRACE("backend_setattr_cbk"); + if (op_errno == ENOENT) { + op_errno = ENODATA; + op_ret = -1; + } + STACK_UNWIND_STRICT(setattr, frame, op_ret, op_errno, statpre, statpost, + xdata); + return 0; +} + +int32_t +metadisp_backend_setattr_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, + dict_t *xdata) + +{ + METADISP_TRACE("backend_setattr_resume"); + loc_t backend_loc = { + 0, + }; + if (build_backend_loc(loc->gfid, loc, &backend_loc)) { + goto unwind; + } + + STACK_WIND(frame, metadisp_backend_setattr_cbk, DATA_CHILD(this), + DATA_CHILD(this)->fops->setattr, &backend_loc, stbuf, valid, + xdata); + return 0; + +unwind: + STACK_UNWIND_STRICT(setattr, frame, -1, EINVAL, NULL, NULL, NULL); + return 0; +} + +int32_t +metadisp_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, dict_t *xdata) +{ + METADISP_TRACE("%d %d", op_ret, op_errno); + call_stub_t *stub = NULL; + stub = cookie; + + if (op_ret != 0) { + goto unwind; + } + + if (!IA_ISREG(statpost->ia_type)) { + goto unwind; + } else if (!stub) { + op_errno = EINVAL; + goto unwind; + } + + METADISP_TRACE("resuming stub"); + call_resume(stub); + return 0; +unwind: + METADISP_TRACE("unwinding %d %d", op_ret, op_errno); + STACK_UNWIND_STRICT(setattr, frame, op_ret, op_errno, statpre, statpost, + xdata); + if (stub) { + call_stub_destroy(stub); + } + return 0; +} + +int32_t +metadisp_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, dict_t *xdata) +{ + METADISP_TRACE("setattr"); + call_stub_t *stub = NULL; + stub = fop_setattr_stub(frame, metadisp_backend_setattr_resume, loc, stbuf, + valid, xdata); + STACK_WIND_COOKIE(frame, metadisp_setattr_cbk, stub, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->setattr, loc, stbuf, valid, + xdata); + return 0; +} diff --git a/xlators/features/metadisp/src/metadisp-stat.c b/xlators/features/metadisp/src/metadisp-stat.c new file mode 100644 index 00000000000..b06d0dbcddd --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-stat.c @@ -0,0 +1,124 @@ +#include "metadisp.h" +#include <glusterfs/call-stub.h> + +/** + * The stat flow in METADISP is complicated because we must + * do ensure a few things: + * 1. stat, on the path within the metadata layer, + * MUST get the backend FD of the data layer. + * --- we wind to the metadata layer, then the data layer. + * + * 2. the metadata layer MUST be able to ask the data + * layer for stat information. + * --- this is 'syncop-internal-from-posix' + * + * 3. when the metadata exists BUT the data is missing, + * we MUST mark the backend file as bad and heal it. + */ + +int32_t +metadisp_stat_backend_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + METADISP_TRACE("got backend stat results %d %d", op_ret, op_errno); + if (op_errno == ENOENT) { + STACK_UNWIND_STRICT(open, frame, -1, ENODATA, NULL, NULL); + return 0; + } + STACK_UNWIND_STRICT(stat, frame, op_ret, op_errno, buf, xdata); + return 0; +} + +int32_t +metadisp_stat_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) +{ + METADISP_TRACE("winding stat to path %s", loc->path); + if (gf_uuid_is_null(loc->gfid)) { + METADISP_TRACE("bad object, sending EUCLEAN"); + STACK_UNWIND_STRICT(open, frame, -1, EUCLEAN, NULL, NULL); + return 0; + } + + STACK_WIND(frame, metadisp_stat_backend_cbk, SECOND_CHILD(this), + SECOND_CHILD(this)->fops->stat, loc, xdata); + return 0; +} + +int32_t +metadisp_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + call_stub_t *stub = NULL; + + METADISP_TRACE("got stat results %d %d", op_ret, op_errno); + + if (cookie) { + stub = cookie; + } + + if (op_ret != 0) { + goto unwind; + } + + // only use the stub for the files + if (!IA_ISREG(buf->ia_type)) { + goto unwind; + } + + if (stub->poison) { + call_stub_destroy(stub); + stub = NULL; + return 0; + } + + call_resume(stub); + return 0; + +unwind: + if (stub) { + call_stub_destroy(stub); + } + STACK_UNWIND_STRICT(stat, frame, op_ret, op_errno, buf, xdata); + return 0; +} + +int32_t +metadisp_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + call_stub_t *stub = NULL; + int32_t ret = 0; + loc_t backend_loc = { + 0, + }; + METADISP_FILTER_ROOT(stat, loc, xdata); + + if (build_backend_loc(loc->gfid, loc, &backend_loc)) { + goto unwind; + } + + if (dict_get_int32(xdata, "syncop-internal-from-posix", &ret) == 0) { + // if we've just been sent a stat from posix, then we know + // that we must send down a stat for a file to the second child. + // + // that means we can skip the stat for the first child and just + // send to the data disk. + METADISP_TRACE("got syncop-internal-from-posix"); + STACK_WIND(frame, default_stat_cbk, DATA_CHILD(this), + DATA_CHILD(this)->fops->stat, &backend_loc, xdata); + return 0; + } + + // we do not know if the request is for a file, folder, etc. wind + // to first child to find out. + stub = fop_stat_stub(frame, metadisp_stat_resume, &backend_loc, xdata); + METADISP_TRACE("winding stat to first child %s", loc->path); + STACK_WIND_COOKIE(frame, metadisp_stat_cbk, stub, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->stat, loc, xdata); + return 0; +unwind: + STACK_UNWIND_STRICT(stat, frame, -1, EINVAL, NULL, NULL); + return 0; +} diff --git a/xlators/features/metadisp/src/metadisp-unlink.c b/xlators/features/metadisp/src/metadisp-unlink.c new file mode 100644 index 00000000000..1f6a8eb35ce --- /dev/null +++ b/xlators/features/metadisp/src/metadisp-unlink.c @@ -0,0 +1,160 @@ + +#include "metadisp.h" +#include <glusterfs/call-stub.h> + +/** + * The unlink flow in metadisp is complicated because we must + * do ensure that UNLINK causes both the metadata objects + * to get removed and the data objects to get removed. + */ + +int32_t +metadisp_unlink_resume(call_frame_t *frame, xlator_t *this, loc_t *loc, + int xflag, dict_t *xdata) +{ + METADISP_TRACE("winding backend unlink to path %s", loc->path); + STACK_WIND(frame, default_unlink_cbk, DATA_CHILD(this), + DATA_CHILD(this)->fops->unlink, loc, xflag, xdata); + return 0; +} + +int32_t +metadisp_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, dict_t *xdata) +{ + METADISP_TRACE(". %d %d", op_ret, op_errno); + + int ret = 0; + call_stub_t *stub = NULL; + int nlink = 0; + + if (cookie) { + stub = cookie; + } + + if (op_ret != 0) { + goto unwind; + } + + if (stub->poison) { + call_stub_destroy(stub); + stub = NULL; + return 0; + } + + ret = dict_get_uint32(xdata, GF_RESPONSE_LINK_COUNT_XDATA, &nlink); + if (ret != 0) { + op_errno = EINVAL; + op_ret = -1; + goto unwind; + } + METADISP_TRACE("frontend hardlink count %d %d", ret, nlink); + if (nlink > 1) { + goto unwind; + } + + call_resume(stub); + return 0; + +unwind: + if (stub) { + call_stub_destroy(stub); + } + STACK_UNWIND_STRICT(unlink, frame, op_ret, op_errno, preparent, postparent, + xdata); + return 0; +} + +int32_t +metadisp_unlink_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, + struct iatt *postparent) +{ + call_stub_t *stub = NULL; + + if (cookie) { + stub = cookie; + } + + if (op_ret != 0) { + goto unwind; + } + + // fail fast on empty gfid so we don't loop forever + if (gf_uuid_is_null(buf->ia_gfid)) { + op_ret = -1; + op_errno = ENODATA; + goto unwind; + } + + // fill gfid since the stub is incomplete + memcpy(stub->args.loc.gfid, buf->ia_gfid, sizeof(uuid_t)); + memcpy(stub->args.loc.pargfid, postparent->ia_gfid, sizeof(uuid_t)); + + if (stub->poison) { + call_stub_destroy(stub); + stub = NULL; + return 0; + } + + call_resume(stub); + return 0; + +unwind: + if (stub) { + call_stub_destroy(stub); + } + STACK_UNWIND_STRICT(unlink, frame, op_ret, op_errno, NULL, NULL, NULL); + return 0; +} + +int32_t +metadisp_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata) +{ + call_stub_t *stub = NULL; + loc_t backend_loc = { + 0, + }; + + if (gf_uuid_is_null(loc->gfid)) { + METADISP_TRACE("winding lookup for unlink to path %s", loc->path); + + // loop back to ourselves after a lookup + stub = fop_unlink_stub(frame, metadisp_unlink, loc, xflag, xdata); + STACK_WIND_COOKIE(frame, metadisp_unlink_lookup_cbk, stub, + METADATA_CHILD(this), + METADATA_CHILD(this)->fops->lookup, loc, xdata); + return 0; + } + + if (build_backend_loc(loc->gfid, loc, &backend_loc)) { + goto unwind; + } + + // + // ensure we get the link count on the unlink response, so we can + // account for hardlinks before winding to the backend. + // NOTE: + // multiple xlators use GF_REQUEST_LINK_COUNT_XDATA. confirmation + // is needed to ensure that multiple requests will work in the same + // xlator stack. + // + if (!xdata) { + xdata = dict_new(); + } + dict_set_int32(xdata, GF_REQUEST_LINK_COUNT_XDATA, 1); + + METADISP_TRACE("winding frontend unlink to path %s", loc->path); + stub = fop_unlink_stub(frame, metadisp_unlink_resume, &backend_loc, xflag, + xdata); + + STACK_WIND_COOKIE(frame, metadisp_unlink_cbk, stub, METADATA_CHILD(this), + METADATA_CHILD(this)->fops->unlink, loc, xflag, xdata); + return 0; +unwind: + STACK_UNWIND_STRICT(unlink, frame, -1, EINVAL, NULL, NULL, NULL); + return 0; +} diff --git a/xlators/features/metadisp/src/metadisp.c b/xlators/features/metadisp/src/metadisp.c new file mode 100644 index 00000000000..3c8f150cebc --- /dev/null +++ b/xlators/features/metadisp/src/metadisp.c @@ -0,0 +1,46 @@ +#include <glusterfs/call-stub.h> + +#include "metadisp.h" +#include "metadisp-fops.h" + +int32_t +init(xlator_t *this) +{ + if (!this->children) { + gf_log(this->name, GF_LOG_ERROR, + "not configured with children. exiting"); + return -1; + } + + if (!this->parents) { + gf_log(this->name, GF_LOG_WARNING, "dangling volume. check volfile "); + } + + return 0; +} + +void +fini(xlator_t *this) +{ + return; +} + +/* defined in fops.c */ +struct xlator_fops fops; + +struct xlator_cbks cbks = {}; + +struct volume_options options[] = { + {.key = {NULL}}, +}; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .fops = &fops, + .cbks = &cbks, + .options = options, + .op_version = {1}, + .identifier = "metadisp", + .category = GF_EXPERIMENTAL, +}; diff --git a/xlators/features/metadisp/src/metadisp.h b/xlators/features/metadisp/src/metadisp.h new file mode 100644 index 00000000000..c8fd7a13c04 --- /dev/null +++ b/xlators/features/metadisp/src/metadisp.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ +#ifndef GF_METADISP_H_ +#define GF_METADISP_H_ + +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> + +#define METADATA_CHILD(_this) FIRST_CHILD(_this) +#define DATA_CHILD(_this) SECOND_CHILD(_this) + +int32_t +build_backend_loc(uuid_t gfid, loc_t *src_loc, loc_t *dst_loc); + +#define METADISP_TRACE(_args...) gf_log("metadisp", GF_LOG_INFO, _args) + +#define METADISP_FILTER_ROOT(_op, _args...) \ + if (strcmp(loc->path, "/") == 0) { \ + STACK_WIND(frame, default_##_op##_cbk, METADATA_CHILD(this), \ + METADATA_CHILD(this)->fops->_op, _args); \ + return 0; \ + } + +#define METADISP_FILTER_ROOT_BY_GFID(_op, _gfid, _args...) \ + if (__is_root_gfid(_gfid)) { \ + STACK_WIND(frame, default_##_op##_cbk, METADATA_CHILD(this), \ + METADATA_CHILD(this)->fops->_op, _args); \ + return 0; \ + } + +#define RESOLVE_GFID_REQ(_dict, _dest, _lbl) \ + VALIDATE_OR_GOTO(dict_get_ptr(_dict, "gfid-req", (void **)&_dest) == 0, \ + _lbl) + +#endif /* __TEMPLATE_H__ */ diff --git a/xlators/features/namespace/src/namespace.c b/xlators/features/namespace/src/namespace.c index 581b470381d..86c5ebee900 100644 --- a/xlators/features/namespace/src/namespace.c +++ b/xlators/features/namespace/src/namespace.c @@ -15,10 +15,9 @@ #include <sys/types.h> -#include "defaults.h" -#include "glusterfs.h" -#include "hashfn.h" -#include "logging.h" +#include <glusterfs/defaults.h> +#include <glusterfs/hashfn.h> +#include <glusterfs/logging.h> #include "namespace.h" /* Return codes for common path parsing functions. */ @@ -147,7 +146,7 @@ ns_inode_ctx_put(inode_t *inode, xlator_t *this, ns_info_t *info) } *cached_ns_info = *info; - ns_as_64 = (uint64_t)cached_ns_info; + ns_as_64 = (uint64_t)(uintptr_t)cached_ns_info; ret = inode_ctx_put(inode, this, ns_as_64); @@ -181,7 +180,7 @@ ns_inode_ctx_get(inode_t *inode, xlator_t *this, ns_info_t *info) ret = inode_ctx_get(inode, this, &ns_as_64); if (!ret) { - cached_ns_info = (ns_info_t *)ns_as_64; + cached_ns_info = (ns_info_t *)(uintptr_t)ns_as_64; *info = *cached_ns_info; } @@ -1190,7 +1189,7 @@ ns_forget(xlator_t *this, inode_t *inode) return 0; } - info = (ns_info_t *)ns_as_64; + info = (ns_info_t *)(uintptr_t)ns_as_64; GF_FREE(info); return 0; @@ -1249,7 +1248,6 @@ reconfigure(xlator_t *this, dict_t *options) int ret = -1; ns_private_t *priv = NULL; - GF_VALIDATE_OR_GOTO(this->name, this, out); GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, options, out); @@ -1331,3 +1329,16 @@ struct volume_options options[] = { }, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .op_version = {GD_OP_VERSION_3_12_0}, + .dumpops = &dumpops, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "namespace", + .category = GF_TECH_PREVIEW, +}; diff --git a/xlators/features/namespace/src/namespace.h b/xlators/features/namespace/src/namespace.h index 4c04cb3f471..3a9b84d6426 100644 --- a/xlators/features/namespace/src/namespace.h +++ b/xlators/features/namespace/src/namespace.h @@ -6,8 +6,8 @@ #include "config.h" #endif -#include "xlator.h" -#include "call-stub.h" +#include <glusterfs/xlator.h> +#include <glusterfs/call-stub.h> #define GF_NAMESPACE "namespace" diff --git a/xlators/features/quiesce/src/quiesce-mem-types.h b/xlators/features/quiesce/src/quiesce-mem-types.h index 914bfb22ed0..416456b13af 100644 --- a/xlators/features/quiesce/src/quiesce-mem-types.h +++ b/xlators/features/quiesce/src/quiesce-mem-types.h @@ -11,7 +11,7 @@ #ifndef __QUIESCE_MEM_TYPES_H__ #define __QUIESCE_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_quiesce_mem_types_ { gf_quiesce_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/quiesce/src/quiesce-messages.h b/xlators/features/quiesce/src/quiesce-messages.h index 864a18147dc..32ffd409807 100644 --- a/xlators/features/quiesce/src/quiesce-messages.h +++ b/xlators/features/quiesce/src/quiesce-messages.h @@ -11,7 +11,7 @@ #ifndef __QUIESCE_MESSAGES_H__ #define __QUIESCE_MESSAGES_H__ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/quiesce/src/quiesce.c b/xlators/features/quiesce/src/quiesce.c index b7c2c549a91..0e5eb60a16f 100644 --- a/xlators/features/quiesce/src/quiesce.c +++ b/xlators/features/quiesce/src/quiesce.c @@ -8,8 +8,8 @@ cases as published by the Free Software Foundation. */ #include "quiesce.h" -#include "defaults.h" -#include "call-stub.h" +#include <glusterfs/defaults.h> +#include <glusterfs/call-stub.h> /* TODO: */ /* Think about 'writev/_*_lk/setattr/xattrop/' fops to do re-transmittion */ @@ -89,13 +89,14 @@ gf_quiesce_populate_failover_hosts(xlator_t *this, quiesce_priv_t *priv, if (!dup_val) goto out; + addr_tok = strtok_r(dup_val, ",", &save_ptr); LOCK(&priv->lock); { if (!list_empty(&priv->failover_list)) __gf_quiesce_cleanup_failover_hosts(this, priv); - addr_tok = strtok_r(dup_val, ",", &save_ptr); + while (addr_tok) { - if (!valid_internet_address(addr_tok, _gf_true)) { + if (!valid_internet_address(addr_tok, _gf_true, _gf_false)) { gf_msg(this->name, GF_LOG_INFO, 0, QUIESCE_MSG_INVAL_HOST, "Specified " "invalid internet address:%s", @@ -186,6 +187,11 @@ __gf_quiesce_perform_failover(xlator_t *this) } frame = create_frame(this, this->ctx->pool); + if (!frame) { + gf_msg_debug(this->name, 0, "failed to create the frame"); + ret = -1; + goto out; + } dict = dict_new(); @@ -1187,6 +1193,33 @@ quiesce_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, } int32_t +quiesce_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + quiesce_priv_t *priv = NULL; + call_stub_t *stub = NULL; + + priv = this->private; + + if (priv->pass_through) { + STACK_WIND(frame, default_fremovexattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); + return 0; + } + + stub = fop_fremovexattr_stub(frame, default_fremovexattr_resume, fd, name, + xdata); + if (!stub) { + STACK_UNWIND_STRICT(fremovexattr, frame, -1, ENOMEM, NULL); + return 0; + } + + gf_quiesce_enqueue(this, stub); + + return 0; +} + +int32_t quiesce_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata) { @@ -2359,19 +2392,10 @@ quiesce_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, { quiesce_priv_t *priv = NULL; call_stub_t *stub = NULL; - quiesce_local_t *local = NULL; priv = this->private; if (priv && priv->pass_through) { - local = mem_get0(priv->local_pool); - local->fd = fd_ref(fd); - local->offset = offset; - local->len = len; - local->flag = mode; - - frame->local = local; - STACK_WIND(frame, default_fallocate_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fallocate, fd, mode, offset, len, xdata); @@ -2531,6 +2555,7 @@ fini(xlator_t *this) this->private = NULL; mem_pool_destroy(priv->local_pool); + priv->local_pool = NULL; LOCK_DESTROY(&priv->lock); GF_FREE(priv); out: @@ -2587,7 +2612,9 @@ struct xlator_fops fops = { .truncate = quiesce_truncate, .ftruncate = quiesce_ftruncate, .setxattr = quiesce_setxattr, + .fsetxattr = quiesce_fsetxattr, .removexattr = quiesce_removexattr, + .fremovexattr = quiesce_fremovexattr, .symlink = quiesce_symlink, .unlink = quiesce_unlink, .link = quiesce_link, @@ -2620,6 +2647,7 @@ struct xlator_fops fops = { .access = quiesce_access, .readlink = quiesce_readlink, .getxattr = quiesce_getxattr, + .fgetxattr = quiesce_fgetxattr, .open = quiesce_open, .readv = quiesce_readv, .flush = quiesce_flush, @@ -2659,3 +2687,18 @@ struct volume_options options[] = { "the thin clients can failover to."}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {GD_OP_VERSION_3_12_0}, + .dumpops = &dumpops, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "quiesce", + .category = GF_TECH_PREVIEW, +}; diff --git a/xlators/features/quiesce/src/quiesce.h b/xlators/features/quiesce/src/quiesce.h index ed8f8fa2934..6ab2af40a56 100644 --- a/xlators/features/quiesce/src/quiesce.h +++ b/xlators/features/quiesce/src/quiesce.h @@ -13,8 +13,8 @@ #include "quiesce-mem-types.h" #include "quiesce-messages.h" -#include "xlator.h" -#include "timer.h" +#include <glusterfs/xlator.h> +#include <glusterfs/timer.h> #define GF_FOPS_EXPECTED_IN_PARALLEL 512 diff --git a/xlators/features/quota/src/Makefile.am b/xlators/features/quota/src/Makefile.am index 0ae47fc189f..1c2dcef0ca3 100644 --- a/xlators/features/quota/src/Makefile.am +++ b/xlators/features/quota/src/Makefile.am @@ -4,7 +4,7 @@ endif xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features quota_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) -quotad_la_LDFLAGS = -module -export-symbols $(top_srcdir)/xlators/features/quota/src/quotad.sym $(GF_XLATOR_LDFLAGS) +quotad_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) quota_la_SOURCES = quota.c quota-enforcer-client.c quota_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ @@ -27,6 +27,3 @@ AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ AM_CFLAGS = -Wall $(GF_CFLAGS) CLEANFILES = - -EXTRA_DIST = quotad.sym - diff --git a/xlators/features/quota/src/quota-enforcer-client.c b/xlators/features/quota/src/quota-enforcer-client.c index 57105549cf8..480d64ade27 100644 --- a/xlators/features/quota/src/quota-enforcer-client.c +++ b/xlators/features/quota/src/quota-enforcer-client.c @@ -32,12 +32,6 @@ #include <malloc.h> #endif -#ifdef HAVE_MALLOC_STATS -#ifdef DEBUG -#include <mcheck.h> -#endif -#endif - #include "quota.h" #include "quota-messages.h" @@ -362,16 +356,28 @@ quota_enforcer_notify(struct rpc_clnt *rpc, void *mydata, { xlator_t *this = NULL; int ret = 0; + quota_priv_t *priv = NULL; this = mydata; - + priv = this->private; switch (event) { case RPC_CLNT_CONNECT: { + pthread_mutex_lock(&priv->conn_mutex); + { + priv->conn_status = _gf_true; + } + pthread_mutex_unlock(&priv->conn_mutex); gf_msg_trace(this->name, 0, "got RPC_CLNT_CONNECT"); break; } case RPC_CLNT_DISCONNECT: { + pthread_mutex_lock(&priv->conn_mutex); + { + priv->conn_status = _gf_false; + pthread_cond_signal(&priv->conn_cond); + } + pthread_mutex_unlock(&priv->conn_mutex); gf_msg_trace(this->name, 0, "got RPC_CLNT_DISCONNECT"); break; } @@ -395,7 +401,7 @@ quota_enforcer_blocking_connect(rpc_clnt_t *rpc) if (options == NULL) goto out; - ret = dict_set_str(options, "non-blocking-io", "no"); + ret = dict_set_sizen_str_sizen(options, "non-blocking-io", "no"); if (ret) goto out; @@ -403,7 +409,7 @@ quota_enforcer_blocking_connect(rpc_clnt_t *rpc) rpc_clnt_start(rpc); - ret = dict_set_str(options, "non-blocking-io", "yes"); + ret = dict_set_sizen_str_sizen(options, "non-blocking-io", "yes"); if (ret) goto out; @@ -442,16 +448,16 @@ quota_enforcer_init(xlator_t *this, dict_t *options) priv->quota_enforcer = "a_enforcer_clnt; - ret = dict_set_str(options, "transport.address-family", "unix"); + ret = dict_set_sizen_str_sizen(options, "transport.address-family", "unix"); if (ret) goto out; - ret = dict_set_str(options, "transport-type", "socket"); + ret = dict_set_sizen_str_sizen(options, "transport-type", "socket"); if (ret) goto out; - ret = dict_set_str(options, "transport.socket.connect-path", - "/var/run/gluster/quotad.socket"); + ret = dict_set_sizen_str_sizen(options, "transport.socket.connect-path", + "/var/run/gluster/quotad.socket"); if (ret) goto out; diff --git a/xlators/features/quota/src/quota-mem-types.h b/xlators/features/quota/src/quota-mem-types.h index e04d2e846cd..782a7de96bb 100644 --- a/xlators/features/quota/src/quota-mem-types.h +++ b/xlators/features/quota/src/quota-mem-types.h @@ -10,9 +10,10 @@ #ifndef __QUOTA_MEM_TYPES_H__ #define __QUOTA_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_quota_mem_types_ { + /* Those are used by QUOTA_ALLOC_OR_GOTO macro */ gf_quota_mt_quota_priv_t = gf_common_mt_end + 1, gf_quota_mt_quota_inode_ctx_t, gf_quota_mt_loc_t, diff --git a/xlators/features/quota/src/quota-messages.h b/xlators/features/quota/src/quota-messages.h index 5129d2ee9ad..d434ed75e76 100644 --- a/xlators/features/quota/src/quota-messages.h +++ b/xlators/features/quota/src/quota-messages.h @@ -11,7 +11,7 @@ #ifndef _QUOTA_MESSAGES_H_ #define _QUOTA_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c index 44f00580495..18df9ae6d19 100644 --- a/xlators/features/quota/src/quota.c +++ b/xlators/features/quota/src/quota.c @@ -7,15 +7,11 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include <fnmatch.h> #include "quota.h" -#include "common-utils.h" -#include "defaults.h" -#include "statedump.h" -#include "quota-common-utils.h" +#include <glusterfs/statedump.h> #include "quota-messages.h" -#include "events.h" +#include <glusterfs/events.h> struct volume_options options[]; @@ -564,15 +560,14 @@ quota_handle_validate_error(call_frame_t *frame, int32_t op_ret, if (local == NULL) goto out; - LOCK(&local->lock); - { - if (op_ret < 0) { + if (op_ret < 0) { + LOCK(&local->lock); + { local->op_ret = op_ret; local->op_errno = op_errno; } + UNLOCK(&local->lock); } - UNLOCK(&local->lock); - /* we abort checking limits on this path to root */ quota_link_count_decrement(frame); out: @@ -615,7 +610,8 @@ quota_validate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto unwind; } - ret = quota_dict_get_meta(xdata, QUOTA_SIZE_KEY, &size); + ret = quota_dict_get_meta(xdata, QUOTA_SIZE_KEY, SLEN(QUOTA_SIZE_KEY), + &size); if (ret == -1) { gf_msg(this->name, GF_LOG_WARNING, EINVAL, Q_MSG_SIZE_KEY_MISSING, "quota size key not present " @@ -630,9 +626,9 @@ quota_validate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, LOCK(&ctx->lock); { ctx->size = size.size; + ctx->validate_time = gf_time(); ctx->file_count = size.file_count; ctx->dir_count = size.dir_count; - gettimeofday(&ctx->tv, NULL); } UNLOCK(&ctx->lock); @@ -644,64 +640,51 @@ unwind: return 0; } -static uint64_t -quota_time_elapsed(struct timeval *now, struct timeval *then) +static inline gf_boolean_t +quota_timeout(time_t t, uint32_t timeout) { - return (now->tv_sec - then->tv_sec); -} - -int32_t -quota_timeout(struct timeval *tv, int32_t timeout) -{ - struct timeval now = { - 0, - }; - int32_t timed_out = 0; - - gettimeofday(&now, NULL); - - if (quota_time_elapsed(&now, tv) >= timeout) { - timed_out = 1; - } - - return timed_out; + return (gf_time() - t) >= timeout; } /* Return: 1 if new entry added * 0 no entry added + * -1 on errors */ static int32_t quota_add_parent(struct list_head *list, char *name, uuid_t pgfid) { quota_dentry_t *entry = NULL; gf_boolean_t found = _gf_false; + int ret = 0; - if (list == NULL) { - goto out; - } - - list_for_each_entry(entry, list, next) - { - if (gf_uuid_compare(pgfid, entry->par) == 0) { - found = _gf_true; - goto out; + if (!list_empty(list)) { + list_for_each_entry(entry, list, next) + { + if (gf_uuid_compare(pgfid, entry->par) == 0) { + found = _gf_true; + goto out; + } } } entry = __quota_dentry_new(NULL, name, pgfid); if (entry) list_add_tail(&entry->next, list); + else + ret = -1; out: if (found) return 0; - else + else if (ret == 0) return 1; + else + return -1; } /* This function iterates the parent list in inode * context and add unique parent to the list - * Returns number of dentry added to the list + * Returns number of dentry added to the list, or -1 on errors */ static int32_t quota_add_parents_from_ctx(quota_inode_ctx_t *ctx, struct list_head *list) @@ -718,15 +701,16 @@ quota_add_parents_from_ctx(quota_inode_ctx_t *ctx, struct list_head *list) list_for_each_entry(dentry, &ctx->parents, next) { ret = quota_add_parent(list, dentry->name, dentry->par); - if (ret == 1) count++; + else if (ret == -1) + break; } } UNLOCK(&ctx->lock); out: - return count; + return (ret == -1) ? -1 : count; } int32_t @@ -745,10 +729,9 @@ quota_build_ancestry_cbk(call_frame_t *frame, void *cookie, xlator_t *this, quota_dentry_t *dentry = NULL; quota_dentry_t *tmp = NULL; quota_inode_ctx_t *ctx = NULL; - struct list_head parents = { - 0, - }; + struct list_head parents; quota_local_t *local = NULL; + int ret; INIT_LIST_HEAD(&parents); @@ -823,7 +806,11 @@ quota_build_ancestry_cbk(call_frame_t *frame, void *cookie, xlator_t *this, quota_inode_ctx_get(local->loc.inode, this, &ctx, 0); - quota_add_parents_from_ctx(ctx, &parents); + ret = quota_add_parents_from_ctx(ctx, &parents); + if (ret == -1) { + op_errno = errno; + goto err; + } if (list_empty(&parents)) { /* we built ancestry for a directory */ @@ -838,7 +825,11 @@ quota_build_ancestry_cbk(call_frame_t *frame, void *cookie, xlator_t *this, GF_ASSERT (&entry->list != &entries->list); */ - quota_add_parent(&parents, entry->d_name, parent->gfid); + ret = quota_add_parent(&parents, entry->d_name, parent->gfid); + if (ret == -1) { + op_errno = errno; + goto err; + } } local->ancestry_cbk(&parents, local->loc.inode, 0, 0, local->ancestry_data); @@ -856,9 +847,11 @@ cleanup: parent = NULL; } - list_for_each_entry_safe(dentry, tmp, &parents, next) - { - __quota_dentry_free(dentry); + if (!list_empty(&parents)) { + list_for_each_entry_safe(dentry, tmp, &parents, next) + { + __quota_dentry_free(dentry); + } } return 0; @@ -1114,7 +1107,7 @@ quota_check_object_limit(call_frame_t *frame, quota_inode_ctx_t *ctx, timeout = priv->hard_timeout; } - if (!just_validated && quota_timeout(&ctx->tv, timeout)) { + if (!just_validated && quota_timeout(ctx->validate_time, timeout)) { need_validate = 1; } else if ((object_aggr_count) > ctx->object_hard_lim) { hard_limit_exceeded = 1; @@ -1181,7 +1174,7 @@ quota_check_size_limit(call_frame_t *frame, quota_inode_ctx_t *ctx, timeout = priv->hard_timeout; } - if (!just_validated && quota_timeout(&ctx->tv, timeout)) { + if (!just_validated && quota_timeout(ctx->validate_time, timeout)) { need_validate = 1; } else if (wouldbe_size >= ctx->hard_lim) { hard_limit_exceeded = 1; @@ -1750,19 +1743,13 @@ quota_writev_helper(call_frame_t *frame, xlator_t *this, fd_t *fd, if ((op_errno == EDQUOT) && (local->space_available > 0)) { new_count = iov_subset(vector, count, 0, local->space_available, - NULL); - - new_vector = GF_CALLOC(new_count, sizeof(struct iovec), - gf_common_mt_iovec); - if (new_vector == NULL) { + &new_vector, 0); + if (new_count < 0) { local->op_ret = -1; local->op_errno = ENOMEM; goto unwind; } - new_count = iov_subset(vector, count, 0, local->space_available, - new_vector); - vector = new_vector; count = new_count; } else if (op_errno == ENOENT || op_errno == ESTALE) { @@ -1834,9 +1821,7 @@ quota_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, quota_inode_ctx_t *ctx = NULL; quota_dentry_t *dentry = NULL, *tmp = NULL; call_stub_t *stub = NULL; - struct list_head head = { - 0, - }; + struct list_head head; inode_t *par_inode = NULL; priv = this->private; @@ -1876,9 +1861,13 @@ quota_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, priv = this->private; GF_VALIDATE_OR_GOTO(this->name, priv, unwind); - size = iov_length(vector, count); - parents = quota_add_parents_from_ctx(ctx, &head); + if (parents == -1) { + op_errno = errno; + goto unwind; + } + + size = iov_length(vector, count); LOCK(&local->lock); { @@ -1900,10 +1889,12 @@ quota_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, par_inode = do_quota_check_limit(frame, fd->inode, this, dentry, _gf_false); if (par_inode == NULL) { - /* remove stale entry from inode ctx */ - quota_dentry_del(ctx, dentry->name, dentry->par); - parents--; - fail_count++; + if (ctx) { + /* remove stale entry from inode ctx */ + quota_dentry_del(ctx, dentry->name, dentry->par); + parents--; + fail_count++; + } } else { inode_unref(par_inode); } @@ -3151,12 +3142,13 @@ off: return 0; } -int32_t +static int32_t quota_send_dir_limit_to_cli(call_frame_t *frame, xlator_t *this, inode_t *inode, - const char *name) + const char *name, const int namelen) { int32_t ret = 0; - char dir_limit[1024] = { + int dir_limit_len = 0; + char dir_limit[64] = { 0, }; dict_t *dict = NULL; @@ -3166,7 +3158,8 @@ quota_send_dir_limit_to_cli(call_frame_t *frame, xlator_t *this, inode_t *inode, priv = this->private; if (!priv->is_quota_on) { - snprintf(dir_limit, 1024, "Quota is disabled please turn on"); + dir_limit_len = snprintf(dir_limit, sizeof(dir_limit), + "Quota is disabled please turn on"); goto dict_set; } @@ -3175,7 +3168,8 @@ quota_send_dir_limit_to_cli(call_frame_t *frame, xlator_t *this, inode_t *inode, goto out; ctx = (quota_inode_ctx_t *)(unsigned long)value; - snprintf(dir_limit, 1024, "%" PRId64 ",%" PRId64, ctx->size, ctx->hard_lim); + dir_limit_len = snprintf(dir_limit, sizeof(dir_limit), + "%" PRId64 ",%" PRId64, ctx->size, ctx->hard_lim); dict_set: dict = dict_new(); @@ -3184,7 +3178,7 @@ dict_set: goto out; } - ret = dict_set_str(dict, (char *)name, dir_limit); + ret = dict_set_nstrn(dict, (char *)name, namelen, dir_limit, dir_limit_len); if (ret < 0) goto out; @@ -3207,7 +3201,9 @@ quota_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, int32_t ret = 0; if (name && strcasecmp(name, "trusted.limit.list") == 0) { - ret = quota_send_dir_limit_to_cli(frame, this, fd->inode, name); + ret = quota_send_dir_limit_to_cli(frame, this, fd->inode, + "trusted.limit.list", + SLEN("trusted.limit.list")); if (ret == 0) { return 0; } @@ -3225,7 +3221,9 @@ quota_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t ret = 0; if ((name != NULL) && strcasecmp(name, "trusted.limit.list") == 0) { - ret = quota_send_dir_limit_to_cli(frame, this, loc->inode, name); + ret = quota_send_dir_limit_to_cli(frame, this, loc->inode, + "trusted.limit.list", + SLEN("trusted.limit.list")); if (ret == 0) return 0; } @@ -3264,12 +3262,11 @@ quota_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - LOCK(&ctx->lock); - { - if (buf) - ctx->buf = *buf; + if (buf) { + LOCK(&ctx->lock); + ctx->buf = *buf; + UNLOCK(&ctx->lock); } - UNLOCK(&ctx->lock); out: QUOTA_STACK_UNWIND(stat, frame, op_ret, op_errno, buf, xdata); @@ -3343,12 +3340,11 @@ quota_fstat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - LOCK(&ctx->lock); - { - if (buf) - ctx->buf = *buf; + if (buf) { + LOCK(&ctx->lock); + ctx->buf = *buf; + UNLOCK(&ctx->lock); } - UNLOCK(&ctx->lock); out: QUOTA_STACK_UNWIND(fstat, frame, op_ret, op_errno, buf, xdata); @@ -3638,12 +3634,11 @@ quota_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto out; } - LOCK(&ctx->lock); - { - if (statpost) - ctx->buf = *statpost; + if (statpost) { + LOCK(&ctx->lock); + ctx->buf = *statpost; + UNLOCK(&ctx->lock); } - UNLOCK(&ctx->lock); out: QUOTA_STACK_UNWIND(setattr, frame, op_ret, op_errno, statpre, statpost, @@ -3959,7 +3954,7 @@ quota_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, VALIDATE_OR_GOTO(this, err); VALIDATE_OR_GOTO(loc, err); - if (xdata && dict_get(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) + if (xdata && dict_get_sizen(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) internal_fop = _gf_true; if (frame->root->pid >= 0 && internal_fop == _gf_false) { @@ -4320,7 +4315,8 @@ quota_statfs_validate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, goto resume; } - ret = quota_dict_get_meta(xdata, QUOTA_SIZE_KEY, &size); + ret = quota_dict_get_meta(xdata, QUOTA_SIZE_KEY, SLEN(QUOTA_SIZE_KEY), + &size); if (ret == -1) { gf_msg(this->name, GF_LOG_WARNING, EINVAL, Q_MSG_SIZE_KEY_MISSING, "size key not present in " @@ -4331,13 +4327,14 @@ quota_statfs_validate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, LOCK(&ctx->lock); { ctx->size = size.size; + ctx->validate_time = gf_time(); ctx->file_count = size.file_count; ctx->dir_count = size.dir_count; - gettimeofday(&ctx->tv, NULL); } UNLOCK(&ctx->lock); resume: + local->op_errno = op_errno; quota_link_count_decrement(frame); return 0; } @@ -4787,6 +4784,10 @@ quota_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, GF_VALIDATE_OR_GOTO(this->name, priv, unwind); parents = quota_add_parents_from_ctx(ctx, &head); + if (parents == -1) { + op_errno = errno; + goto unwind; + } /* * Note that by using len as the delta we're assuming the range from @@ -4847,7 +4848,7 @@ off: void quota_log_helper(char **usage_str, int64_t cur_size, inode_t *inode, - char **path, struct timeval *cur_time) + char **path, time_t *cur_time) { xlator_t *this = THIS; @@ -4866,7 +4867,7 @@ quota_log_helper(char **usage_str, int64_t cur_size, inode_t *inode, if (!(*path)) *path = uuid_utoa(inode->gfid); - gettimeofday(cur_time, NULL); + *cur_time = gf_time(); } /* Logs if @@ -4877,9 +4878,7 @@ void quota_log_usage(xlator_t *this, quota_inode_ctx_t *ctx, inode_t *inode, int64_t delta) { - struct timeval cur_time = { - 0, - }; + time_t cur_time = 0; char *usage_str = NULL; char *path = NULL; int64_t cur_size = 0; @@ -4905,12 +4904,12 @@ quota_log_usage(xlator_t *this, quota_inode_ctx_t *ctx, inode_t *inode, "path=%s", usage_str, priv->volume_uuid, path); - ctx->prev_log = cur_time; + ctx->prev_log_time = cur_time; } /* Usage is above soft limit */ else if (cur_size > ctx->soft_lim && - quota_timeout(&ctx->prev_log, priv->log_timeout)) { + quota_timeout(ctx->prev_log_time, priv->log_timeout)) { quota_log_helper(&usage_str, cur_size, inode, &path, &cur_time); gf_msg(this->name, GF_LOG_ALERT, 0, Q_MSG_CROSSED_SOFT_LIMIT, @@ -4921,9 +4920,12 @@ quota_log_usage(xlator_t *this, quota_inode_ctx_t *ctx, inode_t *inode, "path=%s", usage_str, priv->volume_uuid, path); - ctx->prev_log = cur_time; + ctx->prev_log_time = cur_time; } + if (path) + GF_FREE(path); + if (usage_str) GF_FREE(usage_str); } @@ -4979,6 +4981,43 @@ quota_forget(xlator_t *this, inode_t *inode) return 0; } +int +notify(xlator_t *this, int event, void *data, ...) +{ + quota_priv_t *priv = NULL; + int ret = 0; + rpc_clnt_t *rpc = NULL; + gf_boolean_t conn_status = _gf_true; + xlator_t *victim = data; + + priv = this->private; + if (!priv || !priv->is_quota_on) + goto out; + + if (event == GF_EVENT_PARENT_DOWN) { + rpc = priv->rpc_clnt; + if (rpc) { + rpc_clnt_disable(rpc); + pthread_mutex_lock(&priv->conn_mutex); + { + conn_status = priv->conn_status; + while (conn_status) { + (void)pthread_cond_wait(&priv->conn_cond, + &priv->conn_mutex); + conn_status = priv->conn_status; + } + } + pthread_mutex_unlock(&priv->conn_mutex); + gf_log(this->name, GF_LOG_INFO, + "Notify GF_EVENT_PARENT_DOWN for brick %s", victim->name); + } + } + +out: + ret = default_notify(this, event, data); + return ret; +} + int32_t init(xlator_t *this) { @@ -5021,6 +5060,10 @@ init(xlator_t *this) goto err; } + pthread_mutex_init(&priv->conn_mutex, NULL); + pthread_cond_init(&priv->conn_cond, NULL); + priv->conn_status = _gf_false; + if (priv->is_quota_on) { rpc = quota_enforcer_init(this, this->options); if (rpc == NULL) { @@ -5114,13 +5157,14 @@ quota_priv_dump(xlator_t *this) if (ret) goto out; else { - gf_proc_dump_write("soft-timeout", "%d", priv->soft_timeout); - gf_proc_dump_write("hard-timeout", "%d", priv->hard_timeout); - gf_proc_dump_write("alert-time", "%d", priv->log_timeout); + gf_proc_dump_write("soft-timeout", "%u", priv->soft_timeout); + gf_proc_dump_write("hard-timeout", "%u", priv->hard_timeout); + gf_proc_dump_write("alert-time", "%u", priv->log_timeout); gf_proc_dump_write("quota-on", "%d", priv->is_quota_on); gf_proc_dump_write("statfs", "%d", priv->consider_statfs); gf_proc_dump_write("volume-uuid", "%s", priv->volume_uuid); - gf_proc_dump_write("validation-count", "%ld", priv->validation_count); + gf_proc_dump_write("validation-count", "%" PRIu64, + priv->validation_count); } UNLOCK(&priv->lock); @@ -5133,20 +5177,22 @@ fini(xlator_t *this) { quota_priv_t *priv = NULL; rpc_clnt_t *rpc = NULL; - int i = 0, cnt = 0; priv = this->private; if (!priv) return; rpc = priv->rpc_clnt; priv->rpc_clnt = NULL; - this->private = NULL; if (rpc) { - cnt = GF_ATOMIC_GET(rpc->refcount); - for (i = 0; i < cnt; i++) - rpc_clnt_unref(rpc); + rpc_clnt_connection_cleanup(&rpc->conn); + rpc_clnt_unref(rpc); } + + this->private = NULL; LOCK_DESTROY(&priv->lock); + pthread_mutex_destroy(&priv->conn_mutex); + pthread_cond_destroy(&priv->conn_cond); + GF_FREE(priv); if (this->local_pool) { mem_pool_destroy(this->local_pool); @@ -5274,3 +5320,17 @@ struct volume_options options[] = { .tags = {}, }, {.key = {NULL}}}; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "quota", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/quota/src/quota.h b/xlators/features/quota/src/quota.h index 7ced27a6188..0395d78c9ef 100644 --- a/xlators/features/quota/src/quota.h +++ b/xlators/features/quota/src/quota.h @@ -10,25 +10,22 @@ #ifndef _QUOTA_H #define _QUOTA_H -#include "xlator.h" -#include "call-stub.h" -#include "defaults.h" -#include "common-utils.h" +#include <glusterfs/call-stub.h> #include "quota-mem-types.h" -#include "glusterfs.h" -#include "compat.h" -#include "logging.h" -#include "dict.h" -#include "gf-event.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/logging.h> +#include <glusterfs/dict.h> +#include <glusterfs/gf-event.h> #include "rpcsvc.h" #include "rpc-clnt.h" -#include "byte-order.h" +#include <glusterfs/byte-order.h> #include "glusterfs3-xdr.h" #include "glusterfs3.h" #include "xdr-generic.h" -#include "compat-errno.h" +#include <glusterfs/compat-errno.h> #include "protocol-common.h" -#include "quota-common-utils.h" +#include <glusterfs/quota-common-utils.h> #include "quota-messages.h" #define DIRTY "dirty" @@ -47,7 +44,7 @@ #define QUOTA_WIND_FOR_INTERNAL_FOP(xdata, label) \ do { \ - if (xdata && dict_get(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) \ + if (xdata && dict_get_sizen(xdata, GLUSTERFS_INTERNAL_FOP_KEY)) \ goto label; \ } while (0) @@ -156,8 +153,8 @@ struct quota_inode_ctx { int64_t object_soft_lim; struct iatt buf; struct list_head parents; - struct timeval tv; - struct timeval prev_log; + time_t validate_time; + time_t prev_log_time; gf_boolean_t ancestry_built; gf_lock_t lock; }; @@ -202,6 +199,7 @@ struct quota_local { typedef struct quota_local quota_local_t; struct quota_priv { + /* FIXME: consider time_t for timeouts. */ uint32_t soft_timeout; uint32_t hard_timeout; uint32_t log_timeout; @@ -217,6 +215,9 @@ struct quota_priv { char *volume_uuid; uint64_t validation_count; int32_t quotad_conn_status; + pthread_mutex_t conn_mutex; + pthread_cond_t conn_cond; + gf_boolean_t conn_status; }; typedef struct quota_priv quota_priv_t; diff --git a/xlators/features/quota/src/quotad-aggregator.c b/xlators/features/quota/src/quotad-aggregator.c index d30b8cdedfc..75d47867b5b 100644 --- a/xlators/features/quota/src/quotad-aggregator.c +++ b/xlators/features/quota/src/quotad-aggregator.c @@ -13,7 +13,14 @@ #include "quotad-helpers.h" #include "quotad-aggregator.h" -struct rpcsvc_program quotad_aggregator_prog; +static char *qd_ext_xattrs[] = { + QUOTA_SIZE_KEY, + QUOTA_LIMIT_KEY, + QUOTA_LIMIT_OBJECTS_KEY, + NULL, +}; + +static struct rpcsvc_program quotad_aggregator_prog; struct iobuf * quotad_serialize_reply(rpcsvc_request_t *req, void *arg, struct iovec *outmsg, @@ -132,17 +139,20 @@ quotad_aggregator_getlimit_cbk(xlator_t *this, call_frame_t *frame, int ret = -1; int type = 0; + if (!rsp || (rsp->op_ret == -1)) + goto reply; + GF_PROTOCOL_DICT_UNSERIALIZE(frame->this, xdata, (rsp->xdata.xdata_val), (rsp->xdata.xdata_len), rsp->op_ret, rsp->op_errno, out); if (xdata) { state = frame->root->state; - ret = dict_get_int32(state->xdata, "type", &type); + ret = dict_get_int32n(state->req_xdata, "type", SLEN("type"), &type); if (ret < 0) goto out; - ret = dict_set_int32(xdata, "type", type); + ret = dict_set_int32_sizen(xdata, "type", type); if (ret < 0) goto out; } @@ -166,8 +176,9 @@ out: } reply: - quotad_aggregator_submit_reply(frame, frame->local, (void *)&cli_rsp, NULL, - 0, NULL, (xdrproc_t)xdr_gf_cli_rsp); + quotad_aggregator_submit_reply(frame, (frame) ? frame->local : NULL, + (void *)&cli_rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_cli_rsp); dict_unref(xdata); GF_FREE(cli_rsp.dict.dict_val); @@ -182,22 +193,20 @@ quotad_aggregator_getlimit(rpcsvc_request_t *req) {0}, }; gf_cli_rsp cli_rsp = {0}; - gfs3_lookup_req args = { - { - 0, - }, - }; quotad_aggregator_state_t *state = NULL; xlator_t *this = NULL; dict_t *dict = NULL; int ret = -1, op_errno = 0; char *gfid_str = NULL; uuid_t gfid = {0}; + char *volume_uuid = NULL; GF_VALIDATE_OR_GOTO("quotad-aggregator", req, err); this = THIS; + cli_req.dict.dict_val = alloca(req->msg[0].iov_len); + ret = xdr_to_generic(req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req); if (ret < 0) { // failed to decode msg; @@ -219,7 +228,12 @@ quotad_aggregator_getlimit(rpcsvc_request_t *req) } } - ret = dict_get_str(dict, "gfid", &gfid_str); + ret = dict_get_strn(dict, "gfid", SLEN("gfid"), &gfid_str); + if (ret) { + goto err; + } + + ret = dict_get_strn(dict, "volume-uuid", SLEN("volume-uuid"), &volume_uuid); if (ret) { goto err; } @@ -232,34 +246,31 @@ quotad_aggregator_getlimit(rpcsvc_request_t *req) goto errx; } state = frame->root->state; - state->xdata = dict; + state->req_xdata = dict; + state->xdata = dict_new(); + dict = NULL; - ret = dict_set_int32(state->xdata, QUOTA_LIMIT_KEY, 42); + ret = dict_set_int32_sizen(state->xdata, QUOTA_LIMIT_KEY, 42); if (ret) goto err; - ret = dict_set_int32(state->xdata, QUOTA_LIMIT_OBJECTS_KEY, 42); + ret = dict_set_int32_sizen(state->xdata, QUOTA_LIMIT_OBJECTS_KEY, 42); if (ret) { gf_msg(this->name, GF_LOG_ERROR, ENOMEM, Q_MSG_ENOMEM, "Failed to set QUOTA_LIMIT_OBJECTS_KEY"); goto err; } - ret = dict_set_int32(state->xdata, QUOTA_SIZE_KEY, 42); + ret = dict_set_int32_sizen(state->xdata, QUOTA_SIZE_KEY, 42); if (ret) goto err; - ret = dict_set_int32(state->xdata, GET_ANCESTRY_PATH_KEY, 42); + ret = dict_set_int32_sizen(state->xdata, GET_ANCESTRY_PATH_KEY, 42); if (ret) goto err; - memcpy(&args.gfid, &gfid, 16); - - args.bname = alloca(req->msg[0].iov_len); - args.xdata.xdata_val = alloca(req->msg[0].iov_len); - - ret = qd_nameless_lookup(this, frame, &args, state->xdata, - quotad_aggregator_getlimit_cbk); + ret = qd_nameless_lookup(this, frame, (char *)gfid, state->xdata, + volume_uuid, quotad_aggregator_getlimit_cbk); if (ret) { cli_rsp.op_errno = ret; goto errx; @@ -276,14 +287,14 @@ errx: quotad_aggregator_getlimit_cbk(this, frame, &cli_rsp); if (dict) dict_unref(dict); - return ret; } int quotad_aggregator_lookup_cbk(xlator_t *this, call_frame_t *frame, void *rsp) { - quotad_aggregator_submit_reply(frame, frame->local, rsp, NULL, 0, NULL, + quotad_aggregator_submit_reply(frame, frame ? frame->local : NULL, rsp, + NULL, 0, NULL, (xdrproc_t)xdr_gfs3_lookup_rsp); return 0; @@ -298,12 +309,14 @@ quotad_aggregator_lookup(rpcsvc_request_t *req) 0, }, }; - int ret = -1, op_errno = 0; + int i = 0, ret = -1, op_errno = 0; gfs3_lookup_rsp rsp = { 0, }; quotad_aggregator_state_t *state = NULL; xlator_t *this = NULL; + dict_t *dict = NULL; + char *volume_uuid = NULL; GF_VALIDATE_OR_GOTO("quotad-aggregator", req, err); @@ -326,16 +339,34 @@ quotad_aggregator_lookup(rpcsvc_request_t *req) state = frame->root->state; - GF_PROTOCOL_DICT_UNSERIALIZE(this, state->xdata, (args.xdata.xdata_val), + GF_PROTOCOL_DICT_UNSERIALIZE(this, dict, (args.xdata.xdata_val), (args.xdata.xdata_len), ret, op_errno, err); - ret = qd_nameless_lookup(this, frame, &args, state->xdata, + ret = dict_get_str(dict, "volume-uuid", &volume_uuid); + if (ret) { + goto err; + } + + state->xdata = dict_new(); + + for (i = 0; qd_ext_xattrs[i]; i++) { + if (dict_get(dict, qd_ext_xattrs[i])) { + ret = dict_set_uint32(state->xdata, qd_ext_xattrs[i], 1); + if (ret < 0) + goto err; + } + } + + ret = qd_nameless_lookup(this, frame, args.gfid, state->xdata, volume_uuid, quotad_aggregator_lookup_cbk); if (ret) { rsp.op_errno = ret; goto err; } + if (dict) + dict_unref(dict); + return ret; err: @@ -343,6 +374,9 @@ err: rsp.op_errno = op_errno; quotad_aggregator_lookup_cbk(this, frame, &rsp); + if (dict) + dict_unref(dict); + return ret; } @@ -384,16 +418,21 @@ quotad_aggregator_init(xlator_t *this) return 0; } - ret = dict_set_str(this->options, "transport.address-family", "unix"); + ret = dict_set_nstrn(this->options, "transport.address-family", + SLEN("transport.address-family"), "unix", + SLEN("unix")); if (ret) goto out; - ret = dict_set_str(this->options, "transport-type", "socket"); + ret = dict_set_nstrn(this->options, "transport-type", + SLEN("transport-type"), "socket", SLEN("socket")); if (ret) goto out; - ret = dict_set_str(this->options, "transport.socket.listen-path", - "/var/run/gluster/quotad.socket"); + ret = dict_set_nstrn(this->options, "transport.socket.listen-path", + SLEN("transport.socket.listen-path"), + "/var/run/gluster/quotad.socket", + SLEN("/var/run/gluster/quotad.socket")); if (ret) goto out; @@ -439,15 +478,15 @@ out: return ret; } -rpcsvc_actor_t quotad_aggregator_actors[GF_AGGREGATOR_MAXVALUE] = { - [GF_AGGREGATOR_NULL] = {"NULL", GF_AGGREGATOR_NULL, NULL, NULL, 0, DRC_NA}, - [GF_AGGREGATOR_LOOKUP] = {"LOOKUP", GF_AGGREGATOR_NULL, - quotad_aggregator_lookup, NULL, 0, DRC_NA}, - [GF_AGGREGATOR_GETLIMIT] = {"GETLIMIT", GF_AGGREGATOR_GETLIMIT, - quotad_aggregator_getlimit, NULL, 0, DRC_NA}, +static rpcsvc_actor_t quotad_aggregator_actors[GF_AGGREGATOR_MAXVALUE] = { + [GF_AGGREGATOR_NULL] = {"NULL", NULL, NULL, GF_AGGREGATOR_NULL, DRC_NA, 0}, + [GF_AGGREGATOR_LOOKUP] = {"LOOKUP", quotad_aggregator_lookup, NULL, + GF_AGGREGATOR_NULL, DRC_NA, 0}, + [GF_AGGREGATOR_GETLIMIT] = {"GETLIMIT", quotad_aggregator_getlimit, NULL, + GF_AGGREGATOR_GETLIMIT, DRC_NA, 0}, }; -struct rpcsvc_program quotad_aggregator_prog = { +static struct rpcsvc_program quotad_aggregator_prog = { .progname = "GlusterFS 3.3", .prognum = GLUSTER_AGGREGATOR_PROGRAM, .progver = GLUSTER_AGGREGATOR_VERSION, diff --git a/xlators/features/quota/src/quotad-aggregator.h b/xlators/features/quota/src/quotad-aggregator.h index 02a0094102f..706592c7d50 100644 --- a/xlators/features/quota/src/quotad-aggregator.h +++ b/xlators/features/quota/src/quotad-aggregator.h @@ -12,9 +12,9 @@ #define _QUOTAD_AGGREGATOR_H #include "quota.h" -#include "stack.h" +#include <glusterfs/stack.h> #include "glusterfs3-xdr.h" -#include "inode.h" +#include <glusterfs/inode.h> typedef struct { void *pool; @@ -23,13 +23,15 @@ typedef struct { inode_table_t *itable; loc_t loc; dict_t *xdata; + dict_t *req_xdata; } quotad_aggregator_state_t; typedef int (*quotad_aggregator_lookup_cbk_t)(xlator_t *this, call_frame_t *frame, void *rsp); int -qd_nameless_lookup(xlator_t *this, call_frame_t *frame, gfs3_lookup_req *req, - dict_t *xdata, quotad_aggregator_lookup_cbk_t lookup_cbk); +qd_nameless_lookup(xlator_t *this, call_frame_t *frame, char *gfid, + dict_t *xdata, char *volume_uuid, + quotad_aggregator_lookup_cbk_t lookup_cbk); int quotad_aggregator_init(xlator_t *this); diff --git a/xlators/features/quota/src/quotad-helpers.c b/xlators/features/quota/src/quotad-helpers.c index be8f9080f14..51ff1d7e98d 100644 --- a/xlators/features/quota/src/quotad-helpers.c +++ b/xlators/features/quota/src/quotad-helpers.c @@ -47,6 +47,9 @@ quotad_aggregator_free_state(quotad_aggregator_state_t *state) if (state->xdata) dict_unref(state->xdata); + if (state->req_xdata) + dict_unref(state->req_xdata); + GF_FREE(state); } @@ -73,7 +76,6 @@ quotad_aggregator_alloc_frame(rpcsvc_request_t *req) goto out; frame->root->state = state; - frame->root->unique = 0; frame->this = this; out: @@ -93,8 +95,6 @@ quotad_aggregator_get_frame_from_req(rpcsvc_request_t *req) frame->root->op = req->procnum; - frame->root->unique = req->xid; - frame->root->uid = req->uid; frame->root->gid = req->gid; frame->root->pid = req->pid; diff --git a/xlators/features/quota/src/quotad.c b/xlators/features/quota/src/quotad.c index 1b61468f183..643f25c9c2a 100644 --- a/xlators/features/quota/src/quotad.c +++ b/xlators/features/quota/src/quotad.c @@ -9,7 +9,6 @@ */ #include "quota.h" #include "quotad-aggregator.h" -#include "common-utils.h" int qd_notify(xlator_t *this, int32_t event, void *data, ...) @@ -81,14 +80,16 @@ qd_find_subvol(xlator_t *this, char *volume_uuid) xlator_list_t *child = NULL; xlator_t *subvol = NULL; char key[1024]; + int keylen = 0; char *optstr = NULL; if (!this || !volume_uuid) goto out; for (child = this->children; child; child = child->next) { - snprintf(key, 1024, "%s.volume-id", child->xlator->name); - if (dict_get_str(this->options, key, &optstr) < 0) + keylen = snprintf(key, sizeof(key), "%s.volume-id", + child->xlator->name); + if (dict_get_strn(this->options, key, keylen, &optstr) < 0) continue; if (strcmp(optstr, volume_uuid) == 0) { @@ -102,8 +103,9 @@ out: } int -qd_nameless_lookup(xlator_t *this, call_frame_t *frame, gfs3_lookup_req *req, - dict_t *xdata, quotad_aggregator_lookup_cbk_t lookup_cbk) +qd_nameless_lookup(xlator_t *this, call_frame_t *frame, char *gfid, + dict_t *xdata, char *volume_uuid, + quotad_aggregator_lookup_cbk_t lookup_cbk) { gfs3_lookup_rsp rsp = { 0, @@ -114,7 +116,6 @@ qd_nameless_lookup(xlator_t *this, call_frame_t *frame, gfs3_lookup_req *req, }; quotad_aggregator_state_t *state = NULL; xlator_t *subvol = NULL; - char *volume_uuid = NULL; state = frame->root->state; @@ -126,13 +127,7 @@ qd_nameless_lookup(xlator_t *this, call_frame_t *frame, gfs3_lookup_req *req, goto out; } - memcpy(loc.gfid, req->gfid, 16); - - ret = dict_get_str(xdata, "volume-uuid", &volume_uuid); - if (ret < 0) { - op_errno = EINVAL; - goto out; - } + memcpy(loc.gfid, gfid, 16); ret = dict_set_int8(xdata, QUOTA_READ_ONLY_KEY, 1); if (ret < 0) { @@ -217,11 +212,6 @@ err: return ret; } -class_methods_t class_methods = {.init = qd_init, - .fini = qd_fini, - .reconfigure = qd_reconfigure, - .notify = qd_notify}; - struct xlator_fops fops = {}; struct xlator_cbks cbks = {}; @@ -237,4 +227,19 @@ struct volume_options options[] = { .key = {"transport.*"}, .type = GF_OPTION_TYPE_ANY, }, - {.key = {NULL}}}; + {.key = {NULL}}, +}; + +xlator_api_t xlator_api = { + .init = qd_init, + .fini = qd_fini, + .reconfigure = qd_reconfigure, + .notify = qd_notify, + .mem_acct_init = mem_acct_init, + .op_version = {1}, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "quotad", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/quota/src/quotad.sym b/xlators/features/quota/src/quotad.sym deleted file mode 100644 index 0829ffe1584..00000000000 --- a/xlators/features/quota/src/quotad.sym +++ /dev/null @@ -1,7 +0,0 @@ -fops -cbks -class_methods -options -mem_acct_init -reconfigure -dumpops diff --git a/xlators/features/read-only/src/read-only-common.c b/xlators/features/read-only/src/read-only-common.c index 39985169991..9640e7e3eee 100644 --- a/xlators/features/read-only/src/read-only-common.c +++ b/xlators/features/read-only/src/read-only-common.c @@ -9,7 +9,7 @@ */ #include "read-only.h" #include "read-only-mem-types.h" -#include "defaults.h" +#include <glusterfs/defaults.h> gf_boolean_t is_readonly_or_worm_enabled(call_frame_t *frame, xlator_t *this) diff --git a/xlators/features/read-only/src/read-only-common.h b/xlators/features/read-only/src/read-only-common.h index 32719da28f1..5561961ffa2 100644 --- a/xlators/features/read-only/src/read-only-common.h +++ b/xlators/features/read-only/src/read-only-common.h @@ -7,8 +7,8 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> gf_boolean_t is_readonly_or_worm_enabled(call_frame_t *frame, xlator_t *this); diff --git a/xlators/features/read-only/src/read-only-mem-types.h b/xlators/features/read-only/src/read-only-mem-types.h index 4baaeb41216..c67d6c02cd0 100644 --- a/xlators/features/read-only/src/read-only-mem-types.h +++ b/xlators/features/read-only/src/read-only-mem-types.h @@ -11,7 +11,7 @@ #ifndef __READONLY_MEM_TYPES_H__ #define __READONLY_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_read_only_mem_types_ { gf_read_only_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/read-only/src/read-only.c b/xlators/features/read-only/src/read-only.c index c92a9801196..48654998e63 100644 --- a/xlators/features/read-only/src/read-only.c +++ b/xlators/features/read-only/src/read-only.c @@ -7,7 +7,6 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "defaults.h" #include "read-only-common.h" #include "read-only-mem-types.h" #include "read-only.h" @@ -130,3 +129,16 @@ struct volume_options options[] = { "\"off\" by default."}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "read-only", + .category = GF_TECH_PREVIEW, +}; diff --git a/xlators/features/read-only/src/read-only.h b/xlators/features/read-only/src/read-only.h index d74053a2a8f..aced5d3c577 100644 --- a/xlators/features/read-only/src/read-only.h +++ b/xlators/features/read-only/src/read-only.h @@ -11,25 +11,26 @@ #ifndef __READONLY_H__ #define __READONLY_H__ -#include "read-only-mem-types.h" -#include "xlator.h" +#include <stdint.h> // for uint64_t, uint8_t +#include <sys/time.h> // for time_t +#include "glusterfs/glusterfs.h" // for gf_boolean_t typedef struct { uint8_t worm : 1; uint8_t retain : 1; uint8_t legal_hold : 1; uint8_t ret_mode : 1; - uint64_t ret_period; - uint64_t auto_commit_period; + int64_t ret_period; + int64_t auto_commit_period; } worm_reten_state_t; typedef struct { gf_boolean_t readonly_or_worm_enabled; gf_boolean_t worm_file; gf_boolean_t worm_files_deletable; - uint64_t reten_period; - uint64_t com_period; - char *reten_mode; + int64_t reten_period; + int64_t com_period; + int reten_mode; time_t start_time; } read_only_priv_t; diff --git a/xlators/features/read-only/src/worm-helper.c b/xlators/features/read-only/src/worm-helper.c index 3f882fe08d6..df45f2a940b 100644 --- a/xlators/features/read-only/src/worm-helper.c +++ b/xlators/features/read-only/src/worm-helper.c @@ -9,8 +9,8 @@ */ #include "read-only-mem-types.h" #include "read-only.h" -#include "xlator.h" -#include "syncop.h" +#include <glusterfs/xlator.h> +#include <glusterfs/syncop.h> #include "worm-helper.h" /*Function to check whether file is read-only. @@ -41,7 +41,7 @@ worm_init_state(xlator_t *this, gf_boolean_t fop_with_fd, void *file_ptr) GF_VALIDATE_OR_GOTO("worm", this, out); GF_VALIDATE_OR_GOTO(this->name, file_ptr, out); - start_time = time(NULL); + start_time = gf_time(); dict = dict_new(); if (!dict) { gf_log(this->name, GF_LOG_ERROR, "Error creating the dict"); @@ -84,10 +84,7 @@ worm_set_state(xlator_t *this, gf_boolean_t fop_with_fd, void *file_ptr, retention_state->worm = 1; retention_state->retain = 1; retention_state->legal_hold = 0; - if (strcmp(priv->reten_mode, "relax") == 0) - retention_state->ret_mode = 0; - else - retention_state->ret_mode = 1; + retention_state->ret_mode = priv->reten_mode; retention_state->ret_period = priv->reten_period; retention_state->auto_commit_period = priv->com_period; if (fop_with_fd) @@ -97,7 +94,7 @@ worm_set_state(xlator_t *this, gf_boolean_t fop_with_fd, void *file_ptr, if (ret) goto out; stbuf->ia_mtime = stpre.ia_mtime; - stbuf->ia_atime = time(NULL) + retention_state->ret_period; + stbuf->ia_atime = gf_time() + retention_state->ret_period; if (fop_with_fd) ret = syncop_fsetattr(this, (fd_t *)file_ptr, stbuf, GF_SET_ATTR_ATIME, @@ -289,6 +286,7 @@ gf_worm_state_transition(xlator_t *this, gf_boolean_t fop_with_fd, { int op_errno = EROFS; int ret = -1; + time_t now = 0; uint64_t com_period = 0; uint64_t start_time = 0; dict_t *dict = NULL; @@ -340,8 +338,10 @@ gf_worm_state_transition(xlator_t *this, gf_boolean_t fop_with_fd, goto out; } - if (ret == -1 && (time(NULL) - start_time) >= com_period) { - if ((time(NULL) - stbuf.ia_mtime) >= com_period) { + now = gf_time(); + + if (ret == -1 && (now - start_time) >= com_period) { + if ((now - stbuf.ia_mtime) >= com_period) { ret = worm_set_state(this, fop_with_fd, file_ptr, &reten_state, &stbuf); if (ret) { @@ -355,10 +355,10 @@ gf_worm_state_transition(xlator_t *this, gf_boolean_t fop_with_fd, op_errno = 0; goto out; } - } else if (ret == -1 && (time(NULL) - start_time) < com_period) { + } else if (ret == -1 && (now - start_time) < com_period) { op_errno = 0; goto out; - } else if (reten_state.retain && ((time(NULL) >= stbuf.ia_atime))) { + } else if (reten_state.retain && ((now >= stbuf.ia_atime))) { gf_worm_state_lookup(this, fop_with_fd, file_ptr, &reten_state, &stbuf); } if (reten_state.worm && !reten_state.retain && priv->worm_files_deletable && diff --git a/xlators/features/read-only/src/worm.c b/xlators/features/read-only/src/worm.c index db128b75196..1cc5526d5cd 100644 --- a/xlators/features/read-only/src/worm.c +++ b/xlators/features/read-only/src/worm.c @@ -7,12 +7,12 @@ later), or the GNU General Public License, version 2 (GPLv2), in all cases as published by the Free Software Foundation. */ -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "read-only-common.h" #include "read-only-mem-types.h" #include "read-only.h" -#include "syncop.h" +#include <glusterfs/syncop.h> #include "worm-helper.h" int32_t @@ -292,6 +292,12 @@ worm_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, goto out; } } + reten_state.ret_period = reten_state.ret_period + stbuf->ia_atime - + stpre.ia_atime; + ret = gf_worm_set_xattr(this, &reten_state, _gf_false, loc); + if (ret) { + goto out; + } stbuf->ia_mtime = stpre.ia_mtime; } } @@ -372,6 +378,13 @@ worm_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, goto out; } } + reten_state.ret_period = reten_state.ret_period + stbuf->ia_atime - + stpre.ia_atime; + ret = gf_worm_set_xattr(this, &reten_state, _gf_true, fd); + if (ret) { + goto out; + } + stbuf->ia_mtime = stpre.ia_mtime; } } @@ -427,29 +440,22 @@ worm_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, { int ret = 0; read_only_priv_t *priv = NULL; - dict_t *dict = NULL; + // In case of an error exit because fd can be NULL and this would + // cause an segfault when performing fsetxattr . We explicitly + // unwind to avoid future problems + if (op_ret < 0) { + goto out; + } priv = this->private; GF_ASSERT(priv); if (priv->worm_file) { - dict = dict_new(); - if (!dict) { - gf_log(this->name, GF_LOG_ERROR, - "Error creating the " - "dict"); - goto out; - } - ret = dict_set_int8(dict, "trusted.worm_file", 1); + ret = fd_ctx_set(fd, this, 1); if (ret) { gf_log(this->name, GF_LOG_ERROR, - "Error in setting " - "the dict"); - goto out; - } - ret = syncop_fsetxattr(this, fd, dict, 0, NULL, NULL); - if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Error setting xattr"); - goto out; + "Failed to set the fd ctx " + "for gfid:%s . Worm feature may not work for the gfid", + uuid_utoa(inode->gfid)); } ret = worm_init_state(this, _gf_true, fd); if (ret) { @@ -460,8 +466,6 @@ worm_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, out: STACK_UNWIND_STRICT(create, frame, op_ret, op_errno, fd, inode, buf, preparent, postparent, xdata); - if (dict) - dict_unref(dict); return ret; } @@ -475,11 +479,21 @@ worm_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, return 0; } +static void +set_reten_mode(read_only_priv_t *priv, char *reten_mode) +{ + if (strcmp(reten_mode, "relax") == 0) + priv->reten_mode = 0; + else + priv->reten_mode = 1; +} + int32_t init(xlator_t *this) { int ret = -1; read_only_priv_t *priv = NULL; + char *reten_mode = NULL; if (!this->children || this->children->next) { gf_log(this->name, GF_LOG_ERROR, @@ -509,9 +523,10 @@ init(xlator_t *this) GF_OPTION_INIT("worm", priv->readonly_or_worm_enabled, bool, out); GF_OPTION_INIT("worm-file-level", priv->worm_file, bool, out); - GF_OPTION_INIT("default-retention-period", priv->reten_period, uint64, out); - GF_OPTION_INIT("auto-commit-period", priv->com_period, uint64, out); - GF_OPTION_INIT("retention-mode", priv->reten_mode, str, out); + GF_OPTION_INIT("default-retention-period", priv->reten_period, int64, out); + GF_OPTION_INIT("auto-commit-period", priv->com_period, int64, out); + GF_OPTION_INIT("retention-mode", reten_mode, str, out); + set_reten_mode(priv, reten_mode); GF_OPTION_INIT("worm-files-deletable", priv->worm_files_deletable, bool, out); @@ -524,6 +539,7 @@ int reconfigure(xlator_t *this, dict_t *options) { read_only_priv_t *priv = NULL; + char *reten_mode = NULL; int ret = -1; priv = this->private; @@ -533,9 +549,10 @@ reconfigure(xlator_t *this, dict_t *options) out); GF_OPTION_RECONF("worm-file-level", priv->worm_file, options, bool, out); GF_OPTION_RECONF("default-retention-period", priv->reten_period, options, - uint64, out); - GF_OPTION_RECONF("retention-mode", priv->reten_mode, options, str, out); - GF_OPTION_RECONF("auto-commit-period", priv->com_period, options, uint64, + int64, out); + GF_OPTION_RECONF("retention-mode", reten_mode, options, str, out); + set_reten_mode(priv, reten_mode); + GF_OPTION_RECONF("auto-commit-period", priv->com_period, options, int64, out); GF_OPTION_RECONF("worm-files-deletable", priv->worm_files_deletable, options, bool, out); @@ -556,6 +573,7 @@ fini(xlator_t *this) mem_put(priv); this->private = NULL; mem_pool_destroy(this->local_pool); + this->local_pool = NULL; out: return; } @@ -583,7 +601,62 @@ struct xlator_fops fops = { .lk = ro_lk, }; -struct xlator_cbks cbks; +int32_t +worm_release(xlator_t *this, fd_t *fd) +{ + dict_t *dict = NULL; + int ret = -1; + dict = dict_new(); + uint64_t value = 0; + loc_t loc = { + 0, + }; + read_only_priv_t *priv = NULL; + priv = this->private; + + if (priv->worm_file) { + if (!dict) { + gf_log(this->name, GF_LOG_ERROR, "Error creating the dict"); + goto out; + } + + ret = fd_ctx_get(fd, this, &value); + if (ret) { + gf_log(this->name, GF_LOG_DEBUG, "Failed to get the fd ctx"); + } + if (!value) { + goto out; + } + + ret = dict_set_int8(dict, "trusted.worm_file", 1); + if (ret) { + gf_log(this->name, GF_LOG_ERROR, + "Error in setting " + "the dict"); + goto out; + } + + loc.inode = inode_ref(fd->inode); + gf_uuid_copy(loc.gfid, fd->inode->gfid); + ret = syncop_setxattr(this, &loc, dict, 0, NULL, NULL); + if (ret) { + gf_log(this->name, GF_LOG_ERROR, "Error setting xattr"); + goto out; + } + + gf_worm_state_transition(this, _gf_false, &loc, GF_FOP_WRITE); + } + +out: + loc_wipe(&loc); + if (dict) + dict_unref(dict); + return 0; +} + +struct xlator_cbks cbks = { + .release = worm_release, +}; struct volume_options options[] = { {.key = {"worm"}, @@ -634,3 +707,16 @@ struct volume_options options[] = { .description = "Auto commit period for the files."}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "worm", + .category = GF_TECH_PREVIEW, +}; diff --git a/xlators/features/sdfs/src/sdfs-messages.h b/xlators/features/sdfs/src/sdfs-messages.h index cf866c8512a..3053efa8935 100644 --- a/xlators/features/sdfs/src/sdfs-messages.h +++ b/xlators/features/sdfs/src/sdfs-messages.h @@ -11,7 +11,7 @@ #ifndef _DFS_MESSAGES_H_ #define _DFS_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* file bit-rot-bitd-messages.h * brief SDFS log-message IDs and their descriptions diff --git a/xlators/features/sdfs/src/sdfs.c b/xlators/features/sdfs/src/sdfs.c index 5dbe0653cbc..aaf13f0852e 100644 --- a/xlators/features/sdfs/src/sdfs.c +++ b/xlators/features/sdfs/src/sdfs.c @@ -139,6 +139,8 @@ sdfs_get_new_frame_common(call_frame_t *frame, call_frame_t **new_frame) } local->main_frame = frame; + /*Set unique lk-owner for the fop*/ + set_lk_owner_from_ptr(&(*new_frame)->root->lk_owner, (*new_frame)->root); ret = 0; err: @@ -175,9 +177,10 @@ sdfs_get_new_frame(call_frame_t *frame, loc_t *loc, call_frame_t **new_frame) ret = 0; err: - if ((ret < 0) && (*new_frame != NULL)) { + if (ret && (*new_frame)) { SDFS_STACK_DESTROY((*new_frame)); *new_frame = NULL; + ret = -1; } return ret; @@ -868,6 +871,8 @@ sdfs_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, op_errno = ENOMEM; goto err; } + /*Set unique lk-owner for the fop*/ + set_lk_owner_from_ptr(&new_frame->root->lk_owner, new_frame->root); gf_client_ref(client); new_frame->root->client = client; @@ -1121,6 +1126,8 @@ sdfs_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, op_errno = ENOMEM; goto err; } + /*Set unique lk-owner for the fop*/ + set_lk_owner_from_ptr(&new_frame->root->lk_owner, new_frame->root); gf_client_ref(client); new_frame->root->client = client; @@ -1425,12 +1432,12 @@ out: return ret; } -int +void fini(xlator_t *this) { mem_pool_destroy(this->local_pool); - - return 0; + this->local_pool = NULL; + return; } struct xlator_fops fops = { @@ -1451,10 +1458,22 @@ struct xlator_cbks cbks; struct volume_options options[] = { {.key = {"pass-through"}, .type = GF_OPTION_TYPE_BOOL, - .default_value = "false", + .default_value = "true", .op_version = {GD_OP_VERSION_4_1_0}, .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC | OPT_FLAG_CLIENT_OPT, .tags = {"sdfs"}, .description = "Enable/Disable dentry serialize functionality"}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .op_version = {GD_OP_VERSION_4_0_0}, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "sdfs", + .category = GF_TECH_PREVIEW, +}; diff --git a/xlators/features/sdfs/src/sdfs.h b/xlators/features/sdfs/src/sdfs.h index 986d7c2731c..dded5a2d7fc 100644 --- a/xlators/features/sdfs/src/sdfs.h +++ b/xlators/features/sdfs/src/sdfs.h @@ -8,10 +8,10 @@ cases as published by the Free Software Foundation. */ -#include "xlator.h" -#include "call-stub.h" +#include <glusterfs/xlator.h> +#include <glusterfs/call-stub.h> #include "sdfs-messages.h" -#include "atomic.h" +#include <glusterfs/atomic.h> #define SDFS_LOCK_COUNT_MAX 2 diff --git a/xlators/features/selinux/src/selinux-mem-types.h b/xlators/features/selinux/src/selinux-mem-types.h index a8c544fba52..553e59e5a9d 100644 --- a/xlators/features/selinux/src/selinux-mem-types.h +++ b/xlators/features/selinux/src/selinux-mem-types.h @@ -10,7 +10,7 @@ #ifndef __SELINUX_MEM_TYPES_H__ #define __SELINUX_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_selinux_mem_types_ { gf_selinux_mt_selinux_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/selinux/src/selinux-messages.h b/xlators/features/selinux/src/selinux-messages.h index 1f5739d8dc7..f49a54f956c 100644 --- a/xlators/features/selinux/src/selinux-messages.h +++ b/xlators/features/selinux/src/selinux-messages.h @@ -11,7 +11,7 @@ #ifndef _SELINUX_MESSAGES_H__ #define _SELINUX_MESSAGES_H__ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/selinux/src/selinux.c b/xlators/features/selinux/src/selinux.c index 91e74d1a3fc..9b1b4b55e1a 100644 --- a/xlators/features/selinux/src/selinux.c +++ b/xlators/features/selinux/src/selinux.c @@ -8,12 +8,12 @@ cases as published by the Free Software Foundation. */ -#include "xlator.h" +#include <glusterfs/xlator.h> #include "selinux.h" #include "selinux-messages.h" #include "selinux-mem-types.h" -#include "compat-errno.h" +#include <glusterfs/compat-errno.h> static int selinux_fgetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, @@ -234,7 +234,6 @@ init(xlator_t *this) priv = GF_CALLOC(1, sizeof(*priv), gf_selinux_mt_selinux_priv_t); if (!priv) { gf_log(this->name, GF_LOG_ERROR, "out of memory"); - ret = ENOMEM; goto out; } @@ -242,7 +241,6 @@ init(xlator_t *this) this->local_pool = mem_pool_new(selinux_priv_t, 64); if (!this->local_pool) { - ret = -1; gf_msg(this->name, GF_LOG_ERROR, ENOMEM, SL_MSG_ENOMEM, "Failed to create local_t's memory pool"); goto out; @@ -252,10 +250,9 @@ init(xlator_t *this) ret = 0; out: if (ret) { - if (priv) { - GF_FREE(priv); - } + GF_FREE(priv); mem_pool_destroy(this->local_pool); + this->local_pool = NULL; } return ret; } @@ -284,6 +281,7 @@ fini(xlator_t *this) GF_FREE(priv); mem_pool_destroy(this->local_pool); + this->local_pool = NULL; return; } @@ -310,3 +308,16 @@ struct volume_options options[] = { { .key = {NULL}, }}; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "selinux", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/selinux/src/selinux.h b/xlators/features/selinux/src/selinux.h index 787bff348f0..1bbdad3bb36 100644 --- a/xlators/features/selinux/src/selinux.h +++ b/xlators/features/selinux/src/selinux.h @@ -10,7 +10,7 @@ #ifndef __SELINUX_H__ #define __SELINUX_H__ -#include "common-utils.h" +#include <glusterfs/common-utils.h> #define SELINUX_XATTR "security.selinux" #define SELINUX_GLUSTER_XATTR "trusted.glusterfs.selinux" diff --git a/xlators/features/shard/src/shard-mem-types.h b/xlators/features/shard/src/shard-mem-types.h index 39a57ba6fd0..1fe7e2e2798 100644 --- a/xlators/features/shard/src/shard-mem-types.h +++ b/xlators/features/shard/src/shard-mem-types.h @@ -10,7 +10,7 @@ #ifndef __SHARD_MEM_TYPES_H__ #define __SHARD_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_shard_mem_types_ { gf_shard_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/shard/src/shard-messages.h b/xlators/features/shard/src/shard-messages.h index 89a96709219..2d0867eb136 100644 --- a/xlators/features/shard/src/shard-messages.h +++ b/xlators/features/shard/src/shard-messages.h @@ -11,7 +11,7 @@ #ifndef _SHARD_MESSAGES_H_ #define _SHARD_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c index 5715555109d..e5f93063943 100644 --- a/xlators/features/shard/src/shard.c +++ b/xlators/features/shard/src/shard.c @@ -12,9 +12,9 @@ #include "shard.h" #include "shard-mem-types.h" -#include "byte-order.h" -#include "defaults.h" -#include "statedump.h" +#include <glusterfs/byte-order.h> +#include <glusterfs/defaults.h> +#include <glusterfs/statedump.h> static gf_boolean_t __is_shard_dir(uuid_t gfid) @@ -69,7 +69,7 @@ __shard_inode_ctx_get(inode_t *inode, xlator_t *this, shard_inode_ctx_t **ctx) ret = __inode_ctx_get(inode, this, &ctx_uint); if (ret == 0) { - *ctx = (shard_inode_ctx_t *)ctx_uint; + *ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; return ret; } @@ -80,7 +80,8 @@ __shard_inode_ctx_get(inode_t *inode, xlator_t *this, shard_inode_ctx_t **ctx) INIT_LIST_HEAD(&ctx_p->ilist); INIT_LIST_HEAD(&ctx_p->to_fsync_list); - ret = __inode_ctx_set(inode, this, (uint64_t *)&ctx_p); + ctx_uint = (uint64_t)(uintptr_t)ctx_p; + ret = __inode_ctx_set(inode, this, &ctx_uint); if (ret < 0) { GF_FREE(ctx_p); return ret; @@ -273,6 +274,7 @@ shard_inode_ctx_add_to_fsync_list(inode_t *base_inode, xlator_t *this, * of the to_fsync_list. */ inode_ref(base_inode); + inode_ref(shard_inode); LOCK(&base_inode->lock); LOCK(&shard_inode->lock); @@ -286,8 +288,10 @@ shard_inode_ctx_add_to_fsync_list(inode_t *base_inode, xlator_t *this, /* Unref the base inode corresponding to the ref above, if the shard is * found to be already part of the fsync list. */ - if (ret != 0) + if (ret != 0) { inode_unref(base_inode); + inode_unref(shard_inode); + } return ret; } @@ -363,7 +367,7 @@ __shard_inode_ctx_get_block_size(inode_t *inode, xlator_t *this, if (ret < 0) return ret; - ctx = (shard_inode_ctx_t *)ctx_uint; + ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; *block_size = ctx->block_size; @@ -397,7 +401,7 @@ __shard_inode_ctx_get_fsync_count(inode_t *inode, xlator_t *this, if (ret < 0) return ret; - ctx = (shard_inode_ctx_t *)ctx_uint; + ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; *fsync_count = ctx->fsync_needed; @@ -430,7 +434,7 @@ __shard_inode_ctx_get_all(inode_t *inode, xlator_t *this, if (ret < 0) return ret; - ctx = (shard_inode_ctx_t *)ctx_uint; + ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; memcpy(ctx_out, ctx, sizeof(shard_inode_ctx_t)); return 0; @@ -464,7 +468,7 @@ __shard_inode_ctx_fill_iatt_from_cache(inode_t *inode, xlator_t *this, if (ret < 0) return ret; - ctx = (shard_inode_ctx_t *)ctx_uint; + ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; if (ctx->refresh == _gf_false) *buf = ctx->stat; @@ -509,6 +513,9 @@ shard_local_wipe(shard_local_t *local) loc_wipe(&local->int_entrylk.loc); loc_wipe(&local->newloc); + if (local->name) + GF_FREE(local->name); + if (local->int_entrylk.basename) GF_FREE(local->int_entrylk.basename); if (local->fd) @@ -686,8 +693,7 @@ __shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this, ctx->block_num = block_num; list_add_tail(&ctx->ilist, &priv->ilist_head); priv->inode_count++; - if (base_inode) - ctx->base_inode = inode_ref(base_inode); + ctx->base_inode = inode_ref(base_inode); } else { /*If on the other hand there is no available slot for this inode * in the list, delete the lru inode from the head of the list, @@ -734,6 +740,10 @@ __shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this, inode_unlink(lru_inode, priv->dot_shard_inode, block_bname); inode_forget(lru_inode, 0); } else { + /* The following unref corresponds to the ref + * held when the shard was added to fsync list. + */ + inode_unref(lru_inode); fsync_inode = lru_inode; if (lru_base_inode) inode_unref(lru_base_inode); @@ -758,8 +768,7 @@ __shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this, else gf_uuid_copy(ctx->base_gfid, gfid); ctx->block_num = block_num; - if (base_inode) - ctx->base_inode = inode_ref(base_inode); + ctx->base_inode = inode_ref(base_inode); list_add_tail(&ctx->ilist, &priv->ilist_head); } } else { @@ -879,26 +888,34 @@ int shard_common_inode_write_success_unwind(glusterfs_fop_t fop, call_frame_t *frame, int32_t op_ret) { - shard_local_t *local = NULL; + shard_local_t *local = frame->local; - local = frame->local; + /* the below 3 variables are required because, in SHARD_STACK_UNWIND() + macro, there is a check for local being null. So many static analyzers + backtrace the code with assumption of possible (local == NULL) case, + and complains for below lines. By handling it like below, we overcome + the warnings */ + + struct iatt *prebuf = ((local) ? &local->prebuf : NULL); + struct iatt *postbuf = ((local) ? &local->postbuf : NULL); + dict_t *xattr_rsp = ((local) ? local->xattr_rsp : NULL); switch (fop) { case GF_FOP_WRITE: - SHARD_STACK_UNWIND(writev, frame, op_ret, 0, &local->prebuf, - &local->postbuf, local->xattr_rsp); + SHARD_STACK_UNWIND(writev, frame, op_ret, 0, prebuf, postbuf, + xattr_rsp); break; case GF_FOP_FALLOCATE: - SHARD_STACK_UNWIND(fallocate, frame, op_ret, 0, &local->prebuf, - &local->postbuf, local->xattr_rsp); + SHARD_STACK_UNWIND(fallocate, frame, op_ret, 0, prebuf, postbuf, + xattr_rsp); break; case GF_FOP_ZEROFILL: - SHARD_STACK_UNWIND(zerofill, frame, op_ret, 0, &local->prebuf, - &local->postbuf, local->xattr_rsp); + SHARD_STACK_UNWIND(zerofill, frame, op_ret, 0, prebuf, postbuf, + xattr_rsp); break; case GF_FOP_DISCARD: - SHARD_STACK_UNWIND(discard, frame, op_ret, 0, &local->prebuf, - &local->postbuf, local->xattr_rsp); + SHARD_STACK_UNWIND(discard, frame, op_ret, 0, prebuf, postbuf, + xattr_rsp); break; default: gf_msg(THIS->name, GF_LOG_WARNING, 0, SHARD_MSG_INVALID_FOP, @@ -987,6 +1004,10 @@ shard_initiate_evicted_inode_fsync(xlator_t *this, inode_t *inode) } int +shard_common_inode_write_post_lookup_shards_handler(call_frame_t *frame, + xlator_t *this); + +int shard_common_resolve_shards(call_frame_t *frame, xlator_t *this, shard_post_resolve_fop_handler_t post_res_handler) { @@ -1003,21 +1024,47 @@ shard_common_resolve_shards(call_frame_t *frame, xlator_t *this, inode_t *fsync_inode = NULL; shard_priv_t *priv = NULL; shard_local_t *local = NULL; + uint64_t resolve_count = 0; priv = this->private; local = frame->local; local->call_count = 0; shard_idx_iter = local->first_block; res_inode = local->resolver_base_inode; + + if ((local->op_ret < 0) || (local->resolve_not)) + goto out; + + /* If this prealloc FOP is for fresh file creation, then the size of the + * file will be 0. Then there will be no shards associated with this file. + * So we can skip the lookup process for the shards which do not exists + * and directly issue mknod to crete shards. + * + * In case the prealloc fop is to extend the preallocated file to bigger + * size then just lookup and populate inodes of existing shards and + * update the create count + */ + if (local->fop == GF_FOP_FALLOCATE) { + if (!local->prebuf.ia_size) { + local->inode_list[0] = inode_ref(res_inode); + local->create_count = local->last_block; + shard_common_inode_write_post_lookup_shards_handler(frame, this); + return 0; + } + if (local->prebuf.ia_size < local->total_size) + local->create_count = local->last_block - + ((local->prebuf.ia_size - 1) / + local->block_size); + } + + resolve_count = local->last_block - local->create_count; + if (res_inode) gf_uuid_copy(gfid, res_inode->gfid); else gf_uuid_copy(gfid, local->base_gfid); - if ((local->op_ret < 0) || (local->resolve_not)) - goto out; - - while (shard_idx_iter <= local->last_block) { + while (shard_idx_iter <= resolve_count) { i++; if (shard_idx_iter == 0) { local->inode_list[i] = inode_ref(res_inode); @@ -1130,6 +1177,7 @@ shard_update_file_size(call_frame_t *frame, xlator_t *this, fd_t *fd, { int ret = -1; int64_t *size_attr = NULL; + int64_t delta_blocks = 0; inode_t *inode = NULL; shard_local_t *local = NULL; dict_t *xattr_req = NULL; @@ -1151,13 +1199,13 @@ shard_update_file_size(call_frame_t *frame, xlator_t *this, fd_t *fd, /* If both size and block count have not changed, then skip the xattrop. */ - if ((local->delta_size + local->hole_size == 0) && - (local->delta_blocks == 0)) { + delta_blocks = GF_ATOMIC_GET(local->delta_blocks); + if ((local->delta_size + local->hole_size == 0) && (delta_blocks == 0)) { goto out; } ret = shard_set_size_attrs(local->delta_size + local->hole_size, - local->delta_blocks, &size_attr); + delta_blocks, &size_attr); if (ret) { gf_msg(this->name, GF_LOG_ERROR, 0, SHARD_MSG_SIZE_SET_FAILED, "Failed to set size attrs for %s", uuid_utoa(inode->gfid)); @@ -1593,7 +1641,8 @@ shard_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) shard_local_t *local = NULL; this->itable = loc->inode->table; - if (frame->root->pid != GF_CLIENT_PID_GSYNCD) { + if ((frame->root->pid != GF_CLIENT_PID_GSYNCD) && + (frame->root->pid != GF_CLIENT_PID_GLFS_HEAL)) { SHARD_ENTRY_FOP_CHECK(loc, op_errno, err); } @@ -1643,26 +1692,24 @@ err: } int -shard_lookup_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, dict_t *xdata, - struct iatt *postparent) +shard_set_iattr_invoke_post_handler(call_frame_t *frame, xlator_t *this, + inode_t *inode, int32_t op_ret, + int32_t op_errno, struct iatt *buf, + dict_t *xdata) { int ret = -1; int32_t mask = SHARD_INODE_WRITE_MASK; - shard_local_t *local = NULL; + shard_local_t *local = frame->local; shard_inode_ctx_t ctx = { 0, }; - local = frame->local; - if (op_ret < 0) { gf_msg(this->name, GF_LOG_ERROR, op_errno, SHARD_MSG_BASE_FILE_LOOKUP_FAILED, "Lookup on base file" " failed : %s", - loc_gfid_utoa(&(local->loc))); + uuid_utoa(inode->gfid)); local->op_ret = op_ret; local->op_errno = op_errno; goto unwind; @@ -1696,18 +1743,57 @@ unwind: } int -shard_lookup_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc, - shard_post_fop_handler_t handler) +shard_fstat_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + shard_local_t *local = frame->local; + + shard_set_iattr_invoke_post_handler(frame, this, local->fd->inode, op_ret, + op_errno, buf, xdata); + return 0; +} + +int +shard_lookup_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata, + struct iatt *postparent) +{ + /* In case of op_ret < 0, inode passed to this function will be NULL + ex: in case of op_errno = ENOENT. So refer prefilled inode data + which is part of local. + Note: Reassigning/overriding the inode passed to this cbk with inode + which is part of *struct shard_local_t* won't cause any issue as + both inodes have same reference/address as of the inode passed */ + inode = ((shard_local_t *)frame->local)->loc.inode; + + shard_set_iattr_invoke_post_handler(frame, this, inode, op_ret, op_errno, + buf, xdata); + return 0; +} + +/* This function decides whether to make file based lookup or + * fd based lookup (fstat) depending on the 3rd and 4th arg. + * If fd != NULL and loc == NULL then call is for fstat + * If fd == NULL and loc != NULL then call is for file based + * lookup. Please pass args based on the requirement. + */ +int +shard_refresh_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc, + fd_t *fd, shard_post_fop_handler_t handler) { int ret = -1; + inode_t *inode = NULL; shard_local_t *local = NULL; dict_t *xattr_req = NULL; gf_boolean_t need_refresh = _gf_false; local = frame->local; local->handler = handler; + inode = fd ? fd->inode : loc->inode; - ret = shard_inode_ctx_fill_iatt_from_cache(loc->inode, this, &local->prebuf, + ret = shard_inode_ctx_fill_iatt_from_cache(inode, this, &local->prebuf, &need_refresh); /* By this time, inode ctx should have been created either in create, * mknod, readdirp or lookup. If not it is a bug! @@ -1716,7 +1802,7 @@ shard_lookup_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc, gf_msg_debug(this->name, 0, "Skipping lookup on base file: %s" "Serving prebuf off the inode ctx cache", - uuid_utoa(loc->gfid)); + uuid_utoa(inode->gfid)); goto out; } @@ -1727,10 +1813,14 @@ shard_lookup_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc, goto out; } - SHARD_MD_READ_FOP_INIT_REQ_DICT(this, xattr_req, loc->gfid, local, out); + SHARD_MD_READ_FOP_INIT_REQ_DICT(this, xattr_req, inode->gfid, local, out); - STACK_WIND(frame, shard_lookup_base_file_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, loc, xattr_req); + if (fd) + STACK_WIND(frame, shard_fstat_base_file_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, xattr_req); + else + STACK_WIND(frame, shard_lookup_base_file_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xattr_req); dict_unref(xattr_req); return 0; @@ -1942,6 +2032,7 @@ shard_truncate_last_shard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, dict_t *xdata) { inode_t *inode = NULL; + int64_t delta_blocks = 0; shard_local_t *local = NULL; local = frame->local; @@ -1962,14 +2053,15 @@ shard_truncate_last_shard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, } local->postbuf.ia_size = local->offset; - local->postbuf.ia_blocks -= (prebuf->ia_blocks - postbuf->ia_blocks); /* Let the delta be negative. We want xattrop to do subtraction */ local->delta_size = local->postbuf.ia_size - local->prebuf.ia_size; - local->delta_blocks = postbuf->ia_blocks - prebuf->ia_blocks; + delta_blocks = GF_ATOMIC_ADD(local->delta_blocks, + postbuf->ia_blocks - prebuf->ia_blocks); + GF_ASSERT(delta_blocks <= 0); + local->postbuf.ia_blocks += delta_blocks; local->hole_size = 0; - shard_inode_ctx_set(inode, this, postbuf, 0, SHARD_MASK_TIMES); - + shard_inode_ctx_set(inode, this, &local->postbuf, 0, SHARD_MASK_TIMES); shard_update_file_size(frame, this, NULL, &local->loc, shard_post_update_size_truncate_handler); return 0; @@ -1997,10 +2089,9 @@ shard_truncate_last_shard(call_frame_t *frame, xlator_t *this, inode_t *inode) */ if (!inode) { gf_msg_debug(this->name, 0, - "Last shard to be truncated absent" - " in backend: %s. Directly proceeding to update " - "file size", - uuid_utoa(inode->gfid)); + "Last shard to be truncated absent in backend: %" PRIu64 + " of gfid %s. Directly proceeding to update file size", + local->first_block, uuid_utoa(local->loc.inode->gfid)); shard_update_file_size(frame, this, NULL, &local->loc, shard_post_update_size_truncate_handler); return 0; @@ -2029,8 +2120,10 @@ shard_truncate_htol_cbk(call_frame_t *frame, void *cookie, xlator_t *this, struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { + int ret = 0; int call_count = 0; int shard_block_num = (long)cookie; + uint64_t block_count = 0; shard_local_t *local = NULL; local = frame->local; @@ -2040,6 +2133,16 @@ shard_truncate_htol_cbk(call_frame_t *frame, void *cookie, xlator_t *this, local->op_errno = op_errno; goto done; } + ret = dict_get_uint64(xdata, GF_GET_FILE_BLOCK_COUNT, &block_count); + if (!ret) { + GF_ATOMIC_SUB(local->delta_blocks, block_count); + } else { + /* dict_get failed possibly due to a heterogeneous cluster? */ + gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_DICT_OP_FAILED, + "Failed to get key %s from dict during truncate of gfid %s", + GF_GET_FILE_BLOCK_COUNT, + uuid_utoa(local->resolver_base_inode->gfid)); + } shard_unlink_block_inode(local, shard_block_num); done: @@ -2069,6 +2172,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode) gf_boolean_t wind_failed = _gf_false; shard_local_t *local = NULL; shard_priv_t *priv = NULL; + dict_t *xdata_req = NULL; local = frame->local; priv = this->private; @@ -2096,7 +2200,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode) local->postbuf.ia_size = local->offset; local->postbuf.ia_blocks = local->prebuf.ia_blocks; local->delta_size = local->postbuf.ia_size - local->prebuf.ia_size; - local->delta_blocks = 0; + GF_ATOMIC_INIT(local->delta_blocks, 0); local->hole_size = 0; shard_update_file_size(frame, this, local->fd, &local->loc, shard_post_update_size_truncate_handler); @@ -2105,6 +2209,21 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode) local->call_count = call_count; i = 1; + xdata_req = dict_new(); + if (!xdata_req) { + shard_common_failure_unwind(local->fop, frame, -1, ENOMEM); + return 0; + } + ret = dict_set_uint64(xdata_req, GF_GET_FILE_BLOCK_COUNT, 8 * 8); + if (ret) { + gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_DICT_OP_FAILED, + "Failed to set key %s into dict during truncate of %s", + GF_GET_FILE_BLOCK_COUNT, + uuid_utoa(local->resolver_base_inode->gfid)); + dict_unref(xdata_req); + shard_common_failure_unwind(local->fop, frame, -1, ENOMEM); + return 0; + } SHARD_SET_ROOT_FS_ID(frame, local); while (cur_block <= last_block) { @@ -2143,7 +2262,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode) STACK_WIND_COOKIE(frame, shard_truncate_htol_cbk, (void *)(long)cur_block, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, &loc, 0, NULL); + FIRST_CHILD(this)->fops->unlink, &loc, 0, xdata_req); loc_wipe(&loc); next: i++; @@ -2151,6 +2270,7 @@ shard_truncate_htol(call_frame_t *frame, xlator_t *this, inode_t *inode) if (!--call_count) break; } + dict_unref(xdata_req); return 0; } @@ -2206,13 +2326,19 @@ shard_link_block_inode(shard_local_t *local, int block_num, inode_t *inode, xlator_t *this = NULL; inode_t *fsync_inode = NULL; shard_priv_t *priv = NULL; + inode_t *base_inode = NULL; this = THIS; priv = this->private; - if (local->loc.inode) + if (local->loc.inode) { gf_uuid_copy(gfid, local->loc.inode->gfid); - else + base_inode = local->loc.inode; + } else if (local->resolver_base_inode) { + gf_uuid_copy(gfid, local->resolver_base_inode->gfid); + base_inode = local->resolver_base_inode; + } else { gf_uuid_copy(gfid, local->base_gfid); + } shard_make_block_bname(block_num, gfid, block_bname, sizeof(block_bname)); @@ -2225,7 +2351,7 @@ shard_link_block_inode(shard_local_t *local, int block_num, inode_t *inode, LOCK(&priv->lock); { fsync_inode = __shard_update_shards_inode_list( - linked_inode, this, local->loc.inode, block_num, gfid); + linked_inode, this, base_inode, block_num, gfid); } UNLOCK(&priv->lock); if (fsync_inode) @@ -2347,7 +2473,7 @@ shard_common_lookup_shards(call_frame_t *frame, xlator_t *this, inode_t *inode, int count = 0; int call_count = 0; int32_t shard_idx_iter = 0; - int last_block = 0; + int lookup_count = 0; char path[PATH_MAX] = { 0, }; @@ -2367,7 +2493,7 @@ shard_common_lookup_shards(call_frame_t *frame, xlator_t *this, inode_t *inode, local = frame->local; count = call_count = local->call_count; shard_idx_iter = local->first_block; - last_block = local->last_block; + lookup_count = local->last_block - local->create_count; local->pls_fop_handler = handler; if (local->lookup_shards_barriered) local->barrier.waitfor = local->call_count; @@ -2377,7 +2503,7 @@ shard_common_lookup_shards(call_frame_t *frame, xlator_t *this, inode_t *inode, else gf_uuid_copy(gfid, local->base_gfid); - while (shard_idx_iter <= last_block) { + while (shard_idx_iter <= lookup_count) { if (local->inode_list[i]) { i++; shard_idx_iter++; @@ -2522,6 +2648,7 @@ shard_truncate_begin(call_frame_t *frame, xlator_t *this) local->block_size); local->num_blocks = local->last_block - local->first_block + 1; + GF_ASSERT(local->num_blocks > 0); local->resolver_base_inode = (local->fop == GF_FOP_TRUNCATE) ? local->loc.inode : local->fd->inode; @@ -2597,7 +2724,7 @@ shard_post_lookup_truncate_handler(call_frame_t *frame, xlator_t *this) */ local->hole_size = local->offset - local->prebuf.ia_size; local->delta_size = 0; - local->delta_blocks = 0; + GF_ATOMIC_INIT(local->delta_blocks, 0); local->postbuf.ia_size = local->offset; tmp_stbuf.ia_size = local->offset; shard_inode_ctx_set(local->loc.inode, this, &tmp_stbuf, 0, @@ -2613,7 +2740,7 @@ shard_post_lookup_truncate_handler(call_frame_t *frame, xlator_t *this) */ local->hole_size = 0; local->delta_size = (local->offset - local->prebuf.ia_size); - local->delta_blocks = 0; + GF_ATOMIC_INIT(local->delta_blocks, 0); tmp_stbuf.ia_size = local->offset; shard_inode_ctx_set(local->loc.inode, this, &tmp_stbuf, 0, SHARD_INODE_WRITE_MASK); @@ -2669,9 +2796,10 @@ shard_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, if (!local->xattr_req) goto err; local->resolver_base_inode = loc->inode; + GF_ATOMIC_INIT(local->delta_blocks, 0); - shard_lookup_base_file(frame, this, &local->loc, - shard_post_lookup_truncate_handler); + shard_refresh_base_file(frame, this, &local->loc, NULL, + shard_post_lookup_truncate_handler); return 0; err: @@ -2724,9 +2852,10 @@ shard_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, local->loc.inode = inode_ref(fd->inode); gf_uuid_copy(local->loc.gfid, fd->inode->gfid); local->resolver_base_inode = fd->inode; + GF_ATOMIC_INIT(local->delta_blocks, 0); - shard_lookup_base_file(frame, this, &local->loc, - shard_post_lookup_truncate_handler); + shard_refresh_base_file(frame, this, NULL, fd, + shard_post_lookup_truncate_handler); return 0; err: shard_common_failure_unwind(GF_FOP_FTRUNCATE, frame, -1, ENOMEM); @@ -2870,8 +2999,8 @@ shard_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, if (!local->xattr_req) goto err; - shard_lookup_base_file(frame, this, &local->loc, - shard_post_lookup_link_handler); + shard_refresh_base_file(frame, this, &local->loc, NULL, + shard_post_lookup_link_handler); return 0; err: shard_common_failure_unwind(GF_FOP_LINK, frame, -1, ENOMEM); @@ -2885,13 +3014,20 @@ int shard_post_lookup_shards_unlink_handler(call_frame_t *frame, xlator_t *this) { shard_local_t *local = NULL; + uuid_t gfid = { + 0, + }; local = frame->local; + if (local->resolver_base_inode) + gf_uuid_copy(gfid, local->resolver_base_inode->gfid); + else + gf_uuid_copy(gfid, local->base_gfid); + if ((local->op_ret < 0) && (local->op_errno != ENOENT)) { gf_msg(this->name, GF_LOG_ERROR, local->op_errno, SHARD_MSG_FOP_FAILED, - "failed to delete shards of %s", - uuid_utoa(local->resolver_base_inode->gfid)); + "failed to delete shards of %s", uuid_utoa(gfid)); return 0; } local->op_ret = 0; @@ -2932,8 +3068,8 @@ shard_unlink_block_inode(shard_local_t *local, int shard_block_num) shard_priv_t *priv = NULL; shard_inode_ctx_t *ctx = NULL; shard_inode_ctx_t *base_ictx = NULL; - gf_boolean_t unlink_unref_forget = _gf_false; int unref_base_inode = 0; + int unref_shard_inode = 0; this = THIS; priv = this->private; @@ -2958,11 +3094,12 @@ shard_unlink_block_inode(shard_local_t *local, int shard_block_num) list_del_init(&ctx->ilist); priv->inode_count--; unref_base_inode++; + unref_shard_inode++; GF_ASSERT(priv->inode_count >= 0); - unlink_unref_forget = _gf_true; } if (ctx->fsync_needed) { unref_base_inode++; + unref_shard_inode++; list_del_init(&ctx->to_fsync_list); if (base_inode) { __shard_inode_ctx_get(base_inode, this, &base_ictx); @@ -2973,11 +3110,11 @@ shard_unlink_block_inode(shard_local_t *local, int shard_block_num) UNLOCK(&inode->lock); if (base_inode) UNLOCK(&base_inode->lock); - if (unlink_unref_forget) { - inode_unlink(inode, priv->dot_shard_inode, block_bname); - inode_unref(inode); - inode_forget(inode, 0); - } + + inode_unlink(inode, priv->dot_shard_inode, block_bname); + inode_ref_reduce_by_n(inode, unref_shard_inode); + inode_forget(inode, 0); + if (base_inode && unref_base_inode) inode_ref_reduce_by_n(base_inode, unref_base_inode); UNLOCK(&priv->lock); @@ -3155,8 +3292,14 @@ shard_regulated_shards_deletion(call_frame_t *cleanup_frame, xlator_t *this, gf_uuid_copy(local->base_gfid, gfid); local->resolver_base_inode = inode_find(this->itable, gfid); local->call_count = 0; - syncbarrier_init(&local->barrier); - + ret = syncbarrier_init(&local->barrier); + if (ret) { + GF_FREE(local->inode_list); + local->inode_list = NULL; + inode_unref(local->resolver_base_inode); + local->resolver_base_inode = NULL; + return -errno; + } shard_common_resolve_shards(cleanup_frame, this, shard_post_resolve_unlink_handler); @@ -3976,6 +4119,7 @@ shard_unlink_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this, local->op_ret = op_ret; local->op_errno = op_errno; } else { + shard_inode_ctx_set_refresh_flag(local->int_inodelk.loc.inode, this); local->preoldparent = *preparent; local->postoldparent = *postparent; if (xdata) @@ -4185,8 +4329,8 @@ shard_post_inodelk_fop_handler(call_frame_t *frame, xlator_t *this) switch (local->fop) { case GF_FOP_UNLINK: case GF_FOP_RENAME: - shard_lookup_base_file(frame, this, &local->int_inodelk.loc, - shard_post_lookup_base_shard_rm_handler); + shard_refresh_base_file(frame, this, &local->int_inodelk.loc, NULL, + shard_post_lookup_base_shard_rm_handler); break; default: gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_INVALID_FOP, @@ -4441,8 +4585,8 @@ shard_rename_src_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (local->block_size) { local->tmp_loc.inode = inode_new(this->itable); gf_uuid_copy(local->tmp_loc.gfid, (local->loc.inode)->gfid); - shard_lookup_base_file(frame, this, &local->tmp_loc, - shard_post_rename_lookup_handler); + shard_refresh_base_file(frame, this, &local->tmp_loc, NULL, + shard_post_rename_lookup_handler); } else { shard_rename_cbk(frame, this); } @@ -4699,8 +4843,11 @@ out: if (xdata) local->xattr_rsp = dict_ref(xdata); vec.iov_base = local->iobuf->ptr; + if (local->offset + local->req_size > local->prebuf.ia_size) + local->total_size = local->prebuf.ia_size - local->offset; vec.iov_len = local->total_size; - SHARD_STACK_UNWIND(readv, frame, local->total_size, local->op_errno, + local->op_ret = local->total_size; + SHARD_STACK_UNWIND(readv, frame, local->op_ret, local->op_errno, &vec, 1, &local->prebuf, local->iobref, local->xattr_rsp); return 0; @@ -5013,7 +5160,8 @@ shard_post_resolve_readv_handler(call_frame_t *frame, xlator_t *this) vec.iov_base = local->iobuf->ptr; vec.iov_len = local->total_size; - SHARD_STACK_UNWIND(readv, frame, local->total_size, 0, &vec, 1, + local->op_ret = local->total_size; + SHARD_STACK_UNWIND(readv, frame, local->op_ret, 0, &vec, 1, &local->prebuf, local->iobref, NULL); return 0; } @@ -5077,6 +5225,7 @@ shard_post_lookup_readv_handler(call_frame_t *frame, xlator_t *this) local->block_size); local->num_blocks = local->last_block - local->first_block + 1; + GF_ASSERT(local->num_blocks > 0); local->resolver_base_inode = local->loc.inode; local->inode_list = GF_CALLOC(local->num_blocks, sizeof(inode_t *), @@ -5099,9 +5248,9 @@ shard_post_lookup_readv_handler(call_frame_t *frame, xlator_t *this) goto err; } + memset(iobuf->ptr, 0, local->total_size); iobuf_unref(iobuf); local->iobuf = iobuf; - memset(iobuf->ptr, 0, local->total_size); local->dot_shard_loc.inode = inode_find(this->itable, priv->dot_shard_gfid); if (!local->dot_shard_loc.inode) { @@ -5173,8 +5322,8 @@ shard_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, local->loc.inode = inode_ref(fd->inode); gf_uuid_copy(local->loc.gfid, fd->inode->gfid); - shard_lookup_base_file(frame, this, &local->loc, - shard_post_lookup_readv_handler); + shard_refresh_base_file(frame, this, NULL, fd, + shard_post_lookup_readv_handler); return 0; err: shard_common_failure_unwind(GF_FOP_READ, frame, -1, ENOMEM); @@ -5223,7 +5372,7 @@ __shard_get_delta_size_from_inode_ctx(shard_local_t *local, inode_t *inode, if (ret < 0) return ret; - ctx = (shard_inode_ctx_t *)ctx_uint; + ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; if (shard_is_appending_write(local)) { local->delta_size = local->total_size; @@ -5275,7 +5424,8 @@ shard_common_inode_write_do_cbk(call_frame_t *frame, void *cookie, local->op_errno = op_errno; } else { local->written_size += op_ret; - local->delta_blocks += (post->ia_blocks - pre->ia_blocks); + GF_ATOMIC_ADD(local->delta_blocks, + post->ia_blocks - pre->ia_blocks); local->delta_size += (post->ia_size - pre->ia_size); shard_inode_ctx_set(local->fd->inode, this, post, 0, SHARD_MASK_TIMES); @@ -5414,21 +5564,17 @@ shard_common_inode_write_do(call_frame_t *frame, xlator_t *this) remaining_size -= shard_write_size; if (local->fop == GF_FOP_WRITE) { + vec = NULL; count = iov_subset(local->vector, local->count, vec_offset, - vec_offset + shard_write_size, NULL); - - vec = GF_CALLOC(count, sizeof(struct iovec), gf_shard_mt_iovec); - if (!vec) { + shard_write_size, &vec, 0); + if (count < 0) { local->op_ret = -1; local->op_errno = ENOMEM; wind_failed = _gf_true; - GF_FREE(vec); shard_common_inode_write_do_cbk(frame, (void *)(long)0, this, -1, ENOMEM, NULL, NULL, NULL); goto next; } - count = iov_subset(local->vector, local->count, vec_offset, - vec_offset + shard_write_size, vec); } if (cur_block == 0) { @@ -5540,6 +5686,8 @@ shard_common_inode_write_post_resolve_handler(call_frame_t *frame, shard_common_lookup_shards( frame, this, local->resolver_base_inode, shard_common_inode_write_post_lookup_shards_handler); + } else if (local->create_count) { + shard_common_inode_write_post_lookup_shards_handler(frame, this); } else { shard_common_inode_write_do(frame, this); } @@ -5570,6 +5718,7 @@ shard_common_inode_write_post_lookup_handler(call_frame_t *frame, local->last_block = get_highest_block(local->offset, local->total_size, local->block_size); local->num_blocks = local->last_block - local->first_block + 1; + GF_ASSERT(local->num_blocks > 0); local->inode_list = GF_CALLOC(local->num_blocks, sizeof(inode_t *), gf_shard_mt_inode_list); if (!local->inode_list) { @@ -5578,9 +5727,9 @@ shard_common_inode_write_post_lookup_handler(call_frame_t *frame, } gf_msg_trace(this->name, 0, - "%s: gfid=%s first_block=%" PRIu32 + "%s: gfid=%s first_block=%" PRIu64 " " - "last_block=%" PRIu32 " num_blocks=%" PRIu32 " offset=%" PRId64 + "last_block=%" PRIu64 " num_blocks=%" PRIu64 " offset=%" PRId64 " total_size=%zu flags=%" PRId32 "", gf_fop_list[local->fop], uuid_utoa(local->resolver_base_inode->gfid), @@ -5746,7 +5895,7 @@ __shard_get_timestamps_from_inode_ctx(shard_local_t *local, inode_t *inode, if (ret < 0) return ret; - ctx = (shard_inode_ctx_t *)ctx_uint; + ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; local->postbuf.ia_ctime = ctx->stat.ia_ctime; local->postbuf.ia_ctime_nsec = ctx->stat.ia_ctime_nsec; @@ -5785,6 +5934,7 @@ shard_fsync_shards_cbk(call_frame_t *frame, void *cookie, xlator_t *this, shard_inode_ctx_t *ctx = NULL; shard_inode_ctx_t *base_ictx = NULL; inode_t *base_inode = NULL; + gf_boolean_t unref_shard_inode = _gf_false; local = frame->local; base_inode = local->fd->inode; @@ -5818,11 +5968,16 @@ out: if (ctx->fsync_needed != 0) { list_add_tail(&ctx->to_fsync_list, &base_ictx->to_fsync_list); base_ictx->fsync_count++; + } else { + unref_shard_inode = _gf_true; } } UNLOCK(&anon_fd->inode->lock); UNLOCK(&base_inode->lock); } + + if (unref_shard_inode) + inode_unref(anon_fd->inode); if (anon_fd) fd_unref(anon_fd); @@ -5969,8 +6124,8 @@ shard_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync, local->loc.inode = inode_ref(fd->inode); gf_uuid_copy(local->loc.gfid, fd->inode->gfid); - shard_lookup_base_file(frame, this, &local->loc, - shard_post_lookup_fsync_handler); + shard_refresh_base_file(frame, this, NULL, fd, + shard_post_lookup_fsync_handler); return 0; err: shard_common_failure_unwind(GF_FOP_FSYNC, frame, -1, ENOMEM); @@ -6162,48 +6317,210 @@ shard_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, } int32_t -shard_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name, dict_t *xdata) +shard_modify_and_set_iatt_in_dict(dict_t *xdata, shard_local_t *local, + char *key) { - int op_errno = EINVAL; + int ret = 0; + struct iatt *tmpbuf = NULL; + struct iatt *stbuf = NULL; + data_t *data = NULL; - if (frame->root->pid != GF_CLIENT_PID_GSYNCD) { - GF_IF_NATIVE_XATTR_GOTO(SHARD_XATTR_PREFIX "*", name, op_errno, out); + if (!xdata) + return 0; + + data = dict_get(xdata, key); + if (!data) + return 0; + + tmpbuf = data_to_iatt(data, key); + stbuf = GF_MALLOC(sizeof(struct iatt), gf_common_mt_char); + if (stbuf == NULL) { + local->op_ret = -1; + local->op_errno = ENOMEM; + goto err; } + *stbuf = *tmpbuf; + stbuf->ia_size = local->prebuf.ia_size; + stbuf->ia_blocks = local->prebuf.ia_blocks; + ret = dict_set_iatt(xdata, key, stbuf, false); + if (ret < 0) { + local->op_ret = -1; + local->op_errno = ENOMEM; + goto err; + } + return 0; - if (xdata && (frame->root->pid != GF_CLIENT_PID_GSYNCD)) { - dict_del(xdata, GF_XATTR_SHARD_BLOCK_SIZE); - dict_del(xdata, GF_XATTR_SHARD_FILE_SIZE); +err: + GF_FREE(stbuf); + return -1; +} + +int32_t +shard_common_remove_xattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + int ret = -1; + shard_local_t *local = NULL; + + local = frame->local; + + if (op_ret < 0) { + local->op_ret = op_ret; + local->op_errno = op_errno; + goto err; } - STACK_WIND_TAIL(frame, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); + ret = shard_modify_and_set_iatt_in_dict(xdata, local, GF_PRESTAT); + if (ret < 0) + goto err; + + ret = shard_modify_and_set_iatt_in_dict(xdata, local, GF_POSTSTAT); + if (ret < 0) + goto err; + + if (local->fd) + SHARD_STACK_UNWIND(fremovexattr, frame, local->op_ret, local->op_errno, + xdata); + else + SHARD_STACK_UNWIND(removexattr, frame, local->op_ret, local->op_errno, + xdata); return 0; -out: - shard_common_failure_unwind(GF_FOP_REMOVEXATTR, frame, -1, op_errno); + +err: + shard_common_failure_unwind(local->fop, frame, local->op_ret, + local->op_errno); return 0; } int32_t -shard_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name, dict_t *xdata) +shard_post_lookup_remove_xattr_handler(call_frame_t *frame, xlator_t *this) { - int op_errno = EINVAL; + shard_local_t *local = NULL; + local = frame->local; + + if (local->op_ret < 0) { + shard_common_failure_unwind(local->fop, frame, local->op_ret, + local->op_errno); + return 0; + } + + if (local->fd) + STACK_WIND(frame, shard_common_remove_xattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, local->fd, + local->name, local->xattr_req); + else + STACK_WIND(frame, shard_common_remove_xattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, &local->loc, + local->name, local->xattr_req); + return 0; +} + +int32_t +shard_common_remove_xattr(call_frame_t *frame, xlator_t *this, + glusterfs_fop_t fop, loc_t *loc, fd_t *fd, + const char *name, dict_t *xdata) +{ + int ret = -1; + int op_errno = ENOMEM; + uint64_t block_size = 0; + shard_local_t *local = NULL; + inode_t *inode = loc ? loc->inode : fd->inode; + + if ((IA_ISDIR(inode->ia_type)) || (IA_ISLNK(inode->ia_type))) { + if (loc) + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, loc, name, + xdata); + else + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, fd, name, + xdata); + return 0; + } + + /* If shard's special xattrs are attempted to be removed, + * fail the fop with EPERM (except if the client is gsyncd). + */ if (frame->root->pid != GF_CLIENT_PID_GSYNCD) { - GF_IF_NATIVE_XATTR_GOTO(SHARD_XATTR_PREFIX "*", name, op_errno, out); + GF_IF_NATIVE_XATTR_GOTO(SHARD_XATTR_PREFIX "*", name, op_errno, err); } + /* Repeat the same check for bulk-removexattr */ if (xdata && (frame->root->pid != GF_CLIENT_PID_GSYNCD)) { dict_del(xdata, GF_XATTR_SHARD_BLOCK_SIZE); dict_del(xdata, GF_XATTR_SHARD_FILE_SIZE); } - STACK_WIND_TAIL(frame, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); + ret = shard_inode_ctx_get_block_size(inode, this, &block_size); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, SHARD_MSG_INODE_CTX_GET_FAILED, + "Failed to get block size from inode ctx of %s", + uuid_utoa(inode->gfid)); + goto err; + } + + if (!block_size || frame->root->pid == GF_CLIENT_PID_GSYNCD) { + if (loc) + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, loc, name, + xdata); + else + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, fd, name, + xdata); + return 0; + } + + local = mem_get0(this->local_pool); + if (!local) + goto err; + + frame->local = local; + local->fop = fop; + if (loc) { + if (loc_copy(&local->loc, loc) != 0) + goto err; + } + + if (fd) { + local->fd = fd_ref(fd); + local->loc.inode = inode_ref(fd->inode); + gf_uuid_copy(local->loc.gfid, fd->inode->gfid); + } + + if (name) { + local->name = gf_strdup(name); + if (!local->name) + goto err; + } + + if (xdata) + local->xattr_req = dict_ref(xdata); + + shard_refresh_base_file(frame, this, loc, fd, + shard_post_lookup_remove_xattr_handler); return 0; -out: - shard_common_failure_unwind(GF_FOP_FREMOVEXATTR, frame, -1, op_errno); +err: + shard_common_failure_unwind(fop, frame, -1, op_errno); + return 0; +} + +int32_t +shard_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) +{ + shard_common_remove_xattr(frame, this, GF_FOP_REMOVEXATTR, loc, NULL, name, + xdata); + return 0; +} + +int32_t +shard_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + shard_common_remove_xattr(frame, this, GF_FOP_FREMOVEXATTR, NULL, fd, name, + xdata); return 0; } @@ -6284,38 +6601,164 @@ out: } int32_t -shard_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, - int32_t flags, dict_t *xdata) +shard_common_set_xattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - int op_errno = EINVAL; + int ret = -1; + shard_local_t *local = NULL; - if (frame->root->pid != GF_CLIENT_PID_GSYNCD) { - GF_IF_INTERNAL_XATTR_GOTO(SHARD_XATTR_PREFIX "*", dict, op_errno, out); + local = frame->local; + + if (op_ret < 0) { + local->op_ret = op_ret; + local->op_errno = op_errno; + goto err; } - STACK_WIND_TAIL(frame, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); + ret = shard_modify_and_set_iatt_in_dict(xdata, local, GF_PRESTAT); + if (ret < 0) + goto err; + + ret = shard_modify_and_set_iatt_in_dict(xdata, local, GF_POSTSTAT); + if (ret < 0) + goto err; + + if (local->fd) + SHARD_STACK_UNWIND(fsetxattr, frame, local->op_ret, local->op_errno, + xdata); + else + SHARD_STACK_UNWIND(setxattr, frame, local->op_ret, local->op_errno, + xdata); + return 0; + +err: + shard_common_failure_unwind(local->fop, frame, local->op_ret, + local->op_errno); return 0; -out: - shard_common_failure_unwind(GF_FOP_FSETXATTR, frame, -1, op_errno); +} + +int32_t +shard_post_lookup_set_xattr_handler(call_frame_t *frame, xlator_t *this) +{ + shard_local_t *local = NULL; + + local = frame->local; + + if (local->op_ret < 0) { + shard_common_failure_unwind(local->fop, frame, local->op_ret, + local->op_errno); + return 0; + } + + if (local->fd) + STACK_WIND(frame, shard_common_set_xattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, local->fd, + local->xattr_req, local->flags, local->xattr_rsp); + else + STACK_WIND(frame, shard_common_set_xattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, &local->loc, + local->xattr_req, local->flags, local->xattr_rsp); return 0; } int32_t -shard_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, - int32_t flags, dict_t *xdata) +shard_common_set_xattr(call_frame_t *frame, xlator_t *this, glusterfs_fop_t fop, + loc_t *loc, fd_t *fd, dict_t *dict, int32_t flags, + dict_t *xdata) { - int op_errno = EINVAL; + int ret = -1; + int op_errno = ENOMEM; + uint64_t block_size = 0; + shard_local_t *local = NULL; + inode_t *inode = loc ? loc->inode : fd->inode; + if ((IA_ISDIR(inode->ia_type)) || (IA_ISLNK(inode->ia_type))) { + if (loc) + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, + xdata); + else + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, + xdata); + return 0; + } + + /* Sharded or not, if shard's special xattrs are attempted to be set, + * fail the fop with EPERM (except if the client is gsyncd. + */ if (frame->root->pid != GF_CLIENT_PID_GSYNCD) { - GF_IF_INTERNAL_XATTR_GOTO(SHARD_XATTR_PREFIX "*", dict, op_errno, out); + GF_IF_INTERNAL_XATTR_GOTO(SHARD_XATTR_PREFIX "*", dict, op_errno, err); + } + + ret = shard_inode_ctx_get_block_size(inode, this, &block_size); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, 0, SHARD_MSG_INODE_CTX_GET_FAILED, + "Failed to get block size from inode ctx of %s", + uuid_utoa(inode->gfid)); + goto err; } - STACK_WIND_TAIL(frame, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, - loc, dict, flags, xdata); + if (!block_size || frame->root->pid == GF_CLIENT_PID_GSYNCD) { + if (loc) + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, + xdata); + else + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, + xdata); + return 0; + } + + local = mem_get0(this->local_pool); + if (!local) + goto err; + + frame->local = local; + local->fop = fop; + if (loc) { + if (loc_copy(&local->loc, loc) != 0) + goto err; + } + + if (fd) { + local->fd = fd_ref(fd); + local->loc.inode = inode_ref(fd->inode); + gf_uuid_copy(local->loc.gfid, fd->inode->gfid); + } + local->flags = flags; + /* Reusing local->xattr_req and local->xattr_rsp to store the setxattr dict + * and the xdata dict + */ + if (dict) + local->xattr_req = dict_ref(dict); + if (xdata) + local->xattr_rsp = dict_ref(xdata); + + shard_refresh_base_file(frame, this, loc, fd, + shard_post_lookup_set_xattr_handler); return 0; -out: - shard_common_failure_unwind(GF_FOP_SETXATTR, frame, -1, op_errno); +err: + shard_common_failure_unwind(fop, frame, -1, op_errno); + return 0; +} + +int32_t +shard_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + shard_common_set_xattr(frame, this, GF_FOP_FSETXATTR, NULL, fd, dict, flags, + xdata); + return 0; +} + +int32_t +shard_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + shard_common_set_xattr(frame, this, GF_FOP_SETXATTR, loc, NULL, dict, flags, + xdata); return 0; } @@ -6573,12 +7016,13 @@ shard_common_inode_write_begin(call_frame_t *frame, xlator_t *this, local->fd = fd_ref(fd); local->block_size = block_size; local->resolver_base_inode = local->fd->inode; + GF_ATOMIC_INIT(local->delta_blocks, 0); local->loc.inode = inode_ref(fd->inode); gf_uuid_copy(local->loc.gfid, fd->inode->gfid); - shard_lookup_base_file(frame, this, &local->loc, - shard_common_inode_write_post_lookup_handler); + shard_refresh_base_file(frame, this, NULL, fd, + shard_common_inode_write_post_lookup_handler); return 0; out: shard_common_failure_unwind(fop, frame, -1, ENOMEM); @@ -6723,6 +7167,9 @@ fini(xlator_t *this) GF_VALIDATE_OR_GOTO("shard", this, out); + /*Itable was not created by shard, hence setting to NULL.*/ + this->itable = NULL; + mem_pool_destroy(this->local_pool); this->local_pool = NULL; @@ -6771,7 +7218,7 @@ shard_forget(xlator_t *this, inode_t *inode) if (!ctx_uint) return 0; - ctx = (shard_inode_ctx_t *)ctx_uint; + ctx = (shard_inode_ctx_t *)(uintptr_t)ctx_uint; /* When LRU limit reaches inode will be forcefully removed from the * table, inode needs to be removed from LRU of shard as well. @@ -6870,6 +7317,14 @@ struct xlator_dumpops dumpops = { struct volume_options options[] = { { + .key = {"shard"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "enable/disable shard", + .op_version = {GD_OP_VERSION_6_0}, + .flags = OPT_FLAG_SETTABLE, + }, + { .key = {"shard-block-size"}, .type = GF_OPTION_TYPE_SIZET, .op_version = {GD_OP_VERSION_3_7_0}, @@ -6911,3 +7366,17 @@ struct volume_options options[] = { }, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .dumpops = &dumpops, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "shard", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/shard/src/shard.h b/xlators/features/shard/src/shard.h index 15c3cef0a07..4fe181b64d5 100644 --- a/xlators/features/shard/src/shard.h +++ b/xlators/features/shard/src/shard.h @@ -11,10 +11,10 @@ #ifndef __SHARD_H__ #define __SHARD_H__ -#include "xlator.h" -#include "compat-errno.h" +#include <glusterfs/xlator.h> +#include <glusterfs/compat-errno.h> #include "shard-messages.h" -#include "syncop.h" +#include <glusterfs/syncop.h> #define GF_SHARD_DIR ".shard" #define GF_SHARD_REMOVE_ME_DIR ".remove_me" @@ -254,9 +254,9 @@ typedef int32_t (*shard_post_update_size_fop_handler_t)(call_frame_t *frame, typedef struct shard_local { int op_ret; int op_errno; - int first_block; - int last_block; - int num_blocks; + uint64_t first_block; + uint64_t last_block; + uint64_t num_blocks; int call_count; int eexist_count; int create_count; @@ -275,7 +275,7 @@ typedef struct shard_local { size_t req_size; size_t readdir_size; int64_t delta_size; - int delta_blocks; + gf_atomic_t delta_blocks; loc_t loc; loc_t dot_shard_loc; loc_t dot_shard_rm_loc; @@ -318,6 +318,7 @@ typedef struct shard_local { uint32_t deletion_rate; gf_boolean_t cleanup_required; uuid_t base_gfid; + char *name; } shard_local_t; typedef struct shard_inode_ctx { diff --git a/xlators/features/snapview-client/src/Makefile.am b/xlators/features/snapview-client/src/Makefile.am index a40d2b291ad..fa08656c537 100644 --- a/xlators/features/snapview-client/src/Makefile.am +++ b/xlators/features/snapview-client/src/Makefile.am @@ -6,7 +6,7 @@ snapview_client_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) snapview_client_la_SOURCES = snapview-client.c snapview_client_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la -noinst_HEADERS = snapview-client.h snapview-client-mem-types.h +noinst_HEADERS = snapview-client.h snapview-client-mem-types.h snapview-client-messages.h AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src diff --git a/xlators/features/snapview-client/src/snapview-client-mem-types.h b/xlators/features/snapview-client/src/snapview-client-mem-types.h index aac0d571c41..3c3ab555a55 100644 --- a/xlators/features/snapview-client/src/snapview-client-mem-types.h +++ b/xlators/features/snapview-client/src/snapview-client-mem-types.h @@ -11,7 +11,7 @@ #ifndef _SVC_MEM_TYPES_H #define _SVC_MEM_TYPES_H -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum svc_mem_types { gf_svc_mt_svc_private_t = gf_common_mt_end + 1, diff --git a/xlators/features/snapview-client/src/snapview-client-messages.h b/xlators/features/snapview-client/src/snapview-client-messages.h new file mode 100644 index 00000000000..c02fb154930 --- /dev/null +++ b/xlators/features/snapview-client/src/snapview-client-messages.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2018 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. + */ + +#ifndef _SNAPVIEW_CLIENT_MESSAGES_H_ +#define _SNAPVIEW_CLIENT_MESSAGES_H_ + +#include <glusterfs/glfs-message-id.h> + +/* To add new message IDs, append new identifiers at the end of the list. + * + * Never remove a message ID. If it's not used anymore, you can rename it or + * leave it as it is, but not delete it. This is to prevent reutilization of + * IDs by other messages. + * + * The component name must match one of the entries defined in + * glfs-message-id.h. + */ + +GLFS_MSGID(SNAPVIEW_CLIENT, SVC_MSG_NO_MEMORY, SVC_MSG_MEM_ACNT_FAILED, + SVC_MSG_SET_INODE_CONTEXT_FAILED, SVC_MSG_GET_INODE_CONTEXT_FAILED, + SVC_MSG_DELETE_INODE_CONTEXT_FAILED, SVC_MSG_SET_FD_CONTEXT_FAILED, + SVC_MSG_GET_FD_CONTEXT_FAILED, SVC_MSG_DICT_SET_FAILED, + SVC_MSG_SUBVOLUME_NULL, SVC_MSG_NO_CHILD_FOR_XLATOR, + SVC_MSG_XLATOR_CHILDREN_WRONG, SVC_MSG_NORMAL_GRAPH_LOOKUP_FAIL, + SVC_MSG_SNAPVIEW_GRAPH_LOOKUP_FAIL, SVC_MSG_OPENDIR_SPECIAL_DIR, + SVC_MSG_RENAME_SNAPSHOT_ENTRY, SVC_MSG_LINK_SNAPSHOT_ENTRY, + SVC_MSG_COPY_ENTRY_POINT_FAILED, SVC_MSG_ENTRY_POINT_SPECIAL_DIR, + SVC_MSG_STR_LEN, SVC_MSG_INVALID_ENTRY_POINT, SVC_MSG_NULL_PRIV, + SVC_MSG_PRIV_DESTROY_FAILED, SVC_MSG_ALLOC_FD_FAILED, + SVC_MSG_ALLOC_INODE_FAILED, SVC_MSG_NULL_SPECIAL_DIR, + SVC_MSG_MEM_POOL_GET_FAILED); + +#define SVC_MSG_ALLOC_FD_FAILED_STR "failed to allocate new fd context" +#define SVC_MSG_SET_FD_CONTEXT_FAILED_STR "failed to set fd context" +#define SVC_MSG_STR_LEN_STR \ + "destination buffer size is less than the length of entry point name" +#define SVC_MSG_NORMAL_GRAPH_LOOKUP_FAIL_STR "lookup failed on normal graph" +#define SVC_MSG_SNAPVIEW_GRAPH_LOOKUP_FAIL_STR "lookup failed on snapview graph" +#define SVC_MSG_SET_INODE_CONTEXT_FAILED_STR "failed to set inode context" +#define SVC_MSG_NO_MEMORY_STR "failed to allocate memory" +#define SVC_MSG_COPY_ENTRY_POINT_FAILED_STR \ + "failed to copy the entry point string" +#define SVC_MSG_GET_FD_CONTEXT_FAILED_STR "fd context not found" +#define SVC_MSG_GET_INODE_CONTEXT_FAILED_STR "failed to get inode context" +#define SVC_MSG_ALLOC_INODE_FAILED_STR "failed to allocate new inode" +#define SVC_MSG_DICT_SET_FAILED_STR "failed to set dict" +#define SVC_MSG_RENAME_SNAPSHOT_ENTRY_STR \ + "rename happening on a entry residing in snapshot" +#define SVC_MSG_DELETE_INODE_CONTEXT_FAILED_STR "failed to delete inode context" +#define SVC_MSG_NULL_PRIV_STR "priv NULL" +#define SVC_MSG_INVALID_ENTRY_POINT_STR "not a valid entry point" +#define SVC_MSG_MEM_ACNT_FAILED_STR "Memory accouting init failed" +#define SVC_MSG_NO_CHILD_FOR_XLATOR_STR "configured without any child" +#define SVC_MSG_XLATOR_CHILDREN_WRONG_STR \ + "snap-view-client has got wrong subvolumes. It can have only 2" +#define SVC_MSG_ENTRY_POINT_SPECIAL_DIR_STR \ + "entry point directory cannot be part of special directory" +#define SVC_MSG_NULL_SPECIAL_DIR_STR "null special directory" +#define SVC_MSG_MEM_POOL_GET_FAILED_STR \ + "could not get mem pool for frame->local" +#define SVC_MSG_PRIV_DESTROY_FAILED_STR "failed to destroy private" +#define SVC_MSG_LINK_SNAPSHOT_ENTRY_STR \ + "link happening on a entry residin gin snapshot" +#endif /* !_SNAPVIEW_CLIENT_MESSAGES_H_ */ diff --git a/xlators/features/snapview-client/src/snapview-client.c b/xlators/features/snapview-client/src/snapview-client.c index 7a152c47a0f..486c5179d5b 100644 --- a/xlators/features/snapview-client/src/snapview-client.c +++ b/xlators/features/snapview-client/src/snapview-client.c @@ -9,8 +9,8 @@ */ #include "snapview-client.h" -#include "inode.h" -#include "byte-order.h" +#include <glusterfs/inode.h> +#include <glusterfs/byte-order.h> static void svc_local_free(svc_local_t *local) @@ -198,19 +198,15 @@ __svc_fd_ctx_get_or_new(xlator_t *this, fd_t *fd) svc_fd = svc_fd_new(); if (!svc_fd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to allocate new fd " - "context for gfid %s", - uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, SVC_MSG_ALLOC_FD_FAILED, + "gfid=%s", uuid_utoa(inode->gfid), NULL); goto out; } ret = __svc_fd_ctx_set(this, fd, svc_fd); if (ret) { - gf_log(this->name, GF_LOG_ERROR, - "failed to set fd context " - "for gfid %s", - uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_SET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(inode->gfid), NULL); ret = -1; } @@ -241,6 +237,50 @@ out: return svc_fd; } +/** + * @this: xlator + * @entry_point: pointer to the buffer provided by consumer + * + * This function is mainly for copying the entry point name + * (stored as string in priv->path) to a buffer point to by + * @entry_point within the lock. It is for the consumer to + * allocate the memory for the buffer. + * + * This function is called by all the functions (or fops) + * who need to use priv->path for avoiding the race. + * For example, either in lookup or in any other fop, + * while priv->path is being accessed, a reconfigure can + * happen to change priv->path. This ensures that, a lock + * is taken before accessing priv->path. + **/ +int +gf_svc_get_entry_point(xlator_t *this, char *entry_point, size_t dest_size) +{ + int ret = -1; + svc_private_t *priv = NULL; + + GF_VALIDATE_OR_GOTO("snapview-client", this, out); + GF_VALIDATE_OR_GOTO(this->name, entry_point, out); + + priv = this->private; + + LOCK(&priv->lock); + { + if (dest_size <= strlen(priv->path)) { + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_STR_LEN, + "dest-size=%zu", dest_size, "priv-path-len=%zu", + strlen(priv->path), "path=%s", priv->path, NULL); + } else { + snprintf(entry_point, dest_size, "%s", priv->path); + ret = 0; + } + } + UNLOCK(&priv->lock); + +out: + return ret; +} + static int32_t gf_svc_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, @@ -255,10 +295,9 @@ gf_svc_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, local = frame->local; subvolume = local->subvolume; if (!subvolume) { - gf_log_callingfn(this->name, GF_LOG_ERROR, - "path: %s, " - "gfid: %s ", - local->loc.path, inode ? uuid_utoa(inode->gfid) : ""); + gf_msg_callingfn(this->name, GF_LOG_ERROR, 0, SVC_MSG_SUBVOLUME_NULL, + "path: %s gfid: %s ", local->loc.path, + inode ? uuid_utoa(inode->gfid) : ""); GF_ASSERT(0); } @@ -279,17 +318,17 @@ gf_svc_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, */ if (op_ret) { if (subvolume == FIRST_CHILD(this)) { - gf_log(this->name, - (op_errno == ENOENT || op_errno == ESTALE) ? GF_LOG_DEBUG - : GF_LOG_ERROR, - "Lookup failed on normal graph with error %s", - strerror(op_errno)); + gf_smsg(this->name, + (op_errno == ENOENT || op_errno == ESTALE) ? GF_LOG_DEBUG + : GF_LOG_ERROR, + op_errno, SVC_MSG_NORMAL_GRAPH_LOOKUP_FAIL, "error=%s", + strerror(op_errno), NULL); } else { - gf_log(this->name, - (op_errno == ENOENT || op_errno == ESTALE) ? GF_LOG_DEBUG - : GF_LOG_ERROR, - "Lookup failed on snapview graph with error %s", - strerror(op_errno)); + gf_smsg(this->name, + (op_errno == ENOENT || op_errno == ESTALE) ? GF_LOG_DEBUG + : GF_LOG_ERROR, + op_errno, SVC_MSG_SNAPVIEW_GRAPH_LOOKUP_FAIL, "error=%s", + strerror(op_errno), NULL); goto out; } @@ -299,10 +338,9 @@ gf_svc_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, ret = svc_inode_ctx_get(this, inode, &inode_type); if (ret < 0 || inode == NULL) { - gf_log(this->name, GF_LOG_DEBUG, - "Lookup on normal graph failed. " - "Sending lookup to snapview-server"); - + gf_msg_debug(this->name, 0, + "Lookup on normal graph failed. " + " Sending lookup to snapview-server"); subvolume = SECOND_CHILD(this); local->subvolume = subvolume; STACK_WIND(frame, gf_svc_lookup_cbk, subvolume, @@ -321,9 +359,8 @@ gf_svc_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, ret = svc_inode_ctx_set(this, inode, inode_type); if (ret) - gf_log(this->name, GF_LOG_ERROR, - "failed to set inode type" - "into the context"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_SET_INODE_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(inode->gfid), NULL); out: if (do_unwind) { @@ -343,20 +380,19 @@ gf_svc_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) int op_ret = -1; int op_errno = EINVAL; inode_t *parent = NULL; - svc_private_t *priv = NULL; dict_t *new_xdata = NULL; int inode_type = -1; int parent_type = -1; gf_boolean_t wind = _gf_false; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("svc", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); - priv = this->private; - ret = svc_inode_ctx_get(this, loc->inode, &inode_type); if (!__is_root_gfid(loc->gfid)) { if (loc->parent) { @@ -371,9 +407,9 @@ gf_svc_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) local = mem_get0(this->local_pool); if (!local) { - gf_log(this->name, GF_LOG_ERROR, "failed to allocate local"); op_ret = -1; op_errno = ENOMEM; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, SVC_MSG_NO_MEMORY, NULL); goto out; } @@ -412,7 +448,13 @@ gf_svc_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) } } - if (strcmp(loc->name, priv->path)) { + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); + goto out; + } + + if (strcmp(loc->name, entry_point)) { if (parent_type == VIRTUAL_INODE) { subvolume = SECOND_CHILD(this); } else { @@ -430,8 +472,8 @@ gf_svc_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) /* Indication of whether the lookup is happening on the entry point or not, to the snapview-server. */ - SVC_ENTRY_POINT_SET(this, xdata, op_ret, op_errno, new_xdata, priv, - ret, out); + SVC_ENTRY_POINT_SET(this, xdata, op_ret, op_errno, new_xdata, ret, + out); } } @@ -470,6 +512,9 @@ gf_svc_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) 0, }; loc_t *temp_loc = NULL; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("svc", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); @@ -485,7 +530,13 @@ gf_svc_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) if (path_len >= snap_len && inode_type == VIRTUAL_INODE) { path = &loc->path[path_len - snap_len]; - if (!strcmp(path, priv->path)) { + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); + goto out; + } + + if (!strcmp(path, entry_point)) { /* * statfs call for virtual snap directory. * Sent the fops to parent volume by removing @@ -516,20 +567,24 @@ gf_svc_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata) { - /* Consider a testcase: + /* TODO: FIX ME + * Consider a testcase: * #mount -t nfs host1:/vol1 /mnt * #ls /mnt * #ls /mnt/.snaps (As expected this fails) * #gluster volume set vol1 features.uss enable - * Now `ls /mnt/.snaps` should work, - * but fails with No such file or directory. - * This is because NFS client caches the list of files in - * a directory. This cache is updated if there are any changes - * in the directory attributes. To solve this problem change - * a attribute 'ctime' when USS is enabled + * Now `ls /mnt/.snaps` should work, but fails with No such file or + * directory. This is because NFS client (gNFS) caches the list of files + * in a directory. This cache is updated if there are any changes in the + * directory attributes. So, one way to solve this problem is to change + * 'ctime' attribute when USS is enabled as below. + * + * if (op_ret == 0 && IA_ISDIR(buf->ia_type)) + * buf->ia_ctime_nsec++; + * + * But this is not the ideal solution as applications see the unexpected + * ctime change causing failures. */ - if (op_ret == 0 && IA_ISDIR(buf->ia_type)) - buf->ia_ctime_nsec++; SVC_STACK_UNWIND(stat, frame, op_ret, op_errno, buf, xdata); return 0; @@ -627,10 +682,10 @@ gf_svc_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (!strcmp(local->loc.path, priv->special_dir) || !strcmp(local->loc.path, path)) { - gf_log_callingfn(this->name, GF_LOG_DEBUG, - "got opendir on special " - "directory %s (%s)", - path, uuid_utoa(fd->inode->gfid)); + gf_msg_debug(this->name, 0, + "got opendir on special directory" + " %s (gfid: %s)", + path, uuid_utoa(fd->inode->gfid)); special_dir = _gf_true; } } @@ -638,8 +693,8 @@ gf_svc_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (special_dir) { svc_fd = svc_fd_ctx_get_or_new(this, fd); if (!svc_fd) { - gf_log(this->name, GF_LOG_ERROR, "fd context not found for %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_GET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto out; } @@ -683,20 +738,18 @@ gf_svc_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, local = mem_get0(this->local_pool); if (!local) { - gf_log(this->name, GF_LOG_ERROR, - "failed to allocate memory " - "for local (path: %s, gfid: %s)", - loc->path, uuid_utoa(fd->inode->gfid)); op_errno = ENOMEM; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, SVC_MSG_NO_MEMORY, + "path=%s", loc->path, "gfid=%s", uuid_utoa(fd->inode->gfid), + NULL); goto out; } + loc_copy(&local->loc, loc); + frame->local = local; SVC_GET_SUBVOL_FROM_CTX(this, op_ret, op_errno, inode_type, ret, loc->inode, subvolume, out); - - loc_copy(&local->loc, loc); local->subvolume = subvolume; - frame->local = local; STACK_WIND(frame, gf_svc_opendir_cbk, subvolume, subvolume->fops->opendir, loc, fd, xdata); @@ -729,10 +782,9 @@ gf_svc_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, if (ret < 0) { op_ret = -1; op_errno = EINVAL; - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s (gfid: %s)", - loc->path, uuid_utoa(loc->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "path=%s", loc->path, + "gfid= %s", uuid_utoa(loc->inode->gfid), NULL); goto out; } @@ -773,10 +825,12 @@ gf_svc_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, ret = svc_inode_ctx_get (this, fd->inode, &inode_type); if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, "failed to get the inode " - "context for %s", uuid_utoa (fd->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_msg (this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "failed to " + "get the inode context for %s", + uuid_utoa (fd->inode->gfid)); goto out; } @@ -814,6 +868,9 @@ gf_svc_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, char attrname[PATH_MAX] = ""; char attrval[64] = ""; dict_t *dict = NULL; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("svc", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); @@ -837,14 +894,20 @@ gf_svc_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, strcat(attrname, ":"); if (!strcmp(attrname, GF_XATTR_GET_REAL_FILENAME_KEY)) { - if (!strcasecmp(attrval, priv->path)) { + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); + goto out; + } + + if (!strcasecmp(attrval, entry_point)) { dict = dict_new(); if (NULL == dict) { op_errno = ENOMEM; goto out; } - ret = dict_set_dynstr_with_alloc(dict, (char *)name, priv->path); + ret = dict_set_dynstr_with_alloc(dict, (char *)name, entry_point); if (ret) { op_errno = ENOMEM; @@ -852,7 +915,7 @@ gf_svc_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, } op_errno = 0; - op_ret = strlen(priv->path) + 1; + op_ret = strlen(entry_point) + 1; /* We should return from here */ goto out; } @@ -927,12 +990,11 @@ gf_svc_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, ret = svc_inode_ctx_get(this, loc->inode, &inode_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get inode context " - "for %s (gfid: %s)", - loc->name, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "name=%s", loc->name, + "gfid=%s", uuid_utoa(loc->inode->gfid), NULL); goto out; } @@ -972,12 +1034,11 @@ gf_svc_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, ret = svc_inode_ctx_get(this, fd->inode, &inode_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get inode context " - "for %s", - uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(fd->inode->gfid), NULL); goto out; } @@ -1017,12 +1078,11 @@ gf_svc_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, ret = svc_inode_ctx_get(this, loc->inode, &inode_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s (gfid: %s)", - loc->name, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "name=%s", loc->name, + "gfid=%s", uuid_utoa(loc->inode->gfid), NULL); goto out; } @@ -1058,9 +1118,8 @@ gf_svc_mkdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, inode_type = NORMAL_INODE; ret = svc_inode_ctx_set(this, inode, inode_type); if (ret) - gf_log(this->name, GF_LOG_ERROR, - "failed to set inode " - "context"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_SET_INODE_CONTEXT_FAILED, + NULL); out: SVC_STACK_UNWIND(mkdir, frame, op_ret, op_errno, inode, buf, preparent, @@ -1076,29 +1135,33 @@ gf_svc_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, int ret = -1; int op_ret = -1; int op_errno = EINVAL; - svc_private_t *priv = NULL; gf_boolean_t wind = _gf_false; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("svc", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); - priv = this->private; - ret = svc_inode_ctx_get(this, loc->parent, &parent_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s", - uuid_utoa(loc->parent->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(loc->parent->gfid), NULL); + goto out; + } + + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); goto out; } - if (strcmp(loc->name, priv->path) && parent_type == NORMAL_INODE) { + if (strcmp(loc->name, entry_point) && parent_type == NORMAL_INODE) { STACK_WIND(frame, gf_svc_mkdir_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); } else { @@ -1131,9 +1194,8 @@ gf_svc_mknod_cbk(call_frame_t *frame, void *cookie, xlator_t *this, inode_type = NORMAL_INODE; ret = svc_inode_ctx_set(this, inode, inode_type); if (ret) - gf_log(this->name, GF_LOG_ERROR, - "failed to set inode " - "context"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_SET_INODE_CONTEXT_FAILED, + NULL); out: SVC_STACK_UNWIND(mknod, frame, op_ret, op_errno, inode, buf, preparent, @@ -1149,29 +1211,33 @@ gf_svc_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, int ret = -1; int op_ret = -1; int op_errno = EINVAL; - svc_private_t *priv = NULL; gf_boolean_t wind = _gf_false; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("svc", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); - priv = this->private; - ret = svc_inode_ctx_get(this, loc->parent, &parent_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s", - uuid_utoa(loc->parent->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(loc->parent->gfid), NULL); + goto out; + } + + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); goto out; } - if (strcmp(loc->name, priv->path) && parent_type == NORMAL_INODE) { + if (strcmp(loc->name, entry_point) && parent_type == NORMAL_INODE) { STACK_WIND(frame, gf_svc_mknod_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, xdata); @@ -1252,9 +1318,8 @@ gf_svc_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, inode_type = NORMAL_INODE; ret = svc_inode_ctx_set(this, inode, inode_type); if (ret) - gf_log(this->name, GF_LOG_ERROR, - "failed to set inode " - "context"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_SET_INODE_CONTEXT_FAILED, + NULL); out: SVC_STACK_UNWIND(create, frame, op_ret, op_errno, fd, inode, stbuf, @@ -1271,30 +1336,34 @@ gf_svc_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, int ret = -1; int op_ret = -1; int op_errno = EINVAL; - svc_private_t *priv = NULL; gf_boolean_t wind = _gf_false; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("svc", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); GF_VALIDATE_OR_GOTO(this->name, fd, out); - priv = this->private; - ret = svc_inode_ctx_get(this, loc->parent, &parent_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s", - uuid_utoa(loc->parent->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(loc->parent->gfid), NULL); + goto out; + } + + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); goto out; } - if (strcmp(loc->name, priv->path) && parent_type == NORMAL_INODE) { + if (strcmp(loc->name, entry_point) && parent_type == NORMAL_INODE) { STACK_WIND(frame, gf_svc_create_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, fd, xdata); @@ -1328,9 +1397,8 @@ gf_svc_symlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, inode_type = NORMAL_INODE; ret = svc_inode_ctx_set(this, inode, inode_type); if (ret) - gf_log(this->name, GF_LOG_ERROR, - "failed to set inode " - "context"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_SET_INODE_CONTEXT_FAILED, + NULL); out: SVC_STACK_UNWIND(symlink, frame, op_ret, op_errno, inode, buf, preparent, @@ -1347,29 +1415,33 @@ gf_svc_symlink(call_frame_t *frame, xlator_t *this, const char *linkpath, int op_ret = -1; int op_errno = EINVAL; int ret = -1; - svc_private_t *priv = NULL; gf_boolean_t wind = _gf_false; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("svc", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); - priv = this->private; - ret = svc_inode_ctx_get(this, loc->parent, &parent_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s", - uuid_utoa(loc->parent->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(loc->parent->gfid), NULL); + goto out; + } + + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); goto out; } - if (strcmp(loc->name, priv->path) && parent_type == NORMAL_INODE) { + if (strcmp(loc->name, entry_point) && parent_type == NORMAL_INODE) { STACK_WIND(frame, gf_svc_symlink_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->symlink, linkpath, loc, umask, xdata); @@ -1405,12 +1477,11 @@ gf_svc_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, ret = svc_inode_ctx_get(this, loc->inode, &inode_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s", - uuid_utoa(loc->parent->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(loc->parent->gfid), NULL); goto out; } @@ -1532,14 +1603,13 @@ gf_svc_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, gf_dirent_t *entry = NULL; gf_dirent_t *tmpentry = NULL; svc_local_t *local = NULL; - svc_private_t *priv = NULL; + char entry_point[NAME_MAX + 1] = { + 0, + }; if (op_ret < 0) goto out; - GF_VALIDATE_OR_GOTO(this->name, this->private, out); - - priv = this->private; local = frame->local; /* If .snaps pre-exists, then it should not be listed @@ -1550,9 +1620,23 @@ gf_svc_readdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, if (local->subvolume != FIRST_CHILD(this)) goto out; + /* + * Better to goto out if getting the entry point + * fails. We might end up sending the directory + * entry for the snapview entry point in the readdir + * response. But, the intention is to avoid the race + * condition where priv->path is being changed in + * reconfigure while this is accessing it. + */ + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, op_errno, + SVC_MSG_COPY_ENTRY_POINT_FAILED, NULL); + goto out; + } + list_for_each_entry_safe(entry, tmpentry, &entries->list, list) { - if (strcmp(priv->path, entry->d_name) == 0) + if (strcmp(entry_point, entry->d_name) == 0) gf_dirent_entry_free(entry); } @@ -1584,10 +1668,8 @@ gf_svc_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, svc_fd = svc_fd_ctx_get_or_new(this, fd); if (!svc_fd) - gf_log(this->name, GF_LOG_ERROR, - "failed to get the fd " - "context for the inode %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_GET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); else { if (svc_fd->entry_point_handled && off == svc_fd->last_offset) { op_ret = 0; @@ -1601,7 +1683,8 @@ gf_svc_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, local = mem_get0(this->local_pool); if (!local) { - gf_log(this->name, GF_LOG_ERROR, "failed to allocate local"); + gf_smsg(this->name, GF_LOG_ERROR, op_errno, SVC_MSG_NO_MEMORY, + "inode-gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto out; } local->subvolume = subvolume; @@ -1653,17 +1736,16 @@ gf_svc_readdirp_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, { gf_dirent_t entries; gf_dirent_t *entry = NULL; - svc_private_t *private = NULL; svc_fd_t *svc_fd = NULL; svc_local_t *local = NULL; int inode_type = -1; int ret = -1; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("snapview-client", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); - private - = this->private; INIT_LIST_HEAD(&entries.list); local = frame->local; @@ -1683,21 +1765,25 @@ gf_svc_readdirp_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, svc_fd = svc_fd_ctx_get(this, local->fd); if (!svc_fd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the fd " - "context for the inode %s", - uuid_utoa(local->fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_GET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(local->fd->inode->gfid), NULL); + op_ret = 0; + op_errno = ENOENT; + goto out; + } + + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, 0, SVC_MSG_COPY_ENTRY_POINT_FAILED, + NULL); op_ret = 0; op_errno = ENOENT; goto out; } - entry = gf_dirent_for_name(private->path); + entry = gf_dirent_for_name(entry_point); if (!entry) { - gf_log(this->name, GF_LOG_ERROR, - "failed to allocate memory " - "for the entry %s", - private->path); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_NO_MEMORY, + "entry-point=%s", entry_point, NULL); op_ret = 0; op_errno = ENOMEM; goto out; @@ -1711,9 +1797,8 @@ gf_svc_readdirp_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, inode_type = VIRTUAL_INODE; ret = svc_inode_ctx_set(this, entry->inode, inode_type); if (ret) - gf_log(this->name, GF_LOG_ERROR, - "failed to set the inode " - "context"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_SET_INODE_CONTEXT_FAILED, + "entry-name=%s", entry->d_name, NULL); list_add_tail(&entry->list, &entries.list); op_ret = 1; @@ -1733,18 +1818,16 @@ int gf_svc_special_dir_revalidate_lookup(call_frame_t *frame, xlator_t *this, dict_t *xdata) { - svc_private_t *private = NULL; svc_local_t *local = NULL; loc_t *loc = NULL; dict_t *tmp_xdata = NULL; char *path = NULL; int ret = -1; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("snapview-client", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); - - private - = this->private; local = frame->local; loc = &local->loc; @@ -1760,14 +1843,19 @@ gf_svc_special_dir_revalidate_lookup(call_frame_t *frame, xlator_t *this, inode_unref(loc->inode); loc->inode = inode_new(loc->parent->table); if (!loc->inode) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate new inode"); + gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, SVC_MSG_ALLOC_INODE_FAILED, + NULL); + goto out; + } + + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, 0, SVC_MSG_COPY_ENTRY_POINT_FAILED, + NULL); goto out; } gf_uuid_copy(local->loc.gfid, loc->inode->gfid); - ret = inode_path(loc->parent, private->path, &path); + ret = inode_path(loc->parent, entry_point, &path); if (ret < 0) goto out; @@ -1792,7 +1880,7 @@ gf_svc_special_dir_revalidate_lookup(call_frame_t *frame, xlator_t *this, ret = dict_set_str(tmp_xdata, "entry-point", "true"); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "failed to set dict"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_DICT_SET_FAILED, NULL); goto out; } @@ -1821,6 +1909,9 @@ gf_svc_readdir_on_special_dir(call_frame_t *frame, void *cookie, xlator_t *this, int ret = -1; gf_boolean_t unwind = _gf_true; svc_fd_t *svc_fd = NULL; + char entry_point[NAME_MAX + 1] = { + 0, + }; GF_VALIDATE_OR_GOTO("snapview-client", this, out); GF_VALIDATE_OR_GOTO(this->name, this->private, out); @@ -1833,10 +1924,8 @@ gf_svc_readdir_on_special_dir(call_frame_t *frame, void *cookie, xlator_t *this, fd = local->fd; svc_fd = svc_fd_ctx_get(this, fd); if (!svc_fd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the fd " - "context for the inode %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_GET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); goto out; } @@ -1852,13 +1941,18 @@ gf_svc_readdir_on_special_dir(call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret == 0 && op_errno == ENOENT && private->special_dir && strcmp(private->special_dir, "") && svc_fd->special_dir && local->subvolume == FIRST_CHILD(this)) { - inode = inode_grep(fd->inode->table, fd->inode, private->path); + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, 0, + SVC_MSG_GET_FD_CONTEXT_FAILED, NULL); + goto out; + } + + inode = inode_grep(fd->inode->table, fd->inode, entry_point); if (!inode) { inode = inode_new(fd->inode->table); if (!inode) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate new inode"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_ALLOC_INODE_FAILED, + NULL); goto out; } } @@ -1866,7 +1960,7 @@ gf_svc_readdir_on_special_dir(call_frame_t *frame, void *cookie, xlator_t *this, gf_uuid_copy(local->loc.pargfid, fd->inode->gfid); gf_uuid_copy(local->loc.gfid, inode->gfid); if (gf_uuid_is_null(inode->gfid)) - ret = inode_path(fd->inode, private->path, &path); + ret = inode_path(fd->inode, entry_point, &path); else ret = inode_path(inode, NULL, &path); @@ -1888,7 +1982,7 @@ gf_svc_readdir_on_special_dir(call_frame_t *frame, void *cookie, xlator_t *this, goto out; ret = dict_set_str(tmp_xdata, "entry-point", "true"); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "failed to set dict"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_DICT_SET_FAILED, NULL); goto out; } @@ -1925,22 +2019,21 @@ gf_svc_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int ret = -1; svc_fd_t *svc_fd = NULL; gf_boolean_t unwind = _gf_true; - svc_private_t *priv = NULL; + char entry_point[NAME_MAX + 1] = { + 0, + }; if (op_ret < 0) goto out; GF_VALIDATE_OR_GOTO("snapview-client", this, out); - GF_VALIDATE_OR_GOTO(this->name, this->private, out); - priv = this->private; + local = frame->local; svc_fd = svc_fd_ctx_get(this, local->fd); if (!svc_fd) { - gf_log(this->name, GF_LOG_WARNING, - "failed to get the fd " - "context for the gfid %s", - uuid_utoa(local->fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_WARNING, 0, SVC_MSG_GET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(local->fd->inode->gfid), NULL); } if (local->subvolume == FIRST_CHILD(this)) @@ -1948,6 +2041,19 @@ gf_svc_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, else inode_type = VIRTUAL_INODE; + /* + * Better to goto out and return whatever is there in the + * readdirp response (even if the readdir response contains + * a directory entry for the snapshot entry point). Otherwise + * if we ignore the error, then there is a chance of race + * condition where, priv->path is changed in reconfigure + */ + if (gf_svc_get_entry_point(this, entry_point, sizeof(entry_point))) { + gf_smsg(this->name, GF_LOG_WARNING, 0, SVC_MSG_COPY_ENTRY_POINT_FAILED, + NULL); + goto out; + } + list_for_each_entry_safe(entry, tmpentry, &entries->list, list) { /* If .snaps pre-exists, then it should not be listed @@ -1955,7 +2061,7 @@ gf_svc_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, * so filter the .snaps entry if exists. * However it is OK to list .snaps in VIRTUAL world */ - if (inode_type == NORMAL_INODE && !strcmp(priv->path, entry->d_name)) { + if (inode_type == NORMAL_INODE && !strcmp(entry_point, entry->d_name)) { gf_dirent_entry_free(entry); continue; } @@ -1965,9 +2071,8 @@ gf_svc_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, ret = svc_inode_ctx_set(this, entry->inode, inode_type); if (ret) - gf_log(this->name, GF_LOG_ERROR, - "failed to set inode " - "context"); + gf_smsg(this->name, GF_LOG_ERROR, 0, + SVC_MSG_SET_INODE_CONTEXT_FAILED, NULL); if (svc_fd) svc_fd->last_offset = entry->d_off; } @@ -2005,8 +2110,8 @@ gf_svc_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, local = mem_get0(this->local_pool); if (!local) { - gf_log(this->name, GF_LOG_ERROR, "failed to allocate local"); op_errno = ENOMEM; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, SVC_MSG_NO_MEMORY, NULL); goto out; } @@ -2021,10 +2126,8 @@ gf_svc_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, */ svc_fd = svc_fd_ctx_get_or_new(this, fd); if (!svc_fd) - gf_log(this->name, GF_LOG_ERROR, - "failed to get the fd " - "context for the inode %s", - uuid_utoa(fd->inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_GET_FD_CONTEXT_FAILED, + "gfid=%s", uuid_utoa(fd->inode->gfid), NULL); else { if (svc_fd->entry_point_handled && off == svc_fd->last_offset) { op_ret = 0; @@ -2077,34 +2180,30 @@ gf_svc_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, ret = svc_inode_ctx_get(this, oldloc->inode, &src_inode_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for the inode %s", - uuid_utoa(oldloc->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(oldloc->inode->gfid), NULL); goto out; } if (src_inode_type == VIRTUAL_INODE) { - gf_log(this->name, GF_LOG_ERROR, - "rename happening on a entry" - " %s residing in snapshot", - oldloc->name); op_ret = -1; op_errno = EROFS; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_RENAME_SNAPSHOT_ENTRY, "name=%s", oldloc->name, NULL); goto out; } if (newloc->inode) { ret = svc_inode_ctx_get(this, newloc->inode, &dst_inode_type); if (!ret && dst_inode_type == VIRTUAL_INODE) { - gf_log(this->name, GF_LOG_ERROR, - "rename of %s " - "happening to a entry %s residing in snapshot", - oldloc->name, newloc->name); op_ret = -1; op_errno = EROFS; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_RENAME_SNAPSHOT_ENTRY, "oldloc-name=%s", + oldloc->name, "newloc-name=%s", newloc->name, NULL); goto out; } } @@ -2112,12 +2211,11 @@ gf_svc_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, if (dst_inode_type < 0) { ret = svc_inode_ctx_get(this, newloc->parent, &dst_parent_type); if (!ret && dst_parent_type == VIRTUAL_INODE) { - gf_log(this->name, GF_LOG_ERROR, - "rename of %s " - "happening to a entry %s residing in snapshot", - oldloc->name, newloc->name); op_ret = -1; op_errno = EROFS; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_RENAME_SNAPSHOT_ENTRY, "oldloc-name=%s", + oldloc->name, "newloc-name=%s", newloc->name, NULL); goto out; } } @@ -2157,23 +2255,20 @@ gf_svc_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, ret = svc_inode_ctx_get(this, oldloc->inode, &src_inode_type); if (!ret && src_inode_type == VIRTUAL_INODE) { - gf_log(this->name, GF_LOG_ERROR, - "rename happening on a entry" - " %s residing in snapshot", - oldloc->name); op_ret = -1; op_errno = EROFS; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, SVC_MSG_LINK_SNAPSHOT_ENTRY, + "oldloc-name=%s", oldloc->name, NULL); goto out; } ret = svc_inode_ctx_get(this, newloc->parent, &dst_parent_type); if (!ret && dst_parent_type == VIRTUAL_INODE) { - gf_log(this->name, GF_LOG_ERROR, - "rename of %s " - "happening to a entry %s residing in snapshot", - oldloc->name, newloc->name); op_ret = -1; op_errno = EROFS; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, SVC_MSG_LINK_SNAPSHOT_ENTRY, + "oldloc-name=%s", oldloc->name, "newloc-name=%s", newloc->name, + NULL); goto out; } @@ -2206,12 +2301,11 @@ gf_svc_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, ret = svc_inode_ctx_get(this, loc->inode, &inode_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the inode " - "context for %s (gfid: %s)", - loc->path, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "path=%s", loc->path, + "gfid=%s", uuid_utoa(loc->inode->gfid), NULL); goto out; } @@ -2250,12 +2344,11 @@ gf_svc_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int datasync, ret = svc_inode_ctx_get(this, fd->inode, &inode_type); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get inode context " - "for %s", - uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_smsg(this->name, GF_LOG_ERROR, op_errno, + SVC_MSG_GET_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(fd->inode->gfid), NULL); goto out; } @@ -2318,7 +2411,7 @@ gf_svc_releasedir(xlator_t *this, fd_t *fd) ret = fd_ctx_del(fd, this, &tmp_pfd); if (ret < 0) { - gf_log(this->name, GF_LOG_DEBUG, "pfd from fd=%p is NULL", fd); + gf_msg_debug(this->name, 0, "pfd from fd=%p is NULL", fd); goto out; } @@ -2339,10 +2432,9 @@ gf_svc_forget(xlator_t *this, inode_t *inode) ret = inode_ctx_del(inode, this, &value); if (ret) { - gf_log(this->name, GF_LOG_ERROR, - "failed to delete inode " - "context for %s", - uuid_utoa(inode->gfid)); + gf_smsg(this->name, GF_LOG_ERROR, 0, + SVC_MSG_DELETE_INODE_CONTEXT_FAILED, "gfid=%s", + uuid_utoa(inode->gfid), NULL); goto out; } @@ -2350,16 +2442,112 @@ out: return 0; } +static int +gf_svc_priv_destroy(xlator_t *this, svc_private_t *priv) +{ + int ret = -1; + + if (!priv) { + gf_smsg(this->name, GF_LOG_WARNING, 0, SVC_MSG_NULL_PRIV, NULL); + goto out; + } + + GF_FREE(priv->path); + GF_FREE(priv->special_dir); + + LOCK_DESTROY(&priv->lock); + + GF_FREE(priv); + + if (this->local_pool) { + mem_pool_destroy(this->local_pool); + this->local_pool = NULL; + } + + ret = 0; + +out: + return ret; +} + +/** + * ** NOTE **: + * ============= + * The option "snapdir-entry-path" is NOT reconfigurable. + * That option as of now is only for the consumption of + * samba, where, it needs to tell glusterfs about the + * directory that is shared with windows client for the + * access. Now, in windows-explorer (GUI) interface, for + * the directory shared, the entry point to the snapshot + * world (snapshot-directory option) should be visible, + * atleast as a hidden entry. For that to happen, glusterfs + * has to send that entry in the readdir response coming on + * the directory used as the smb share. Therefore, samba, + * while initializing the gluster volume (via gfapi) sets + * the xlator option "snapdir-entry-path" to the directory + * which is to be shared with windows (check the file + * vfs_glusterfs.c from samba source code). So to avoid + * problems with smb access, not allowing snapdir-entry-path + * option to be configurable. That option is for those + * consumers who know what they are doing. + **/ int reconfigure(xlator_t *this, dict_t *options) { svc_private_t *priv = NULL; + char *path = NULL; + gf_boolean_t show_entry_point = _gf_false; + char *tmp = NULL; priv = this->private; - GF_OPTION_RECONF("snapshot-directory", priv->path, options, str, out); - GF_OPTION_RECONF("show-snapshot-directory", priv->show_entry_point, options, - bool, out); + GF_OPTION_RECONF("snapshot-directory", path, options, str, out); + if (!path || (strlen(path) > NAME_MAX) || path[0] != '.') { + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_INVALID_ENTRY_POINT, + "path=%s", path, NULL); + goto out; + } + + GF_OPTION_RECONF("show-snapshot-directory", show_entry_point, options, bool, + out); + + /* + * The assumption now is that priv->path is an allocated memory (either + * in init or in a previous reconfigure). + * So, the intention here is to preserve the older contents of the option + * until the new option's value has been completely stored in the priv. + * So, do this. + * - Store the pointer of priv->path in a temporary pointer. + * - Allocate new memory for the new value of the option that is just + * obtained from the above call to GF_OPTION_RECONF. + * - If the above allocation fails, again set the pointer from priv + * to the address stored in tmp. i.e. the previous value. + * - If the allocation succeeds, then free the tmp pointer. + * WARNING: Before changing the allocation and freeing logic of + * priv->path, always check the init function to see how + * priv->path is set. Take decisions accordingly. As of now, + * the assumption is that, the string elements of private + * structure of snapview-client are allocated (either in + * init or here in reconfugure). + */ + LOCK(&priv->lock); + { + tmp = priv->path; + priv->path = NULL; + priv->path = gf_strdup(path); + if (!priv->path) { + gf_log(this->name, GF_LOG_ERROR, + "failed to reconfigure snapshot-directory option to %s", + path); + priv->path = tmp; + } else { + GF_FREE(tmp); + tmp = NULL; + } + + priv->show_entry_point = show_entry_point; + } + UNLOCK(&priv->lock); out: return 0; @@ -2376,10 +2564,7 @@ mem_acct_init(xlator_t *this) ret = xlator_mem_acct_init(this, gf_svc_mt_end + 1); if (ret != 0) { - gf_log(this->name, GF_LOG_WARNING, - "Memory accounting" - " init failed"); - return ret; + gf_smsg(this->name, GF_LOG_WARNING, 0, SVC_MSG_MEM_ACNT_FAILED, NULL); } return ret; @@ -2392,9 +2577,11 @@ init(xlator_t *this) int ret = -1; int children = 0; xlator_list_t *xl = NULL; + char *path = NULL; + char *special_dir = NULL; if (!this->children) { - gf_log(this->name, GF_LOG_ERROR, "configured without any child"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_NO_CHILD_FOR_XLATOR, NULL); goto out; } @@ -2405,16 +2592,16 @@ init(xlator_t *this) } if (children != 2) { - gf_log(this->name, GF_LOG_ERROR, - "snap-view-client has got " - "%d subvolumes. It can have only 2 subvolumes.", - children); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_XLATOR_CHILDREN_WRONG, + "subvol-num=%d", children, NULL); goto out; } /* This can be the top of graph in certain cases */ if (!this->parents) { - gf_log(this->name, GF_LOG_DEBUG, "dangling volume. check volfile "); + gf_msg_debug(this->name, 0, + "dangling volume. Check " + "volfile"); } private @@ -2422,35 +2609,59 @@ init(xlator_t *this) if (!private) goto out; - GF_OPTION_INIT("snapshot-directory", private->path, str, out); - GF_OPTION_INIT("snapdir-entry-path", private->special_dir, str, out); - GF_OPTION_INIT("show-snapshot-directory", private->show_entry_point, bool, - out); + LOCK_INIT(&private->lock); - if (strstr(private->special_dir, private->path)) { - gf_log(this->name, GF_LOG_ERROR, - "entry point directory " - "cannot be part of the special directory"); - GF_FREE(private->special_dir); - private - ->special_dir = NULL; + GF_OPTION_INIT("snapshot-directory", path, str, out); + if (!path || (strlen(path) > NAME_MAX) || path[0] != '.') { + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_INVALID_ENTRY_POINT, + "path=%s", path, NULL); goto out; } - this->private = private; + private + ->path = gf_strdup(path); + if (!private->path) { + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_NO_MEMORY, + "entry-point-path=%s", path, NULL); + goto out; + } + + GF_OPTION_INIT("snapdir-entry-path", special_dir, str, out); + if (!special_dir || strstr(special_dir, path)) { + if (special_dir) + gf_smsg(this->name, GF_LOG_ERROR, 0, + SVC_MSG_ENTRY_POINT_SPECIAL_DIR, "path=%s", path, + "special-dir=%s", special_dir); + else + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_NULL_SPECIAL_DIR, + NULL); + goto out; + } + + private + ->special_dir = gf_strdup(special_dir); + if (!private->special_dir) { + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_NO_MEMORY, + "special-directory=%s", special_dir, NULL); + goto out; + } + + GF_OPTION_INIT("show-snapshot-directory", private->show_entry_point, bool, + out); + this->local_pool = mem_pool_new(svc_local_t, 128); if (!this->local_pool) { - gf_log(this->name, GF_LOG_ERROR, - "could not get mem pool for " - "frame->local"); + gf_smsg(this->name, GF_LOG_ERROR, 0, SVC_MSG_MEM_POOL_GET_FAILED, NULL); goto out; } + this->private = private; + ret = 0; out: if (ret) - GF_FREE(private); + (void)gf_svc_priv_destroy(this, private); return ret; } @@ -2467,9 +2678,15 @@ fini(xlator_t *this) if (!priv) return; - this->private = NULL; + /* + * Just log the failure and go ahead to + * set this->priv to NULL. + */ + if (gf_svc_priv_destroy(this, priv)) + gf_smsg(this->name, GF_LOG_WARNING, 0, SVC_MSG_PRIV_DESTROY_FAILED, + NULL); - GF_FREE(priv); + this->private = NULL; return; } @@ -2558,3 +2775,17 @@ struct volume_options options[] = { }, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "snapview-client", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/snapview-client/src/snapview-client.h b/xlators/features/snapview-client/src/snapview-client.h index ccce7bebca6..166116a439d 100644 --- a/xlators/features/snapview-client/src/snapview-client.h +++ b/xlators/features/snapview-client/src/snapview-client.h @@ -10,12 +10,13 @@ #ifndef __SNAP_VIEW_CLIENT_H__ #define __SNAP_VIEW_CLIENT_H__ -#include "glusterfs.h" -#include "logging.h" -#include "dict.h" -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "snapview-client-mem-types.h" +#include "snapview-client-messages.h" struct __svc_local { loc_t loc; @@ -38,8 +39,8 @@ typedef struct __svc_local svc_local_t; svc_local_free(__local); \ } while (0) -#define SVC_ENTRY_POINT_SET(this, xdata, op_ret, op_errno, new_xdata, priv, \ - ret, label) \ +#define SVC_ENTRY_POINT_SET(this, xdata, op_ret, op_errno, new_xdata, ret, \ + label) \ do { \ if (!xdata) { \ xdata = new_xdata = dict_new(); \ @@ -80,6 +81,7 @@ struct svc_private { char *path; char *special_dir; /* needed for samba */ gf_boolean_t show_entry_point; + gf_lock_t lock; /* mainly to guard private->path */ }; typedef struct svc_private svc_private_t; diff --git a/xlators/features/snapview-server/src/Makefile.am b/xlators/features/snapview-server/src/Makefile.am index 2d39759ff80..2935f138a4c 100644 --- a/xlators/features/snapview-server/src/Makefile.am +++ b/xlators/features/snapview-server/src/Makefile.am @@ -13,7 +13,7 @@ snapview_server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ $(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la -noinst_HEADERS = snapview-server.h snapview-server-mem-types.h +noinst_HEADERS = snapview-server.h snapview-server-mem-types.h snapview-server-messages.h AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ -I$(top_srcdir)/api/src -I$(top_srcdir)/rpc/rpc-lib/src \ diff --git a/xlators/features/snapview-server/src/snapview-server-helpers.c b/xlators/features/snapview-server/src/snapview-server-helpers.c index 2559c4e089b..62c1ddac49c 100644 --- a/xlators/features/snapview-server/src/snapview-server-helpers.c +++ b/xlators/features/snapview-server/src/snapview-server-helpers.c @@ -10,7 +10,7 @@ #include "snapview-server.h" #include "snapview-server-mem-types.h" -#include "xlator.h" +#include <glusterfs/xlator.h> #include "rpc-clnt.h" #include "xdr-generic.h" #include "protocol-common.h" @@ -238,7 +238,7 @@ __svs_fd_ctx_get_or_new(xlator_t *this, fd_t *fd) svs_fd = svs_fd_new(); if (!svs_fd) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_NEW_FD_CTX_FAILED, "failed to allocate new fd " "context for gfid %s", uuid_utoa(inode->gfid)); @@ -248,7 +248,8 @@ __svs_fd_ctx_get_or_new(xlator_t *this, fd_t *fd) if (fd_is_anonymous(fd)) { inode_ctx = svs_inode_ctx_get(this, inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "failed to get inode " "context for %s", uuid_utoa(inode->gfid)); @@ -261,7 +262,7 @@ __svs_fd_ctx_get_or_new(xlator_t *this, fd_t *fd) if (inode->ia_type == IA_IFDIR) { glfd = glfs_h_opendir(fs, object); if (!glfd) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_OPENDIR_FAILED, "failed to " "open the directory %s", uuid_utoa(inode->gfid)); @@ -272,7 +273,7 @@ __svs_fd_ctx_get_or_new(xlator_t *this, fd_t *fd) if (inode->ia_type == IA_IFREG) { glfd = glfs_h_open(fs, object, O_RDONLY | O_LARGEFILE); if (!glfd) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_OPEN_FAILED, "failed to " "open the file %s", uuid_utoa(inode->gfid)); @@ -285,7 +286,7 @@ __svs_fd_ctx_get_or_new(xlator_t *this, fd_t *fd) ret = __svs_fd_ctx_set(this, fd, svs_fd); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_SET_FD_CONTEXT_FAILED, "failed to set fd context " "for gfid %s", uuid_utoa(inode->gfid)); @@ -293,14 +294,15 @@ __svs_fd_ctx_get_or_new(xlator_t *this, fd_t *fd) if (inode->ia_type == IA_IFDIR) { ret = glfs_closedir(svs_fd->fd); if (ret) - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, errno, + SVS_MSG_CLOSEDIR_FAILED, "failed to close the fd for %s", uuid_utoa(inode->gfid)); } if (inode->ia_type == IA_IFREG) { ret = glfs_close(svs_fd->fd); if (ret) - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_CLOSE_FAILED, "failed to close the fd for %s", uuid_utoa(inode->gfid)); } @@ -352,7 +354,7 @@ svs_uuid_generate(xlator_t *this, uuid_t gfid, char *snapname, uuid_utoa(origin_gfid)); if (gf_gfid_generate_from_xxh64(tmp, ino_string)) { - gf_log(this->name, GF_LOG_WARNING, + gf_msg(this->name, GF_LOG_WARNING, 0, SVS_MSG_GFID_GEN_FAILED, "failed to generate " "gfid for object with actual gfid of %s " "(snapname: %s, key: %s)", @@ -364,7 +366,7 @@ svs_uuid_generate(xlator_t *this, uuid_t gfid, char *snapname, ret = 0; - gf_log(this->name, GF_LOG_DEBUG, "gfid generated is %s ", uuid_utoa(gfid)); + gf_msg_debug(this->name, 0, "gfid generated is %s ", uuid_utoa(gfid)); out: return ret; @@ -474,6 +476,7 @@ __svs_initialise_snapshot_volume(xlator_t *this, const char *name, char logfile[PATH_MAX] = { 0, }; + char *volfile_server = NULL; GF_VALIDATE_OR_GOTO("snapview-server", this, out); GF_VALIDATE_OR_GOTO(this->name, this->private, out); @@ -483,10 +486,10 @@ __svs_initialise_snapshot_volume(xlator_t *this, const char *name, dirent = __svs_get_snap_dirent(this, name); if (!dirent) { - gf_log(this->name, GF_LOG_DEBUG, - "snap entry for " - "name %s not found", - name); + gf_msg_debug(this->name, 0, + "snap entry for " + "name %s not found", + name); local_errno = ENOENT; goto out; } @@ -502,21 +505,58 @@ __svs_initialise_snapshot_volume(xlator_t *this, const char *name, fs = glfs_new(volname); if (!fs) { - gf_log(this->name, GF_LOG_ERROR, + local_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, local_errno, SVS_MSG_GLFS_NEW_FAILED, "glfs instance for snap volume %s " "failed", dirent->name); - local_errno = ENOMEM; goto out; } - ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); + /* + * Before, localhost was used as the volfile server. But, with that + * method, accessing snapshots started giving ENOENT error if a + * specific bind address is mentioned in the glusterd volume file. + * Check the bug https://bugzilla.redhat.com/show_bug.cgi?id=1725211. + * So, the new method is tried below, where, snapview-server first + * uses the volfile server used by the snapd (obtained from the + * command line arguments saved in the global context of the process). + * If the volfile server in global context is NULL, then localhost + * is tried (like before). + */ + if (this->ctx->cmd_args.volfile_server) { + volfile_server = gf_strdup(this->ctx->cmd_args.volfile_server); + if (!volfile_server) { + gf_msg(this->name, GF_LOG_WARNING, ENOMEM, + SVS_MSG_VOLFILE_SERVER_GET_FAIL, + "failed to copy volfile server %s. ", + this->ctx->cmd_args.volfile_server); + ret = -1; + goto out; + } + } else { + gf_msg(this->name, GF_LOG_WARNING, ENOMEM, + SVS_MSG_VOLFILE_SERVER_GET_FAIL, + "volfile server is NULL in cmd args. " + "Trying with localhost"); + volfile_server = gf_strdup("localhost"); + if (!volfile_server) { + gf_msg(this->name, GF_LOG_WARNING, ENOMEM, + SVS_MSG_VOLFILE_SERVER_GET_FAIL, + "failed to copy volfile server localhost."); + ret = -1; + goto out; + } + } + + ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 24007); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, local_errno, + SVS_MSG_SET_VOLFILE_SERVR_FAILED, "setting the " - "volfile server for snap volume %s " + "volfile server %s for snap volume %s " "failed", - dirent->name); + volfile_server, dirent->name); goto out; } @@ -526,7 +566,8 @@ __svs_initialise_snapshot_volume(xlator_t *this, const char *name, ret = glfs_set_logging(fs, logfile, loglevel); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, local_errno, + SVS_MSG_SET_LOGGING_FAILED, "failed to set the " "log file path"); goto out; @@ -534,7 +575,7 @@ __svs_initialise_snapshot_volume(xlator_t *this, const char *name, ret = glfs_init(fs); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, local_errno, SVS_MSG_GLFS_INIT_FAILED, "initing the " "fs for %s failed", dirent->name); @@ -557,6 +598,7 @@ out: dirent->fs = fs; } + GF_FREE(volfile_server); return fs; } @@ -659,7 +701,7 @@ svs_inode_glfs_mapping(xlator_t *this, inode_t *inode) inode_ctx = svs_inode_ctx_get(this, inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_GET_INODE_CONTEXT_FAILED, "inode context not found for" " the inode %s", uuid_utoa(inode->gfid)); diff --git a/xlators/features/snapview-server/src/snapview-server-mem-types.h b/xlators/features/snapview-server/src/snapview-server-mem-types.h index 504c7969bdc..63456b85323 100644 --- a/xlators/features/snapview-server/src/snapview-server-mem-types.h +++ b/xlators/features/snapview-server/src/snapview-server-mem-types.h @@ -11,7 +11,7 @@ #ifndef __SNAP_VIEW_MEM_TYPES_H #define __SNAP_VIEW_MEM_TYPES_H -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum snapview_mem_types { gf_svs_mt_priv_t = gf_common_mt_end + 1, diff --git a/xlators/features/snapview-server/src/snapview-server-messages.h b/xlators/features/snapview-server/src/snapview-server-messages.h new file mode 100644 index 00000000000..f634ab5d2b0 --- /dev/null +++ b/xlators/features/snapview-server/src/snapview-server-messages.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2018 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. + */ + +#ifndef _SNAPVIEW_SERVER_MESSAGES_H_ +#define _SNAPVIEW_SERVER_MESSAGES_H_ + +#include <glusterfs/glfs-message-id.h> + +/* To add new message IDs, append new identifiers at the end of the list. + * + * Never remove a message ID. If it's not used anymore, you can rename it or + * leave it as it is, but not delete it. This is to prevent reutilization of + * IDs by other messages. + * + * The component name must match one of the entries defined in + * glfs-message-id.h. + */ + +GLFS_MSGID(SNAPVIEW_SERVER, SVS_MSG_NO_MEMORY, SVS_MSG_MEM_ACNT_FAILED, + SVS_MSG_NULL_GFID, SVS_MSG_GET_LATEST_SNAP_FAILED, + SVS_MSG_INVALID_GLFS_CTX, SVS_MSG_LOCK_DESTROY_FAILED, + SVS_MSG_SNAPSHOT_LIST_CHANGED, SVS_MSG_MGMT_INIT_FAILED, + SVS_MSG_GET_SNAPSHOT_LIST_FAILED, SVS_MSG_GET_GLFS_H_OBJECT_FAILED, + SVS_MSG_PARENT_CTX_OR_NAME_NULL, SVS_MSG_SET_INODE_CONTEXT_FAILED, + SVS_MSG_GET_INODE_CONTEXT_FAILED, SVS_MSG_NEW_INODE_CTX_FAILED, + SVS_MSG_DELETE_INODE_CONTEXT_FAILED, SVS_MSG_SET_FD_CONTEXT_FAILED, + SVS_MSG_NEW_FD_CTX_FAILED, SVS_MSG_DELETE_FD_CTX_FAILED, + SVS_MSG_GETXATTR_FAILED, SVS_MSG_LISTXATTR_FAILED, + SVS_MSG_RELEASEDIR_FAILED, SVS_MSG_RELEASE_FAILED, + SVS_MSG_TELLDIR_FAILED, SVS_MSG_STAT_FAILED, SVS_MSG_STATFS_FAILED, + SVS_MSG_OPEN_FAILED, SVS_MSG_READ_FAILED, SVS_MSG_READLINK_FAILED, + SVS_MSG_ACCESS_FAILED, SVS_MSG_GET_FD_CONTEXT_FAILED, + SVS_MSG_DICT_SET_FAILED, SVS_MSG_OPENDIR_FAILED, + SVS_MSG_FS_INSTANCE_INVALID, SVS_MSG_SETFSUID_FAIL, + SVS_MSG_SETFSGID_FAIL, SVS_MSG_SETFSGRPS_FAIL, + SVS_MSG_BUILD_TRNSPRT_OPT_FAILED, SVS_MSG_RPC_INIT_FAILED, + SVS_MSG_REG_NOTIFY_FAILED, SVS_MSG_REG_CBK_PRGM_FAILED, + SVS_MSG_RPC_CLNT_START_FAILED, SVS_MSG_XDR_PAYLOAD_FAILED, + SVS_MSG_NULL_CTX, SVS_MSG_RPC_CALL_FAILED, SVS_MSG_XDR_DECODE_FAILED, + SVS_MSG_RSP_DICT_EMPTY, SVS_MSG_DICT_GET_FAILED, + SVS_MSG_SNAP_LIST_REFRESH_FAILED, SVS_MSG_RPC_REQ_FAILED, + SVS_MSG_CLOSEDIR_FAILED, SVS_MSG_CLOSE_FAILED, + SVS_MSG_GFID_GEN_FAILED, SVS_MSG_GLFS_NEW_FAILED, + SVS_MSG_SET_VOLFILE_SERVR_FAILED, SVS_MSG_SET_LOGGING_FAILED, + SVS_MSG_VOLFILE_SERVER_GET_FAIL, SVS_MSG_GLFS_INIT_FAILED); + +#endif /* !_SNAPVIEW_CLIENT_MESSAGES_H_ */ diff --git a/xlators/features/snapview-server/src/snapview-server-mgmt.c b/xlators/features/snapview-server/src/snapview-server-mgmt.c index aff00221032..ecf31c3b880 100644 --- a/xlators/features/snapview-server/src/snapview-server-mgmt.c +++ b/xlators/features/snapview-server/src/snapview-server-mgmt.c @@ -19,17 +19,18 @@ mgmt_cbk_snap(struct rpc_clnt *rpc, void *mydata, void *data) this = mydata; GF_ASSERT(this); - gf_log("mgmt", GF_LOG_INFO, "list of snapshots changed"); + gf_msg("mgmt", GF_LOG_INFO, 0, SVS_MSG_SNAPSHOT_LIST_CHANGED, + "list of snapshots changed"); svs_get_snapshot_list(this); return 0; } -rpcclnt_cb_actor_t svs_cbk_actors[GF_CBK_MAXVALUE] = { - [GF_CBK_GET_SNAPS] = {"GETSNAPS", GF_CBK_GET_SNAPS, mgmt_cbk_snap}, +static rpcclnt_cb_actor_t svs_cbk_actors[GF_CBK_MAXVALUE] = { + [GF_CBK_GET_SNAPS] = {"GETSNAPS", mgmt_cbk_snap, GF_CBK_GET_SNAPS}, }; -struct rpcclnt_cb_program svs_cbk_prog = { +static struct rpcclnt_cb_program svs_cbk_prog = { .progname = "GlusterFS Callback", .prognum = GLUSTER_CBK_PROGRAM, .progver = GLUSTER_CBK_VERSION, @@ -37,12 +38,12 @@ struct rpcclnt_cb_program svs_cbk_prog = { .numactors = GF_CBK_MAXVALUE, }; -char *clnt_handshake_procs[GF_HNDSK_MAXVALUE] = { +static char *clnt_handshake_procs[GF_HNDSK_MAXVALUE] = { [GF_HNDSK_NULL] = "NULL", [GF_HNDSK_EVENT_NOTIFY] = "EVENTNOTIFY", }; -rpc_clnt_prog_t svs_clnt_handshake_prog = { +static rpc_clnt_prog_t svs_clnt_handshake_prog = { .progname = "GlusterFS Handshake", .prognum = GLUSTER_HNDSK_PROGRAM, .progver = GLUSTER_HNDSK_VERSION, @@ -62,7 +63,8 @@ svs_rpc_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, case RPC_CLNT_CONNECT: ret = svs_get_snapshot_list(this); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, EINVAL, + SVS_MSG_GET_SNAPSHOT_LIST_FAILED, "Error in refreshing the snaplist " "infrastructure"); ret = -1; @@ -84,6 +86,7 @@ svs_mgmt_init(xlator_t *this) char *host = NULL; cmd_args_t *cmd_args = NULL; glusterfs_ctx_t *ctx = NULL; + xlator_cmdline_option_t *opt = NULL; GF_VALIDATE_OR_GOTO("snapview-server", this, out); GF_VALIDATE_OR_GOTO(this->name, this->private, out); @@ -98,9 +101,15 @@ svs_mgmt_init(xlator_t *this) if (cmd_args->volfile_server) host = cmd_args->volfile_server; - ret = rpc_transport_inet_options_build(&options, host, port); + options = dict_new(); + if (!options) + goto out; + + opt = find_xlator_option_in_cmd_args_t("address-family", cmd_args); + ret = rpc_transport_inet_options_build(options, host, port, + (opt != NULL ? opt->value : NULL)); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_BUILD_TRNSPRT_OPT_FAILED, "failed to build the " "transport options"); goto out; @@ -108,26 +117,28 @@ svs_mgmt_init(xlator_t *this) priv->rpc = rpc_clnt_new(options, this, this->name, 8); if (!priv->rpc) { - gf_log(this->name, GF_LOG_ERROR, "failed to initialize RPC"); + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_RPC_INIT_FAILED, + "failed to initialize RPC"); goto out; } ret = rpc_clnt_register_notify(priv->rpc, svs_rpc_notify, this); if (ret) { - gf_log(this->name, GF_LOG_WARNING, + gf_msg(this->name, GF_LOG_WARNING, 0, SVS_MSG_REG_NOTIFY_FAILED, "failed to register notify function"); goto out; } ret = rpcclnt_cbk_program_register(priv->rpc, &svs_cbk_prog, this); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "failed to register callback program"); + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_REG_CBK_PRGM_FAILED, + "failed to register callback program"); goto out; } ret = rpc_clnt_start(priv->rpc); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_RPC_CLNT_START_FAILED, "failed to start the rpc " "client"); goto out; @@ -135,9 +146,11 @@ svs_mgmt_init(xlator_t *this) ret = 0; - gf_log(this->name, GF_LOG_DEBUG, "svs mgmt init successful"); + gf_msg_debug(this->name, 0, "svs mgmt init successful"); out: + if (options) + dict_unref(options); if (ret) if (priv) { rpc_clnt_connection_cleanup(&priv->rpc->conn); @@ -171,6 +184,9 @@ svs_mgmt_submit_request(void *req, call_frame_t *frame, glusterfs_ctx_t *ctx, iobref = iobref_new(); if (!iobref) { + gf_msg(frame->this->name, GF_LOG_WARNING, ENOMEM, SVS_MSG_NO_MEMORY, + "failed to allocate " + "new iobref"); goto out; } @@ -190,8 +206,8 @@ svs_mgmt_submit_request(void *req, call_frame_t *frame, glusterfs_ctx_t *ctx, /* Create the xdr payload */ ret = xdr_serialize_generic(iov, req, xdrproc); if (ret == -1) { - gf_log(frame->this->name, GF_LOG_WARNING, - "Failed to create XDR payload"); + gf_msg(frame->this->name, GF_LOG_WARNING, 0, + SVS_MSG_XDR_PAYLOAD_FAILED, "Failed to create XDR payload"); goto out; } iov.iov_len = ret; @@ -221,7 +237,8 @@ mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count, glusterfs_ctx_t *ctx = NULL; int ret = -1; dict_t *dict = NULL; - char key[1024] = {0}; + char key[32] = {0}; + int len; int snapcount = 0; svs_private_t *priv = NULL; xlator_t *this = NULL; @@ -240,23 +257,24 @@ mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count, this = frame->this; ctx = frame->this->ctx; priv = this->private; - old_dirents = priv->dirents; if (!ctx) { - gf_log(frame->this->name, GF_LOG_ERROR, "NULL context"); errno = EINVAL; + gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_NULL_CTX, + "NULL context"); goto out; } if (-1 == req->rpc_status) { - gf_log(frame->this->name, GF_LOG_ERROR, "RPC call is not successful"); errno = EINVAL; + gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_RPC_CALL_FAILED, + "RPC call is not successful"); goto out; } ret = xdr_to_generic(*iov, &rsp, (xdrproc_t)xdr_gf_getsnap_name_uuid_rsp); if (ret < 0) { - gf_log(frame->this->name, GF_LOG_ERROR, + gf_msg(frame->this->name, GF_LOG_ERROR, 0, SVS_MSG_XDR_DECODE_FAILED, "Failed to decode xdr response, rsp.op_ret = %d", rsp.op_ret); goto out; } @@ -268,10 +286,10 @@ mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count, } if (!rsp.dict.dict_len) { - gf_log(frame->this->name, GF_LOG_ERROR, - "Response dict is not populated"); ret = -1; errno = EINVAL; + gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_RSP_DICT_EMPTY, + "Response dict is not populated"); goto out; } @@ -284,17 +302,18 @@ mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count, ret = dict_unserialize(rsp.dict.dict_val, rsp.dict.dict_len, &dict); if (ret) { - gf_log(frame->this->name, GF_LOG_ERROR, - "Failed to unserialize dictionary"); errno = EINVAL; + gf_msg(frame->this->name, GF_LOG_ERROR, errno, + LG_MSG_DICT_UNSERIAL_FAILED, "Failed to unserialize dictionary"); goto out; } ret = dict_get_int32(dict, "snap-count", (int32_t *)&snapcount); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Error retrieving snapcount"); errno = EINVAL; ret = -1; + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED, + "Error retrieving snapcount"); goto out; } @@ -303,46 +322,46 @@ mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count, dirents = GF_CALLOC(snapcount, sizeof(snap_dirent_t), gf_svs_mt_dirents_t); if (!dirents) { - gf_log(frame->this->name, GF_LOG_ERROR, - "Unable to allocate memory"); errno = ENOMEM; ret = -1; + gf_msg(frame->this->name, GF_LOG_ERROR, errno, SVS_MSG_NO_MEMORY, + "Unable to allocate memory"); goto out; } } for (i = 0; i < snapcount; i++) { - snprintf(key, sizeof(key), "snap-volname.%d", i + 1); - ret = dict_get_str(dict, key, &value); + len = snprintf(key, sizeof(key), "snap-volname.%d", i + 1); + ret = dict_get_strn(dict, key, len, &value); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Error retrieving snap volname %d", - i + 1); errno = EINVAL; ret = -1; + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED, + "Error retrieving snap volname %d", i + 1); goto out; } strncpy(dirents[i].snap_volname, value, sizeof(dirents[i].snap_volname)); - snprintf(key, sizeof(key), "snap-id.%d", i + 1); - ret = dict_get_str(dict, key, &value); + len = snprintf(key, sizeof(key), "snap-id.%d", i + 1); + ret = dict_get_strn(dict, key, len, &value); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Error retrieving snap uuid %d", - i + 1); errno = EINVAL; ret = -1; + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED, + "Error retrieving snap uuid %d", i + 1); goto out; } strncpy(dirents[i].uuid, value, sizeof(dirents[i].uuid)); - snprintf(key, sizeof(key), "snapname.%d", i + 1); - ret = dict_get_str(dict, key, &value); + len = snprintf(key, sizeof(key), "snapname.%d", i + 1); + ret = dict_get_strn(dict, key, len, &value); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Error retrieving snap name %d", - i + 1); errno = EINVAL; ret = -1; + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_DICT_GET_FAILED, + "Error retrieving snap name %d", i + 1); goto out; } strncpy(dirents[i].name, value, sizeof(dirents[i].name)); @@ -369,6 +388,7 @@ mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count, LOCK(&priv->snaplist_lock); { oldcount = priv->num_snaps; + old_dirents = priv->dirents; for (i = 0; i < priv->num_snaps; i++) { for (j = 0; j < snapcount; j++) { if ((!strcmp(old_dirents[i].name, dirents[j].name)) && @@ -388,7 +408,12 @@ mgmt_get_snapinfo_cbk(struct rpc_req *req, struct iovec *iov, int count, if (old_dirents) { for (i = 0; i < oldcount; i++) { if (old_dirents[i].fs) - glfs_fini(old_dirents[i].fs); + gf_msg_debug(this->name, 0, + "calling glfs_fini on " + "name: %s, snap_volname: %s, uuid: %s", + old_dirents[i].name, old_dirents[i].snap_volname, + old_dirents[i].uuid); + glfs_fini(old_dirents[i].fs); } } @@ -404,7 +429,7 @@ out: free(rsp.op_errstr); if (ret && dirents) { - gf_log(this->name, GF_LOG_WARNING, + gf_msg(this->name, GF_LOG_WARNING, 0, SVS_MSG_SNAP_LIST_REFRESH_FAILED, "Could not update dirents with refreshed snap list"); GF_FREE(dirents); } @@ -433,13 +458,14 @@ svs_get_snapshot_list(xlator_t *this) ctx = this->ctx; if (!ctx) { - gf_log(this->name, GF_LOG_ERROR, "ctx is NULL"); + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_NULL_CTX, "ctx is NULL"); goto out; } frame = create_frame(this, ctx->pool); if (!frame) { - gf_log(this->name, GF_LOG_ERROR, "Error allocating frame"); + gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_FRAME_ERROR, + "Error allocating frame"); goto out; } @@ -447,20 +473,23 @@ svs_get_snapshot_list(xlator_t *this) dict = dict_new(); if (!dict) { - gf_log(this->name, GF_LOG_ERROR, "Error allocating dictionary"); + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, SVS_MSG_NO_MEMORY, + "Error allocating dictionary"); goto out; } ret = dict_set_str(dict, "volname", priv->volname); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Error setting volname in dict"); + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_DICT_SET_FAILED, + "Error setting volname in dict"); goto out; } ret = dict_allocate_and_serialize(dict, &req.dict.dict_val, &req.dict.dict_len); if (ret) { - gf_log(this->name, GF_LOG_ERROR, "Failed to serialize dictionary"); + gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_UNSERIAL_FAILED, + "Failed to serialize dictionary"); ret = -1; goto out; } @@ -470,7 +499,7 @@ svs_get_snapshot_list(xlator_t *this) mgmt_get_snapinfo_cbk, (xdrproc_t)xdr_gf_getsnap_name_uuid_req); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_RPC_REQ_FAILED, "Error sending snapshot names RPC request"); } diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c index 266a02c8c60..76cccae5914 100644 --- a/xlators/features/snapview-server/src/snapview-server.c +++ b/xlators/features/snapview-server/src/snapview-server.c @@ -9,15 +9,17 @@ */ #include "snapview-server.h" #include "snapview-server-mem-types.h" -#include "compat-errno.h" +#include <glusterfs/compat-errno.h> -#include "xlator.h" +#include <glusterfs/xlator.h> #include "rpc-clnt.h" #include "xdr-generic.h" #include "protocol-common.h" -#include "syscall.h" +#include <glusterfs/syscall.h> #include <pthread.h> +#include "glfs-internal.h" + int gf_setcredentials(uid_t *uid, gid_t *gid, uint16_t ngrps, uint32_t *groups) { @@ -26,7 +28,7 @@ gf_setcredentials(uid_t *uid, gid_t *gid, uint16_t ngrps, uint32_t *groups) if (uid) { ret = glfs_setfsuid(*uid); if (ret != 0) { - gf_log("snapview-server", GF_LOG_ERROR, + gf_msg("snapview-server", GF_LOG_ERROR, 0, SVS_MSG_SETFSUID_FAIL, "failed to set uid " "%u in thread context", *uid); @@ -36,7 +38,7 @@ gf_setcredentials(uid_t *uid, gid_t *gid, uint16_t ngrps, uint32_t *groups) if (gid) { ret = glfs_setfsgid(*gid); if (ret != 0) { - gf_log("snapview-server", GF_LOG_ERROR, + gf_msg("snapview-server", GF_LOG_ERROR, 0, SVS_MSG_SETFSGID_FAIL, "failed to set gid " "%u in thread context", *gid); @@ -47,7 +49,7 @@ gf_setcredentials(uid_t *uid, gid_t *gid, uint16_t ngrps, uint32_t *groups) if (ngrps != 0 && groups) { ret = glfs_setfsgroups(ngrps, groups); if (ret != 0) { - gf_log("snapview-server", GF_LOG_ERROR, + gf_msg("snapview-server", GF_LOG_ERROR, 0, SVS_MSG_SETFSGRPS_FAIL, "failed to set " "groups in thread context"); return ret; @@ -88,12 +90,13 @@ svs_lookup_entry_point(xlator_t *this, loc_t *loc, inode_t *parent, inode_ctx = svs_inode_ctx_get_or_new(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + *op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_NEW_INODE_CTX_FAILED, "failed to " "allocate inode context for entry point " "directory"); - op_ret = -1; - *op_errno = ENOMEM; goto out; } @@ -162,7 +165,7 @@ svs_lookup_gfid(xlator_t *this, loc_t *loc, struct iatt *buf, GF_VALIDATE_OR_GOTO(this->name, postparent, out); if (gf_uuid_is_null(loc->gfid) && gf_uuid_is_null(loc->inode->gfid)) { - gf_log(this->name, GF_LOG_ERROR, "gfid is NULL"); + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_NULL_GFID, "gfid is NULL"); goto out; } @@ -173,33 +176,36 @@ svs_lookup_gfid(xlator_t *this, loc_t *loc, struct iatt *buf, fs = svs_get_latest_snapshot(this); if (!fs) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the latest " - "snapshot"); op_ret = -1; *op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_GET_LATEST_SNAP_FAILED, + "failed to get the latest " + "snapshot"); goto out; } object = glfs_h_create_from_handle(fs, handle_obj, GFAPI_HANDLE_LENGTH, &statbuf); if (!object) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + *op_errno = ESTALE; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_GET_GLFS_H_OBJECT_FAILED, "failed to do lookup and get " "the handle on the snapshot %s (path: %s, gfid: %s)", loc->name, loc->path, uuid_utoa(loc->gfid)); - op_ret = -1; - *op_errno = ESTALE; goto out; } inode_ctx = svs_inode_ctx_get_or_new(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "failed to allocate inode " - "context"); op_ret = -1; *op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_NEW_INODE_CTX_FAILED, + "failed to allocate inode " + "context"); goto out; } @@ -255,10 +261,10 @@ svs_lookup_snapshot(xlator_t *this, loc_t *loc, struct iatt *buf, fs = svs_initialise_snapshot_volume(this, loc->name, op_errno); if (!fs) { - gf_log(this->name, GF_LOG_DEBUG, - "failed to " - "create the fs instance for snap %s", - loc->name); + gf_msg_debug(this->name, 0, + "failed to create " + "the fs instance for snap %s", + loc->name); *op_errno = ENOENT; op_ret = -1; goto out; @@ -268,22 +274,24 @@ svs_lookup_snapshot(xlator_t *this, loc_t *loc, struct iatt *buf, object = glfs_h_create_from_handle(fs, handle_obj, GFAPI_HANDLE_LENGTH, &statbuf); if (!object) { - gf_log(this->name, GF_LOG_DEBUG, - "failed to do lookup and " - "get the handle on the snapshot %s", - loc->name); op_ret = -1; *op_errno = errno; + /* Should this be in warning or error mode? */ + gf_msg_debug(this->name, 0, + "failed to do lookup and " + "get the handle on the snapshot %s", + loc->name); goto out; } inode_ctx = svs_inode_ctx_get_or_new(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate inode context"); op_ret = -1; *op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_NEW_INODE_CTX_FAILED, + "failed to allocate " + "inode context"); goto out; } @@ -355,20 +363,22 @@ svs_lookup_entry(xlator_t *this, loc_t *loc, struct iatt *buf, object = glfs_h_lookupat(fs, parent_object, loc->name, &statbuf, 0); if (!object) { - gf_log(this->name, GF_LOG_DEBUG, - "failed to do lookup and " - "get the handle for entry %s (path: %s)", - loc->name, loc->path); + /* should this be in WARNING or ERROR mode? */ + gf_msg_debug(this->name, 0, + "failed to do lookup and " + "get the handle for entry %s (path: %s)", + loc->name, loc->path); op_ret = -1; *op_errno = errno; goto out; } if (gf_uuid_is_null(object->gfid)) { - gf_log(this->name, GF_LOG_DEBUG, - "gfid from glfs handle is " - "NULL for entry %s (path: %s)", - loc->name, loc->path); + /* should this be in WARNING or ERROR mode? */ + gf_msg_debug(this->name, 0, + "gfid from glfs handle is " + "NULL for entry %s (path: %s)", + loc->name, loc->path); op_ret = -1; *op_errno = errno; goto out; @@ -376,11 +386,12 @@ svs_lookup_entry(xlator_t *this, loc_t *loc, struct iatt *buf, inode_ctx = svs_inode_ctx_get_or_new(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate inode context"); op_ret = -1; *op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_NEW_INODE_CTX_FAILED, + "failed to allocate " + "inode context"); goto out; } @@ -521,7 +532,8 @@ svs_revalidate(xlator_t *this, loc_t *loc, inode_t *parent, inode_ctx->object = NULL; ret = svs_get_handle(this, loc, inode_ctx, op_errno); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_GET_GLFS_H_OBJECT_FAILED, "failed to get the handle for " "%s (gfid %s)", loc->path, uuid_utoa_r(loc->inode->gfid, tmp_uuid)); @@ -536,7 +548,8 @@ svs_revalidate(xlator_t *this, loc_t *loc, inode_t *parent, */ if (!loc->name || !parent_ctx) { *op_errno = ESTALE; - gf_log(this->name, GF_LOG_ERROR, "%s is NULL", + gf_msg(this->name, GF_LOG_ERROR, *op_errno, + SVS_MSG_PARENT_CTX_OR_NAME_NULL, "%s is NULL", loc->name ? "parent context" : "loc->name"); goto out; } @@ -577,7 +590,6 @@ svs_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) GF_VALIDATE_OR_GOTO("svs", this, out); GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); @@ -621,9 +633,9 @@ svs_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) if (xdata && !inode_ctx) { ret = dict_get_str_boolean(xdata, "entry-point", _gf_false); if (ret == -1) { - gf_log(this->name, GF_LOG_DEBUG, - "failed to get the " - "entry point info"); + gf_msg_debug(this->name, 0, + "failed to get the " + "entry point info"); entry_point_key = _gf_false; } else { entry_point_key = ret; @@ -668,12 +680,12 @@ svs_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) */ if (!inode_ctx && !parent_ctx) { if (gf_uuid_is_null(loc->gfid) && gf_uuid_is_null(loc->inode->gfid)) { - gf_log(this->name, GF_LOG_DEBUG, - "gfid is NULL, " - "either the lookup came on missing entry or " - "the entry is stale"); op_ret = -1; op_errno = ESTALE; + gf_msg_debug(this->name, 0, + "gfid is NULL. Either the lookup " + "came on missing entry or the " + "entry is stale"); goto out; } @@ -738,7 +750,6 @@ svs_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, fd, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); @@ -752,12 +763,13 @@ svs_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, inode_ctx = svs_inode_ctx_get(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = ESTALE; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "inode context not found " "for the inode %s", uuid_utoa(loc->inode->gfid)); - op_ret = -1; - op_errno = ESTALE; goto out; } @@ -776,20 +788,21 @@ svs_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, if (!glfd) { op_ret = -1; op_errno = errno; - gf_log(this->name, GF_LOG_ERROR, - "opendir on %s " - "failed (gfid: %s)", + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_OPENDIR_FAILED, + "opendir on %s failed " + "(gfid: %s)", loc->name, uuid_utoa(loc->inode->gfid)); goto out; } svs_fd = svs_fd_ctx_get_or_new(this, fd); if (!svs_fd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to allocate " - "fd context %s (gfid: %s)", - loc->name, uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_NEW_FD_CTX_FAILED, + "failed to allocate fd context " + "for %s (gfid: %s)", + loc->name, uuid_utoa(fd->inode->gfid)); glfs_closedir(glfd); goto out; } @@ -815,7 +828,8 @@ out: * back into the dict. But to get the values for those xattrs it has to do the * getxattr operation on each xattr which might turn out to be a costly * operation. So for each of the xattrs present in the list, a 0 byte value - * ("") is set into the dict before unwinding. This can be treated as an + * ("") is set into the dict before unwinding. Since ("") is also a valid xattr + * value(in a file system) we use an extra key in the same dictionary as an * indicator to other xlators which want to cache the xattrs (as of now, * md-cache which caches acl and selinux related xattrs) to not to cache the * values of the xattrs present in the dict. @@ -847,7 +861,7 @@ svs_add_xattrs_to_dict(xlator_t *this, dict_t *dict, char *list, ssize_t size) #endif ret = dict_set_str(dict, keybuffer, ""); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_DICT_SET_FAILED, "dict set operation " "for the key %s failed.", keybuffer); @@ -858,6 +872,15 @@ svs_add_xattrs_to_dict(xlator_t *this, dict_t *dict, char *list, ssize_t size) list_offset += strlen(keybuffer) + 1; } /* while (remaining_size > 0) */ + /* Add an additional key to indicate that we don't need to cache these + * xattrs(with value "") */ + ret = dict_set_str(dict, "glusterfs.skip-cache", ""); + if (ret < 0) { + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_DICT_SET_FAILED, + "dict set operation for the key glusterfs.skip-cache failed."); + goto out; + } + ret = 0; out: @@ -880,7 +903,6 @@ svs_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO("snap-view-daemon", frame, out); - GF_VALIDATE_OR_GOTO("snap-view-daemon", frame->root, out); GF_VALIDATE_OR_GOTO("snap-view-daemon", loc, out); GF_VALIDATE_OR_GOTO("snap-view-daemon", loc->inode, out); @@ -893,12 +915,13 @@ svs_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, inode_ctx = svs_inode_ctx_get(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = ESTALE; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "inode context not found " "for the inode %s", uuid_utoa(loc->inode->gfid)); - op_ret = -1; - op_errno = ESTALE; goto out; } @@ -918,43 +941,49 @@ svs_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict = dict_new(); if (!dict) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate dict"); op_ret = -1; op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, + "failed to allocate dict"); goto out; } size = glfs_h_getxattrs(fs, object, name, NULL, 0); if (size == -1) { - gf_log(this->name, errno == ENODATA ? GF_LOG_DEBUG : GF_LOG_ERROR, - "getxattr on %s failed (key: %s) with %s", loc->path, name, - strerror(errno)); op_ret = -1; op_errno = errno; + if (errno == ENODATA) { + gf_msg_debug(this->name, 0, + "getxattr on " + "%s failed (ket: %s) with %s", + loc->path, name, strerror(errno)); + } else { + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GETXATTR_FAILED, + "getxattr on %s failed (key: %s) with %s", loc->path, + name, strerror(errno)); + } goto out; } value = GF_CALLOC(size + 1, sizeof(char), gf_common_mt_char); if (!value) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate memory for getxattr on %s " - "(key: %s)", - loc->name, name); op_ret = -1; op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, + "failed to allocate memory for getxattr " + "on %s (key: %s)", + loc->name, name); goto out; } size = glfs_h_getxattrs(fs, object, name, value, size); if (size == -1) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "get the xattr %s for entry %s", - name, loc->name); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_GETXATTR_FAILED, + "failed to get the xattr %s for " + "entry %s", + name, loc->name); goto out; } value[size] = '\0'; @@ -963,10 +992,10 @@ svs_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, op_ret = dict_set_dynptr(dict, (char *)name, value, size); if (op_ret < 0) { op_errno = -op_ret; - gf_log(this->name, GF_LOG_ERROR, - "dict set " - "operation for %s for the key %s " - "failed.", + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_DICT_SET_FAILED, + "dict set operation for %s for " + "the key %s failed.", loc->path, name); GF_FREE(value); value = NULL; @@ -975,13 +1004,15 @@ svs_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, } else { op_ret = svs_add_xattrs_to_dict(this, dict, value, size); if (op_ret == -1) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "add the xattrs from the list to dict"); op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, + "failed to add xattrs from the list to " + "dict for %s (gfid: %s)", + loc->path, uuid_utoa(loc->inode->gfid)); goto out; } GF_FREE(value); + value = NULL; } } @@ -1017,35 +1048,37 @@ svs_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, inode_ctx = svs_inode_ctx_get(this, fd->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = ESTALE; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "inode context not found " "for the inode %s", uuid_utoa(fd->inode->gfid)); - op_ret = -1; - op_errno = ESTALE; goto out; } if (!(svs_inode_ctx_glfs_mapping(this, inode_ctx))) { - gf_log(this->name, GF_LOG_ERROR, - "glfs instance " - "instance %p to which the inode %s belongs" - "to does not exist. That snapshot might have" - "been deleted or deactivated", - inode_ctx->fs, uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EBADF; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_FS_INSTANCE_INVALID, + "glfs instance %p to which the inode %s " + "belongs to does not exist. The snapshot " + "corresponding to the instance might have" + "been deleted or deactivated", + inode_ctx->fs, uuid_utoa(fd->inode->gfid)); goto out; } sfd = svs_fd_ctx_get_or_new(this, fd); if (!sfd) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = EBADFD; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_FD_CONTEXT_FAILED, "failed to get the fd " "context for %s", uuid_utoa(fd->inode->gfid)); - op_ret = -1; - op_errno = EBADFD; goto out; } @@ -1063,45 +1096,48 @@ svs_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, } else { dict = dict_new(); if (!dict) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate dict"); op_ret = -1; op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, + "failed to allocate dict " + "(gfid: %s, key: %s)", + uuid_utoa(fd->inode->gfid), name); goto out; } if (name) { size = glfs_fgetxattr(glfd, name, NULL, 0); if (size == -1) { - gf_log(this->name, GF_LOG_ERROR, - "getxattr on " - "%s failed (key: %s)", - uuid_utoa(fd->inode->gfid), name); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GETXATTR_FAILED, + "getxattr on %s failed " + "(key: %s)", + uuid_utoa(fd->inode->gfid), name); goto out; } value = GF_CALLOC(size + 1, sizeof(char), gf_common_mt_char); if (!value) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, "failed to " "allocate memory for getxattr on %s " "(key: %s)", uuid_utoa(fd->inode->gfid), name); - op_ret = -1; - op_errno = ENOMEM; goto out; } size = glfs_fgetxattr(glfd, name, value, size); if (size == -1) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "get the xattr %s for inode %s", - name, uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GETXATTR_FAILED, + "failed to get the xattr %s " + "for inode %s", + name, uuid_utoa(fd->inode->gfid)); goto out; } value[size] = '\0'; @@ -1109,19 +1145,19 @@ svs_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, op_ret = dict_set_dynptr(dict, (char *)name, value, size); if (op_ret < 0) { op_errno = -op_ret; - gf_log(this->name, GF_LOG_ERROR, - "dict set " - "operation for gfid %s for the key %s " - "failed.", + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_DICT_SET_FAILED, + "dict set operation for gfid %s " + "for the key %s failed.", uuid_utoa(fd->inode->gfid), name); goto out; } } else { size = glfs_flistxattr(glfd, NULL, 0); if (size == -1) { - gf_log(this->name, GF_LOG_ERROR, - "listxattr " - "on %s failed", + op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_LISTXATTR_FAILED, "listxattr on %s failed", uuid_utoa(fd->inode->gfid)); goto out; } @@ -1130,9 +1166,10 @@ svs_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, if (!value) { op_ret = -1; op_errno = ENOMEM; - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, "failed to " - "allocate buffer for xattr list (%s)", + "allocate buffer for xattr " + "list (%s)", uuid_utoa(fd->inode->gfid)); goto out; } @@ -1141,19 +1178,19 @@ svs_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, if (size == -1) { op_ret = -1; op_errno = errno; - gf_log(this->name, GF_LOG_ERROR, - "listxattr " - "on %s failed", + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_LISTXATTR_FAILED, "listxattr on %s failed", uuid_utoa(fd->inode->gfid)); goto out; } op_ret = svs_add_xattrs_to_dict(this, dict, value, size); if (op_ret == -1) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "add the xattrs from the list to dict"); op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, + "failed to add xattrs from the list " + "to dict (gfid: %s)", + uuid_utoa(fd->inode->gfid)); goto out; } GF_FREE(value); @@ -1190,7 +1227,7 @@ svs_releasedir(xlator_t *this, fd_t *fd) ret = fd_ctx_del(fd, this, &tmp_pfd); if (ret < 0) { - gf_log(this->name, GF_LOG_DEBUG, "pfd from fd=%p is NULL", fd); + gf_msg_debug(this->name, 0, "pfd from fd=%p is NULL", fd); goto out; } @@ -1205,9 +1242,10 @@ svs_releasedir(xlator_t *this, fd_t *fd) if (sfd->fd) { ret = glfs_closedir(sfd->fd); if (ret) - gf_log(this->name, GF_LOG_WARNING, - "failed to close the glfd" - "for directory %s", + gf_msg(this->name, GF_LOG_WARNING, errno, + SVS_MSG_RELEASEDIR_FAILED, + "failed to close the glfd for " + "directory %s", uuid_utoa(fd->inode->gfid)); } } @@ -1231,7 +1269,6 @@ svs_flush(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) GF_VALIDATE_OR_GOTO("snapview-server", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, fd, out); root = frame->root; @@ -1243,19 +1280,21 @@ svs_flush(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) inode_ctx = svs_inode_ctx_get(this, fd->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "inode context not found for" " the inode %s", uuid_utoa(fd->inode->gfid)); - op_ret = -1; - op_errno = EINVAL; goto out; } ret = fd_ctx_get(fd, this, &value); if (ret < 0 && inode_ctx->type != SNAP_VIEW_ENTRY_POINT_INODE) { op_errno = EINVAL; - gf_log(this->name, GF_LOG_WARNING, "pfd is NULL on fd=%p", fd); + gf_msg(this->name, GF_LOG_WARNING, op_errno, + SVS_MSG_GET_FD_CONTEXT_FAILED, "pfd is NULL on fd=%p", fd); goto out; } @@ -1282,7 +1321,7 @@ svs_release(xlator_t *this, fd_t *fd) ret = fd_ctx_del(fd, this, &tmp_pfd); if (ret < 0) { - gf_log(this->name, GF_LOG_DEBUG, "pfd from fd=%p is NULL", fd); + gf_msg_debug(this->name, 0, "pfd from fd=%p is NULL", fd); goto out; } @@ -1297,7 +1336,8 @@ svs_release(xlator_t *this, fd_t *fd) if (sfd->fd) { ret = glfs_close(sfd->fd); if (ret) - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, errno, + SVS_MSG_RELEASE_FAILED, "failed to close " "the glfd for %s", uuid_utoa(fd->inode->gfid)); @@ -1322,20 +1362,42 @@ svs_forget(xlator_t *this, inode_t *inode) ret = inode_ctx_del(inode, this, &value); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_DELETE_INODE_CONTEXT_FAILED, "failed to delete the inode " "context of %s", uuid_utoa(inode->gfid)); goto out; } - inode_ctx = (svs_inode_t *)value; + inode_ctx = (svs_inode_t *)(uintptr_t)value; if (!inode_ctx) goto out; if (inode_ctx->snapname) GF_FREE(inode_ctx->snapname); + /* + * glfs_h_close leads to unref and forgetting of the + * underlying inode in the gfapi world. i.e. the inode + * which inode_ctx->object points to. + * As of now the only possibility is, this forget came as a + * result of snapdaemon's inode table reaching the lru + * limit and receiving forget as a result of purging of + * extra inodes that exceeded the limit. But, care must + * be taken to ensure that, the gfapi instance to which + * the glfs_h_object belongs to is not deleted. Otherwise + * this might result in access of a freed pointer. + * This will still be helpful in reducing the memory + * footprint of snapdaemon when the fs instance itself is + * valid (i.e. present and not destroyed due to either snap + * deactivate or snap delete), but the lru limit is reached. + * The forget due to lru limit will make the underlying inode + * being unrefed and forgotten. + */ + if (svs_inode_ctx_glfs_mapping(this, inode_ctx)) { + glfs_h_close(inode_ctx->object); + inode_ctx->object = NULL; + } GF_FREE(inode_ctx); out: @@ -1371,7 +1433,7 @@ svs_fill_readdir(xlator_t *this, gf_dirent_t *entries, size_t size, off_t off) entry = gf_dirent_for_name(dirents[i].name); if (!entry) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, SVS_MSG_NO_MEMORY, "failed to allocate dentry for %s", dirents[i].name); goto unlock; } @@ -1426,7 +1488,8 @@ svs_glfs_readdir(xlator_t *this, glfs_fd_t *glfd, gf_dirent_t *entries, while (filled_size < size) { in_case = glfs_telldir(glfd); if (in_case == -1) { - gf_log(this->name, GF_LOG_ERROR, "telldir failed"); + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_TELLDIR_FAILED, + "telldir failed"); break; } @@ -1449,7 +1512,14 @@ svs_glfs_readdir(xlator_t *this, glfs_fd_t *glfd, gf_dirent_t *entries, entry = gf_dirent_for_name(de.d_name); if (!entry) { - gf_log(this->name, GF_LOG_ERROR, + /* + * Since gf_dirent_for_name can return + * NULL only when it fails to allocate + * memory for the directory entry, + * SVS_MSG_NO_MEMORY is used as the + * message-id. + */ + gf_msg(this->name, GF_LOG_ERROR, errno, SVS_MSG_NO_MEMORY, "could not create gf_dirent " "for entry %s: (%s)", entry->d_name, strerror(errno)); @@ -1545,9 +1615,9 @@ svs_readdirp_fill(xlator_t *this, inode_t *parent, svs_inode_t *parent_ctx, */ inode_ctx = svs_inode_ctx_get_or_new(this, inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "failed to " - "allocate inode context for %s", + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, SVS_MSG_NO_MEMORY, + "failed to allocate inode " + "context for %s", entry->d_name); inode_unref(entry->inode); entry->inode = NULL; @@ -1611,7 +1681,6 @@ svs_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, GF_VALIDATE_OR_GOTO("snap-view-daemon", this, unwind); GF_VALIDATE_OR_GOTO(this->name, frame, unwind); - GF_VALIDATE_OR_GOTO(this->name, frame->root, unwind); GF_VALIDATE_OR_GOTO(this->name, fd, unwind); GF_VALIDATE_OR_GOTO(this->name, fd->inode, unwind); @@ -1626,12 +1695,13 @@ svs_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, parent_ctx = svs_inode_ctx_get(this, fd->inode); if (!parent_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "failed to get the inode " "context for %s", uuid_utoa(fd->inode->gfid)); - op_ret = -1; - op_errno = EINVAL; goto unwind; } @@ -1653,12 +1723,13 @@ svs_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, } else { svs_fd = svs_fd_ctx_get_or_new(this, fd); if (!svs_fd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the " - "fd context %s", - uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EBADFD; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_FD_CONTEXT_FAILED, + "failed to get the fd context " + "for the inode %s", + uuid_utoa(fd->inode->gfid)); goto unwind; } @@ -1716,12 +1787,13 @@ svs_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, inode_ctx = svs_inode_ctx_get(this, fd->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "inode context not found in " "the inode %s", uuid_utoa(fd->inode->gfid)); - op_ret = -1; - op_errno = EINVAL; goto unwind; } @@ -1734,12 +1806,13 @@ svs_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, } else { svs_fd = svs_fd_ctx_get_or_new(this, fd); if (!svs_fd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the " - "fd context %s", - uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EBADFD; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_FD_CONTEXT_FAILED, + "failed to get the fd " + "context for %s", + uuid_utoa(fd->inode->gfid)); goto unwind; } @@ -1854,11 +1927,12 @@ svs_get_handle(xlator_t *this, loc_t *loc, svs_inode_t *inode_ctx, parent_ctx = svs_inode_ctx_get(this, parent); if (!parent_ctx) { - gf_log(this->name, GF_LOG_WARNING, + *op_errno = EINVAL; + gf_msg(this->name, GF_LOG_WARNING, *op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "failed to get the parent " "context for %s (%s)", loc->path, uuid_utoa_r(loc->inode->gfid, uuid1)); - *op_errno = EINVAL; goto out; } @@ -1897,7 +1971,6 @@ svs_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); @@ -1915,12 +1988,11 @@ svs_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) inode_ctx = svs_inode_ctx_get(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "inode context not found for" - " %s", - uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, + "inode context not found for %s", uuid_utoa(loc->inode->gfid)); goto out; } @@ -1933,14 +2005,16 @@ svs_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) ret = glfs_h_stat(fs, object, &stat); if (ret) { - gf_log(this->name, GF_LOG_ERROR, - "glfs_h_stat on %s " - "(gfid: %s) failed", - loc->name, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_STAT_FAILED, + "glfs_h_stat on %s (gfid: %s) " + "failed", + loc->name, uuid_utoa(loc->inode->gfid)); goto out; - } + } else + gf_msg_debug(this->name, 0, "stat on %s (%s) successful", loc->path, + uuid_utoa(loc->inode->gfid)); iatt_from_stat(&buf, &stat); gf_uuid_copy(buf.ia_gfid, loc->inode->gfid); @@ -1972,7 +2046,6 @@ svs_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, fd, out); GF_VALIDATE_OR_GOTO(this->name, fd->inode, out); @@ -1990,12 +2063,13 @@ svs_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) inode_ctx = svs_inode_ctx_get(this, fd->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "inode context not found for" " the inode %s", uuid_utoa(fd->inode->gfid)); - op_ret = -1; - op_errno = EINVAL; goto out; } @@ -2004,37 +2078,37 @@ svs_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) op_ret = 0; } else { if (!(svs_inode_ctx_glfs_mapping(this, inode_ctx))) { - gf_log(this->name, GF_LOG_ERROR, - "glfs instance " - "instance %p to which the inode %s belongs " - "to does not exist. That snapshot might have " - "been deleted or deactivated", - inode_ctx->fs, uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EBADF; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_FS_INSTANCE_INVALID, + "glfs instance %p to which the inode %s " + "belongs to does not exist. That snapshot " + "corresponding to the fs instance " + "might have been deleted or deactivated.", + inode_ctx->fs, uuid_utoa(fd->inode->gfid)); goto out; } sfd = svs_fd_ctx_get_or_new(this, fd); if (!sfd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to get the " - "fd context for %s", - uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EBADFD; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_FD_CONTEXT_FAILED, + "failed to get the fd context " + "for %s", + uuid_utoa(fd->inode->gfid)); goto out; } glfd = sfd->fd; ret = glfs_fstat(glfd, &stat); if (ret) { - gf_log(this->name, GF_LOG_ERROR, - "glfs_fstat on " - "gfid: %s failed", - uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_STAT_FAILED, + "glfs_fstat on gfid: %s failed", uuid_utoa(fd->inode->gfid)); goto out; } @@ -2065,7 +2139,6 @@ svs_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); @@ -2082,12 +2155,11 @@ svs_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) */ inode_ctx = svs_inode_ctx_get(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "inode context not found for" - " %s", - uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, + "inode context not found for %s", uuid_utoa(loc->inode->gfid)); goto out; } @@ -2096,12 +2168,12 @@ svs_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) ret = glfs_h_statfs(fs, object, &buf); if (ret) { - gf_log(this->name, GF_LOG_ERROR, - "glfs_h_statvfs on %s " - "(gfid: %s) failed", - loc->name, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_STATFS_FAILED, + "glfs_h_statvfs on %s (gfid: %s) " + "failed", + loc->name, uuid_utoa(loc->inode->gfid)); goto out; } op_ret = ret; @@ -2126,7 +2198,6 @@ svs_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, fd, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); @@ -2135,9 +2206,10 @@ svs_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, inode_ctx = svs_inode_ctx_get(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "inode context for %s " - "(gfid: %s) not found", + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, + "inode context for %s (gfid: %s) " + "not found", loc->name, uuid_utoa(loc->inode->gfid)); goto out; } @@ -2156,23 +2228,22 @@ svs_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, glfd = glfs_h_open(fs, object, flags); if (!glfd) { - gf_log(this->name, GF_LOG_ERROR, - "glfs_h_open on %s failed " - "(gfid: %s)", - loc->name, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_OPEN_FAILED, + "glfs_h_open on %s failed (gfid: %s)", loc->name, + uuid_utoa(loc->inode->gfid)); goto out; } sfd = svs_fd_ctx_get_or_new(this, fd); if (!sfd) { - gf_log(this->name, GF_LOG_ERROR, - "failed to allocate fd " - "context for %s (gfid: %s)", - loc->name, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, + "failed to allocate fd context " + "for %s (gfid: %s)", + loc->name, uuid_utoa(loc->inode->gfid)); glfs_close(glfd); goto out; } @@ -2199,7 +2270,7 @@ svs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, }; svs_fd_t *sfd = NULL; int ret = -1; - struct stat fstatbuf = { + struct glfs_stat fstatbuf = { 0, }; glfs_fd_t *glfd = NULL; @@ -2210,7 +2281,6 @@ svs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, fd, out); GF_VALIDATE_OR_GOTO(this->name, fd->inode, out); @@ -2225,24 +2295,25 @@ svs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, } if (!svs_inode_glfs_mapping(this, fd->inode)) { - gf_log(this->name, GF_LOG_ERROR, - "glfs instance to " - "which the inode %s receiving read request belongs, " - "does not exist anymore", - uuid_utoa(fd->inode->gfid)); op_ret = -1; op_errno = EBADF; /* should this be some other error? */ + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_FS_INSTANCE_INVALID, + "glfs instance to which the inode " + "%s receiving read request belongs, " + "does not exist anymore", + uuid_utoa(fd->inode->gfid)); goto out; } sfd = svs_fd_ctx_get_or_new(this, fd); if (!sfd) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = EBADFD; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "failed to get the fd " "context for %s", uuid_utoa(fd->inode->gfid)); - op_ret = -1; - op_errno = EBADFD; goto out; } @@ -2252,14 +2323,20 @@ svs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, if (!iobuf) { op_ret = -1; op_errno = ENOMEM; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_NO_MEMORY, + "failed to " + "allocate iobuf while reading the " + "file with gfid %s", + uuid_utoa(fd->inode->gfid)); goto out; } - ret = glfs_pread(glfd, iobuf->ptr, size, offset, 0); + ret = glfs_pread(glfd, iobuf->ptr, size, offset, 0, &fstatbuf); if (ret < 0) { op_ret = -1; op_errno = errno; - gf_log(this->name, GF_LOG_ERROR, "glfs_read failed (%s)", + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_READ_FAILED, + "glfs_read failed on %s (%s)", uuid_utoa(fd->inode->gfid), strerror(op_errno)); goto out; } @@ -2270,19 +2347,7 @@ svs_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, iobref = iobref_new(); iobref_add(iobref, iobuf); - - ret = glfs_fstat(glfd, &fstatbuf); - if (ret) { - op_ret = -1; - op_errno = errno; - gf_log(this->name, GF_LOG_ERROR, - "glfs_fstat failed after " - "readv on %s", - uuid_utoa(fd->inode->gfid)); - goto out; - } - - iatt_from_stat(&stbuf, &fstatbuf); + glfs_iatt_from_statx(&stbuf, &fstatbuf); gf_uuid_copy(stbuf.ia_gfid, fd->inode->gfid); svs_fill_ino_from_gfid(&stbuf); @@ -2326,7 +2391,6 @@ svs_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, GF_VALIDATE_OR_GOTO("snap-view-daemon", this, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); @@ -2339,12 +2403,13 @@ svs_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, inode_ctx = svs_inode_ctx_get(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, + op_ret = -1; + op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, "failed to get inode context " "for %s (gfid: %s)", loc->name, uuid_utoa(loc->inode->gfid)); - op_ret = -1; - op_errno = EINVAL; goto out; } @@ -2353,12 +2418,12 @@ svs_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, ret = glfs_h_stat(fs, object, &stat); if (ret) { - gf_log(this->name, GF_LOG_ERROR, - "glfs_h_stat on %s " - "(gfid: %s) failed", - loc->name, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_STAT_FAILED, + "glfs_h_stat on %s (gfid: %s) " + "failed", + loc->name, uuid_utoa(loc->inode->gfid)); goto out; } @@ -2369,11 +2434,10 @@ svs_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, buf = alloca(size + 1); op_ret = glfs_h_readlink(fs, object, buf, size); if (op_ret == -1) { - gf_log(this->name, GF_LOG_ERROR, - "readlink on %s failed " - "(gfid: %s)", - loc->name, uuid_utoa(loc->inode->gfid)); op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_READLINK_FAILED, + "readlink on %s failed (gfid: %s)", loc->name, + uuid_utoa(loc->inode->gfid)); goto out; } @@ -2402,7 +2466,6 @@ svs_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int mask, GF_VALIDATE_OR_GOTO("svs", this, out); GF_VALIDATE_OR_GOTO(this->name, this->private, out); GF_VALIDATE_OR_GOTO(this->name, frame, out); - GF_VALIDATE_OR_GOTO(this->name, frame->root, out); GF_VALIDATE_OR_GOTO(this->name, loc, out); GF_VALIDATE_OR_GOTO(this->name, loc->inode, out); @@ -2415,12 +2478,11 @@ svs_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int mask, inode_ctx = svs_inode_ctx_get(this, loc->inode); if (!inode_ctx) { - gf_log(this->name, GF_LOG_ERROR, - "inode context not found for" - " %s", - uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = EINVAL; + gf_msg(this->name, GF_LOG_ERROR, op_errno, + SVS_MSG_GET_INODE_CONTEXT_FAILED, + "inode context not found for %s", uuid_utoa(loc->inode->gfid)); goto out; } @@ -2459,12 +2521,11 @@ svs_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int mask, ret = glfs_h_access(fs, object, mask); if (ret < 0) { - gf_log(this->name, GF_LOG_ERROR, - "failed to access %s " - "(gfid: %s)", - loc->path, uuid_utoa(loc->inode->gfid)); op_ret = -1; op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, op_errno, SVS_MSG_ACCESS_FAILED, + "failed to access %s (gfid: %s)", loc->path, + uuid_utoa(loc->inode->gfid)); goto out; } @@ -2502,7 +2563,7 @@ mem_acct_init(xlator_t *this) ret = xlator_mem_acct_init(this, gf_svs_mt_end + 1); if (ret != 0) { - gf_log(this->name, GF_LOG_WARNING, + gf_msg(this->name, GF_LOG_WARNING, 0, SVS_MSG_MEM_ACNT_FAILED, "Memory accounting" " init failed"); return ret; @@ -2519,12 +2580,16 @@ init(xlator_t *this) /* This can be the top of graph in certain cases */ if (!this->parents) { - gf_log(this->name, GF_LOG_DEBUG, "dangling volume. check volfile "); + gf_msg_debug(this->name, 0, "dangling volume. check volfile "); } priv = GF_CALLOC(1, sizeof(*priv), gf_svs_mt_priv_t); - if (!priv) + if (!priv) { + gf_msg(this->name, GF_LOG_ERROR, ENOMEM, SVS_MSG_NO_MEMORY, + "failed to " + "allocate memory for this->private "); goto out; + } this->private = priv; @@ -2542,7 +2607,7 @@ init(xlator_t *this) /* happen.*/ ret = svs_mgmt_init(this); if (ret) { - gf_log(this->name, GF_LOG_WARNING, + gf_msg(this->name, GF_LOG_WARNING, EINVAL, SVS_MSG_MGMT_INIT_FAILED, "failed to initiate the " "mgmt rpc callback for svs. Dymamic management of the" "snapshots will not happen"); @@ -2552,7 +2617,8 @@ init(xlator_t *this) /* get the list of snaps first to return to client xlator */ ret = svs_get_snapshot_list(this); if (ret) { - gf_log(this->name, GF_LOG_ERROR, + gf_msg(this->name, GF_LOG_ERROR, EINVAL, + SVS_MSG_GET_SNAPSHOT_LIST_FAILED, "Error initializing snaplist infrastructure"); ret = -1; goto out; @@ -2582,12 +2648,14 @@ fini(xlator_t *this) this->private = NULL; ctx = this->ctx; if (!ctx) - gf_log(this->name, GF_LOG_ERROR, "Invalid ctx found"); + gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_INVALID_GLFS_CTX, + "Invalid ctx found"); if (priv) { ret = LOCK_DESTROY(&priv->snaplist_lock); if (ret != 0) { - gf_log(this->name, GF_LOG_WARNING, + gf_msg(this->name, GF_LOG_WARNING, errno, + SVS_MSG_LOCK_DESTROY_FAILED, "Could not destroy mutex snaplist_lock"); } @@ -2637,3 +2705,16 @@ struct volume_options options[] = { }, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .mem_acct_init = mem_acct_init, + .op_version = {1}, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "snapview-server", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/snapview-server/src/snapview-server.h b/xlators/features/snapview-server/src/snapview-server.h index e07d3bcad0c..6472422e715 100644 --- a/xlators/features/snapview-server/src/snapview-server.h +++ b/xlators/features/snapview-server/src/snapview-server.h @@ -10,29 +10,28 @@ #ifndef __SNAP_VIEW_H__ #define __SNAP_VIEW_H__ -#include "dict.h" -#include "defaults.h" -#include "mem-types.h" -#include "call-stub.h" -#include "byte-order.h" -#include "iatt.h" +#include <glusterfs/dict.h> +#include <glusterfs/defaults.h> +#include <glusterfs/mem-types.h> +#include <glusterfs/call-stub.h> +#include <glusterfs/byte-order.h> +#include <glusterfs/iatt.h> #include <ctype.h> #include <sys/uio.h> -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> #include "glfs.h" -#include "common-utils.h" #include "glfs-handles.h" #include "glfs-internal.h" #include "glusterfs3-xdr.h" -#include "glusterfs-acl.h" -#include "syncop.h" -#include "list.h" -#include "timer.h" +#include <glusterfs/glusterfs-acl.h> +#include <glusterfs/syncop.h> +#include <glusterfs/list.h> +#include <glusterfs/timer.h> #include "rpc-clnt.h" #include "protocol-common.h" #include "xdr-generic.h" +#include "snapview-server-messages.h" #define DEFAULT_SVD_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs" @@ -57,9 +56,16 @@ { \ for (i = 0; i < _private->num_snaps; i++) { \ tmp_fs = _private->dirents[i].fs; \ - gf_log(this->name, GF_LOG_DEBUG, "dirent->fs: %p", tmp_fs); \ + gf_log(this->name, GF_LOG_DEBUG, \ + "snap name: %s, snap volume: %s," \ + "dirent->fs: %p", \ + _private->dirents[i].name, \ + _private->dirents[i].snap_volname, tmp_fs); \ if (tmp_fs && fs && (tmp_fs == fs)) { \ found = _gf_true; \ + gf_msg_debug(this->name, 0, \ + "found the fs " \ + "instance"); \ break; \ } \ } \ diff --git a/xlators/features/thin-arbiter/src/Makefile.am b/xlators/features/thin-arbiter/src/Makefile.am index 7fd31a66caa..a3c133e7798 100644 --- a/xlators/features/thin-arbiter/src/Makefile.am +++ b/xlators/features/thin-arbiter/src/Makefile.am @@ -1,6 +1,4 @@ -if WITH_SERVER xlator_LTLIBRARIES = thin-arbiter.la -endif xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features diff --git a/xlators/features/thin-arbiter/src/thin-arbiter-mem-types.h b/xlators/features/thin-arbiter/src/thin-arbiter-mem-types.h index 79b5ce0eee3..69562d2febc 100644 --- a/xlators/features/thin-arbiter/src/thin-arbiter-mem-types.h +++ b/xlators/features/thin-arbiter/src/thin-arbiter-mem-types.h @@ -9,7 +9,7 @@ #ifndef __THIN_ARBITER_MEM_TYPES_H__ #define __THIN_ARBITER_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> typedef enum gf_ta_mem_types_ { gf_ta_mt_local_t = gf_common_mt_end + 1, diff --git a/xlators/features/thin-arbiter/src/thin-arbiter-messages.h b/xlators/features/thin-arbiter/src/thin-arbiter-messages.h index f49b3eedadf..81d7491577a 100644 --- a/xlators/features/thin-arbiter/src/thin-arbiter-messages.h +++ b/xlators/features/thin-arbiter/src/thin-arbiter-messages.h @@ -11,7 +11,7 @@ #ifndef _TA_MESSAGES_H_ #define _TA_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/thin-arbiter/src/thin-arbiter.c b/xlators/features/thin-arbiter/src/thin-arbiter.c index 062e04132d6..ce3008636f1 100644 --- a/xlators/features/thin-arbiter/src/thin-arbiter.c +++ b/xlators/features/thin-arbiter/src/thin-arbiter.c @@ -11,11 +11,11 @@ #include "thin-arbiter.h" #include "thin-arbiter-messages.h" #include "thin-arbiter-mem-types.h" -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "byte-order.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/byte-order.h> +#include <glusterfs/common-utils.h> int ta_set_incoming_values(dict_t *dict, char *key, data_t *value, void *data) @@ -646,3 +646,16 @@ struct xlator_cbks cbks = {}; struct volume_options options[] = { {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {GD_OP_VERSION_6_0}, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "thin-arbiter", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/thin-arbiter/src/thin-arbiter.h b/xlators/features/thin-arbiter/src/thin-arbiter.h index af3d4b1af92..e5f914b84bf 100644 --- a/xlators/features/thin-arbiter/src/thin-arbiter.h +++ b/xlators/features/thin-arbiter/src/thin-arbiter.h @@ -11,12 +11,12 @@ #ifndef _THIN_ARBITER_H #define _THIN_ARBITER_H -#include "locking.h" -#include "common-utils.h" -#include "glusterfs.h" -#include "xlator.h" -#include "defaults.h" -#include "list.h" +#include <glusterfs/locking.h> +#include <glusterfs/common-utils.h> +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> +#include <glusterfs/list.h> #define THIN_ARBITER_SOURCE_XATTR "trusted.ta.source" #define THIN_ARBITER_SOURCE_SIZE 2 diff --git a/xlators/features/trash/src/trash-mem-types.h b/xlators/features/trash/src/trash-mem-types.h index 133f2edf99b..43353c8f095 100644 --- a/xlators/features/trash/src/trash-mem-types.h +++ b/xlators/features/trash/src/trash-mem-types.h @@ -10,7 +10,7 @@ #ifndef __TRASH_MEM_TYPES_H__ #define __TRASH_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_trash_mem_types_ { gf_trash_mt_trash_private_t = gf_common_mt_end + 1, diff --git a/xlators/features/trash/src/trash.c b/xlators/features/trash/src/trash.c index 82cc6d6a8e8..7d09cba3e9c 100644 --- a/xlators/features/trash/src/trash.c +++ b/xlators/features/trash/src/trash.c @@ -9,7 +9,7 @@ */ #include "trash.h" #include "trash-mem-types.h" -#include "syscall.h" +#include <glusterfs/syscall.h> #define root_gfid \ (uuid_t) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } @@ -170,7 +170,7 @@ store_eliminate_path(char *str, trash_elim_path **eliminate) int ret = 0; char *strtokptr = NULL; - if (eliminate == NULL) { + if ((str == NULL) || (eliminate == NULL)) { ret = EINVAL; goto out; } @@ -194,6 +194,7 @@ store_eliminate_path(char *str, trash_elim_path **eliminate) if (!trav->path) { ret = ENOMEM; gf_log("trash", GF_LOG_DEBUG, "out of memory"); + GF_FREE(trav); goto out; } trav->next = *eliminate; @@ -211,11 +212,11 @@ void append_time_stamp(char *name, size_t name_size) { int i; - char timestr[64] = { + char timestr[GF_TIMESTR_SIZE] = { 0, }; - gf_time_fmt(timestr, sizeof(timestr), time(NULL), gf_timefmt_F_HMS); + gf_time_fmt(timestr, sizeof(timestr), gf_time(), gf_timefmt_F_HMS); /* removing white spaces in timestamp */ for (i = 0; i < strlen(timestr); i++) { @@ -2522,6 +2523,7 @@ out: GF_FREE(priv); } mem_pool_destroy(this->local_pool); + this->local_pool = NULL; } return ret; } @@ -2635,3 +2637,17 @@ struct volume_options options[] = { .default_value = "{{ brick.path }}"}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "trash", + .category = GF_TECH_PREVIEW, +}; diff --git a/xlators/features/trash/src/trash.h b/xlators/features/trash/src/trash.h index 675f9f97350..6671617c2c6 100644 --- a/xlators/features/trash/src/trash.h +++ b/xlators/features/trash/src/trash.h @@ -10,11 +10,11 @@ #ifndef __TRASH_H__ #define __TRASH_H__ -#include "glusterfs.h" -#include "logging.h" -#include "dict.h" -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/logging.h> +#include <glusterfs/dict.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "inode.c" #include "fnmatch.h" diff --git a/xlators/features/upcall/src/upcall-cache-invalidation.h b/xlators/features/upcall/src/upcall-cache-invalidation.h index e509a89acd5..db649b2c9a6 100644 --- a/xlators/features/upcall/src/upcall-cache-invalidation.h +++ b/xlators/features/upcall/src/upcall-cache-invalidation.h @@ -15,10 +15,4 @@ * events post its last access */ #define CACHE_INVALIDATION_TIMEOUT "60" -/* xlator options */ -gf_boolean_t -is_cache_invalidation_enabled(xlator_t *this); -int32_t -get_cache_invalidation_timeout(xlator_t *this); - #endif /* __UPCALL_CACHE_INVALIDATION_H__ */ diff --git a/xlators/features/upcall/src/upcall-internal.c b/xlators/features/upcall/src/upcall-internal.c index 9d16e5f0ef8..c641bd6f432 100644 --- a/xlators/features/upcall/src/upcall-internal.c +++ b/xlators/features/upcall/src/upcall-internal.c @@ -12,20 +12,20 @@ #include <fcntl.h> #include <limits.h> -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> -#include "statedump.h" -#include "syncop.h" +#include <glusterfs/statedump.h> +#include <glusterfs/syncop.h> #include "upcall.h" #include "upcall-mem-types.h" #include "glusterfs3-xdr.h" #include "protocol-common.h" -#include "defaults.h" +#include <glusterfs/defaults.h> /* * Check if any of the upcall options are enabled: @@ -35,62 +35,37 @@ gf_boolean_t is_upcall_enabled(xlator_t *this) { upcall_private_t *priv = NULL; - gf_boolean_t is_enabled = _gf_false; if (this->private) { priv = (upcall_private_t *)this->private; - - if (priv->cache_invalidation_enabled) { - is_enabled = _gf_true; - } + return priv->cache_invalidation_enabled; } - return is_enabled; + return _gf_false; } /* * Get the cache_invalidation_timeout */ -int32_t +static int32_t get_cache_invalidation_timeout(xlator_t *this) { upcall_private_t *priv = NULL; - int32_t timeout = 0; if (this->private) { priv = (upcall_private_t *)this->private; - timeout = priv->cache_invalidation_timeout; - } - - return timeout; -} - -/* - * Allocate and add a new client entry to the given upcall entry - */ -upcall_client_t * -add_upcall_client(call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx) -{ - upcall_client_t *up_client_entry = NULL; - - pthread_mutex_lock(&up_inode_ctx->client_list_lock); - { - up_client_entry = __add_upcall_client(frame, client, up_inode_ctx); + return priv->cache_invalidation_timeout; } - pthread_mutex_unlock(&up_inode_ctx->client_list_lock); - return up_client_entry; + return 0; } -upcall_client_t * +static upcall_client_t * __add_upcall_client(call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx) + upcall_inode_ctx_t *up_inode_ctx, time_t now) { - upcall_client_t *up_client_entry = NULL; - - up_client_entry = GF_CALLOC(1, sizeof(*up_client_entry), - gf_upcall_mt_upcall_client_entry_t); + upcall_client_t *up_client_entry = GF_MALLOC( + sizeof(*up_client_entry), gf_upcall_mt_upcall_client_entry_t); if (!up_client_entry) { gf_msg("upcall", GF_LOG_WARNING, 0, UPCALL_MSG_NO_MEMORY, "Memory allocation failed"); @@ -98,7 +73,7 @@ __add_upcall_client(call_frame_t *frame, client_t *client, } INIT_LIST_HEAD(&up_client_entry->client_list); up_client_entry->client_uid = gf_strdup(client->client_uid); - up_client_entry->access_time = time(NULL); + up_client_entry->access_time = now; up_client_entry->expire_time_attr = get_cache_invalidation_timeout( frame->this); @@ -110,39 +85,7 @@ __add_upcall_client(call_frame_t *frame, client_t *client, return up_client_entry; } -/* - * Given client->uid, retrieve the corresponding upcall client entry. - * If none found, create a new entry. - */ -upcall_client_t * -__get_upcall_client(call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx) -{ - upcall_client_t *up_client_entry = NULL; - upcall_client_t *tmp = NULL; - gf_boolean_t found_client = _gf_false; - - list_for_each_entry_safe(up_client_entry, tmp, &up_inode_ctx->client_list, - client_list) - { - if (strcmp(client->client_uid, up_client_entry->client_uid) == 0) { - /* found client entry. Update the access_time */ - up_client_entry->access_time = time(NULL); - found_client = _gf_true; - gf_log(THIS->name, GF_LOG_DEBUG, "upcall_entry_t client found - %s", - up_client_entry->client_uid); - break; - } - } - - if (!found_client) { /* create one */ - up_client_entry = __add_upcall_client(frame, client, up_inode_ctx); - } - - return up_client_entry; -} - -int +static int __upcall_inode_ctx_set(inode_t *inode, xlator_t *this) { upcall_inode_ctx_t *inode_ctx = NULL; @@ -158,7 +101,7 @@ __upcall_inode_ctx_set(inode_t *inode, xlator_t *this) if (!ret) goto out; - inode_ctx = GF_CALLOC(1, sizeof(upcall_inode_ctx_t), + inode_ctx = GF_MALLOC(sizeof(upcall_inode_ctx_t), gf_upcall_mt_upcall_inode_ctx_t); if (!inode_ctx) { @@ -190,7 +133,7 @@ out: return ret; } -upcall_inode_ctx_t * +static upcall_inode_ctx_t * __upcall_inode_ctx_get(inode_t *inode, xlator_t *this) { upcall_inode_ctx_t *inode_ctx = NULL; @@ -229,8 +172,20 @@ upcall_inode_ctx_get(inode_t *inode, xlator_t *this) return inode_ctx; } -int -upcall_cleanup_expired_clients(xlator_t *this, upcall_inode_ctx_t *up_inode_ctx) +static int +__upcall_cleanup_client_entry(upcall_client_t *up_client) +{ + list_del_init(&up_client->client_list); + + GF_FREE(up_client->client_uid); + GF_FREE(up_client); + + return 0; +} + +static int +upcall_cleanup_expired_clients(xlator_t *this, upcall_inode_ctx_t *up_inode_ctx, + time_t now) { upcall_client_t *up_client = NULL; upcall_client_t *tmp = NULL; @@ -245,7 +200,7 @@ upcall_cleanup_expired_clients(xlator_t *this, upcall_inode_ctx_t *up_inode_ctx) list_for_each_entry_safe(up_client, tmp, &up_inode_ctx->client_list, client_list) { - t_expired = time(NULL) - up_client->access_time; + t_expired = now - up_client->access_time; if (t_expired > (2 * timeout)) { gf_log(THIS->name, GF_LOG_TRACE, "Cleaning up client_entry(%s)", @@ -269,17 +224,6 @@ out: return ret; } -int -__upcall_cleanup_client_entry(upcall_client_t *up_client) -{ - list_del_init(&up_client->client_list); - - GF_FREE(up_client->client_uid); - GF_FREE(up_client); - - return 0; -} - /* * Free Upcall inode_ctx client list */ @@ -298,6 +242,10 @@ __upcall_cleanup_inode_ctx_client_list(upcall_inode_ctx_t *inode_ctx) return 0; } +static void +upcall_cache_forget(xlator_t *this, inode_t *inode, + upcall_inode_ctx_t *up_inode_ctx); + /* * Free upcall_inode_ctx */ @@ -360,6 +308,7 @@ upcall_reaper_thread(void *data) upcall_inode_ctx_t *tmp = NULL; xlator_t *this = NULL; time_t timeout = 0; + time_t time_now; this = (xlator_t *)data; GF_ASSERT(this); @@ -367,33 +316,35 @@ upcall_reaper_thread(void *data) priv = this->private; GF_ASSERT(priv); + time_now = gf_time(); while (!priv->fini) { list_for_each_entry_safe(inode_ctx, tmp, &priv->inode_ctx_list, inode_ctx_list) { /* cleanup expired clients */ - upcall_cleanup_expired_clients(this, inode_ctx); + upcall_cleanup_expired_clients(this, inode_ctx, time_now); if (!inode_ctx->destroy) { continue; } + /* client list would have been cleaned up*/ + gf_msg_debug("upcall", 0, "Freeing upcall_inode_ctx (%p)", + inode_ctx); LOCK(&priv->inode_ctx_lk); { - /* client list would have been cleaned up*/ - gf_msg_debug("upcall", 0, "Freeing upcall_inode_ctx (%p)", - inode_ctx); list_del_init(&inode_ctx->inode_ctx_list); pthread_mutex_destroy(&inode_ctx->client_list_lock); - GF_FREE(inode_ctx); - inode_ctx = NULL; } UNLOCK(&priv->inode_ctx_lk); + GF_FREE(inode_ctx); + inode_ctx = NULL; } /* don't do a very busy loop */ timeout = get_cache_invalidation_timeout(this); sleep(timeout / 2); + time_now = gf_time(); } return NULL; @@ -486,6 +437,13 @@ up_filter_xattr(dict_t *xattr, dict_t *regd_xattrs) return ret; } +static void +upcall_client_cache_invalidate(xlator_t *this, uuid_t gfid, + upcall_client_t *up_client_entry, uint32_t flags, + struct iatt *stbuf, struct iatt *p_stbuf, + struct iatt *oldp_stbuf, dict_t *xattr, + time_t now); + gf_boolean_t up_invalidate_needed(dict_t *xattrs) { @@ -520,6 +478,8 @@ upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, upcall_client_t *tmp = NULL; upcall_inode_ctx_t *up_inode_ctx = NULL; gf_boolean_t found = _gf_false; + time_t time_now; + inode_t *linked_inode = NULL; if (!is_upcall_enabled(this)) return; @@ -532,7 +492,20 @@ upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, return; } - if (inode) + /* For nameless LOOKUPs, inode created shall always be + * invalid. Hence check if there is any already linked inode. + * If yes, update the inode_ctx of that valid inode + */ + if (inode && (inode->ia_type == IA_INVAL) && stbuf) { + linked_inode = inode_find(inode->table, stbuf->ia_gfid); + if (linked_inode) { + gf_log("upcall", GF_LOG_DEBUG, + "upcall_inode_ctx_get of linked inode (%p)", inode); + up_inode_ctx = upcall_inode_ctx_get(linked_inode, this); + } + } + + if (inode && !up_inode_ctx) up_inode_ctx = upcall_inode_ctx_get(inode, this); if (!up_inode_ctx) { @@ -560,6 +533,7 @@ upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, goto out; } + time_now = gf_time(); pthread_mutex_lock(&up_inode_ctx->client_list_lock); { list_for_each_entry_safe(up_client_entry, tmp, @@ -567,7 +541,7 @@ upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, { /* Do not send UPCALL event if same client. */ if (!strcmp(client->client_uid, up_client_entry->client_uid)) { - up_client_entry->access_time = time(NULL); + up_client_entry->access_time = time_now; found = _gf_true; continue; } @@ -589,17 +563,21 @@ upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, * Also if the file is frequently accessed, set * expire_time_attr to 0. */ - upcall_client_cache_invalidate(this, up_inode_ctx->gfid, - up_client_entry, flags, stbuf, - p_stbuf, oldp_stbuf, xattr); + upcall_client_cache_invalidate( + this, up_inode_ctx->gfid, up_client_entry, flags, stbuf, + p_stbuf, oldp_stbuf, xattr, time_now); } if (!found) { - up_client_entry = __add_upcall_client(frame, client, up_inode_ctx); + up_client_entry = __add_upcall_client(frame, client, up_inode_ctx, + time_now); } } pthread_mutex_unlock(&up_inode_ctx->client_list_lock); out: + /* release the ref from inode_find */ + if (linked_inode) + inode_unref(linked_inode); return; } @@ -607,11 +585,12 @@ out: * If the upcall_client_t has recently accessed the file (i.e, within * priv->cache_invalidation_timeout), send a upcall notification. */ -void +static void upcall_client_cache_invalidate(xlator_t *this, uuid_t gfid, upcall_client_t *up_client_entry, uint32_t flags, struct iatt *stbuf, struct iatt *p_stbuf, - struct iatt *oldp_stbuf, dict_t *xattr) + struct iatt *oldp_stbuf, dict_t *xattr, + time_t now) { struct gf_upcall up_req = { 0, @@ -621,7 +600,7 @@ upcall_client_cache_invalidate(xlator_t *this, uuid_t gfid, }; time_t timeout = 0; int ret = -1; - time_t t_expired = time(NULL) - up_client_entry->access_time; + time_t t_expired = now - up_client_entry->access_time; GF_VALIDATE_OR_GOTO("upcall_client_cache_invalidate", !(gf_uuid_is_null(gfid)), out); @@ -678,32 +657,32 @@ out: * Send "UP_FORGET" to all the clients so that they invalidate their cache * entry and do a fresh lookup next time when any I/O comes in. */ -void +static void upcall_cache_forget(xlator_t *this, inode_t *inode, upcall_inode_ctx_t *up_inode_ctx) { upcall_client_t *up_client_entry = NULL; upcall_client_t *tmp = NULL; - uint32_t flags = 0; + uint32_t flags = UP_FORGET; + time_t time_now; if (!up_inode_ctx) { return; } + time_now = gf_time(); pthread_mutex_lock(&up_inode_ctx->client_list_lock); { list_for_each_entry_safe(up_client_entry, tmp, &up_inode_ctx->client_list, client_list) { - flags = UP_FORGET; - - /* Set the access time to time(NULL) + /* Set the access time to gf_time() * to send notify */ - up_client_entry->access_time = time(NULL); + up_client_entry->access_time = time_now; upcall_client_cache_invalidate(this, up_inode_ctx->gfid, up_client_entry, flags, NULL, NULL, - NULL, NULL); + NULL, NULL, time_now); } } pthread_mutex_unlock(&up_inode_ctx->client_list_lock); diff --git a/xlators/features/upcall/src/upcall-mem-types.h b/xlators/features/upcall/src/upcall-mem-types.h index 079677ff79c..f9883d9d72c 100644 --- a/xlators/features/upcall/src/upcall-mem-types.h +++ b/xlators/features/upcall/src/upcall-mem-types.h @@ -11,7 +11,7 @@ #ifndef __UPCALL_MEM_TYPES_H__ #define __UPCALL_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_upcall_mem_types_ { gf_upcall_mt_conf_t = gf_common_mt_end + 1, diff --git a/xlators/features/upcall/src/upcall-messages.h b/xlators/features/upcall/src/upcall-messages.h index db5cac1e07d..4095a34c200 100644 --- a/xlators/features/upcall/src/upcall-messages.h +++ b/xlators/features/upcall/src/upcall-messages.h @@ -11,7 +11,7 @@ #ifndef _UPCALL_MESSAGES_H_ #define _UPCALL_MESSAGES_H_ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c index 5fdd4993003..0795f58059d 100644 --- a/xlators/features/upcall/src/upcall.c +++ b/xlators/features/upcall/src/upcall.c @@ -13,19 +13,19 @@ #include <limits.h> #include <pthread.h> -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> -#include "statedump.h" +#include <glusterfs/statedump.h> #include "upcall.h" #include "upcall-mem-types.h" #include "glusterfs3-xdr.h" #include "protocol-common.h" -#include "defaults.h" +#include <glusterfs/defaults.h> static int32_t up_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, @@ -57,14 +57,13 @@ static int32_t up_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, fd_t *fd, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -111,14 +110,13 @@ up_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int count, off_t off, uint32_t flags, struct iobref *iobref, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -167,14 +165,13 @@ static int32_t up_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -220,14 +217,13 @@ static int32_t up_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, struct gf_flock *flock, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -274,14 +270,13 @@ static int32_t up_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -343,14 +338,13 @@ static int32_t up_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf, int32_t valid, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -410,14 +404,13 @@ static int32_t up_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, newloc, NULL, oldloc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -472,14 +465,13 @@ static int32_t up_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, loc, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -531,14 +523,13 @@ static int32_t up_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, newloc, NULL, oldloc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -592,14 +583,13 @@ static int32_t up_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, loc, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -653,14 +643,13 @@ static int32_t up_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, mode_t umask, dict_t *params) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -717,15 +706,13 @@ static int32_t up_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, mode_t mode, mode_t umask, fd_t *fd, dict_t *params) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); - if (!local) { - op_errno = ENOMEM; goto err; } @@ -774,14 +761,13 @@ out: static int32_t up_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -826,14 +812,13 @@ out: static int32_t up_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -852,14 +837,13 @@ err: static int32_t up_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -879,14 +863,13 @@ static int32_t up_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -932,14 +915,13 @@ static int32_t up_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -986,14 +968,13 @@ static int32_t up_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1047,14 +1028,13 @@ static int32_t up_mknod(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1110,14 +1090,13 @@ static int32_t up_symlink(call_frame_t *frame, xlator_t *this, const char *linkpath, loc_t *loc, mode_t umask, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1164,14 +1143,13 @@ static int32_t up_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1216,14 +1194,13 @@ out: static int32_t up_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1270,14 +1247,13 @@ static int32_t up_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1334,14 +1310,13 @@ static int32_t up_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, off_t off, dict_t *dict) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1361,14 +1336,13 @@ static int32_t up_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, int32_t valid, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1415,14 +1389,13 @@ static int32_t up_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, off_t offset, size_t len, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1470,14 +1443,13 @@ static int32_t up_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, size_t len, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1524,14 +1496,13 @@ static int up_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, off_t len, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1577,14 +1548,13 @@ static int32_t up_seek(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, gf_seek_what_t what, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1652,14 +1622,13 @@ static int32_t up_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, int32_t flags, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, loc, NULL, loc->inode, dict); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1727,14 +1696,13 @@ static int32_t up_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, int32_t flags, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, fd, fd->inode, dict); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1800,7 +1768,7 @@ static int32_t up_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; dict_t *xattr = NULL; @@ -1808,13 +1776,11 @@ up_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, xattr = dict_for_key_value(name, "", 1, _gf_true); if (!xattr) { - op_errno = ENOMEM; goto err; } local = upcall_local_init(frame, this, NULL, fd, fd->inode, xattr); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1885,7 +1851,7 @@ static int32_t up_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; dict_t *xattr = NULL; @@ -1893,13 +1859,11 @@ up_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, xattr = dict_for_key_value(name, "", 1, _gf_true); if (!xattr) { - op_errno = ENOMEM; goto err; } local = upcall_local_init(frame, this, loc, NULL, loc->inode, xattr); if (!local) { - op_errno = ENOMEM; goto err; } @@ -1950,14 +1914,13 @@ static int32_t up_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -2000,14 +1963,13 @@ static int32_t up_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { - int32_t op_errno = -1; + int32_t op_errno = ENOMEM; upcall_local_t *local = NULL; EXIT_IF_UPCALL_OFF(this, out); local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); if (!local) { - op_errno = ENOMEM; goto err; } @@ -2335,14 +2297,14 @@ out: return ret; } -int +void fini(xlator_t *this) { upcall_private_t *priv = NULL; priv = this->private; if (!priv) { - return 0; + return; } this->private = NULL; @@ -2367,7 +2329,7 @@ fini(xlator_t *this) this->local_pool = NULL; } - return 0; + return; } int @@ -2527,3 +2489,17 @@ struct volume_options options[] = { .tags = {"cache", "cachetimeout", "upcall"}}, {.key = {NULL}}, }; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "upcall", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/upcall/src/upcall.h b/xlators/features/upcall/src/upcall.h index 3797e62aac3..aa535088ad7 100644 --- a/xlators/features/upcall/src/upcall.h +++ b/xlators/features/upcall/src/upcall.h @@ -10,12 +10,12 @@ #ifndef __UPCALL_H__ #define __UPCALL_H__ -#include "compat-errno.h" +#include <glusterfs/compat-errno.h> #include "upcall-mem-types.h" -#include "client_t.h" +#include <glusterfs/client_t.h> #include "upcall-messages.h" #include "upcall-cache-invalidation.h" -#include "upcall-utils.h" +#include <glusterfs/upcall-utils.h> #define EXIT_IF_UPCALL_OFF(this, label) \ do { \ @@ -100,32 +100,10 @@ upcall_local_t * upcall_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, inode_t *inode, dict_t *xattr); -upcall_client_t * -add_upcall_client(call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx); -upcall_client_t * -__add_upcall_client(call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx); -upcall_client_t * -__get_upcall_client(call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx); -int -__upcall_cleanup_client_entry(upcall_client_t *up_client); -int -upcall_cleanup_expired_clients(xlator_t *this, - upcall_inode_ctx_t *up_inode_ctx); - -int -__upcall_inode_ctx_set(inode_t *inode, xlator_t *this); -upcall_inode_ctx_t * -__upcall_inode_ctx_get(inode_t *inode, xlator_t *this); upcall_inode_ctx_t * upcall_inode_ctx_get(inode_t *inode, xlator_t *this); int upcall_cleanup_inode_ctx(xlator_t *this, inode_t *inode); -void -upcall_cache_forget(xlator_t *this, inode_t *inode, - upcall_inode_ctx_t *up_inode_ctx); void * upcall_reaper_thread(void *data); @@ -142,12 +120,6 @@ upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, inode_t *inode, uint32_t flags, struct iatt *stbuf, struct iatt *p_stbuf, struct iatt *oldp_stbuf, dict_t *xattr); -void -upcall_client_cache_invalidate(xlator_t *xl, uuid_t gfid, - upcall_client_t *up_client_entry, uint32_t flags, - struct iatt *stbuf, struct iatt *p_stbuf, - struct iatt *oldp_stbuf, dict_t *xattr); - int up_filter_xattr(dict_t *xattr, dict_t *regd_xattrs); diff --git a/xlators/features/utime/src/utime-autogen-fops-tmpl.c b/xlators/features/utime/src/utime-autogen-fops-tmpl.c index b4be66eebd1..f2f35322926 100644 --- a/xlators/features/utime/src/utime-autogen-fops-tmpl.c +++ b/xlators/features/utime/src/utime-autogen-fops-tmpl.c @@ -18,11 +18,11 @@ #include "config.h" #endif -#include "glusterfs.h" -#include "xlator.h" -#include "logging.h" -#include "statedump.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/statedump.h> #include "utime-helpers.h" -#include "timespec.h" +#include <glusterfs/timespec.h> #pragma generate diff --git a/xlators/features/utime/src/utime-autogen-fops-tmpl.h b/xlators/features/utime/src/utime-autogen-fops-tmpl.h index e2e807cdf64..4e102ffed6c 100644 --- a/xlators/features/utime/src/utime-autogen-fops-tmpl.h +++ b/xlators/features/utime/src/utime-autogen-fops-tmpl.h @@ -15,7 +15,7 @@ #ifndef _UTIME_AUTOGEN_FOPS_H #define _UTIME_AUTOGEN_FOPS_H -#include "xlator.h" +#include <glusterfs/xlator.h> #pragma generate diff --git a/xlators/features/utime/src/utime-gen-fops-c.py b/xlators/features/utime/src/utime-gen-fops-c.py index ab56dc9a4b3..9fb3e1b8b1a 100644..100755 --- a/xlators/features/utime/src/utime-gen-fops-c.py +++ b/xlators/features/utime/src/utime-gen-fops-c.py @@ -62,6 +62,20 @@ gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this, } """ +FOPS_COPY_FILE_RANGE_TEMPLATE = """ +int32_t +gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this, + @LONG_ARGS@) +{ + gl_timespec_get(&frame->root->ctime); + + (void) utime_update_attribute_flags(frame, this, GF_FOP_COPY_FILE_RANGE); + STACK_WIND (frame, gf_utime_@NAME@_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->@NAME@, @SHORT_ARGS@); + return 0; +} +""" + FOPS_SETATTR_TEMPLATE = """ int32_t gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this, @@ -81,6 +95,16 @@ gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this, frame->root->flags |= MDATA_CTIME; } + if (valid & (GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME)) { + if (valid & GF_ATTR_ATIME_NOW) { + frame->root->ctime.tv_sec = stbuf->ia_atime; + frame->root->ctime.tv_nsec = stbuf->ia_atime_nsec; + } else if (valid & GF_ATTR_MTIME_NOW) { + frame->root->ctime.tv_sec = stbuf->ia_mtime; + frame->root->ctime.tv_nsec = stbuf->ia_mtime_nsec; + } + } + STACK_WIND (frame, gf_utime_@NAME@_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->@NAME@, @SHORT_ARGS@); return 0; @@ -94,6 +118,7 @@ utime_ops = ['fallocate', 'zerofill', 'opendir', 'mknod', 'mkdir', utime_read_op = ['readv'] utime_write_op = ['writev'] utime_setattr_ops = ['setattr', 'fsetattr'] +utime_copy_file_range_ops = ['copy_file_range'] def gen_defaults(): for name in ops: @@ -109,6 +134,9 @@ def gen_defaults(): if name in utime_setattr_ops: print(generate(FOPS_CBK_COMMON_TEMPLATE, name, cbk_subs)) print(generate(FOPS_SETATTR_TEMPLATE, name, fop_subs)) + if name in utime_copy_file_range_ops: + print(generate(FOPS_CBK_COMMON_TEMPLATE, name, cbk_subs)) + print(generate(FOPS_COPY_FILE_RANGE_TEMPLATE, name, fop_subs)) for l in open(sys.argv[1], 'r').readlines(): if l.find('#pragma generate') != -1: diff --git a/xlators/features/utime/src/utime-gen-fops-h.py b/xlators/features/utime/src/utime-gen-fops-h.py index 3686f2e3c1e..e96274c229a 100644..100755 --- a/xlators/features/utime/src/utime-gen-fops-h.py +++ b/xlators/features/utime/src/utime-gen-fops-h.py @@ -18,7 +18,7 @@ gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this, utime_ops = ['fallocate', 'zerofill', 'opendir', 'mknod', 'mkdir', 'unlink', 'rmdir', 'symlink', 'rename', 'link', 'truncate', 'ftruncate', 'create', 'open', 'removexattr', 'fremovexattr', - 'readv', 'writev', 'setattr', 'fsetattr'] + 'readv', 'writev', 'setattr', 'fsetattr', 'copy_file_range'] def gen_defaults(): for name, value in ops.items(): diff --git a/xlators/features/utime/src/utime-helpers.c b/xlators/features/utime/src/utime-helpers.c index c79e12badfa..29d9ad93561 100644 --- a/xlators/features/utime/src/utime-helpers.c +++ b/xlators/features/utime/src/utime-helpers.c @@ -17,7 +17,7 @@ gl_timespec_get(struct timespec *ts) #ifdef TIME_UTC timespec_get(ts, TIME_UTC); #else - timespec_now(ts); + timespec_now_realtime(ts); #endif } @@ -93,6 +93,15 @@ utime_update_attribute_flags(call_frame_t *frame, xlator_t *this, frame->root->flags |= MDATA_CTIME; break; + case GF_FOP_COPY_FILE_RANGE: + /* Below 2 are for destination fd */ + frame->root->flags |= MDATA_CTIME; + frame->root->flags |= MDATA_MTIME; + /* Below flag is for the source fd */ + if (!utime_priv->noatime) { + frame->root->flags |= MDATA_ATIME; + } + break; default: frame->root->flags = 0; } diff --git a/xlators/features/utime/src/utime-helpers.h b/xlators/features/utime/src/utime-helpers.h index b89867a3db3..2e32d4bece6 100644 --- a/xlators/features/utime/src/utime-helpers.h +++ b/xlators/features/utime/src/utime-helpers.h @@ -11,10 +11,9 @@ #ifndef _UTIME_HELPERS_H #define _UTIME_HELPERS_H -#include "glusterfs-fops.h" -#include "stack.h" -#include "xlator.h" -#include "timespec.h" +#include <glusterfs/stack.h> +#include <glusterfs/xlator.h> +#include <glusterfs/timespec.h> #include <time.h> void diff --git a/xlators/features/utime/src/utime-mem-types.h b/xlators/features/utime/src/utime-mem-types.h index fbd9aff0eca..ad1255f85f3 100644 --- a/xlators/features/utime/src/utime-mem-types.h +++ b/xlators/features/utime/src/utime-mem-types.h @@ -11,7 +11,7 @@ #ifndef __UTIME_MEM_TYPES_H__ #define __UTIME_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_utime_mem_types_ { utime_mt_utime_t = gf_common_mt_end + 1, diff --git a/xlators/features/utime/src/utime-messages.h b/xlators/features/utime/src/utime-messages.h index 7613c335d43..bd40265abaf 100644 --- a/xlators/features/utime/src/utime-messages.h +++ b/xlators/features/utime/src/utime-messages.h @@ -11,7 +11,7 @@ #ifndef __UTIME_MESSAGES_H__ #define __UTIME_MESSAGES_H__ -#include "glfs-message-id.h" +#include <glusterfs/glfs-message-id.h> /* To add new message IDs, append new identifiers at the end of the list. * @@ -23,6 +23,7 @@ * glfs-message-id.h. */ -GLFS_MSGID(UTIME, UTIME_MSG_NO_MEMORY); +GLFS_MSGID(UTIME, UTIME_MSG_NO_MEMORY, UTIME_MSG_SET_MDATA_FAILED, + UTIME_MSG_DICT_SET_FAILED); #endif /* __UTIME_MESSAGES_H__ */ diff --git a/xlators/features/utime/src/utime.c b/xlators/features/utime/src/utime.c index 418e4c4a0d5..2acc63e6a05 100644 --- a/xlators/features/utime/src/utime.c +++ b/xlators/features/utime/src/utime.c @@ -9,8 +9,10 @@ */ #include "utime.h" +#include "utime-helpers.h" #include "utime-messages.h" #include "utime-mem-types.h" +#include <glusterfs/call-stub.h> int32_t gf_utime_invalidate(xlator_t *this, inode_t *inode) @@ -133,6 +135,141 @@ mem_acct_init(xlator_t *this) } int32_t +gf_utime_set_mdata_setxattr_cbk(call_frame_t *frame, void *cookie, + xlator_t *this, int op_ret, int op_errno, + dict_t *xdata) +{ + call_stub_t *stub = frame->local; + /* Don't fail lookup if mdata setxattr fails */ + if (op_ret) { + gf_msg(this->name, GF_LOG_ERROR, op_errno, UTIME_MSG_SET_MDATA_FAILED, + "dict set of key for set-ctime-mdata failed"); + } + frame->local = NULL; + call_resume(stub); + STACK_DESTROY(frame->root); + return 0; +} + +int32_t +gf_utime_set_mdata_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *stbuf, dict_t *xdata, + struct iatt *postparent) +{ + dict_t *dict = NULL; + struct mdata_iatt *mdata = NULL; + int ret = 0; + loc_t loc = { + 0, + }; + call_frame_t *new_frame = NULL; + + if (!op_ret && dict_get(xdata, GF_XATTR_MDATA_KEY) == NULL) { + dict = dict_new(); + if (!dict) { + op_errno = ENOMEM; + goto err; + } + mdata = GF_MALLOC(sizeof(struct mdata_iatt), gf_common_mt_char); + if (mdata == NULL) { + op_errno = ENOMEM; + goto err; + } + iatt_to_mdata(mdata, stbuf); + ret = dict_set_mdata(dict, CTIME_MDATA_XDATA_KEY, mdata, _gf_false); + if (ret < 0) { + gf_msg(this->name, GF_LOG_WARNING, ENOMEM, UTIME_MSG_NO_MEMORY, + "dict set of key for set-ctime-mdata failed"); + goto err; + } + new_frame = copy_frame(frame); + if (!new_frame) { + op_errno = ENOMEM; + goto stub_err; + } + + new_frame->local = fop_lookup_cbk_stub(frame, default_lookup_cbk, + op_ret, op_errno, inode, stbuf, + xdata, postparent); + if (!new_frame->local) { + gf_msg(this->name, GF_LOG_WARNING, ENOMEM, UTIME_MSG_NO_MEMORY, + "lookup_cbk stub allocation failed"); + op_errno = ENOMEM; + STACK_DESTROY(new_frame->root); + goto stub_err; + } + + loc.inode = inode_ref(inode); + gf_uuid_copy(loc.gfid, stbuf->ia_gfid); + + new_frame->root->uid = 0; + new_frame->root->gid = 0; + new_frame->root->pid = GF_CLIENT_PID_SET_UTIME; + STACK_WIND(new_frame, gf_utime_set_mdata_setxattr_cbk, + FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, &loc, + dict, 0, NULL); + + dict_unref(dict); + inode_unref(loc.inode); + return 0; + } + + STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, stbuf, xdata, + postparent); + return 0; + +err: + if (mdata) { + GF_FREE(mdata); + } +stub_err: + if (dict) { + dict_unref(dict); + } + STACK_UNWIND_STRICT(lookup, frame, -1, op_errno, NULL, NULL, NULL, NULL); + return 0; +} + +int +gf_utime_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + int op_errno = EINVAL; + int ret = -1; + + VALIDATE_OR_GOTO(frame, err); + VALIDATE_OR_GOTO(this, err); + VALIDATE_OR_GOTO(loc, err); + VALIDATE_OR_GOTO(loc->inode, err); + + xdata = xdata ? dict_ref(xdata) : dict_new(); + if (!xdata) { + op_errno = ENOMEM; + goto err; + } + + ret = dict_set_int8(xdata, GF_XATTR_MDATA_KEY, 1); + if (ret < 0) { + gf_msg(this->name, GF_LOG_WARNING, -ret, UTIME_MSG_DICT_SET_FAILED, + "%s: Unable to set dict value for %s", loc->path, + GF_XATTR_MDATA_KEY); + op_errno = -ret; + goto free_dict; + } + + STACK_WIND(frame, gf_utime_set_mdata_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); + dict_unref(xdata); + return 0; + +free_dict: + dict_unref(xdata); +err: + STACK_UNWIND_STRICT(lookup, frame, ret, op_errno, NULL, NULL, NULL, NULL); + return 0; +} + +int32_t init(xlator_t *this) { utime_priv_t *utime = NULL; @@ -182,19 +319,27 @@ notify(xlator_t *this, int event, void *data, ...) } struct xlator_fops fops = { - /* TODO: Need to go through other fops and - * check if they modify time attributes - */ - .rename = gf_utime_rename, .mknod = gf_utime_mknod, - .readv = gf_utime_readv, .fremovexattr = gf_utime_fremovexattr, - .open = gf_utime_open, .create = gf_utime_create, - .mkdir = gf_utime_mkdir, .writev = gf_utime_writev, - .rmdir = gf_utime_rmdir, .fallocate = gf_utime_fallocate, - .truncate = gf_utime_truncate, .symlink = gf_utime_symlink, - .zerofill = gf_utime_zerofill, .link = gf_utime_link, - .ftruncate = gf_utime_ftruncate, .unlink = gf_utime_unlink, - .setattr = gf_utime_setattr, .fsetattr = gf_utime_fsetattr, - .opendir = gf_utime_opendir, .removexattr = gf_utime_removexattr, + .rename = gf_utime_rename, + .mknod = gf_utime_mknod, + .readv = gf_utime_readv, + .fremovexattr = gf_utime_fremovexattr, + .open = gf_utime_open, + .create = gf_utime_create, + .mkdir = gf_utime_mkdir, + .writev = gf_utime_writev, + .rmdir = gf_utime_rmdir, + .fallocate = gf_utime_fallocate, + .truncate = gf_utime_truncate, + .symlink = gf_utime_symlink, + .zerofill = gf_utime_zerofill, + .link = gf_utime_link, + .ftruncate = gf_utime_ftruncate, + .unlink = gf_utime_unlink, + .setattr = gf_utime_setattr, + .fsetattr = gf_utime_fsetattr, + .opendir = gf_utime_opendir, + .removexattr = gf_utime_removexattr, + .lookup = gf_utime_lookup, }; struct xlator_cbks cbks = { .invalidate = gf_utime_invalidate, @@ -230,3 +375,18 @@ struct volume_options options[] = { "enabled. When noatime is on, atime is not updated with " "ctime feature enabled and vice versa."}, {.key = {NULL}}}; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {GD_OP_VERSION_5_0}, + .dumpops = &dumpops, + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "utime", + .category = GF_MAINTAINED, +}; diff --git a/xlators/features/utime/src/utime.h b/xlators/features/utime/src/utime.h index 236183d4bcc..ba55eec00de 100644 --- a/xlators/features/utime/src/utime.h +++ b/xlators/features/utime/src/utime.h @@ -11,9 +11,9 @@ #ifndef __UTIME_H__ #define __UTIME_H__ -#include "glusterfs.h" -#include "xlator.h" -#include "defaults.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/xlator.h> +#include <glusterfs/defaults.h> #include "utime-autogen-fops.h" typedef struct utime_priv { |
