X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi_util.c;h=e8af531c7ffb1051d197bee2ef56634e7a23fb85;hb=HEAD;hp=59f7e98bdb430d5048c41544984a59beb22bad72;hpb=1fd63fcb045c91aa259068d3077b481652da0270;p=fs%2Flustre-release.git diff --git a/lustre/utils/liblustreapi_util.c b/lustre/utils/liblustreapi_util.c index 59f7e98..ceab7a4 100644 --- a/lustre/utils/liblustreapi_util.c +++ b/lustre/utils/liblustreapi_util.c @@ -41,6 +41,7 @@ #include #include #include +#include /* for dirname() */ #include #include /* only until LUSTRE_VERSION_CODE is gone */ #include "lustreapi_internal.h" @@ -115,8 +116,8 @@ int llapi_get_version_string(char *version, unsigned int version_size) 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; @@ -160,16 +161,15 @@ int llapi_get_version_string(char *version, unsigned int version_size) */ int llapi_get_version(char *buffer, int buffer_size, char **version) { - int rc; -#if LUSTRE_VERSION_CODE > OBD_OCD_VERSION(2, 8, 53, 0) static bool printed; + int rc; + if (!printed) { fprintf(stderr, "%s deprecated, use llapi_get_version_string()\n", __func__); printed = true; } -#endif rc = llapi_get_version_string(buffer, buffer_size); /* keep old return style for this legacy function */ @@ -287,27 +287,238 @@ int llapi_search_ost(const char *fsname, const char *poolname, return llapi_search_tgt(fsname, poolname, ostname, false); } +/** + * Return the open fd for a given device/path provided + * + * \param device[in] buffer holding device or path string + * \param rootfd[out] file descriptor after successful opening of + * of above path or device + * + * \retval 0 on success + * \retval -ve on failure + */ +int llapi_root_path_open(const char *device, int *rootfd) +{ + int tmp_fd, rc; + + if (*device == '/') + rc = get_root_path(WANT_FD, NULL, &tmp_fd, + (char *)device, -1, NULL, NULL); + else + rc = get_root_path(WANT_FD, (char *)device, &tmp_fd, + NULL, -1, NULL, NULL); + + if (!rc) + *rootfd = dup(tmp_fd); + + return rc; +} + +/** + * Call IOCTL to remove file by fid. The fd must be valid and fa + * (fid_array) struct must allready be populated. + * + * \param fd[in] valid descriptor of device/path + * \param fa[in] fid_array struct holding fids + * + * \retval 0 on success + * \retval -ve/errno on failure + */ +int llapi_rmfid_at(int fd, struct fid_array *fa) +{ + return ioctl(fd, LL_IOC_RMFID, fa) ? -errno : 0; +} + int llapi_rmfid(const char *path, struct fid_array *fa) { - char rootpath[PATH_MAX]; - int fd, rc; + int rootfd, rc; + + rc = llapi_root_path_open(path, &rootfd); + if (rc < 0) { + fprintf(stderr, + "lfs rmfid: error opening device/fsname '%s': %s\n", + path, strerror(-rc)); + return -rc; + } + + rc = llapi_rmfid_at(rootfd, fa); + close(rootfd); + if (rc < 0) { + fprintf(stderr, "lfs rmfid: cannot remove FIDs: %s\n", + strerror(-rc)); + return rc; + } + + return rc ? -errno : 0; +} + +int llapi_direntry_remove(char *dname) +{ +#ifdef LL_IOC_REMOVE_ENTRY + char *dirpath = NULL; + char *namepath = NULL; + char *dir; + char *filename; + int fd = -1; + int rc = 0; + + dirpath = strdup(dname); + if (!dirpath) + return -ENOMEM; + + namepath = strdup(dname); + if (!namepath) { + rc = -ENOMEM; + goto out_dirpath; + } + + filename = basename(namepath); -retry_open: - fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW); + dir = dirname(dirpath); + + fd = open(dir, O_DIRECTORY | O_RDONLY); if (fd < 0) { - if (errno == ENOENT && path != rootpath) { - rc = llapi_search_rootpath(rootpath, path); - if (!rc) { - path = rootpath; - goto retry_open; - } - } else { - return -errno; - } + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'", + filename); + goto out; } - rc = ioctl(fd, LL_IOC_RMFID, fa); + 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: close(fd); + free(namepath); +out_dirpath: + free(dirpath); + return rc; +#else + return -EOPNOTSUPP; +#endif +} - return rc ? -errno : 0; +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); }