#include <unistd.h>
#include <errno.h>
#include <limits.h>
+#include <assert.h>
#include <sys/xattr.h>
#include <sys/param.h>
*
* \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
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.
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;
}
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;
}
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
* 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;
}
/**
}
/**
+ * 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.
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;
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 */
}
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;
idx++;
if (idx >= comp_size) {
- fprintf(stderr, "%s: resync_comp array too small.\n",
- __func__);
rc = -EINVAL;
goto error;
}
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;
}
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;
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 */