X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi.c;h=818d54cc1b63289abd48e4eaa189ce6e8605a65e;hp=bc010c1da3a10d3ef2f6e44686a9e604a61916e1;hb=d39b08def6512ee6ae883a0db62cebd808646208;hpb=a5fed8233f4f5755d61909849e23d146a94d4396 diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index bc010c1..818d54c 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -29,7 +27,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Whamcloud, Inc. + * Copyright (c) 2011, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -63,6 +61,7 @@ #include #include #include +#include /* for dirname() */ #ifdef HAVE_LINUX_UNISTD_H #include #else @@ -73,9 +72,9 @@ #include #include #include -#include #include -#include +#include +#include "lustreapi_internal.h" static unsigned llapi_dir_filetype_table[] = { [DT_UNKNOWN]= 0, @@ -228,47 +227,47 @@ int parse_size(char *optarg, unsigned long long *size, /* XXX: llapi_xxx() functions return negative values upon failure */ int llapi_stripe_limit_check(unsigned long long stripe_size, int stripe_offset, - int stripe_count, int stripe_pattern) + int stripe_count, int stripe_pattern) { - int page_size, rc; - - /* 64 KB is the largest common page size I'm aware of (on ia64), but - * check the local page size just in case. */ - page_size = LOV_MIN_STRIPE_SIZE; - if (getpagesize() > page_size) { - page_size = getpagesize(); - llapi_err_noerrno(LLAPI_MSG_WARN, - "warning: your page size (%u) is " - "larger than expected (%u)", page_size, - LOV_MIN_STRIPE_SIZE); - } - if (stripe_size < 0 || (stripe_size & (LOV_MIN_STRIPE_SIZE - 1))) { - rc = -EINVAL; - llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe_size %lu, " - "must be an even multiple of %d bytes", - stripe_size, page_size); - return rc; - } - if (stripe_offset < -1 || stripe_offset > MAX_OBD_DEVICES) { - rc = -EINVAL; - llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe offset %d", - stripe_offset); - return rc; - } - if (stripe_count < -1 || stripe_count > LOV_MAX_STRIPE_COUNT) { - rc = -EINVAL; - llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe count %d", - stripe_count); - return rc; - } - if (stripe_size >= (1ULL << 32)){ - rc = -EINVAL; - llapi_error(LLAPI_MSG_ERROR, rc, - "warning: stripe size larger than 4G " - "is not currently supported and would wrap"); - return rc; - } - return 0; + int page_size, rc; + + /* 64 KB is the largest common page size I'm aware of (on ia64), but + * check the local page size just in case. */ + page_size = LOV_MIN_STRIPE_SIZE; + if (getpagesize() > page_size) { + page_size = getpagesize(); + llapi_err_noerrno(LLAPI_MSG_WARN, + "warning: your page size (%u) is " + "larger than expected (%u)", page_size, + LOV_MIN_STRIPE_SIZE); + } + if (stripe_size < 0 || (stripe_size & (LOV_MIN_STRIPE_SIZE - 1))) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe_size %lu, " + "must be an even multiple of %d bytes", + stripe_size, page_size); + return rc; + } + if (stripe_offset < -1 || stripe_offset > MAX_OBD_DEVICES) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe offset %d", + stripe_offset); + return rc; + } + if (stripe_count < -1 || stripe_count > LOV_MAX_STRIPE_COUNT) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, "error: bad stripe count %d", + stripe_count); + return rc; + } + if (stripe_size >= (1ULL << 32)) { + rc = -EINVAL; + llapi_error(LLAPI_MSG_ERROR, rc, + "warning: stripe size 4G or larger " + "is not currently supported and would wrap"); + return rc; + } + return 0; } /* return the first file matching this pattern */ @@ -412,6 +411,8 @@ static int get_param_obdvar(const char *fsname, const char *file_path, llapi_error(LLAPI_MSG_ERROR, rc, "'%s' is not on a Lustre filesystem", file_path); + if (fp != NULL) + fclose(fp); return rc; } } else if (fsname) { @@ -449,16 +450,95 @@ static int get_param_obdvar(const char *fsname, const char *file_path, return get_param(devices, value, val_len); } -static int get_mds_md_size(char *path) +/* + * TYPE one of llite, lmv, lov. + * /proc/fs/lustre/TYPE/INST the directory of interest. + */ +static int get_param_cli(const char *type, const char *inst, + const char *param, char *buf, size_t buf_size) { - int lumlen = lov_mds_md_size(LOV_MAX_STRIPE_COUNT, LOV_MAGIC_V3); - char buf[16]; + char param_path[PATH_MAX + 1]; + FILE *param_file = NULL; + int rc; + + snprintf(param_path, sizeof(param_path), + "/proc/fs/lustre/%s/%s/%s", type, inst, param); + + param_file = fopen(param_path, "r"); + if (param_file == NULL) { + rc = -errno; + goto out; + } + + if (fgets(buf, buf_size, param_file) == NULL) { + rc = -errno; + goto out; + } + + rc = 0; +out: + if (param_file != NULL) + fclose(param_file); + + return rc; +} + +static int get_param_llite(const char *path, + const char *param, char *buf, size_t buf_size) +{ + char inst[80]; + int rc; + + rc = llapi_getname(path, inst, sizeof(inst)); + if (rc != 0) + return rc; - /* Now get the maxea from llite proc */ - if (!get_param_obdvar(NULL, path, "llite", "max_easize", - buf, sizeof(buf))) - lumlen = atoi(buf); - return lumlen; + return get_param_cli("llite", inst, param, buf, buf_size); +} + +static int get_param_lov(const char *path, + const char *param, char *buf, size_t buf_size) +{ + struct obd_uuid uuid; + int rc; + + rc = llapi_file_get_lov_uuid(path, &uuid); + if (rc != 0) + return rc; + + return get_param_cli("lov", uuid.uuid, param, buf, buf_size); +} + +static int get_param_lmv(const char *path, + const char *param, char *buf, size_t buf_size) +{ + struct obd_uuid uuid; + int rc; + + rc = llapi_file_get_lmv_uuid(path, &uuid); + if (rc != 0) + return rc; + + return get_param_cli("lmv", uuid.uuid, param, buf, buf_size); +} + +static int get_mds_md_size(const char *path) +{ + int md_size = lov_user_md_size(LOV_MAX_STRIPE_COUNT, LOV_USER_MAGIC_V3); + char buf[80]; + int rc; + + /* Get the max ea size from llite proc. */ + rc = get_param_llite(path, "max_easize", buf, sizeof(buf)); + if (rc != 0) + goto out; + + rc = atoi(buf); + if (rc > 0) + md_size = rc; + +out: + return md_size; } /* @@ -647,17 +727,129 @@ int llapi_file_create_pool(const char *name, unsigned long long stripe_size, return 0; } +/** + * In DNE phase I, only stripe_offset will be used in this function. + * stripe_count, stripe_pattern and pool_name will be supported later. + */ +int llapi_dir_create_pool(const char *name, int flags, int stripe_offset, + int stripe_count, int stripe_pattern, char *pool_name) +{ + struct lmv_user_md lmu = { 0 }; + struct obd_ioctl_data data = { 0 }; + char rawbuf[8192]; + char *buf = rawbuf; + char *dirpath = NULL; + char *namepath = NULL; + char *dir; + char *filename; + int fd = -1; + int rc; + + dirpath = strdup(name); + namepath = strdup(name); + if (!dirpath || !namepath) + return -ENOMEM; + + lmu.lum_magic = LMV_USER_MAGIC; + lmu.lum_stripe_offset = stripe_offset; + lmu.lum_stripe_count = stripe_count; + lmu.lum_hash_type = stripe_pattern; + if (pool_name != NULL) { + if (strlen(pool_name) >= LOV_MAXPOOLNAME) { + llapi_err_noerrno(LLAPI_MSG_ERROR, + "error LL_IOC_LMV_SETSTRIPE '%s' : too large" + "pool name: %s", name, pool_name); + GOTO(out, rc = -E2BIG); + } + memcpy(lmu.lum_pool_name, pool_name, strlen(pool_name)); + } + + filename = basename(namepath); + lmu.lum_type = LMV_STRIPE_TYPE; + dir = dirname(dirpath); + + data.ioc_inlbuf1 = (char *)filename; + data.ioc_inllen1 = strlen(filename) + 1; + data.ioc_inlbuf2 = (char *)&lmu; + data.ioc_inllen2 = sizeof(struct lmv_user_md); + rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf)); + if (rc) { + llapi_error(LLAPI_MSG_ERROR, rc, + "error: LL_IOC_LMV_SETSTRIPE pack failed '%s'.", + name); + GOTO(out, rc); + } + + fd = open(dir, O_DIRECTORY | O_RDONLY); + if (fd < 0) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'", name); + GOTO(out, rc); + } + + if (ioctl(fd, LL_IOC_LMV_SETSTRIPE, buf)) { + char *errmsg = "stripe already set"; + rc = -errno; + if (errno != EEXIST && errno != EALREADY) + errmsg = strerror(errno); + + llapi_err_noerrno(LLAPI_MSG_ERROR, + "error on LL_IOC_LMV_SETSTRIPE '%s' (%d): %s", + name, fd, errmsg); + } + close(fd); +out: + free(dirpath); + free(namepath); + return rc; +} + +int llapi_direntry_remove(char *dname) +{ + 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, rc); + } + + if (ioctl(fd, LL_IOC_REMOVE_ENTRY, filename)) { + char *errmsg = strerror(errno); + llapi_err_noerrno(LLAPI_MSG_ERROR, + "error on ioctl "LPX64" for '%s' (%d): %s", + (__u64)LL_IOC_LMV_SETSTRIPE, filename, + fd, errmsg); + } +out: + free(dirpath); + free(namepath); + if (fd != -1) + close(fd); + return rc; +} + /* * Find the fsname, the full path, and/or an open fd. * Either the fsname or path must not be NULL */ -#define WANT_PATH 0x1 -#define WANT_FSNAME 0x2 -#define WANT_FD 0x4 -#define WANT_INDEX 0x8 -#define WANT_ERROR 0x10 -static int get_root_path(int want, char *fsname, int *outfd, char *path, - int index) +int get_root_path(int want, char *fsname, int *outfd, char *path, int index) { struct mntent mnt; char buf[PATH_MAX], mntdir[PATH_MAX]; @@ -686,10 +878,11 @@ static int get_root_path(int want, char *fsname, int *outfd, char *path, mntlen = strlen(mnt.mnt_dir); ptr = strrchr(mnt.mnt_fsname, '/'); - if (!ptr && !len) { - rc = -EINVAL; - break; - } + /* thanks to the call to llapi_is_lustre_mnt() above, + * we are sure that mnt.mnt_fsname contains ":/", + * so ptr should never be NULL */ + if (ptr == NULL) + continue; ptr++; /* Check the fsname for a match, if given */ @@ -808,6 +1001,11 @@ int llapi_search_fsname(const char *pathname, char *fsname) return rc; } +int llapi_search_rootpath(char *pathname, const char *fsname) +{ + return get_root_path(WANT_PATH, (char *)fsname, NULL, pathname, -1); +} + int llapi_getname(const char *path, char *buf, size_t size) { struct obd_uuid uuid_buf; @@ -1018,7 +1216,7 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, rc = -errno; llapi_error(LLAPI_MSG_ERROR, rc, "Error reading pool list for '%s'", name); - return rc; + goto out; } else if ((rc == 0) && (cookie == NULL)) { /* end of directory */ break; @@ -1029,13 +1227,17 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, continue; /* check output bounds */ - if (nb_entries >= list_size) - return -EOVERFLOW; + if (nb_entries >= list_size) { + rc = -EOVERFLOW; + goto out; + } /* +2 for '.' and final '\0' */ - if (used + strlen(pool.d_name) + strlen(fsname) + 2 - > buffer_size) - return -EOVERFLOW; + if (used + strlen(pool.d_name) + strlen(fsname) + 2 + > buffer_size) { + rc = -EOVERFLOW; + goto out; + } sprintf(buffer + used, "%s.%s", fsname, pool.d_name); poollist[nb_entries] = buffer + used; @@ -1043,8 +1245,9 @@ int llapi_get_poollist(const char *name, char **poollist, int list_size, nb_entries++; } +out: closedir(dir); - return nb_entries; + return ((rc != 0) ? rc : nb_entries); } /* wrapper for lfs.c and obd.c */ @@ -1111,38 +1314,56 @@ err: } typedef int (semantic_func_t)(char *path, DIR *parent, DIR *d, - void *data, cfs_dirent_t *de); + void *data, struct dirent64 *de); #define OBD_NOT_FOUND (-1) static int common_param_init(struct find_param *param, char *path) { - param->lumlen = get_mds_md_size(path); - param->lmd = malloc(sizeof(lstat_t) + param->lumlen); - if (param->lmd == NULL) { - llapi_error(LLAPI_MSG_ERROR, -ENOMEM, - "error: allocation of %d bytes for ioctl", - sizeof(lstat_t) + param->lumlen); - return -ENOMEM; - } - - param->got_uuids = 0; - param->obdindexes = NULL; - param->obdindex = OBD_NOT_FOUND; - return 0; + int lumlen = get_mds_md_size(path); + + if (lumlen < PATH_MAX + 1) + lumlen = PATH_MAX + 1; + + param->lumlen = lumlen; + param->lmd = malloc(sizeof(lstat_t) + param->lumlen); + if (param->lmd == NULL) { + llapi_error(LLAPI_MSG_ERROR, -ENOMEM, + "error: allocation of %d bytes for ioctl", + sizeof(lstat_t) + param->lumlen); + return -ENOMEM; + } + + param->fp_lmv_count = 256; + param->fp_lmv_md = malloc(lmv_user_md_size(256, LMV_MAGIC_V1)); + if (param->fp_lmv_md == NULL) { + llapi_error(LLAPI_MSG_ERROR, -ENOMEM, + "error: allocation of %d bytes for ioctl", + lmv_user_md_size(256, LMV_MAGIC_V1)); + return -ENOMEM; + } + + param->got_uuids = 0; + param->obdindexes = NULL; + param->obdindex = OBD_NOT_FOUND; + param->mdtindex = OBD_NOT_FOUND; + return 0; } static void find_param_fini(struct find_param *param) { - if (param->obdindexes) - free(param->obdindexes); + if (param->obdindexes) + free(param->obdindexes); - if (param->lmd) - free(param->lmd); + if (param->lmd) + free(param->lmd); + + if (param->fp_lmv_md) + free(param->fp_lmv_md); } static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data, - cfs_dirent_t *de) + struct dirent64 *de) { struct find_param *param = (struct find_param *)data; param->depth--; @@ -1167,6 +1388,17 @@ static DIR *opendir_parent(char *path) return parent; } +static int cb_get_dirstripe(char *path, DIR *d, struct find_param *param) +{ + struct lmv_user_md *lmv = (struct lmv_user_md *)param->fp_lmv_md; + int ret = 0; + + lmv->lum_stripe_count = param->fp_lmv_count; + lmv->lum_magic = LMV_MAGIC_V1; + ret = ioctl(dirfd(d), LL_IOC_LMV_GETSTRIPE, lmv); + return ret; +} + static int get_lmd_info(char *path, DIR *parent, DIR *dir, struct lov_user_mds_data *lmd, int lumlen) { @@ -1211,32 +1443,25 @@ static int get_lmd_info(char *path, DIR *parent, DIR *dir, "%s ioctl failed for %s.", dir ? "LL_IOC_MDC_GETINFO" : "IOC_MDC_GETFILEINFO", path); - } else { - ret = -errno; - llapi_error(LLAPI_MSG_ERROR, ret, - "error: %s: IOC_MDC_GETFILEINFO failed for %s", - __func__, path); - } - } - return ret; -} - -int llapi_mds_getfileinfo(char *path, DIR *parent, - struct lov_user_mds_data *lmd) -{ - int lumlen = get_mds_md_size(path); - - return get_lmd_info(path, parent, NULL, lmd, lumlen); + } else { + ret = -errno; + llapi_error(LLAPI_MSG_ERROR, ret, + "error: %s: IOC_MDC_GETFILEINFO failed for %s", + __func__, path); + } + } + return ret; } static int llapi_semantic_traverse(char *path, int size, DIR *parent, - semantic_func_t sem_init, - semantic_func_t sem_fini, void *data, - cfs_dirent_t *de) + semantic_func_t sem_init, + semantic_func_t sem_fini, void *data, + struct dirent64 *de) { - cfs_dirent_t *dent; - int len, ret; - DIR *d, *p = NULL; + struct find_param *param = (struct find_param *)data; + struct dirent64 *dent; + int len, ret; + DIR *d, *p = NULL; ret = 0; len = strlen(path); @@ -1257,11 +1482,11 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, if (sem_init && (ret = sem_init(path, parent ?: p, d, data, de))) goto err; - if (!d) - GOTO(out, ret = 0); + if (!d || (param->get_lmv && !param->recursive)) + GOTO(out, ret = 0); - while ((dent = readdir64(d)) != NULL) { - ((struct find_param *)data)->have_fileinfo = 0; + while ((dent = readdir64(d)) != NULL) { + param->have_fileinfo = 0; if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; @@ -1281,20 +1506,18 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, strcat(path, dent->d_name); if (dent->d_type == DT_UNKNOWN) { - lstat_t *st = &((struct find_param *)data)->lmd->lmd_st; + lstat_t *st = ¶m->lmd->lmd_st; - ret = llapi_mds_getfileinfo(path, d, - ((struct find_param *)data)->lmd); + ret = get_lmd_info(path, d, NULL, param->lmd, + param->lumlen); if (ret == 0) { - ((struct find_param *)data)->have_fileinfo = 1; - dent->d_type = - llapi_filetype_dir_table[st->st_mode & - S_IFMT]; - } + dent->d_type = + llapi_filetype_dir_table[st->st_mode & + S_IFMT]; + } if (ret == -ENOENT) continue; - } - + } switch (dent->d_type) { case DT_UNKNOWN: llapi_err_noerrno(LLAPI_MSG_ERROR, @@ -1400,6 +1623,23 @@ int llapi_file_get_lov_uuid(const char *path, struct obd_uuid *lov_uuid) return rc; } +int llapi_file_get_lmv_uuid(const char *path, struct obd_uuid *lov_uuid) +{ + int fd, rc; + + fd = open(path, O_RDONLY); + if (fd < 0) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error opening %s", path); + return rc; + } + + rc = llapi_file_fget_lmv_uuid(fd, lov_uuid); + + close(fd); + return rc; +} + enum tgt_type { LOV_TYPE = 1, LMV_TYPE @@ -1589,10 +1829,12 @@ static int setup_indexes(DIR *dir, char *path, struct obd_uuid *obduuids, char buf[16]; int *indexes; - ret = get_param_obdvar(NULL, path, type == LOV_TYPE ? "lov" : "lmv", - "numobd", buf, sizeof(buf)); - if (ret) - return ret; + if (type == LOV_TYPE) + ret = get_param_lov(path, "numobd", buf, sizeof(buf)); + else + ret = get_param_lmv(path, "numobd", buf, sizeof(buf)); + if (ret != 0) + return ret; obdcount = atoi(buf); uuids = (struct obd_uuid *)malloc(obdcount * @@ -1608,8 +1850,10 @@ retry_get_uuids: if (ret == -EOVERFLOW) { uuids_temp = realloc(uuids, obdcount * sizeof(struct obd_uuid)); - if (uuids_temp != NULL) + if (uuids_temp != NULL) { + uuids = uuids_temp; goto retry_get_uuids; + } else ret = -ENOMEM; } @@ -1874,23 +2118,23 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, char nl = is_dir ? ' ' : '\n'; int rc; - if (is_dir && lum->lmm_object_seq == FID_SEQ_LOV_DEFAULT) { - lum->lmm_object_seq = FID_SEQ_OST_MDT0; - if (verbose & VERBOSE_DETAIL) - llapi_printf(LLAPI_MSG_NORMAL, "(Default) "); - } + if (is_dir && lmm_oi_seq(&lum->lmm_oi) == FID_SEQ_LOV_DEFAULT) { + lmm_oi_set_seq(&lum->lmm_oi, 0); + if (verbose & VERBOSE_DETAIL) + llapi_printf(LLAPI_MSG_NORMAL, "(Default) "); + } if (depth && path && ((verbose != VERBOSE_OBJID) || !is_dir)) llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); - if ((verbose & VERBOSE_DETAIL) && !is_dir) { - llapi_printf(LLAPI_MSG_NORMAL, "lmm_magic: 0x%08X\n", - lum->lmm_magic); - llapi_printf(LLAPI_MSG_NORMAL, "lmm_seq: "LPX64"\n", - lum->lmm_object_seq); - llapi_printf(LLAPI_MSG_NORMAL, "lmm_object_id: "LPX64"\n", - lum->lmm_object_id); - } + if ((verbose & VERBOSE_DETAIL) && !is_dir) { + llapi_printf(LLAPI_MSG_NORMAL, "lmm_magic: 0x%08X\n", + lum->lmm_magic); + llapi_printf(LLAPI_MSG_NORMAL, "lmm_seq: "LPX64"\n", + lmm_oi_seq(&lum->lmm_oi)); + llapi_printf(LLAPI_MSG_NORMAL, "lmm_object_id: "LPX64"\n", + lmm_oi_id(&lum->lmm_oi)); + } if (verbose & VERBOSE_COUNT) { if (verbose & ~VERBOSE_COUNT) @@ -1942,17 +2186,19 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, } } - if ((verbose & VERBOSE_DETAIL) && !is_dir) { - llapi_printf(LLAPI_MSG_NORMAL, "lmm_stripe_pattern: %x%c", - lum->lmm_pattern, nl); - } + if ((verbose & VERBOSE_LAYOUT) && !is_dir) { + if (verbose & ~VERBOSE_LAYOUT) + llapi_printf(LLAPI_MSG_NORMAL, "%spattern: ", + prefix); + llapi_printf(LLAPI_MSG_NORMAL, "%.x%c", lum->lmm_pattern, nl); + } if ((verbose & VERBOSE_GENERATION) && !is_dir) { if (verbose & ~VERBOSE_GENERATION) llapi_printf(LLAPI_MSG_NORMAL, "%slayout_gen: ", prefix); llapi_printf(LLAPI_MSG_NORMAL, "%u%c", - (int)lum->u.lum_layout_gen, nl); + (int)lum->lmm_layout_gen, nl); } if (verbose & VERBOSE_OFFSET) { @@ -2000,29 +2246,116 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, lov_dump_user_lmm_header(lum, path, objects, is_dir, header, depth, raw, pool_name); - if (!is_dir && (header & VERBOSE_OBJID)) { + if (!is_dir && (header & VERBOSE_OBJID) && + !(lum->lmm_pattern & LOV_PATTERN_F_RELEASED)) { if (obdstripe == 1) llapi_printf(LLAPI_MSG_NORMAL, - "\tobdidx\t\t objid\t\tobjid\t\t group\n"); + "\tobdidx\t\t objid\t\t objid\t\t group\n"); for (i = 0; i < lum->lmm_stripe_count; i++) { int idx = objects[i].l_ost_idx; - long long oid = objects[i].l_object_id; - long long gr = objects[i].l_object_seq; - if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx)) - llapi_printf(LLAPI_MSG_NORMAL, - "\t%6u\t%14llu\t%#13llx\t%14llu%s\n", - idx, oid, oid, gr, - obdindex == idx ? " *" : ""); + long long oid = ostid_id(&objects[i].l_ost_oi); + long long gr = ostid_seq(&objects[i].l_ost_oi); + if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx)) { + char fmt[48]; + sprintf(fmt, "%s%s%s\n", + "\t%6u\t%14llu\t%#13llx\t", + (fid_seq_is_rsvd(gr) || + fid_seq_is_mdt0(gr)) ? + "%14llu" : "%#14llx", "%s"); + llapi_printf(LLAPI_MSG_NORMAL, fmt, idx, oid, + oid, gr, + obdindex == idx ? " *" : ""); + } + } llapi_printf(LLAPI_MSG_NORMAL, "\n"); } } -void llapi_lov_dump_user_lmm(struct find_param *param, - char *path, int is_dir) +void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, + char *path, int obdindex, int depth, int verbose) +{ + struct lmv_user_mds_data *objects = lum->lum_objects; + char *prefix = lum->lum_magic == LMV_USER_MAGIC ? "(Default)" : ""; + int i, obdstripe = 0; + + if (obdindex != OBD_NOT_FOUND) { + for (i = 0; i < lum->lum_stripe_count; i++) { + if (obdindex == objects[i].lum_mds) { + llapi_printf(LLAPI_MSG_NORMAL, "%s%s\n", prefix, + path); + obdstripe = 1; + break; + } + } + } else { + obdstripe = 1; + } + + /* show all information default */ + if (!verbose) { + if (lum->lum_magic == LMV_USER_MAGIC) + verbose = VERBOSE_POOL | VERBOSE_COUNT | VERBOSE_OFFSET; + else + verbose = VERBOSE_OBJID; + } + + if (lum->lum_magic == LMV_USER_MAGIC) + verbose &= ~VERBOSE_OBJID; + + if (depth && path && ((verbose != VERBOSE_OBJID))) + llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path); + + if (verbose & VERBOSE_COUNT) { + if (verbose & ~VERBOSE_COUNT) + llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_count: "); + llapi_printf(LLAPI_MSG_NORMAL, "%u\n", + (int)lum->lum_stripe_count); + } + + if (verbose & VERBOSE_OFFSET) { + if (verbose & ~VERBOSE_OFFSET) + llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_offset: "); + llapi_printf(LLAPI_MSG_NORMAL, "%d\n", + (int)lum->lum_stripe_offset); + } + + if (verbose & VERBOSE_OBJID) { + if ((obdstripe == 1)) + llapi_printf(LLAPI_MSG_NORMAL, + "\tmdtidx\t\t FID[seq:oid:ver]\n"); + for (i = 0; i < lum->lum_stripe_count; i++) { + int idx = objects[i].lum_mds; + struct lu_fid *fid = &objects[i].lum_fid; + if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx)) + llapi_printf(LLAPI_MSG_NORMAL, + "\t%6u\t\t "DFID"\t\t%s\n", + idx, PFID(fid), + obdindex == idx ? " *" : ""); + } + + } + + if ((verbose & VERBOSE_POOL) && (pool_name[0] != '\0')) { + if (verbose & ~VERBOSE_POOL) + llapi_printf(LLAPI_MSG_NORMAL, "%slmv_pool: ", + prefix); + llapi_printf(LLAPI_MSG_NORMAL, "%s%c ", pool_name, ' '); + } + llapi_printf(LLAPI_MSG_NORMAL, "\n"); +} + +void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) { - switch(*(__u32 *)¶m->lmd->lmd_lmm) { /* lum->lmm_magic */ + __u32 magic; + + if (param->get_lmv) + magic = (__u32)param->fp_lmv_md->lum_magic; + else + magic = *(__u32 *)¶m->lmd->lmd_lmm; /* lum->lmm_magic */ + + switch (magic) { case LOV_USER_MAGIC_V1: lov_dump_user_lmm_v1v3(¶m->lmd->lmd_lmm, NULL, param->lmd->lmd_lmm.lmm_objects, @@ -2044,13 +2377,26 @@ void llapi_lov_dump_user_lmm(struct find_param *param, param->verbose, param->raw); break; } - default: - llapi_printf(LLAPI_MSG_NORMAL, "unknown lmm_magic: %#x " - "(expecting one of %#x %#x %#x)\n", - *(__u32 *)¶m->lmd->lmd_lmm, - LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3); - return; - } + case LMV_MAGIC_V1: + case LMV_USER_MAGIC: { + char pool_name[LOV_MAXPOOLNAME + 1]; + struct lmv_user_md *lum; + + lum = (struct lmv_user_md *)param->fp_lmv_md; + strncpy(pool_name, lum->lum_pool_name, LOV_MAXPOOLNAME); + lmv_dump_user_lmm(lum, pool_name, path, + param->obdindex, param->maxdepth, + param->verbose); + break; + } + default: + llapi_printf(LLAPI_MSG_NORMAL, "unknown lmm_magic: %#x " + "(expecting one of %#x %#x %#x %#x)\n", + *(__u32 *)¶m->lmd->lmd_lmm, + LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3, + LMV_USER_MAGIC, LMV_MAGIC_V1); + return; + } } int llapi_file_get_stripe(const char *path, struct lov_user_md *lum) @@ -2318,7 +2664,7 @@ static int print_failed_tgt(struct find_param *param, char *path, int type) } static int cb_find_init(char *path, DIR *parent, DIR *dir, - void *data, cfs_dirent_t *de) + void *data, struct dirent64 *de) { struct find_param *param = (struct find_param *)data; int decision = 1; /* 1 is accepted; -1 is rejected. */ @@ -2359,11 +2705,12 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir, /* Request MDS for the stat info if some of these parameters need * to be compared. */ - if (param->obduuid || param->mdtuuid || param->check_uid || - param->check_gid || param->check_pool || param->atime || - param->ctime || param->mtime || param->check_size || - param->check_stripecount || param->check_stripesize) - decision = 0; + if (param->obduuid || param->mdtuuid || param->check_uid || + param->check_gid || param->check_pool || param->atime || + param->ctime || param->mtime || param->check_size || + param->check_stripecount || param->check_stripesize || + param->check_layout) + decision = 0; if (param->type && checked_type == 0) decision = 0; @@ -2468,6 +2815,18 @@ static int cb_find_init(char *path, DIR *parent, DIR *dir, goto decided; } + if (param->check_layout) { + __u32 found; + + found = (param->lmd->lmd_lmm.lmm_pattern & param->layout); + if ((param->lmd->lmd_lmm.lmm_pattern == 0xFFFFFFFF) || + (found && param->exclude_layout) || + (!found && !param->exclude_layout)) { + decision = -1; + goto decided; + } + } + /* If an OBD UUID is specified but none matches, skip this file. */ if ((param->obduuid && param->obdindex == OBD_NOT_FOUND) || (param->mdtuuid && param->mdtindex == OBD_NOT_FOUND)) @@ -2639,7 +2998,7 @@ int llapi_file_fget_mdtidx(int fd, int *mdtidx) } static int cb_get_mdt_index(char *path, DIR *parent, DIR *d, void *data, - cfs_dirent_t *de) + struct dirent64 *de) { struct find_param *param = (struct find_param *)data; int ret = 0; @@ -2684,9 +3043,15 @@ static int cb_get_mdt_index(char *path, DIR *parent, DIR *d, void *data, return ret; } + /* The 'LASSERT(parent != NULL || d != NULL);' guarantees + * that either 'd' or 'parent' is not null. + * So in all cases llapi_file_fget_mdtidx() is called, + * thus initializing 'mdtidx'. */ if (param->quiet || !(param->verbose & VERBOSE_DETAIL)) + /* coverity[uninit_use_in_call] */ llapi_printf(LLAPI_MSG_NORMAL, "%d\n", mdtidx); else + /* coverity[uninit_use_in_call] */ llapi_printf(LLAPI_MSG_NORMAL, "%s\nmdt_index:\t%d\n", path, mdtidx); @@ -2700,7 +3065,7 @@ out: } static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, - cfs_dirent_t *de) + struct dirent64 *de) { struct find_param *param = (struct find_param *)data; int ret = 0; @@ -2714,38 +3079,50 @@ static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data, return ret; } - if (d) { - ret = ioctl(dirfd(d), LL_IOC_LOV_GETSTRIPE, - (void *)¶m->lmd->lmd_lmm); - } else if (parent) { - char *fname = strrchr(path, '/'); - fname = (fname == NULL ? path : fname + 1); + if (d) { + if (param->get_lmv) { + ret = cb_get_dirstripe(path, d, param); + } else { + ret = ioctl(dirfd(d), LL_IOC_LOV_GETSTRIPE, + (void *)¶m->lmd->lmd_lmm); + } - strncpy((char *)¶m->lmd->lmd_lmm, fname, param->lumlen); + } else if (parent) { + char *fname = strrchr(path, '/'); + fname = (fname == NULL ? path : fname + 1); - ret = ioctl(dirfd(parent), IOC_MDC_GETFILESTRIPE, - (void *)¶m->lmd->lmd_lmm); - } + if (param->get_lmv) { + llapi_printf(LLAPI_MSG_NORMAL, + "%s get dirstripe information for file\n", + path); + goto out; + } + + strncpy((char *)¶m->lmd->lmd_lmm, fname, param->lumlen); + + ret = ioctl(dirfd(parent), IOC_MDC_GETFILESTRIPE, + (void *)¶m->lmd->lmd_lmm); + } if (ret) { if (errno == ENODATA && d != NULL) { - /* We need to "fake" the "use the default" values - * since the lmm struct is zeroed out at this point. - * The magic needs to be set in order to satisfy - * a check later on in the code path. - * The object_seq needs to be set for the "(Default)" - * prefix to be displayed. */ - struct lov_user_md *lmm = ¶m->lmd->lmd_lmm; - lmm->lmm_magic = LOV_MAGIC_V1; - if (!param->raw) - lmm->lmm_object_seq = FID_SEQ_LOV_DEFAULT; - lmm->lmm_stripe_count = 0; - lmm->lmm_stripe_size = 0; - lmm->lmm_stripe_offset = -1; - goto dump; - + /* We need to "fake" the "use the default" values + * since the lmm struct is zeroed out at this point. + * The magic needs to be set in order to satisfy + * a check later on in the code path. + * The object_seq needs to be set for the "(Default)" + * prefix to be displayed. */ + struct lov_user_md *lmm = ¶m->lmd->lmd_lmm; + lmm->lmm_magic = LOV_USER_MAGIC_V1; + if (!param->raw) + ostid_set_seq(&lmm->lmm_oi, + FID_SEQ_LOV_DEFAULT); + lmm->lmm_stripe_count = 0; + lmm->lmm_stripe_size = 0; + lmm->lmm_stripe_offset = -1; + goto dump; } else if (errno == ENODATA && parent != NULL) { - if (!param->obduuid) + if (!param->obduuid && !param->mdtuuid) llapi_printf(LLAPI_MSG_NORMAL, "%s has no stripe info\n", path); goto out; @@ -2852,6 +3229,8 @@ int llapi_ping(char *obd_type, char *obd_name) return rc; } + /* The purpose is to send a byte as a ping, whatever this byte is. */ + /* coverity[uninit_use_in_call] */ rc = write(fd, buf, 1); if (rc < 0) rc = -errno; @@ -2926,51 +3305,6 @@ int llapi_target_check(int type_num, char **obd_type, char *dir) #undef MAX_STRING_SIZE -int llapi_catinfo(char *dir, char *keyword, char *node_name) -{ - char raw[OBD_MAX_IOCTL_BUFFER]; - char out[LLOG_CHUNK_SIZE]; - char *buf = raw; - struct obd_ioctl_data data = { 0 }; - char key[30]; - DIR *root; - int rc; - - sprintf(key, "%s", keyword); - memset(raw, 0, sizeof(raw)); - memset(out, 0, sizeof(out)); - data.ioc_inlbuf1 = key; - data.ioc_inllen1 = strlen(key) + 1; - if (node_name) { - data.ioc_inlbuf2 = node_name; - data.ioc_inllen2 = strlen(node_name) + 1; - } - data.ioc_pbuf1 = out; - data.ioc_plen1 = sizeof(out); - rc = obd_ioctl_pack(&data, &buf, sizeof(raw)); - if (rc) - return rc; - - root = opendir(dir); - if (root == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "open %s failed", dir); - return rc; - } - - rc = ioctl(dirfd(root), OBD_IOC_LLOG_CATINFO, buf); - if (rc) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, - "ioctl OBD_IOC_CATINFO failed"); - } else { - llapi_printf(LLAPI_MSG_NORMAL, "%s", data.ioc_pbuf1); - } - - closedir(root); - return rc; -} - /* Is this a lustre fs? */ int llapi_is_lustre_mnttype(const char *type) { @@ -3051,7 +3385,7 @@ int llapi_quotactl(char *mnt, struct if_quotactl *qctl) } static int cb_quotachown(char *path, DIR *parent, DIR *d, void *data, - cfs_dirent_t *de) + struct dirent64 *de) { struct find_param *param = (struct find_param *)data; lstat_t *st; @@ -3115,7 +3449,7 @@ static int rmtacl_notify(int ops) { FILE *fp; struct mntent *mnt; - int found = 0, fd, rc; + int found = 0, fd = 0, rc = 0; fp = setmntent(MOUNTED, "r"); if (fp == NULL) { @@ -3130,7 +3464,7 @@ static int rmtacl_notify(int ops) if (!mnt) break; - if (!llapi_is_lustre_mnt(mnt)) + if (!llapi_is_lustre_mnt(mnt)) continue; fd = open(mnt->mnt_dir, O_RDONLY | O_DIRECTORY); @@ -3138,20 +3472,25 @@ static int rmtacl_notify(int ops) rc = -errno; llapi_error(LLAPI_MSG_ERROR, rc, "Can't open '%s'\n", mnt->mnt_dir); - return rc; + goto out; } rc = ioctl(fd, LL_IOC_RMTACL, ops); + close(fd); if (rc < 0) { rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "ioctl %d\n", fd); - return rc; + llapi_error(LLAPI_MSG_ERROR, rc, + "ioctl RMTACL on '%s' err %d\n", + mnt->mnt_dir, rc); + goto out; } found++; } + +out: endmntent(fp); - return found; + return ((rc != 0) ? rc : found); } static char *next_token(char *p, int div) @@ -3444,8 +3783,8 @@ static int get_mdtname(char *name, char *format, char *buf) * \param mdtidxp pointer to integer within data to be filled in with the * mdt index (0 if no mdt is specified). NULL won't be filled. */ -static int root_ioctl(const char *mdtname, int opc, void *data, int *mdtidxp, - int want_error) +int root_ioctl(const char *mdtname, int opc, void *data, int *mdtidxp, + int want_error) { char fsname[20]; char *ptr; @@ -3571,6 +3910,24 @@ int llapi_changelog_fini(void **priv) return 0; } +/** Convert a changelog_rec to changelog_ext_rec, in this way client can treat + * all records in the format of changelog_ext_rec, this can make record + * analysis simpler. + */ +static inline int changelog_extend_rec(struct changelog_ext_rec *ext) +{ + if (!CHANGELOG_REC_EXTENDED(ext)) { + struct changelog_rec *rec = (struct changelog_rec *)ext; + + memmove(ext->cr_name, rec->cr_name, rec->cr_namelen); + fid_zero(&ext->cr_sfid); + fid_zero(&ext->cr_spfid); + return 1; + } + + return 0; +} + /** Read the next changelog entry * @param priv Opaque private control structure * @param rech Changelog record handle; record will be allocated here @@ -3578,7 +3935,7 @@ int llapi_changelog_fini(void **priv) * <0 error code * 1 EOF */ -int llapi_changelog_recv(void *priv, struct changelog_rec **rech) +int llapi_changelog_recv(void *priv, struct changelog_ext_rec **rech) { struct changelog_private *cp = (struct changelog_private *)priv; struct kuc_hdr *kuch; @@ -3619,10 +3976,11 @@ repeat: } } - /* Our message is a changelog_rec. Use pointer math to skip - * kuch_hdr and point directly to the message payload. - */ - *rech = (struct changelog_rec *)(kuch + 1); + /* Our message is a changelog_ext_rec. Use pointer math to skip + * kuch_hdr and point directly to the message payload. + */ + *rech = (struct changelog_ext_rec *)(kuch + 1); + changelog_extend_rec(*rech); return 0; @@ -3633,7 +3991,7 @@ out_free: } /** Release the changelog record when done with it. */ -int llapi_changelog_free(struct changelog_rec **rech) +int llapi_changelog_free(struct changelog_ext_rec **rech) { if (*rech) { /* We allocated memory starting at the kuc_hdr, but passed @@ -3712,215 +4070,54 @@ int llapi_fid2path(const char *device, const char *fidstr, char *buf, return rc; } -static int path2fid_from_lma(const char *path, lustre_fid *fid) +static int fid_from_lma(const char *path, const int fd, lustre_fid *fid) { - char buf[512]; - struct lustre_mdt_attrs *lma; - int rc; - - rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf)); - if (rc < 0) - return -errno; - lma = (struct lustre_mdt_attrs *)buf; - fid_le_to_cpu(fid, &lma->lma_self_fid); - return 0; + char buf[512]; + struct lustre_mdt_attrs *lma; + int rc; + + if (path == NULL) + rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf)); + else + rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf)); + if (rc < 0) + return -errno; + lma = (struct lustre_mdt_attrs *)buf; + fid_le_to_cpu(fid, &lma->lma_self_fid); + return 0; } -int llapi_path2fid(const char *path, lustre_fid *fid) +int llapi_fd2fid(const int fd, lustre_fid *fid) { - int fd, rc; + int rc; - memset(fid, 0, sizeof(*fid)); - fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW); - if (fd < 0) { - if (errno == ELOOP) /* symbolic link */ - return path2fid_from_lma(path, fid); - return -errno; - } + memset(fid, 0, sizeof(*fid)); - rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0; - if (rc == -EINVAL) /* char special device */ - rc = path2fid_from_lma(path, fid); + rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0; + if (rc == -EINVAL || rc == -ENOTTY) + rc = fid_from_lma(NULL, fd, fid); - close(fd); - return rc; -} - -/****** HSM Copytool API ********/ -#define CT_PRIV_MAGIC 0xC0BE2001 -struct copytool_private { - int magic; - char *fsname; - lustre_kernelcomm kuc; - __u32 archives; -}; - -#include - -/** Register a copytool - * @param[out] priv Opaque private control structure - * @param fsname Lustre filesystem - * @param flags Open flags, currently unused (e.g. O_NONBLOCK) - * @param archive_count - * @param archives Which archive numbers this copytool is responsible for - */ -int llapi_copytool_start(void **priv, char *fsname, int flags, - int archive_count, int *archives) -{ - struct copytool_private *ct; - int rc; - - if (archive_count > 0 && archives == NULL) { - llapi_err_noerrno(LLAPI_MSG_ERROR, - "NULL archive numbers"); - return -EINVAL; - } - - ct = calloc(1, sizeof(*ct)); - if (ct == NULL) - return -ENOMEM; - - ct->fsname = malloc(strlen(fsname) + 1); - if (ct->fsname == NULL) { - rc = -ENOMEM; - goto out_err; - } - strcpy(ct->fsname, fsname); - ct->magic = CT_PRIV_MAGIC; - ct->archives = 0; - for (rc = 0; rc < archive_count; rc++) { - if (archives[rc] > sizeof(ct->archives)) { - llapi_err_noerrno(LLAPI_MSG_ERROR, - "Maximum of %d archives supported", - sizeof(ct->archives)); - goto out_err; - } - ct->archives |= 1 << archives[rc]; - } - /* special case: if no archives specified, default to archive #0. */ - if (ct->archives == 0) - ct->archives = 1; - - rc = libcfs_ukuc_start(&ct->kuc, KUC_GRP_HSM); - if (rc < 0) - goto out_err; - - /* Storing archive(s) in lk_data; see mdc_ioc_hsm_ct_start */ - ct->kuc.lk_data = ct->archives; - rc = root_ioctl(ct->fsname, LL_IOC_HSM_CT_START, &(ct->kuc), NULL, - WANT_ERROR); - /* Only the kernel reference keeps the write side open */ - close(ct->kuc.lk_wfd); - ct->kuc.lk_wfd = 0; - if (rc < 0) - goto out_err; - - *priv = ct; - return 0; - -out_err: - if (ct->fsname) - free(ct->fsname); - free(ct); - return rc; + return rc; } -/** Deregister a copytool */ -int llapi_copytool_fini(void **priv) -{ - struct copytool_private *ct = (struct copytool_private *)*priv; - - if (!ct || (ct->magic != CT_PRIV_MAGIC)) - return -EINVAL; - - /* Tell the kernel to stop sending us messages */ - ct->kuc.lk_flags = LK_FLG_STOP; - root_ioctl(ct->fsname, LL_IOC_HSM_CT_START, &(ct->kuc), NULL, 0); - - /* Shut down the kernelcomms */ - libcfs_ukuc_stop(&ct->kuc); - - free(ct->fsname); - free(ct); - *priv = NULL; - return 0; -} - -/** Wait for the next hsm_action_list - * @param priv Opaque private control structure - * @param halh Action list handle, will be allocated here - * @param msgsize Number of bytes in the message, will be set here - * @return 0 valid message received; halh and msgsize are set - * <0 error code - */ -int llapi_copytool_recv(void *priv, struct hsm_action_list **halh, int *msgsize) -{ - struct copytool_private *ct = (struct copytool_private *)priv; - struct kuc_hdr *kuch; - struct hsm_action_list *hal; - int rc = 0; - - if (!ct || (ct->magic != CT_PRIV_MAGIC)) - return -EINVAL; - if (halh == NULL || msgsize == NULL) - return -EINVAL; - - kuch = malloc(HAL_MAXSIZE + sizeof(*kuch)); - if (kuch == NULL) - return -ENOMEM; - - rc = libcfs_ukuc_msg_get(&ct->kuc, (char *)kuch, - HAL_MAXSIZE + sizeof(*kuch), - KUC_TRANSPORT_HSM); - if (rc < 0) - goto out_free; - - /* Handle generic messages */ - if (kuch->kuc_transport == KUC_TRANSPORT_GENERIC && - kuch->kuc_msgtype == KUC_MSG_SHUTDOWN) { - rc = -ESHUTDOWN; - goto out_free; - } - - if (kuch->kuc_transport != KUC_TRANSPORT_HSM || - kuch->kuc_msgtype != HMT_ACTION_LIST) { - llapi_err_noerrno(LLAPI_MSG_ERROR, - "Unknown HSM message type %d:%d\n", - kuch->kuc_transport, kuch->kuc_msgtype); - rc = -EPROTO; - goto out_free; - } - - /* Our message is a hsm_action_list. Use pointer math to skip - * kuch_hdr and point directly to the message payload. - */ - hal = (struct hsm_action_list *)(kuch + 1); - - /* Check that we have registered for this archive # */ - if (((1 << hal->hal_archive_num) & ct->archives) == 0) { - llapi_err_noerrno(LLAPI_MSG_INFO, - "Ignoring request for archive #%d (bitmask %#x)\n", - hal->hal_archive_num, ct->archives); - rc = 0; - goto out_free; - } - - *halh = hal; - *msgsize = kuch->kuc_msglen - sizeof(*kuch); - return 0; - -out_free: - *halh = NULL; - *msgsize = 0; - free(kuch); - return rc; -} - -/** Release the action list when done with it. */ -int llapi_copytool_free(struct hsm_action_list **hal) +int llapi_path2fid(const char *path, lustre_fid *fid) { - /* Reuse the llapi_changelog_free function */ - return llapi_changelog_free((struct changelog_rec **)hal); + int fd, rc; + + memset(fid, 0, sizeof(*fid)); + fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW); + if (fd < 0) { + if (errno == ELOOP || errno == ENXIO) + return fid_from_lma(path, -1, fid); + return -errno; + } + + rc = llapi_fd2fid(fd, fid); + if (rc == -EINVAL || rc == -ENOTTY) + rc = fid_from_lma(path, -1, fid); + + close(fd); + return rc; } int llapi_get_connect_flags(const char *mnt, __u64 *flags) @@ -4002,3 +4199,121 @@ int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags) return rc; } + +/* + * Create a volatile file and open it for write: + * - file is created as a standard file in the directory + * - file does not appears in directory and directory mtime does not change + * - file is removed at close + * - file modes are rw-------, if user wants another one it must use fchmod() + * \param directory Directory where the file is created + * \param idx MDT index on which the file is created + * \param flags Std open flags + * + * \retval 0 on success. + * \retval -errno on error. + */ +int llapi_create_volatile_idx(char *directory, int idx, int mode) +{ + char file_path[PATH_MAX]; + char filename[PATH_MAX]; + int fd; + int random; + int rc; + + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) { + llapi_error(LLAPI_MSG_ERROR, errno, + "Cannot open /dev/urandom\n"); + return -errno; + } + rc = read(fd, &random, sizeof(random)); + close(fd); + if (rc < sizeof(random)) { + llapi_error(LLAPI_MSG_ERROR, errno, + "Cannot read %d bytes from /dev/urandom\n", + sizeof(random)); + return -errno; + } + if (idx == -1) + snprintf(filename, sizeof(filename), + LUSTRE_VOLATILE_HDR"::%.4X", random); + else + snprintf(filename, sizeof(filename), + LUSTRE_VOLATILE_IDX"%.4X", 0, random); + + rc = snprintf(file_path, sizeof(file_path), + "%s/%s", directory, filename); + if (rc >= sizeof(file_path)) + return -E2BIG; + + fd = open(file_path, (O_RDWR | O_CREAT | mode), (S_IRUSR | S_IWUSR)); + if (fd < 0) { + llapi_error(LLAPI_MSG_ERROR, errno, + "Cannot create volatile file %s in %s\n", + filename + LUSTRE_VOLATILE_HDR_LEN, + directory); + return -errno; + } + return fd; +} + +/** + * Swap the layouts between 2 file descriptors + * the 2 files must be open in write + * first fd received the ioctl, second fd is passed as arg + * this is assymetric but avoid use of root path for ioctl + */ +int llapi_fswap_layouts(int fd1, int fd2, __u64 dv1, __u64 dv2, __u64 flags) +{ + struct lustre_swap_layouts lsl; + int rc; + + srandom(time(NULL)); + lsl.sl_fd = fd2; + lsl.sl_flags = flags; + lsl.sl_gid = random(); + lsl.sl_dv1 = dv1; + lsl.sl_dv2 = dv2; + rc = ioctl(fd1, LL_IOC_LOV_SWAP_LAYOUTS, &lsl); + if (rc) + rc = -errno; + return rc; +} + +/** + * Swap the layouts between 2 files + * the 2 files are open in write + */ +int llapi_swap_layouts(const char *path1, const char *path2, + __u64 dv1, __u64 dv2, __u64 flags) +{ + int fd1, fd2, rc; + + fd1 = open(path1, O_WRONLY | O_LOV_DELAY_CREATE); + if (fd1 < 0) { + llapi_error(LLAPI_MSG_ERROR, -errno, + "error: cannot open for write %s", + path1); + return -errno; + } + + fd2 = open(path2, O_WRONLY | O_LOV_DELAY_CREATE); + if (fd2 < 0) { + llapi_error(LLAPI_MSG_ERROR, -errno, + "error: cannot open for write %s", + path2); + close(fd1); + return -errno; + } + + rc = llapi_fswap_layouts(fd1, fd2, dv1, dv2, flags); + if (rc < 0) + llapi_error(LLAPI_MSG_ERROR, rc, + "error: cannot swap layouts between %s and %s\n", + path1, path2); + + close(fd1); + close(fd2); + return rc; +}