|  | /* SPDX-License-Identifier: GPL-2.0-only */ | 
|  | /* | 
|  | * | 
|  | * Copyright (C) 2011 Novell Inc. | 
|  | * Copyright (C) 2016 Red Hat, Inc. | 
|  | */ | 
|  |  | 
|  | struct ovl_config { | 
|  | char *upperdir; | 
|  | char *workdir; | 
|  | char **lowerdirs; | 
|  | bool default_permissions; | 
|  | int redirect_mode; | 
|  | int verity_mode; | 
|  | bool index; | 
|  | int uuid; | 
|  | bool nfs_export; | 
|  | int xino; | 
|  | bool metacopy; | 
|  | bool userxattr; | 
|  | bool ovl_volatile; | 
|  | }; | 
|  |  | 
|  | struct ovl_sb { | 
|  | struct super_block *sb; | 
|  | dev_t pseudo_dev; | 
|  | /* Unusable (conflicting) uuid */ | 
|  | bool bad_uuid; | 
|  | /* Used as a lower layer (but maybe also as upper) */ | 
|  | bool is_lower; | 
|  | }; | 
|  |  | 
|  | struct ovl_layer { | 
|  | /* ovl_free_fs() relies on @mnt being the first member! */ | 
|  | 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; | 
|  | /* xwhiteouts were found on this layer */ | 
|  | bool has_xwhiteouts; | 
|  | }; | 
|  |  | 
|  | struct ovl_path { | 
|  | const struct ovl_layer *layer; | 
|  | struct dentry *dentry; | 
|  | }; | 
|  |  | 
|  | struct ovl_entry { | 
|  | unsigned int __numlower; | 
|  | struct ovl_path __lowerstack[] __counted_by(__numlower); | 
|  | }; | 
|  |  | 
|  | /* private information held for overlayfs's superblock */ | 
|  | struct ovl_fs { | 
|  | unsigned int numlayer; | 
|  | /* Number of unique fs among layers including upper fs */ | 
|  | unsigned int numfs; | 
|  | /* Number of data-only lower layers */ | 
|  | unsigned int numdatalayer; | 
|  | struct ovl_layer *layers; | 
|  | struct ovl_sb *fs; | 
|  | /* workbasedir is the path at workdir= mount option */ | 
|  | struct dentry *workbasedir; | 
|  | /* workdir is the 'work' or 'index' directory under workbasedir */ | 
|  | struct dentry *workdir; | 
|  | 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; | 
|  | bool nofh; | 
|  | /* Did we take the inuse lock? */ | 
|  | bool upperdir_locked; | 
|  | bool workdir_locked; | 
|  | /* Traps in ovl inode cache */ | 
|  | struct inode *workbasedir_trap; | 
|  | struct inode *workdir_trap; | 
|  | /* -1: disabled, 0: same fs, 1..32: number of unused ino bits */ | 
|  | int xino_mode; | 
|  | /* For allocation of non-persistent inode numbers */ | 
|  | atomic_long_t last_ino; | 
|  | /* Shared whiteout cache */ | 
|  | struct dentry *whiteout; | 
|  | bool no_shared_whiteout; | 
|  | struct mutex whiteout_lock; | 
|  | /* r/o snapshot of upperdir sb's only taken on volatile mounts */ | 
|  | errseq_t errseq; | 
|  | bool casefold; | 
|  | }; | 
|  |  | 
|  | /* Number of lower layers, not including data-only layers */ | 
|  | static inline unsigned int ovl_numlowerlayer(struct ovl_fs *ofs) | 
|  | { | 
|  | return ofs->numlayer - ofs->numdatalayer - 1; | 
|  | } | 
|  |  | 
|  | static inline struct vfsmount *ovl_upper_mnt(struct ovl_fs *ofs) | 
|  | { | 
|  | return ofs->layers[0].mnt; | 
|  | } | 
|  |  | 
|  | static inline struct mnt_idmap *ovl_upper_mnt_idmap(struct ovl_fs *ofs) | 
|  | { | 
|  | return mnt_idmap(ovl_upper_mnt(ofs)); | 
|  | } | 
|  |  | 
|  | extern struct file_system_type ovl_fs_type; | 
|  |  | 
|  | static inline struct ovl_fs *OVL_FS(struct super_block *sb) | 
|  | { | 
|  | if (IS_ENABLED(CONFIG_OVERLAY_FS_DEBUG)) | 
|  | WARN_ON_ONCE(sb->s_type != &ovl_fs_type); | 
|  |  | 
|  | return (struct ovl_fs *)sb->s_fs_info; | 
|  | } | 
|  |  | 
|  | static inline bool ovl_should_sync(struct ovl_fs *ofs) | 
|  | { | 
|  | return !ofs->config.ovl_volatile; | 
|  | } | 
|  |  | 
|  | static inline unsigned int ovl_numlower(struct ovl_entry *oe) | 
|  | { | 
|  | return oe ? oe->__numlower : 0; | 
|  | } | 
|  |  | 
|  | static inline struct ovl_path *ovl_lowerstack(struct ovl_entry *oe) | 
|  | { | 
|  | return ovl_numlower(oe) ? oe->__lowerstack : NULL; | 
|  | } | 
|  |  | 
|  | static inline struct ovl_path *ovl_lowerpath(struct ovl_entry *oe) | 
|  | { | 
|  | return ovl_lowerstack(oe); | 
|  | } | 
|  |  | 
|  | static inline struct ovl_path *ovl_lowerdata(struct ovl_entry *oe) | 
|  | { | 
|  | struct ovl_path *lowerstack = ovl_lowerstack(oe); | 
|  |  | 
|  | return lowerstack ? &lowerstack[oe->__numlower - 1] : NULL; | 
|  | } | 
|  |  | 
|  | /* May return NULL if lazy lookup of lowerdata is needed */ | 
|  | static inline struct dentry *ovl_lowerdata_dentry(struct ovl_entry *oe) | 
|  | { | 
|  | struct ovl_path *lowerdata = ovl_lowerdata(oe); | 
|  |  | 
|  | return lowerdata ? READ_ONCE(lowerdata->dentry) : NULL; | 
|  | } | 
|  |  | 
|  | /* private information held for every overlayfs dentry */ | 
|  | static inline unsigned long *OVL_E_FLAGS(struct dentry *dentry) | 
|  | { | 
|  | return (unsigned long *) &dentry->d_fsdata; | 
|  | } | 
|  |  | 
|  | struct ovl_inode { | 
|  | union { | 
|  | struct ovl_dir_cache *cache;	/* directory */ | 
|  | const char *lowerdata_redirect;	/* regular file */ | 
|  | }; | 
|  | const char *redirect; | 
|  | u64 version; | 
|  | unsigned long flags; | 
|  | struct inode vfs_inode; | 
|  | struct dentry *__upperdentry; | 
|  | struct ovl_entry *oe; | 
|  |  | 
|  | /* 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 ovl_entry *OVL_I_E(struct inode *inode) | 
|  | { | 
|  | return inode ? OVL_I(inode)->oe : NULL; | 
|  | } | 
|  |  | 
|  | static inline struct ovl_entry *OVL_E(struct dentry *dentry) | 
|  | { | 
|  | return OVL_I_E(d_inode(dentry)); | 
|  | } | 
|  |  | 
|  | static inline struct dentry *ovl_upperdentry_dereference(struct ovl_inode *oi) | 
|  | { | 
|  | return READ_ONCE(oi->__upperdentry); | 
|  | } |