X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fliblustreapi.c;h=8f69ac68693355c2519dcdfd1c79e1ad32f49763;hp=85057b82990f9e18f701c7c166e6194ad1ea5fbd;hb=6bbae72c6900dbd2b853d716bc4d456dc7fd586e;hpb=470bdeec6ca5b4c68f456a10d68511653e67b378 diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 85057b8..8f69ac6 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -68,6 +68,7 @@ #include #endif #include +#include #include #include @@ -1343,26 +1344,36 @@ int llapi_search_rootpath(char *pathname, const char *fsname) int llapi_getname(const char *path, char *buf, size_t size) { - struct obd_uuid uuid_buf; - char *uuid = uuid_buf.uuid; - int rc, nr; + struct obd_uuid uuid_buf; + char *uuid = uuid_buf.uuid; + char *cfg_instance; + int rc, len, fsname_len; - memset(&uuid_buf, 0, sizeof(uuid_buf)); - rc = llapi_file_get_lov_uuid(path, &uuid_buf); - if (rc) - return 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 lustre-clilov-ffff88002738bc00 into - * lustre-ffff88002738bc00. */ + /* + * We want to turn testfs-clilov-ffff88002738bc00 into + * testfs-ffff88002738bc00 in a portable way that doesn't depend + * on what is after "-clilov-" as it may change in the future. + * Unfortunately, the "fsname" part may contain a dash, so we + * can't just skip to the first dash, and the "instance" may be a + * UUID in the future, so we can't necessarily go to the last dash. + */ + cfg_instance = strstr(uuid, "-clilov-"); + if (!cfg_instance) + return -EINVAL; - nr = snprintf(buf, size, "%.*s-%s", - (int) (strlen(uuid) - 24), uuid, - uuid + strlen(uuid) - 16); + fsname_len = cfg_instance - uuid; + cfg_instance += strlen("-clilov-"); + len = snprintf(buf, size, "%.*s-%s", fsname_len, uuid, cfg_instance); - if (nr >= size) - rc = -ENAMETOOLONG; + if (len >= size) + rc = -ENAMETOOLONG; - return rc; + return rc; } /** @@ -1924,8 +1935,10 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent, rc = 0; if (sem_init) { rc = sem_init(path, d, NULL, data, dent); - if (rc < 0 && ret == 0) + if (rc < 0 && ret == 0) { ret = rc; + break; + } } if (sem_fini && rc == 0) sem_fini(path, d, NULL, data, dent); @@ -2481,7 +2494,8 @@ enum lov_dump_flags { static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, struct lov_user_ost_data_v1 *objects, - int verbose, int depth, char *pool_name, + enum llapi_layout_verbose verbose, + int depth, char *pool_name, enum lov_dump_flags flags) { bool is_dir = flags & LDF_IS_DIR; @@ -2552,8 +2566,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, seq, oid, ver); } - if (verbose & VERBOSE_COUNT) { - if (verbose & ~VERBOSE_COUNT) + if (verbose & VERBOSE_STRIPE_COUNT) { + if (verbose & ~VERBOSE_STRIPE_COUNT) llapi_printf(LLAPI_MSG_NORMAL, "%s%sstripe_count: ", space, prefix); if (is_dir) { @@ -2586,9 +2600,9 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, separator = "\n"; } - if (verbose & VERBOSE_SIZE) { + if (verbose & VERBOSE_STRIPE_SIZE) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); - if (verbose & ~VERBOSE_SIZE) + if (verbose & ~VERBOSE_STRIPE_SIZE) llapi_printf(LLAPI_MSG_NORMAL, "%s%sstripe_size: ", space, prefix); if (is_dir && !is_raw && lum->lmm_stripe_size == 0) { @@ -2611,9 +2625,9 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, separator = "\n"; } - if ((verbose & VERBOSE_LAYOUT)) { + if ((verbose & VERBOSE_PATTERN)) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); - if (verbose & ~VERBOSE_LAYOUT) + if (verbose & ~VERBOSE_PATTERN) llapi_printf(LLAPI_MSG_NORMAL, "%s%spattern: ", space, prefix); if (lov_pattern_supported(lum->lmm_pattern)) @@ -2634,9 +2648,9 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, separator = "\n"; } - if (verbose & VERBOSE_OFFSET) { + if (verbose & VERBOSE_STRIPE_OFFSET) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); - if (verbose & ~VERBOSE_OFFSET) + if (verbose & ~VERBOSE_STRIPE_OFFSET) llapi_printf(LLAPI_MSG_NORMAL, "%s%sstripe_offset: ", space, prefix); if (is_dir || skip_objs) @@ -2674,7 +2688,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path, void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, struct lov_user_ost_data_v1 *objects, char *path, int obdindex, int depth, - int header, enum lov_dump_flags flags) + enum llapi_layout_verbose verbose, + enum lov_dump_flags flags) { bool is_dir = flags & LDF_IS_DIR; bool indent = flags & LDF_INDENT; @@ -2695,10 +2710,10 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, if (!obdstripe) return; - lov_dump_user_lmm_header(lum, path, objects, header, depth, pool_name, + lov_dump_user_lmm_header(lum, path, objects, verbose, depth, pool_name, flags); - if (!is_dir && !skip_objs && (header & VERBOSE_OBJID) && + if (!is_dir && !skip_objs && (verbose & VERBOSE_OBJID) && !(lum->lmm_pattern & LOV_PATTERN_F_RELEASED || lov_pattern(lum->lmm_pattern) == LOV_PATTERN_MDT)) { char *space = " - "; @@ -2753,7 +2768,8 @@ void lov_dump_user_lmm_v1v3(struct lov_user_md *lum, char *pool_name, } void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, - char *path, int obdindex, int depth, int verbose, + char *path, int obdindex, int depth, + enum llapi_layout_verbose verbose, enum lov_dump_flags flags) { struct lmv_user_mds_data *objects = lum->lum_objects; @@ -2788,8 +2804,8 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, /* show all information default */ if (!verbose) { if (lum->lum_magic == LMV_USER_MAGIC) - verbose = VERBOSE_POOL | VERBOSE_COUNT | - VERBOSE_OFFSET | VERBOSE_HASH_TYPE; + verbose = VERBOSE_POOL | VERBOSE_STRIPE_COUNT | + VERBOSE_STRIPE_OFFSET | VERBOSE_HASH_TYPE; else verbose = VERBOSE_OBJID; } @@ -2797,21 +2813,21 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, if (depth && path && ((verbose != VERBOSE_OBJID))) llapi_printf(LLAPI_MSG_NORMAL, "%s%s\n", prefix, path); - if (verbose & VERBOSE_COUNT) { + if (verbose & VERBOSE_STRIPE_COUNT) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); - if (verbose & ~VERBOSE_COUNT) + if (verbose & ~VERBOSE_STRIPE_COUNT) llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_count: "); llapi_printf(LLAPI_MSG_NORMAL, "%u", (int)lum->lum_stripe_count); - if ((verbose & VERBOSE_OFFSET) && !yaml) + if ((verbose & VERBOSE_STRIPE_OFFSET) && !yaml) separator = " "; else separator = "\n"; } - if (verbose & VERBOSE_OFFSET) { + if (verbose & VERBOSE_STRIPE_OFFSET) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); - if (verbose & ~VERBOSE_OFFSET) + if (verbose & ~VERBOSE_STRIPE_OFFSET) llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_offset: "); llapi_printf(LLAPI_MSG_NORMAL, "%d", (int)lum->lum_stripe_offset); @@ -2822,7 +2838,8 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, } if (verbose & VERBOSE_HASH_TYPE) { - unsigned int type = lum->lum_hash_type; + unsigned int type = lum->lum_hash_type & LMV_HASH_TYPE_MASK; + unsigned int flags = lum->lum_hash_type & ~LMV_HASH_TYPE_MASK; llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); if (verbose & ~VERBOSE_HASH_TYPE) @@ -2831,9 +2848,18 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name, llapi_printf(LLAPI_MSG_NORMAL, "%s", mdt_hash_name[type]); else - llapi_printf(LLAPI_MSG_NORMAL, "%d", - (int)type); + llapi_printf(LLAPI_MSG_NORMAL, "%#x", type); + + if (flags & LMV_HASH_FLAG_MIGRATION) + llapi_printf(LLAPI_MSG_NORMAL, ",migrating"); + if (flags & LMV_HASH_FLAG_DEAD) + llapi_printf(LLAPI_MSG_NORMAL, ",dead"); + if (flags & LMV_HASH_FLAG_BAD_TYPE) + llapi_printf(LLAPI_MSG_NORMAL, ",bad_type"); + if (flags & LMV_HASH_FLAG_LOST_LMV) + llapi_printf(LLAPI_MSG_NORMAL, ",lost_lmv"); separator = "\n"; + } if (verbose & VERBOSE_OBJID && lum->lum_magic != LMV_USER_MAGIC) { @@ -2872,7 +2898,7 @@ static void lov_dump_comp_v1_header(struct find_param *param, char *path, { struct lov_comp_md_v1 *comp_v1 = (void *)¶m->fp_lmd->lmd_lmm; int depth = param->fp_max_depth; - int verbose = param->fp_verbose; + enum llapi_layout_verbose verbose = param->fp_verbose; bool yaml = flags & LDF_YAML; if (depth && path && ((verbose != VERBOSE_OBJID) || @@ -2957,7 +2983,7 @@ static void lov_dump_comp_v1_entry(struct find_param *param, struct lov_comp_md_v1 *comp_v1 = (void *)¶m->fp_lmd->lmd_lmm; struct lov_comp_md_entry_v1 *entry; char *separator = ""; - int verbose = param->fp_verbose; + enum llapi_layout_verbose verbose = param->fp_verbose; bool yaml = flags & LDF_YAML; entry = &comp_v1->lcm_entries[index]; @@ -3000,6 +3026,26 @@ static void lov_dump_comp_v1_entry(struct find_param *param, lcme_flags2str(entry->lcme_flags); separator = "\n"; } + /* print snapshot timestamp if its a nosync comp */ + if ((verbose & VERBOSE_COMP_FLAGS) && + (entry->lcme_flags & LCME_FL_NOSYNC)) { + llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); + if (verbose & ~VERBOSE_COMP_FLAGS) + llapi_printf(LLAPI_MSG_NORMAL, + "%4slcme_timestamp: ", " "); + if (yaml) { + llapi_printf(LLAPI_MSG_NORMAL, "%llu", + entry->lcme_timestamp); + } else { + time_t stamp = entry->lcme_timestamp; + char *date_str = asctime(localtime(&stamp)); + + date_str[strlen(date_str) - 1] = '\0'; + llapi_printf(LLAPI_MSG_NORMAL, "'%s'", date_str); + } + + separator = "\n"; + } if (verbose & VERBOSE_COMP_START) { llapi_printf(LLAPI_MSG_NORMAL, "%s", separator); @@ -3369,7 +3415,7 @@ static void lov_dump_comp_v1(struct find_param *param, char *path, static inline bool has_any_comp_options(struct find_param *param) { - int verbose = param->fp_verbose; + enum llapi_layout_verbose verbose = param->fp_verbose; if (param->fp_check_comp_id || param->fp_check_comp_count || param->fp_check_comp_start || param->fp_check_comp_end || @@ -3480,6 +3526,7 @@ static void llapi_lov_dump_user_lmm(struct find_param *param, char *path, switch (magic) { case LOV_USER_MAGIC_V1: case LOV_USER_MAGIC_V3: + case LOV_USER_MAGIC_SPECIFIC: lov_dump_plain_user_lmm(param, path, flags); break; case LMV_MAGIC_V1: @@ -4433,11 +4480,18 @@ migrate: sync(); retry = true; goto migrate; + } else if (errno == EALREADY) { + if (param->fp_verbose & VERBOSE_DETAIL) + fprintf(stdout, + "%s was migrated to MDT%d already\n", + path, lmu->lum_stripe_offset); + ret = 0; + } else { + ret = -errno; + fprintf(stderr, "%s migrate failed: %s (%d)\n", + path, strerror(-ret), ret); + goto out; } - ret = -errno; - fprintf(stderr, "%s migrate failed: %s (%d)\n", - path, strerror(-ret), ret); - goto out; } else if (param->fp_verbose & VERBOSE_DETAIL) { fprintf(stdout, "migrate %s to MDT%d stripe count %d\n", path, lmu->lum_stripe_offset, lmu->lum_stripe_count); @@ -4466,9 +4520,41 @@ out: return ret; } +/* dir migration finished, shrink its stripes */ +static int cb_migrate_mdt_fini(char *path, DIR *parent, DIR **dirp, void *data, + struct dirent64 *de) +{ + struct find_param *param = data; + struct lmv_user_md *lmu = param->fp_lmv_md; + int lmulen = lmv_user_md_size(lmu->lum_stripe_count, lmu->lum_magic); + int ret = 0; + + if (de && de->d_type != DT_DIR) + goto out; + + if (*dirp) { + /* + * close it before setxattr because the latter may destroy the + * original object, and cause close fail. + */ + ret = closedir(*dirp); + *dirp = NULL; + if (ret) + goto out; + } + + ret = setxattr(path, XATTR_NAME_LMV, lmu, lmulen, 0); + if (ret == -EALREADY) + ret = 0; +out: + cb_common_fini(path, parent, dirp, data, de); + return ret; +} + int llapi_migrate_mdt(char *path, struct find_param *param) { - return param_callback(path, cb_migrate_mdt_init, cb_common_fini, param); + return param_callback(path, cb_migrate_mdt_init, cb_migrate_mdt_fini, + param); } int llapi_mv(char *path, struct find_param *param) @@ -4735,26 +4821,32 @@ int llapi_obd_statfs(char *path, __u32 type, __u32 index, int llapi_ping(char *obd_type, char *obd_name) { + int flags = O_RDONLY; + char buf[1] = { 0 }; glob_t path; - char buf[1]; int rc, fd; rc = cfs_get_param_paths(&path, "%s/%s/ping", obd_type, obd_name); if (rc != 0) return -errno; - - fd = open(path.gl_pathv[0], O_WRONLY); +retry_open: + fd = open(path.gl_pathv[0], flags); if (fd < 0) { + if (errno == EACCES && flags == O_RDONLY) { + flags = O_WRONLY; + goto retry_open; + } rc = -errno; llapi_error(LLAPI_MSG_ERROR, rc, "error opening %s", path.gl_pathv[0]); goto failed; } - /* 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 (flags == O_RDONLY) + rc = read(fd, buf, sizeof(buf)); + else + rc = write(fd, buf, sizeof(buf)); if (rc < 0) rc = -errno; close(fd); @@ -5210,75 +5302,120 @@ int llapi_get_ost_layout_version(int fd, __u32 *layout_version) } /* - * Create a file without any name open it for read/write + * Create a file without any name and open it for read/write * * - file is created as if it were a standard file in the given \a directory * - file does not appear in \a directory and mtime does not change because * the filename is handled specially by the Lustre MDS. - * - file is removed at final close - * - file modes are rw------- since it doesn't make sense to have a read-only - * or write-only file that cannot be opened again. - * - if user wants another mode it must use fchmod() on the open file, no - * security problems arise because it cannot be opened by another process. + * - file is destroyed at final close * * \param[in] directory directory from which to inherit layout/MDT idx - * \param[in] idx MDT index on which the file is created, + * \param[in] mdt_idx MDT index on which the file is created, * \a idx == -1 means no specific MDT is requested - * \param[in] open_flags standard open(2) flags + * \param[in] mode standard open(2) mode + * \param[in] stripe_param stripe parameters. May be NULL. * - * \retval 0 on success. + * \retval a file descriptor on success. * \retval -errno on error. */ -int llapi_create_volatile_idx(char *directory, int idx, int open_flags) +int llapi_create_volatile_param(const char *directory, int mdt_idx, + int open_flags, mode_t mode, + const struct llapi_stripe_param *stripe_param) { - char file_path[PATH_MAX]; - char filename[PATH_MAX]; - int saved_errno = errno; - int fd; - int rnumber; - int rc; + char file_path[PATH_MAX]; + int saved_errno = errno; + int fd; + unsigned int rnumber; + int rc; do { rnumber = random(); - if (idx == -1) - snprintf(filename, sizeof(filename), - LUSTRE_VOLATILE_HDR"::%.4X", rnumber); + if (mdt_idx == -1) + rc = snprintf(file_path, sizeof(file_path), + "%s/" LUSTRE_VOLATILE_HDR "::%.4X", + directory, rnumber); else - snprintf(filename, sizeof(filename), - LUSTRE_VOLATILE_HDR":%.4X:%.4X", idx, rnumber); + rc = snprintf(file_path, sizeof(file_path), + "%s/" LUSTRE_VOLATILE_HDR ":%.4X:%.4X", + directory, mdt_idx, rnumber); + + if (rc < 0 || rc >= sizeof(file_path)) + return -ENAMETOOLONG; - rc = snprintf(file_path, sizeof(file_path), - "%s/%s", directory, filename); - if (rc >= sizeof(file_path)) - return -E2BIG; + /* + * Either open O_WRONLY or O_RDWR, creating RDONLY + * is non-sensical here + */ + if ((open_flags & O_ACCMODE) == O_RDONLY) + open_flags = O_RDWR | (open_flags & ~O_ACCMODE); - fd = open(file_path, - O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | open_flags, - S_IRUSR | S_IWUSR); - } while (fd < 0 && errno == EEXIST); + open_flags |= O_CREAT | O_EXCL | O_NOFOLLOW; + + if (stripe_param != NULL) { + fd = llapi_file_open_param(file_path, open_flags, + mode, stripe_param); + if (fd < 0) + rc = fd; + } else { + fd = open(file_path, open_flags, mode); + if (fd < 0) + rc = -errno; + } + } while (fd < 0 && rc == -EEXIST); if (fd < 0) { - llapi_error(LLAPI_MSG_ERROR, errno, + llapi_error(LLAPI_MSG_ERROR, rc, "Cannot create volatile file '%s' in '%s'", - filename + LUSTRE_VOLATILE_HDR_LEN, + file_path + strlen(directory) + 1 + + LUSTRE_VOLATILE_HDR_LEN, directory); - return -errno; + return rc; } - /* Unlink file in case this wasn't a Lustre filesystem and the - * magic volatile filename wasn't handled as intended. The - * effect is the same. If volatile open was supported then we - * expect unlink() to return -ENOENT. */ + /* + * Unlink file in case this wasn't a Lustre filesystem and the magic + * volatile filename wasn't handled as intended. The effect is the + * same. If volatile open was supported then we expect unlink() to + * return -ENOENT. + */ (void)unlink(file_path); - /* Since we are returning successfully we restore errno (and - * mask out possible EEXIST from open() and ENOENT from - * unlink(). */ + /* + * Since we are returning successfully we restore errno (and + * mask out possible EEXIST from open() and ENOENT from unlink(). + */ errno = saved_errno; return fd; } +/* + * Create a file without any name open it for read/write + * + * - file is created as if it were a standard file in the given \a directory + * - file does not appear in \a directory and mtime does not change because + * the filename is handled specially by the Lustre MDS. + * - file is removed at final close + * - file modes are rw------- since it doesn't make sense to have a read-only + * or write-only file that cannot be opened again. + * - if user wants another mode it must use fchmod() on the open file, no + * security problems arise because it cannot be opened by another process. + * + * \param[in] directory directory from which to inherit layout/MDT idx + * \param[in] idx MDT index on which the file is created, + * \a idx == -1 means no specific MDT is requested + * \param[in] open_flags standard open(2) flags + * + * \retval a file descriptor on success. + * \retval -errno on error. + */ +int llapi_create_volatile_idx(const char *directory, int mdt_idx, + int open_flags) +{ + return llapi_create_volatile_param(directory, mdt_idx, open_flags, + S_IRUSR | S_IWUSR, NULL); +} + /** * Swap the layouts between 2 file descriptors * the 2 files must be open for writing