opt
/
kaspersky
/
kav4fs
/
src
/
kernel
/
redirfs
➕ New
📤 Upload
✎ Editing:
rfs.h
← Back
/* * RedirFS: Redirecting File System * Written by Frantisek Hrbata <frantisek.hrbata@redirfs.org> * * Copyright 2008 - 2010 Frantisek Hrbata * All rights reserved. * * This file is part of RedirFS. * * RedirFS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RedirFS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RedirFS. If not, see <http://www.gnu.org/licenses/>. */ #ifndef _RFS_H #define _RFS_H #include <linux/wait.h> #include <linux/sched.h> #include <linux/quotaops.h> #include <linux/slab.h> #include <linux/nfs_fs.h> #include <linux/mount.h> #include "redirfs.h" #include "../osdef.h" #define RFS_ADD_OP(ops_new, op) (ops_new.op = rfs_##op) #define RFS_REM_OP(ops_new, ops_old, op) (ops_new.op = ops_old ? ops_old->op : NULL) #define RFS_SET_OP(arr, id, ops_new, ops_old, op) \ (arr[id] ? RFS_ADD_OP(ops_new, op) : RFS_REM_OP(ops_new, ops_old, op)) #define RFS_SET_FOP(rf, id, op) \ (rf->rdentry->rinfo->rops ? RFS_SET_OP(rf->rdentry->rinfo->rops->arr, id, \ rf->op_new, rf->op_old, op) \ : RFS_REM_OP(rf->op_new, rf->op_old, op)) #define RFS_SET_DOP(rd, id, op) \ (rd->rinfo->rops \ ? RFS_SET_OP(rd->rinfo->rops->arr, id, rd->op_new, rd->op_old, op) \ : RFS_REM_OP(rd->op_new, rd->op_old, op)) #define RFS_SET_IOP_MGT(ri, op) \ (ri->rinfo->rops ? RFS_ADD_OP(ri->op_new, op) \ : RFS_REM_OP(ri->op_new, ri->op_old, op)) #define RFS_SET_IOP(ri, id, op) \ (ri->rinfo->rops \ ? RFS_SET_OP(ri->rinfo->rops->arr, id, ri->op_new, ri->op_old, op) \ : RFS_REM_OP(ri->op_new, ri->op_old, op)) struct rfs_file; #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)) && !defined(DEFINE_MUTEX) #define rfs_mutex_t semaphore #define RFS_DEFINE_MUTEX(mutex) DECLARE_MUTEX(mutex) #define rfs_mutex_init(mutex) init_MUTEX(mutex) #define rfs_mutex_lock(mutex) down(mutex) #define rfs_mutex_unlock(mutex) up(mutex) #define rfs_for_each_d_child(pos, head) list_for_each_entry(pos, head, d_child) #define rfs_d_child_entry(pos) list_entry(pos, struct dentry, d_child) inline static void rfs_inode_mutex_lock(struct inode* inode) { down(&inode->i_sem); } inline static void rfs_inode_mutex_unlock(struct inode* inode) { up(&inode->i_sem); } #else #define rfs_mutex_t mutex #define RFS_DEFINE_MUTEX(mutex) DEFINE_MUTEX(mutex) #define rfs_mutex_init(mutex) mutex_init(mutex) #define rfs_mutex_lock(mutex) mutex_lock(mutex) #define rfs_mutex_unlock(mutex) mutex_unlock(mutex) #if defined(DENTRY_HAS_D_CHILD) #define rfs_for_each_d_child(pos, head) list_for_each_entry(pos, head, d_child) #define rfs_d_child_entry(pos) list_entry(pos, struct dentry, d_child) #else #define rfs_for_each_d_child(pos, head) list_for_each_entry(pos, head, d_u.d_child) #define rfs_d_child_entry(pos) list_entry(pos, struct dentry, d_u.d_child) #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)) inline static void rfs_inode_mutex_lock(struct inode *inode) { mutex_lock(&inode->i_mutex); } inline static void rfs_inode_mutex_unlock(struct inode *inode) { mutex_unlock(&inode->i_mutex); } #else #define rfs_inode_mutex_lock(inode) inode_lock(inode) #define rfs_inode_mutex_unlock(inode) inode_unlock(inode) #endif #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)) #define rfs_kmem_cache_t kmem_cache_t #else #define rfs_kmem_cache_t struct kmem_cache #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)) #define fmode_t unsigned #define rfs_path_lookup(p, flags, nd) path_lookup(p, flags, &(nd)) #else #define rfs_path_lookup(p, flags, nd) kern_path(p, flags, &(nd).path) #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)) #define DCACHE_LOCK(d) spin_lock(&dcache_lock) #define DCACHE_UNLOCK(d) spin_unlock(&dcache_lock) #define RENAME_LOCK() spin_lock(&dcache_lock) #define RENAME_UNLOCK() spin_unlock(&dcache_lock) #define DENTRY_LOCK(d) #define DENTRY_NESTED(d) #define DENTRY_UNLOCK(d) #define dget_dlock(d) dget_locked(d) #else #define DENTRY_LOCK(d) spin_lock(&(d)->d_lock) #define DENTRY_NESTED(d) spin_lock_nested(&(d)->d_lock, DENTRY_D_LOCK_NESTED) #define DENTRY_UNLOCK(d) spin_unlock(&(d)->d_lock) #define DCACHE_LOCK(d) spin_lock(&(d)->d_lock) #define DCACHE_UNLOCK(d) spin_unlock(&(d)->d_lock) #define RENAME_LOCK() write_seqlock(&rename_lock) #define RENAME_UNLOCK() write_sequnlock(&rename_lock) #endif struct rfs_op_info { enum redirfs_rv (*pre_cb)(redirfs_context, struct redirfs_args*); enum redirfs_rv (*post_cb)(redirfs_context, struct redirfs_args*); }; struct rfs_flt { struct list_head list; struct rfs_op_info cbs[REDIRFS_OP_END]; struct module* owner; char* name; int priority; int paths_nr; atomic_t count; spinlock_t lock; struct redirfs_filter_operations* ops; }; void rfs_flt_put(struct rfs_flt* rflt); struct rfs_flt* rfs_flt_get(struct rfs_flt* rflt); struct rfs_path { struct list_head list; struct list_head rfst_list; struct list_head rroot_list; struct rfs_root* rroot; struct rfs_chain* rinch; struct rfs_chain* rexch; struct vfsmount* mnt; struct dentry* dentry; atomic_t count; spinlock_t lock; int id; }; extern struct rfs_mutex_t rfs_path_mutex; struct rfs_path* rfs_path_get(struct rfs_path* rpath); void rfs_path_put(struct rfs_path* rpath); struct rfs_path* rfs_path_find_id(int id); int rfs_fsrename(struct inode* old_dir, struct dentry* old_dentry, struct inode* new_dir, struct dentry* new_dentry); struct rfs_root { struct list_head list; struct list_head walk_list; struct list_head rpaths; struct list_head data; struct rfs_chain* rinch; struct rfs_chain* rexch; struct rfs_info* rinfo; struct dentry* dentry; int paths_nr; spinlock_t lock; atomic_t count; }; extern struct list_head rfs_root_list; extern struct list_head rfs_root_walk_list; struct rfs_root* rfs_root_get(struct rfs_root* rroot); void rfs_root_put(struct rfs_root* rroot); void rfs_root_add_rpath(struct rfs_root* rroot, struct rfs_path* rpath); void rfs_root_rem_rpath(struct rfs_root* rroot, struct rfs_path* rpath); struct rfs_root* rfs_root_add(struct dentry* dentry); int rfs_root_add_include(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_root_add_exclude(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_root_rem_include(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_root_rem_exclude(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_root_add_flt(struct rfs_root* rroot, void* data); int rfs_root_rem_flt(struct rfs_root* rroot, void* data); int rfs_root_walk(int (*cb)(struct rfs_root*, void*), void* data); void rfs_root_add_walk(struct dentry* dentry); void rfs_root_set_rinfo(struct rfs_root* rroot, struct rfs_info* rinfo); struct rfs_ops { char* arr; atomic_t count; spinlock_t lock; int flags; }; struct rfs_ops* rfs_ops_alloc(void); struct rfs_ops* rfs_ops_get(struct rfs_ops* rops); void rfs_ops_put(struct rfs_ops* rops); struct rfs_chain { struct rfs_flt** rflts; int rflts_nr; atomic_t count; spinlock_t lock; }; struct rfs_chain* rfs_chain_get(struct rfs_chain* rchain); void rfs_chain_put(struct rfs_chain* rchain); int rfs_chain_find(struct rfs_chain* rchain, struct rfs_flt* rflt); struct rfs_chain* rfs_chain_add(struct rfs_chain* rchain, struct rfs_flt* rflt); struct rfs_chain* rfs_chain_rem(struct rfs_chain* rchain, struct rfs_flt* rflt); void rfs_chain_ops(struct rfs_chain* rchain, struct rfs_ops* ops); int rfs_chain_cmp(struct rfs_chain* rch1, struct rfs_chain* rch2); struct rfs_chain* rfs_chain_join(struct rfs_chain* rch1, struct rfs_chain* rch2); struct rfs_chain* rfs_chain_diff(struct rfs_chain* rch1, struct rfs_chain* rch2); struct rfs_info { struct rfs_chain* rchain; struct rfs_ops* rops; struct rfs_root* rroot; atomic_t count; spinlock_t lock; }; extern struct rfs_info* rfs_info_none; struct rfs_info* rfs_info_alloc(struct rfs_root* rroot, struct rfs_chain* rchain); struct rfs_info* rfs_info_get(struct rfs_info* rinfo); void rfs_info_put(struct rfs_info* rinfo); struct rfs_info* rfs_info_parent(struct dentry* dentry); int rfs_info_add_include(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_info_add_exclude(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_info_rem_include(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_info_rem_exclude(struct rfs_root* rroot, struct rfs_flt* rflt); int rfs_info_add(struct dentry* dentry, struct rfs_info* rinfo, struct rfs_flt* rflt); int rfs_info_rem(struct dentry* dentry, struct rfs_info* rinfo, struct rfs_flt* rflt); int rfs_info_set(struct dentry* dentry, struct rfs_info* rinfo, struct rfs_flt* rflt); int rfs_info_reset(struct dentry* dentry, struct rfs_info* rinfo); struct rfs_dentry { struct list_head rinode_list; struct list_head rfiles; struct list_head data; struct dentry* dentry; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) const struct dentry_operations* op_old; #else struct dentry_operations* op_old; #endif struct dentry_operations op_new; struct rfs_inode* rinode; struct rfs_info* rinfo; spinlock_t lock; atomic_t count; }; #define rfs_dentry_find(dentry) \ (dentry && dentry->d_op && dentry->d_op->d_iput == rfs_d_iput \ ? rfs_dentry_get(container_of(dentry->d_op, struct rfs_dentry, op_new)) \ : NULL) void rfs_d_iput(struct dentry* dentry, struct inode* inode); struct rfs_dentry* rfs_dentry_get(struct rfs_dentry* rdentry); void rfs_dentry_put(struct rfs_dentry* rdentry); struct rfs_dentry* rfs_dentry_add(struct dentry* dentry, struct rfs_info* rinfo); void rfs_dentry_del(struct rfs_dentry* rdentry); int rfs_dentry_add_rinode(struct rfs_dentry* rdentry, struct rfs_info* rinfo); void rfs_dentry_rem_rinode(struct rfs_dentry* rdentry); struct rfs_info* rfs_dentry_get_rinfo(struct rfs_dentry* rdentry); void rfs_dentry_set_rinfo(struct rfs_dentry* rdentry, struct rfs_info* rinfo); void rfs_dentry_add_rfile(struct rfs_dentry* rdentry, struct rfs_file* rfile); void rfs_dentry_rem_rfile(struct rfs_file* rfile); void rfs_dentry_rem_rfiles(struct rfs_dentry* rdentry); void rfs_dentry_set_ops(struct rfs_dentry* dentry); int rfs_dentry_cache_create(void); void rfs_dentry_cache_destory(void); void rfs_dentry_rem_data(struct dentry* dentry, struct rfs_flt* rflt); int rfs_dentry_move(struct dentry* dentry, struct rfs_flt* rflt, struct rfs_root* src, struct rfs_root* dst); #if defined(S_IOPS_WRAPPER) #define INODE_OPERATIONS inode_operations_wrapper #define OP_NEW(rinode) rinode->op_new #else #define INODE_OPERATIONS inode_operations #endif struct rfs_inode { struct list_head rdentries; /* mutex */ struct list_head data; struct inode* inode; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)) const struct inode_operations* op_old; const struct file_operations* fop_old; #else struct inode_operations* op_old; struct file_operations* fop_old; #endif #if defined(S_IOPS_WRAPPER) union { struct inode_operations_wrapper op_new_w; struct inode_operations op_new; }; unsigned int i_flags; #else struct inode_operations op_new; #endif struct rfs_info* rinfo; struct rfs_mutex_t mutex; spinlock_t lock; atomic_t count; atomic_t nlink; int rdentries_nr; /* mutex */ }; #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)) int rfs_rename(struct inode* old_dir, struct dentry* old_dentry, struct inode* new_dir, struct dentry* new_dentry); #else int rfs_rename(struct inode* old_dir, struct dentry* old_dentry, struct inode* new_dir, struct dentry* new_dentry, unsigned int flags); #endif #if defined(IOP_HAS_RENAME2) int rfs_rename2(struct inode* old_dir, struct dentry* old_dentry, struct inode* new_dir, struct dentry* new_dentry, unsigned int); #define RFS_RENAME rfs_rename2 #define RENAME rename2 #else #define RFS_RENAME rfs_rename #define RENAME rename #endif #if defined(S_IOPS_WRAPPER) #define IS_INODE_RENAME2_SET(inode) \ (inode->i_op && \ ((((struct inode_operations_wrapper*)&inode->i_op)->rename2 == rfs_rename2) || \ (inode->i_op->rename == rfs_rename))) #define IS_RINODE_RENAME2_SET(inode) \ (IS_IOPS_WRAPPER(inode) \ ? (inode->op_old && \ ((struct inode_operations_wrapper*)&inode->op_old)->rename2) \ : inode->op_old && inode->op_old->rename) #define RENAME2_CALL(inode, od, oe, nd, ne, f) \ IS_IOPS_WRAPPER(inode) \ ? ((struct inode_operations_wrapper*)&inode->op_old) \ ->rename2(od, oe, nd, ne, f) \ : inode->op_old->rename(od, oe, nd, ne) #else /* S_IOPS_WRAPPER */ #define IS_IOPS_WRAPPER(inode) false #define IS_INODE_RENAME2_SET(inode) \ (inode && inode->i_op && inode->i_op.RENAME == RFS_RENAME) #define IS_RINODE_RENAME2_SET(inode) (inode->op_old && inode->op_old->rename2) #define RENAME2_CALL(inode, od, oe, nd, ne, f) \ inode->op_old->rename2(od, oe, nd, ne, f) #endif /* S_IOPS_WRAPPER */ extern rwlock_t rfs_inode_rwlock; struct rfs_inode* rfs_inode_find(struct inode* inode); struct rfs_inode* rfs_inode_get(struct rfs_inode* rinode); void rfs_inode_put(struct rfs_inode* rinode); struct rfs_inode* rfs_inode_add(struct inode* inode, struct rfs_info* rinfo); void rfs_inode_del(struct rfs_inode* rinode); void rfs_inode_add_rdentry(struct rfs_inode* rinode, struct rfs_dentry* rdentry); void rfs_inode_rem_rdentry(struct rfs_inode* rinode, struct rfs_dentry* rdentry); struct rfs_info* rfs_inode_get_rinfo(struct rfs_inode* rinode); int rfs_inode_set_rinfo(struct rfs_inode* rinode); void rfs_inode_set_ops(struct rfs_inode* rinode); int rfs_inode_cache_create(void); void rfs_inode_cache_destroy(void); struct rfs_file { struct list_head rdentry_list; struct list_head data; struct file* file; struct rfs_dentry* rdentry; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)) const struct file_operations* op_old; #else struct file_operations* op_old; #endif struct file_operations op_new; spinlock_t lock; atomic_t count; }; #define rfs_file_find(file) \ (file && file->f_op && file->f_op->open == rfs_open \ ? rfs_file_get(container_of(file->f_op, struct rfs_file, op_new)) \ : NULL) extern struct file_operations rfs_file_ops; struct rfs_file* rfs_file_add(struct file* file); int rfs_open(struct inode* inode, struct file* file); struct rfs_file* rfs_file_get(struct rfs_file* rfile); void rfs_file_put(struct rfs_file* rfile); void rfs_file_set_ops(struct rfs_file* rfile); int rfs_file_cache_create(void); void rfs_file_cache_destory(void); struct rfs_dcache_data { struct rfs_info* rinfo; struct rfs_flt* rflt; struct dentry* droot; }; struct rfs_dcache_data* rfs_dcache_data_alloc(struct dentry* dentry, struct rfs_info* rinfo, struct rfs_flt* rflt); void rfs_dcache_data_free(struct rfs_dcache_data* rdata); struct rfs_dcache_entry { struct list_head list; struct dentry* dentry; }; int rfs_dcache_walk(struct dentry* root, int (*cb)(struct dentry*, void*), void* data); int rfs_dcache_add_dir(struct dentry* dentry, void* data); int rfs_dcache_add(struct dentry* dentry, void* data); int rfs_dcache_rem(struct dentry* dentry, void* data); int rfs_dcache_set(struct dentry* dentry, void* data); int rfs_dcache_reset(struct dentry* dentry, void* data); int rfs_dcache_rdentry_add(struct dentry* dentry, struct rfs_info* rinfo); int rfs_dcache_rinode_del(struct rfs_dentry* rdentry, struct inode* inode); int rfs_dcache_get_subs(struct dentry* dir, struct list_head* sibs, struct dentry* last); void rfs_dcache_entry_free_list(struct list_head* head); struct rfs_context { struct list_head data; int idx; int idx_start; }; void rfs_context_init(struct rfs_context* rcont, int start); void rfs_context_deinit(struct rfs_context* rcont); int rfs_precall_flts(struct rfs_chain* rchain, struct rfs_context* rcont, struct redirfs_args* rargs); void rfs_postcall_flts(struct rfs_chain* rchain, struct rfs_context* rcont, struct redirfs_args* rargs); void rfs_data_remove(struct list_head* head); #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 16)) #define rfs_rename_lock(sb) down(&sb->s_vfs_rename_sem) #define rfs_rename_unlock(sb) up(&sb->s_vfs_rename_sem) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)) typedef unsigned gfp_t; static inline void* kzalloc(size_t size, gfp_t flags) { void* p; p = kmalloc(size, flags); if (!p) return NULL; memset(p, 0, size); return p; } #endif static inline void* kmem_cache_zalloc(kmem_cache_t* cache, gfp_t flags) { void* obj; obj = kmem_cache_alloc(cache, flags); if (!obj) return NULL; memset(obj, 0, kmem_cache_size(cache)); return obj; } #else #define rfs_rename_lock(sb) mutex_lock(&sb->s_vfs_rename_mutex) #define rfs_rename_unlock(sb) mutex_unlock(&sb->s_vfs_rename_mutex) #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)) static inline rfs_kmem_cache_t* rfs_kmem_cache_create(const char* n, size_t s) { return kmem_cache_create(n, s, 0, SLAB_RECLAIM_ACCOUNT, NULL); } #else static inline rfs_kmem_cache_t* rfs_kmem_cache_create(const char* n, size_t s) { return kmem_cache_create(n, s, 0, SLAB_RECLAIM_ACCOUNT, NULL, NULL); } #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) static inline void rfs_set_nameidata_path(struct nameidata* nd, struct dentry* dentry, struct vfsmount* vfsmnt) { nd->dentry = dentry; nd->mnt = vfsmnt; } static inline void rfs_nameidata_put(struct nameidata* nd) { path_release(nd); } static inline struct dentry* rfs_nameidata_dentry(struct nameidata* nd) { return nd->dentry; } static inline struct vfsmount* rfs_nameidata_mnt(struct nameidata* nd) { return nd->mnt; } #elif(LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) static inline void rfs_set_nameidata_path(struct nameidata* nd, struct dentry* dentry, struct vfsmount* vfsmnt) { nd->path = (struct path){.dentry = dentry, .mnt = vfsmnt}; } static inline void rfs_nameidata_put(struct nameidata* nd) { path_put(&nd->path); } static inline struct dentry* rfs_nameidata_dentry(struct nameidata* nd) { return nd->path.dentry; } static inline struct vfsmount* rfs_nameidata_mnt(struct nameidata* nd) { return nd->path.mnt; } #else #define f_dentry f_path.dentry #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) #define rfs_dq_transfer vfs_dq_transfer #else #define rfs_dq_transfer DQUOT_TRANSFER #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)) #define to_open_flags(flags) ((flags) + ((((flags) + 1) & O_ACCMODE) ? 1 : 0)) #else #define to_open_flags(flags) ((flags) + ((((flags)&O_ACCMODE) == 3) ? 1 : 0)) #endif #define rfs_skip_file(mode) (S_ISSOCK(mode) || S_ISBLK(mode) || S_ISCHR(mode)) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) #define ERR_CAST(ptr) (void*)(ptr) #endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) #define IS_ERR_OR_NULL(ptr) (IS_ERR(ptr) || !ptr) #endif #endif
💾 Save Changes
Cancel
📤 Upload File
×
Select File
Upload
Cancel
➕ Create New
×
Type
📄 File
📁 Folder
Name
Create
Cancel
✎ Rename Item
×
Current Name
New Name
Rename
Cancel
🔐 Change Permissions
×
Target File
Permission (e.g., 0755, 0644)
0755
0644
0777
Apply
Cancel