return obj;
}
+static struct json_object *read_pin_xattr_object_fd(int fd)
+{
+ int rc;
+ struct json_object *obj = NULL;
+ char buff[XATTR_SIZE_MAX];
+
+ rc = fgetxattr(fd, XATTR_LUSTRE_PIN, buff, sizeof(buff));
+ if (rc < 0)
+ goto out;
+ buff[rc] = '\0';
+
+ obj = json_tokener_parse(buff);
+ if (obj == NULL) {
+ llapi_error(LLAPI_MSG_ERROR, -EINVAL,
+ "failed to parse pin xattr '%s'.", buff);
+ errno = -EINVAL;
+ goto out;
+ }
+
+ rc = verify_pin_xattr_object(obj);
+ if (rc) {
+ llapi_error(LLAPI_MSG_ERROR, -rc, "invalid pin object.");
+ json_object_put(obj);
+ obj = NULL;
+ errno = -rc;
+ goto out;
+ }
+out:
+ return obj;
+}
+
int llapi_pcc_pin_file(const char *path, __u32 id)
{
int rc = 0, i;
add_entry:
/* add a new entry */
node = json_object_new_object();
- json_object_object_add(node, PIN_JSON_HSM_STR, json_object_new_int64(id));
+ json_object_object_add(node, PIN_JSON_HSM_STR,
+ json_object_new_int64(id));
json_object_array_add(obj, node);
str = json_object_to_json_string_ext(obj, 0);
return rc;
}
+int llapi_pcc_pin_fd(int fd, __u32 id)
+{
+ int rc = 0, i;
+ struct json_object *obj = NULL, *node, *val;
+ const char *str = NULL;
+ bool found;
+
+ obj = read_pin_xattr_object_fd(fd);
+
+ if (obj == NULL && errno == ENODATA) {
+ obj = json_object_new_array();
+ goto add_entry;
+
+ }
+ if (obj == NULL) {
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "cannot read or parse pin xattr");
+ rc = -errno;
+ goto out;
+ }
+
+ /* Now we have an valid pin object, search for existing entry */
+ for (i = 0; i < json_object_array_length(obj); i++) {
+ node = json_object_array_get_idx(obj, i);
+ found = json_object_object_get_ex(node, PIN_JSON_HSM_STR, &val);
+ if (found && json_object_get_int64(val) == id)
+ break;
+ }
+ /* found existing entry, do nothing and return success */
+ if (i < json_object_array_length(obj)) {
+ rc = 0;
+ goto out;
+ }
+
+add_entry:
+ /* add a new entry */
+ node = json_object_new_object();
+ json_object_object_add(node, PIN_JSON_HSM_STR,
+ json_object_new_int64(id));
+ json_object_array_add(obj, node);
+ str = json_object_to_json_string_ext(obj, 0);
+
+ rc = fsetxattr(fd, XATTR_LUSTRE_PIN, str, strlen(str), 0);
+ if (rc < 0)
+ rc = -errno;
+out:
+ json_object_put(obj);
+ return rc;
+}
+
int llapi_pcc_unpin_file(const char *path, __u32 id)
{
int rc = 0, i;
return rc;
}
-static int generate_fid_path(const char *lustre_dir, const struct lu_fid *fid,
- char *path, int maxlen)
-{
- int rc;
-
- rc = snprintf(path, maxlen, "%s/.lustre/fid/"DFID, lustre_dir,
- PFID(fid));
- if (rc >= maxlen)
- rc = -EOVERFLOW;
- else if (rc > 0)
- rc = 0;
- else
- rc = -errno;
-
- return rc;
-}
-
/**
* Pin a given file with lustre mount point and fid for a PCC backend.
*
int llapi_pcc_pin_fid(const char *lustre_dir, const struct lu_fid *fid,
__u32 id)
{
+ int fd;
int rc;
- char path[PATH_MAX];
- rc = generate_fid_path(lustre_dir, fid, path, PATH_MAX);
- if (rc)
+ fd = llapi_open_by_fid(lustre_dir, fid, O_RDWR);
+ if (fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc,
+ "llapi_open_by_fid for " DFID "failed", PFID(fid));
return rc;
+ }
- return llapi_pcc_pin_file(path, id);
+ rc = llapi_pcc_pin_fd(fd, id);
+ close(fd);
+ return rc;
}
bool llapi_pcc_is_pinned_file(const char *path, __u32 id)
return false;
}
+bool llapi_pcc_is_pinned_fd(int fd, __u32 id)
+{
+ struct json_object *obj, *node, *val;
+ int i;
+
+ obj = read_pin_xattr_object_fd(fd);
+ if (obj == NULL && errno == ENODATA) {
+ errno = 0;
+ return false;
+ }
+
+ if (obj == NULL) {
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "cannot read or parse pin xattr for file");
+ return false;
+ }
+
+ /* Now we have an valid pin object, search for the entry */
+ for (i = 0; i < json_object_array_length(obj); i++) {
+ bool found;
+
+ node = json_object_array_get_idx(obj, i);
+ found = json_object_object_get_ex(node, PIN_JSON_HSM_STR, &val);
+ if (found && json_object_get_int64(val) == id) {
+ json_object_put(obj);
+ return true;
+ }
+ }
+
+ json_object_put(obj);
+ errno = 0;
+ return false;
+}
+
bool llapi_pcc_is_pinned_fid(const char *lustre_dir, const struct lu_fid *fid,
__u32 id)
{
- char path[PATH_MAX];
+ bool pinned;
+ int fd;
int rc;
- rc = generate_fid_path(lustre_dir, fid, path, PATH_MAX);
- if (rc)
+ fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
+ if (fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc,
+ "llapi_open_by_fid for " DFID "failed", PFID(fid));
return rc;
+ }
+
+ pinned = llapi_pcc_is_pinned_fd(fd, id);
+ close(fd);
- return llapi_pcc_is_pinned_file(path, id);
+ return pinned;
}