Whamcloud - gitweb
LU-14583 llapi: handle symlinks in llapi_file_get_stripe()
[fs/lustre-release.git] / lustre / utils / liblustreapi.c
index 60fd7ea..14263ac 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/utils/liblustreapi.c
  *
 static int llapi_msg_level = LLAPI_MSG_MAX;
 const char *liblustreapi_cmd;
 
-char *mdt_hash_name[] = { "none",
-                         LMV_HASH_NAME_ALL_CHARS,
-                         LMV_HASH_NAME_FNV_1A_64,
-                         LMV_HASH_NAME_CRUSH,
-};
-
 struct lustre_foreign_type lu_foreign_types[] = {
        {.lft_type = LU_FOREIGN_TYPE_NONE, .lft_name = "none"},
        {.lft_type = LU_FOREIGN_TYPE_SYMLINK, .lft_name = "symlink"},
@@ -969,6 +962,8 @@ static inline void param2lmu(struct lmv_user_md *lmu,
        lmu->lum_stripe_count = param->lsp_stripe_count;
        lmu->lum_stripe_offset = param->lsp_stripe_offset;
        lmu->lum_hash_type = param->lsp_stripe_pattern;
+       lmu->lum_max_inherit = param->lsp_max_inherit;
+       lmu->lum_max_inherit_rr = param->lsp_max_inherit_rr;
        if (param->lsp_pool != NULL)
                strncpy(lmu->lum_pool_name, param->lsp_pool, LOV_MAXPOOLNAME);
        if (param->lsp_is_specific) {
@@ -1093,6 +1088,9 @@ int llapi_dir_create(const char *name, mode_t mode,
        data.ioc_inlbuf2 = (char *)lmu;
        data.ioc_inllen2 = lmu_size;
        data.ioc_type = mode;
+       if (param->lsp_is_create)
+               /* borrow obdo1.o_flags to store this flag */
+               data.ioc_obdo1.o_flags = OBD_FL_OBDMDEXISTS;
        rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
        if (rc) {
                llapi_error(LLAPI_MSG_ERROR, rc,
@@ -2317,23 +2315,29 @@ out:
 
 int llapi_file_fget_lov_uuid(int fd, struct obd_uuid *lov_name)
 {
-       int rc = ioctl(fd, OBD_IOC_GETNAME, lov_name);
+       int rc;
 
+       rc = ioctl(fd, OBD_IOC_GETDTNAME, lov_name);
+       if (rc && errno == ENOTTY)
+               rc = ioctl(fd, OBD_IOC_GETNAME_OLD, lov_name);
        if (rc) {
                rc = -errno;
                llapi_error(LLAPI_MSG_ERROR, rc, "cannot get lov name");
        }
+
        return rc;
 }
 
 int llapi_file_fget_lmv_uuid(int fd, struct obd_uuid *lov_name)
 {
-       int rc = ioctl(fd, OBD_IOC_GETMDNAME, lov_name);
+       int rc;
 
+       rc = ioctl(fd, OBD_IOC_GETMDNAME, lov_name);
        if (rc) {
                rc = -errno;
                llapi_error(LLAPI_MSG_ERROR, rc, "error: can't get lmv name.");
        }
+
        return rc;
 }
 
@@ -3173,7 +3177,7 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name,
                llapi_printf(LLAPI_MSG_NORMAL, "%s", separator);
                if (verbose & ~VERBOSE_STRIPE_COUNT)
                        llapi_printf(LLAPI_MSG_NORMAL, "lmv_stripe_count: ");
-               llapi_printf(LLAPI_MSG_NORMAL, "%u",
+               llapi_printf(LLAPI_MSG_NORMAL, "%d",
                             (int)lum->lum_stripe_count);
                if ((verbose & VERBOSE_STRIPE_OFFSET) && !yaml)
                        separator = " ";
@@ -3213,9 +3217,50 @@ void lmv_dump_user_lmm(struct lmv_user_md *lum, char *pool_name,
                if (flags & LMV_HASH_FLAG_LOST_LMV)
                        llapi_printf(LLAPI_MSG_NORMAL, ",lost_lmv");
 
-               separator = "\n";
+               if (verbose & VERBOSE_HASH_TYPE && !yaml)
+                       separator = " ";
+               else
+                       separator = "\n";
        }
 
+       if ((verbose & VERBOSE_INHERIT) && lum->lum_magic == LMV_USER_MAGIC) {
+               llapi_printf(LLAPI_MSG_NORMAL, "%s", separator);
+               if (verbose & ~VERBOSE_INHERIT)
+                       llapi_printf(LLAPI_MSG_NORMAL, "lmv_max_inherit: ");
+               if (lum->lum_max_inherit == LMV_INHERIT_UNLIMITED)
+                       llapi_printf(LLAPI_MSG_NORMAL, "-1");
+               else if (lum->lum_max_inherit == LMV_INHERIT_NONE)
+                       llapi_printf(LLAPI_MSG_NORMAL, "0");
+               else
+                       llapi_printf(LLAPI_MSG_NORMAL, "%hhu",
+                                    lum->lum_max_inherit);
+               if (verbose & VERBOSE_INHERIT && !yaml)
+                       separator = " ";
+               else
+                       separator = "\n";
+       }
+
+       if ((verbose & VERBOSE_INHERIT_RR) &&
+           lum->lum_magic == LMV_USER_MAGIC &&
+           lum->lum_stripe_offset == LMV_OFFSET_DEFAULT) {
+               llapi_printf(LLAPI_MSG_NORMAL, "%s", separator);
+               if (verbose & ~VERBOSE_INHERIT_RR)
+                       llapi_printf(LLAPI_MSG_NORMAL, "lmv_max_inherit_rr: ");
+               if (lum->lum_max_inherit_rr == LMV_INHERIT_RR_UNLIMITED)
+                       llapi_printf(LLAPI_MSG_NORMAL, "-1");
+               else if (lum->lum_max_inherit_rr == LMV_INHERIT_RR_NONE)
+                       llapi_printf(LLAPI_MSG_NORMAL, "0");
+               else
+                       llapi_printf(LLAPI_MSG_NORMAL, "%hhu",
+                                    lum->lum_max_inherit_rr);
+               if (verbose & VERBOSE_INHERIT_RR && !yaml)
+                       separator = " ";
+               else
+                       separator = "\n";
+       }
+
+       separator = "\n";
+
        if (verbose & VERBOSE_OBJID && lum->lum_magic != LMV_USER_MAGIC) {
                llapi_printf(LLAPI_MSG_NORMAL, "%s", separator);
                if (lum->lum_stripe_count > 0)
@@ -4006,7 +4051,7 @@ static void llapi_lov_dump_user_lmm(struct find_param *param, char *path,
        }
 }
 
-int llapi_file_get_stripe(const char *path, struct lov_user_md *lum)
+static int llapi_file_get_stripe1(const char *path, struct lov_user_md *lum)
 {
        const char *fname;
        char *dname;
@@ -4048,6 +4093,31 @@ out_free:
        return rc;
 }
 
+int llapi_file_get_stripe(const char *path, struct lov_user_md *lum)
+{
+       char *canon_path = NULL;
+       int rc, rc2;
+
+       rc = llapi_file_get_stripe1(path, lum);
+       if (!(rc == -ENOTTY || rc == -ENODATA))
+               goto out;
+
+       /* Handle failure due to symlinks by dereferencing path manually. */
+       canon_path = canonicalize_file_name(path);
+       if (canon_path == NULL)
+               goto out; /* Keep original rc. */
+
+       rc2 = llapi_file_get_stripe1(canon_path, lum);
+       if (rc2 < 0)
+               goto out; /* Keep original rc. */
+
+       rc = 0;
+out:
+       free(canon_path);
+
+       return rc;
+}
+
 int llapi_file_lookup(int dirfd, const char *name)
 {
        struct obd_ioctl_data data = { 0 };
@@ -4751,7 +4821,8 @@ static int cb_find_init(char *path, int p, int *dp,
            param->fp_atime || param->fp_mtime || param->fp_ctime ||
            param->fp_check_size || param->fp_check_blocks ||
            find_check_lmm_info(param) ||
-           param->fp_check_mdt_count || param->fp_check_hash_type)
+           param->fp_check_mdt_count || param->fp_hash_type ||
+           param->fp_check_hash_flag)
                decision = 0;
 
        if (param->fp_type != 0 && checked_type == 0)
@@ -4759,7 +4830,8 @@ static int cb_find_init(char *path, int p, int *dp,
 
        if (decision == 0) {
                if (d != -1 && (param->fp_check_mdt_count ||
-                   param->fp_check_hash_type || param->fp_check_foreign)) {
+                   param->fp_hash_type || param->fp_check_foreign ||
+                   param->fp_check_hash_flag)) {
                        param->fp_get_lmv = 1;
                        ret = cb_get_dirstripe(path, &d, param);
                        if (ret != 0) {
@@ -4923,15 +4995,17 @@ static int cb_find_init(char *path, int p, int *dp,
                        goto decided;
        }
 
-       if (param->fp_check_hash_type) {
+       if (param->fp_hash_type) {
                __u32 found;
+               __u32 type = param->fp_lmv_md->lum_hash_type &
+                            LMV_HASH_TYPE_MASK;
 
                if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) {
                        decision = -1;
                        goto decided;
                }
 
-               found = param->fp_lmv_md->lum_hash_type & param->fp_hash_type;
+               found = (1 << type) & param->fp_hash_type;
                if ((found && param->fp_exclude_hash_type) ||
                    (!found && !param->fp_exclude_hash_type)) {
                        decision = -1;
@@ -4939,6 +5013,22 @@ static int cb_find_init(char *path, int p, int *dp,
                }
        }
 
+       if (param->fp_check_hash_flag) {
+               __u32 flags = param->fp_lmv_md->lum_hash_type &
+                             ~LMV_HASH_TYPE_MASK;
+
+               if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) {
+                       decision = -1;
+                       goto decided;
+               }
+
+               if (!(flags & param->fp_hash_inflags) ||
+                    (flags & param->fp_hash_exflags)) {
+                       decision = -1;
+                       goto decided;
+               }
+       }
+
        /* If an OBD UUID is specified but none matches, skip this file. */
        if ((param->fp_obd_uuid && param->fp_obd_index == OBD_NOT_FOUND) ||
            (param->fp_mdt_uuid && param->fp_mdt_index == OBD_NOT_FOUND))
@@ -5802,39 +5892,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
@@ -5848,301 +5905,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;
-}