+static int pcc_try_dataset_attach(struct inode *inode, __u32 gen,
+ enum lu_pcc_type type,
+ struct pcc_dataset *dataset,
+ bool *cached)
+{
+ struct ll_inode_info *lli = ll_i2info(inode);
+ struct pcc_inode *pcci = lli->lli_pcc_inode;
+ const struct cred *old_cred;
+ struct dentry *pcc_dentry;
+ struct path path;
+ char *pathname;
+ __u32 pcc_gen;
+ int rc;
+
+ ENTRY;
+
+ if (type == LU_PCC_READWRITE &&
+ !(dataset->pccd_flags & PCC_DATASET_RWPCC))
+ RETURN(0);
+
+ OBD_ALLOC(pathname, PATH_MAX);
+ if (pathname == NULL)
+ RETURN(-ENOMEM);
+
+ pcc_fid2dataset_fullpath(pathname, PATH_MAX, &lli->lli_fid, dataset);
+
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
+ rc = kern_path(pathname, LOOKUP_FOLLOW, &path);
+ if (rc)
+ /* ignore this error */
+ GOTO(out, rc = 0);
+
+ pcc_dentry = path.dentry;
+#ifndef HAVE_VFS_SETXATTR
+ if (!pcc_dentry->d_inode->i_op->getxattr)
+ /* ignore this error */
+ GOTO(out_put_path, rc = 0);
+
+ rc = pcc_dentry->d_inode->i_op->getxattr(pcc_dentry, pcc_xattr_layout,
+ &pcc_gen, sizeof(pcc_gen));
+#else
+ rc = __vfs_getxattr(pcc_dentry, pcc_dentry->d_inode, pcc_xattr_layout,
+ &pcc_gen, sizeof(pcc_gen));
+#endif
+
+ if (rc < 0)
+ /* ignore this error */
+ GOTO(out_put_path, rc = 0);
+
+ rc = 0;
+ /* The file is still valid cached in PCC, attach it immediately. */
+ if (pcc_gen == gen) {
+ CDEBUG(D_CACHE, DFID" L.Gen (%d) consistent, auto attached.\n",
+ PFID(&lli->lli_fid), gen);
+ if (!pcci) {
+ OBD_SLAB_ALLOC_PTR_GFP(pcci, pcc_inode_slab, GFP_NOFS);
+ if (pcci == NULL)
+ GOTO(out_put_path, rc = -ENOMEM);
+
+ pcc_inode_init(pcci, lli);
+ dget(pcc_dentry);
+ pcc_inode_attach_init(dataset, pcci, pcc_dentry, type);
+ } else {
+ /*
+ * This happened when a file was once attached into
+ * PCC, and some processes keep this file opened
+ * (pcci->refcount > 1) and corresponding PCC file
+ * without any I/O activity, and then this file was
+ * detached by the manual detach command or the
+ * revocation of the layout lock (i.e. cached LRU lock
+ * shrinking).
+ */
+ pcc_inode_get(pcci);
+ pcci->pcci_type = type;
+ }
+ pcc_layout_gen_set(pcci, gen);
+ *cached = true;
+ }
+out_put_path:
+ path_put(&path);
+out:
+ revert_creds(old_cred);
+ OBD_FREE(pathname, PATH_MAX);
+ RETURN(rc);
+}
+
+static int pcc_try_datasets_attach(struct inode *inode, __u32 gen,
+ enum lu_pcc_type type, bool *cached)
+{
+ struct pcc_dataset *dataset, *tmp;
+ struct pcc_super *super = &ll_i2sbi(inode)->ll_pcc_super;
+ int rc = 0;
+
+ ENTRY;
+
+ down_read(&super->pccs_rw_sem);
+ list_for_each_entry_safe(dataset, tmp,
+ &super->pccs_datasets, pccd_linkage) {
+ if (!pcc_open_attach_enabled(dataset))
+ continue;
+ rc = pcc_try_dataset_attach(inode, gen, type, dataset, cached);
+ if (rc < 0 || (!rc && *cached))
+ break;
+ }
+ up_read(&super->pccs_rw_sem);
+
+ RETURN(rc);
+}
+
+static int pcc_try_open_attach(struct inode *inode, bool *cached)
+{
+ struct pcc_super *super = &ll_i2sbi(inode)->ll_pcc_super;
+ struct cl_layout clt = {
+ .cl_layout_gen = 0,
+ .cl_is_released = false,
+ };
+ int rc;
+
+ ENTRY;
+
+ /*
+ * Quick check whether there is PCC device.
+ */
+ if (list_empty(&super->pccs_datasets))
+ RETURN(0);
+
+ /*
+ * The file layout lock was cancelled. And this open does not
+ * obtain valid layout lock from MDT (i.e. the file is being
+ * HSM restoring).
+ */
+ if (ll_layout_version_get(ll_i2info(inode)) == CL_LAYOUT_GEN_NONE)
+ RETURN(0);
+
+ rc = pcc_get_layout_info(inode, &clt);
+ if (rc)
+ RETURN(rc);
+
+ if (clt.cl_is_released)
+ rc = pcc_try_datasets_attach(inode, clt.cl_layout_gen,
+ LU_PCC_READWRITE, cached);
+
+ RETURN(rc);
+}
+