Whamcloud - gitweb
LU-10830 utils: fix create mode for lfs setstripe
[fs/lustre-release.git] / lustre / utils / liblustreapi_layout.c
index ae5a074..e85b39d 100644 (file)
@@ -23,7 +23,7 @@
  * Lustre files while hiding details of the internal data structures
  * from the user.
  *
- * Copyright (c) 2016, Intel Corporation.
+ * Copyright (c) 2016, 2017, Intel Corporation.
  *
  * Author: Ned Bass <bass6@llnl.gov>
  */
@@ -34,6 +34,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <limits.h>
+#include <assert.h>
 #include <sys/xattr.h>
 #include <sys/param.h>
 
@@ -1430,7 +1431,7 @@ int llapi_layout_pool_name_set(struct llapi_layout *layout,
  *
  * \param[in] path             name of the file to open
  * \param[in] open_flags       open() flags
- * \param[in] mode             permissions to create new file with
+ * \param[in] mode             permissions to create file, filtered by umask
  * \param[in] layout           layout to create new file with
  *
  * \retval             non-negative file descriptor on successful open
@@ -1538,6 +1539,32 @@ int llapi_layout_flags_set(struct llapi_layout *layout, uint32_t flags)
        return 0;
 }
 
+const char *llapi_layout_flags_string(uint32_t flags)
+{
+       switch (flags & LCM_FL_FLR_MASK) {
+       case LCM_FL_RDONLY:
+               return "ro";
+       case LCM_FL_WRITE_PENDING:
+               return "wp";
+       case LCM_FL_SYNC_PENDING:
+               return "sp";
+       }
+
+       return "0";
+}
+
+const __u16 llapi_layout_string_flags(char *string)
+{
+       if (strncmp(string, "ro", strlen(string)) == 0)
+               return LCM_FL_RDONLY;
+       if (strncmp(string, "wp", strlen(string)) == 0)
+               return LCM_FL_WRITE_PENDING;
+       if (strncmp(string, "sp", strlen(string)) == 0)
+               return LCM_FL_SYNC_PENDING;
+
+       return 0;
+}
+
 /**
  * llapi_layout_mirror_count_is_valid() - Check the validity of mirror count.
  * @count: Mirror count value to be checked.
@@ -1660,7 +1687,7 @@ int llapi_layout_comp_extent_set(struct llapi_layout *layout,
        if (comp->llc_list.prev != &layout->llot_comp_list) {
                prev = list_entry(comp->llc_list.prev, typeof(*prev),
                                  llc_list);
-               if (start != prev->llc_extent.e_end) {
+               if (start != 0 && start != prev->llc_extent.e_end) {
                        errno = EINVAL;
                        return -1;
                }
@@ -1669,7 +1696,8 @@ int llapi_layout_comp_extent_set(struct llapi_layout *layout,
        if (comp->llc_list.next != &layout->llot_comp_list) {
                next = list_entry(comp->llc_list.next, typeof(*next),
                                  llc_list);
-               if (end != next->llc_extent.e_start) {
+               if (next->llc_extent.e_start != 0 &&
+                   end != next->llc_extent.e_start) {
                        errno = EINVAL;
                        return -1;
                }
@@ -1848,6 +1876,37 @@ int llapi_layout_comp_add(struct llapi_layout *layout)
 
        return 0;
 }
+/**
+ * Adds a first component of a mirror to \a layout.
+ * The \a layout will change it's current component pointer to
+ * the newly added component, and it'll be turned into a composite
+ * layout if it was not before the adding.
+ *
+ * \param[in] layout           existing composite or plain layout
+ *
+ * \retval     0 on success
+ * \retval     <0 if error occurs
+ */
+int llapi_layout_add_first_comp(struct llapi_layout *layout)
+{
+       struct llapi_layout_comp *comp, *new;
+
+       comp = __llapi_layout_cur_comp(layout);
+       if (comp == NULL)
+               return -1;
+
+       new = __llapi_comp_alloc(0);
+       if (new == NULL)
+               return -1;
+
+       new->llc_extent.e_start = 0;
+
+       list_add_tail(&new->llc_list, &layout->llot_comp_list);
+       layout->llot_cur_comp = new;
+       layout->llot_is_composite = true;
+
+       return 0;
+}
 
 /**
  * Deletes current component from the composite layout. The component
@@ -2119,13 +2178,100 @@ out:
  * comp->lcme_id value, which must be an unique component ID. The new
  * attributes are passed in by @comp and @valid is used to specify which
  * attributes in the component are going to be changed.
+ *
+ * \param[in] path     path name of the file
+ * \param[in] ids      An array of component IDs
+ * \param[in] flags    flags: LCME_FL_* or;
+ *                     negative flags: (LCME_FL_NEG|LCME_FL_*)
+ * \param[in] count    Number of elements in ids and flags array
  */
