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 #ifdef HAVE_LINUX_TYPES_H
43 #include <linux/types.h>
47 #ifdef HAVE_LINUX_UNISTD_H
48 #include <linux/unistd.h>
52 #include <liblustre.h>
53 #include <linux/obd.h>
54 #include <linux/lustre_lib.h>
55 #include <linux/lustre_acl.h>
56 #include <lustre/lustre_user.h>
57 #include <linux/obd_lov.h>
59 #include <portals/ptlctl.h>
61 static void err_msg(char *fmt, ...)
64 int tmp_errno = errno;
67 vfprintf(stderr, fmt, args);
69 fprintf(stderr, ": %s (%d)\n", strerror(tmp_errno), tmp_errno);
72 int llapi_file_create(char *name, long stripe_size, int stripe_offset,
73 int stripe_count, int stripe_pattern)
75 struct lov_user_md lum = { 0 };
79 /* Initialize IOCTL striping pattern structure */
80 lum.lmm_magic = LOV_USER_MAGIC;
81 lum.lmm_pattern = stripe_pattern;
82 lum.lmm_stripe_size = stripe_size;
83 lum.lmm_stripe_count = stripe_count;
84 lum.lmm_stripe_offset = stripe_offset;
86 fd = open(name, O_CREAT | O_RDWR | O_LOV_DELAY_CREATE, 0644);
87 if (errno == EISDIR) {
88 fd = open(name, O_DIRECTORY | O_RDONLY);
93 err_msg("unable to open '%s'",name);
98 /* setting stripe pattern 0 -1 0 to a dir means to delete it */
100 if (stripe_size == 0 && stripe_count == 0 &&
102 lum.lmm_stripe_size = -1;
104 if (stripe_size == -1) {
105 err_msg("deleting file stripe info is not allowed\n");
111 if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum)) {
112 char *errmsg = "stripe already set";
113 if (errno != EEXIST && errno != EALREADY)
114 errmsg = strerror(errno);
116 fprintf(stderr, "error on ioctl for '%s' (%d): %s\n",
122 err_msg("error on close for '%s' (%d)", name, fd);
129 int op_create_dir(char *name, int stripe_count)
131 struct ll_user_mkdir_stripe lums = { 0 };
136 dirname = rindex(name, '/');
144 lums.lums_nstripes = stripe_count;
145 lums.lums_namelen = strlen(dirname);
146 lums.lums_name = dirname;
147 /* XXX: Probably users might want to specify permissions as well? */
148 lums.lums_mode = 0755;
150 fd = open(name, O_RDONLY|O_DIRECTORY);
154 err_msg("unable to open '%s'",name);
159 if (ioctl(fd, LL_IOC_MDC_MKDIRSTRIPE, &lums)) {
160 char *errmsg = strerror(errno);
162 fprintf(stderr, "error on ioctl for '%s' (%d): %s\n",
167 err_msg("error on close for '%s' (%d)", name, fd);
174 /* short term backwards compat only */
175 int op_create_file(char *name, long stripe_size, int stripe_offset,
178 return llapi_file_create(name, stripe_size, stripe_offset,
187 struct obd_uuid *obduuid;
189 struct lov_user_md *data;
195 /* XXX Max obds per lov currently hardcoded to 1000 in lov/lov_obd.c */
196 #define MAX_LOV_UUID_COUNT 1000
197 #define OBD_NOT_FOUND (-1)
199 static int prepare_find(struct find_param *param)
201 if (param->showfid) {
202 param->datalen = PATH_MAX + 1;
203 if ((param->data = malloc(param->datalen)) == NULL) {
204 err_msg("unable to allocate %d bytes of memory for ioctl",
209 param->datalen = lov_mds_md_size(MAX_LOV_UUID_COUNT);
210 if ((param->data = malloc(param->datalen)) == NULL) {
211 err_msg("unable to allocate %d bytes of memory for ioctl",
216 param->got_uuids = 0;
217 param->obdindex = OBD_NOT_FOUND;
221 static void cleanup_find(struct find_param *param)
224 free(param->obduuid);
229 int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp,
230 __u32 *obdgens, int *ost_count)
232 struct obd_ioctl_data data = { 0, };
233 struct lov_desc desc = { 0, };
235 int max_ost_count, rc;
237 max_ost_count = (OBD_MAX_IOCTL_BUFFER - size_round(sizeof(data)) -
238 size_round(sizeof(desc))) /
239 (sizeof(*uuidp) + sizeof(*obdgens));
240 if (max_ost_count > *ost_count)
241 max_ost_count = *ost_count;
243 data.ioc_inllen1 = sizeof(desc);
244 data.ioc_inlbuf1 = (char *)&desc;
245 data.ioc_inllen2 = size_round(max_ost_count * sizeof(*uuidp));
246 data.ioc_inlbuf2 = (char *)uuidp;
247 data.ioc_inllen3 = size_round(max_ost_count * sizeof(*obdgens));
248 data.ioc_inlbuf3 = (char *)obdgens;
250 desc.ld_tgt_count = max_ost_count;
252 if (obd_ioctl_pack(&data, &buf, OBD_MAX_IOCTL_BUFFER)) {
253 fprintf(stderr, "internal buffer error packing\n");
258 rc = ioctl(fd, OBD_IOC_LOV_GET_CONFIG, buf);
260 err_msg("error getting LOV config");
265 if (obd_ioctl_unpack(&data, buf, OBD_MAX_IOCTL_BUFFER)) {
266 fprintf(stderr, "invalid reply from ioctl");
271 *ost_count = desc.ld_tgt_count;
278 static int setup_obd_uuids(DIR *dir, char *dname, struct find_param *param)
280 struct obd_uuid uuids[1024], *uuidp;
281 __u32 obdgens[1024], *genp;
285 param->got_uuids = 1;
287 rc = llapi_lov_get_uuids(dirfd(dir), uuids, obdgens, &obdcount);
289 return (param->obduuid ? rc : 0);
294 if (param->obduuid) {
295 for (i = 0, uuidp = uuids; i < obdcount; i++, uuidp++) {
296 if (strncmp((char *)param->obduuid->uuid, (char *)uuidp->uuid,
297 sizeof(*uuidp)) == 0) {
302 if (param->obdindex == OBD_NOT_FOUND) {
303 printf("unknown obduuid: %s\n", param->obduuid->uuid);
306 } else if (!param->quiet) {
308 printf("OBDS:\tobdidx\t\tobdgen\t\t obduuid\n");
311 for (i = 0; i < obdcount; i++, uuidp++, genp++) {
312 if (obd_uuid_empty(uuidp))
314 printf("\t%6u\t%14u\t\t %s\n", i, *genp, uuidp->uuid);
320 void lov_dump_user_lmm_v1(struct lov_user_md_v1 *lum, char *dname, char *fname,
321 int obdindex, int quiet, int header, int body)
323 int i, obdstripe = 0;
325 if (obdindex != OBD_NOT_FOUND) {
326 for (i = 0; i < lum->lmm_stripe_count; i++) {
327 if (obdindex == lum->lmm_objects[i].l_ost_idx) {
328 printf("%s/%s\n", dname, fname);
334 printf("%s/%s\n", dname, fname);
338 /* if it's a directory */
339 if (*fname == '\0') {
340 if (header && (obdstripe == 1)) {
341 printf("count: %d, size: %d, offset: %d\n\n",
342 lum->lmm_stripe_count, lum->lmm_stripe_size,
343 (short int)lum->lmm_stripe_offset);
348 if (header && (obdstripe == 1)) {
349 printf("lmm_magic: 0x%08X\n", lum->lmm_magic);
350 printf("lmm_object_gr: "LPX64"\n", lum->lmm_object_gr);
351 printf("lmm_object_id: "LPX64"\n", lum->lmm_object_id);
352 printf("lmm_stripe_count: %u\n", (int)lum->lmm_stripe_count);
353 printf("lmm_stripe_size: %u\n", lum->lmm_stripe_size);
354 printf("lmm_stripe_pattern: %x\n", lum->lmm_pattern);
358 if ((!quiet) && (obdstripe == 1))
359 printf("\tobdidx\t\t obdgen\t\t objid\t\tobjid\t\t group\n");
361 for (i = 0; i < lum->lmm_stripe_count; i++) {
362 int idx = lum->lmm_objects[i].l_ost_idx;
363 long long oid = lum->lmm_objects[i].l_object_id;
364 int gen = lum->lmm_objects[i].l_ost_gen;
365 long long gr = lum->lmm_objects[i].l_object_gr;
366 if ((obdindex == OBD_NOT_FOUND) || (obdindex == idx))
367 printf("\t%6u\t%14u\t%14llu\t%#13llx\t%14lld%s\n",
368 idx, gen, oid, oid, gr,
369 obdindex == idx ? " *" : "");
375 void llapi_lov_dump_user_lmm(struct find_param *param, char *dname, char *fname)
377 switch(*(__u32 *)param->data) { /* lum->lmm_magic */
378 case LOV_USER_MAGIC_V1:
379 lov_dump_user_lmm_v1(param->data, dname, fname, param->obdindex,
380 param->quiet, param->verbose,
381 (param->verbose || !param->obduuid));
384 printf("unknown lmm_magic: 0x%08X\n", *(__u32 *)param->data);
389 void llapi_dump_fid(struct find_param *param, char *dname, char *fname)
393 char path[PATH_MAX + 1];
395 n = snprintf(path, PATH_MAX, "%s/%s",
403 printf("%s:%*s"DLID4"\n", path, n, "",
404 OLID4((struct lustre_id *)param->data));
408 int llapi_file_get_stripe(char *path, struct lov_user_md *lum)
413 fname = strrchr(path, '/');
415 /* It should be a file (or other non-directory) */
417 dname = (char *)malloc(2);
423 dname = (char *)malloc(fname - path + 1);
426 strncpy(dname, path, fname - path);
427 dname[fname - path] = '\0';
431 if ((fd = open(dname, O_RDONLY)) == -1) {
436 strncpy((char *)lum, fname, sizeof(*lum));
437 if (ioctl(fd, IOC_MDC_GETSTRIPE, (void *)lum) == -1) {
451 int llapi_file_get_fid(char *path, void *data)
456 fname = strrchr(path, '/');
459 dname = (char *)malloc(2);
465 dname = (char *)malloc(fname - path + 1);
468 strncpy(dname, path, fname - path);
469 dname[fname - path] = '\0';
476 if ((fd = open(dname, O_RDONLY)) == -1) {
481 strncpy((char *)data, fname, strlen(fname));
482 if (ioctl(fd, IOC_MDC_SHOWFID, (void *)data) == -1) {
495 /* short term backwards compat only */
496 int op_get_file_stripe(char *path, struct lov_user_md *lum)
498 return llapi_file_get_stripe(path, lum);
501 static int process_file(DIR *dir, char *dname, char *fname,
502 struct find_param *param)
506 if (param->showfid) {
507 char path[PATH_MAX + 1];
509 snprintf(path, PATH_MAX, "%s/%s", dname, fname);
510 rc = llapi_file_get_fid(path, (void *)param->data);
512 err_msg("IOC_MDC_SHOWFID ioctl failed");
515 llapi_dump_fid(param, dname, fname);
517 strncpy((char *)param->data, fname, param->datalen);
518 rc = ioctl(dirfd(dir), IOC_MDC_GETSTRIPE, (void *)param->data);
520 if (errno == ENODATA) {
521 if (!param->obduuid && !param->quiet)
523 "%s/%s has no stripe info\n",
526 } else if (errno == EISDIR) {
527 fprintf(stderr, "process_file on directory %s/%s!\n",
529 /* add fname to directory list; */
532 err_msg("IOC_MDC_GETSTRIPE ioctl failed");
537 llapi_lov_dump_user_lmm(param, dname, fname);
542 /* some 64bit libcs implement readdir64() by calling sys_getdents(). the
543 * kernel's sys_getdents() doesn't return d_type. */
544 unsigned char handle_dt_unknown(char *parent, char *entry)
546 char path[PATH_MAX + 1];
549 ret = snprintf(path, PATH_MAX, "%s/%s", parent, entry);
553 fd = open(path, O_DIRECTORY|O_RDONLY);
555 if (errno == ENOTDIR)
556 return DT_REG; /* kind of a lie */
563 static int process_dir(DIR *dir, char *dname, struct find_param *param)
565 char path[PATH_MAX + 1];
566 struct dirent64 *dirp;
570 /* retrieve dir's stripe info */
571 if (param->showfid) {
572 rc = llapi_file_get_fid(dname, (void *)param->data);
574 err_msg("IOC_MDC_SHOWFID ioctl failed");
577 llapi_dump_fid(param, dname, "");
579 if (!param->got_uuids) {
580 rc = setup_obd_uuids(dir, dname, param);
585 strncpy((char *)param->data, dname, param->datalen);
586 rc = ioctl(dirfd(dir), LL_IOC_LOV_GETSTRIPE, (void *)param->data);
588 if (errno == ENODATA) {
589 if (!param->obduuid && param->verbose)
590 printf("%s/%s has no stripe info\n", dname, "");
593 err_msg("IOC_MDC_GETSTRIPE ioctl failed");
597 llapi_lov_dump_user_lmm(param, dname, "");
601 /* Handle the contents of the directory */
602 while ((dirp = readdir64(dir)) != NULL) {
603 if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
606 if (dirp->d_type == DT_UNKNOWN)
607 dirp->d_type = handle_dt_unknown(dname, dirp->d_name);
609 switch (dirp->d_type) {
611 err_msg("\"%s\" is UNKNOWN type %d", dirp->d_name,
613 /* If we cared we could stat the file to determine
614 * type and continue on here, but we don't since we
615 * know d_type should be valid for lustre and this
616 * tool only makes sense for lustre filesystems. */
619 if (!param->recursive)
623 strcat(path, dirp->d_name);
624 subdir = opendir(path);
625 if (subdir == NULL) {
626 err_msg("\"%.40s\" opendir failed", path);
629 rc = process_dir(subdir, path, param);
635 rc = process_file(dir, dname, dirp->d_name, param);
647 static int process_path(char *path, struct find_param *param)
653 fname = strrchr(path, '/');
654 if (fname != NULL && fname[1] == '\0') {
655 /* Trailing '/', it must be a dir */
659 err_msg("\"%.40s\" opendir failed", path);
662 rc = process_dir(dir, path, param);
665 } else if ((dir = opendir(path)) != NULL) {
666 /* No trailing '/', but it is still a dir */
667 rc = process_dir(dir, path, param);
670 /* It must be a file (or other non-directory) */
679 dir = opendir(dname);
681 err_msg("\"%.40s\" opendir failed", dname);
684 if (!param->showfid) {
685 if (!param->got_uuids)
686 rc = setup_obd_uuids(dir, dname, param);
689 rc = process_file(dir, dname, fname, param);
697 int llapi_find(char *path, struct obd_uuid *obduuid, int recursive,
698 int verbose, int quiet, int showfid)
700 struct find_param param;
703 memset(¶m, 0, sizeof(param));
704 param.recursive = recursive;
705 param.showfid = showfid;
706 param.verbose = verbose;
709 param.obduuid = malloc(sizeof(*obduuid));
710 if (param.obduuid == NULL) {
714 memcpy(param.obduuid, obduuid, sizeof(*obduuid));
717 ret = prepare_find(¶m);
721 process_path(path, ¶m);
723 cleanup_find(¶m);
727 #define MAX_STRING_SIZE 128
728 #define DEVICES_LIST "/proc/fs/lustre/devices"
730 int llapi_target_check(int type_num, char **obd_type, char *dir)
732 char buf[MAX_STRING_SIZE];
733 FILE *fp = fopen(DEVICES_LIST, "r");
738 fprintf(stderr, "error: %s opening "DEVICES_LIST"\n",
739 strerror(rc = errno));
743 while (fgets(buf, sizeof(buf), fp) != NULL) {
744 char *obd_type_name = NULL;
745 char *obd_name = NULL;
746 char rawbuf[OBD_MAX_IOCTL_BUFFER];
749 struct obd_ioctl_data datal = { 0, };
750 struct obd_statfs osfs_buffer;
752 while(bufp[0] == ' ')
755 for(i = 0; i < 3; i++) {
756 obd_type_name = strsep(&bufp, " ");
758 obd_name = strsep(&bufp, " ");
760 memset(&osfs_buffer, 0, sizeof (osfs_buffer));
762 memset(bufl, 0, sizeof(rawbuf));
763 datal.ioc_pbuf1 = (char *)&osfs_buffer;
764 datal.ioc_plen1 = sizeof(osfs_buffer);
766 for (i = 0; i < type_num; i++)
767 if (strcmp(obd_type_name, obd_type[i]) == 0) {
768 datal.ioc_inlbuf1 = obd_name;
769 datal.ioc_inllen1 = strlen(obd_name) + 1;
771 rc = obd_ioctl_pack(&datal, &bufl, OBD_MAX_IOCTL_BUFFER);
773 fprintf(stderr, "internal buffer error packing\n");
777 rc = ioctl(dirfd(opendir(dir)), OBD_IOC_PING,
781 fprintf(stderr, "error: check %s: %s\n",
782 obd_name, strerror(rc = errno));
784 printf("%s active.\n",obd_name);
793 #undef MAX_STRING_SIZE
795 int llapi_catinfo(char *dir, char *keyword, char *node_name)
797 char raw[OBD_MAX_IOCTL_BUFFER];
798 char out[LLOG_CHUNK_SIZE];
800 struct obd_ioctl_data data;
805 sprintf(key, "%s", keyword);
806 memset(raw, 0, sizeof(buf));
807 memset(out, 0, sizeof(out));
808 data.ioc_inlbuf1 = key;
809 data.ioc_inllen1 = strlen(key) + 1;
811 data.ioc_inlbuf2 = node_name;
812 data.ioc_inllen2 = strlen(node_name) + 1;
814 data.ioc_pbuf1 = out;
815 data.ioc_plen1 = sizeof(out);
816 rc = obd_ioctl_pack(&data, &buf, sizeof(raw));
822 err_msg("open %s failed", dir);
826 rc = ioctl(dirfd(root), OBD_IOC_LLOG_CATINFO, buf);
828 err_msg("ioctl OBD_IOC_CATINFO failed");
830 fprintf(stdout, "%s", data.ioc_pbuf1);
836 int llapi_getfacl(char *dir, char *cmd)
838 struct ll_acl_ioctl_data data;
839 char out[LUSTRE_ACL_SIZE_MAX];
843 data.cmd_len = strlen(cmd) + 1;
845 data.res_len = sizeof(out);
848 fd = open(dir, O_RDONLY | O_DIRECTORY);
850 err_msg("can't open dir %s", dir);
854 rc = ioctl(fd, LL_IOC_GETFACL, &data);
856 err_msg("getfacl failed");
858 out[sizeof(out) - 1] = '\0';
868 int llapi_setfacl(char *dir, char *cmd)
870 struct ll_acl_ioctl_data data;
871 char out[LUSTRE_ACL_SIZE_MAX];
875 data.cmd_len = strlen(cmd) + 1;
877 data.res_len = sizeof(out);
880 fd = open(dir, O_RDONLY | O_DIRECTORY);
882 err_msg("can't open dir %s", dir);
886 rc = ioctl(fd, LL_IOC_SETFACL, &data);
888 err_msg("setfacl failed");
890 out[sizeof(out) - 1] = '\0';
900 int llapi_is_lustre_mnttype(char *type)
902 return (strcmp(type,"lustre") == 0 || strcmp(type,"lustre_lite") == 0);