From 5059c744cbf541df3d410e7843eb4b2f61ace4cc Mon Sep 17 00:00:00 2001 From: donmilos Date: Tue, 5 Nov 2002 01:48:17 +0000 Subject: [PATCH] Issue# 330: Approver: Andreas - New utility to find files affected by loss of an OBD. --- lustre/include/linux/lustre_lite.h | 8 + lustre/llite/file.c | 57 ++++++- lustre/lov/lov_obd.c | 37 ++++- lustre/osc/osc_request.c | 37 +++++ lustre/utils/Makefile.am | 4 +- lustre/utils/lfind.c | 318 +++++++++++++++++++++++++++++++++++++ 6 files changed, 458 insertions(+), 3 deletions(-) create mode 100644 lustre/utils/lfind.c diff --git a/lustre/include/linux/lustre_lite.h b/lustre/include/linux/lustre_lite.h index ec5ec35..1ed055f 100644 --- a/lustre/include/linux/lustre_lite.h +++ b/lustre/include/linux/lustre_lite.h @@ -255,12 +255,20 @@ void ll_sysctl_clean(void); #define LL_IOC_SETFLAGS _IOW ('f', 152, long) #define LL_IOC_CLRFLAGS _IOW ('f', 153, long) #define LL_IOC_LOV_SETSTRIPE _IOW ('f', 154, long) +#define LL_IOC_LOV_GETSTRIPE _IOW ('f', 155, long) + +struct lov_user_oinfo { + __u64 luo_id; /* object ID on the target OBD */ + __u32 luo_idx; /* OBD stripe index in lmd_objects array */ + __u32 luo_pad; +}; struct lov_user_md { __u64 lum_stripe_size; __u32 lum_stripe_pattern; __u32 lum_stripe_offset; __u32 lum_stripe_count; + struct lov_user_oinfo lum_luoinfo[0]; }; #define O_LOV_DELAY_CREATE 0100000000 /* hopefully this does not conflict */ diff --git a/lustre/llite/file.c b/lustre/llite/file.c index 0bd1198..5648826 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -605,10 +605,62 @@ out_lov_up: return rc; } +static int ll_lov_getstripe(struct inode *inode, unsigned long arg) +{ + struct lov_user_md lum; + struct lov_user_md *lump; + struct ll_inode_info *lli = ll_i2info(inode); + struct lov_stripe_md *lsm = lli->lli_smd; + struct lov_user_oinfo *luoip; + struct lov_oinfo *loip; + int count, len, i, rc; + + rc = copy_from_user(&lum, (void *)arg, sizeof(lum)); + if (rc) + RETURN(rc); + + if ((count = lsm->lsm_stripe_count) == 0) + count = 1; + + if (lum.lum_stripe_count < count) + RETURN(-EINVAL); + + len = sizeof(*lump) + count * sizeof(*luoip); + + rc = verify_area(VERIFY_WRITE, (void *)arg, len); + if (rc) + RETURN(rc); + + lump = (struct lov_user_md *)arg; + lump->lum_stripe_count = count; + luoip = lump->lum_luoinfo; + + if (lsm->lsm_stripe_count == 0) { + lump->lum_stripe_size = 0; + lump->lum_stripe_pattern = 0; + lump->lum_stripe_offset = 0; + luoip->luo_idx = 0; + luoip->luo_id = lsm->lsm_object_id; + } else { + lump->lum_stripe_size = lsm->lsm_stripe_size; + lump->lum_stripe_pattern = lsm->lsm_stripe_pattern; + lump->lum_stripe_offset = lsm->lsm_stripe_offset; + + loip = lsm->lsm_oinfo; + for (i = 0; i < count; i++, luoip++, loip++) { + luoip->luo_idx = loip->loi_ost_idx; + luoip->luo_id = loip->loi_id; + } + } + + RETURN(0); +} + int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct ll_file_data *fd = (struct ll_file_data *)file->private_data; + struct lustre_handle *conn; int flags; switch(cmd) { @@ -631,6 +683,8 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; case LL_IOC_LOV_SETSTRIPE: return ll_lov_setstripe(inode, file, (struct lov_user_md *)arg); + case LL_IOC_LOV_GETSTRIPE: + return ll_lov_getstripe(inode, arg); /* We need to special case any other ioctls we want to handle, * to send them to the MDS/OST as appropriate and to properly @@ -643,7 +697,8 @@ int ll_file_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case EXT2_IOC_SETVERSION_NEW: */ default: - return -ENOTTY; + conn = ll_i2obdconn(inode); + return obd_iocontrol(cmd, conn, 0, NULL, (void *)arg); } } diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index 9d57f0e..0530a82 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -1298,13 +1298,48 @@ static int lov_iocontrol(long cmd, struct lustre_handle *conn, int len, struct obd_device *obddev = class_conn2obd(conn); struct obd_ioctl_data *data = karg; struct lov_obd *lov = &obddev->u.lov; - int rc, i; + struct lov_desc *desc; + struct lov_tgt_desc *tgtdesc; + obd_uuid_t *uuidp; + char *buf; + int rc, i, count; ENTRY; switch (cmd) { case IOC_LOV_SET_OSC_ACTIVE: rc = lov_set_osc_active(lov,data->ioc_inlbuf1,data->ioc_offset); break; + case OBD_IOC_LOV_GET_CONFIG: + buf = NULL; + len = 0; + if (obd_ioctl_getdata(&buf, &len, (void *)uarg)) + RETURN(-EINVAL); + + data = (struct obd_ioctl_data *)buf; + + if (sizeof(*desc) > data->ioc_inllen1) { + OBD_FREE(buf, len); + RETURN(-EINVAL); + } + + count = lov->desc.ld_tgt_count; + + if (sizeof(*uuidp) * count > data->ioc_inllen2) { + OBD_FREE(buf, len); + RETURN(-EINVAL); + } + + desc = (struct lov_desc *)data->ioc_inlbuf1; + uuidp = (obd_uuid_t *)data->ioc_inlbuf2; + memcpy(desc, &(lov->desc), sizeof(*desc)); + + tgtdesc = lov->tgts; + for (i = 0; i < count; i++, uuidp++, tgtdesc++) + memcpy(uuidp, tgtdesc->uuid, sizeof(*uuidp)); + + rc = copy_to_user((void *)uarg, buf, len); + OBD_FREE(buf, len); + break; default: if (lov->desc.ld_tgt_count == 0) RETURN(-ENOTTY); diff --git a/lustre/osc/osc_request.c b/lustre/osc/osc_request.c index a28de1f..6de5d7e 100644 --- a/lustre/osc/osc_request.c +++ b/lustre/osc/osc_request.c @@ -811,7 +811,44 @@ static int osc_iocontrol(long cmd, struct lustre_handle *conn, int len, obddev->u.cli.cl_containing_lov = (struct obd_device *)karg; GOTO(out, err); } + case OBD_IOC_LOV_GET_CONFIG: { + char *buf; + struct lov_desc *desc; + obd_uuid_t *uuidp; + buf = NULL; + len = 0; + if (obd_ioctl_getdata(&buf, &len, (void *)uarg)) + GOTO(out, err = -EINVAL); + + data = (struct obd_ioctl_data *)buf; + + if (sizeof(*desc) > data->ioc_inllen1) { + OBD_FREE(buf, len); + GOTO(out, err = -EINVAL); + } + + if (data->ioc_inllen2 < sizeof(*uuidp)) { + OBD_FREE(buf, len); + GOTO(out, err = -EINVAL); + } + + desc = (struct lov_desc *)data->ioc_inlbuf1; + desc->ld_tgt_count = 1; + desc->ld_active_tgt_count = 1; + desc->ld_default_stripe_count = 1; + desc->ld_default_stripe_size = 0; + desc->ld_default_stripe_offset = 0; + desc->ld_pattern = 0; + memcpy(desc->ld_uuid, obddev->obd_uuid, sizeof(*uuidp)); + + uuidp = (obd_uuid_t *)data->ioc_inlbuf2; + memcpy(uuidp, obddev->obd_uuid, sizeof(*uuidp)); + + err = copy_to_user((void *)uarg, buf, len); + OBD_FREE(buf, len); + GOTO(out, err); + } default: GOTO(out, err = -ENOTTY); } diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index 497fc75..dc713f4 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -6,10 +6,12 @@ KFLAGS:= CPPFLAGS = $(HAVE_LIBREADLINE) obdctl_LDADD := $(LIBREADLINE) lctl_LDADD := $(LIBREADLINE) -lptlctl -sbin_PROGRAMS = lctl obdctl +sbin_PROGRAMS = lctl lfind obdctl sbin_SCRIPTS = lconf lmc obdctl_SOURCES = parser.c obdctl.c obd.c parser.h obdctl.h lctl_SOURCES = parser.c obd.c lctl.c parser.h +lfind_SOURCES = lfind.c +lfind_CPPFLAGS = -D_XOPEN_SOURCE=500 EXTRA_DIST = $(sbin_SCRIPTS) include $(top_srcdir)/Rules diff --git a/lustre/utils/lfind.c b/lustre/utils/lfind.c new file mode 100644 index 0000000..6628a9c --- /dev/null +++ b/lustre/utils/lfind.c @@ -0,0 +1,318 @@ +#define _XOPEN_SOURCE 500 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define printk printf +#include +#include + +#warning Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c +#define MAX_LOV_UUID_COUNT 1000 +#define OBD_NOT_FOUND ((__u32)-1) +#define debugMsg if (debug) printf + +char * cmd; +int debug; +struct option longOpts[] = { + {"debug", 0, 0, 'd'}, + {"help", 0, 0, 'h'}, + {"obd", 1, 0, 'o'}, + {"query", 0, 0, 'o'}, + {0, 0, 0, 0} + }; +int query; +char * shortOpts = "dho:qv"; +char * usageMsg = "[ --obd | --query ] ..."; + +int max_stripe_count = MAX_LOV_UUID_COUNT; +obd_uuid_t * obduuid; +__u32 obdcount; +__u32 obdindex; +char * buf; +int buflen; +struct obd_ioctl_data data; +struct lov_desc desc; +obd_uuid_t * uuids; +int uuidslen; +int cfglen; +struct lov_user_md *lum; +int lumlen; + +void init(); +void usage(FILE *stream); +void errMsg(char *fmt, ...); +void processPath(char *path); +int processFile( + const char *path, + const struct stat *sp, + int flag, + struct FTW *ftwp + ); +__u32 getobdindex(const char *path); + +int +main (int argc, char **argv) { + int c; + + cmd = basename(argv[0]); + + while ((c = getopt_long(argc, argv, shortOpts, longOpts, NULL)) != -1) { + switch (c) { + case 'd': + debug++; + break; + case 'o': + if (obduuid) { + errMsg("obd '%s' already specified: '%s'.", + obduuid, optarg); + exit(1); + } + + obduuid = (obd_uuid_t *)optarg; + break; + case 'h': + usage(stdout); + exit(0); + case 'q': + query++; + break; + case '?': + usage(stderr); + exit(1); + default: + errMsg("Internal error. Valid '%s' unrecognized.", + argv[optind - 1]); + usage(stderr); + exit(1); + } + } + + if (optind >= argc) { + usage(stderr); + exit(1); + } + + if (obduuid == NULL) + query++; + + init(); + + do { + processPath(argv[optind]); + } while (++optind < argc); + + exit (0); +} + +void +init() +{ + int datalen, desclen; + + datalen = size_round(sizeof(data)); + desclen = size_round(sizeof(desc)); + uuidslen = size_round(max_stripe_count * sizeof(*uuids)); + cfglen = datalen + desclen + uuidslen; + lumlen = sizeof(*lum) + max_stripe_count * sizeof(*lum->lum_luoinfo); + if (cfglen > lumlen) + buflen = cfglen; + else + buflen = lumlen; + +#warning max ioctl buffer size currently hardcoded to 8192 + if (buflen > 8192) { + int nuuids, remaining, nluoinfos; + + buflen = 8192; + nuuids = (buflen - datalen - desclen) / sizeof(*uuids); + uuidslen = size_round(nuuids * sizeof(*uuids)); + remaining = nuuids * sizeof(*uuids); + if (uuidslen > remaining) + nuuids--; + nluoinfos = (buflen - sizeof(*lum)) / sizeof(*lum->lum_luoinfo); + if (nuuids > nluoinfos) + max_stripe_count = nluoinfos; + else + max_stripe_count = nuuids; + + cfglen = datalen + desclen + uuidslen; + lumlen = sizeof(*lum) + max_stripe_count * + sizeof(*lum->lum_luoinfo); + } + + if ((buf = malloc(buflen)) == NULL) { + errMsg("Unable to allocate %d bytes of memory for ioctl's.", + buflen); + exit(1); + } + + lum = (struct lov_user_md *)buf; + uuids = (obd_uuid_t *)buf; +} + +void +usage(FILE *stream) +{ + fprintf(stream, "usage: %s %s\n", cmd, usageMsg); +} + +void +errMsg(char *fmt, ...) +{ + va_list args; + + fprintf(stderr, "%s: ", cmd); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); +} + +void +processPath(char *path) +{ + obdindex = OBD_NOT_FOUND; + nftw((const char *)path, processFile, 128, FTW_PHYS|FTW_MOUNT); +} + +int +processFile(const char *path, + const struct stat *sp, + int flag, + struct FTW *ftwp +) { + struct lov_user_oinfo *luoinfo; + int fd; + int count; + int rc; + int i; + + if (flag != FTW_F) + return 0; + + if ((obdcount == 0) && (getobdindex(path) == OBD_NOT_FOUND)) { + /* terminate nftw walking this tree */ + return(1); + } + + if ((fd = open(path, O_RDONLY)) < 0) { + errMsg("open \"%.20s\" failed.", path); + perror("open"); + exit(1); + } + + memset((void *)buf, 0, buflen); + lum->lum_stripe_count = max_stripe_count; + + if ((rc = ioctl(fd, LL_IOC_LOV_GETSTRIPE, (void *)lum)) < 0) { + errMsg("LL_IOC_LOV_GETSTRIPE ioctl failed."); + perror("ioctl"); + exit(1); + } + + close(fd); + + count = lum->lum_stripe_count; + luoinfo = lum->lum_luoinfo; + + if (query) { + printf("%s\n", path); + for (i = 0; i < count; i++, luoinfo++) { + printf("%4d: obdindex: %-4d objid: %lld\n", + i, luoinfo->luo_idx, luoinfo->luo_id); + } + return(0); + } + + debugMsg("LL_IOC_LOV_GETSTRIPE:%s: obdindex: %d count: %d\n", + path, obdindex, count); + + for (i = 0; i < count; i++, luoinfo++) { + debugMsg("%-4d: obdidx: %-4d objid: %lld\n", + i, luoinfo->luo_idx, luoinfo->luo_id); + if (luoinfo->luo_idx == obdindex) { + printf("%s\n", path); + return 0; + } + } + + return(0); +} + +__u32 +getobdindex(const char *path) +{ + obd_uuid_t *uuidp; + int fd; + int rc; + int i; + + if ((fd = open(path, O_RDONLY)) < 0) { + errMsg("open \"%.20s\" failed.", path); + perror("open"); + exit(1); + } + + data.ioc_inllen1 = sizeof(desc); + data.ioc_inlbuf1 = (char *)&desc; + data.ioc_inllen2 = uuidslen; + data.ioc_inlbuf2 = (char *)uuids; + data.ioc_inllen3 = 0; + + memset(&desc, 0, sizeof(desc)); + desc.ld_tgt_count = max_stripe_count; + + if (obd_ioctl_pack(&data, &buf, buflen)) { + errMsg("internal buffering error."); + exit(1); + } + + rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf); + if (rc) { + errMsg("OBD_IOC_LOV_GET_CONFIG ioctl failed: %d.", errno); + perror("ioctl"); + exit(1); + } + + if (obd_ioctl_unpack(&data, buf, buflen)) { + errMsg("Invalid reply from ioctl."); + exit(1); + } + + close(fd); + + obdcount = desc.ld_tgt_count; + + if (query) { + printf("OBDS:\n"); + for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) + printf("%4d: %s\n", i, (char *)uuidp); + + return(0); + } + + for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) { + rc = strncmp((const char *)obduuid, (const char *)uuidp, + sizeof(*uuidp)); + if (rc == 0) { + obdindex = i; + break; + } + } + + if (obdindex == OBD_NOT_FOUND) { + errMsg("obd UUID '%s' not found.", obduuid); + return(OBD_NOT_FOUND); + } + + return(0); +} -- 1.8.3.1