#include "lipe_config.h"
#include "lipe_version.h"
+#ifndef swap
+# define swap(a, b) \
+ do { typeof(a) __swap_tmp = (a); (a) = (b); (b) = __swap_tmp; } while (0)
+#endif
+
#define DEF_POOL_REFRESH_INTV (10 * 60)
#define DEF_PROGRESS_INTV (10 * 60)
#define DEF_MIN_AGE 600
enum llapi_message_level lx_log_level = LLAPI_MSG_INFO;
char *lx_log_prefix = "NONE";
+static char *lamigo_changelog_user;
static LIPE_LIST_HEAD(lamigo_rule_list);
__u64 lamigo_rule_attrs; /* attributes needed to evalute the rules */
}
}
-static void systemf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
-static void systemf(const char *fmt, ...)
+static int systemf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+static int systemf(const char *fmt, ...)
{
char *cmd = NULL;
va_list args;
va_end(args);
if (rc < 0)
- return;
+ return rc;
- system(cmd);
+ rc = system(cmd);
free(cmd);
+
+ return rc;
}
#define JOB_FMT \
" mountpoint: %s\n"
" source_pool: ",
PACKAGE_VERSION, LIPE_RELEASE, LIPE_REVISION,
- opt.o_chlg_user, opt.o_mdtname, opt.o_mntpt);
+ lamigo_changelog_user, opt.o_mdtname, opt.o_mntpt);
i = 0;
for (pl = src_pools; pl != NULL; pl = pl->pl_next, i++)
fprintf(f, "%s%s", i ? "," : "", pl->pl_pool);
return;
LX_DEBUG("CLEAR upto %llu in %s (%llu last)\n",
- index, opt.o_chlg_user, lamigo_last_processed_idx);
+ index, lamigo_changelog_user, lamigo_last_processed_idx);
lamigo_last_cleared_index = index;
- rc = llapi_changelog_clear(opt.o_mdtname, opt.o_chlg_user, index);
+ rc = llapi_changelog_clear(opt.o_mdtname, lamigo_changelog_user, index);
if (rc < 0) {
llapi_error(LLAPI_MSG_ERROR, rc,
"failed to clear changelog record %s:%llu (%llu last)",
- opt.o_chlg_user, index, lamigo_last_cleared_index);
+ lamigo_changelog_user, index, lamigo_last_cleared_index);
systemf("lctl get_param 'mdd.%s.changelog_users'", opt.o_mdtname);
}
}
opt.o_tgt_pool = strdup(optarg);
break;
case 'u':
- opt.o_chlg_user = strdup(optarg);
+ opt.o_changelog_user = strdup(optarg);
break;
case 'v':
lx_log_level++;
return rc;
}
-static void lamigo_changelog_check_and_set_mask(void)
+static void lamigo_changelog_mask_set(void)
{
char buf[256];
glob_t paths;
}
/*
- * check whether @user is registered in changelogs
- * returns: 0 - registered, <0 - not registered
+ * check is @user is registered in changelogs
+ * returns a malloced copy of whatever it found.
*/
-static int lamigo_check_changelog_user(const char *user)
+static char *lamigo_changelog_user_find(const char *user)
{
char buf[4096];
- char *p, *s, *e;
+ char *s, *line;
glob_t paths;
+ char *found = NULL;
int rc;
rc = cfs_get_param_paths(&paths, "mdd/%s/changelog_users",
if (rc < 0)
LX_FATAL("can't get changelog users\n");
- rc = -1;
s = buf;
+
+ /* mdd.lustre-MDT0000.changelog_users=
+ * current_index: 0
+ * ID index (idle) mask
+ * cl4-lamigo 0 (19) mask=MARK,UNLNK,CLOSE
+ */
/* skip current index line */
- strsep(&s, "\n\r");
+ strsep(&s, "\n");
+
/* skip ID index.. header */
- strsep(&s, "\n\r");
- /* try to find specified user */
- while ((p = strsep(&s, "\n\r"))) {
- e = strsep(&p, " \t");
- if (!strcmp(e, user)) {
- rc = 0;
- break;
+ strsep(&s, "\n");
+
+ /* try to find @user or a named user is @user == NULL */
+ while ((line = strsep(&s, "\n")) != NULL) {
+ char *s2 = strsep(&line, " \t");
+ char *user1_and_name1 = xstrdup(s2);
+ char *user1 = strsep(&s2, "-");
+ char *name1 = s2;
+
+ if (user != NULL) {
+ if (strcmp(user, user1_and_name1) == 0 ||
+ strcmp(user, user1) == 0) {
+ found = user1_and_name1;
+ break;
+ }
+ } else {
+ if (name1 != NULL && strcmp(name1, "lamigo") == 0) {
+ found = user1_and_name1;
+ break;
+ }
}
+
+ free(user1_and_name1);
}
+
globfree(&paths);
- return rc;
+ return found;
}
-static void lamigo_check_changelogs(void)
+static void lamigo_changelog_user_find_any(void)
{
- char buf[4096];
- char user[32];
- int rc;
- bool registered = false;
+ char var_user_path[PATH_MAX]; /* /var/lib/lamigo-MDTxxxx.chlg */
+ char var_user_buf[32] = "";
+ char *named_user = NULL;
+ char *opt_user = NULL;
+ char *var_user = NULL;
- lamigo_changelog_check_and_set_mask();
+ /* This is a real mess that we've made for ourselves.
+ *
+ * Find or register a suitable changelog user for lamigo.
+ * If there is a user with name "lamigo" then we use that.
+ * Otherwise we try the user in /var/lib/lamigo-<mdtname>.chlg.
+ * Otherwise we try the configured user.
+ *
+ * Note due to failover pairing, a previously registered user
+ * may not be in var_use /var/lib/lamigo-<mdtname>.chlg on the
+ * current node. */
+ assert(lamigo_changelog_user == NULL);
-again:
- /*
- * first, check in /var/lib/lamigo-**.chlg
- * then try user from the config file
- * if not found - create and write to /var/lib/lamigo-**.chlg
- */
- snprintf(buf, sizeof(buf), LAMIGO_USERFILE, opt.o_mdtname);
- rc = lamigo_read_file(buf, user, sizeof(user));
- if (rc >= 0) {
- rc = lamigo_check_changelog_user(user);
- if (!rc) {
- /* found, use it */
- opt.o_chlg_user = strdup(user);
- LX_DEBUG("found Changelog user '%s' in '%s'\n",
- user, buf);
- return;
- }
- }
+ named_user = lamigo_changelog_user_find(NULL);
- if (registered)
- LX_FATAL("cannot find just registered Changelog user '%s'\n", user);
+ if (opt.o_changelog_user != NULL)
+ opt_user = lamigo_changelog_user_find(opt.o_changelog_user);
- /* try one from the config file */
- if (opt.o_chlg_user) {
- rc = lamigo_check_changelog_user(opt.o_chlg_user);
- if (!rc) {
- /* found, use it */
- LX_DEBUG("found Changelog user '%s' from config\n",
- opt.o_chlg_user);
- return;
- }
+ snprintf(var_user_path, sizeof(var_user_path), LAMIGO_USERFILE, opt.o_mdtname);
+
+ /* lamigo_read_file() strips the trailing newline and adds a
+ * trailing '\0'. */
+ lamigo_read_file(var_user_path, var_user_buf, sizeof(var_user_buf));
+ if (var_user_buf[0] != '\0')
+ var_user = lamigo_changelog_user_find(var_user_buf);
+
+ if (named_user != NULL && opt_user != NULL && strcmp(named_user, opt_user) != 0)
+ LX_ERROR("multiple registered changelog users '%s' and '%s'\n",
+ named_user, opt_user);
+
+ if (named_user != NULL && var_user != NULL && strcmp(named_user, var_user) != 0)
+ LX_ERROR("multiple registered changelog users '%s' and '%s'\n",
+ named_user, var_user);
+
+ if (opt_user != NULL && var_user != NULL && strcmp(opt_user, var_user) != 0)
+ LX_ERROR("multiple registered changelog users '%s' and '%s'\n",
+ opt_user, var_user);
+
+ if (named_user != NULL) {
+ swap(lamigo_changelog_user, named_user);
+ LX_INFO("using named changelog user '%s'\n",
+ lamigo_changelog_user);
+ goto out;
+ } else if (var_user != NULL) {
+ swap(lamigo_changelog_user, var_user);
+ LX_INFO("using changelog user '%s' from '%s'\n",
+ lamigo_changelog_user, var_user_path);
+ goto out;
+ } else if (opt_user != NULL) {
+ swap(lamigo_changelog_user, opt_user);
+ LX_INFO("using configured changelog user '%s'\n",
+ lamigo_changelog_user);
+ goto out;
}
- llapi_err_noerrno(LLAPI_MSG_INFO, "register new Changelog user");
- /* not found, try to register own */
- snprintf(buf, sizeof(buf),
- "lctl --device %s changelog_register -n >"LAMIGO_USERFILE,
- opt.o_mdtname, opt.o_mdtname);
- rc = system(buf);
+out:
+ LX_DEBUG_S(lamigo_changelog_user);
+ LX_DEBUG_S(named_user);
+ LX_DEBUG_S(opt.o_changelog_user);
+ LX_DEBUG_S(opt_user);
+ LX_DEBUG_S(var_user_path);
+ LX_DEBUG_S(var_user_buf);
+ LX_DEBUG_S(var_user);
+
+ free(named_user);
+ free(opt_user);
+ free(var_user);
+}
+
+static void lamigo_changelog_user_register(void)
+{
+ int rc;
+
+ lamigo_changelog_user_find_any();
+
+ if (lamigo_changelog_user != NULL)
+ return;
+
+ LX_INFO("registering new changelog user\n");
+
+ rc = systemf("lctl --device %s changelog_register --mask='CLOSE UNLNK' --user=lamigo --nameonly > "LAMIGO_USERFILE,
+ opt.o_mdtname, opt.o_mdtname);
if (rc < 0)
- LX_FATAL("changelog user '%s' is not registered\n",
- opt.o_chlg_user);
-
- registered = true;
- /* if a new changelog user was just registered, either this is the
- * first time lamigo was run on the filesystem, or it has been some
- * time since it was last run and changes were not logged. Run a
- * full filesystem scan to look for any files that need processing.
- */
- opt.o_rescan = true;
+ LX_FATAL("cannot execute 'lctl changelog_register': %s\n", strerror(errno));
+ else if (rc != 0)
+ LX_FATAL("lctl changelog_register cannot register changelog user: status = %d\n", rc);
+
+ lamigo_changelog_user_find_any();
+
+ if (lamigo_changelog_user != NULL)
+ return;
- goto again;
+ LX_FATAL("cannot find just registered changelog user\n");
}
static unsigned long progress_timestamp;
/* refresh source pools */
lamigo_refresh_pools();
+
/* register changelog before full scan to avoid missing new files */
- lamigo_check_changelogs();
+ lamigo_changelog_user_register();
+
+ /* ensure that changelog mask includes "CLOSE" and "UNLNK". */
+ lamigo_changelog_mask_set();
/* start heat collection and maintaining */
lamigo_alr_init();