*
*/
-
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>
+#include <ctype.h>
+/* For dirname() */
+#include <libgen.h>
#include <lnet/api-support.h>
#include <lnet/lnetctl.h>
static int lfs_setquota(int argc, char **argv);
static int lfs_quota(int argc, char **argv);
#endif
+static int lfs_flushctx(int argc, char **argv);
static int lfs_join(int argc, char **argv);
+static int lfs_getfacl(int argc, char **argv);
+static int lfs_setfacl(int argc, char **argv);
/* all avaialable commands */
command_t cmdlist[] = {
"Create a new file with a specific striping pattern or\n"
"set the default striping pattern on an existing directory or\n"
"delete the default striping pattern from an existing directory\n"
- "usage: setstripe <filename|dirname> <stripe size> <stripe start> <stripe count>\n"
+ "usage: setstripe <filename|dirname> <stripe_size> <stripe_index> <stripe_count>\n"
+ " or \n"
+ " setstripe <filename|dirname> [--size|-s stripe_size]\n"
+ " [--index|-i stripe_index]\n"
+ " [--count|-c stripe_count]\n"
" or \n"
" setstripe -d <dirname> (to delete default striping)\n"
- "\tstripe size: Number of bytes on each OST (0 filesystem default)\n"
- "\tstripe start: OST index of first stripe (-1 filesystem default)\n"
- "\tstripe count: Number of OSTs to stripe over (0 default, -1 all)"},
+ "\tstripe_size: Number of bytes on each OST (0 filesystem default)\n"
+ "\t Can be specified with k, m or g (in KB, MB and GB respectively)\n"
+ "\tstripe_index: OST index of first stripe (-1 filesystem default)\n"
+ "\tstripe_count: Number of OSTs to stripe over (0 default, -1 all)"},
{"getstripe", lfs_getstripe, 0,
"To list the striping info for a given filename or files in a\n"
"directory or recursively for all files in a directory tree.\n"
"usage: setquota [ -u | -g ] <name> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> <filesystem>\n"
" setquota -t [ -u | -g ] <block-grace> <inode-grace> <filesystem>"},
{"quota", lfs_quota, 0, "Display disk usage and limits.\n"
- "usage: quota [ -o obd_uuid ] [ -u | -g ] [name] <filesystem>"},
+ "usage: quota [ -o obd_uuid ] [{-u|-g <name>}|-t] <filesystem>"},
#endif
+ {"flushctx", lfs_flushctx, 0, "Flush security context for current user.\n"
+ "usage: flushctx [-k] [mountpoint...]"},
+ {"getfacl", lfs_getfacl, 0,
+ "Get file access control list in remote client.\n"
+ "usage: getfacl [-dRLPvh] file"},
+ {"setfacl", lfs_setfacl, 0,
+ "Set file access control list in remote client.\n"
+ "usage: setfacl [-bkndRLPvh] [{-m|-x} acl_spec] [{-M|-X} acl_file] file"},
{"help", Parser_help, 0, "help"},
{"exit", Parser_quit, 0, "quit"},
{"quit", Parser_quit, 0, "quit"},
{
char *fname;
int result;
- long st_size;
+ unsigned long st_size;
int st_offset, st_count;
char *end;
+ int c;
+ int delete = 0;
+ char *stripe_size_arg = NULL;
+ char *stripe_off_arg = NULL;
+ char *stripe_count_arg = NULL;
- if (argc != 5 && argc != 3)
- return CMD_HELP;
-
-
- if (argc == 3) {
- if (strcmp(argv[1], "-d") != 0)
- return CMD_HELP;
+ struct option long_opts[] = {
+ {"size", required_argument, 0, 's'},
+ {"count", required_argument, 0, 'c'},
+ {"index", required_argument, 0, 'i'},
+ {"delete", no_argument, 0, 'd'},
+ {0, 0, 0, 0}
+ };
+ st_size = 0;
+ st_offset = -1;
+ st_count = 0;
+ if (argc == 3 && strcmp(argv[1], "-d") == 0) {
+ /* for compatibility with the existing positional parameter
+ * usage */
fname = argv[2];
- st_size = 0;
- st_offset = -1;
- st_count = 0;
- } else {
+ optind = 2;
+ } else if (argc == 5 &&
+ (argv[2][0] != '-' || isdigit(argv[2][1])) &&
+ (argv[3][0] != '-' || isdigit(argv[3][1])) &&
+ (argv[4][0] != '-' || isdigit(argv[4][1])) ) {
+ /* for compatibility with the existing positional parameter
+ * usage */
fname = argv[1];
+ stripe_size_arg = argv[2];
+ stripe_off_arg = argv[3];
+ stripe_count_arg = argv[4];
+ optind = 4;
+ } else {
+ while ((c = getopt_long(argc, argv, "c:di:s:",
+ long_opts, NULL)) >= 0)
+ {
+ switch (c) {
+ case 0:
+ /* Long options. */
+ break;
+ case 'c':
+ stripe_count_arg = optarg;
+ break;
+ case 'd':
+ /* delete the default striping pattern */
+ delete = 1;
+ break;
+ case 'i':
+ stripe_off_arg = optarg;
+ break;
+ case 's':
+ stripe_size_arg = optarg;
+ break;
+ case '?':
+ return CMD_HELP;
+ default:
+ fprintf(stderr, "error: %s: option '%s' "
+ "unrecognized\n",
+ argv[0], argv[optind - 1]);
+ return CMD_HELP;
+ }
+ }
+ if (optind < argc)
+ fname = argv[optind];
+ else
+ 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]);
+
+ if (delete &&
+ (stripe_size_arg != NULL || stripe_off_arg != NULL ||
+ stripe_count_arg != NULL)) {
+ fprintf(stderr, "error: %s: cannot specify -d with "
+ "-s, -c or -i options\n",
+ argv[0]);
return CMD_HELP;
}
+ }
+ if (optind != argc - 1) {
+ fprintf(stderr, "error: %s: only 1 filename|dirname can be "
+ "specified: '%s'\n",
+ argv[0], argv[argc - 1]);
+ return CMD_HELP;
+ }
- /* get the stripe offset */
- st_offset = strtoul(argv[3], &end, 0);
+ /* get the stripe size */
+ if (stripe_size_arg != NULL) {
+ st_size = strtoul(stripe_size_arg, &end, 0);
+ if (*end != '\0') {
+ if ((*end == 'k' || *end == 'K') &&
+ *(end+1) == '\0' &&
+ (st_size & (~0UL << (32 - 10))) == 0) {
+ st_size <<= 10;
+ } else if ((*end == 'm' || *end == 'M') &&
+ *(end+1) == '\0' &&
+ (st_size & (~0UL << (32 - 20))) == 0) {
+ st_size <<= 20;
+ } else if ((*end == 'g' || *end == 'G') &&
+ *(end+1) == '\0' &&
+ (st_size & (~0UL << (32 - 30))) == 0) {
+ st_size <<= 30;
+ } else {
+ fprintf(stderr, "error: %s: bad stripe size '%s'\n",
+ argv[0], stripe_size_arg);
+ return CMD_HELP;
+ }
+ }
+ }
+ /* get the stripe offset */
+ if (stripe_off_arg != NULL) {
+ st_offset = strtoul(stripe_off_arg, &end, 0);
if (*end != '\0') {
fprintf(stderr, "error: %s: bad stripe offset '%s'\n",
- argv[0], argv[3]);
+ argv[0], stripe_off_arg);
return CMD_HELP;
}
- /* get the stripe count */
- st_count = strtoul(argv[4], &end, 0);
+ }
+ /* get the stripe count */
+ if (stripe_count_arg != NULL) {
+ st_count = strtoul(stripe_count_arg, &end, 0);
if (*end != '\0') {
fprintf(stderr, "error: %s: bad stripe count '%s'\n",
- argv[0], argv[4]);
+ argv[0], stripe_count_arg);
return CMD_HELP;
}
}
{
int new_fashion = 1;
int c, ret;
- int zeroend;
time_t t;
- unsigned int depth;
- int quiet, verbose, recursive;
- struct find_param param;
- struct obd_uuid *obduuid = NULL;
+ struct find_param param = { .maxdepth = -1 };
char timestr[1024];
struct option long_opts[] = {
/* New find options. */
int isoption;
time(&t);
- zeroend = 0;
- depth = -1;
- quiet = verbose = recursive = 0;
-
- memset(¶m, 0, sizeof(param));
- while ((c = getopt_long_only(argc, argv, "-A:C:D:M:n:PpOqrv",
- long_opts, NULL)) >= 0)
- {
+ while ((c = getopt_long_only(argc, argv, "-A:C:D:M:n:PpO:qrv",
+ long_opts, NULL)) >= 0) {
xtime = NULL;
xsign = NULL;
if (neg_opt)
case 1:
if (strcmp(optarg, "!") == 0)
neg_opt = 2;
- break;
+ break;
case 'A':
xtime = ¶m.atime;
xsign = ¶m.asign;
*xsign = ret;
break;
case 'D':
- depth = strtol(optarg, 0, 0);
+ param.maxdepth = strtol(optarg, 0, 0);
break;
case 'n':
new_fashion = 1;
param.exclude_pattern = 0;
break;
case 'O':
- if (obduuid) {
+ if (param.obduuid) {
fprintf(stderr,
"error: %s: only one obduuid allowed",
argv[0]);
return CMD_HELP;
}
- obduuid = (struct obd_uuid *)optarg;
+ param.obduuid = (struct obd_uuid *)optarg;
break;
case 'p':
- zeroend = 1;
+ param.zeroend = 1;
break;
case 'P':
break;
case 'q':
new_fashion = 0;
- quiet++;
- verbose = 0;
+ param.quiet++;
+ param.verbose = 0;
break;
case 'r':
new_fashion = 0;
- recursive = 1;
+ param.recursive = 1;
break;
case 'v':
new_fashion = 0;
- verbose++;
- quiet = 0;
+ param.verbose++;
+ param.quiet = 0;
break;
case '?':
return CMD_HELP;
return CMD_HELP;
};
}
-
+
if (pathstart == -1) {
fprintf(stderr, "error: %s: no filename|pathname\n",
- argv[0]);
+ argv[0]);
return CMD_HELP;
} else if (pathend == -1) {
/* no options */
pathend = argc;
}
- param.obduuid = obduuid;
if (new_fashion) {
- param.maxdepth = depth;
- param.zeroend = zeroend;
param.quiet = 1;
} else {
- param.recursive = recursive;
- param.verbose = verbose;
- param.quiet = quiet;
- param.maxdepth = recursive ? -1 : 1;
+ if (!param.recursive && param.maxdepth == -1)
+ param.maxdepth = 1;
}
-
+
do {
if (new_fashion)
ret = llapi_find(argv[pathstart], ¶m);
if (ret)
fprintf(stderr, "error: %s failed for %s.\n",
argv[0], argv[optind - 1]);
-
return ret;
}
{0, 0, 0, 0}
};
char short_opts[] = "hO:qrv";
- int quiet, verbose, recursive, c, rc;
- struct obd_uuid *obduuid = NULL;
- struct find_param param;
+ int c, rc;
+ struct find_param param = { 0 };
optind = 0;
- quiet = verbose = recursive = 0;
while ((c = getopt_long(argc, argv, short_opts,
long_opts, NULL)) != -1) {
switch (c) {
case 'O':
- if (obduuid) {
+ if (param.obduuid) {
fprintf(stderr,
"error: %s: only one obduuid allowed",
argv[0]);
return CMD_HELP;
}
- obduuid = (struct obd_uuid *)optarg;
+ param.obduuid = (struct obd_uuid *)optarg;
break;
case 'q':
- quiet++;
- verbose = 0;
+ param.quiet++;
+ param.verbose = 0;
break;
case 'r':
- recursive = 1;
+ param.recursive = 1;
break;
case 'v':
- verbose++;
- quiet = 0;
+ param.verbose++;
+ param.quiet = 0;
break;
case '?':
return CMD_HELP;
if (optind >= argc)
return CMD_HELP;
- memset(¶m, 0, sizeof(param));
- param.recursive = recursive;
- param.verbose = verbose;
- param.quiet = quiet;
- param.obduuid = obduuid;
- param.maxdepth = recursive ? -1 : 1;
+ param.maxdepth = param.recursive ? -1 : 1;
do {
rc = llapi_getstripe(argv[optind], ¶m);
memset(¶m, 0, sizeof(param));
param.obduuid = obduuid;
while (feof(fp) == 0 && ferror(fp) ==0) {
- if (llapi_is_lustre_mnttype(mnt)) {
+ if (llapi_is_lustre_mnt(mnt)) {
rc = llapi_getstripe(mnt->mnt_dir, ¶m);
if (rc)
fprintf(stderr,
len = 0;
mnt = getmntent(fp);
while (feof(fp) == 0 && ferror(fp) == 0) {
- if (llapi_is_lustre_mnttype(mnt)) {
+ if (llapi_is_lustre_mnt(mnt)) {
len = strlen(mnt->mnt_dir);
if (len > out_len &&
!strncmp(rpath, mnt->mnt_dir, len)) {
} else {
mnt = getmntent(fp);
while (feof(fp) == 0 && ferror(fp) == 0) {
- if (llapi_is_lustre_mnttype(mnt)) {
+ if (llapi_is_lustre_mnt(mnt)) {
rc = mntdf(mnt->mnt_dir, ishow, cooked);
if (rc)
break;
} else {
mnt = getmntent(fp);
while (feof(fp) == 0 && ferror(fp) ==0) {
- if (llapi_is_lustre_mnttype(mnt))
+ if (llapi_is_lustre_mnt(mnt))
break;
mnt = getmntent(fp);
}
} else {
mnt = getmntent(fp);
while (feof(fp) == 0 && ferror(fp) == 0) {
- if (llapi_is_lustre_mnttype(mnt))
+ if (llapi_is_lustre_mnt(mnt))
break;
mnt = getmntent(fp);
}
*type2name(qctl->qc_type), qctl->qc_id);
printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n",
"Filesystem",
- "blocks", "quota", "limit", "grace",
+ "kbytes", "quota", "limit", "grace",
"files", "quota", "limit", "grace");
}
{
int c;
char *name = NULL, *mnt;
- struct if_quotactl qctl;
+ struct if_quotactl qctl = { .qc_cmd = LUSTRE_Q_GETQUOTA,
+ .qc_type = 0x01 };
char *obd_type = qctl.obd_type;
char *obd_uuid = qctl.obd_uuid.uuid;
int rc;
- memset(&qctl, 0, sizeof(qctl));
- qctl.qc_cmd = LUSTRE_Q_GETQUOTA;
-
optind = 0;
while ((c = getopt(argc, argv, "ugto:")) != -1) {
switch (c) {
case 'u':
- qctl.qc_type |= 0x01;
+ qctl.qc_type = 0x01;
break;
case 'g':
- qctl.qc_type |= 0x02;
+ qctl.qc_type = 0x02;
break;
case 't':
qctl.qc_cmd = LUSTRE_Q_GETINFO;
if (qctl.qc_type)
qctl.qc_type--;
- if (qctl.qc_type == UGQUOTA) {
- fprintf(stderr, "error: user or group can't be specified"
- "both\n");
- return CMD_HELP;
- }
if (qctl.qc_cmd == LUSTRE_Q_GETQUOTA) {
- if (optind + 2 != argc)
+ if (optind + 2 != argc) {
+ fprintf(stderr, "error: missing quota argument(s)\n");
return CMD_HELP;
+ }
name = argv[optind++];
rc = name2id(&qctl.qc_id, name, qctl.qc_type);
if (rc) {
- fprintf(stderr, "error: find id for name %s failed: %s\n",
+ fprintf(stderr,"error: can't find id for name %s: %s\n",
name, strerror(errno));
return CMD_HELP;
}
print_quota_title(name, &qctl);
} else if (optind + 1 != argc) {
+ fprintf(stderr, "error: missing quota info argument(s)\n");
return CMD_HELP;
}
}
#endif /* HAVE_QUOTA_SUPPORT */
+static int flushctx_ioctl(char *mp)
+{
+ int fd, rc;
+
+ fd = open(mp, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "flushctx: error open %s: %s\n",
+ mp, strerror(errno));
+ return -1;
+ }
+
+ rc = ioctl(fd, LL_IOC_FLUSHCTX);
+ if (rc == -1)
+ fprintf(stderr, "flushctx: error ioctl %s: %s\n",
+ mp, strerror(errno));
+
+ close(fd);
+ return rc;
+}
+
+static int lfs_flushctx(int argc, char **argv)
+{
+ int kdestroy = 0, c;
+ FILE *proc;
+ char procline[PATH_MAX], *line;
+ int rc = 0;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "k")) != -1) {
+ switch (c) {
+ case 'k':
+ kdestroy = 1;
+ break;
+ default:
+ fprintf(stderr, "error: %s: option '-%c' "
+ "unrecognized\n", argv[0], c);
+ return CMD_HELP;
+ }
+ }
+
+ if (kdestroy)
+ system("kdestroy > /dev/null");
+
+ if (optind >= argc) {
+ /* flush for all mounted lustre fs. */
+ proc = fopen("/proc/mounts", "r");
+ if (!proc) {
+ fprintf(stderr, "error: %s: can't open /proc/mounts\n",
+ argv[0]);
+ return -1;
+ }
+
+ while ((line = fgets(procline, PATH_MAX, proc)) != NULL) {
+ char dev[PATH_MAX];
+ char mp[PATH_MAX];
+ char fs[PATH_MAX];
+
+ if (sscanf(line, "%s %s %s", dev, mp, fs) != 3) {
+ fprintf(stderr, "%s: unexpected format in "
+ "/proc/mounts\n",
+ argv[0]);
+ return -1;
+ }
+
+ if (strcmp(fs, "lustre") != 0)
+ continue;
+ /* we use '@' to determine it's a client. are there
+ * any other better way?
+ */
+ if (strchr(dev, '@') == NULL)
+ continue;
+
+ if (flushctx_ioctl(mp))
+ rc = -1;
+ }
+ } else {
+ /* flush fs as specified */
+ while (optind < argc) {
+ if (flushctx_ioctl(argv[optind++]))
+ rc = -1;
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * We assume one and only one filename is supplied as the
+ * last parameter.
+ */
+static int acl_cmd_parse(int argc, char **argv, char *fname, char *cmd)
+{
+ char *dname, *rpath = NULL;
+ char path[PATH_MAX], cwd[PATH_MAX];
+ FILE *fp;
+ struct mntent *mnt;
+ int i;
+
+ if (argc < 2)
+ return -1;
+
+ /* FIXME the premise is there is no sub-mounted filesystems under this
+ * mounted lustre tree. */
+ strncpy(fname, argv[argc - 1], PATH_MAX);
+
+ /* get path prefix */
+ dname = dirname(fname);
+
+ /* try to resolve the pathname into relative to the root of the mounted
+ * lustre filesystem.
+ */
+ if (getcwd(cwd, sizeof(cwd)) == NULL) {
+ fprintf(stderr, "getcwd %s failed: %s\n", cwd, strerror(errno));
+ return -1;
+ }
+
+ if (chdir(dname) == -1) {
+ fprintf(stderr, "chdir to %s failed: %s\n",
+ dname, strerror(errno));
+ return -1;
+ }
+
+ if (getcwd(path, sizeof(path)) == NULL) {
+ fprintf(stderr, "getcwd %s: %s\n", path, strerror(errno));
+ return -1;
+ }
+
+ if (chdir(cwd) == -1) {
+ fprintf(stderr, "chdir back to %s: %s\n",
+ cwd, strerror(errno));
+ return -1;
+ }
+
+ strncat(path, "/", PATH_MAX);
+ strncpy(fname, argv[argc - 1], PATH_MAX);
+ strncat(path, basename(fname), PATH_MAX);
+
+ fp = setmntent(MOUNTED, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "setmntent %s failed: %s\n",
+ MOUNTED, strerror(errno));
+ return -1;
+ }
+
+ while (1) {
+ mnt = getmntent(fp);
+ if (!mnt)
+ break;
+
+ if (!llapi_is_lustre_mnttype(mnt->mnt_type))
+ continue;
+
+ if (!strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir))) {
+ rpath = path + strlen(mnt->mnt_dir);
+ break;
+ }
+ }
+ endmntent(fp);
+
+ /* remove char '/' from rpath to be a relative path */
+ while (rpath && *rpath == '/') rpath++;
+
+ if (!rpath) {
+ fprintf(stderr,
+ "%s: file %s doesn't belong to a lustre file system!\n",
+ argv[0], argv[argc - 1]);
+ return -1;
+ }
+
+ for (i = 0; i < argc - 1; i++) {
+ strncat(cmd, argv[i], PATH_MAX);
+ strncat(cmd, " ", PATH_MAX);
+ }
+ strncat(cmd, *rpath ? rpath : ".", PATH_MAX);
+ strncpy(fname, argv[argc - 1], sizeof(fname));
+
+ return 0;
+}
+
+static int lfs_getfacl(int argc, char **argv)
+{
+ char fname[PATH_MAX] = "", cmd[PATH_MAX] = "";
+
+ if (acl_cmd_parse(argc, argv, fname, cmd))
+ return CMD_HELP;
+
+ return llapi_getfacl(fname, cmd);
+}
+
+static int lfs_setfacl(int argc, char **argv)
+{
+ char fname[PATH_MAX] = "", cmd[PATH_MAX] = "";
+
+ if (acl_cmd_parse(argc, argv, fname, cmd))
+ return CMD_HELP;
+
+ return llapi_setfacl(fname, cmd);
+}
+
int main(int argc, char **argv)
{
int rc;