X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/0e33f7f87f55a9458bd0b5308004d46c8f327b2a..bdc54107c5a7268f3a700335389bf494df136bf7:/sbin/hammer/cmd_cleanup.c diff --git a/sbin/hammer/cmd_cleanup.c b/sbin/hammer/cmd_cleanup.c index de830a7335..83426842ef 100644 --- a/sbin/hammer/cmd_cleanup.c +++ b/sbin/hammer/cmd_cleanup.c @@ -34,25 +34,29 @@ * $DragonFly: src/sbin/hammer/cmd_cleanup.c,v 1.6 2008/10/07 22:28:41 thomas Exp $ */ /* - * Clean up a specific HAMMER filesystem or all HAMMER filesystems. + * Clean up specific HAMMER filesystems or all HAMMER filesystems. * - * Each filesystem is expected to have a /snapshots directory. - * No cleanup will be performed on any filesystem that does not. If - * no filesystems are specified the 'df' program is run and any HAMMER - * or null-mounted hammer PFS's are extracted. + * If no filesystems are specified any HAMMER- or null-mounted hammer PFS's + * are cleaned. * - * The snapshots directory may contain a config file called 'config'. If - * no config file is present one will be created with the following + * Each HAMMER filesystem may contain a configuration file. If no + * configuration file is present one will be created with the following * defaults: * * snapshots 1d 60d (0d 0d for /tmp, /var/tmp, /usr/obj) * prune 1d 5m * rebalance 1d 5m * reblock 1d 5m - * recopy 30d 5m + * recopy 30d 10m * * All hammer commands create and maintain cycle files in the snapshots * directory. + * + * For HAMMER version 2- the configuration file is a named 'config' in + * the snapshots directory, which defaults to /snapshots. + * For HAMMER version 3+ the configuration file is saved in filesystem + * meta-data. The snapshots directory defaults to /var/hammer/ + * (/var/hammer/root for root mount). */ #include "hammer.h" @@ -77,10 +81,10 @@ static void save_period(const char *snapshots_path, const char *cmd, static int check_softlinks(int fd, int new_config, const char *snapshots_path); static void cleanup_softlinks(int fd, int new_config, const char *snapshots_path, int arg2, char *arg3); +static void delete_snapshots(int fd, struct hammer_ioc_snapshot *dsnapshot); static int check_expired(const char *fpath, int arg2); -static int create_snapshot(int new_config, const char *path, - const char *snapshots_path); +static int create_snapshot(const char *path, const char *snapshots_path); static int cleanup_rebalance(const char *path, const char *snapshots_path, int arg1, int arg2); static int cleanup_prune(const char *path, const char *snapshots_path, @@ -92,6 +96,12 @@ static int cleanup_recopy(const char *path, const char *snapshots_path, static void runcmd(int *resp, const char *ctl, ...); +/* + * WARNING: Do not make the SNAPSHOTS_BASE "/var/snapshots" because + * it will interfere with the older HAMMER VERS < 3 snapshots directory + * for the /var PFS. + */ +#define SNAPSHOTS_BASE "/var/hammer" /* HAMMER VERS >= 3 */ #define WS " \t\r\n" struct didpfs *FirstPFS; @@ -143,7 +153,7 @@ do_cleanup(const char *path) struct hammer_ioc_config config; struct hammer_ioc_version version; union hammer_ioc_mrecord_any mrec_tmp; - char *snapshots_path; + char *snapshots_path = NULL; char *config_path; struct stat st; char *cmd; @@ -155,11 +165,12 @@ do_cleanup(const char *path) char buf[256]; char *cbase; char *cptr; - FILE *fp; + FILE *fp = NULL; struct didpfs *didpfs; int snapshots_disabled = 0; int prune_warning = 0; int new_config = 0; + int snapshots_from_pfs = 0; int fd; int r; int found_rebal = 0; @@ -218,44 +229,39 @@ do_cleanup(const char *path) didpfs->uuid = mrec_tmp.pfs.pfsd.unique_uuid; /* - * Figure out where the snapshot directory is. + * Calculate the old snapshots directory for HAMMER VERSION < 3 + * + * If the directory is explicitly specified in the PFS config + * we flag it and will not migrate it later. */ if (mrec_tmp.pfs.pfsd.snapshots[0] == '/') { asprintf(&snapshots_path, "%s", mrec_tmp.pfs.pfsd.snapshots); + snapshots_from_pfs = 1; } else if (mrec_tmp.pfs.pfsd.snapshots[0]) { printf(" WARNING: pfs-slave's snapshots dir is not absolute\n"); close(fd); return; } else if (mrec_tmp.pfs.pfsd.mirror_flags & HAMMER_PFSD_SLAVE) { - printf(" WARNING: must configure snapshot dir for PFS slave\n"); - printf("\tWe suggest /var/slaves/ where " - " is the base HAMMER fs\n"); - printf("\tcontaining the slave\n"); - close(fd); - return; + if (version.cur_version < 3) { + printf(" WARNING: must configure snapshot dir for PFS slave\n"); + printf("\tWe suggest /var/slaves/ where " + " is the base HAMMER fs\n"); + printf("\tcontaining the slave\n"); + close(fd); + return; + } } else { asprintf(&snapshots_path, "%s%ssnapshots", path, dividing_slash(path)); } /* - * Create a snapshot directory if necessary, and a config file if - * necessary. - * - * If the filesystem is running version >= 3 migrate the config - * file to meta-data. + * Check for old-style config file */ - if (stat(snapshots_path, &st) < 0) { - if (mkdir(snapshots_path, 0755) != 0) { - free(snapshots_path); - printf(" unable to create snapshot dir \"%s\": %s\n", - snapshots_path, strerror(errno)); - close(fd); - return; - } + if (snapshots_path) { + asprintf(&config_path, "%s/config", snapshots_path); + fp = fopen(config_path, "r"); } - asprintf(&config_path, "%s/config", snapshots_path); - fp = fopen(config_path, "r"); /* * Handle upgrades to hammer version 3, move the config @@ -287,6 +293,22 @@ do_cleanup(const char *path) } new_config = 1; } else { + /* + * Create missing snapshots directory for HAMMER VERSION < 3 + */ + if (stat(snapshots_path, &st) < 0) { + if (mkdir(snapshots_path, 0755) != 0) { + free(snapshots_path); + printf(" unable to create snapshot dir \"%s\": %s\n", + snapshots_path, strerror(errno)); + close(fd); + return; + } + } + + /* + * Create missing config file for HAMMER VERSION < 3 + */ if (fp == NULL) { config_init(path, &config); fp = fopen(config_path, "w"); @@ -301,6 +323,58 @@ do_cleanup(const char *path) } } + /* + * If snapshots_from_pfs is not set we calculate the new snapshots + * directory default (in /var) for HAMMER VERSION >= 3 and migrate + * the old snapshots directory over. + * + * People who have set an explicit snapshots directory will have + * to migrate the data manually into /var/hammer, or not bother at + * all. People running slaves may wish to migrate it and then + * clear the snapshots specification in the PFS config for the + * slave. + */ + if (new_config && snapshots_from_pfs == 0) { + char *npath; + + assert(path[0] == '/'); + if (strcmp(path, "/") == 0) + asprintf(&npath, "%s/root", SNAPSHOTS_BASE); + else + asprintf(&npath, "%s/%s", SNAPSHOTS_BASE, path + 1); + if (snapshots_path) { + if (stat(npath, &st) < 0 && errno == ENOENT) { + if (stat(snapshots_path, &st) < 0 && errno == ENOENT) { + printf(" HAMMER UPGRADE: Creating snapshots\n" + "\tCreating snapshots in %s\n", + npath); + runcmd(&r, "mkdir -p %s", npath); + } else { + printf(" HAMMER UPGRADE: Moving snapshots\n" + "\tMoving snapshots from %s to %s\n", + snapshots_path, npath); + runcmd(&r, "mkdir -p %s", npath); + runcmd(&r, "cpdup %s %s", snapshots_path, npath); + if (r != 0) { + printf("Unable to move snapshots directory!\n"); + printf("Please fix this critical error.\n"); + printf("Aborting cleanup of %s\n", path); + close(fd); + return; + } + runcmd(&r, "rm -rf %s", snapshots_path); + } + } + free(snapshots_path); + } else if (stat(npath, &st) < 0 && errno == ENOENT) { + runcmd(&r, "mkdir -p %s", npath); + } + snapshots_path = npath; + } + + /* + * Lock the PFS. fd is the base directory of the mounted PFS. + */ if (flock(fd, LOCK_EX|LOCK_NB) == -1) { if (errno == EWOULDBLOCK) printf(" PFS #%d locked by other process\n", pfs.pfs_id); @@ -323,6 +397,9 @@ do_cleanup(const char *path) cbase = cptr + 1; cmd = strtok(buf, WS); + if (cmd == NULL || cmd[0] == '#') + continue; + arg1 = 0; arg2 = 0; arg3 = NULL; @@ -358,8 +435,7 @@ do_cleanup(const char *path) cleanup_softlinks(fd, new_config, snapshots_path, arg2, arg3); - r = create_snapshot(new_config, - path, snapshots_path); + r = create_snapshot(path, snapshots_path); } else { printf("skip\n"); } @@ -428,7 +504,7 @@ do_cleanup(const char *path) /* * Add new rebalance feature if the config doesn't have it. - * (old style config only) + * (old style config only). */ if (new_config == 0 && found_rebal == 0) { if ((fp = fopen(config_path, "r+")) != NULL) { @@ -466,13 +542,12 @@ config_init(const char *path, struct hammer_ioc_config *config) "prune 1d 5m\n" "rebalance 1d 5m\n" "reblock 1d 5m\n" - "recopy 30d 10m\n" - "rebalance 1d 5m\n"); + "recopy 30d 10m\n"); } /* * Migrate configuration data from the old snapshots/config - * file to the new mata-data format. + * file to the new meta-data format. */ static void migrate_config(FILE *fp, struct hammer_ioc_config *config) @@ -542,7 +617,11 @@ migrate_one_snapshot(int fd, const char *fpath, t = (time_t)-1; tid = (hammer_tid_t)(int64_t)-1; - ptr = fpath; + /* fpath may contain directory components */ + if ((ptr = strrchr(fpath, '/')) != NULL) + ++ptr; + else + ptr = fpath; while (*ptr && *ptr != '-' && *ptr != '.') ++ptr; if (*ptr) @@ -574,6 +653,9 @@ migrate_one_snapshot(int fd, const char *fpath, snprintf(snap->label, sizeof(snap->label), "migrated"); ++snapshot->count; + } else { + printf(" non-canonical snapshot softlink: %s->%s\n", + fpath, linkbuf); } } @@ -588,7 +670,7 @@ again: ++snapshot->index; goto again; } else if (snapshot->head.error) { - printf(" Ioctl to delete snapshots failed: %s\n", + printf(" Ioctl to migrate snapshots failed: %s\n", strerror(snapshot->head.error)); } printf("index %d\n", snapshot->index); @@ -642,6 +724,8 @@ dividing_slash(const char *path) * Periods in minutes, hours, or days are assumed to have been crossed * if the local time crosses a minute, hour, or day boundary regardless * of how close the last operation actually was. + * + * If ForceOpt is set always return true. */ static int check_period(const char *snapshots_path, const char *cmd, int arg1, @@ -657,6 +741,12 @@ check_period(const char *snapshots_path, const char *cmd, int arg1, time(savep); localtime_r(savep, &tp1); + /* + * Force run if -F + */ + if (ForceOpt) + return(1); + /* * Retrieve the start time of the last successful operation. */ @@ -824,6 +914,7 @@ cleanup_softlinks(int fd, int new_config, struct hammer_snapshot_data *snap; struct tm *tp; time_t t; + time_t dt; char snapts[32]; u_int32_t i; @@ -837,12 +928,13 @@ cleanup_softlinks(int fd, int new_config, } for (i = 0; i < snapshot.count; ++i) { snap = &snapshot.snaps[i]; - t = time(NULL) - snap->ts / 1000000ULL; - if ((int)t > arg2) { + t = snap->ts / 1000000ULL; + dt = time(NULL) - t; + if ((int)dt > arg2 || snap->tid == 0) { dsnapshot.snaps[dsnapshot.count++] = *snap; } - if ((int)t > arg2 && VerboseOpt) { + if ((int)dt > arg2 && VerboseOpt) { tp = localtime(&t); strftime(snapts, sizeof(snapts), "%Y-%m-%d %H:%M:%S %Z", tp); @@ -851,28 +943,38 @@ cleanup_softlinks(int fd, int new_config, snapts, snap->label); } - if (dsnapshot.count == HAMMER_SNAPS_PER_IOCTL) { - if (ioctl(fd, HAMMERIOC_DEL_SNAPSHOT, &dsnapshot) < 0) { - printf(" Ioctl to delete snapshots failed: %s\n", strerror(errno)); - } else if (dsnapshot.head.error) { - printf(" Ioctl to delete snapshots failed: %s\n", strerror(dsnapshot.head.error)); - } - dsnapshot.count = 0; - dsnapshot.head.error = 0; - } + if (dsnapshot.count == HAMMER_SNAPS_PER_IOCTL) + delete_snapshots(fd, &dsnapshot); } } while (snapshot.head.error == 0 && snapshot.count); - if (dsnapshot.count) { - if (ioctl(fd, HAMMERIOC_DEL_SNAPSHOT, &dsnapshot) < 0) { - printf(" Ioctl to delete snapshots failed: %s\n", strerror(errno)); - } else if (dsnapshot.head.error) { - printf(" Ioctl to delete snapshots failed: %s\n", strerror(dsnapshot.head.error)); - } - dsnapshot.count = 0; - dsnapshot.head.error = 0; + if (dsnapshot.count) + delete_snapshots(fd, &dsnapshot); + } +} + +static void +delete_snapshots(int fd, struct hammer_ioc_snapshot *dsnapshot) +{ + for (;;) { + if (ioctl(fd, HAMMERIOC_DEL_SNAPSHOT, dsnapshot) < 0) { + printf(" Ioctl to delete snapshots failed: %s\n", + strerror(errno)); + break; + } + if (dsnapshot->head.error) { + printf(" Ioctl to delete snapshots failed at " + "snap=%016jx: %s\n", + dsnapshot->snaps[dsnapshot->index].tid, + strerror(dsnapshot->head.error)); + if (++dsnapshot->index < dsnapshot->count) + continue; } + break; } + dsnapshot->index = 0; + dsnapshot->count = 0; + dsnapshot->head.error = 0; } /* @@ -922,21 +1024,11 @@ check_expired(const char *fpath, int arg2) * Issue a snapshot. */ static int -create_snapshot(int new_config, const char *path, const char *snapshots_path) +create_snapshot(const char *path, const char *snapshots_path) { int r; - if (new_config) { - /* - * New-style snapshot >= version 3. - */ - runcmd(&r, "hammer snap %s cleanup", snapshots_path); - } else { - /* - * Old-style snapshot prior to version 3 - */ - runcmd(&r, "hammer snapshot %s %s", path, snapshots_path); - } + runcmd(&r, "hammer snapshot %s %s", path, snapshots_path); return(r); }