| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * |
| * Copyright (C) 2011 Novell Inc. |
| * Copyright (C) 2016 Red Hat, Inc. |
| */ |
| |
| struct ovl_config { |
| char *lowerdir; |
| char *upperdir; |
| char *workdir; |
| bool default_permissions; |
| bool redirect_dir; |
| bool redirect_follow; |
| const char *redirect_mode; |
| bool index; |
| bool nfs_export; |
| int xino; |
| bool metacopy; |
| }; |
| |
| struct ovl_sb { |
| struct super_block *sb; |
| dev_t pseudo_dev; |
| /* Unusable (conflicting) uuid */ |
| bool bad_uuid; |
| }; |
| |
| struct ovl_layer { |
| struct vfsmount *mnt; |
| /* Trap in ovl inode cache */ |
| struct inode *trap; |
| struct ovl_sb *fs; |
| /* Index of this layer in fs root (upper idx == 0) */ |
| int idx; |
| /* One fsid per unique underlying sb (upper fsid == 0) */ |
| int fsid; |
| }; |
| |
| struct ovl_path { |
| struct ovl_layer *layer; |
| struct dentry *dentry; |
| }; |
| |
| /* private information held for overlayfs's superblock */ |
| struct ovl_fs { |
| struct vfsmount *upper_mnt; |
| unsigned int numlower; |
| /* Number of unique lower sb that differ from upper sb */ |
| unsigned int numlowerfs; |
| struct ovl_layer *lower_layers; |
| struct ovl_sb *lower_fs; |
| /* workbasedir is the path at workdir= mount option */ |
| struct dentry *workbasedir; |
| /* workdir is the 'work' directory under workbasedir */ |
| struct dentry *workdir; |
| /* index directory listing overlay inodes by origin file handle */ |
| struct dentry *indexdir; |
| long namelen; |
| /* pathnames of lower and upper dirs, for show_options */ |
| struct ovl_config config; |
| /* creds of process who forced instantiation of super block */ |
| const struct cred *creator_cred; |
| bool tmpfile; |
| bool noxattr; |
| /* Did we take the inuse lock? */ |
| bool upperdir_locked; |
| bool workdir_locked; |
| /* Traps in ovl inode cache */ |
| struct inode *upperdir_trap; |
| struct inode *workbasedir_trap; |
| struct inode *workdir_trap; |
| struct inode *indexdir_trap; |
| /* Inode numbers in all layers do not use the high xino_bits */ |
| unsigned int xino_bits; |
| }; |
| |
| /* private information held for every overlayfs dentry */ |
| struct ovl_entry { |
| union { |
| struct { |
| unsigned long flags; |
| }; |
| struct rcu_head rcu; |
| }; |
| unsigned numlower; |
| struct ovl_path lowerstack[]; |
| }; |
| |
| struct ovl_entry *ovl_alloc_entry(unsigned int numlower); |
| |
| static inline struct ovl_entry *OVL_E(struct dentry *dentry) |
| { |
| return (struct ovl_entry *) dentry->d_fsdata; |
| } |
| |
| struct ovl_inode { |
| union { |
| struct ovl_dir_cache *cache; /* directory */ |
| struct inode *lowerdata; /* regular file */ |
| }; |
| const char *redirect; |
| u64 version; |
| unsigned long flags; |
| struct inode vfs_inode; |
| struct dentry *__upperdentry; |
| struct inode *lower; |
| |
| /* synchronize copy up and more */ |
| struct mutex lock; |
| }; |
| |
| static inline struct ovl_inode *OVL_I(struct inode *inode) |
| { |
| return container_of(inode, struct ovl_inode, vfs_inode); |
| } |
| |
| static inline struct dentry *ovl_upperdentry_dereference(struct ovl_inode *oi) |
| { |
| return READ_ONCE(oi->__upperdentry); |
| } |