Viewing: pcc.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2017, DDN Storage Corporation.
*/
/*
* Persistent Client Cache
*
* Author: Li Xi <lixi@ddn.com>
*/
#ifndef LLITE_PCC_H
#define LLITE_PCC_H
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/kref.h>
#include <linux/types.h>
#include <linux/seq_file.h>
#include <uapi/linux/lustre/lustre_user.h>
extern struct kmem_cache *pcc_inode_slab;
#define LPROCFS_WR_PCC_MAX_CMD 4096
/* User/Group/Project ID */
struct pcc_match_id {
__u32 pmi_id;
struct list_head pmi_linkage;
};
/* Lazy file size */
struct pcc_match_size {
__u64 pms_size;
struct list_head pms_linkage;
};
/* wildcard file name */
struct pcc_match_fname {
char *pmf_name;
struct list_head pmf_linkage;
};
enum pcc_field {
PCC_FIELD_UID,
PCC_FIELD_GID,
PCC_FIELD_PROJID,
PCC_FIELD_FNAME,
PCC_FIELD_SIZE,
PCC_FIELD_MTIME,
PCC_FIELD_MAX
};
enum pcc_field_op {
PCC_FIELD_OP_EQ = 0,
PCC_FIELD_OP_LT = 1,
PCC_FIELD_OP_GT = 2,
PCC_FIELD_OP_MAX = 3,
PCC_FIELD_OP_INV = PCC_FIELD_MAX,
};
struct pcc_expression {
struct list_head pe_linkage;
enum pcc_field pe_field;
enum pcc_field_op pe_opc;
union {
struct list_head pe_cond;
__u64 pe_size; /* file size in bytes */
__u64 pe_mtime; /* relative age in seconds */
__u32 pe_id; /* UID/GID/PROJID */
};
};
struct pcc_conjunction {
/* link to disjunction */
struct list_head pc_linkage;
/* list of logical conjunction */
struct list_head pc_expressions;
};
/**
* Match rule for auto PCC-cached files.
*/
struct pcc_match_rule {
char *pmr_conds_str;
struct list_head pmr_conds;
};
struct pcc_matcher {
__u32 pm_uid;
__u32 pm_gid;
__u32 pm_projid;
__u64 pm_size;
__u64 pm_mtime;
const struct qstr *pm_name;
};
enum pcc_dataset_flags {
PCC_DATASET_INVALID = 0x0,
/* Indicate that known the file is not in PCC. */
PCC_DATASET_NONE = 0x01,
/* Try auto attach at open, enabled by default */
PCC_DATASET_OPEN_ATTACH = 0x02,
/* Try auto attach during IO when layout refresh, enabled by default */
PCC_DATASET_IO_ATTACH = 0x04,
/* Try auto attach at stat */
PCC_DATASET_STAT_ATTACH = 0x08,
PCC_DATASET_AUTO_ATTACH = PCC_DATASET_OPEN_ATTACH |
PCC_DATASET_IO_ATTACH |
PCC_DATASET_STAT_ATTACH,
/* PCC backend is only used for PCC-RW */
PCC_DATASET_PCCRW = 0x10,
/* PCC backend is only used for PCC-RO */
PCC_DATASET_PCCRO = 0x20,
/* PCC backend provides caching services for both PCC-RW and PCC-RO */
PCC_DATASET_PCC_ALL = PCC_DATASET_PCCRW | PCC_DATASET_PCCRO,
/* Default PCC caching mode: PCC-RO mode */
PCC_DATASET_PCC_DEFAULT = PCC_DATASET_PCCRO,
/* Move pagecache from mapping of PCC copy to Lustre file for mmap */
PCC_DATASET_MMAP_CONV = 0x40,
/* Set the project ID for the PCC copy */
PCC_DATASET_PROJ_QUOTA = 0x80,
};
struct pcc_dataset {
__u32 pccd_rwid; /* Archive ID */
__u32 pccd_roid; /* Readonly ID */
struct pcc_match_rule pccd_rule; /* Match rule */
enum pcc_dataset_flags pccd_flags; /* Flags of PCC backend */
char pccd_pathname[PATH_MAX]; /* full path */
struct path pccd_path; /* Root path */
struct list_head pccd_linkage; /* Linked to pccs_datasets */
struct kref pccd_refcount; /* Reference count */
enum hsmtool_type pccd_hsmtool_type; /* HSM copytool type */
};
#define PCC_DEFAULT_ASYNC_THRESHOLD (256 << 20)
struct pcc_super {
/* Protect pccs_datasets */
struct rw_semaphore pccs_rw_sem;
/* List of datasets */
struct list_head pccs_datasets;
/* creds of process who forced instantiation of super block */
const struct cred *pccs_cred;
/*
* Gobal PCC Generation: it will be increased once the configuration
* for PCC is changed, i.e. add or delete a PCC backend, modify the
* parameters for PCC.
*/
__u64 pccs_generation;
/* Size threshold for asynchrous PCC-RO attach in background. */
__u64 pccs_async_threshold;
bool pccs_async_affinity;
umode_t pccs_mode;
};
struct pcc_inode {
struct ll_inode_info *pcci_lli;
/* Cache path on local file system */
struct path pcci_path;
/*
* If reference count is 0, then the cache is not inited, if 1, then
* no one is using it.
*/
atomic_t pcci_refcount;
/* Whether readonly or readwrite PCC */
enum lu_pcc_type pcci_type:8;
/* Whether the inode attr is cached locally */
bool pcci_attr_valid;
/* Whether the PCC inode is unlinked at detach */
bool pcci_unlinked;
/* Layout generation */
__u32 pcci_layout_gen;
/*
* How many IOs are on going on this cached object. Layout can be
* changed only if there is no active IO.
*/
atomic_t pcci_active_ios;
/* Waitq - wait for PCC I/O completion. */
wait_queue_head_t pcci_waitq;
};
struct pcc_file {
/* Opened cache file */
struct file *pccf_file;
/* Whether readonly or readwrite PCC */
enum lu_pcc_type pccf_type;
/* I/O especially mmap() I/O must fallback to Lustre OSTs. */
__u32 pccf_fallback:1;
};
struct pcc_vma {
atomic_t pccv_refcnt;
struct file *pccv_file;
const struct vm_operations_struct *pccv_vm_ops;
};
struct pcc_attach_context {
struct file *pccx_file;
struct inode *pccx_inode;
__u32 pccx_attach_id;
};
enum pcc_io_type {
/* read system call */
PIT_READ = 1,
/* write system call */
PIT_WRITE,
/* truncate, utime system calls */
PIT_SETATTR,
/* stat system call */
PIT_GETATTR,
/* mmap write handling */
PIT_PAGE_MKWRITE,
/* page fault handling */
PIT_FAULT,
/* fsync system call handling */
PIT_FSYNC,
/* splice_read system call */
PIT_SPLICE_READ,
/* open system call */
PIT_OPEN
};
enum pcc_cmd_type {
PCC_ADD_DATASET = 0,
PCC_DEL_DATASET,
PCC_CLEAR_ALL,
};
struct pcc_cmd {
enum pcc_cmd_type pccc_cmd;
char *pccc_pathname;
union {
struct pcc_cmd_add {
__u32 pccc_rwid;
__u32 pccc_roid;
struct list_head pccc_conds;
char *pccc_conds_str;
enum pcc_dataset_flags pccc_flags;
enum hsmtool_type pccc_hsmtool_type;
} pccc_add;
struct pcc_cmd_del {
__u32 pccc_pad;
} pccc_del;
} u;
};
struct pcc_create_attach {
struct pcc_dataset *pca_dataset;
struct dentry *pca_dentry;
};
int pcc_super_init(struct pcc_super *super);
void pcc_super_fini(struct pcc_super *super);
int pcc_cmd_handle(char *buffer, unsigned long count,
struct pcc_super *super);
int pcc_super_dump(struct pcc_super *super, struct seq_file *m);
int pcc_readwrite_attach(struct file *file, struct inode *inode,
__u32 arch_id);
int pcc_readwrite_attach_fini(struct file *file, struct inode *inode,
__u32 gen, bool lease_broken, int rc,
bool attached);
int pcc_ioctl_attach(struct file *file, struct inode *inode,
struct lu_pcc_attach *attach);
int pcc_ioctl_detach(struct inode *inode, __u32 *flags);
int pcc_ioctl_state(struct file *file, struct inode *inode,
struct lu_pcc_state *state);
void pcc_file_init(struct pcc_file *pccf);
bool pcc_inode_permission(struct inode *inode);
int pcc_file_open(struct inode *inode, struct file *file);
void pcc_file_release(struct inode *inode, struct file *file);
ssize_t pcc_file_read_iter(struct kiocb *iocb, struct iov_iter *iter,
bool *cached);
ssize_t pcc_file_write_iter(struct kiocb *iocb, struct iov_iter *iter,
bool *cached);
int pcc_inode_getattr(struct inode *inode, u32 request_mask,
unsigned int flags, bool *cached);
int pcc_inode_setattr(struct inode *inode, struct iattr *attr, bool *cached);
ssize_t pcc_file_splice_read(struct file *in_file, loff_t *ppos,
struct pipe_inode_info *pipe, size_t count,
unsigned int flags);
int pcc_fsync(struct file *file, loff_t start, loff_t end,
int datasync, bool *cached);
int pcc_file_mmap(struct file *file, struct vm_area_struct *vma, bool *cached);
void pcc_vm_open(struct vm_area_struct *vma);
void pcc_vm_close(struct vm_area_struct *vma);
int pcc_fault(struct vm_area_struct *mva, struct vm_fault *vmf, bool *cached);
int pcc_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
bool *cached);
int pcc_inode_create(struct super_block *sb, struct pcc_dataset *dataset,
struct lu_fid *fid, struct dentry **pcc_dentry);
int pcc_inode_create_fini(struct inode *inode, struct pcc_create_attach *pca);
void pcc_create_attach_cleanup(struct super_block *sb,
struct pcc_create_attach *pca);
struct pcc_dataset *pcc_dataset_match_get(struct pcc_super *super,
enum lu_pcc_type type,
struct pcc_matcher *matcher);
void pcc_dataset_free(struct kref *kref);
void pcc_dataset_put(struct pcc_dataset *dataset);
void pcc_inode_free(struct inode *inode);
void pcc_layout_invalidate(struct inode *inode);
static inline struct file *pcc_vma_file(struct vm_area_struct *vma)
{
struct pcc_vma *pccv = (struct pcc_vma *)vma->vm_private_data;
struct file *file;
if (pccv)
file = pccv->pccv_file;
else
file = vma->vm_file;
return file;
}
#endif /* LLITE_PCC_H */