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) {
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
case EXT2_IOC_SETVERSION_NEW:
*/
default:
- return -ENOTTY;
+ conn = ll_i2obdconn(inode);
+ return obd_iocontrol(cmd, conn, 0, NULL, (void *)arg);
}
}
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);
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);
}
--- /dev/null
+#define _XOPEN_SOURCE 500
+
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <ftw.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#define printk printf
+#include <linux/lustre_lib.h>
+#include <linux/lustre_lite.h>
+
+#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 <obd uuid> | --query ] <dir|file> ...";
+
+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);
+}