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