Whamcloud - gitweb
LU-10092 llite: Add persistent cache on client
[fs/lustre-release.git] / lustre / llite / dir.c
index 914fff0..c70cd20 100644 (file)
@@ -1983,6 +1983,72 @@ migrate_free:
                RETURN(ll_ioctl_fsgetxattr(inode, cmd, arg));
        case LL_IOC_FSSETXATTR:
                RETURN(ll_ioctl_fssetxattr(inode, cmd, arg));
+       case LL_IOC_PCC_DETACH: {
+               struct lu_pcc_detach *detach;
+               struct lu_fid *fid;
+               struct inode *inode2;
+               unsigned long ino;
+
+               /*
+                * The reason why a dir IOCTL is used to detach a PCC-cached
+                * file rather than making it a file IOCTL is:
+                * When PCC caching a file, it will attach the file firstly,
+                * and increase the refcount of PCC inode (pcci->pcci_refcount)
+                * from 0 to 1.
+                * When detaching a PCC-cached file, it will check whether the
+                * refcount is 1. If so, the file can be detached successfully.
+                * Otherwise, it means there are some users opened and using
+                * the file currently, and it will return -EBUSY.
+                * Each open on the PCC-cached file will increase the refcount
+                * of the PCC inode;
+                * Each close on the PCC-cached file will decrease the refcount
+                * of the PCC inode;
+                * When used a file IOCTL to detach a PCC-cached file, it needs
+                * to open it at first, which will increase the refcount. So
+                * during the process of the detach IOCTL, it will return
+                * -EBUSY as the PCC inode refcount is larger than 1. Someone
+                * might argue that here it can just decrease the refcount
+                * of the PCC inode, return succeed and make the close of
+                * IOCTL file handle to perform the real detach. But this
+                * may result in inconsistent state of a PCC file. i.e. Process
+                * A got a successful return form the detach IOCTL; Process B
+                * opens the file before Process A finally closed the IOCTL
+                * file handle. It makes the following I/O of Process B will
+                * direct into PCC although the file was already detached from
+                * the view of Process A.
+                * Using a dir IOCTL does not exist the problem above.
+                */
+               OBD_ALLOC_PTR(detach);
+               if (detach == NULL)
+                       RETURN(-ENOMEM);
+
+               if (copy_from_user(detach,
+                                  (const struct lu_pcc_detach __user *)arg,
+                                  sizeof(*detach)))
+                       GOTO(out_detach, rc = -EFAULT);
+
+               fid = &detach->pccd_fid;
+               ino = cl_fid_build_ino(fid, ll_need_32bit_api(sbi));
+               inode2 = ilookup5(inode->i_sb, ino, ll_test_inode_by_fid, fid);
+               if (inode2 == NULL)
+                       /* Target inode is not in inode cache, and PCC file
+                        * has aleady released, return immdiately.
+                        */
+                       GOTO(out_detach, rc = 0);
+
+               if (!S_ISREG(inode2->i_mode))
+                       GOTO(out_iput, rc = -EINVAL);
+
+               if (!inode_owner_or_capable(inode2))
+                       GOTO(out_iput, rc = -EPERM);
+
+               rc = pcc_ioctl_detach(inode2);
+out_iput:
+               iput(inode2);
+out_detach:
+               OBD_FREE_PTR(detach);
+               RETURN(rc);
+       }
        default:
                RETURN(obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL,
                                     (void __user *)arg));