diff options
Diffstat (limited to 'fs/overlayfs/ovl_entry.h')
-rw-r--r-- | fs/overlayfs/ovl_entry.h | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h new file mode 100644 index 000000000..a479680a5 --- /dev/null +++ b/fs/overlayfs/ovl_entry.h @@ -0,0 +1,160 @@ +/* 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 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; +}; + +/* + * ovl_free_fs() relies on @mnt being the first member when unmounting + * the private mounts created for each layer. Let's check both the + * offset and type. + */ +static_assert(offsetof(struct ovl_layer, mnt) == 0); +static_assert(__same_type(typeof_member(struct ovl_layer, mnt), struct vfsmount *)); + +struct ovl_path { + const struct ovl_layer *layer; + struct dentry *dentry; +}; + +/* 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; + const struct ovl_layer *layers; + struct ovl_sb *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; + bool share_whiteout; + /* Traps in ovl inode cache */ + struct inode *workbasedir_trap; + struct inode *workdir_trap; + struct inode *indexdir_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; + /* Whiteout dentry cache */ + struct dentry *whiteout; + /* r/o snapshot of upperdir sb's only taken on volatile mounts */ + errseq_t errseq; +}; + +static inline struct vfsmount *ovl_upper_mnt(struct ovl_fs *ofs) +{ + return ofs->layers[0].mnt; +} + +static inline struct user_namespace *ovl_upper_mnt_userns(struct ovl_fs *ofs) +{ + return mnt_user_ns(ovl_upper_mnt(ofs)); +} + +static inline struct ovl_fs *OVL_FS(struct super_block *sb) +{ + return (struct ovl_fs *)sb->s_fs_info; +} + +static inline bool ovl_should_sync(struct ovl_fs *ofs) +{ + return !ofs->config.ovl_volatile; +} + +/* 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 ovl_path lowerpath; + + /* 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); +} |