introduced "marsadm log-delete"

TBD: "marsadm log-purge"
TBD: long-term cleanup of symlinks in /mars/todo-global/
This commit is contained in:
Thomas Schoebel-Theuer 2011-10-24 12:54:15 +02:00 committed by Thomas Schoebel-Theuer
parent 6127f1d14c
commit 977e5a3b3a
4 changed files with 158 additions and 11 deletions

View File

@ -55,6 +55,7 @@ struct light_class {
bool cl_hostcontext;
bool cl_serial;
int cl_father;
light_worker_fn cl_prepare;
light_worker_fn cl_forward;
light_worker_fn cl_backward;
};
@ -2406,12 +2407,57 @@ done:
return status;
}
static int prepare_delete(void *buf, struct mars_dent *dent)
{
struct mars_global *global = buf;
struct mars_dent *target;
struct mars_dent *response;
const char *response_path = NULL;
int max_serial = 0;
if (!global || !dent || !dent->new_link) {
goto done;
}
target = _mars_find_dent(global, dent->new_link);
if (target) {
mars_unlink(dent->new_link);
target->d_killme = true;
MARS_DBG("target '%s' deleted and marked for removal\n", dent->new_link);
} else {
MARS_DBG("target '%s' does no longer exist\n", dent->new_link);
}
response_path = path_make("/mars/todo-global/deleted-%s", my_id());
if (!response_path) {
MARS_ERR("cannot build response path for '%s'\n", dent->new_link);
goto done;
}
response = _mars_find_dent(global, response_path);
if (response && response->new_link) {
sscanf(response->new_link, "%d", &max_serial);
}
if (dent->d_serial > max_serial) {
char response_val[16];
max_serial = dent->d_serial;
snprintf(response_val, sizeof(response_val), "%09d", max_serial);
mars_symlink(response_val, response_path, NULL, 0);
}
done:
brick_string_free(response_path);
return 0;
}
///////////////////////////////////////////////////////////////////////
// the order is important!
enum {
// root element: this must have index 0
CL_ROOT,
// global todos
CL_GLOBAL_TODO,
CL_GLOBAL_TODO_DELETE,
CL_GLOBAL_TODO_ITEMS,
// replacement for DNS in kernelspace
CL_IPS,
CL_PEERS,
@ -2448,6 +2494,32 @@ static const struct light_class light_classes[] = {
[CL_ROOT] = {
},
/* Subdirectory for global controlling items...
*/
[CL_GLOBAL_TODO] = {
.cl_name = "todo-global",
.cl_len = 11,
.cl_type = 'd',
.cl_hostcontext = false,
.cl_father = CL_ROOT,
},
/* ... and its contents
*/
[CL_GLOBAL_TODO_DELETE] = {
.cl_name = "delete-",
.cl_len = 7,
.cl_type = 'l',
.cl_serial = true,
.cl_father = CL_GLOBAL_TODO,
.cl_prepare = prepare_delete,
},
[CL_GLOBAL_TODO_ITEMS] = {
.cl_name = "",
.cl_len = 0, // catch any
.cl_type = 'l',
.cl_father = CL_GLOBAL_TODO,
},
/* Directory containing the addresses of all peers
*/
[CL_IPS] = {
@ -2798,7 +2870,7 @@ done:
/* Do some syntactic checks, then delegate work to the real worker functions
* from the light_classes[] table.
*/
static int light_worker(struct mars_global *global, struct mars_dent *dent, bool direction)
static int light_worker(struct mars_global *global, struct mars_dent *dent, bool prepare, bool direction)
{
light_worker_fn worker;
int class = dent->d_class;
@ -2845,7 +2917,9 @@ static int light_worker(struct mars_global *global, struct mars_dent *dent, bool
return -EINVAL;
}
}
if (direction) {
if (prepare) {
worker = light_classes[class].cl_prepare;
} else if (direction) {
worker = light_classes[class].cl_backward;
} else {
worker = light_classes[class].cl_forward;

View File

@ -57,10 +57,11 @@ struct mars_global {
int global_version;
};
typedef int (*mars_dent_checker)(struct mars_dent *parent, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial);
typedef int (*mars_dent_worker)(struct mars_global *global, struct mars_dent *dent, bool direction);
typedef int (*mars_dent_checker_fn)(struct mars_dent *parent, const char *name, int namlen, unsigned int d_type, int *prefix, int *serial);
typedef int (*mars_dent_worker_fn)(struct mars_global *global, struct mars_dent *dent, bool prepare, bool direction);
extern int mars_dent_work(struct mars_global *global, char *dirname, int allocsize, mars_dent_checker checker, mars_dent_worker worker, void *buf, int maxdepth);
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);
extern struct mars_dent *_mars_find_dent(struct mars_global *global, const char *path);
extern struct mars_dent *mars_find_dent(struct mars_global *global, const char *path);
extern int mars_find_dent_all(struct mars_global *global, char *prefix, struct mars_dent ***table);
extern void mars_kill_dent(struct mars_dent *dent);
@ -112,6 +113,7 @@ extern struct mars_brick *make_brick_all(
*/
extern int mars_stat(const char *path, struct kstat *stat, bool use_lstat);
extern int mars_mkdir(const char *path);
extern int mars_unlink(const char *path);
extern int mars_symlink(const char *oldpath, const char *newpath, const struct timespec *stamp, uid_t uid);
extern int mars_rename(const char *oldpath, const char *newpath);
extern int mars_chmod(const char *path, mode_t mode);

View File

@ -96,6 +96,20 @@ int mars_mkdir(const char *path)
}
EXPORT_SYMBOL_GPL(mars_mkdir);
int mars_unlink(const char *path)
{
mm_segment_t oldfs;
int status;
oldfs = get_fs();
set_fs(get_ds());
status = sys_unlink(path);
set_fs(oldfs);
return status;
}
EXPORT_SYMBOL_GPL(mars_unlink);
int mars_symlink(const char *oldpath, const char *newpath, const struct timespec *stamp, uid_t uid)
{
char *tmp = backskip_replace(newpath, '/', true, "/.tmp-");
@ -270,7 +284,7 @@ EXPORT_SYMBOL_GPL(mars_power_button_recursive);
struct mars_cookie {
struct mars_global *global;
mars_dent_checker checker;
mars_dent_checker_fn checker;
char *path;
struct mars_dent *parent;
int pathlen;
@ -479,7 +493,7 @@ static int _mars_readdir(struct mars_cookie *cookie)
return status;
}
int mars_dent_work(struct mars_global *global, char *dirname, int allocsize, mars_dent_checker checker, mars_dent_worker worker, void *buf, int maxdepth)
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)
{
static int version = 0;
struct mars_cookie cookie = {
@ -555,6 +569,20 @@ restart:
goto restart;
}
/* Preparation pass.
* Here is a chance to mark some dents for removal
* (or other types of non-destructive operations)
*/
for (tmp = global->dent_anchor.next, next = tmp->next; tmp != &global->dent_anchor; tmp = next, next = next->next) {
struct mars_dent *dent = container_of(tmp, struct mars_dent, dent_link);
msleep(10); // yield
MARS_IO("forward prepare '%s'\n", dent->d_path);
status = worker(buf, dent, true, false);
if (status)
MARS_IO("forward treat '%s' status = %d\n", dent->d_path, status);
total_status |= status;
}
/* Remove all dents marked for removal.
*/
for (tmp = global->dent_anchor.next, next = tmp->next; tmp != &global->dent_anchor; tmp = next, next = next->next) {
@ -576,7 +604,7 @@ restart:
up_read(&global->dent_mutex);
msleep(10); // yield
MARS_IO("forward treat '%s'\n", dent->d_path);
status = worker(buf, dent, false);
status = worker(buf, dent, false, false);
if (status)
MARS_IO("forward treat '%s' status = %d\n", dent->d_path, status);
down_read(&global->dent_mutex);
@ -590,7 +618,7 @@ restart:
up_read(&global->dent_mutex);
msleep(10); // yield
MARS_IO("backward treat '%s'\n", dent->d_path);
status = worker(buf, dent, true);
status = worker(buf, dent, false, true);
if (status)
MARS_IO("backward treat '%s' status = %d\n", dent->d_path, status);
down_read(&global->dent_mutex);
@ -607,7 +635,6 @@ done:
}
EXPORT_SYMBOL_GPL(mars_dent_work);
static
struct mars_dent *_mars_find_dent(struct mars_global *global, const char *path)
{
struct mars_dent *res = NULL;
@ -627,7 +654,7 @@ struct mars_dent *_mars_find_dent(struct mars_global *global, const char *path)
return res;
}
//EXPORT_SYMBOL_GPL(_mars_find_dent);
EXPORT_SYMBOL_GPL(_mars_find_dent);
struct mars_dent *mars_find_dent(struct mars_global *global, const char *path)
{

View File

@ -229,6 +229,7 @@ sub _create_cluster {
system("mkdir $mars/ips") unless -d "$mars/ips";
system("mkdir $mars/defaults") unless -d "$mars/defaults";
system("mkdir $mars/defaults-$host") unless -d "$mars/defaults-$host";
system("mkdir $mars/todo-global") unless -d "$mars/todo-global";
symlink($ip, "$mars/ips/ip-$host");
}
@ -375,6 +376,46 @@ sub logrotate_res {
system("touch $next");
}
sub _allowed_logdelete {
my ($cmd, $res) = @_;
my $max = -1;
my @paths = glob("$mars/resource-$res/replay-*") or die "cannot find any replay symlinks\n";
foreach my $path (@paths) {
my $target = readlink($path) or die "cannot read symlink '$path'\n";
my $nr = $target;
$nr =~ s/^.*log-([0-9]+)-.+$/$1/;
$max = $nr if $nr > $max;
}
return $max;
}
sub _create_delete {
my ($target) = @_;
my $nr = 0;
my @paths = glob("$mars/todo-global/delete-*");
if(@paths) {
my $last = pop(@paths);
$nr = $last;
$nr =~ s/^.*delete-([0-9]+)$/$1/;
}
my $new = sprintf("$mars/todo-global/delete-%09d", $nr + 1);
print "create symlink $new -> $target\n";
symlink($target, $new);
}
sub logdelete_res {
my ($cmd, $res) = @_;
my @paths = glob("$mars/resource-$res/log-*-$host") or die "cannot find any logfiles\n";
@paths = sort(@paths);
my $first = shift(@paths);
print "chosen '$first' for deletion\n";
my $nr = $first;
$nr =~ s/^.*log-([0-9]+)-.+$/$1/;
my $max = _allowed_logdelete(@_);
die "only logfile numbers smaller than $max are allowed to be deleted\n" unless $nr < $max;
_create_delete($first);
}
sub attach_res {
my ($cmd, $res) = @_;
my $detach = ($cmd eq "detach");
@ -523,6 +564,9 @@ my %cmd_table =
"create-resource" => \&create_res,
"join-resource" => \&create_res,
"logrotate" => \&logrotate_res,
"log-rotate" => \&logrotate_res,
"logdelete" => \&logdelete_res,
"log-delete" => \&logdelete_res,
"fake-sync" => \&fake_local_res,
# compatible keywords