Whamcloud - gitweb
LU-14612 utils: Add functions llapi_group_lock64/unlock64() 10/43310/8
authorEmoly Liu <emoly@whamcloud.com>
Sun, 25 Apr 2021 00:48:42 +0000 (08:48 +0800)
committerOleg Drokin <green@whamcloud.com>
Wed, 5 May 2021 02:50:35 +0000 (02:50 +0000)
Add new functions llapi_group_lock64/unlock64() for 64-bit usage.

Test-Parameters: trivial
Signed-off-by: Emoly Liu <emoly@whamcloud.com>
Change-Id: Id79ae634ba6a787974be481b51743604c4adb536
Reviewed-on: https://review.whamcloud.com/43310
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Bobi Jam <bobijam@hotmail.com>
Reviewed-by: Wang Shilong <wshilong@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/doc/llapi_group_lock.3
lustre/include/lustre/lustreapi.h
lustre/utils/LCOPYING
lustre/utils/Makefile.am
lustre/utils/liblustreapi.c
lustre/utils/liblustreapi_swap.c [new file with mode: 0644]
lustre/utils/wirehdr.c
lustre/utils/wiretest.c

index 18b529c..6a48384 100644 (file)
@@ -1,37 +1,46 @@
 .TH llapi_group_lock 3 "2014 Oct 03" "Lustre User API"
 .SH NAME
-llapi_group_lock, llapi_group_unlock \- get and put a Lustre group lock.
+llapi_group_lock, llapi_group_unlock, llapi_group_lock64, llapi_group_unlock64 \- get and put a Lustre group lock.
 .SH SYNOPSIS
 .nf
 .B #include <lustre/lustreapi.h>
 .PP
 .BI "int llapi_group_lock(int "fd ", int "gid );
+.BI "int llapi_group_lock64(int "fd ", __u64 "gid );
 
 .BI "int llapi_group_unlock(int "fd ", int "gid );
+.BI "int llapi_group_unlock64(int "fd ", __u64 "gid );
 .fi
 .SH DESCRIPTION
 .PP
-The function
+The functions
 .BR llapi_group_lock()
-takes a group lock on the file descriptor
+and
+.BR llapi_group_lock64()
+take a group lock on the file descriptor
 .I fd
 with group identifier
-.IR gid .
+.IR gid
+(int or __u64 type) .
 
-The function
+The functions
 .BR llapi_group_unlock()
-releases a group lock identified by group identifier
+and
+.BR llapi_group_unlock64()
+release a group lock identified by group identifier
 .I gid
-on the file descriptor
+(int or __u64 type) on the file descriptor
 .IR fd .
 
 The group lock is a whole file lock that blocks concurrent I/O originating from descriptors that have not been locked. Multiple processes can acquire a lock by specifying the same group identifier.
 
 .SH RETURN VALUES
 .LP
-.B llapi_group_lock(\|)
-and
+.B llapi_group_lock(\|),
+.B llapi_group_lock64(\|),
 .B llapi_group_unlock(\|)
+and
+.B llapi_group_unlock64(\|)
 return 0 on success or a negative errno value on failure.
 .SH ERRORS
 .TP 15
index 78a2e44..8beeefc 100644 (file)
@@ -65,6 +65,16 @@ typedef struct statx lstatx_t;
 
 #define lustre_fid struct lu_fid
 
+/*
+ * BUILD_BUG_ON() is Compile-time check which verifies correctness at
+ * compile-time rather than runtime. If "cond" is true, (1 - 2*!!(cond))
+ * will be a negative value, which will cause the compiler to complain.
+ *
+ */
+#ifndef BUILD_BUG_ON
+#define BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2*!!(cond)]))
+#endif
+
 /* Currently external applications can access this but in the
  * future this will no longer be exposed for the user. Instead
  * if you want to know if the library is initialized just call
@@ -609,6 +619,8 @@ int llapi_lease_put(int fd); /* obsoleted */
 /* Group lock */
 int llapi_group_lock(int fd, int gid);
 int llapi_group_unlock(int fd, int gid);
+int llapi_group_lock64(int fd, __u64 gid);
+int llapi_group_unlock64(int fd, __u64 gid);
 
 bool llapi_file_is_sparse(int fd);
 off_t llapi_data_seek(int src_fd, off_t offset, size_t *length);
