#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
+#include <libgen.h> /* for dirname() */
#include <lustre/lustreapi.h>
#include <linux/lustre/lustre_ver.h> /* only until LUSTRE_VERSION_CODE is gone */
#include "lustreapi_internal.h"
return -1;
}
- rc = get_lustre_param_value(NULL, NULL, FILTER_BY_NONE, buffer,
- "version", sizeof(buffer));
+ rc = get_lustre_param_value(NULL, NULL, FILTER_BY_NONE, "version",
+ buffer, sizeof(buffer));
if (rc < 0) {
errno = -rc;
return -1;
return rc ? -errno : 0;
}
+
+int llapi_direntry_remove(char *dname)
+{
+#ifdef HAVE_IOC_REMOVE_ENTRY
+ char *dirpath = NULL;
+ char *namepath = NULL;
+ char *dir;
+ char *filename;
+ int fd = -1;
+ int rc = 0;
+
+ dirpath = strdup(dname);
+ namepath = strdup(dname);
+ if (!dirpath || !namepath)
+ return -ENOMEM;
+
+ filename = basename(namepath);
+
+ dir = dirname(dirpath);
+
+ fd = open(dir, O_DIRECTORY | O_RDONLY);
+ if (fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'",
+ filename);
+ goto out;
+ }
+
+ if (ioctl(fd, LL_IOC_REMOVE_ENTRY, filename))
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "error on ioctl %#lx for '%s' (%d)",
+ (long)LL_IOC_LMV_SETSTRIPE, filename, fd);
+out:
+ free(dirpath);
+ free(namepath);
+ if (fd != -1)
+ close(fd);
+ return rc;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+int llapi_unlink_foreign(char *name)
+{
+ int fd = -1;
+ int rc = 0;
+
+ fd = open(name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW);
+ if (fd < 0 && errno != ENOTDIR) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'", name);
+ goto out;
+ } else if (errno == ENOTDIR) {
+ fd = open(name, O_RDONLY | O_NOFOLLOW);
+ if (fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'",
+ name);
+ goto out;
+ }
+ }
+
+ /* allow foreign symlink file/dir to be unlinked */
+ if (ioctl(fd, LL_IOC_UNLOCK_FOREIGN)) {
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "error on ioctl %#lx for '%s' (%d)",
+ (long)LL_IOC_UNLOCK_FOREIGN, name, fd);
+ rc = -errno;
+ }
+
+ /* XXX do not set AT_REMOVEDIR in flags even for a dir, as due to the
+ * hack for foreign symlink it will fail the directory check in
+ * Kernel's syscall code and return ENOTDIR, so treat all as files
+ */
+ rc = unlinkat(AT_FDCWD, name, 0);
+ if (rc == -1 && errno == EISDIR)
+ rc = unlinkat(AT_FDCWD, name, AT_REMOVEDIR);
+
+ if (rc == -1) {
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "error on unlinkat for '%s' (%d)", name, fd);
+ rc = -errno;
+ }
+
+out:
+ if (fd != -1)
+ close(fd);
+ return rc;
+}
+
+int llapi_get_fsname_instance(const char *path, char *fsname, size_t fsname_len,
+ char *instance, size_t instance_len)
+{
+ struct obd_uuid uuid_buf;
+ char *uuid = uuid_buf.uuid;
+ char *ptr;
+ int rc;
+
+ memset(&uuid_buf, 0, sizeof(uuid_buf));
+ rc = llapi_file_get_lov_uuid(path, &uuid_buf);
+ if (rc)
+ return rc;
+
+ /*
+ * We want to turn fs-foo-clilov-ffff88002738bc00 into 'fs-foo' and
+ * 'ffff88002738bc00' in a portable way that doesn't depend on what is
+ * after "-clilov-" as it may change to a UUID string in the future.
+ * Unfortunately, the "fsname" part may contain a dash, so we can't
+ * just skip to the first dash, and if the "instance" is a UUID in the
+ * future we can't necessarily go to the last dash either.
+ */
+ ptr = strstr(uuid, "-clilov-");
+ if (!ptr || (!fsname && !instance)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ *ptr = '\0';
+ ptr += strlen("-clilov-");
+ if (instance) {
+ snprintf(instance, instance_len, "%s", ptr);
+ if (strlen(ptr) >= instance_len)
+ rc = -ENAMETOOLONG;
+ }
+
+ if (fsname) {
+ snprintf(fsname, fsname_len, "%s", uuid);
+ if (strlen(uuid) >= fsname_len)
+ rc = -ENAMETOOLONG;
+ }
+
+out:
+ errno = -rc;
+ return rc;
+}
+
+int llapi_getname(const char *path, char *name, size_t namelen)
+{
+ char fsname[16];
+ char instance[40];
+ int rc;
+
+ rc = llapi_get_fsname_instance(path, fsname, sizeof(fsname),
+ instance, sizeof(instance));
+ if (rc)
+ return rc;
+
+ snprintf(name, namelen, "%s-%s", fsname, instance);
+ if (strlen(fsname) + 1 + strlen(instance) >= namelen) {
+ rc = -ENAMETOOLONG;
+ errno = -rc;
+ }
+
+ return rc;
+}
+
+int llapi_get_instance(const char *path, char *instance, size_t instance_len)
+{
+ return llapi_get_fsname_instance(path, NULL, 0, instance, instance_len);
+}
+
+int llapi_get_fsname(const char *path, char *fsname, size_t fsname_len)
+{
+ return llapi_get_fsname_instance(path, fsname, fsname_len, NULL, 0);
+}