+
+#ifdef HAVE_SERVER_SUPPORT
+struct lustre_cfg_entry {
+ struct list_head lce_list;
+ char lce_name[0];
+};
+
+static struct lustre_cfg_entry *lustre_cfg_entry_init(const char *name)
+{
+ struct lustre_cfg_entry *lce;
+ int len = strlen(name) + 1;
+
+ lce = malloc(sizeof(*lce) + len);
+ if (lce) {
+ INIT_LIST_HEAD(&lce->lce_list);
+ memcpy(lce->lce_name, name, len);
+ }
+
+ return lce;
+}
+
+static void lustre_cfg_entry_fini(struct lustre_cfg_entry *lce)
+{
+ free(lce);
+}
+
+int lustre_rename_fsname(struct mkfs_opts *mop, const char *mntpt,
+ const char *oldname)
+{
+ struct lustre_disk_data *ldd = &mop->mo_ldd;
+ struct lr_server_data lsd;
+ char filepnm[132];
+ char cfg_dir[128];
+ DIR *dir = NULL;
+ struct dirent64 *dirent;
+ struct lustre_cfg_entry *lce;
+ struct list_head cfg_list;
+ int old_namelen = strlen(oldname);
+ int new_namelen = strlen(ldd->ldd_fsname);
+ int ret;
+ int fd;
+
+ INIT_LIST_HEAD(&cfg_list);
+
+ snprintf(filepnm, sizeof(filepnm), "%s/%s", mntpt, LAST_RCVD);
+ fd = open(filepnm, O_RDWR);
+ if (fd < 0) {
+ if (errno == ENOENT)
+ goto config;
+
+ if (errno != 0)
+ ret = errno;
+ else
+ ret = fd;
+ fprintf(stderr, "Unable to open %s: %s\n",
+ filepnm, strerror(ret));
+ return ret;
+ }
+
+ ret = read(fd, &lsd, sizeof(lsd));
+ if (ret != sizeof(lsd)) {
+ if (errno != 0)
+ ret = errno;
+ fprintf(stderr, "Unable to read %s: %s\n",
+ filepnm, strerror(ret));
+ close(fd);
+ return ret;
+ }
+
+ ret = lseek(fd, 0, SEEK_SET);
+ if (ret) {
+ if (errno != 0)
+ ret = errno;
+ fprintf(stderr, "Unable to lseek %s: %s\n",
+ filepnm, strerror(ret));
+ close(fd);
+ return ret;
+ }
+
+ /* replace fsname in lr_server_data::lsd_uuid. */
+ if (old_namelen > new_namelen)
+ memmove(lsd.lsd_uuid + new_namelen,
+ lsd.lsd_uuid + old_namelen,
+ sizeof(lsd.lsd_uuid) - old_namelen);
+ else if (old_namelen < new_namelen)
+ memmove(lsd.lsd_uuid + new_namelen,
+ lsd.lsd_uuid + old_namelen,
+ sizeof(lsd.lsd_uuid) - new_namelen);
+ memcpy(lsd.lsd_uuid, ldd->ldd_fsname, new_namelen);
+ ret = write(fd, &lsd, sizeof(lsd));
+ if (ret != sizeof(lsd)) {
+ if (errno != 0)
+ ret = errno;
+ fprintf(stderr, "Unable to write %s: %s\n",
+ filepnm, strerror(ret));
+ close(fd);
+ return ret;
+ }
+
+ close(fd);
+
+config:
+ snprintf(cfg_dir, sizeof(cfg_dir), "%s/%s", mntpt, MOUNT_CONFIGS_DIR);
+ dir = opendir(cfg_dir);
+ if (!dir) {
+ if (errno != 0)
+ ret = errno;
+ else
+ ret = EINVAL;
+ fprintf(stderr, "Unable to opendir %s: %s\n",
+ cfg_dir, strerror(ret));
+ return ret;
+ }
+
+ while ((dirent = readdir64(dir)) != NULL) {
+ char *ptr;
+
+ if (strlen(dirent->d_name) <= old_namelen)
+ continue;
+
+ ptr = strrchr(dirent->d_name, '-');
+ if (!ptr || (ptr - dirent->d_name) != old_namelen)
+ continue;
+
+ if (strncmp(dirent->d_name, oldname, old_namelen) != 0)
+ continue;
+
+ lce = lustre_cfg_entry_init(dirent->d_name);
+ if (!lce) {
+ if (errno != 0)
+ ret = errno;
+ else
+ ret = EINVAL;
+
+ fprintf(stderr, "Fail to init item for %s: %s\n",
+ dirent->d_name, strerror(ret));
+ goto out;
+ }
+
+ list_add(&lce->lce_list, &cfg_list);
+ }
+
+ closedir(dir);
+ dir = NULL;
+ ret = 0;
+
+ while (!list_empty(&cfg_list) && ret == 0) {
+ lce = list_entry(cfg_list.next, struct lustre_cfg_entry,
+ lce_list);
+ list_del(&lce->lce_list);
+ snprintf(filepnm, sizeof(filepnm), "%s/%s", cfg_dir,
+ lce->lce_name);
+ if (IS_MGS(ldd))
+ /*
+ * Store the new fsname in the XATTR_TARGET_RENAME EA.
+ * When the MGS start, it will scan config logs, and
+ * for the ones which have the XATTR_TARGET_RENAME EA,
+ * it will replace old fsname with the new fsname in
+ * the config log by some shared kernel level config
+ * logs {fork,erase} functionalities automatically.
+ */
+ ret = setxattr(filepnm, XATTR_TARGET_RENAME,
+ ldd->ldd_fsname,
+ strlen(ldd->ldd_fsname), 0);
+ else
+ ret = unlink(filepnm);
+
+ if (ret) {
+ if (errno != 0)
+ ret = errno;
+
+ fprintf(stderr, "Fail to %s %s: %s\n",
+ IS_MGS(ldd) ? "setxattr" : "unlink",
+ filepnm, strerror(ret));
+ }
+
+ lustre_cfg_entry_fini(lce);
+ }
+
+out:
+ if (dir)
+ closedir(dir);
+
+ while (!list_empty(&cfg_list)) {
+ lce = list_entry(cfg_list.next, struct lustre_cfg_entry,
+ lce_list);
+ list_del(&lce->lce_list);
+ lustre_cfg_entry_fini(lce);
+ }
+
+ return ret;
+}
+#endif /* HAVE_SERVER_SUPPORT */
+
+#ifdef HAVE_GSS
+#ifdef HAVE_OPENSSL_SSK
+int load_shared_keys(struct mount_opts *mop)
+{
+ DIR *dir;
+ struct dirent *dentry;
+ struct stat sbuf;
+ char fullpath[PATH_MAX];
+ char *path = mop->mo_skpath;
+ int rc;
+
+ /* init logging */
+ sk_init_logging(NULL, 1, 1);
+
+ rc = stat(path, &sbuf);
+ if (rc < 0) {
+ fprintf(stderr, "stat() failed for key %s: %s\n", path,
+ strerror(errno));
+ return -errno;
+ }
+
+ /* Load individual keys or a directory of them */
+ if (S_ISREG(sbuf.st_mode)) {
+ return sk_load_keyfile(path);
+ } else if (!S_ISDIR(sbuf.st_mode)) {
+ fprintf(stderr, "Invalid shared key path: %s\n", path);
+ return -ENOKEY;
+ }
+
+ dir = opendir(path);
+ if (!dir) {
+ fprintf(stderr, "Unable to open shared key directory: %s\n",
+ path);
+ return -ENOENT;
+ }
+
+ /*
+ * Loop through the files in the directory attempting to load them.
+ * Any issue with loading the keyfile is treated as an error although
+ * the loop continues until all files have been attempted. This will
+ * allow all errors be reported at once rather then requiring
+ * incremental corrections to fix each one and try again.
+ */
+ while ((dentry = readdir(dir)) != NULL) {
+ if (strcmp(".", dentry->d_name) == 0 ||
+ strcmp("..", dentry->d_name) == 0)
+ continue;
+
+ rc = snprintf(fullpath, PATH_MAX, "%s/%s", path,
+ dentry->d_name);
+ if (rc >= PATH_MAX) {
+ fprintf(stderr, "Path too long for %s/%s\n",
+ path, dentry->d_name);
+ rc = -ENAMETOOLONG;
+ continue;
+ }
+
+ rc = stat(fullpath, &sbuf);
+ if (rc < 0) {
+ fprintf(stderr, "Unable to stat %s: %s\n", fullpath,
+ strerror(errno));
+ rc = -errno;
+ continue;
+ }
+
+ if (!S_ISREG(sbuf.st_mode))
+ continue;
+
+ rc = sk_load_keyfile(fullpath);
+ if (rc)
+ fprintf(stderr, "Failed to load key %s\n", fullpath);
+ }
+ closedir(dir);
+
+ return rc;
+}
+#endif /* HAVE_OPENSSL_SSK */
+#endif /* HAVE_GSS */