* Copyright (c) 2018, 2019, Data Direct Networks
*/
-/* for O_DIRECTORY */
+/* for O_DIRECTORY and struct file_handle */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <sys/ioctl.h>
#include <sys/xattr.h>
#include <unistd.h>
+#include <sched.h>
#include <libcfs/util/ioctl.h>
+#include <libcfs/util/hash.h>
#include <lustre/lustreapi.h>
#include <linux/lustre/lustre_fid.h>
#include "lustreapi_internal.h"
return rc;
}
-int llapi_fid2path(const char *path_or_device, const char *fidstr, char *path,
- int pathlen, long long *recno, int *linkno)
+static inline char *get_gf_path(struct getinfo_fid2path *gf)
+{
+#ifndef HAVE_FID2PATH_ANON_UNIONS
+ return gf->gf_u.gf_path;
+#else
+ return gf->gf_path;
+#endif
+}
+
+int llapi_fid2path_at(int mnt_fd, const struct lu_fid *fid,
+ char *path_buf, int path_buf_size,
+ long long *recno, int *linkno)
{
- struct lu_fid fid;
struct getinfo_fid2path *gf = NULL;
- int mnt_fd = -1;
int rc;
- if (path_or_device == NULL || *path_or_device == '\0') {
- rc = -EINVAL;
- goto out;
- }
-
- if (*path_or_device == '/')
- rc = get_root_path(WANT_FD, NULL, &mnt_fd,
- (char *)path_or_device, -1);
- else
- rc = get_root_path(WANT_FD, (char *)path_or_device,
- &mnt_fd, NULL, -1);
-
- if (rc < 0)
- goto out;
-
- rc = llapi_fid_parse(fidstr, &fid, NULL);
- if (rc < 0) {
- 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 = calloc(1, sizeof(*gf) + pathlen);
+ gf = calloc(1, sizeof(*gf) + path_buf_size);
if (gf == NULL) {
rc = -ENOMEM;
goto out;
}
- gf->gf_fid = fid;
- if (recno)
+ gf->gf_fid = *fid;
+ if (recno != NULL)
gf->gf_recno = *recno;
- if (linkno)
+
+ if (linkno != NULL)
gf->gf_linkno = *linkno;
- gf->gf_pathlen = pathlen;
+
+ gf->gf_pathlen = path_buf_size;
rc = ioctl(mnt_fd, OBD_IOC_FID2PATH, gf);
- if (rc < 0) {
+ if (rc) {
rc = -errno;
goto out;
}
- rc = copy_strip_dne_path(gf->gf_u.gf_path, path, pathlen);
+ rc = copy_strip_dne_path(get_gf_path(gf), path_buf, path_buf_size);
- if (recno)
+ if (recno != NULL)
*recno = gf->gf_recno;
- if (linkno)
+ if (linkno != NULL)
*linkno = gf->gf_linkno;
-
out:
- if (!(mnt_fd < 0))
- close(mnt_fd);
-
free(gf);
- errno = -rc;
+ return rc;
+}
+
+int llapi_fid2path(const char *path_or_device, const char *fidstr, char *path,
+ int pathlen, long long *recno, int *linkno)
+{
+ struct lu_fid fid;
+ int mnt_fd = -1;
+ int rc;
+
+ if (path_or_device == NULL || *path_or_device == '\0') {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ rc = llapi_fid_parse(fidstr, &fid, NULL);
+ if (rc < 0) {
+ 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;
+ }
+ rc = llapi_root_path_open(path_or_device, &mnt_fd);
+ if (rc < 0)
+ goto out;
+
+ /* mnt_fd is cached internally, no need to close it */
+ rc = llapi_fid2path_at(mnt_fd, &fid, path, pathlen, recno, linkno);
+ close(mnt_fd);
+
+out:
return rc;
}
static int fid_from_lma(const char *path, int fd, struct lu_fid *fid)
{
+#ifdef HAVE_SERVER_SUPPORT
struct lustre_mdt_attrs *lma;
char buf[512];
int rc = -1;
lma = (struct lustre_mdt_attrs *)buf;
memcpy(fid, &lma->lma_self_fid, sizeof(lma->lma_self_fid));
return 0;
+#else
+ return -ENOTSUP;
+#endif
}
int llapi_fd2fid(int fd, struct lu_fid *fid)
}
/**
+ * Convert a struct lu_fid into a struct file_handle
+ *
+ * \param[out] _handle a newly allocated struct file_handle on success
+ * \param[in] fid a Lustre File IDentifier
+ *
+ * \retval 0 on success
+ * \retval negative errno if an error occured
+ *
+ * On success, the caller is responsible for freeing \p handle.
+ */
+int llapi_fid_to_handle(struct file_handle **_handle, const struct lu_fid *fid)
+{
+ struct lustre_file_handle *lfh;
+ struct file_handle *handle;
+
+ if (!_handle || !fid)
+ return -EINVAL;
+
+ handle = calloc(1, sizeof(*handle) + sizeof(*lfh));
+ if (handle == NULL)
+ return -errno;
+
+ handle->handle_bytes = sizeof(*lfh);
+ handle->handle_type = FILEID_LUSTRE;
+ lfh = (struct lustre_file_handle *)handle->f_handle;
+ /* Only lfh->lfh_child needs to be set */
+ lfh->lfh_child = *fid;
+
+ *_handle = handle;
+ return 0;
+}
+
+/**
+ * Attempt to open a file with a Lustre File IDentifier
+ *
+ * \param[in] lustre_fd an open file descriptor for an object in lustre
+ * \param[in] fid a Lustre File IDentifier of the file to open
+ * \param[in] flags open(2) flags
+ *
+ * \retval non-negative file descriptor on success
+ * \retval negative errno if an error occured
+ */
+int llapi_open_by_fid_at(int lustre_fd, const struct lu_fid *fid, int flags)
+{
+ struct file_handle *handle = NULL;
+ int fd;
+ int rc;
+
+ rc = llapi_fid_to_handle(&handle, fid);
+ if (rc < 0)
+ return rc;
+
+ /* Sadly open_by_handle_at() only works for root, but this is also the
+ * case for the original approach of opening $MOUNT/.lustre/FID.
+ */
+ fd = open_by_handle_at(lustre_fd, handle, flags);
+ rc = -errno;
+ free(handle);
+
+ return fd < 0 ? rc : fd;
+}
+
+/**
* Attempt to open a file with Lustre file identifier \a fid
* and return an open file descriptor.
*
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;
+ int mnt_fd, rc;
- rc = llapi_search_mounts(lustre_dir, 0, mntdir, NULL);
+ rc = llapi_root_path_open(lustre_dir, &mnt_fd);
if (rc)
- return rc;
-
- snprintf(path, sizeof(path), "%s/.lustre/fid/"DFID, mntdir, PFID(fid));
- rc = open(path, flags);
- if (rc < 0)
- rc = -errno;
+ goto out;
+ rc = llapi_open_by_fid_at(mnt_fd, fid, flags);
+ close(mnt_fd);
+out:
return rc;
}
+
+unsigned long llapi_fid_hash(const struct lu_fid *f, unsigned int shift)
+{
+ return hash_long(fid_flatten_long(f), shift);
+}