@@ -1918,7 +1918,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case FS_IOC_FSSETXATTR:
return ll_ioctl_fssetxattr(inode, cmd, arg);
case LL_IOC_PCC_DETACH_BY_FID: {
- struct lu_pcc_detach *detach;
+ struct lu_pcc_detach_fid *detach;
struct lu_fid *fid;
struct inode *inode2;
unsigned long ino;
@@ -1928,7 +1928,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -ENOMEM;
if (copy_from_user(detach,
- (const struct lu_pcc_detach __user *)arg,
+ (const struct lu_pcc_detach_fid __user *)arg,
sizeof(*detach))) {
rc = -EFAULT;
goto out_detach;
@@ -1955,7 +1955,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto out_iput;
}
- rc = pcc_ioctl_detach(inode2);
+ rc = pcc_ioctl_detach(inode2, detach->pccd_opt);
out_iput:
iput(inode2);
out_detach:
@@ -3732,14 +3732,35 @@ static int ll_heat_set(struct inode *inode, enum lu_heat_flag flags)
rc = ll_heat_set(inode, flags);
return rc;
}
- case LL_IOC_PCC_DETACH:
- if (!S_ISREG(inode->i_mode))
- return -EINVAL;
+ case LL_IOC_PCC_DETACH: {
+ struct lu_pcc_detach *detach;
- if (!inode_owner_or_capable(inode))
- return -EPERM;
+ detach = kzalloc(sizeof(*detach), GFP_KERNEL);
+ if (!detach)
+ return -ENOMEM;
+
+ if (copy_from_user(detach,
+ (const struct lu_pcc_detach __user *)arg,
+ sizeof(*detach))) {
+ rc = -EFAULT;
+ goto out_detach_free;
+ }
+
+ if (!S_ISREG(inode->i_mode)) {
+ rc = -EINVAL;
+ goto out_detach_free;
+ }
- return pcc_ioctl_detach(inode);
+ if (!inode_owner_or_capable(inode)) {
+ rc = -EPERM;
+ goto out_detach_free;
+ }
+
+ rc = pcc_ioctl_detach(inode, detach->pccd_opt);
+out_detach_free:
+ kfree(detach);
+ return rc;
+ }
case LL_IOC_PCC_STATE: {
struct lu_pcc_state __user *ustate =
(struct lu_pcc_state __user *)arg;
@@ -1002,6 +1002,7 @@ static void pcc_inode_init(struct pcc_inode *pcci, struct ll_inode_info *lli)
{
pcci->pcci_lli = lli;
lli->lli_pcc_inode = pcci;
+ lli->lli_pcc_state = PCC_STATE_FL_NONE;
atomic_set(&pcci->pcci_refcount, 0);
pcci->pcci_type = LU_PCC_NONE;
pcci->pcci_layout_gen = CL_LAYOUT_GEN_NONE;
@@ -1715,8 +1716,9 @@ int pcc_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
CDEBUG(D_MMAP,
"%s: PCC backend fs not support ->page_mkwrite()\n",
ll_i2sbi(inode)->ll_fsname);
- pcc_ioctl_detach(inode);
+ pcc_ioctl_detach(inode, PCC_DETACH_OPT_NONE);
up_read(&mm->mmap_sem);
+ *cached = true;
return VM_FAULT_RETRY | VM_FAULT_NOPAGE;
}
/* Pause to allow for a race with concurrent detach */
@@ -1755,7 +1757,7 @@ int pcc_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
*/
if (OBD_FAIL_CHECK(OBD_FAIL_LLITE_PCC_DETACH_MKWRITE)) {
pcc_io_fini(inode);
- pcc_ioctl_detach(inode);
+ pcc_ioctl_detach(inode, PCC_DETACH_OPT_NONE);
up_read(&mm->mmap_sem);
return VM_FAULT_RETRY | VM_FAULT_NOPAGE;
}
@@ -2243,10 +2245,51 @@ int pcc_readwrite_attach_fini(struct file *file, struct inode *inode,
return rc;
}
-int pcc_ioctl_detach(struct inode *inode)
+static int pcc_hsm_remove(struct inode *inode)
+{
+ struct hsm_user_request *hur;
+ u32 gen;
+ int len;
+ int rc;
+
+ rc = ll_layout_restore(inode, 0, OBD_OBJECT_EOF);
+ if (rc) {
+ CDEBUG(D_CACHE, DFID" RESTORE failure: %d\n",
+ PFID(&ll_i2info(inode)->lli_fid), rc);
+ return rc;
+ }
+
+ ll_layout_refresh(inode, &gen);
+
+ len = sizeof(struct hsm_user_request) +
+ sizeof(struct hsm_user_item);
+ hur = kzalloc(len, GFP_NOFS);
+ if (!hur)
+ return -ENOMEM;
+
+ hur->hur_request.hr_action = HUA_REMOVE;
+ hur->hur_request.hr_archive_id = 0;
+ hur->hur_request.hr_flags = 0;
+ memcpy(&hur->hur_user_item[0].hui_fid, &ll_i2info(inode)->lli_fid,
+ sizeof(hur->hur_user_item[0].hui_fid));
+ hur->hur_user_item[0].hui_extent.offset = 0;
+ hur->hur_user_item[0].hui_extent.length = OBD_OBJECT_EOF;
+ hur->hur_request.hr_itemcount = 1;
+ rc = obd_iocontrol(LL_IOC_HSM_REQUEST, ll_i2sbi(inode)->ll_md_exp,
+ len, hur, NULL);
+ if (rc)
+ CDEBUG(D_CACHE, DFID" HSM REMOVE failure: %d\n",
+ PFID(&ll_i2info(inode)->lli_fid), rc);
+
+ kfree(hur);
+ return rc;
+}
+
+int pcc_ioctl_detach(struct inode *inode, u32 opt)
{
struct ll_inode_info *lli = ll_i2info(inode);
struct pcc_inode *pcci;
+ bool hsm_remove = false;
int rc = 0;
pcc_inode_lock(inode);
@@ -2255,11 +2298,26 @@ int pcc_ioctl_detach(struct inode *inode)
!pcc_inode_has_layout(pcci))
goto out_unlock;
- __pcc_layout_invalidate(pcci);
- pcc_inode_put(pcci);
+ LASSERT(atomic_read(&pcci->pcci_refcount) > 0);
+
+ if (pcci->pcci_type == LU_PCC_READWRITE) {
+ if (opt == PCC_DETACH_OPT_UNCACHE)
+ hsm_remove = true;
+
+ __pcc_layout_invalidate(pcci);
+ pcc_inode_put(pcci);
+ }
out_unlock:
pcc_inode_unlock(inode);
+ if (hsm_remove) {
+ const struct cred *old_cred;
+
+ old_cred = override_creds(pcc_super_cred(inode->i_sb));
+ rc = pcc_hsm_remove(inode);
+ revert_creds(old_cred);
+ }
+
return rc;
}
@@ -187,7 +187,7 @@ int pcc_readwrite_attach(struct file *file, struct inode *inode,
int pcc_readwrite_attach_fini(struct file *file, struct inode *inode,
u32 gen, bool lease_broken, int rc,
bool attached);
-int pcc_ioctl_detach(struct inode *inode);
+int pcc_ioctl_detach(struct inode *inode, u32 opt);
int pcc_ioctl_state(struct file *file, struct inode *inode,
struct lu_pcc_state *state);
void pcc_file_init(struct pcc_file *pccf);
@@ -357,8 +357,8 @@ struct ll_ioc_lease_id {
#define LL_IOC_LADVISE _IOR('f', 250, struct llapi_lu_ladvise)
#define LL_IOC_HEAT_GET _IOWR('f', 251, struct lu_heat)
#define LL_IOC_HEAT_SET _IOW('f', 251, __u64)
-#define LL_IOC_PCC_DETACH _IO('f', 252)
-#define LL_IOC_PCC_DETACH_BY_FID _IOW('f', 252, struct lu_pcc_detach)
+#define LL_IOC_PCC_DETACH _IOW('f', 252, struct lu_pcc_detach)
+#define LL_IOC_PCC_DETACH_BY_FID _IOW('f', 252, struct lu_pcc_detach_fid)
#define LL_IOC_PCC_STATE _IOR('f', 252, struct lu_pcc_state)
#define LL_STATFS_LMV 1
@@ -2093,9 +2093,19 @@ struct lu_pcc_attach {
__u32 pcca_id; /* archive ID for readwrite, group ID for readonly */
};
-struct lu_pcc_detach {
+enum lu_pcc_detach_opts {
+ PCC_DETACH_OPT_NONE = 0, /* Detach only, keep the PCC copy */
+ PCC_DETACH_OPT_UNCACHE, /* Remove the cached file after detach */
+};
+
+struct lu_pcc_detach_fid {
/* fid of the file to detach */
struct lu_fid pccd_fid;
+ __u32 pccd_opt;
+};
+
+struct lu_pcc_detach {
+ __u32 pccd_opt;
};
enum lu_pcc_state_flags {