index 105f1fd..6e12b62 100644 (file)
@@ -6,6 +6,7 @@ lustre/utils/liblustreapi_layout.c
 lustre/utils/liblustreapi_lease.c
 lustre/utils/liblustreapi_nodemap.c
 lustre/utils/liblustreapi_util.c
+lustre/utils/liblustreapi_swap.c
 lustre/utils/lustreapi_internal.h
 -------------------------------------------------------------------------------
                  GNU LESSER GENERAL PUBLIC LICENSE
index 898a36f..a806331 100644 (file)
@@ -104,7 +104,7 @@ liblustreapi_la_SOURCES = liblustreapi.c liblustreapi_hsm.c \
                          liblustreapi_mirror.c liblustreapi_fid.c \
                          liblustreapi_ladvise.c liblustreapi_chlg.c \
                          liblustreapi_heat.c liblustreapi_pcc.c \
-                         liblustreapi_lseek.c
+                         liblustreapi_lseek.c liblustreapi_swap.c
 liblustreapi_la_LDFLAGS = $(LIBREADLINE) -version-info 1:0:0 \
                          -Wl,--version-script=liblustreapi.map
 liblustreapi_la_LIBADD = $(top_builddir)/libcfs/libcfs/libcfs.la
index 40a6ee7..8ffd467 100644 (file)
@@ -5824,39 +5824,6 @@ int llapi_get_connect_flags(const char *mnt, __u64 *flags)
 }
 
 /**
- * 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
@@ -5870,301 +5837,3 @@ int llapi_file_flush(int fd)
        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;
-}
diff --git a/lustre/utils/liblustreapi_swap.c b/lustre/utils/liblustreapi_swap.c
new file mode 100644 (file)
index 0000000..21b4d8d
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * 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
+ */
+/*
+ * Copyright (c) 2012 Commissariat a l'energie atomique et aux energies
+ * alternatives
+ * Copyright (c) 2017, 2021, DDN Storage Corporation.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ */
+/*
+ * lustreapi library for file layout swapping.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <lustre/lustreapi.h>
+
+/**
+ * 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;
+}
+
+/*
+ * 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;
+}
+
+int llapi_group_lock64(int fd, __u64 gid)
+{
+       int rc;
+
+       /* If this is ever compiled on a 32-bit system then a new
+        * LL_IOC_GROUP_LOCK64 will need to be defined that takes
+        * __u64 as an argument.  That may never happen again.
+        */
+       BUILD_BUG_ON(sizeof(long) != sizeof(__u64));
+       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;
+}
+
+int llapi_group_unlock64(int fd, __u64 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;
+}
index cb26f19..a6c27c2 100644 (file)
 
 #define LASSERT(cond) if (!(cond)) { printf("failed " #cond "\n"); ret = 1; }
 #define LASSERTF(cond, fmt, ...) if (!(cond)) { printf("failed '" #cond "'" fmt, ## __VA_ARGS__); ret = 1; }
-/*
- * BUILD_BUG_ON() is Compile-time check which verifies correctness at
- * compile-time rather than runtime. If "cond" is true, then there are two
- * identical cases ("0" and "0"), which is an error that causes the compiler to
- * complain. If "cond" is false, then there are two different cases
- * ("(non-zero)" and "0").
- *
- */
-#ifndef BUILD_BUG_ON
-#define BUILD_BUG_ON(cond) do {switch (0) {case (cond): case 1: break; } } while (0)
-#endif
 
 int ret;
 
index 83e07b6..f04b715 100644 (file)
 #endif /* CONFIG_FS_POSIX_ACL */
 #endif /* HAVE_SERVER_SUPPORT */
 #include <linux/lustre/lustre_cfg.h>
+#include <lustre/lustreapi.h>
 
 #define LASSERT(cond) if (!(cond)) { printf("failed " #cond "\n"); ret = 1; }
 #define LASSERTF(cond, fmt, ...) if (!(cond)) { printf("failed '" #cond "'" fmt, ## __VA_ARGS__); ret = 1; }
-/*
- * BUILD_BUG_ON() is Compile-time check which verifies correctness at
- * compile-time rather than runtime. If "cond" is true, then there are two
- * identical cases ("0" and "0"), which is an error that causes the compiler to
- * complain. If "cond" is false, then there are two different cases
- * ("(non-zero)" and "0").
- *
- */
-#ifndef BUILD_BUG_ON
-#define BUILD_BUG_ON(cond) do {switch (0) {case (cond): case 1: break; } } while (0)
-#endif
 
 int ret;