1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 1998-2022 Erez Zadok 4 * Copyright (c) 2009 Shrikar Archak 5 * Copyright (c) 2003-2022 Stony Brook University 6 * Copyright (c) 2003-2022 The Research Foundation of SUNY 7 * Copyright (c) 2023 Huawei Device Co., Ltd. 8 */ 9 10#ifndef _SHAREFS_H_ 11#define _SHAREFS_H_ 12 13#include <linux/dcache.h> 14#include <linux/file.h> 15#include <linux/fs.h> 16#include <linux/mm.h> 17#include <linux/mount.h> 18#include <linux/namei.h> 19#include <linux/seq_file.h> 20#include <linux/statfs.h> 21#include <linux/fs_stack.h> 22#include <linux/magic.h> 23#include <linux/uaccess.h> 24#include <linux/slab.h> 25#include <linux/sched.h> 26#include <linux/xattr.h> 27#include <linux/exportfs.h> 28#include <linux/pagemap.h> 29 30/* the file system name */ 31#define SHAREFS_NAME "sharefs" 32 33/* sharefs root inode number */ 34#define SHAREFS_ROOT_INO 1 35#define OID_ROOT 0 36#define ROOT_UID KUIDT_INIT(OID_ROOT) 37#define ROOT_GID KGIDT_INIT(OID_ROOT) 38#define SHAREFS_SUPER_MAGIC 0x20230212 39 40/* useful for tracking code reachability */ 41#define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__) 42 43/* file private data */ 44struct sharefs_file_info { 45 struct file *lower_file; 46 const struct vm_operations_struct *lower_vm_ops; 47}; 48 49/* sharefs inode data in memory */ 50struct sharefs_inode_info { 51 struct inode *lower_inode; 52 struct inode vfs_inode; 53 __u16 perm; 54}; 55 56/* sharefs dentry data in memory */ 57struct sharefs_dentry_info { 58 spinlock_t lock; /* protects lower_path */ 59 struct path lower_path; 60}; 61 62/* sharefs super-block data in memory */ 63struct sharefs_sb_info { 64 struct super_block *lower_sb; 65 /* multi user */ 66 unsigned int user_id; 67 bool override; 68 bool override_support_delete; 69}; 70 71/* operations vectors defined in specific files */ 72extern const struct file_operations sharefs_main_fops; 73extern const struct file_operations sharefs_dir_fops; 74extern const struct inode_operations sharefs_main_iops; 75extern const struct inode_operations sharefs_dir_iops; 76extern const struct inode_operations sharefs_symlink_iops; 77extern const struct super_operations sharefs_sops; 78extern const struct dentry_operations sharefs_dops; 79 80extern int sharefs_init_inode_cache(void); 81extern void sharefs_destroy_inode_cache(void); 82extern int sharefs_init_dentry_cache(void); 83extern void sharefs_destroy_dentry_cache(void); 84extern int new_dentry_private_data(struct dentry *dentry); 85extern void free_dentry_private_data(struct dentry *dentry); 86extern struct dentry *sharefs_lookup(struct inode *dir, struct dentry *dentry, 87 unsigned int flags); 88extern struct inode *sharefs_iget(struct super_block *sb, 89 struct inode *lower_inode); 90extern int sharefs_interpose(struct dentry *dentry, struct super_block *sb, 91 struct path *lower_path); 92extern int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, 93 const char *name, unsigned int flags, 94 struct path *path); 95extern int sharefs_parse_options(struct sharefs_sb_info *sbi, 96 const char *data); 97 98/* 99 * inode to private data 100 * 101 * Since we use containers and the struct inode is _inside_ the 102 * sharefs_inode_info structure, SHAREFS_I will always (given a non-NULL 103 * inode pointer), return a valid non-NULL pointer. 104 */ 105static inline struct sharefs_inode_info *SHAREFS_I(const struct inode *inode) 106{ 107 return container_of(inode, struct sharefs_inode_info, vfs_inode); 108} 109 110/* dentry to private data */ 111#define SHAREFS_D(dent) ((struct sharefs_dentry_info *)(dent)->d_fsdata) 112 113/* superblock to private data */ 114#define SHAREFS_SB(super) ((struct sharefs_sb_info *)(super)->s_fs_info) 115 116/* file to private Data */ 117#define SHAREFS_F(file) ((struct sharefs_file_info *)((file)->private_data)) 118 119/* file to lower file */ 120static inline struct file *sharefs_lower_file(const struct file *f) 121{ 122 return SHAREFS_F(f)->lower_file; 123} 124 125static inline void sharefs_set_lower_file(struct file *f, struct file *val) 126{ 127 SHAREFS_F(f)->lower_file = val; 128} 129 130/* inode to lower inode. */ 131static inline struct inode *sharefs_lower_inode(const struct inode *i) 132{ 133 return SHAREFS_I(i)->lower_inode; 134} 135 136static inline void sharefs_set_lower_inode(struct inode *i, struct inode *val) 137{ 138 SHAREFS_I(i)->lower_inode = val; 139} 140 141/* superblock to lower superblock */ 142static inline struct super_block *sharefs_lower_super( 143 const struct super_block *sb) 144{ 145 return SHAREFS_SB(sb)->lower_sb; 146} 147 148static inline void sharefs_set_lower_super(struct super_block *sb, 149 struct super_block *val) 150{ 151 SHAREFS_SB(sb)->lower_sb = val; 152} 153 154/* path based (dentry/mnt) macros */ 155static inline void pathcpy(struct path *dst, const struct path *src) 156{ 157 dst->dentry = src->dentry; 158 dst->mnt = src->mnt; 159} 160/* Returns struct path. Caller must path_put it. */ 161static inline void sharefs_get_lower_path(const struct dentry *dent, 162 struct path *lower_path) 163{ 164 spin_lock(&SHAREFS_D(dent)->lock); 165 pathcpy(lower_path, &SHAREFS_D(dent)->lower_path); 166 path_get(lower_path); 167 spin_unlock(&SHAREFS_D(dent)->lock); 168 return; 169} 170static inline void sharefs_put_lower_path(const struct dentry *dent, 171 struct path *lower_path) 172{ 173 path_put(lower_path); 174 return; 175} 176static inline void sharefs_set_lower_path(const struct dentry *dent, 177 struct path *lower_path) 178{ 179 spin_lock(&SHAREFS_D(dent)->lock); 180 pathcpy(&SHAREFS_D(dent)->lower_path, lower_path); 181 spin_unlock(&SHAREFS_D(dent)->lock); 182 return; 183} 184static inline void sharefs_reset_lower_path(const struct dentry *dent) 185{ 186 spin_lock(&SHAREFS_D(dent)->lock); 187 SHAREFS_D(dent)->lower_path.dentry = NULL; 188 SHAREFS_D(dent)->lower_path.mnt = NULL; 189 spin_unlock(&SHAREFS_D(dent)->lock); 190 return; 191} 192static inline void sharefs_put_reset_lower_path(const struct dentry *dent) 193{ 194 struct path lower_path; 195 spin_lock(&SHAREFS_D(dent)->lock); 196 pathcpy(&lower_path, &SHAREFS_D(dent)->lower_path); 197 SHAREFS_D(dent)->lower_path.dentry = NULL; 198 SHAREFS_D(dent)->lower_path.mnt = NULL; 199 spin_unlock(&SHAREFS_D(dent)->lock); 200 path_put(&lower_path); 201 return; 202} 203 204/* locking helpers */ 205static inline struct dentry *lock_parent(struct dentry *dentry) 206{ 207 struct dentry *dir = dget_parent(dentry); 208 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT); 209 return dir; 210} 211 212static inline void unlock_dir(struct dentry *dir) 213{ 214 inode_unlock(d_inode(dir)); 215 dput(dir); 216} 217 218static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len) 219{ 220 return !strncasecmp(s1, s2, len); 221} 222 223static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2) 224{ 225 return q1->len == q2->len && str_n_case_eq(q1->name, q2->name, q2->len); 226} 227/***************************************************************************** 228 * log print helpers 229 *****************************************************************************/ 230__printf(4, 5) void __sharefs_log(const char *level, const bool ratelimited, 231 const char *function, const char *fmt, ...); 232#define sharefs_err(fmt, ...) \ 233 __sharefs_log(KERN_ERR, false, __func__, fmt, ##__VA_ARGS__) 234#define sharefs_warning(fmt, ...) \ 235 __sharefs_log(KERN_WARNING, false, __func__, fmt, ##__VA_ARGS__) 236#define sharefs_info(fmt, ...) \ 237 __sharefs_log(KERN_INFO, false, __func__, fmt, ##__VA_ARGS__) 238#define sharefs_err_ratelimited(fmt, ...) \ 239 __sharefs_log(KERN_ERR, true, __func__, fmt, ##__VA_ARGS__) 240#define sharefs_warning_ratelimited(fmt, ...) \ 241 __sharefs_log(KERN_WARNING, true, __func__, fmt, ##__VA_ARGS__) 242#define sharefs_info_ratelimited(fmt, ...) \ 243 __sharefs_log(KERN_INFO, true, __func__, fmt, ##__VA_ARGS__) 244 245#endif /* not _SHAREFS_H_ */ 246