diff --git a/sy_old/mars_light.c b/sy_old/mars_light.c index dfbc6d91..1b4977f9 100644 --- a/sy_old/mars_light.c +++ b/sy_old/mars_light.c @@ -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; diff --git a/sy_old/strategy.h b/sy_old/strategy.h index e5bde5b2..d2a4878f 100644 --- a/sy_old/strategy.h +++ b/sy_old/strategy.h @@ -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); diff --git a/sy_old/sy_generic.c b/sy_old/sy_generic.c index 261d825c..4a620342 100644 --- a/sy_old/sy_generic.c +++ b/sy_old/sy_generic.c @@ -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) { diff --git a/userspace/marsadm b/userspace/marsadm index b70cb634..d3ccf084 100644 --- a/userspace/marsadm +++ b/userspace/marsadm @@ -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