// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab /* * Ceph - scalable distributed file system * * Copyright (C) 2004-2010 Sage Weil * * This is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software * Foundation. See file COPYING. * * Simple little program to let you: * 1) View the layout information on a file or directory, * 2) Modify the layout information on an empty file, * 3) Modify the default layout on a directory */ #include #include #include #include #include #include #include #include #include #include #include "client/ioctl.h" #include "common/errno.h" using namespace std; #define CMD_SHOW_LAYOUT 1 #define CMD_SHOW_LOC 2 #define CMD_SET_LAYOUT 3 #define CMD_MAP 4 void usage(); int init_options(int argc, char **argv, int *fd, char **path, int *cmd, int *stripe_unit, int *stripe_count, int *object_size, int64_t *pool, int *file_offset, bool *dir); int main (int argc, char **argv) { int fd = 0; int err = 0; char *path = 0; int cmd = 0; int stripe_unit = 0; int stripe_count = 0; int object_size = 0; int64_t pool = 0; int file_offset = 0; bool dir = false; if (init_options(argc, argv, &fd, &path, &cmd, &stripe_unit, &stripe_count, &object_size, &pool, &file_offset, &dir)){ usage(); return 0; } if (CMD_SHOW_LAYOUT == cmd) { struct ceph_ioctl_layout layout; memset(&layout, 0, sizeof(layout)); err = ioctl(fd, CEPH_IOC_GET_LAYOUT, (unsigned long)&layout); if (err) { cerr << "Error getting layout: " << (err == -1 ? strerror(errno) : strerror(-err)) << endl; return 1; } if (layout.stripe_unit == 0) { cerr << "layout not specified" << endl; } else { cout << "layout.data_pool: " << layout.data_pool << endl; cout << "layout.object_size: " << layout.object_size << endl; cout << "layout.stripe_unit: " << layout.stripe_unit << endl; cout << "layout.stripe_count: " << layout.stripe_count << endl; } } else if (CMD_SHOW_LOC == cmd) { struct ceph_ioctl_dataloc location; location.file_offset = file_offset; err = ioctl(fd, CEPH_IOC_GET_DATALOC, (unsigned long)&location); if (err) { cerr << "Error getting location: " << (err == -1 ? strerror(errno) : strerror(-err)) << endl; return 1; } cout << "location.file_offset: " << location.file_offset << endl; cout << "location.object_offset:" << location.object_offset << endl; cout << "location.object_no: " << location.object_no << endl; cout << "location.object_size: " << location.object_size << endl; cout << "location.object_name: " << location.object_name << endl; cout << "location.block_offset: " << location.block_offset << endl; cout << "location.block_size: " << location.block_size << endl; cout << "location.osd: " << location.osd << endl; // cout << "osd address: " << location.osd_addr << endl; } else if (CMD_SET_LAYOUT == cmd) { struct ceph_ioctl_layout layout; memset(&layout, 0, sizeof(layout)); int ioctl_num = (dir ? CEPH_IOC_SET_LAYOUT_POLICY : CEPH_IOC_SET_LAYOUT); layout.data_pool = pool; layout.object_size = object_size; layout.stripe_count = stripe_count; layout.stripe_unit = stripe_unit; layout.unused = -1; /* used to be preferred_osd */ err = ioctl(fd, ioctl_num, (unsigned long)&layout); if (err) { cerr << "Error setting layout: " << (err == -1 ? strerror(errno) : strerror(-err)) << endl; return 1; } } else if (CMD_MAP == cmd) { struct stat st; err = ::fstat(fd, &st); if (err < 0) { cerr << "error statting file: " << (err == -1 ? strerror(errno) : strerror(-err)) << endl; return 1; } struct ceph_ioctl_layout layout; memset(&layout, 0, sizeof(layout)); err = ioctl(fd, CEPH_IOC_GET_LAYOUT, (unsigned long)&layout); if (err) { cerr << "Error getting layout: " << (err == -1 ? strerror(errno) : strerror(-err)) << endl; return 1; } printf("%15s %24s %12s %12s %s\n", "FILE OFFSET", "OBJECT", "OFFSET", "LENGTH", "OSD"); for (long long off = 0; off < st.st_size; off += layout.stripe_unit) { struct ceph_ioctl_dataloc location; location.file_offset = off; err = ioctl(fd, CEPH_IOC_GET_DATALOC, (unsigned long)&location); if (err) { cerr << "Error getting location: " << (err == -1 ? strerror(errno) : strerror(-err)) << endl; return 1; } printf("%15lld %24s %12lld %12lld %d\n", off, location.object_name, (long long)location.object_offset, (long long)location.block_size, (int)location.osd); } } else { cerr << "unknown cmd somehow set!" << endl; usage(); return 1; } return 0; } void usage() { cerr << "usage: cephfs path command [options]*" << endl; cerr << "Commands:" << endl; cerr << " show_layout -- view the layout information on a file or dir" << endl; cerr << " set_layout -- set the layout on an empty file,\n" << " or the default layout on a directory" << endl; cerr << " show_location -- view the location information on a file" << endl; cerr << " map -- display file objects, pgs, osds" << endl; cerr << "Options:" << endl; cerr << " Useful for setting layouts:" << endl; cerr << " --stripe_unit, -u: set the size of each stripe" << endl; cerr << " --stripe_count, -c: set the number of objects to stripe across" << endl; cerr << " --object_size, -s: set the size of the objects to stripe across" << endl; cerr << " --pool, -p: set the pool to use" << endl; cerr << endl; cerr << " Useful for getting location data:" << endl; cerr << " --offset, -l: the offset to retrieve location data for" << endl; cerr << endl; } int init_options(int argc, char **argv, int *fd, char **path, int *cmd, int *stripe_unit, int *stripe_count, int *object_size, int64_t *pool, int *file_offset, bool *dir) { // look through the options, make sure they're valid, // and set the variables from them int i = 3; struct stat stat_field; if (argc < 3) { cerr << "not enough parameters!" << endl; return 1; } *path = argv[1]; *fd = open(argv[1], O_RDONLY); if (*fd < 0) { cerr << "error opening path: " << strerror(*fd) << endl; return 1; } if (!strcmp(argv[2], "show_layout")) { *cmd = CMD_SHOW_LAYOUT; if (argc > 4) return 1; } else if (!strcmp(argv[2], "set_layout")) { *cmd = CMD_SET_LAYOUT; } else if (!strcmp(argv[2], "show_location")){ *cmd = CMD_SHOW_LOC; } else if (!strcmp(argv[2], "map")) { *cmd = CMD_MAP; } else { cerr << "invalid command" << endl; return 1; } // okay, fill in options while (i < argc) { if (i == argc-1) { // there's an option without an associated value! cerr << "not all options are paired with a value!" << endl; return 1; } if (!strcmp(argv[i], "--stripe_unit") || argv[i][1] == 'u') { if (*cmd != CMD_SET_LAYOUT) { cerr << "Invalid option for command!" << endl; return 1; } *stripe_unit = strtol(argv[i+1], NULL, 0); if (!*stripe_unit) { cerr << "invalid value for stripe unit" << endl; return 1; } } else if (!strcmp(argv[i], "--stripe_count") || argv[i][1] == 'c') { if (*cmd != CMD_SET_LAYOUT) { cerr << "Invalid option for command!" << endl; return 1; } *stripe_count = strtol(argv[i+1], NULL, 0); if (!*stripe_count) { cerr << "invalid value for stripe count" << endl; return 1; } } else if (!strcmp(argv[i], "--object_size") || argv[i][1] == 's') { if (*cmd != CMD_SET_LAYOUT) { cerr << "Invalid option for command!" << endl; return 1; } *object_size = strtol(argv[i+1], NULL, 0); if (!*object_size) { cerr << "invalid value for object size" << endl; return 1; } } else if (!strcmp(argv[i], "--pool") || argv[i][1] == 'p') { if (*cmd != CMD_SET_LAYOUT) { cerr << "Invalid option for command!" << endl; return 1; } errno = 0; *pool= strtol(argv[i+1], NULL, 0); if (!*pool && errno) { cerr << "invalid value for pool" << endl; return 1; } } else if (!strcmp(argv[i], "--offset") || argv[i][1] == 'l') { if (*cmd != CMD_SHOW_LOC) { cerr << "Invalid option for command!" << endl; return 1; } errno = 0; *file_offset = strtol(argv[i+1], NULL, 0); if (!*file_offset && errno) { cerr << "invalid value for offset" << endl; return 1; } } i += 2; } int r = fstat (*fd, &stat_field); if (r < 0) { int err = errno; cerr << "error doing stat file: " << cpp_strerror(err) << endl; return 1; } if (S_ISREG(stat_field.st_mode)) { // open read-write to set layout close(*fd); *fd = open(argv[1], O_RDWR); if (*fd < 0) { cerr << "error opening file" << endl; return 1; } } else { *dir = true; } return 0; }