1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 2bbb1e54dSMiklos Szeredi /* 3bbb1e54dSMiklos Szeredi * 4bbb1e54dSMiklos Szeredi * Copyright (C) 2011 Novell Inc. 5bbb1e54dSMiklos Szeredi * Copyright (C) 2016 Red Hat, Inc. 6bbb1e54dSMiklos Szeredi */ 7bbb1e54dSMiklos Szeredi 8bbb1e54dSMiklos Szeredi struct ovl_config { 9bbb1e54dSMiklos Szeredi char *lowerdir; 10bbb1e54dSMiklos Szeredi char *upperdir; 11bbb1e54dSMiklos Szeredi char *workdir; 12bbb1e54dSMiklos Szeredi bool default_permissions; 13a6c60655SMiklos Szeredi bool redirect_dir; 14438c84c2SMiklos Szeredi bool redirect_follow; 15438c84c2SMiklos Szeredi const char *redirect_mode; 1602bcd157SAmir Goldstein bool index; 17f168f109SAmir Goldstein bool nfs_export; 18795939a9SAmir Goldstein int xino; 19d5791044SVivek Goyal bool metacopy; 20bbb1e54dSMiklos Szeredi }; 21bbb1e54dSMiklos Szeredi 225148626bSAmir Goldstein struct ovl_sb { 235148626bSAmir Goldstein struct super_block *sb; 245148626bSAmir Goldstein dev_t pseudo_dev; 257e63c87fSAmir Goldstein /* Unusable (conflicting) uuid */ 267e63c87fSAmir Goldstein bool bad_uuid; 275148626bSAmir Goldstein }; 285148626bSAmir Goldstein 29b9343632SChandan Rajendra struct ovl_layer { 30b9343632SChandan Rajendra struct vfsmount *mnt; 31146d62e5SAmir Goldstein /* Trap in ovl inode cache */ 32146d62e5SAmir Goldstein struct inode *trap; 335148626bSAmir Goldstein struct ovl_sb *fs; 345148626bSAmir Goldstein /* Index of this layer in fs root (upper idx == 0) */ 35d583ed7dSAmir Goldstein int idx; 365148626bSAmir Goldstein /* One fsid per unique underlying sb (upper fsid == 0) */ 375148626bSAmir Goldstein int fsid; 38b9343632SChandan Rajendra }; 39b9343632SChandan Rajendra 40b9343632SChandan Rajendra struct ovl_path { 41b9343632SChandan Rajendra struct ovl_layer *layer; 42b9343632SChandan Rajendra struct dentry *dentry; 43b9343632SChandan Rajendra }; 44b9343632SChandan Rajendra 45bbb1e54dSMiklos Szeredi /* private information held for overlayfs's superblock */ 46bbb1e54dSMiklos Szeredi struct ovl_fs { 47bbb1e54dSMiklos Szeredi struct vfsmount *upper_mnt; 4894375f9dSAmir Goldstein unsigned int numlayer; 495148626bSAmir Goldstein /* Number of unique lower sb that differ from upper sb */ 505148626bSAmir Goldstein unsigned int numlowerfs; 5194375f9dSAmir Goldstein struct ovl_layer *layers; 525148626bSAmir Goldstein struct ovl_sb *lower_fs; 532cac0c00SAmir Goldstein /* workbasedir is the path at workdir= mount option */ 542cac0c00SAmir Goldstein struct dentry *workbasedir; 552cac0c00SAmir Goldstein /* workdir is the 'work' directory under workbasedir */ 56bbb1e54dSMiklos Szeredi struct dentry *workdir; 5702bcd157SAmir Goldstein /* index directory listing overlay inodes by origin file handle */ 5802bcd157SAmir Goldstein struct dentry *indexdir; 596b2d5fe4SMiklos Szeredi long namelen; 60bbb1e54dSMiklos Szeredi /* pathnames of lower and upper dirs, for show_options */ 61bbb1e54dSMiklos Szeredi struct ovl_config config; 62bbb1e54dSMiklos Szeredi /* creds of process who forced instantiation of super block */ 63bbb1e54dSMiklos Szeredi const struct cred *creator_cred; 64e7f52429SAmir Goldstein bool tmpfile; 6582b749b2SAmir Goldstein bool noxattr; 6685fdee1eSAmir Goldstein /* Did we take the inuse lock? */ 6785fdee1eSAmir Goldstein bool upperdir_locked; 6885fdee1eSAmir Goldstein bool workdir_locked; 69146d62e5SAmir Goldstein /* Traps in ovl inode cache */ 70146d62e5SAmir Goldstein struct inode *upperdir_trap; 710be0bfd2SAmir Goldstein struct inode *workbasedir_trap; 72146d62e5SAmir Goldstein struct inode *workdir_trap; 73146d62e5SAmir Goldstein struct inode *indexdir_trap; 740f831ec8SAmir Goldstein /* -1: disabled, 0: same fs, 1..32: number of unused ino bits */ 750f831ec8SAmir Goldstein int xino_mode; 76bbb1e54dSMiklos Szeredi }; 77bbb1e54dSMiklos Szeredi 780f831ec8SAmir Goldstein static inline struct ovl_fs *OVL_FS(struct super_block *sb) 790f831ec8SAmir Goldstein { 800f831ec8SAmir Goldstein return (struct ovl_fs *)sb->s_fs_info; 810f831ec8SAmir Goldstein } 820f831ec8SAmir Goldstein 83bbb1e54dSMiklos Szeredi /* private information held for every overlayfs dentry */ 84bbb1e54dSMiklos Szeredi struct ovl_entry { 85bbb1e54dSMiklos Szeredi union { 8655acc661SMiklos Szeredi struct { 87c62520a8SAmir Goldstein unsigned long flags; 8855acc661SMiklos Szeredi }; 89bbb1e54dSMiklos Szeredi struct rcu_head rcu; 90bbb1e54dSMiklos Szeredi }; 91bbb1e54dSMiklos Szeredi unsigned numlower; 92b9343632SChandan Rajendra struct ovl_path lowerstack[]; 93bbb1e54dSMiklos Szeredi }; 94bbb1e54dSMiklos Szeredi 95bbb1e54dSMiklos Szeredi struct ovl_entry *ovl_alloc_entry(unsigned int numlower); 96bbb1e54dSMiklos Szeredi 97c62520a8SAmir Goldstein static inline struct ovl_entry *OVL_E(struct dentry *dentry) 98c62520a8SAmir Goldstein { 99c62520a8SAmir Goldstein return (struct ovl_entry *) dentry->d_fsdata; 100c62520a8SAmir Goldstein } 101c62520a8SAmir Goldstein 10213cf199dSAmir Goldstein struct ovl_inode { 1032664bd08SVivek Goyal union { 1042664bd08SVivek Goyal struct ovl_dir_cache *cache; /* directory */ 1052664bd08SVivek Goyal struct inode *lowerdata; /* regular file */ 1062664bd08SVivek Goyal }; 107cf31c463SMiklos Szeredi const char *redirect; 10804a01ac7SMiklos Szeredi u64 version; 10913c72075SMiklos Szeredi unsigned long flags; 11013cf199dSAmir Goldstein struct inode vfs_inode; 11109d8b586SMiklos Szeredi struct dentry *__upperdentry; 11225b7713aSMiklos Szeredi struct inode *lower; 113a015dafcSAmir Goldstein 114a015dafcSAmir Goldstein /* synchronize copy up and more */ 115a015dafcSAmir Goldstein struct mutex lock; 11613cf199dSAmir Goldstein }; 11713cf199dSAmir Goldstein 11813cf199dSAmir Goldstein static inline struct ovl_inode *OVL_I(struct inode *inode) 11913cf199dSAmir Goldstein { 12013cf199dSAmir Goldstein return container_of(inode, struct ovl_inode, vfs_inode); 12113cf199dSAmir Goldstein } 12209d8b586SMiklos Szeredi 12309d8b586SMiklos Szeredi static inline struct dentry *ovl_upperdentry_dereference(struct ovl_inode *oi) 12409d8b586SMiklos Szeredi { 125506458efSWill Deacon return READ_ONCE(oi->__upperdentry); 12609d8b586SMiklos Szeredi } 127