1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
5 * Author: Peter J. Braam <braam@clusterfs.com>
6 * Author: Phil Schwan <phil@clusterfs.com>
7 * Author: Robert Read <rread@clusterfs.com>
9 * This file is part of Lustre, http://www.lustre.org.
11 * Lustre is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
15 * Lustre is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Lustre; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 #include <sys/ioctl.h>
41 #include <sys/types.h>
42 #include <linux/types.h>
43 #include <linux/unistd.h>
45 #include <portals/ptlctl.h>
47 #include <liblustre.h>
48 #include <linux/obd.h>
49 #include <linux/lustre_lib.h>
50 #include <lustre/lustre_user.h>
51 #include <linux/obd_lov.h>
53 static void err_msg(char *fmt, ...)
56 int tmp_errno = errno;
59 vfprintf(stderr, fmt, args);
61 fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno);
64 int llapi_file_create(char *name, long stripe_size, int stripe_offset,
65 int stripe_count, int stripe_pattern)
67 struct lov_user_md lum = { 0 };
70 /* Initialize IOCTL striping pattern structure */
71 lum.lmm_magic = LOV_USER_MAGIC;
72 lum.lmm_pattern = stripe_pattern;
73 lum.lmm_stripe_size = stripe_size;
74 lum.lmm_stripe_count = stripe_count;
75 lum.lmm_stripe_offset = stripe_offset;
77 fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
79 fd = open(name, O_DIRECTORY | O_RDONLY);
82 err_msg("unable to open '%s'",name);
87 if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum)) {
88 char *errmsg = "stripe already set";
89 if (errno != EEXIST && errno != EALREADY)
90 errmsg = strerror(errno);
92 fprintf(stderr, "error on ioctl for '%s' (%d): %s\n",
97 err_msg("error on close for '%s' (%d)", name, fd);
104 /* short term backwards compat only */
105 int op_create_file(char *name, long stripe_size, int stripe_offset,
108 return llapi_file_create(name, stripe_size, stripe_offset,
116 struct obd_uuid *obduuid;
118 struct lov_user_md *lum;
123 /* XXX Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c */
124 #define MAX_LOV_UUID_COUNT 1000
125 #define OBD_NOT_FOUND (-1)
127 static int prepare_find(struct find_param *param)
129 param->lumlen = lov_mds_md_size(MAX_LOV_UUID_COUNT);
130 if ((param->lum = malloc(param->lumlen)) == NULL) {
131 err_msg("unable to allocate %d bytes of memory for ioctl",
136 param->got_uuids = 0;
137 param->obdindex = OBD_NOT_FOUND;
142 static void cleanup_find(struct find_param *param)
145 free(param->obduuid);
150 int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count)
152 struct obd_ioctl_data data = { 0, };
153 struct lov_desc desc = { 0, };
155 int max_ost_count, rc;
157 max_ost_count = (OBD_MAX_IOCTL_BUFFER - size_round(sizeof(data)) -
158 size_round(sizeof(desc))) / sizeof(*uuidp);
159 if (max_ost_count > *ost_count)
160 max_ost_count = *ost_count;
162 data.ioc_inllen1 = sizeof(desc);
163 data.ioc_inlbuf1 = (char *)&desc;
164 data.ioc_inllen2 = size_round(max_ost_count * sizeof(*uuidp));
165 data.ioc_inlbuf2 = (char *)uuidp;
167 desc.ld_tgt_count = max_ost_count;
169 if (obd_ioctl_pack(&data, &buf, OBD_MAX_IOCTL_BUFFER)) {
170 fprintf(stderr, "internal buffer error packing\n");
175 rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
177 err_msg("error getting LOV config");
182 if (obd_ioctl_unpack(&data, buf, OBD_MAX_IOCTL_BUFFER)) {
183 fprintf(stderr, "invalid reply from ioctl");
188 *ost_count = desc.ld_tgt_count;
195 static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
197 struct obd_uuid uuids[1024], *uuidp;
201 param->got_uuids = 1;
203 rc = llapi_lov_get_uuids(dirfd(dir), uuids, &obdcount);
205 return (param->obduuid ? rc : 0);
210 if (param->obduuid) {
211 for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
212 if (strncmp(param->obduuid->uuid, uuidp->uuid,
213 sizeof(*uuidp)) == 0) {
218 if (param->obdindex == OBD_NOT_FOUND) {
219 printf("unknown obduuid: %s\n", param->obduuid->uuid);
222 } else if (!param->quiet) {
224 for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++)
225 printf("%4d: %s\n", i, uuidp->uuid);
231 void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *dname, char *fname,
232 int obdindex, int quiet, int header, int body)
234 int i, obdstripe = 0;
236 if (obdindex != OBD_NOT_FOUND) {
237 for (i = 0; i < lum->lmm_stripe_count; i++) {
238 if (obdindex == lum->lmm_objects[i].l_ost_idx) {
239 printf("%s/%s\n", dname, fname);
245 printf("%s/%s\n", dname, fname);
249 /* if it's a directory */
250 if (*fname == '\0') {
251 if (header && (obdstripe == 1)) {
252 printf("count: %d, size: %d, offset: %d\n\n",
253 lum->lmm_stripe_count, lum->lmm_stripe_size,
254 (short int)lum->lmm_stripe_offset);
259 if (header && (obdstripe == 1)) {
260 printf("lmm_magic: 0x%08X\n", lum->lmm_magic);
261 printf("lmm_object_gr: "LPX64"\n", lum->lmm_object_gr);
262 printf("lmm_object_id: "LPX64"\n", lum->lmm_object_id);
263 printf("lmm_stripe_count: %u\n", (int)lum->lmm_stripe_count);
264 printf("lmm_stripe_size: %u\n", lum->lmm_stripe_size);
265 printf("lmm_stripe_pattern: %x\n", lum->lmm_pattern);
269 if ((!quiet) && (obdstripe == 1))
270 printf("\tobdidx\t\t objid\t\tobjid\t\t group\n");
272 for (i = 0; i < lum->lmm_stripe_count; i++) {
273 int idx = lum->lmm_objects[i].l_ost_idx;
274 long long oid = lum->lmm_objects[i].l_object_id;
275 long long gr = lum->lmm_objects[i].l_object_gr;
276 if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx))
277 printf("\t%6u\t%14llu\t%#13llx\t%14llu%s\n",
279 obdindex == idx ? " *" : "");
285 void llapi_lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
287 switch(*(__u32 *)param->lum) { /* lum->lmm_magic */
288 case LOV_USER_MAGIC_V1:
289 lov_dump_user_lmm_v1(param->lum, dname, fname, param->obdindex,
290 param->quiet, param->verbose,
291 (param->verbose || !param->obduuid));
294 printf("unknown lmm_magic: 0x%08X\n", *(__u32 *)param->lum);
299 int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
304 fname = strrchr(path, '/');
306 /* It should be a file (or other non-directory) */
308 dname = (char *)malloc(2);
314 dname = (char *)malloc(fname - path + 1);
317 strncpy(dname, path, fname - path);
318 dname[fname - path] = '\0';
322 if ((fd = open(dname, O_RDONLY)) == -1) {
327 strncpy((char *)lum, fname, sizeof(*lum));
328 if (ioctl(fd, IOC_MDC_GETSTRIPE, (void *)lum) == -1) {
342 /* short term backwards compat only */
343 int op_get_file_stripe(char *path, struct lov_user_md *lum)
345 return llapi_file_get_stripe(path, lum);
348 static int process_file(DIR *dir, char *dname, char *fname,
349 struct find_param *param)
353 strncpy((char *)param->lum, fname, param->lumlen);
355 rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)param->lum);
357 if (errno == ENODATA) {
358 if (!param->obduuid && !param->quiet)
360 "%s/%s has no stripe info\n",
363 } else if (errno == EISDIR) {
364 fprintf(stderr, "process_file on directory %s/%s!\n",
366 /* add fname to directory list; */
369 err_msg("IOC_MDC_GETSTRIPE ioctl failed");
375 llapi_lov_dump_user_lmm(param, dname, fname);
380 /* some 64bit libcs implement readdir64() by calling sys_getdents(). the
381 * kernel's sys_getdents() doesn't return d_type. */
382 unsigned char handle_dt_unknown(char *parent, char *entry)
384 char path[PATH_MAX + 1];
387 ret = snprintf(path, PATH_MAX, "%s/%s", parent, entry);
391 fd = open(path, O_DIRECTORY|O_RDONLY);
393 if (errno == ENOTDIR)
394 return DT_REG; /* kind of a lie */
401 static int process_dir(DIR *dir, char *dname, struct find_param *param)
403 struct dirent64 *dirp;
408 if (!param->got_uuids) {
409 rc = setup_obd_uuids(dir, dname, param);
414 /* retrieve dir's stripe info */
415 strncpy((char *)param->lum, dname, param->lumlen);
416 rc = ioctl(dirfd(dir), LL_IOC_LOV_GETSTRIPE, (void *)param->lum);
418 if (errno == ENODATA) {
419 if (!param->obduuid && param->verbose)
420 printf("%s/%s has no stripe info\n", dname, "");
423 err_msg("IOC_MDC_GETSTRIPE ioctl failed");
427 llapi_lov_dump_user_lmm(param, dname, "");
430 /* Handle the contents of the directory */
431 while ((dirp = readdir64(dir)) != NULL) {
432 if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
435 if (dirp->d_type == DT_UNKNOWN)
436 dirp->d_type = handle_dt_unknown(dname, dirp->d_name);
438 switch (dirp->d_type) {
440 err_msg("\"%s\" is UNKNOWN type %d", dirp->d_name,
442 /* If we cared we could stat the file to determine
443 * type and continue on here, but we don't since we
444 * know d_type should be valid for lustre and this
445 * tool only makes sense for lustre filesystems. */
449 if (!param->recursive)
453 strcat(path, dirp->d_name);
454 subdir = opendir(path);
455 if (subdir == NULL) {
456 err_msg("\"%.40s\" opendir failed", path);
459 rc = process_dir(subdir, path, param);
465 rc = process_file(dir, dname, dirp->d_name, param);
477 static int process_path(char *path, struct find_param *param)
483 fname = strrchr(path, '/');
484 if (fname != NULL && fname[1] == '\0') {
485 /* Trailing '/', it must be a dir */
489 err_msg("\"%.40s\" opendir failed", path);
492 rc = process_dir(dir, path, param);
495 } else if ((dir = opendir(path)) != NULL) {
496 /* No trailing '/', but it is still a dir */
497 rc = process_dir(dir, path, param);
500 /* It must be a file (or other non-directory) */
509 dir = opendir(dname);
511 err_msg("\"%.40s\" opendir failed", dname);
514 if (!param->got_uuids)
515 rc = setup_obd_uuids(dir, dname, param);
517 rc = process_file(dir, dname, fname, param);
525 int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
526 int verbose, int quiet)
528 struct find_param param;
531 memset(¶m, 0, sizeof(param));
532 param.recursive = recursive;
533 param.verbose = verbose;
536 param.obduuid = malloc(sizeof(*obduuid));
537 if (param.obduuid == NULL) {
541 memcpy(param.obduuid, obduuid, sizeof(*obduuid));
544 ret = prepare_find(¶m);
548 process_path(path, ¶m);
550 cleanup_find(¶m);
554 #define MAX_STRING_SIZE 128
555 #define DEVICES_LIST "/proc/fs/lustre/devices"
557 int llapi_ping(char *obd_type, char *obd_name)
559 char path[MAX_STRING_SIZE];
563 snprintf(path, MAX_STRING_SIZE, "/proc/fs/lustre/%s/%s/ping",
566 fd = open(path, O_WRONLY);
568 fprintf(stderr, "error opening %s: %s\n", path, strerror(errno));
572 rc = write(fd, buf, 1);
580 int llapi_target_check(int type_num, char **obd_type, char *dir)
582 char buf[MAX_STRING_SIZE];
583 FILE *fp = fopen(DEVICES_LIST, "r");
587 fprintf(stderr, "error: %s opening "DEVICES_LIST"\n",
588 strerror(rc = errno));
592 while (fgets(buf, sizeof(buf), fp) != NULL) {
593 char *obd_type_name = NULL;
594 char *obd_name = NULL;
595 char rawbuf[OBD_MAX_IOCTL_BUFFER];
598 struct obd_ioctl_data datal = { 0, };
599 struct obd_statfs osfs_buffer;
601 while(bufp[0] == ' ')
604 for(i = 0; i < 3; i++) {
605 obd_type_name = strsep(&bufp, " ");
607 obd_name = strsep(&bufp, " ");
609 memset(&osfs_buffer, 0, sizeof (osfs_buffer));
611 memset(bufl, 0, sizeof(rawbuf));
612 datal.ioc_pbuf1 = (char *)&osfs_buffer;
613 datal.ioc_plen1 = sizeof(osfs_buffer);
615 for (i = 0; i < type_num; i++) {
616 if (strcmp(obd_type_name, obd_type[i]) != 0)
619 rc = llapi_ping(obd_type_name, obd_name);
621 fprintf(stderr, "error: check %s: %s\n",
622 obd_name, strerror(rc = errno));
624 printf("%s active.\n", obd_name);
632 #undef MAX_STRING_SIZE
634 int llapi_catinfo(char *dir, char *keyword, char *node_name)
636 char raw[OBD_MAX_IOCTL_BUFFER];
637 char out[LLOG_CHUNK_SIZE];
639 struct obd_ioctl_data data;
644 sprintf(key, "%s", keyword);
645 memset(raw, 0, sizeof(raw));
646 memset(out, 0, sizeof(out));
647 data.ioc_inlbuf1 = key;
648 data.ioc_inllen1 = strlen(key) + 1;
650 data.ioc_inlbuf2 = node_name;
651 data.ioc_inllen2 = strlen(node_name) + 1;
653 data.ioc_pbuf1 = out;
654 data.ioc_plen1 = sizeof(out);
655 rc = obd_ioctl_pack(&data, &buf, sizeof(raw));
661 err_msg("open %s failed", dir);
665 rc = ioctl(dirfd(root), OBD_IOC_LLOG_CATINFO, buf);
667 err_msg("ioctl OBD_IOC_CATINFO failed");
669 fprintf(stdout, "%s", data.ioc_pbuf1);
675 int llapi_is_lustre_mnttype(char *type)
677 return (strcmp(type,"lustre") == 0 || strcmp(type,"lustre_lite") == 0);