}
/**
- * Get a 64-bit value representing the version of file data pointed by fd.
- *
- * Each write or truncate, flushed on OST, will change this value. You can use
- * this value to verify if file data was modified. This only checks the file
- * data, not metadata.
- *
- * \param flags 0: no flush pages, usually used it the process has already
- * taken locks;
- * LL_DV_RD_FLUSH: OSTs will take LCK_PR to flush dirty pages
- * from clients;
- * LL_DV_WR_FLUSH: OSTs will take LCK_PW to flush all caching
- * pages from clients.
- *
- * \retval 0 on success.
- * \retval -errno on error.
- */
-int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags)
-{
- int rc;
- struct ioc_data_version idv;
-
- idv.idv_flags = (__u32)flags;
-
- rc = ioctl(fd, LL_IOC_DATA_VERSION, &idv);
- if (rc)
- rc = -errno;
- else
- *data_version = idv.idv_version;
-
- return rc;
-}
-
-/**
* Flush cached pages from all clients.
*
* \param fd File descriptor
return llapi_get_data_version(fd, &dv, LL_DV_WR_FLUSH);
}
-/*
- * Fetch layout version from OST objects. Layout version on OST objects are
- * only set when the file is a mirrored file AND after the file has been
- * written at least once.
- *
- * It actually fetches the least layout version from the objects.
- */
-int llapi_get_ost_layout_version(int fd, __u32 *layout_version)
-{
- int rc;
- struct ioc_data_version idv = { 0 };
-
- rc = ioctl(fd, LL_IOC_DATA_VERSION, &idv);
- if (rc)
- rc = -errno;
- else
- *layout_version = idv.idv_layout_version;
-
- return rc;
-}
-
-/*
- * Create a file without any name and open it for read/write
- *
- * - file is created as if it were a standard file in the given \a directory
- * - file does not appear in \a directory and mtime does not change because
- * the filename is handled specially by the Lustre MDS.
- * - file is destroyed at final close
- *
- * \param[in] directory directory from which to inherit layout/MDT idx
- * \param[in] mdt_idx MDT index on which the file is created,
- * \a idx == -1 means no specific MDT is requested
- * \param[in] mode standard open(2) mode
- * \param[in] stripe_param stripe parameters. May be NULL.
- *
- * \retval a file descriptor on success.
- * \retval -errno on error.
- */
-int llapi_create_volatile_param(const char *directory, int mdt_idx,
- int open_flags, mode_t mode,
- const struct llapi_stripe_param *stripe_param)
-{
- char file_path[PATH_MAX];
- int saved_errno = errno;
- int fd;
- unsigned int rnumber;
- int rc;
-
- do {
- rnumber = random();
- if (mdt_idx == -1)
- rc = snprintf(file_path, sizeof(file_path),
- "%s/" LUSTRE_VOLATILE_HDR "::%.4X",
- directory, rnumber);
- else
- rc = snprintf(file_path, sizeof(file_path),
- "%s/" LUSTRE_VOLATILE_HDR ":%.4X:%.4X",
- directory, mdt_idx, rnumber);
-
- if (rc < 0 || rc >= sizeof(file_path))
- return -ENAMETOOLONG;
-
- /*
- * Either open O_WRONLY or O_RDWR, creating RDONLY
- * is non-sensical here
- */
- if ((open_flags & O_ACCMODE) == O_RDONLY)
- open_flags = O_RDWR | (open_flags & ~O_ACCMODE);
-
- open_flags |= O_CREAT | O_EXCL | O_NOFOLLOW;
-
- if (stripe_param != NULL) {
- fd = llapi_file_open_param(file_path, open_flags,
- mode, stripe_param);
- if (fd < 0)
- rc = fd;
- } else {
- fd = open(file_path, open_flags, mode);
- if (fd < 0)
- rc = -errno;
- }
- } while (fd < 0 && rc == -EEXIST);
-
- if (fd < 0) {
- llapi_error(LLAPI_MSG_ERROR, rc,
- "Cannot create volatile file '%s' in '%s'",
- file_path + strlen(directory) + 1 +
- LUSTRE_VOLATILE_HDR_LEN,
- directory);
- return rc;
- }
-
- /*
- * Unlink file in case this wasn't a Lustre filesystem and the magic
- * volatile filename wasn't handled as intended. The effect is the
- * same. If volatile open was supported then we expect unlink() to
- * return -ENOENT.
- */
- (void)unlink(file_path);
-
- /*
- * Since we are returning successfully we restore errno (and
- * mask out possible EEXIST from open() and ENOENT from unlink().
- */
- errno = saved_errno;
-
- return fd;
-}
-
-/*
- * Create a file without any name open it for read/write
- *
- * - file is created as if it were a standard file in the given \a directory
- * - file does not appear in \a directory and mtime does not change because
- * the filename is handled specially by the Lustre MDS.
- * - file is removed at final close
- * - file modes are rw------- since it doesn't make sense to have a read-only
- * or write-only file that cannot be opened again.
- * - if user wants another mode it must use fchmod() on the open file, no
- * security problems arise because it cannot be opened by another process.
- *
- * \param[in] directory directory from which to inherit layout/MDT idx
- * \param[in] idx MDT index on which the file is created,
- * \a idx == -1 means no specific MDT is requested
- * \param[in] open_flags standard open(2) flags
- *
- * \retval a file descriptor on success.
- * \retval -errno on error.
- */
-int llapi_create_volatile_idx(const char *directory, int mdt_idx,
- int open_flags)
-{
- return llapi_create_volatile_param(directory, mdt_idx, open_flags,
- S_IRUSR | S_IWUSR, NULL);
-}
-
-/**
- * Swap the layouts between 2 file descriptors
- * the 2 files must be open for writing
- * first fd received the ioctl, second fd is passed as arg
- * this is assymetric but avoid use of root path for ioctl
- */
-int llapi_fswap_layouts_grouplock(int fd1, int fd2, __u64 dv1, __u64 dv2,
- int gid, __u64 flags)
-{
- struct lustre_swap_layouts lsl;
- struct stat st1;
- struct stat st2;
- int rc;
-
- if (flags & (SWAP_LAYOUTS_KEEP_ATIME | SWAP_LAYOUTS_KEEP_MTIME)) {
- rc = fstat(fd1, &st1);
- if (rc < 0)
- return -errno;
-
- rc = fstat(fd2, &st2);
- if (rc < 0)
- return -errno;
- }
- lsl.sl_fd = fd2;
- lsl.sl_flags = flags;
- lsl.sl_gid = gid;
- lsl.sl_dv1 = dv1;
- lsl.sl_dv2 = dv2;
- rc = ioctl(fd1, LL_IOC_LOV_SWAP_LAYOUTS, &lsl);
- if (rc < 0)
- return -errno;
-
- if (flags & (SWAP_LAYOUTS_KEEP_ATIME | SWAP_LAYOUTS_KEEP_MTIME)) {
- struct timeval tv1[2];
- struct timeval tv2[2];
-
- memset(tv1, 0, sizeof(tv1));
- memset(tv2, 0, sizeof(tv2));
-
- if (flags & SWAP_LAYOUTS_KEEP_ATIME) {
- tv1[0].tv_sec = st1.st_atime;
- tv2[0].tv_sec = st2.st_atime;
- } else {
- tv1[0].tv_sec = st2.st_atime;
- tv2[0].tv_sec = st1.st_atime;
- }
-
- if (flags & SWAP_LAYOUTS_KEEP_MTIME) {
- tv1[1].tv_sec = st1.st_mtime;
- tv2[1].tv_sec = st2.st_mtime;
- } else {
- tv1[1].tv_sec = st2.st_mtime;
- tv2[1].tv_sec = st1.st_mtime;
- }
-
- rc = futimes(fd1, tv1);
- if (rc < 0)
- return -errno;
-
- rc = futimes(fd2, tv2);
- if (rc < 0)
- return -errno;
- }
-
- return 0;
-}
-
-int llapi_fswap_layouts(int fd1, int fd2, __u64 dv1, __u64 dv2, __u64 flags)
-{
- int rc;
- int grp_id;
-
- do
- grp_id = random();
- while (grp_id == 0);
-
- rc = llapi_fswap_layouts_grouplock(fd1, fd2, dv1, dv2, grp_id, flags);
- if (rc < 0)
- return rc;
-
- return 0;
-}
-
-/**
- * Swap the layouts between 2 files
- * the 2 files are open in write
- */
-int llapi_swap_layouts(const char *path1, const char *path2,
- __u64 dv1, __u64 dv2, __u64 flags)
-{
- int fd1, fd2, rc;
-
- fd1 = open(path1, O_WRONLY | O_LOV_DELAY_CREATE);
- if (fd1 < 0) {
- rc = -errno;
- llapi_error(LLAPI_MSG_ERROR, rc,
- "error: cannot open '%s' for write", path1);
- goto out;
- }
-
- fd2 = open(path2, O_WRONLY | O_LOV_DELAY_CREATE);
- if (fd2 < 0) {
- rc = -errno;
- llapi_error(LLAPI_MSG_ERROR, rc,
- "error: cannot open '%s' for write", path2);
- goto out_close;
- }
-
- rc = llapi_fswap_layouts(fd1, fd2, dv1, dv2, flags);
- if (rc < 0)
- llapi_error(LLAPI_MSG_ERROR, rc,
- "error: cannot swap layout between '%s' and '%s'",
- path1, path2);
-
- close(fd2);
-out_close:
- close(fd1);
-out:
- return rc;
-}
-
-/**
- * Take group lock.
- *
- * \param fd File to lock.
- * \param gid Group Identifier.
- *
- * \retval 0 on success.
- * \retval -errno on failure.
- */
-int llapi_group_lock(int fd, int gid)
-{
- int rc;
-
- rc = ioctl(fd, LL_IOC_GROUP_LOCK, gid);
- if (rc < 0) {
- rc = -errno;
- llapi_error(LLAPI_MSG_ERROR, rc, "cannot get group lock");
- }
- return rc;
-}
-
-/**
- * Put group lock.
- *
- * \param fd File to unlock.
- * \param gid Group Identifier.
- *
- * \retval 0 on success.
- * \retval -errno on failure.
- */
-int llapi_group_unlock(int fd, int gid)
-{
- int rc;
-
- rc = ioctl(fd, LL_IOC_GROUP_UNLOCK, gid);
- if (rc < 0) {
- rc = -errno;
- llapi_error(LLAPI_MSG_ERROR, rc, "cannot put group lock");
- }
- return rc;
-}