lhbadm.8 \
llapi_create_volatile_param.3 \
llapi_fd2parent.3 \
+ llapi_fid_parse.3 \
llapi_file_create.3 \
llapi_file_create_foreign.3 \
llapi_file_get_stripe.3 \
--- /dev/null
+.TH lustreapi 3 "2019 Sep 13" Lustre user application interface library
+.SH NAME
+llapi_fid_parse \- parse ASCII FID string into binary lu_fid
+.SH SYNOPSIS
+.nf
+.B #include <lustre/lustreapi.h>
+.sp
+.BI "int llapi_fid_parse(const char *" fidstr ", struct lu_fid *" fid ,
+.BI " char **" endptr ");"
+.sp
+.fi
+.SH DESCRIPTION
+.LP
+.B llapi_fid_parse()
+converts an ASCII FID string into a binary
+.B struct lu_fid
+for use in other interfaces such as
+.BR llapi_layout_get_by_fid() .
+.I fidstr
+should contain three numbers in the form
+.IR fid_seq : fid_oid : fid_ver
+and may optionally be enclosed in square braces
+.BR [] .
+It will skip any leading whitespace before the FID.
+.LP
+If
+.I endptr
+is not NULL,
+.B llapi_fid_parse()
+stores the address of the first invalid character in
+.IR *endptr ,
+or the character immediately following the end of the parsed FID.
+.SH RETURN VALUES
+.LP
+.B llapi_fid_parse()
+returns:
+.TP
+0
+on success,
+.TP
+<0
+a negative errno on failure and sets errno.
+.SH ERRORS
+.TP 15
+.SM EINVAL
+.I fidstr
+is NULL or does not contain a valid FID format.
+.TP
+.SM ERANGE
+.I fidstr
+contains numeric values that exceed valid values for a component.
+.SH "EXAMPLE"
+.nf
+#include <lustre/lustreapi.h>
+
+int main(int argc, char *argv[])
+{
+ char fidstr = "[0x200000004:0x2:0x0] [0x200000400:0x345:0x0]";
+ struct lu_fid fid1, fid2;
+ char *end;
+ int rc;
+
+ fidstr = argv[1];
+ rc = llapi_fid_parse(fidstr, &fid1, &end);
+ if (rc < 0) {
+ fprintf(stderr, "invalid first FID '%s': %s\\n",
+ fidstr, strerror(-rc));
+ return -1;
+ }
+
+ fidstr = end;
+ rc = llapi_fid_parse(fidstr, &fid2, &end);
+ if (rc < 0) {
+ fprintf(stderr, "invalid second FID '%s': %s\\n",
+ fidstr, strerror(-rc));
+ return -1;
+ }
+
+ printf("fid1=" DFID " fid2="DFID"\\n", PFID(&fid1), PFID(&fid2));
+ return 0;
+}
+.fi
+.SH "SEE ALSO"
+.BR lustre (7),
+.BR llapi_path2parent (3),
+.BR lustreapi (7)
.BR llapi_create_volatile_param (3),
.BR llapi_fd2parent (3),
.BR llapi_fid2path (3),
+.BR llapi_fid_parse (3),
.BR llapi_file_create (3),
.BR llapi_file_get_stripe (3),
.BR llapi_file_open (3),
int llapi_get_connect_flags(const char *mnt, __u64 *flags);
int llapi_cp(int argc, char *argv[]);
int llapi_ls(int argc, char *argv[]);
+int llapi_fid_parse(const char *fidstr, struct lu_fid *fid, char **endptr);
int llapi_fid2path(const char *device, const char *fidstr, char *path,
int pathlen, long long *recno, int *linkno);
int llapi_path2fid(const char *path, struct lu_fid *fid);
This licence file applies to new library files:
+lustre/utils/liblustreapi_fid.c
lustre/utils/liblustreapi_hsm.c
lustre/utils/liblustreapi_json.c
lustre/utils/liblustreapi_layout.c
liblustreapi_json.c liblustreapi_layout.c \
liblustreapi_lease.c liblustreapi_util.c \
liblustreapi_kernelconn.c liblustreapi_param.c \
- liblustreapi_mirror.c \
+ liblustreapi_mirror.c liblustreapi_fid.c \
liblustreapi_ladvise.c liblustreapi_chlg.c \
liblustreapi_heat.c liblustreapi_pcc.c
liblustreapi_la_LDFLAGS = $(LIBREADLINE) -version-info 1:0:0 \
hui->hui_extent.length = -1;
if (mntpath != NULL) {
- if (*fname == '[')
- fname++;
- rc = sscanf(fname, SFID, RFID(&hui->hui_fid));
- if (rc == 3) {
- rc = 0;
- } else {
+ rc = llapi_fid_parse(fname, &hui->hui_fid, NULL);
+ if (rc)
fprintf(stderr, "hsm: '%s' is not a valid FID\n",
fname);
- rc = -EINVAL;
- }
} else {
rc = lfs_hsm_prepare_file(fname, &hui->hui_fid, last_dev);
}
if (relpath == NULL)
return -EINVAL;
- /* Is relpath a FID? In which case SFID should expand to three
- * elements. */
- rc = sscanf(relpath, SFID, RFID(&import_fid));
- if (rc == 3)
+ /* Is relpath a FID? */
+ rc = llapi_fid_parse(relpath, &import_fid, NULL);
+ if (!rc)
return ct_import_fid(&import_fid);
srcpath = path_concat(opt.o_hsm_root, relpath);
/* each line consists of 2 FID */
while ((r = getline(&line, &line_size, filp)) != -1) {
- struct lu_fid old_fid;
- struct lu_fid new_fid;
+ struct lu_fid old_fid;
+ struct lu_fid new_fid;
+ char *next_fid;
/* Ignore empty and commented out ('#...') lines. */
if (should_ignore_line(line))
nl++;
- rc = sscanf(line, SFID" "SFID, RFID(&old_fid), RFID(&new_fid));
- if (rc != 6 || !fid_is_file(&old_fid) ||
- !fid_is_file(&new_fid)) {
- CT_ERROR(EINVAL,
- "'%s' FID expected near '%s', line %u",
- list, line, nl);
+ rc = llapi_fid_parse(line, &old_fid, &next_fid);
+ if (rc)
+ goto error;
+ rc = llapi_fid_parse(next_fid, &new_fid, NULL);
+ if (rc)
+ goto error;
+ if (!fid_is_file(&old_fid) || !fid_is_file(&new_fid))
+ rc = -EINVAL;
+ if (rc) {
+error: CT_ERROR(rc, "%s:%u: two FIDs expected in '%s'",
+ list, nl, line);
err_major++;
continue;
}
static int ct_rebind(void)
{
- int rc;
+ int rc;
if (opt.o_dst) {
struct lu_fid old_fid;
struct lu_fid new_fid;
- if (sscanf(opt.o_src, SFID, RFID(&old_fid)) != 3 ||
- !fid_is_file(&old_fid)) {
+ rc = llapi_fid_parse(opt.o_src, &old_fid, NULL);
+ if (!rc && !fid_is_file(&old_fid))
rc = -EINVAL;
- CT_ERROR(rc, "'%s' invalid FID format", opt.o_src);
+ if (rc) {
+ CT_ERROR(rc, "invalid source FID '%s'", opt.o_src);
return rc;
}
- if (sscanf(opt.o_dst, SFID, RFID(&new_fid)) != 3 ||
- !fid_is_file(&new_fid)) {
+ rc = llapi_fid_parse(opt.o_dst, &new_fid, NULL);
+ if (!rc && !fid_is_file(&new_fid))
rc = -EINVAL;
- CT_ERROR(rc, "'%s' invalid FID format", opt.o_dst);
+ if (rc) {
+ CT_ERROR(rc, "invalid destination FID '%s'", opt.o_dst);
return rc;
}
return rc;
}
-/* Print mdtname 'name' into 'buf' using 'format'. Add -MDT0000 if needed.
- * format must have %s%s, buf must be > 16
- * Eg: if name = "lustre-MDT0000", "lustre", or "lustre-MDT0000_UUID"
- * then buf = "lustre-MDT0000"
- */
-static int get_mdtname(char *name, char *format, char *buf)
-{
- char suffix[]="-MDT0000";
- int len = strlen(name);
-
- if ((len > 5) && (strncmp(name + len - 5, "_UUID", 5) == 0)) {
- name[len - 5] = '\0';
- len -= 5;
- }
-
- if (len > 8) {
- if ((len <= 16) && strncmp(name + len - 8, "-MDT", 4) == 0) {
- suffix[0] = '\0';
- } else {
- /* Not enough room to add suffix */
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "Invalid MDT name |%s|", name);
- return -EINVAL;
- }
- }
-
- return sprintf(buf, format, name, suffix);
-}
-
-/** ioctl on filsystem root, with mdtindex sent as data
- * \param mdtname path, fsname, or mdtname (lutre-MDT0004)
- * \param mdtidxp pointer to integer within data to be filled in with the
- * mdt index (0 if no mdt is specified). NULL won't be filled.
- */
-int root_ioctl(const char *mdtname, int opc, void *data, int *mdtidxp,
- int want_error)
-{
- char fsname[20];
- char *ptr;
- int fd, rc;
- long index;
-
- /* Take path, fsname, or MDTname. Assume MDT0000 in the former cases.
- Open root and parse mdt index. */
- if (mdtname[0] == '/') {
- index = 0;
- rc = get_root_path(WANT_FD | want_error, NULL, &fd,
- (char *)mdtname, -1);
- } else {
- if (get_mdtname((char *)mdtname, "%s%s", fsname) < 0)
- return -EINVAL;
- ptr = fsname + strlen(fsname) - 8;
- *ptr = '\0';
- index = strtol(ptr + 4, NULL, 16);
- rc = get_root_path(WANT_FD | want_error, fsname, &fd, NULL, -1);
- }
- if (rc < 0) {
- if (want_error)
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "Can't open %s: %d\n", mdtname, rc);
- return rc;
- }
-
- if (mdtidxp)
- *mdtidxp = index;
-
- rc = ioctl(fd, opc, data);
- if (rc == -1)
- rc = -errno;
- else
- rc = 0;
- close(fd);
- return rc;
-}
-
-int llapi_fid2path(const char *device, const char *fidstr, char *buf,
- int buflen, long long *recno, int *linkno)
-{
- const char *fidstr_orig = fidstr;
- struct lu_fid fid;
- struct getinfo_fid2path *gf;
- char *a;
- char *b;
- int rc;
-
- while (*fidstr == '[')
- fidstr++;
-
- sscanf(fidstr, SFID, RFID(&fid));
- if (!fid_is_sane(&fid)) {
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "bad FID format '%s', should be [seq:oid:ver]"
- " (e.g. "DFID")\n", fidstr_orig,
- (unsigned long long)FID_SEQ_NORMAL, 2, 0);
- return -EINVAL;
- }
-
- gf = malloc(sizeof(*gf) + buflen);
- if (gf == NULL)
- return -ENOMEM;
-
- gf->gf_fid = fid;
- gf->gf_recno = *recno;
- gf->gf_linkno = *linkno;
- gf->gf_pathlen = buflen;
-
- /* Take path or fsname */
- rc = root_ioctl(device, OBD_IOC_FID2PATH, gf, NULL, 0);
- if (rc)
- goto out_free;
-
- b = buf;
- /* strip out instances of // */
- for (a = gf->gf_u.gf_path; *a != '\0'; a++) {
- if ((*a == '/') && (*(a + 1) == '/'))
- continue;
- *b = *a;
- b++;
- }
- *b = '\0';
-
- if (buf[0] == '\0') { /* ROOT path */
- buf[0] = '/';
- buf[1] = '\0';
- }
-
- *recno = gf->gf_recno;
- *linkno = gf->gf_linkno;
-
-out_free:
- free(gf);
- return rc;
-}
-
-static int fid_from_lma(const char *path, int fd, struct lu_fid *fid)
-{
- char buf[512];
- struct lustre_mdt_attrs *lma;
- int rc;
-
- if (path == NULL)
- rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf));
- else
- rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf));
- if (rc < 0)
- return -errno;
- lma = (struct lustre_mdt_attrs *)buf;
- fid_le_to_cpu(fid, &lma->lma_self_fid);
- return 0;
-}
-
-int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid,
- int *mdt_index)
-{
- int rc;
-
- rc = ioctl(fd, LL_IOC_FID2MDTIDX, fid);
- if (rc < 0)
- return -errno;
-
- *mdt_index = rc;
-
- return rc;
-}
-
-int llapi_fd2fid(int fd, struct lu_fid *fid)
-{
- int rc;
-
- memset(fid, 0, sizeof(*fid));
-
- rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0;
- if (rc == -EINVAL || rc == -ENOTTY)
- rc = fid_from_lma(NULL, fd, fid);
-
- return rc;
-}
-
-int llapi_path2fid(const char *path, struct lu_fid *fid)
-{
- int fd, rc;
-
- memset(fid, 0, sizeof(*fid));
- fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
- if (fd < 0) {
- if (errno == ELOOP || errno == ENXIO)
- return fid_from_lma(path, -1, fid);
- return -errno;
- }
-
- rc = llapi_fd2fid(fd, fid);
- if (rc == -EINVAL || rc == -ENOTTY)
- rc = fid_from_lma(path, -1, fid);
-
- close(fd);
- return rc;
-}
-
-int llapi_fd2parent(int fd, unsigned int linkno, struct lu_fid *parent_fid,
- char *name, size_t name_size)
-{
- struct getparent *gp;
- int rc;
-
- gp = malloc(sizeof(*gp) + name_size);
- if (gp == NULL)
- return -ENOMEM;
-
- gp->gp_linkno = linkno;
- gp->gp_name_size = name_size;
-
- rc = ioctl(fd, LL_IOC_GETPARENT, gp);
- if (rc < 0) {
- rc = -errno;
- goto err_free;
- }
-
- *parent_fid = gp->gp_fid;
-
- strncpy(name, gp->gp_name, name_size);
- name[name_size - 1] = '\0';
-
-err_free:
- free(gp);
- return rc;
-}
-
-int llapi_path2parent(const char *path, unsigned int linkno,
- struct lu_fid *parent_fid, char *name, size_t name_size)
-{
- int fd;
- int rc;
-
- fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
- if (fd < 0)
- return -errno;
-
- rc = llapi_fd2parent(fd, linkno, parent_fid, name, name_size);
- close(fd);
- return rc;
-}
-
int llapi_get_connect_flags(const char *mnt, __u64 *flags)
{
int root;
}
/**
- * Attempt to open a file with Lustre file identifier \a fid
- * and return an open file descriptor.
- *
- * \param[in] lustre_dir path within Lustre filesystem containing \a fid
- * \param[in] fid Lustre file identifier of file to open
- * \param[in] flags open() flags
- *
- * \retval non-negative file descriptor on successful open
- * \retval -1 if an error occurred
- */
-int llapi_open_by_fid(const char *lustre_dir, const struct lu_fid *fid,
- int flags)
-{
- char mntdir[PATH_MAX];
- char path[PATH_MAX + 64];
- int rc;
-
- rc = llapi_search_mounts(lustre_dir, 0, mntdir, NULL);
- if (rc != 0)
- return -1;
-
- snprintf(path, sizeof(path), "%s/.lustre/fid/"DFID, mntdir, PFID(fid));
- return open(path, flags);
-}
-
-/**
* Take group lock.
*
* \param fd File to lock.
--- /dev/null
+/*
+ * LGPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the GNU Lesser General Public License
+ * (LGPL) version 2.1 or (at your discretion) any later version.
+ * (LGPL) version 2.1 accompanies this distribution, and is available at
+ * http://www.gnu.org/licenses/lgpl-2.1.html
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * LGPL HEADER END
+ */
+/*
+ * lustre/utils/liblustreapi_fid.c
+ *
+ * lustreapi library for FID mapping calls for determining the pathname
+ * of Lustre files from the File IDentifier.
+ *
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2017, Intel Corporation.
+ *
+ * Copyright (c) 2018, 2019, Data Direct Networks
+ */
+
+/* for O_DIRECTORY */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include <libcfs/util/ioctl.h>
+#include <lustre/lustreapi.h>
+#include <linux/lustre/lustre_fid.h>
+#include "lustreapi_internal.h"
+
+/* strip instances of // (DNE striped directory) when copying to reply buffer */
+static int copy_strip_dne_path(const char *src, char *tgt, size_t tgtlen)
+{
+ const char *a;
+ char *b;
+
+ for (a = src, b = tgt; *a != '\0' && b - tgt < tgtlen; a++) {
+ if (*a == '/' && *(a + 1) == '/')
+ continue;
+ *b = *a;
+ b++;
+ }
+ if (b - tgt >= tgtlen) {
+ errno = ERANGE;
+ return -errno;
+ }
+
+ *b = '\0';
+
+ if (tgt[0] == '\0') { /* ROOT path */
+ tgt[0] = '/';
+ tgt[1] = '\0';
+ }
+
+ return 0;
+}
+
+/**
+ * parse a FID from a string into a binary lu_fid
+ *
+ * Only the format of the FID is checked, not whether the numeric value
+ * contains a valid FID sequence or object ID or version. Optional leading
+ * whitespace and '[' from the standard FID format are skipped.
+ *
+ * \param[in] fidstr string to be parsed
+ * \param[out] fid Lustre File IDentifier
+ * \param[out] endptr pointer to first invalid/unused character in @fidstr
+ *
+ * \retval 0 on success
+ * \retval -errno on failure
+ */
+int llapi_fid_parse(const char *fidstr, struct lu_fid *fid, char **endptr)
+{
+ unsigned long long val;
+ bool bracket = false;
+ char *end = (char *)fidstr;
+ int rc = 0;
+
+ if (!fidstr || !fid) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ while (isspace(*fidstr))
+ fidstr++;
+ while (*fidstr == '[') {
+ bracket = true;
+ fidstr++;
+ }
+
+ /* Parse the FID fields individually with strtoull() instead of a
+ * single call to sscanf() so that the character after the FID can
+ * be returned in @endptr, in case the string has more to parse.
+ * If values are present, but too large for the field, continue
+ * parsing to consume the whole FID and return -ERANGE at the end.
+ */
+ errno = 0;
+ val = strtoull(fidstr, &end, 0);
+ if ((val == 0 && errno == EINVAL) || *end != ':') {
+ rc = -EINVAL;
+ goto out;
+ }
+ if (val >= UINT64_MAX)
+ rc = -ERANGE;
+ else
+ fid->f_seq = val;
+
+ fidstr = end + 1; /* skip first ':', checked above */
+ errno = 0;
+ val = strtoull(fidstr, &end, 0);
+ if ((val == 0 && errno == EINVAL) || *end != ':') {
+ rc = -EINVAL;
+ goto out;
+ }
+ if (val > UINT32_MAX)
+ rc = -ERANGE;
+ else
+ fid->f_oid = val;
+
+ fidstr = end + 1; /* skip second ':', checked above */
+ errno = 0;
+ val = strtoull(fidstr, &end, 0);
+ if (val == 0 && errno == EINVAL) {
+ rc = -EINVAL;
+ goto out;
+ }
+ if (val > UINT32_MAX)
+ rc = -ERANGE;
+ else
+ fid->f_ver = val;
+
+ if (bracket && *end == ']')
+ end++;
+out:
+ if (endptr)
+ *endptr = end;
+
+ errno = -rc;
+ return rc;
+}
+
+/* Print mdtname 'name' into 'buf' using 'format'. Add -MDT0000 if needed.
+ * format must have %s%s, buf must be > 16
+ * Eg: if name = "lustre-MDT0000", "lustre", or "lustre-MDT0000_UUID"
+ * then buf = "lustre-MDT0000"
+ */
+static int get_mdtname(char *name, char *format, char *buf)
+{
+ char suffix[] = "-MDT0000";
+ int len = strlen(name);
+
+ if (len > 5 && strncmp(name + len - 5, "_UUID", 5) == 0) {
+ name[len - 5] = '\0';
+ len -= 5;
+ }
+
+ if (len > 8) {
+ if ((len <= 16) && strncmp(name + len - 8, "-MDT", 4) == 0) {
+ suffix[0] = '\0';
+ } else {
+ /* Not enough room to add suffix */
+ llapi_err_noerrno(LLAPI_MSG_ERROR,
+ "Invalid MDT name |%s|", name);
+ return -EINVAL;
+ }
+ }
+
+ return sprintf(buf, format, name, suffix);
+}
+
+/** ioctl on filsystem root, with mdtindex sent as data
+ * \param mdtname path, fsname, or mdtname (lutre-MDT0004)
+ * \param mdtidxp pointer to integer within data to be filled in with the
+ * mdt index (0 if no mdt is specified). NULL won't be filled.
+ */
+int root_ioctl(const char *mdtname, int opc, void *data, int *mdtidxp,
+ int want_error)
+{
+ char fsname[20];
+ char *ptr;
+ int fd, rc;
+ long index;
+
+ /* Take path, fsname, or MDTname. Assume MDT0000 in former cases.
+ * Open root and parse mdt index.
+ */
+ if (mdtname[0] == '/') {
+ index = 0;
+ rc = get_root_path(WANT_FD | want_error, NULL, &fd,
+ (char *)mdtname, -1);
+ } else {
+ if (get_mdtname((char *)mdtname, "%s%s", fsname) < 0)
+ return -EINVAL;
+ ptr = fsname + strlen(fsname) - 8;
+ *ptr = '\0';
+ index = strtol(ptr + 4, NULL, 16);
+ rc = get_root_path(WANT_FD | want_error, fsname, &fd, NULL, -1);
+ }
+ if (rc < 0) {
+ if (want_error)
+ llapi_err_noerrno(LLAPI_MSG_ERROR,
+ "Can't open %s: %d\n", mdtname, rc);
+ return rc;
+ }
+
+ if (mdtidxp)
+ *mdtidxp = index;
+
+ rc = ioctl(fd, opc, data);
+ if (rc == -1)
+ rc = -errno;
+ else
+ rc = 0;
+ close(fd);
+ return rc;
+}
+
+int llapi_fid2path(const char *device, const char *fidstr, char *path,
+ int pathlen, long long *recno, int *linkno)
+{
+ struct lu_fid fid;
+ struct getinfo_fid2path *gf;
+ int rc;
+
+ if (!path || pathlen <= 1) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = llapi_fid_parse(fidstr, &fid, NULL);
+ if (!rc && !fid_is_sane(&fid)) {
+ rc = -EINVAL;
+ goto out;
+ }
+ if (rc) {
+ llapi_err_noerrno(LLAPI_MSG_ERROR,
+ "bad FID format '%s', should be [seq:oid:ver] (e.g. "DFID")\n",
+ fidstr,
+ (unsigned long long)FID_SEQ_NORMAL, 2, 0);
+ goto out;
+ }
+
+ gf = malloc(sizeof(*gf) + pathlen);
+ if (gf == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ gf->gf_fid = fid;
+ if (recno)
+ gf->gf_recno = *recno;
+ if (linkno)
+ gf->gf_linkno = *linkno;
+ gf->gf_pathlen = pathlen;
+
+ /* Take path or fsname */
+ rc = root_ioctl(device, OBD_IOC_FID2PATH, gf, NULL, 0);
+ if (rc)
+ goto out_free;
+
+ rc = copy_strip_dne_path(gf->gf_u.gf_path, path, pathlen);
+
+ if (recno)
+ *recno = gf->gf_recno;
+ if (linkno)
+ *linkno = gf->gf_linkno;
+
+out_free:
+ free(gf);
+out:
+ errno = -rc;
+ return rc;
+}
+
+static int fid_from_lma(const char *path, int fd, struct lu_fid *fid)
+{
+ char buf[512];
+ struct lustre_mdt_attrs *lma;
+ int rc = -1;
+
+ if (fd >= 0)
+ rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf));
+ else if (path)
+ rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf));
+ else
+ errno = EINVAL;
+ if (rc < 0)
+ return -errno;
+
+ lma = (struct lustre_mdt_attrs *)buf;
+ fid_le_to_cpu(fid, &lma->lma_self_fid);
+
+ return 0;
+}
+
+int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid,
+ int *mdt_index)
+{
+ int rc;
+
+ rc = ioctl(fd, LL_IOC_FID2MDTIDX, fid);
+ if (rc < 0)
+ return -errno;
+
+ if (mdt_index)
+ *mdt_index = rc;
+
+ return rc;
+}
+
+int llapi_fd2fid(int fd, struct lu_fid *fid)
+{
+ int rc;
+
+ memset(fid, 0, sizeof(*fid));
+
+ rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0;
+ /* Allow extracting the FID from an ldiskfs-mounted filesystem */
+ if (rc < 0) {
+ if (errno == EINVAL || errno == ENOTTY)
+ rc = fid_from_lma(NULL, fd, fid);
+ else
+ rc = -errno;
+ }
+
+ return rc;
+}
+
+int llapi_path2fid(const char *path, struct lu_fid *fid)
+{
+ int fd, rc;
+
+ fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
+ if (fd >= 0) {
+ rc = llapi_fd2fid(fd, fid);
+ close(fd);
+ } else {
+ memset(fid, 0, sizeof(*fid));
+ rc = -errno;
+ }
+
+ if (rc == -ELOOP || rc == -ENXIO || rc == -EINVAL || rc == -ENOTTY)
+ rc = fid_from_lma(path, -1, fid);
+
+ return rc;
+}
+
+int llapi_fd2parent(int fd, unsigned int linkno, struct lu_fid *parent_fid,
+ char *name, size_t name_size)
+{
+ struct getparent *gp;
+ int rc;
+
+ if (name && name_size <= 1) {
+ errno = EOVERFLOW;
+ return -errno;
+ }
+
+ gp = malloc(sizeof(*gp) + name_size);
+ if (gp == NULL) {
+ errno = ENOMEM;
+ return -errno;
+ }
+
+ gp->gp_linkno = linkno;
+ gp->gp_name_size = name_size;
+
+ rc = ioctl(fd, LL_IOC_GETPARENT, gp);
+ if (rc < 0) {
+ rc = -errno;
+ goto err_free;
+ }
+
+ if (parent_fid)
+ *parent_fid = gp->gp_fid;
+
+ if (name)
+ rc = copy_strip_dne_path(gp->gp_name, name, name_size);
+
+err_free:
+ free(gp);
+ return rc;
+}
+
+int llapi_path2parent(const char *path, unsigned int linkno,
+ struct lu_fid *parent_fid, char *name, size_t name_size)
+{
+ int fd;
+ int rc;
+
+ fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
+ if (fd < 0)
+ return -errno;
+
+ rc = llapi_fd2parent(fd, linkno, parent_fid, name, name_size);
+ close(fd);
+
+ return rc;
+}
+
+/**
+ * Attempt to open a file with Lustre file identifier \a fid
+ * and return an open file descriptor.
+ *
+ * \param[in] lustre_dir path within Lustre filesystem containing \a fid
+ * \param[in] fid Lustre file identifier of file to open
+ * \param[in] flags open() flags
+ *
+ * \retval non-negative file descriptor on successful open
+ * \retval negative errno if an error occurred
+ */
+int llapi_open_by_fid(const char *lustre_dir, const struct lu_fid *fid,
+ int flags)
+{
+ char mntdir[PATH_MAX];
+ char path[PATH_MAX + 64];
+ int rc;
+
+ rc = llapi_search_mounts(lustre_dir, 0, mntdir, NULL);
+ if (rc)
+ return rc;
+
+ snprintf(path, sizeof(path), "%s/.lustre/fid/"DFID, mntdir, PFID(fid));
+ rc = open(path, flags);
+ if (rc < 0)
+ rc = -errno;
+
+ return rc;
+}
}
argc -= optind;
- argv += optind;
+ fidstr = *(argv + optind);
if (!(id != ULLONG_MAX && group != ULLONG_MAX && argc == 0) &&
!(id == ULLONG_MAX && group == ULLONG_MAX && argc == 1))
memset(&data, 0, sizeof data);
data.ioc_dev = cur_device;
if (argc == 1) {
- fidstr = *argv;
- while (*fidstr == '[')
- fidstr++;
- sscanf(fidstr, SFID, RFID(&fid));
+ rc = llapi_fid_parse(fidstr, &fid, NULL);
+ if (rc) {
+ fprintf(stderr, "%s: error parsing FID '%s': %s\n",
+ jt_cmdname(argv[0]), fidstr, strerror(-rc));
+ return rc;
+ }
- data.ioc_inlbuf1 = (char *) &fid;
- data.ioc_inllen1 = sizeof fid;
+ data.ioc_inlbuf1 = (char *)&fid;
+ data.ioc_inllen1 = sizeof(fid);
} else {
- data.ioc_inlbuf3 = (char *) &id;
- data.ioc_inllen3 = sizeof id;
- data.ioc_inlbuf4 = (char *) &group;
- data.ioc_inllen4 = sizeof group;
+ data.ioc_inlbuf3 = (char *)&id;
+ data.ioc_inllen3 = sizeof(id);
+ data.ioc_inlbuf4 = (char *)&group;
+ data.ioc_inllen4 = sizeof(group);
}
data.ioc_inlbuf2 = (char *) &version;
data.ioc_inllen2 = sizeof version;