From fceeeb07e01228eb42d51dea244db2a1a09c53fc Mon Sep 17 00:00:00 2001 From: adilger Date: Mon, 27 Oct 2003 19:34:19 +0000 Subject: [PATCH] Add new LOV EA format which gives us fields for features needed in the post 1.0 stage (e.g. RAID, OST migration/replacement) as well as more efficient storage than the current layout when there are few stripes on lots of OSTs. As well, we will now be able to back up/restore/manipulate EA data via the "getfattr" and "setfattr" tools (attr RPM) that are part of EA tools from the "trusted.lov" attribute (only accessible to root/priviledged users). Also contains code to transparently migrate from old EA format to new one the first time the EA is accessed. Note that there is no going back to old code on the same filesystem once the EAs have been updated. EA conversion is (hopefully) "fail safe" in that an error during conversion just means that the on-disk EA is kept in old format (clients understand both because of common code). Some of the "compat" code can be removed once we hit 1.0 and users have migrated, but the infrastructure itself should probably remain for the next time we need to change the EA format. This also adds "lustre_user.h" which was in b_llp_hp and has existed in b_llnl for some time, but alas the user EA format had to change in order to allow specification of striping format. A recompile should fix it. Some minor warts remain: - mds_objids_from_lmm() knows too much about lmm format. It had an existing bug (looping to ld_tgt_count vs lmm_ost_count) and caused another bug for me because it does its own unpacking of the lmm) and it would be nice to just get rid of it and use obd_unpackmd(lmm) to get an lsm instead and use that instead of "ids" - need to fix up endianness from ll_lov_setstripe() because this is now not done on the same host any more (object creation is done on MDS now) - liblustreapi() should not be doing the printing of structs, but should instead just return structs to user-space and/or using a callback function supplied by the caller (e.g. for lfind iterating over filesystem). The lov_dump_user_lmm* functions should probably be exported from the library and be used as default print functions as a starting point. b=2097 r=braam --- lustre/lov/lov_internal.h | 10 +- lustre/mds/mds_internal.h | 2 + lustre/utils/liblustreapi.c | 379 ++++++++++++++++++++++++-------------------- 3 files changed, 214 insertions(+), 177 deletions(-) diff --git a/lustre/lov/lov_internal.h b/lustre/lov/lov_internal.h index 77778fc..57ba1b3 100644 --- a/lustre/lov/lov_internal.h +++ b/lustre/lov/lov_internal.h @@ -21,7 +21,7 @@ struct lov_async_page { /* lov_obd.c */ int lov_get_stripecnt(struct lov_obd *lov, int stripe_count); -int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count); +int lov_alloc_memmd(struct lov_stripe_md **lsmp, int stripe_count, int pattern); void lov_free_memmd(struct lov_stripe_md **lsmp); /* lov_log.c */ @@ -47,12 +47,12 @@ int lov_log_add(struct obd_export *exp, /* lov_pack.c */ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmm, struct lov_stripe_md *lsm); -int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsm, - struct lov_mds_md *lmm, int lmmsize); +int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_mds_md *lmm, int lmm_bytes); int lov_setstripe(struct obd_export *exp, - struct lov_stripe_md **lsmp, struct lov_mds_md *lump); + struct lov_stripe_md **lsmp, struct lov_user_md *lump); int lov_getstripe(struct obd_export *exp, - struct lov_stripe_md *lsm, struct lov_mds_md *lump); + struct lov_stripe_md *lsm, struct lov_user_md *lump); /* lproc_lov.c */ extern struct file_operations lov_proc_target_fops; diff --git a/lustre/mds/mds_internal.h b/lustre/mds/mds_internal.h index 1c3aa7f..91ad656 100644 --- a/lustre/mds/mds_internal.h +++ b/lustre/mds/mds_internal.h @@ -62,6 +62,8 @@ int mds_lov_set_nextid(struct obd_device *obd); int mds_set_lovdesc(struct obd_device *obd, struct lov_desc *desc, struct obd_uuid *uuidarray); int mds_post_mds_lovconf(struct obd_device *obd); +int mds_convert_lov_ea(struct obd_device *obd, struct inode *inode, + struct lov_mds_md *lmm, int lmm_size); /* mds/mds_open.c */ int mds_query_write_access(struct inode *inode); diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index d0451ba..78091ef 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -43,52 +43,53 @@ #include #include #include -#include -#include +#include #include static void err_msg(char *fmt, ...) { - va_list args; - int tmp_errno = errno; + va_list args; + int tmp_errno = errno; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno); } int op_create_file(char *name, long stripe_size, int stripe_offset, - int stripe_count) + int stripe_count) { - struct lov_mds_md a_striping; - int fd, result = 0; - - /* Initialize IOCTL striping pattern structure */ - a_striping.lmm_magic = LOV_MAGIC; - a_striping.lmm_stripe_size = stripe_size; - a_striping.lmm_stripe_offset = stripe_offset; - a_striping.lmm_stripe_count = stripe_count; - - fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644); - if (fd < 0) { - err_msg("unable to open '%s'",name); - result = -errno; - } - else if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &a_striping)) { - char *errmsg = "stripe already set"; - if (errno != EEXIST && errno != EALREADY) - errmsg = strerror(errno); - - fprintf(stderr, "error on ioctl for '%s' (%d): %s\n", - name, fd, errmsg); - result = -errno; - } - else if (close(fd) < 0) { - err_msg("error on close for '%s' (%d)", name, fd); - result = -errno; - } - return result; + struct lov_user_md lum = { 0 }; + int fd, rc = 0; + + /* Initialize IOCTL striping pattern structure */ + lum.lmm_magic = LOV_USER_MAGIC; + lum.lmm_stripe_size = stripe_size; + lum.lmm_stripe_offset = stripe_offset; + lum.lmm_stripe_count = stripe_count; + + fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644); + if (fd < 0) { + err_msg("unable to open '%s'",name); + rc = -errno; + return rc; + } + if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum)) { + char *errmsg = "stripe already set"; + if (errno != EEXIST && errno != EALREADY) + errmsg = strerror(errno); + + fprintf(stderr, "error on ioctl for '%s' (%d): %s\n", + name, fd, errmsg); + rc = -errno; + } + if (close(fd) < 0) { + err_msg("error on close for '%s' (%d)", name, fd); + if (rc == 0) + rc = -errno; + } + return rc; } @@ -103,7 +104,7 @@ struct find_param { char *buf; int buflen; struct obd_uuid *uuids; - struct lov_mds_md *lmm; + struct lov_user_md *lum; int got_uuids; int obdindex; int max_ost_count; @@ -115,53 +116,50 @@ struct find_param { static int prepare_find(struct find_param *param) { - int datalen, desclen; - int cfglen, lmmlen; + int datalen, desclen; + int cfglen, lumlen; int max_ost_count = MAX_LOV_UUID_COUNT; - - datalen = size_round(sizeof(struct obd_ioctl_data)); - desclen = size_round(sizeof(struct lov_desc)); - param->uuidslen = size_round(max_ost_count * sizeof(struct obd_uuid)); - cfglen = datalen + desclen + param->uuidslen; - lmmlen = lov_mds_md_size(max_ost_count); - if (cfglen > lmmlen) - param->buflen = cfglen; - else - param->buflen = lmmlen; - - /* XXX max ioctl buffer size currently hardcoded to 8192 */ - if (param->buflen > 8192) { - int nuuids, remaining, nluoinfos; - - param->buflen = 8192; - nuuids = (param->buflen - datalen - desclen) / sizeof(struct obd_uuid); - param->uuidslen = size_round(nuuids * sizeof(struct obd_uuid)); - remaining = nuuids * sizeof(struct obd_uuid); - if (param->uuidslen > remaining) - nuuids--; - nluoinfos = (param->buflen - sizeof(struct lov_mds_md)) / - sizeof(*(param->lmm->lmm_objects)); - if (nuuids > nluoinfos) - max_ost_count = nluoinfos; - else - max_ost_count = nuuids; - - cfglen = datalen + desclen + param->uuidslen; - lmmlen = lov_mds_md_size(max_ost_count); - } - - if ((param->buf = malloc(param->buflen)) == NULL) { - err_msg("unable to allocate %d bytes of memory for ioctl's", - param->buflen); - return 1; - } - - param->lmm = (struct lov_mds_md *)param->buf; - param->uuids = (struct obd_uuid *)param->buf; + + datalen = size_round(sizeof(param->data)); + desclen = size_round(sizeof(param->desc)); + param->uuidslen = size_round(max_ost_count * sizeof(*param->uuids)); + cfglen = datalen + desclen + param->uuidslen; + lumlen = lov_mds_md_size(max_ost_count); + if (cfglen > lumlen) + param->buflen = cfglen; + else + param->buflen = lumlen; + + /* XXX max ioctl buffer size currently hardcoded to 8192 */ + if (param->buflen > 8192) { + int nuuids, remaining; + + param->buflen = 8192; + nuuids = (param->buflen - datalen - desclen) / + sizeof(*param->uuids); + param->uuidslen = size_round(nuuids * sizeof(*param->uuids)); + remaining = nuuids * sizeof(*param->uuids); + if (param->uuidslen > remaining) + nuuids--; + max_ost_count = nuuids; + while ((lumlen=lov_mds_md_size(max_ost_count)) > param->buflen) + --max_ost_count; + + cfglen = datalen + desclen + param->uuidslen; + } + + if ((param->buf = malloc(param->buflen)) == NULL) { + err_msg("unable to allocate %d bytes of memory for ioctl's", + param->buflen); + return ENOMEM; + } + + param->lum = (struct lov_user_md *)param->buf; + param->uuids = (struct obd_uuid *)param->buf; param->got_uuids = 0; param->obdindex = OBD_NOT_FOUND; param->max_ost_count = max_ost_count; - + return 0; } @@ -173,14 +171,14 @@ static void cleanup_find(struct find_param *param) free(param->buf); } -static void get_obd_uuids(DIR *dir, char *dname, struct find_param *param) +static int get_obd_uuids(DIR *dir, char *dname, struct find_param *param) { - int obdcount; - struct obd_uuid *uuidp; - int rc, i; + int obdcount; + struct obd_uuid *uuidp; + int rc, i; param->got_uuids = 1; - memset(¶m->data, 0, sizeof(struct obd_ioctl_data)); + memset(¶m->data, 0, sizeof(param->data)); param->data.ioc_inllen1 = sizeof(struct lov_desc); param->data.ioc_inlbuf1 = (char *)¶m->desc; param->data.ioc_inllen2 = param->uuidslen; @@ -191,23 +189,23 @@ static void get_obd_uuids(DIR *dir, char *dname, struct find_param *param) if (obd_ioctl_pack(¶m->data, ¶m->buf, param->buflen)) { fprintf(stderr, "internal buffer error from %s\n", dname); - return; + return (param->obduuid ? EINVAL : 0); } rc = ioctl(dirfd(dir), OBD_IOC_LOV_GET_CONFIG, param->buf); if (rc) { err_msg("error getting LOV config from %s", dname); - return; + return (param->obduuid ? errno : 0); } if (obd_ioctl_unpack(¶m->data, param->buf, param->buflen)) { err_msg("invalid reply from ioctl from %s", dname); - return; + return (param->obduuid ? EINVAL : 0); } obdcount = param->desc.ld_tgt_count; if (obdcount == 0) - return; + return 0; if (param->obduuid) { for (i = 0, uuidp = param->uuids; i < obdcount; i++, uuidp++) { @@ -217,93 +215,118 @@ static void get_obd_uuids(DIR *dir, char *dname, struct find_param *param) break; } } - - if (param->obdindex == OBD_NOT_FOUND) - return; } else if (!param->quiet) { printf("OBDS:\n"); for (i = 0, uuidp = param->uuids; i < obdcount; i++, uuidp++) printf("%4d: %s\n", i, uuidp->uuid); } + + return 0; } -static void process_file(DIR *dir, char *dname, char *fname, struct find_param *param) +void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *dname, char *fname, + int obdindex, int quiet, int header, int body) { - int rc, i; + int i; - strncpy((char *)param->lmm, fname, param->buflen); + if (obdindex != OBD_NOT_FOUND) { + for (i = 0; i < lum->lmm_stripe_count; i++) { + if (obdindex == lum->lmm_objects[i].l_ost_idx) { + printf("%s/%s\n", dname, fname); + break; + } + } + } else if (!quiet) { + printf("%s/%s\n", dname, fname); + } - rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)param->lmm); - if (rc) { - if (errno == ENODATA) { - if (!param->obduuid && !param->quiet) - fprintf(stderr, - "%s/%s has no stripe info\n", - dname, fname); - } else if (errno == EISDIR) { - fprintf(stderr, "process_file on directory %s/%s!\n", - dname, fname); - /* - add fname to directory list; - */ - } else { - err_msg("IOC_MDC_GETSTRIPE ioctl failed"); - } - return; - } + if (header) { + printf("lmm_magic: 0x%80X\n", lum->lmm_magic); + printf("lmm_object_gr: "LPX64"\n", lum->lmm_object_gr); + printf("lmm_object_id: "LPX64"\n", lum->lmm_object_id); + printf("lmm_stripe_count: %u\n", (int)lum->lmm_stripe_count); + printf("lmm_stripe_size: %u\n", lum->lmm_stripe_size); + printf("lmm_stripe_pattern: %x\n", lum->lmm_pattern); + } - if ((param->obduuid && param->lmm->lmm_objects[param->obdindex].l_object_id) || - (!param->obduuid && !param->quiet)) - printf("%s/%s\n", dname, fname); + if (body) { + long long oid; - if (param->verbose) { - printf("lmm_magic: 0x%x\n", param->lmm->lmm_magic); - printf("lmm_object_id: "LPX64"\n", param->lmm->lmm_object_id); - printf("lmm_stripe_offset: %u\n", (int)param->lmm->lmm_stripe_offset); - printf("lmm_stripe_count: %u\n", (int)param->lmm->lmm_stripe_count); - printf("lmm_stripe_size: %u\n", (int)param->lmm->lmm_stripe_size); - printf("lmm_ost_count: %u\n", param->lmm->lmm_ost_count); - printf("lmm_stripe_pattern: %d\n", param->lmm->lmm_magic & 0xf); + if (!quiet) + printf("\tobdidx\t\t objid\t\tobjid\t\t group\n"); + + for (i = 0; i < lum->lmm_stripe_count; i++) { + int idx = lum->lmm_objects[i].l_ost_idx; + oid = lum->lmm_objects[i].l_object_id; + printf("\t%6u\t%14llu\t%#13llx\t%14lld%s\n", idx, oid, + oid, lum->lmm_objects[i].l_object_gr, + obdindex == idx ? " *" : ""); + } + printf("\n"); } +} - if (param->verbose || !param->obduuid) { - long long oid; - int ost = param->lmm->lmm_stripe_offset; - int header = !param->quiet; - - /* FIXME: temporary fix for bug 1612 */ - if (param->lmm->lmm_ost_count == 0) { - oid = param->lmm->lmm_object_id; - if (header) - printf("\tobdidx\t\t objid\t\tobjid\n"); - printf("\t%6u\t%14llu\t%#13llx\n", 0, oid, oid); - } else - for (i = 0; i < param->lmm->lmm_ost_count; i++, ost++) { - ost %= param->lmm->lmm_ost_count; - if ((oid = param->lmm->lmm_objects[ost].l_object_id)) { - if (header) { - printf("\tobdidx\t\t objid\t\tobjid\n"); - header = 0; - } - printf("\t%6u\t%14llu\t%#13llx%s\n", ost, - oid, oid, param->obdindex == ost ? " *" : ""); - } - } - printf("\n"); - } +void lov_dump_user_lmm(struct find_param *param, char *dname, char *fname) +{ + switch(*(__u32 *)param->lum) { /* lum->lmm_magic */ + case LOV_USER_MAGIC_V1: + lov_dump_user_lmm_v1(param->lum, dname, fname, param->obdindex, + param->quiet, param->verbose, + (param->verbose || !param->obduuid)); + break; + default: + printf("unknown lmm_magic: 0x%08X\n", *(__u32 *)param->lum); + return; + } } +static int process_file(DIR *dir, char *dname, char *fname, + struct find_param *param) +{ + int rc; -static void process_dir(DIR *dir, char *dname, struct find_param *param) + strncpy((char *)param->lum, fname, param->buflen); + + rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)param->lum); + if (rc) { + if (errno == ENODATA) { + if (!param->obduuid && !param->quiet) + fprintf(stderr, + "%s/%s has no stripe info\n", + dname, fname); + rc = 0; + } else if (errno == EISDIR) { + fprintf(stderr, "process_file on directory %s/%s!\n", + dname, fname); + /* add fname to directory list; */ + rc = errno; + } else { + err_msg("IOC_MDC_GETSTRIPE ioctl failed"); + rc = errno; + } + return rc; + } + + lov_dump_user_lmm(param, dname, fname); + + return 0; +} + + +static int process_dir(DIR *dir, char *dname, struct find_param *param) { - struct dirent64 *dirp; + struct dirent64 *dirp; DIR *subdir; - char path[1024]; + char path[1024]; + int rc; - if (!param->got_uuids) - get_obd_uuids(dir, dname, param); + if (!param->got_uuids) { + rc = get_obd_uuids(dir, dname, param); + if (rc) + return rc; + } - /* Handle the contents of the directory */ + /* Handle the contents of the directory */ while ((dirp = readdir64(dir)) != NULL) { if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, "..")) continue; @@ -311,12 +334,12 @@ static void process_dir(DIR *dir, char *dname, struct find_param *param) switch (dirp->d_type) { case DT_UNKNOWN: err_msg("\"%s\" is UNKNOWN type %d", dirp->d_name, - dirp->d_type); + dirp->d_type); /* If we cared we could stat the file to determine * type and continue on here, but we don't since we * know d_type should be valid for lustre and this * tool only makes sense for lustre filesystems. */ - return; + return EINVAL; break; case DT_DIR: if (!param->recursive) @@ -327,24 +350,31 @@ static void process_dir(DIR *dir, char *dname, struct find_param *param) subdir = opendir(path); if (subdir == NULL) { err_msg("\"%.40s\" opendir failed", path); - break; + return errno; } - process_dir(subdir, path, param); + rc = process_dir(subdir, path, param); closedir(subdir); + if (rc) + return rc; break; case DT_REG: - process_file(dir, dname, dirp->d_name, param); + rc = process_file(dir, dname, dirp->d_name, param); + if (rc) + return rc; break; default: break; } } + + return 0; } -static void process_path(char *path, struct find_param *param) +static int process_path(char *path, struct find_param *param) { char *fname, *dname; DIR *dir; + int rc = 0; fname = strrchr(path, '/'); if (fname != NULL && fname[1] == '\0') { @@ -353,13 +383,14 @@ static void process_path(char *path, struct find_param *param) dir = opendir(path); if (dir == NULL) { err_msg("\"%.40s\" opendir failed", path); + rc = errno; } else { - process_dir(dir, path, param); + rc = process_dir(dir, path, param); closedir(dir); } } else if ((dir = opendir(path)) != NULL) { /* No trailing '/', but it is still a dir */ - process_dir(dir, path, param); + rc = process_dir(dir, path, param); closedir(dir); } else { /* It must be a file (or other non-directory) */ @@ -374,18 +405,22 @@ static void process_path(char *path, struct find_param *param) dir = opendir(dname); if (dir == NULL) { err_msg("\"%.40s\" opendir failed", dname); + rc = errno; } else { if (!param->got_uuids) - get_obd_uuids(dir, dname, param); - process_file(dir, dname, fname, param); + rc = get_obd_uuids(dir, dname, param); + if (rc == 0) + rc = process_file(dir, dname, fname, param); closedir(dir); } } + + return rc; } -int op_find(char *path, struct obd_uuid *obduuid, int recursive, - int verbose, int quiet) +int op_find(char *path, struct obd_uuid *obduuid, int recursive, + int verbose, int quiet) { struct find_param param; int ret = 0; @@ -395,12 +430,12 @@ int op_find(char *path, struct obd_uuid *obduuid, int recursive, param.verbose = verbose; param.quiet = quiet; if (obduuid) { - param.obduuid = (struct obd_uuid*)malloc(sizeof(struct obd_uuid)); + param.obduuid = malloc(sizeof(*obduuid)); if (param.obduuid == NULL) { - ret = 1; + ret = ENOMEM; goto out; } - memcpy(param.obduuid, obduuid, sizeof(struct obd_uuid)); + memcpy(param.obduuid, obduuid, sizeof(*obduuid)); } ret = prepare_find(¶m); @@ -412,4 +447,4 @@ out: cleanup_find(¶m); return ret; } - + -- 1.8.3.1