Whamcloud - gitweb
EX-7395 pcc: use llapi_open_by_fid to check pinned files
authorQian Yingjin <qian@ddn.com>
Wed, 26 Apr 2023 09:18:18 +0000 (05:18 -0400)
committerAndreas Dilger <adilger@whamcloud.com>
Fri, 12 May 2023 07:19:48 +0000 (07:19 +0000)
When check whether a file was pinned in PCC backend, it reported:
"cannot read or parse pin xattr of file
'/lustre/fsr/.lustre/fid/[0x780001b83:0x2138:0x0]'.: No such file
or directory (2)"

The failure reason is that open by FID is not configured for
subdirectory mounts.
In this patch, we use llapi_open_by_fid (which supports for
subdirectory mount) to open the file to solve this error.

Change-Id: If0120d745418836cfdf449a795b6f524c40f9c27
Signed-off-by: Qian Yingjin <qian@ddn.com>
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/50770
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/include/lustre/lustreapi.h
lustre/utils/liblustreapi_pcc.c

index 2e65763..96392c8 100644 (file)
@@ -668,11 +668,13 @@ int llapi_pccdev_set(const char *mntpath, const char *cmd);
 int llapi_pccdev_get(const char *mntpath);
 int llapi_pcc_del(const char *mntpath, const char *pccpath, __u32 flags);
 int llapi_pcc_clear(const char *mntpath, __u32 flags);
+int llapi_pcc_pin_fd(int fd, __u32 id);
 int llapi_pcc_pin_file(const char *path, __u32 id);
 int llapi_pcc_pin_fid(const char *lustre_dir, const struct lu_fid *fid, __u32 id);
 int llapi_pcc_unpin_file(const char *path, __u32 id);
 int llapi_pcc_backend_id_get(const char *path, enum lu_pcc_type type,
                             __u32 *id);
+bool llapi_pcc_is_pinned_fd(int fd, __u32 id);
 bool llapi_pcc_is_pinned_file(const char *path, __u32 id);
 bool llapi_pcc_is_pinned_fid(const char *lustre_dir, const struct lu_fid *fid,
                             __u32 id);
index 3e84fb7..c62f9d1 100644 (file)
@@ -923,6 +923,37 @@ out:
        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;
@@ -961,7 +992,8 @@ int llapi_pcc_pin_file(const char *path, __u32 id)
 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);
 
@@ -973,6 +1005,56 @@ out:
        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;
@@ -1021,23 +1103,6 @@ out:
        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.
 *
@@ -1049,14 +1114,20 @@ static int generate_fid_path(const char *lustre_dir, const struct lu_fid *fid,
 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)
@@ -1093,15 +1164,57 @@ 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;
 }