2014-11-21 10:51:34 +00:00
|
|
|
/*
|
|
|
|
* MARS Long Distance Replication Software
|
|
|
|
*
|
|
|
|
* This file is part of MARS project: http://schoebel.github.io/mars/
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010-2014 Thomas Schoebel-Theuer
|
|
|
|
* Copyright (C) 2011-2014 1&1 Internet AG
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
// OLD CODE => will disappear!
|
|
|
|
#ifndef _OLD_STRATEGY
|
|
|
|
#define _OLD_STRATEGY
|
|
|
|
|
|
|
|
#define _STRATEGY // call this only in strategy bricks, never in ordinary bricks
|
|
|
|
|
|
|
|
#include "../mars.h"
|
|
|
|
|
|
|
|
#define MARS_ARGV_MAX 4
|
|
|
|
|
2019-07-22 07:19:25 +00:00
|
|
|
/* This _should_ be updated when _compatible_ features
|
|
|
|
* are added. When somebody may _rely_ on the new feature,
|
|
|
|
* then this _must_ be updated.
|
|
|
|
*/
|
2020-07-30 05:22:08 +00:00
|
|
|
/* 1 = traditional
|
|
|
|
* 2 = push operation available
|
2020-08-01 20:47:19 +00:00
|
|
|
* 3 = new alivelinks residing in /mars/actual-$host
|
2020-07-30 05:22:08 +00:00
|
|
|
*/
|
2020-08-01 20:47:19 +00:00
|
|
|
#define OPTIONAL_STRATEGY_VERSION 3
|
2019-07-22 07:19:25 +00:00
|
|
|
|
2020-03-01 15:18:07 +00:00
|
|
|
/* transient, to re-disappear */
|
|
|
|
extern int compat_deletions;
|
|
|
|
|
2019-07-30 11:46:14 +00:00
|
|
|
extern int usable_strategy_version;
|
|
|
|
|
2020-08-10 17:35:57 +00:00
|
|
|
extern int mars_min_update;
|
|
|
|
|
2013-04-05 11:04:55 +00:00
|
|
|
extern loff_t global_total_space;
|
|
|
|
extern loff_t global_remaining_space;
|
|
|
|
|
2012-08-14 14:23:30 +00:00
|
|
|
extern int global_logrot_auto;
|
2013-04-05 11:04:55 +00:00
|
|
|
extern int global_free_space_0;
|
|
|
|
extern int global_free_space_1;
|
|
|
|
extern int global_free_space_2;
|
|
|
|
extern int global_free_space_3;
|
|
|
|
extern int global_free_space_4;
|
2014-02-15 16:48:54 +00:00
|
|
|
extern int global_sync_nr;
|
|
|
|
extern int global_sync_limit;
|
2013-04-05 07:27:59 +00:00
|
|
|
extern int mars_rollover_interval;
|
|
|
|
extern int mars_scan_interval;
|
|
|
|
extern int mars_propagate_interval;
|
|
|
|
extern int mars_sync_flip_interval;
|
2017-01-03 15:02:33 +00:00
|
|
|
extern int mars_running_additional_peers;
|
|
|
|
extern int mars_run_additional_peers;
|
2014-01-15 15:35:03 +00:00
|
|
|
extern int mars_peer_abort;
|
2013-04-05 11:04:55 +00:00
|
|
|
extern int mars_emergency_mode;
|
|
|
|
extern int mars_reset_emergency;
|
2014-02-06 14:03:46 +00:00
|
|
|
extern int mars_keep_msg;
|
2013-04-05 07:27:59 +00:00
|
|
|
|
|
|
|
extern int mars_fast_fullsync;
|
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
extern char *my_id(void);
|
|
|
|
|
2020-08-17 09:37:02 +00:00
|
|
|
struct mars_dent;
|
|
|
|
typedef void (*dent_skip_fn)(struct mars_dent *);
|
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
#define MARS_DENT(TYPE) \
|
|
|
|
struct list_head dent_link; \
|
2019-03-12 19:42:47 +00:00
|
|
|
struct list_head dent_hash_link; \
|
2019-03-12 13:25:04 +00:00
|
|
|
struct list_head dent_quick_link; \
|
2011-07-22 10:43:40 +00:00
|
|
|
struct list_head brick_list; \
|
|
|
|
struct TYPE *d_parent; \
|
2020-08-17 09:37:02 +00:00
|
|
|
dent_skip_fn d_skip_fn; \
|
2011-07-22 10:43:40 +00:00
|
|
|
char *d_argv[MARS_ARGV_MAX]; /* for internal use, will be automatically deallocated*/ \
|
|
|
|
char *d_args; /* ditto uninterpreted */ \
|
|
|
|
char *d_name; /* current path component */ \
|
|
|
|
char *d_rest; /* some "meaningful" rest of d_name*/ \
|
|
|
|
char *d_path; /* full absolute path */ \
|
2012-11-14 09:46:36 +00:00
|
|
|
struct say_channel *d_say_channel; /* for messages */ \
|
2014-03-30 06:18:47 +00:00
|
|
|
loff_t d_corr_A; /* logical size correction */ \
|
|
|
|
loff_t d_corr_B; /* logical size correction */ \
|
2020-09-15 07:36:45 +00:00
|
|
|
atomic_t d_count; \
|
2011-07-22 10:43:40 +00:00
|
|
|
int d_depth; \
|
|
|
|
unsigned int d_type; /* from readdir() => often DT_UNKNOWN => don't rely on it, use new_stat.mode instead */ \
|
|
|
|
int d_class; /* for pre-grouping order */ \
|
|
|
|
int d_serial; /* for pre-grouping order */ \
|
|
|
|
int d_version; /* dynamic programming per call of mars_ent_work() */ \
|
2014-02-20 15:59:37 +00:00
|
|
|
int d_child_count; \
|
2019-03-12 20:07:29 +00:00
|
|
|
int d_hash; \
|
2020-07-08 20:14:03 +00:00
|
|
|
int d_proto; \
|
2011-07-22 10:43:40 +00:00
|
|
|
char d_once_error; \
|
2020-08-17 09:37:02 +00:00
|
|
|
bool d_no_scan; \
|
|
|
|
bool d_running; \
|
2011-07-22 10:43:40 +00:00
|
|
|
bool d_killme; \
|
2012-11-14 09:46:36 +00:00
|
|
|
bool d_use_channel; \
|
2020-08-19 12:20:56 +00:00
|
|
|
bool d_unordered; \
|
2011-07-22 10:43:40 +00:00
|
|
|
struct kstat new_stat; \
|
|
|
|
struct kstat old_stat; \
|
|
|
|
char *new_link; \
|
|
|
|
char *old_link; \
|
2020-02-22 21:17:49 +00:00
|
|
|
struct mars_global *d_subtree; \
|
2012-11-19 10:55:38 +00:00
|
|
|
void (*d_private_destruct)(void *private); \
|
2011-07-22 10:43:40 +00:00
|
|
|
void *d_private;
|
|
|
|
|
|
|
|
struct mars_dent {
|
|
|
|
MARS_DENT(mars_dent);
|
|
|
|
};
|
|
|
|
|
|
|
|
extern const struct meta mars_kstat_meta[];
|
|
|
|
extern const struct meta mars_dent_meta[];
|
|
|
|
|
2020-08-20 08:11:32 +00:00
|
|
|
#define MARS_GLOBAL_HASH_BASE 16
|
|
|
|
#define MARS_GLOBAL_HASH_TABLE (PAGE_SIZE / sizeof(struct list_head))
|
|
|
|
#define MARS_GLOBAL_HASH (MARS_GLOBAL_HASH_BASE * MARS_GLOBAL_HASH_TABLE)
|
2019-03-12 19:42:47 +00:00
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
struct mars_global {
|
|
|
|
struct rw_semaphore dent_mutex;
|
|
|
|
struct rw_semaphore brick_mutex;
|
|
|
|
struct generic_switch global_power;
|
|
|
|
struct list_head dent_anchor;
|
2019-03-12 13:25:04 +00:00
|
|
|
struct list_head dent_quick_anchor;
|
2011-07-22 10:43:40 +00:00
|
|
|
struct list_head brick_anchor;
|
|
|
|
wait_queue_head_t main_event;
|
2011-10-10 13:03:10 +00:00
|
|
|
int global_version;
|
2014-03-15 19:20:05 +00:00
|
|
|
int deleted_my_border;
|
2017-12-12 23:53:56 +00:00
|
|
|
int old_deleted_my_border;
|
2012-02-01 14:05:49 +00:00
|
|
|
int deleted_border;
|
|
|
|
int deleted_min;
|
2020-02-26 10:24:37 +00:00
|
|
|
int trigger_mode;
|
2012-02-01 12:47:35 +00:00
|
|
|
bool main_trigger;
|
2020-08-20 08:11:32 +00:00
|
|
|
struct list_head *dent_hash_table[MARS_GLOBAL_HASH_BASE];
|
2011-07-22 10:43:40 +00:00
|
|
|
};
|
|
|
|
|
2019-08-13 10:14:14 +00:00
|
|
|
extern void _init_mars_global(struct mars_global *global);
|
2020-08-20 08:11:32 +00:00
|
|
|
extern void exit_mars_global(struct mars_global *global);
|
|
|
|
|
2019-08-13 10:14:14 +00:00
|
|
|
#define init_mars_global(__global) \
|
|
|
|
do { \
|
|
|
|
_init_mars_global(__global); \
|
|
|
|
init_rwsem(&(__global)->dent_mutex); \
|
|
|
|
init_rwsem(&(__global)->brick_mutex); \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define alloc_mars_global() \
|
|
|
|
({ \
|
|
|
|
struct mars_global *__global; \
|
|
|
|
\
|
|
|
|
__global = brick_mem_alloc(sizeof(struct mars_global)); \
|
|
|
|
init_mars_global(__global); \
|
|
|
|
__global; \
|
|
|
|
})
|
|
|
|
|
2020-08-20 08:11:32 +00:00
|
|
|
#define free_mars_global(_global_) \
|
|
|
|
({ \
|
|
|
|
exit_mars_global(_global_); \
|
|
|
|
brick_mem_free(_global_); \
|
|
|
|
})
|
|
|
|
|
2012-11-14 09:46:36 +00:00
|
|
|
extern void bind_to_dent(struct mars_dent *dent, struct say_channel **ch);
|
|
|
|
|
|
|
|
typedef int (*mars_dent_checker_fn)(struct mars_dent *parent, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial, bool *use_channel);
|
2011-10-24 10:54:15 +00:00
|
|
|
typedef int (*mars_dent_worker_fn)(struct mars_global *global, struct mars_dent *dent, bool prepare, bool direction);
|
2011-07-22 10:43:40 +00:00
|
|
|
|
2020-02-23 14:38:55 +00:00
|
|
|
extern int mars_dent_work(struct mars_global *global,
|
|
|
|
char *dirname,
|
|
|
|
int allocsize,
|
|
|
|
mars_dent_checker_fn checker,
|
|
|
|
mars_dent_worker_fn worker,
|
|
|
|
void *buf,
|
|
|
|
int maxdepth,
|
|
|
|
bool use_subtree);
|
2020-03-06 18:00:39 +00:00
|
|
|
extern int mars_get_dent_list(struct mars_global *global,
|
2020-07-17 07:40:34 +00:00
|
|
|
const char *path_list,
|
2020-03-06 18:00:39 +00:00
|
|
|
int allocsize,
|
|
|
|
mars_dent_checker_fn checker,
|
|
|
|
int maxdepth);
|
2011-07-22 10:43:40 +00:00
|
|
|
extern struct mars_dent *mars_find_dent(struct mars_global *global, const char *path);
|
2019-03-12 13:36:25 +00:00
|
|
|
extern void mars_kill_dent(struct mars_global *global, struct mars_dent *dent);
|
|
|
|
extern void mars_free_dent(struct mars_global *global, struct mars_dent *dent);
|
2011-09-27 08:46:14 +00:00
|
|
|
extern void mars_free_dent_all(struct mars_global *global, struct list_head *anchor);
|
2011-07-22 10:43:40 +00:00
|
|
|
|
|
|
|
// low-level brick instantiation
|
|
|
|
|
2016-12-31 21:57:07 +00:00
|
|
|
int mars_connect(struct mars_input *a, struct mars_output *b);
|
|
|
|
int mars_disconnect(struct mars_input *a);
|
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
extern struct mars_brick *mars_find_brick(struct mars_global *global, const void *brick_type, const char *path);
|
2013-05-09 16:59:09 +00:00
|
|
|
extern struct mars_brick *mars_make_brick(struct mars_global *global, struct mars_dent *belongs, const void *_brick_type, const char *path, const char *name);
|
2011-07-22 10:43:40 +00:00
|
|
|
extern int mars_free_brick(struct mars_brick *brick);
|
|
|
|
extern int mars_kill_brick(struct mars_brick *brick);
|
2011-08-31 11:42:04 +00:00
|
|
|
extern int mars_kill_brick_all(struct mars_global *global, struct list_head *anchor, bool use_dent_link);
|
2020-03-07 05:28:27 +00:00
|
|
|
extern int mars_kill_brick_when_possible(struct mars_global *global,
|
2020-03-07 06:07:52 +00:00
|
|
|
const struct mars_brick_type *type_list[],
|
2020-03-07 05:28:27 +00:00
|
|
|
bool even_on);
|
2011-07-22 10:43:40 +00:00
|
|
|
|
|
|
|
// mid-level brick instantiation (identity is based on path strings)
|
|
|
|
|
2012-11-19 10:31:55 +00:00
|
|
|
extern char *_vpath_make(int line, const char *fmt, va_list *args);
|
|
|
|
extern char *_path_make(int line, const char *fmt, ...);
|
|
|
|
extern char *_backskip_replace(int line, const char *path, char delim, bool insert, const char *fmt, ...);
|
|
|
|
|
|
|
|
#define vpath_make(_fmt, _args) \
|
|
|
|
_vpath_make(__LINE__, _fmt, _args)
|
|
|
|
#define path_make(_fmt, _args...) \
|
|
|
|
_path_make(__LINE__, _fmt, ##_args)
|
|
|
|
#define backskip_replace(_path, _delim, _insert, _fmt, _args...) \
|
|
|
|
_backskip_replace(__LINE__, _path, _delim, _insert, _fmt, ##_args)
|
2011-07-22 10:43:40 +00:00
|
|
|
|
|
|
|
extern struct mars_brick *path_find_brick(struct mars_global *global, const void *brick_type, const char *fmt, ...);
|
|
|
|
|
|
|
|
/* Create a new brick and connect its inputs to a set of predecessors.
|
|
|
|
* When @timeout > 0, switch on the brick as well as its predecessors.
|
|
|
|
*/
|
|
|
|
extern struct mars_brick *make_brick_all(
|
|
|
|
struct mars_global *global,
|
|
|
|
struct mars_dent *belongs,
|
2011-08-25 10:16:32 +00:00
|
|
|
int (*setup_fn)(struct mars_brick *brick, void *private),
|
2011-07-22 10:43:40 +00:00
|
|
|
void *private,
|
|
|
|
const char *new_name,
|
|
|
|
const struct generic_brick_type *new_brick_type,
|
|
|
|
const struct generic_brick_type *prev_brick_type[],
|
2013-05-10 06:15:00 +00:00
|
|
|
int switch_override, // -1 = off, 0 = leave in current state, +1 = create when necessary, +2 = create + switch on
|
2011-07-22 10:43:40 +00:00
|
|
|
const char *new_fmt,
|
|
|
|
const char *prev_fmt[],
|
|
|
|
int prev_count,
|
|
|
|
...
|
|
|
|
);
|
|
|
|
|
|
|
|
// general MARS infrastructure
|
|
|
|
|
|
|
|
#define MARS_ERR_ONCE(dent, args...) if (!dent->d_once_error++) MARS_ERR(args)
|
|
|
|
|
2020-08-27 11:37:44 +00:00
|
|
|
static inline
|
|
|
|
bool is_deleted_link(const char *str)
|
|
|
|
{
|
|
|
|
return (!str || !str[0]);
|
|
|
|
}
|
|
|
|
|
2020-07-17 08:20:44 +00:00
|
|
|
bool push_link(const char *peer_name,
|
|
|
|
const char *src,
|
|
|
|
const char *dst);
|
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
/* General fs wrappers (for abstraction)
|
|
|
|
*/
|
2020-07-31 06:07:08 +00:00
|
|
|
extern bool mars_is_mountpoint(const char *pathname);
|
2011-07-22 10:43:40 +00:00
|
|
|
extern int mars_stat(const char *path, struct kstat *stat, bool use_lstat);
|
light: fix missing versionlink upon slow or defective IO
Some primary appeared to have died, and was rebooted.
In the meantime, the old secondary was forcefully switched
to primary.
Afterwards, the old primary = new secondary got stuck because 2
versionlinks, which had been _produced_ by _himself_, were
missing, but they were present at the new primary = old secondary!
How could this happen?
All transaction logfiles were fully present and correct everywhere.
However, the old primary kern.log showed that a problem with the
RAID system must have existed. In addition, the RAID controller
errorlog also reported some problems which appeared to have healed.
Problem analysis shows the following possibility:
The transaction logger can continue to write data, even via
fsync(), while the _writeback_ of other parts of the /mars filesystem
(e.g. symlink updates) got stuck for a long time due to an IO problem.
Usually, slow or even missing symlink updates are no problem because
upon recovery after a reboot, everything is healed by transaction
replay (possibly replaying much more data than really necessary,
but this does not affect semantics, and it is even advantageous
when RAID disks might contain defective data).
There is one exception: after a logrotate, the corresponding new
versionlink should appear after a small time. Otherwise, the
above mentioned scenario could emerge.
We use sync_filesystem() to ensure that any versionlink update
to a _new_ versionlink is either guaranteed to become persistent,
or (in case of IO problems) the mars_light thread will hang, which
will be (hopefully) noticed soon by monitoring.
2016-01-29 06:59:54 +00:00
|
|
|
extern void mars_sync(void);
|
2011-07-22 10:43:40 +00:00
|
|
|
extern int mars_mkdir(const char *path);
|
2013-06-26 13:18:32 +00:00
|
|
|
extern int mars_rmdir(const char *path);
|
2011-10-24 10:54:15 +00:00
|
|
|
extern int mars_unlink(const char *path);
|
2020-08-10 17:35:57 +00:00
|
|
|
extern char *mars_readlink(const char *newpath, struct lamport_time *stamp);
|
2011-07-22 10:43:40 +00:00
|
|
|
extern int mars_rename(const char *oldpath, const char *newpath);
|
|
|
|
extern int mars_chmod(const char *path, mode_t mode);
|
2012-01-23 17:40:15 +00:00
|
|
|
extern void mars_remaining_space(const char *fspath, loff_t *total, loff_t *remaining);
|
2011-07-22 10:43:40 +00:00
|
|
|
|
2018-03-12 12:06:31 +00:00
|
|
|
/* Timestamp Ordering */
|
|
|
|
|
2020-03-01 13:55:44 +00:00
|
|
|
#define MARS_DELETED_STR ".deleted"
|
|
|
|
|
2020-08-10 17:35:57 +00:00
|
|
|
extern char *ordered_readlink(const char *path, struct lamport_time *stamp);
|
2020-03-01 13:55:44 +00:00
|
|
|
|
2019-02-19 09:18:29 +00:00
|
|
|
extern int ordered_unlink(const char *path,
|
|
|
|
const struct lamport_time *stamp,
|
|
|
|
int serial,
|
|
|
|
int mode);
|
|
|
|
extern int ordered_symlink(const char *oldpath,
|
|
|
|
const char *newpath,
|
2020-03-24 07:20:39 +00:00
|
|
|
const struct lamport_time *stamp);
|
2018-03-12 12:06:31 +00:00
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
extern struct mars_global *mars_global;
|
|
|
|
|
2013-05-09 09:40:02 +00:00
|
|
|
extern bool mars_check_inputs(struct mars_brick *brick);
|
|
|
|
extern bool mars_check_outputs(struct mars_brick *brick);
|
|
|
|
|
2011-07-22 10:43:40 +00:00
|
|
|
extern int mars_power_button(struct mars_brick *brick, bool val, bool force_off);
|
|
|
|
|
2011-08-25 10:16:32 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2013-01-22 10:30:52 +00:00
|
|
|
// statistics
|
|
|
|
|
|
|
|
extern int global_show_statist;
|
2013-04-11 12:58:36 +00:00
|
|
|
extern int global_show_connections;
|
2013-01-22 10:30:52 +00:00
|
|
|
|
|
|
|
void show_statistics(struct mars_global *global, const char *class);
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-02-08 18:12:57 +00:00
|
|
|
// quirk
|
|
|
|
|
2012-08-08 09:16:52 +00:00
|
|
|
extern int mars_mem_percent;
|
2019-06-25 05:42:20 +00:00
|
|
|
extern int mars_mem_gb;
|
2012-08-08 09:16:52 +00:00
|
|
|
|
2016-03-03 07:57:07 +00:00
|
|
|
extern int main_checker(struct mars_dent *parent, const char *_name, int namlen, unsigned int d_type, int *prefix, int *serial, bool *use_channel);
|
2012-12-18 05:31:24 +00:00
|
|
|
|
2012-02-08 18:12:57 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-08-25 10:16:32 +00:00
|
|
|
// init
|
|
|
|
|
|
|
|
extern int init_sy(void);
|
|
|
|
extern void exit_sy(void);
|
|
|
|
|
|
|
|
extern int init_sy_net(void);
|
|
|
|
extern void exit_sy_net(void);
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|