-int llapi_layout_file_comp_set(const char *path,
-                              const struct llapi_layout *comp,
-                              uint32_t valid)
+int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags,
+                              size_t count)
 {
-       errno = EOPNOTSUPP;
-       return -1;
+       int rc = -1, fd = -1, i;
+       size_t lum_size;
+       struct llapi_layout *layout;
+       struct llapi_layout_comp *comp;
+       struct lov_user_md *lum = NULL;
+
+       if (path == NULL) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (!count)
+               return 0;
+
+       for (i = 0; i < count; i++) {
+               if (!ids[i] || !flags[i]) {
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               if (ids[i] > LCME_ID_MAX || (flags[i] & ~LCME_KNOWN_FLAGS)) {
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               /* do not allow to set or clear INIT flag */
+               if (flags[i] & LCME_FL_INIT) {
+                       errno = EINVAL;
+                       return -1;
+               }
+       }
+
+       layout = __llapi_layout_alloc();
+       if (layout == NULL)
+               return -1;
+
+       layout->llot_is_composite = true;
+       for (i = 0; i < count; i++) {
+               comp = __llapi_comp_alloc(0);
+               if (comp == NULL)
+                       goto out;
+
+               comp->llc_id = ids[i];
+               comp->llc_flags = flags[i];
+
+               list_add_tail(&comp->llc_list, &layout->llot_comp_list);
+               layout->llot_cur_comp = comp;
+       }
+
+       lum = llapi_layout_to_lum(layout);
+       if (lum == NULL)
+               goto out;
+
+       lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
+
+       fd = open(path, O_RDWR);
+       if (fd < 0)
+               goto out;
+
+       /* flush cached pages from clients */
+       rc = llapi_file_flush(fd);
+       if (rc) {
+               errno = -rc;
+               rc = -1;
+               goto out_close;
+       }
+
+       rc = fsetxattr(fd, XATTR_LUSTRE_LOV".set.flags", lum, lum_size, 0);
+       if (rc < 0)
+               goto out_close;
+
+       rc = 0;
+
+out_close:
+       if (fd >= 0) {
+               int tmp_errno = errno;
+               close(fd);
+               errno = tmp_errno;
+       }
+out:
+       if (lum)
+               free(lum);
+       llapi_layout_free(layout);
+       return rc;
 }
 
 /**
@@ -2142,6 +2288,47 @@ bool llapi_layout_is_composite(struct llapi_layout *layout)
 }
 
 /**
+ * Iterate every components in the @layout and call callback function @cb.
+ *
+ * \param[in] layout   component layout list.
+ * \param[in] cb       callback for each component
+ * \param[in] cbdata   callback data
+ *
+ * \retval < 0                         error happens during the iteration
+ * \retval LLAPI_LAYOUT_ITER_CONT      finished the iteration w/o error
+ * \retval LLAPI_LAYOUT_ITER_STOP      got something, stop the iteration
+ */
+int llapi_layout_comp_iterate(struct llapi_layout *layout,
+                             llapi_layout_iter_cb cb, void *cbdata)
+{
+       int rc;
+
+       rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
+       if (rc < 0)
+               return rc;
+
+       /**
+        * make sure on success llapi_layout_comp_use() API returns 0 with
+        * USE_FIRST.
+        */
+       assert(rc == 0);
+
+       while (1) {
+               rc = cb(layout, cbdata);
+               if (rc != LLAPI_LAYOUT_ITER_CONT)
+                       break;
+
+               rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
+               if (rc < 0)
+                       return rc;
+               else if (rc == 1)       /* reached the last comp */
+                       return LLAPI_LAYOUT_ITER_CONT;
+       }
+
+       return rc;
+}
+
+/**
  * llapi_layout_merge() - Merge a composite layout into another one.
  * @dst_layout: Destination composite layout.
  * @src_layout: Source composite layout.
@@ -2237,11 +2424,8 @@ int llapi_mirror_find_stale(struct llapi_layout *layout,
        int rc;
 
        rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
-       if (rc < 0) {
-               fprintf(stderr, "%s: move to the first layout component: %s.\n",
-                       __func__, strerror(errno));
+       if (rc < 0)
                goto error;
-       }
 
        while (rc == 0) {
                uint32_t id;
@@ -2250,21 +2434,15 @@ int llapi_mirror_find_stale(struct llapi_layout *layout,
                uint64_t start, end;
 
                rc = llapi_layout_comp_flags_get(layout, &flags);
-               if (rc < 0) {
-                       fprintf(stderr, "llapi_layout_comp_flags_get: %s.\n",
-                               strerror(errno));
+               if (rc < 0)
                        goto error;
-               }
 
                if (!(flags & LCME_FL_STALE))
                        goto next;
 
                rc = llapi_layout_mirror_id_get(layout, &mirror_id);
-               if (rc < 0) {
-                       fprintf(stderr, "llapi_layout_mirror_id_get: %s.\n",
-                               strerror(errno));
+               if (rc < 0)
                        goto error;
-               }
 
                /* the caller only wants stale components from specific
                 * mirrors */
@@ -2282,18 +2460,12 @@ int llapi_mirror_find_stale(struct llapi_layout *layout,
                }
 
                rc = llapi_layout_comp_id_get(layout, &id);
-               if (rc < 0) {
-                       fprintf(stderr, "llapi_layout_comp_id_get: %s.\n",
-                               strerror(errno));
+               if (rc < 0)
                        goto error;
-               }
 
                rc = llapi_layout_comp_extent_get(layout, &start, &end);
-               if (rc < 0) {
-                       fprintf(stderr, "llapi_layout_comp_extent_get: %s.\n",
-                               strerror(errno));
+               if (rc < 0)
                        goto error;
-               }
 
                /* pack this component into @comp array */
                comp[idx].lrc_id = id;
@@ -2303,8 +2475,6 @@ int llapi_mirror_find_stale(struct llapi_layout *layout,
                idx++;
 
                if (idx >= comp_size) {
-                       fprintf(stderr, "%s: resync_comp array too small.\n",
-                               __func__);
                        rc = -EINVAL;
                        goto error;
                }
@@ -2312,8 +2482,6 @@ int llapi_mirror_find_stale(struct llapi_layout *layout,
        next:
                rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
                if (rc < 0) {
-                       fprintf(stderr, "%s: move to the next layout "
-                               "component: %s.\n", __func__, strerror(errno));
                        rc = -EINVAL;
                        goto error;
                }
@@ -2396,11 +2564,8 @@ ssize_t llapi_mirror_resync_one(int fd, struct llapi_layout *layout,
                ssize_t copied;
 
                src = llapi_mirror_find(layout, start, end, &mirror_end);
-               if (src == 0) {
-                       fprintf(stderr, "llapi_mirror_find cannot find "
-                               "component covering %lu.\n", start);
+               if (src == 0)
                        return -ENOENT;
-               }
 
                if (mirror_end == OBD_OBJECT_EOF)
                        to_copy = count;
@@ -2408,11 +2573,8 @@ ssize_t llapi_mirror_resync_one(int fd, struct llapi_layout *layout,
                        to_copy = MIN(count, mirror_end - start);
 
                copied = llapi_mirror_copy(fd, src, dst, start, to_copy);
-               if (copied < 0) {
-                       fprintf(stderr, "llapi_mirror_copy returned %zd.\n",
-                               copied);
+               if (copied < 0)
                        return copied;
-               }
 
                result += copied;
                if (copied < to_copy) /* end of file */