4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the GNU Lesser General Public License
8 * (LGPL) version 2.1 or (at your discretion) any later version.
9 * (LGPL) version 2.1 accompanies this distribution, and is available at
10 * http://www.gnu.org/licenses/lgpl-2.1.html
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
20 * lustre/utils/liblustreapi_fid.c
22 * lustreapi library for FID mapping calls for determining the pathname
23 * of Lustre files from the File IDentifier.
25 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Use is subject to license terms.
28 * Copyright (c) 2011, 2017, Intel Corporation.
30 * Copyright (c) 2018, 2019, Data Direct Networks
33 /* for O_DIRECTORY and struct file_handle */
43 #include <sys/ioctl.h>
44 #include <sys/xattr.h>
48 #include <libcfs/util/ioctl.h>
49 #include <libcfs/util/hash.h>
50 #include <lustre/lustreapi.h>
51 #include <linux/lustre/lustre_fid.h>
52 #include "lustreapi_internal.h"
54 /* strip instances of // (DNE striped directory) when copying to reply buffer */
55 static int copy_strip_dne_path(const char *src, char *tgt, size_t tgtlen)
60 for (a = src, b = tgt; *a != '\0' && b - tgt < tgtlen; a++) {
61 if (*a == '/' && *(a + 1) == '/')
66 if (b - tgt >= tgtlen) {
73 if (tgt[0] == '\0') { /* ROOT path */
82 * parse a FID from a string into a binary lu_fid
84 * Only the format of the FID is checked, not whether the numeric value
85 * contains a valid FID sequence or object ID or version. Optional leading
86 * whitespace and '[' from the standard FID format are skipped.
88 * \param[in] fidstr string to be parsed
89 * \param[out] fid Lustre File IDentifier
90 * \param[out] endptr pointer to first invalid/unused character in @fidstr
92 * \retval 0 on success
93 * \retval -errno on failure
95 int llapi_fid_parse(const char *fidstr, struct lu_fid *fid, char **endptr)
97 unsigned long long val;
99 char *end = (char *)fidstr;
102 if (!fidstr || !fid) {
107 while (isspace(*fidstr))
109 while (*fidstr == '[') {
114 /* Parse the FID fields individually with strtoull() instead of a
115 * single call to sscanf() so that the character after the FID can
116 * be returned in @endptr, in case the string has more to parse.
117 * If values are present, but too large for the field, continue
118 * parsing to consume the whole FID and return -ERANGE at the end.
121 val = strtoull(fidstr, &end, 0);
122 if ((val == 0 && errno == EINVAL) || *end != ':') {
126 if (val >= UINT64_MAX)
131 fidstr = end + 1; /* skip first ':', checked above */
133 val = strtoull(fidstr, &end, 0);
134 if ((val == 0 && errno == EINVAL) || *end != ':') {
138 if (val > UINT32_MAX)
143 fidstr = end + 1; /* skip second ':', checked above */
145 val = strtoull(fidstr, &end, 0);
146 if (val == 0 && errno == EINVAL) {
150 if (val > UINT32_MAX)
155 if (bracket && *end == ']')
165 static inline char *get_gf_path(struct getinfo_fid2path *gf)
167 #ifndef HAVE_FID2PATH_ANON_UNIONS
168 return gf->gf_u.gf_path;
174 int llapi_fid2path_at(int mnt_fd, const struct lu_fid *fid,
175 char *path_buf, int path_buf_size,
176 long long *recno, int *linkno)
178 struct getinfo_fid2path *gf = NULL;
181 gf = calloc(1, sizeof(*gf) + path_buf_size);
189 gf->gf_recno = *recno;
192 gf->gf_linkno = *linkno;
194 gf->gf_pathlen = path_buf_size;
196 rc = ioctl(mnt_fd, OBD_IOC_FID2PATH, gf);
202 rc = copy_strip_dne_path(get_gf_path(gf), path_buf, path_buf_size);
205 *recno = gf->gf_recno;
208 *linkno = gf->gf_linkno;
215 int llapi_fid2path(const char *path_or_device, const char *fidstr, char *path,
216 int pathlen, long long *recno, int *linkno)
222 if (path_or_device == NULL || *path_or_device == '\0') {
227 rc = llapi_fid_parse(fidstr, &fid, NULL);
229 llapi_err_noerrno(LLAPI_MSG_ERROR,
230 "bad FID format '%s', should be [seq:oid:ver] (e.g. "DFID")\n",
232 (unsigned long long)FID_SEQ_NORMAL, 2, 0);
236 if (path_or_device[0] == '/')
237 rc = get_root_path(WANT_FD, NULL, &mnt_fd,
238 (char *)path_or_device, -1, NULL, NULL);
240 rc = get_root_path(WANT_FD, (char *)path_or_device,
241 &mnt_fd, NULL, -1, NULL, NULL);
246 /* mnt_fd is cached internally, no need to close it */
247 rc = llapi_fid2path_at(mnt_fd, &fid, path, pathlen, recno, linkno);
253 int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid,
258 rc = ioctl(fd, LL_IOC_FID2MDTIDX, fid);
268 static int fid_from_lma(const char *path, int fd, struct lu_fid *fid)
270 #ifdef HAVE_SERVER_SUPPORT
271 struct lustre_mdt_attrs *lma;
276 rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf));
278 rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf));
282 lma = (struct lustre_mdt_attrs *)buf;
283 memcpy(fid, &lma->lma_self_fid, sizeof(lma->lma_self_fid));
290 int llapi_fd2fid(int fd, struct lu_fid *fid)
292 const struct lustre_file_handle *data;
293 struct file_handle *handle;
294 char buffer[sizeof(*handle) + MAX_HANDLE_SZ];
297 memset(fid, 0, sizeof(*fid));
299 /* A lustre file handle should always fit in a 128 bytes long buffer
300 * (which is the value of MAX_HANDLE_SZ at the time this is written)
302 handle = (struct file_handle *)buffer;
303 handle->handle_bytes = MAX_HANDLE_SZ;
305 if (name_to_handle_at(fd, "", handle, &mount_id, AT_EMPTY_PATH)) {
306 if (errno == EOVERFLOW)
307 /* A Lustre file_handle would have fit */
312 if (handle->handle_type != FILEID_LUSTRE)
313 /* Might be a locally mounted Lustre target */
314 return fid_from_lma(NULL, fd, fid);
315 if (handle->handle_bytes < sizeof(*fid))
316 /* Unexpected error try and recover */
317 return fid_from_lma(NULL, fd, fid);
319 /* Parse the FID out of the handle */
320 data = (const struct lustre_file_handle *)handle->f_handle;
321 memcpy(fid, &data->lfh_child, sizeof(data->lfh_child));
326 int llapi_path2fid(const char *path, struct lu_fid *fid)
330 fd = open(path, O_RDONLY | O_PATH | O_CLOEXEC | O_NOFOLLOW);
334 rc = llapi_fd2fid(fd, fid);
338 /* Might be a locally mounted Lustre target
340 * Cannot use `fd' as fgetxattr() does not work on file
341 * descriptor opened with O_PATH
343 rc = fid_from_lma(path, -1, fid);
348 int llapi_fd2parent(int fd, unsigned int linkno, struct lu_fid *parent_fid,
349 char *name, size_t name_size)
351 struct getparent *gp;
354 if (name && name_size <= 1) {
359 gp = malloc(sizeof(*gp) + name_size);
365 gp->gp_linkno = linkno;
366 gp->gp_name_size = name_size;
368 rc = ioctl(fd, LL_IOC_GETPARENT, gp);
375 *parent_fid = gp->gp_fid;
378 rc = copy_strip_dne_path(gp->gp_name, name, name_size);
385 int llapi_path2parent(const char *path, unsigned int linkno,
386 struct lu_fid *parent_fid, char *name, size_t name_size)
391 fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
395 rc = llapi_fd2parent(fd, linkno, parent_fid, name, name_size);
402 * Convert a struct lu_fid into a struct file_handle
404 * \param[out] _handle a newly allocated struct file_handle on success
405 * \param[in] fid a Lustre File IDentifier
407 * \retval 0 on success
408 * \retval negative errno if an error occured
410 * On success, the caller is responsible for freeing \p handle.
412 int llapi_fid_to_handle(struct file_handle **_handle, const struct lu_fid *fid)
414 struct lustre_file_handle *lfh;
415 struct file_handle *handle;
417 if (!_handle || !fid)
420 handle = calloc(1, sizeof(*handle) + sizeof(*lfh));
424 handle->handle_bytes = sizeof(*lfh);
425 handle->handle_type = FILEID_LUSTRE;
426 lfh = (struct lustre_file_handle *)handle->f_handle;
427 /* Only lfh->lfh_child needs to be set */
428 lfh->lfh_child = *fid;
435 * Attempt to open a file with a Lustre File IDentifier
437 * \param[in] lustre_fd an open file descriptor for an object in lustre
438 * \param[in] fid a Lustre File IDentifier of the file to open
439 * \param[in] flags open(2) flags
441 * \retval non-negative file descriptor on success
442 * \retval negative errno if an error occured
444 int llapi_open_by_fid_at(int lustre_fd, const struct lu_fid *fid, int flags)
446 struct file_handle *handle;
450 rc = llapi_fid_to_handle(&handle, fid);
454 /* Sadly open_by_handle_at() only works for root, but this is also the
455 * case for the original approach of opening $MOUNT/.lustre/FID.
457 fd = open_by_handle_at(lustre_fd, handle, flags);
461 return fd < 0 ? rc : fd;
465 * Attempt to open a file with Lustre file identifier \a fid
466 * and return an open file descriptor.
468 * \param[in] lustre_dir path within Lustre filesystem containing \a fid
469 * \param[in] fid Lustre file identifier of file to open
470 * \param[in] flags open() flags
472 * \retval non-negative file descriptor on successful open
473 * \retval negative errno if an error occurred
475 int llapi_open_by_fid(const char *lustre_dir, const struct lu_fid *fid,
480 /* this will return a cached FD if available, so only one open needed.
481 * WANT_FD doesn't modify lustre_dir so casting away "const" is OK */
482 rc = get_root_path(WANT_FD, NULL, &mnt_fd, (char *)lustre_dir, 0, NULL,
487 /* "mnt_fd" is cached internally for reuse, no need to close it */
488 rc = llapi_open_by_fid_at(mnt_fd, fid, flags);
493 unsigned long llapi_fid_hash(const struct lu_fid *f, unsigned int shift)
495 return hash_long(fid_flatten_long(f), shift);