glusterfs
352 строки · 8.7 Кб
1/*
2Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
3This file is part of GlusterFS.
4
5This file is licensed to you under your choice of the GNU Lesser
6General Public License, version 3 or any later version (LGPLv3 or
7later), or the GNU General Public License, version 2 (GPLv2), in all
8cases as published by the Free Software Foundation.
9*/
10
11#include <pthread.h>12
13#include "glusterfs/syncop.h"14#include "glusterfs/libglusterfs-messages.h"15
16const char *gf_fop_list[GF_FOP_MAXVALUE] = {17[GF_FOP_NULL] = "NULL",18[GF_FOP_STAT] = "STAT",19[GF_FOP_READLINK] = "READLINK",20[GF_FOP_MKNOD] = "MKNOD",21[GF_FOP_MKDIR] = "MKDIR",22[GF_FOP_UNLINK] = "UNLINK",23[GF_FOP_RMDIR] = "RMDIR",24[GF_FOP_SYMLINK] = "SYMLINK",25[GF_FOP_RENAME] = "RENAME",26[GF_FOP_LINK] = "LINK",27[GF_FOP_TRUNCATE] = "TRUNCATE",28[GF_FOP_OPEN] = "OPEN",29[GF_FOP_READ] = "READ",30[GF_FOP_WRITE] = "WRITE",31[GF_FOP_STATFS] = "STATFS",32[GF_FOP_FLUSH] = "FLUSH",33[GF_FOP_FSYNC] = "FSYNC",34[GF_FOP_SETXATTR] = "SETXATTR",35[GF_FOP_GETXATTR] = "GETXATTR",36[GF_FOP_REMOVEXATTR] = "REMOVEXATTR",37[GF_FOP_OPENDIR] = "OPENDIR",38[GF_FOP_FSYNCDIR] = "FSYNCDIR",39[GF_FOP_ACCESS] = "ACCESS",40[GF_FOP_CREATE] = "CREATE",41[GF_FOP_FTRUNCATE] = "FTRUNCATE",42[GF_FOP_FSTAT] = "FSTAT",43[GF_FOP_LK] = "LK",44[GF_FOP_LOOKUP] = "LOOKUP",45[GF_FOP_READDIR] = "READDIR",46[GF_FOP_INODELK] = "INODELK",47[GF_FOP_FINODELK] = "FINODELK",48[GF_FOP_ENTRYLK] = "ENTRYLK",49[GF_FOP_FENTRYLK] = "FENTRYLK",50[GF_FOP_XATTROP] = "XATTROP",51[GF_FOP_FXATTROP] = "FXATTROP",52[GF_FOP_FSETXATTR] = "FSETXATTR",53[GF_FOP_FGETXATTR] = "FGETXATTR",54[GF_FOP_RCHECKSUM] = "RCHECKSUM",55[GF_FOP_SETATTR] = "SETATTR",56[GF_FOP_FSETATTR] = "FSETATTR",57[GF_FOP_READDIRP] = "READDIRP",58[GF_FOP_GETSPEC] = "GETSPEC",59[GF_FOP_FORGET] = "FORGET",60[GF_FOP_RELEASE] = "RELEASE",61[GF_FOP_RELEASEDIR] = "RELEASEDIR",62[GF_FOP_FREMOVEXATTR] = "FREMOVEXATTR",63[GF_FOP_FALLOCATE] = "FALLOCATE",64[GF_FOP_DISCARD] = "DISCARD",65[GF_FOP_ZEROFILL] = "ZEROFILL",66[GF_FOP_IPC] = "IPC",67[GF_FOP_SEEK] = "SEEK",68[GF_FOP_LEASE] = "LEASE",69[GF_FOP_COMPOUND] = "COMPOUND",70[GF_FOP_GETACTIVELK] = "GETACTIVELK",71[GF_FOP_SETACTIVELK] = "SETACTIVELK",72[GF_FOP_PUT] = "PUT",73[GF_FOP_ICREATE] = "ICREATE",74[GF_FOP_NAMELINK] = "NAMELINK",75[GF_FOP_COPY_FILE_RANGE] = "COPY_FILE_RANGE",76};77
78const char *gf_upcall_list[GF_UPCALL_FLAGS_MAXVALUE] = {79[GF_UPCALL_NULL] = "NULL",80[GF_UPCALL] = "UPCALL",81[GF_UPCALL_CI_STAT] = "CI_IATT",82[GF_UPCALL_CI_XATTR] = "CI_XATTR",83[GF_UPCALL_CI_RENAME] = "CI_RENAME",84[GF_UPCALL_CI_NLINK] = "CI_UNLINK",85[GF_UPCALL_CI_FORGET] = "CI_FORGET",86[GF_UPCALL_LEASE_RECALL] = "LEASE_RECALL",87};88
89/* THIS */
90
91/* This global ctx is a bad hack to prevent some of the libgfapi crashes.
92* This should be removed once the patch on resource pool is accepted
93*/
94pthread_mutex_t global_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;95xlator_t global_xlator;96static int gf_global_mem_acct_enable = 1;97static pthread_once_t globals_inited = PTHREAD_ONCE_INIT;98
99static pthread_key_t free_key;100
101static __thread xlator_t *thread_xlator = NULL;102static __thread void *thread_synctask = NULL;103static __thread void *thread_leaseid = NULL;104static __thread struct syncopctx thread_syncopctx = {};105static __thread char thread_uuid_buf[GF_UUID_BUF_SIZE] = {};106static __thread char thread_lkowner_buf[GF_LKOWNER_BUF_SIZE] = {};107static __thread char thread_leaseid_buf[GF_LEASE_ID_BUF_SIZE] = {};108
109int
110gf_global_mem_acct_enable_get(void)111{
112return gf_global_mem_acct_enable;113}
114
115int
116gf_global_mem_acct_enable_set(int val)117{
118gf_global_mem_acct_enable = val;119return 0;120}
121
122static struct xlator_cbks global_cbks = {123.forget = NULL,124.release = NULL,125.releasedir = NULL,126.invalidate = NULL,127.client_destroy = NULL,128.client_disconnect = NULL,129.ictxmerge = NULL,130.ictxsize = NULL,131.fdctxsize = NULL,132};133
134/* This is required to get through the check in graph.c */
135static struct xlator_fops global_fops = {};136
137static int138global_xl_reconfigure(xlator_t *this, dict_t *options)139{
140int ret = -1;141gf_boolean_t bool_opt = _gf_false;142
143/* This is not added in volume dump, hence adding the options in log144would be helpful for debugging later */
145dict_dump_to_log(options);146
147GF_OPTION_RECONF("measure-latency", bool_opt, options, bool, out);148this->ctx->measure_latency = bool_opt;149
150GF_OPTION_RECONF("metrics-dump-path", this->ctx->config.metrics_dumppath,151options, str, out);152
153/* TODO: add more things here */154ret = 0;155out:156return ret;157}
158
159static int160global_xl_init(xlator_t *this)161{
162int ret = -1;163gf_boolean_t bool_opt = false;164
165GF_OPTION_INIT("measure-latency", bool_opt, bool, out);166this->ctx->measure_latency = bool_opt;167
168GF_OPTION_INIT("metrics-dump-path", this->ctx->config.metrics_dumppath, str,169out);170
171ret = 0;172
173out:174return ret;175}
176
177static void178global_xl_fini(xlator_t *this)179{
180return;181}
182
183struct volume_options global_xl_options[] = {184{.key = {"measure-latency"},185.type = GF_OPTION_TYPE_BOOL,186.default_value = "no",187.op_version = {GD_OP_VERSION_4_0_0},188.flags = OPT_FLAG_SETTABLE,189.tags = {"global", "context"},190.description = "Use this option to toggle measuring latency"},191{.key = {"metrics-dump-path"},192.type = GF_OPTION_TYPE_STR,193.default_value = "{{gluster_workdir}}/metrics",194.op_version = {GD_OP_VERSION_4_0_0},195.flags = OPT_FLAG_SETTABLE,196.tags = {"global", "context"},197.description = "Use this option to set the metrics dump path"},198
199{200.key = {NULL},201},202};203
204static volume_opt_list_t global_xl_opt_list;205
206void
207glusterfs_this_init(void)208{
209global_xlator.name = "glusterfs";210global_xlator.type = GF_GLOBAL_XLATOR_NAME;211global_xlator.cbks = &global_cbks;212global_xlator.fops = &global_fops;213global_xlator.reconfigure = global_xl_reconfigure;214global_xlator.init = global_xl_init;215global_xlator.fini = global_xl_fini;216
217INIT_LIST_HEAD(&global_xlator.volume_options);218INIT_LIST_HEAD(&global_xl_opt_list.list);219global_xl_opt_list.given_opt = global_xl_options;220
221list_add_tail(&global_xl_opt_list.list, &global_xlator.volume_options);222}
223
224xlator_t **225__glusterfs_this_location(void)226{
227xlator_t **this_location;228
229this_location = &thread_xlator;230if (*this_location == NULL) {231thread_xlator = &global_xlator;232}233return this_location;234}
235
236/* SYNCOPCTX */
237
238void *239syncopctx_getctx(void)240{
241return &thread_syncopctx;242}
243
244/* SYNCTASK */
245
246void *247synctask_get(void)248{
249return thread_synctask;250}
251
252void
253synctask_set(void *synctask)254{
255thread_synctask = synctask;256}
257
258// UUID_BUFFER
259
260char *261glusterfs_uuid_buf_get(void)262{
263return thread_uuid_buf;264}
265
266/* LKOWNER_BUFFER */
267
268char *269glusterfs_lkowner_buf_get(void)270{
271return thread_lkowner_buf;272}
273
274/* Leaseid buffer */
275
276char *277glusterfs_leaseid_buf_get(void)278{
279char *buf = NULL;280
281buf = thread_leaseid;282if (buf == NULL) {283buf = thread_leaseid_buf;284thread_leaseid = buf;285}286
287return buf;288}
289
290char *291glusterfs_leaseid_exist(void)292{
293return thread_leaseid;294}
295
296static void297glusterfs_cleanup(void *ptr)298{
299if (thread_syncopctx.groups != NULL) {300GF_FREE(thread_syncopctx.groups);301}302
303mem_pool_thread_destructor(NULL);304}
305
306void
307gf_thread_needs_cleanup(void)308{
309/* The value stored in free_key TLS is not really used for anything, but310* pthread implementation doesn't call the TLS destruction function unless
311* it's != NULL. This function must be called whenever something is
312* allocated for this thread so that glusterfs_cleanup() will be called
313* and resources can be released. */
314(void)pthread_setspecific(free_key, (void *)1);315}
316
317static void318gf_globals_init_once(void)319{
320int ret = 0;321
322glusterfs_this_init();323
324/* This is needed only to cleanup the potential allocation of325* thread_syncopctx.groups. */
326ret = pthread_key_create(&free_key, glusterfs_cleanup);327if (ret != 0) {328gf_msg("", GF_LOG_ERROR, ret, LG_MSG_PTHREAD_KEY_CREATE_FAILED,329"failed to create the pthread key");330
331gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_GLOBAL_INIT_FAILED,332"Exiting as global initialization failed");333
334exit(ret);335}336}
337
338int
339glusterfs_globals_init(glusterfs_ctx_t *ctx)340{
341int ret = 0;342
343gf_log_globals_init(ctx, GF_LOG_INFO);344
345ret = pthread_once(&globals_inited, gf_globals_init_once);346
347if (ret)348gf_msg("", GF_LOG_CRITICAL, ret, LG_MSG_PTHREAD_FAILED,349"pthread_once failed");350
351return ret;352}
353