--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2002 Cluster File Systems, Inc.
+ * Author: Peter J. Braam <braam@clusterfs.com>
+ * Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Robert Read <rread@clusterfs.com>
+ *
+ * This file is part of Lustre, http://www.lustre.org.
+ *
+ * Lustre is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * Lustre is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Lustre; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+
+#include <liblustre.h>
+#include <linux/lustre_idl.h>
+
+#include "parser.h"
+
+extern int op_create_file(char *name, long stripe_size, int stripe_offset,
+ int stripe_count);
+extern int op_find(char *path, struct obd_uuid *obduuid, int recursive,
+ int verbose, int quiet);
+
+/* all functions */
+static int lfs_setstripe(int argc, char **argv);
+static int lfs_find(int argc, char **argv);
+
+/* all avaialable commands */
+command_t cmdlist[] = {
+ {"setstripe", lfs_setstripe, 0,
+ "blah...\n"
+ "usage: setstripe <filename> <stripe size> <stripe start> <stripe count>\n"
+ "\tstripe size: Number of bytes in each stripe (0 default)\n"
+ "\tstripe start: OST index of first stripe (-1 default)\n"
+ "\tstripe count: Number of OSTs to stripe over (0 default)"},
+ {"find", lfs_find, 0,
+ "blah...\n"
+ "usage: find [--obd <uuid>] [--quiet | --verbose] [--recursive] <dir|file> ..."},
+ {"help", Parser_help, 0, "help"},
+ {"exit", Parser_quit, 0, "quit"},
+ {"quit", Parser_quit, 0, "quit"},
+ { 0, 0, 0, NULL }
+};
+
+/* functions */
+static int lfs_setstripe(int argc, char **argv)
+{
+ int result;
+ long st_size;
+ int st_offset, st_count;
+ char *end;
+
+ if (argc != 5)
+ return CMD_HELP;
+
+ // get the stripe size
+ st_size = strtoul(argv[2], &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "error: %s: bad stripe size '%s'\n",
+ argv[0], argv[2]);
+ return CMD_HELP;
+ }
+ // get the stripe offset
+ st_offset = strtoul(argv[3], &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "error: %s: bad stripe offset '%s'\n",
+ argv[0], argv[3]);
+ return CMD_HELP;
+ }
+ // get the stripe count
+ st_count = strtoul(argv[4], &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "error: %s: bad stripe count '%s'\n",
+ argv[0], argv[4]);
+ return CMD_HELP;
+ }
+
+ result = op_create_file(argv[1], st_size, st_offset, st_count);
+ if (result)
+ fprintf(stderr, "error: %s: create stripe file failed\n",
+ argv[0]);
+
+ return result;
+}
+
+static int lfs_find(int argc, char **argv)
+{
+ struct option long_opts[] = {
+ {"obd", 1, 0, 'o'},
+ {"quiet", 0, 0, 'q'},
+ {"recursive", 0, 0, 'r'},
+ {"verbose", 0, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+ char short_opts[] = "ho:qrv";
+ int quiet, verbose, recursive, c, rc;
+ struct obd_uuid *obduuid = NULL;
+
+ quiet = verbose = recursive = 0;
+ while ((c = getopt_long(argc, argv, short_opts,
+ long_opts, NULL)) != -1) {
+ switch (c) {
+ case 'o':
+ if (obduuid) {
+ fprintf(stderr, "error: %s: only one obduuid allowed",
+ argv[0]);
+ return CMD_HELP;
+ }
+ obduuid = (struct obd_uuid *)optarg;
+ break;
+ case 'q':
+ quiet++;
+ verbose = 0;
+ break;
+ case 'r':
+ recursive = 1;
+ break;
+ case 'v':
+ verbose++;
+ quiet = 0;
+ break;
+ case '?':
+ return CMD_HELP;
+ break;
+ default:
+ fprintf(stderr, "error: %s: option '%s' unrecognized\n",
+ argv[0], argv[optind - 1]);
+ return CMD_HELP;
+ break;
+ }
+ }
+
+ if (optind >= argc)
+ return CMD_HELP;
+
+ do {
+ rc = op_find(argv[optind], obduuid, recursive, verbose, quiet);
+ } while (++optind < argc && !rc);
+
+ if (rc)
+ fprintf(stderr, "error: %s: find failed\n", argv[0]);
+ return rc;
+}
+
+
+int main(int argc, char **argv)
+{
+ int rc;
+
+ setlinebuf(stdout);
+
+ Parser_init("lfs > ", cmdlist);
+
+ if (argc > 1) {
+ rc = Parser_execarg(argc - 1, argv + 1, cmdlist);
+ } else {
+ rc = Parser_commands();
+ }
+
+ return rc;
+}
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2002 Cluster File Systems, Inc.
+ * Author: Peter J. Braam <braam@clusterfs.com>
+ * Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Robert Read <rread@clusterfs.com>
+ *
+ * This file is part of Lustre, http://www.lustre.org.
+ *
+ * Lustre is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * Lustre is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Lustre; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+/* for O_DIRECTORY */
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/types.h>
+#include <linux/unistd.h>
+
+#include <liblustre.h>
+#include <linux/obd.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_lite.h>
+#include <linux/lustre_idl.h>
+#include <linux/obd_lov.h>
+
+static void err_msg(char *fmt, ...)
+{
+ 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);
+}
+
+int op_create_file(char *name, long stripe_size, int stripe_offset,
+ 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 find_param {
+ int recursive;
+ int verbose;
+ int quiet;
+ struct obd_uuid *obduuid;
+ struct obd_ioctl_data data;
+ struct lov_desc desc;
+ int uuidslen;
+ char *buf;
+ int buflen;
+ struct obd_uuid *uuids;
+ struct lov_mds_md *lmm;
+ int got_uuids;
+ int obdindex;
+ int max_ost_count;
+};
+
+/* XXX Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c */
+#define MAX_LOV_UUID_COUNT 1000
+#define OBD_NOT_FOUND (-1)
+
+static int prepare_find(struct find_param *param)
+{
+ int datalen, desclen;
+ int cfglen, lmmlen;
+ 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;
+ param->got_uuids = 0;
+ param->obdindex = OBD_NOT_FOUND;
+ param->max_ost_count = max_ost_count;
+
+ return 0;
+}
+
+static void cleanup_find(struct find_param *param)
+{
+ if (param->obduuid)
+ free(param->obduuid);
+ if (param->buf)
+ free(param->buf);
+}
+
+static void get_obd_uuids(DIR *dir, char *dname, struct find_param *param)
+{
+ int obdcount;
+ struct obd_uuid *uuidp;
+ int rc, i;
+
+ param->got_uuids = 1;
+ memset(¶m->data, 0, sizeof(struct obd_ioctl_data));
+ param->data.ioc_inllen1 = sizeof(struct lov_desc);
+ param->data.ioc_inlbuf1 = (char *)¶m->desc;
+ param->data.ioc_inllen2 = param->uuidslen;
+ param->data.ioc_inlbuf2 = (char *)param->uuids;
+
+ memset(¶m->desc, 0, sizeof(struct lov_desc));
+ param->desc.ld_tgt_count = param->max_ost_count;
+
+ if (obd_ioctl_pack(¶m->data, ¶m->buf, param->buflen)) {
+ fprintf(stderr, "internal buffer error from %s\n", dname);
+ return;
+ }
+
+ rc = ioctl(dirfd(dir), OBD_IOC_LOV_GET_CONFIG, param->buf);
+ if (rc) {
+ err_msg("error getting LOV config from %s", dname);
+ return;
+ }
+
+ if (obd_ioctl_unpack(¶m->data, param->buf, param->buflen)) {
+ err_msg("invalid reply from ioctl from %s", dname);
+ return;
+ }
+
+ obdcount = param->desc.ld_tgt_count;
+ if (obdcount == 0)
+ return;
+
+ if (param->obduuid) {
+ for (i = 0, uuidp = param->uuids; i < obdcount; i++, uuidp++) {
+ if (strncmp(param->obduuid->uuid, uuidp->uuid,
+ sizeof(*uuidp)) == 0) {
+ param->obdindex = i;
+ 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);
+ }
+}
+
+static void process_file(DIR *dir, char *dname, char *fname, struct find_param *param)
+{
+ int rc, i;
+
+ strncpy((char *)param->lmm, fname, param->buflen);
+
+ 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 ((param->obduuid && param->lmm->lmm_objects[param->obdindex].l_object_id) ||
+ (!param->obduuid && !param->quiet))
+ printf("%s/%s\n", dname, fname);
+
+ 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 (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");
+ }
+}
+
+
+static void process_dir(DIR *dir, char *dname, struct find_param *param)
+{
+ struct dirent64 *dirp;
+ DIR *subdir;
+ char path[1024];
+
+ if (!param->got_uuids)
+ get_obd_uuids(dir, dname, param);
+
+ /* Handle the contents of the directory */
+ while ((dirp = readdir64(dir)) != NULL) {
+ if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
+ continue;
+
+ switch (dirp->d_type) {
+ case DT_UNKNOWN:
+ err_msg("\"%s\" is UNKNOWN type %d", dirp->d_name,
+ 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;
+ break;
+ case DT_DIR:
+ if (!param->recursive)
+ break;
+ strcpy(path, dname);
+ strcat(path, "/");
+ strcat(path, dirp->d_name);
+ subdir = opendir(path);
+ if (subdir == NULL) {
+ err_msg("\"%.40s\" opendir failed", path);
+ break;
+ }
+ process_dir(subdir, path, param);
+ closedir(subdir);
+ break;
+ case DT_REG:
+ process_file(dir, dname, dirp->d_name, param);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void process_path(char *path, struct find_param *param)
+{
+ char *fname, *dname;
+ DIR *dir;
+
+ fname = strrchr(path, '/');
+ if (fname != NULL && fname[1] == '\0') {
+ /* Trailing '/', it must be a dir */
+ *fname = '\0';
+ dir = opendir(path);
+ if (dir == NULL) {
+ err_msg("\"%.40s\" opendir failed", path);
+ } else {
+ 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);
+ closedir(dir);
+ } else {
+ /* It must be a file (or other non-directory) */
+ if (fname == NULL) {
+ dname = ".";
+ fname = path;
+ } else {
+ *fname = '\0';
+ fname++;
+ dname = path;
+ }
+ dir = opendir(dname);
+ if (dir == NULL) {
+ err_msg("\"%.40s\" opendir failed", dname);
+ } else {
+ if (!param->got_uuids)
+ get_obd_uuids(dir, dname, param);
+ process_file(dir, dname, fname, param);
+ closedir(dir);
+ }
+ }
+}
+
+
+int op_find(char *path, struct obd_uuid *obduuid, int recursive,
+ int verbose, int quiet)
+{
+ struct find_param param;
+ int ret = 0;
+
+ memset(¶m, 0, sizeof(param));
+ param.recursive = recursive;
+ param.verbose = verbose;
+ param.quiet = quiet;
+ if (obduuid) {
+ param.obduuid = (struct obd_uuid*)malloc(sizeof(struct obd_uuid));
+ if (param.obduuid == NULL) {
+ ret = 1;
+ goto out;
+ }
+ memcpy(param.obduuid, obduuid, sizeof(struct obd_uuid));
+ }
+
+ ret = prepare_find(¶m);
+ if (ret)
+ goto out;
+
+ process_path(path, ¶m);
+out:
+ cleanup_find(¶m);
+ return ret;
+}
+