xref: /linux/fs/overlayfs/overlayfs.h (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2e9be9d5eSMiklos Szeredi /*
3e9be9d5eSMiklos Szeredi  *
4e9be9d5eSMiklos Szeredi  * Copyright (C) 2011 Novell Inc.
5e9be9d5eSMiklos Szeredi  */
6e9be9d5eSMiklos Szeredi 
7e9be9d5eSMiklos Szeredi #include <linux/kernel.h>
83a1e819bSAmir Goldstein #include <linux/uuid.h>
946e5d0a3SMiklos Szeredi #include <linux/fs.h>
10bf070890SAlexander Larsson #include <linux/fsverity.h>
1122f289ceSChristian Brauner #include <linux/namei.h>
120e641857SChristian Brauner #include <linux/posix_acl.h>
130e641857SChristian Brauner #include <linux/posix_acl_xattr.h>
14ee023c30SAmir Goldstein #include "ovl_entry.h"
15e9be9d5eSMiklos Szeredi 
161bd0a3aeSlijiazi #undef pr_fmt
171bd0a3aeSlijiazi #define pr_fmt(fmt) "overlayfs: " fmt
181bd0a3aeSlijiazi 
19e9be9d5eSMiklos Szeredi enum ovl_path_type {
2038e813dbSMiklos Szeredi 	__OVL_PATH_UPPER	= (1 << 0),
2138e813dbSMiklos Szeredi 	__OVL_PATH_MERGE	= (1 << 1),
2259548503SAmir Goldstein 	__OVL_PATH_ORIGIN	= (1 << 2),
23e9be9d5eSMiklos Szeredi };
24e9be9d5eSMiklos Szeredi 
251afaba1eSMiklos Szeredi #define OVL_TYPE_UPPER(type)	((type) & __OVL_PATH_UPPER)
261afaba1eSMiklos Szeredi #define OVL_TYPE_MERGE(type)	((type) & __OVL_PATH_MERGE)
2759548503SAmir Goldstein #define OVL_TYPE_ORIGIN(type)	((type) & __OVL_PATH_ORIGIN)
28d837a49bSMiklos Szeredi 
292d2f2d73SMiklos Szeredi #define OVL_XATTR_NAMESPACE "overlay."
302d2f2d73SMiklos Szeredi #define OVL_XATTR_TRUSTED_PREFIX XATTR_TRUSTED_PREFIX OVL_XATTR_NAMESPACE
31d431e652SAlexander Larsson #define OVL_XATTR_TRUSTED_PREFIX_LEN (sizeof(OVL_XATTR_TRUSTED_PREFIX) - 1)
322d2f2d73SMiklos Szeredi #define OVL_XATTR_USER_PREFIX XATTR_USER_PREFIX OVL_XATTR_NAMESPACE
33d431e652SAlexander Larsson #define OVL_XATTR_USER_PREFIX_LEN (sizeof(OVL_XATTR_USER_PREFIX) - 1)
3443d193f8SMiklos Szeredi 
35dad02fadSAlexander Larsson #define OVL_XATTR_ESCAPE_PREFIX OVL_XATTR_NAMESPACE
36dad02fadSAlexander Larsson #define OVL_XATTR_ESCAPE_PREFIX_LEN (sizeof(OVL_XATTR_ESCAPE_PREFIX) - 1)
37dad02fadSAlexander Larsson #define OVL_XATTR_ESCAPE_TRUSTED_PREFIX OVL_XATTR_TRUSTED_PREFIX OVL_XATTR_ESCAPE_PREFIX
38dad02fadSAlexander Larsson #define OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN (sizeof(OVL_XATTR_ESCAPE_TRUSTED_PREFIX) - 1)
39dad02fadSAlexander Larsson #define OVL_XATTR_ESCAPE_USER_PREFIX OVL_XATTR_USER_PREFIX OVL_XATTR_ESCAPE_PREFIX
40dad02fadSAlexander Larsson #define OVL_XATTR_ESCAPE_USER_PREFIX_LEN (sizeof(OVL_XATTR_ESCAPE_USER_PREFIX) - 1)
41dad02fadSAlexander Larsson 
4243d193f8SMiklos Szeredi enum ovl_xattr {
4343d193f8SMiklos Szeredi 	OVL_XATTR_OPAQUE,
4443d193f8SMiklos Szeredi 	OVL_XATTR_REDIRECT,
4543d193f8SMiklos Szeredi 	OVL_XATTR_ORIGIN,
4643d193f8SMiklos Szeredi 	OVL_XATTR_IMPURE,
4743d193f8SMiklos Szeredi 	OVL_XATTR_NLINK,
4843d193f8SMiklos Szeredi 	OVL_XATTR_UPPER,
49d9544c1bSAmir Goldstein 	OVL_XATTR_UUID,
5043d193f8SMiklos Szeredi 	OVL_XATTR_METACOPY,
51096a218aSAmir Goldstein 	OVL_XATTR_PROTATTR,
52bc8df7a3SAlexander Larsson 	OVL_XATTR_XWHITEOUT,
5343d193f8SMiklos Szeredi };
543a1e819bSAmir Goldstein 
55c62520a8SAmir Goldstein enum ovl_inode_flag {
56b79e05aaSAmir Goldstein 	/* Pure upper dir that may contain non pure upper entries */
5713c72075SMiklos Szeredi 	OVL_IMPURE,
58b79e05aaSAmir Goldstein 	/* Non-merge dir that may contain whiteout entries */
59b79e05aaSAmir Goldstein 	OVL_WHITEOUTS,
60359f392cSAmir Goldstein 	OVL_INDEX,
610c288874SVivek Goyal 	OVL_UPPERDATA,
62a00c2d59SVivek Goyal 	/* Inode number will remain constant over copy up. */
63a00c2d59SVivek Goyal 	OVL_CONST_INO,
64184996e9SAlexander Larsson 	OVL_HAS_DIGEST,
65184996e9SAlexander Larsson 	OVL_VERIFIED_DIGEST,
6613c72075SMiklos Szeredi };
6713c72075SMiklos Szeredi 
68c62520a8SAmir Goldstein enum ovl_entry_flag {
69c62520a8SAmir Goldstein 	OVL_E_UPPER_ALIAS,
70c62520a8SAmir Goldstein 	OVL_E_OPAQUE,
712ca3c148SAmir Goldstein 	OVL_E_CONNECTED,
72420332b9SAmir Goldstein 	/* Lower stack may contain xwhiteout entries */
73420332b9SAmir Goldstein 	OVL_E_XWHITEOUTS,
74c62520a8SAmir Goldstein };
75c62520a8SAmir Goldstein 
76926e94d7SAmir Goldstein enum {
77af5f2396SAmir Goldstein 	OVL_REDIRECT_OFF,	/* "off" mode is never used. In effect	*/
78af5f2396SAmir Goldstein 	OVL_REDIRECT_FOLLOW,	/* ...it translates to either "follow"	*/
79af5f2396SAmir Goldstein 	OVL_REDIRECT_NOFOLLOW,	/* ...or "nofollow".			*/
80af5f2396SAmir Goldstein 	OVL_REDIRECT_ON,
81af5f2396SAmir Goldstein };
82af5f2396SAmir Goldstein 
83af5f2396SAmir Goldstein enum {
84b0504bfeSAmir Goldstein 	OVL_UUID_OFF,
85b0504bfeSAmir Goldstein 	OVL_UUID_NULL,
86cbb44f09SAmir Goldstein 	OVL_UUID_AUTO,
87b0504bfeSAmir Goldstein 	OVL_UUID_ON,
88b0504bfeSAmir Goldstein };
89b0504bfeSAmir Goldstein 
90b0504bfeSAmir Goldstein enum {
91926e94d7SAmir Goldstein 	OVL_XINO_OFF,
92926e94d7SAmir Goldstein 	OVL_XINO_AUTO,
93926e94d7SAmir Goldstein 	OVL_XINO_ON,
94926e94d7SAmir Goldstein };
95926e94d7SAmir Goldstein 
96ae8cba40SAlexander Larsson enum {
97ae8cba40SAlexander Larsson 	OVL_VERITY_OFF,
98ae8cba40SAlexander Larsson 	OVL_VERITY_ON,
99ae8cba40SAlexander Larsson 	OVL_VERITY_REQUIRE,
100ae8cba40SAlexander Larsson };
101ae8cba40SAlexander Larsson 
1023a1e819bSAmir Goldstein /*
1033a1e819bSAmir Goldstein  * The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
1043a1e819bSAmir Goldstein  * where:
1053a1e819bSAmir Goldstein  * origin.fh	- exported file handle of the lower file
1063a1e819bSAmir Goldstein  * origin.uuid	- uuid of the lower filesystem
1073a1e819bSAmir Goldstein  */
1083a1e819bSAmir Goldstein #define OVL_FH_VERSION	0
1093a1e819bSAmir Goldstein #define OVL_FH_MAGIC	0xfb
1103a1e819bSAmir Goldstein 
1113a1e819bSAmir Goldstein /* CPU byte order required for fid decoding:  */
1123a1e819bSAmir Goldstein #define OVL_FH_FLAG_BIG_ENDIAN	(1 << 0)
1133a1e819bSAmir Goldstein #define OVL_FH_FLAG_ANY_ENDIAN	(1 << 1)
11454fb347eSAmir Goldstein /* Is the real inode encoded in fid an upper inode? */
11554fb347eSAmir Goldstein #define OVL_FH_FLAG_PATH_UPPER	(1 << 2)
1163a1e819bSAmir Goldstein 
117961af647SAmir Goldstein #define OVL_FH_FLAG_ALL (OVL_FH_FLAG_BIG_ENDIAN | OVL_FH_FLAG_ANY_ENDIAN | \
118961af647SAmir Goldstein 			 OVL_FH_FLAG_PATH_UPPER)
1193a1e819bSAmir Goldstein 
1203a1e819bSAmir Goldstein #if defined(__LITTLE_ENDIAN)
1213a1e819bSAmir Goldstein #define OVL_FH_FLAG_CPU_ENDIAN 0
1223a1e819bSAmir Goldstein #elif defined(__BIG_ENDIAN)
1233a1e819bSAmir Goldstein #define OVL_FH_FLAG_CPU_ENDIAN OVL_FH_FLAG_BIG_ENDIAN
1243a1e819bSAmir Goldstein #else
1253a1e819bSAmir Goldstein #error Endianness not defined
1263a1e819bSAmir Goldstein #endif
1273a1e819bSAmir Goldstein 
128cbe7fba8SAmir Goldstein /* The type used to be returned by overlay exportfs for misaligned fid */
129cbe7fba8SAmir Goldstein #define OVL_FILEID_V0	0xfb
130cbe7fba8SAmir Goldstein /* The type returned by overlay exportfs for 32bit aligned fid */
131cbe7fba8SAmir Goldstein #define OVL_FILEID_V1	0xf8
1328ed5eec9SAmir Goldstein 
133cbe7fba8SAmir Goldstein /* On-disk format for "origin" file handle */
134cbe7fba8SAmir Goldstein struct ovl_fb {
1353a1e819bSAmir Goldstein 	u8 version;	/* 0 */
1363a1e819bSAmir Goldstein 	u8 magic;	/* 0xfb */
1373a1e819bSAmir Goldstein 	u8 len;		/* size of this header + size of fid */
1383a1e819bSAmir Goldstein 	u8 flags;	/* OVL_FH_FLAG_* */
1393a1e819bSAmir Goldstein 	u8 type;	/* fid_type of fid */
14001633fd2SChristoph Hellwig 	uuid_t uuid;	/* uuid of filesystem */
1410efbe7c4SGustavo A. R. Silva 	u32 fid[];	/* file identifier should be 32bit aligned in-memory */
1423a1e819bSAmir Goldstein } __packed;
143e9be9d5eSMiklos Szeredi 
144cbe7fba8SAmir Goldstein /* In-memory and on-wire format for overlay file handle */
145cbe7fba8SAmir Goldstein struct ovl_fh {
146cbe7fba8SAmir Goldstein 	u8 padding[3];	/* make sure fb.fid is 32bit aligned */
147cbe7fba8SAmir Goldstein 	union {
148cbe7fba8SAmir Goldstein 		struct ovl_fb fb;
149cf8aa9bfSKees Cook 		DECLARE_FLEX_ARRAY(u8, buf);
150cbe7fba8SAmir Goldstein 	};
151cbe7fba8SAmir Goldstein } __packed;
152cbe7fba8SAmir Goldstein 
153cbe7fba8SAmir Goldstein #define OVL_FH_WIRE_OFFSET	offsetof(struct ovl_fh, fb)
154cbe7fba8SAmir Goldstein #define OVL_FH_LEN(fh)		(OVL_FH_WIRE_OFFSET + (fh)->fb.len)
155cbe7fba8SAmir Goldstein #define OVL_FH_FID_OFFSET	(OVL_FH_WIRE_OFFSET + \
156cbe7fba8SAmir Goldstein 				 offsetof(struct ovl_fb, fid))
157cbe7fba8SAmir Goldstein 
158bf070890SAlexander Larsson /* On-disk format for "metacopy" xattr (if non-zero size) */
159bf070890SAlexander Larsson struct ovl_metacopy {
160bf070890SAlexander Larsson 	u8 version;	/* 0 */
161bf070890SAlexander Larsson 	u8 len;         /* size of this header + used digest bytes */
162bf070890SAlexander Larsson 	u8 flags;
163bf070890SAlexander Larsson 	u8 digest_algo;	/* FS_VERITY_HASH_ALG_* constant, 0 for no digest */
164bf070890SAlexander Larsson 	u8 digest[FS_VERITY_MAX_DIGEST_SIZE];  /* Only the used part on disk */
165bf070890SAlexander Larsson } __packed;
166bf070890SAlexander Larsson 
167bf070890SAlexander Larsson #define OVL_METACOPY_MAX_SIZE (sizeof(struct ovl_metacopy))
168bf070890SAlexander Larsson #define OVL_METACOPY_MIN_SIZE (OVL_METACOPY_MAX_SIZE - FS_VERITY_MAX_DIGEST_SIZE)
169bf070890SAlexander Larsson #define OVL_METACOPY_INIT { 0, OVL_METACOPY_MIN_SIZE }
170bf070890SAlexander Larsson 
171bf070890SAlexander Larsson static inline int ovl_metadata_digest_size(const struct ovl_metacopy *metacopy)
172bf070890SAlexander Larsson {
173bf070890SAlexander Larsson 	if (metacopy->len < OVL_METACOPY_MIN_SIZE)
174bf070890SAlexander Larsson 		return 0;
175bf070890SAlexander Larsson 	return (int)metacopy->len - OVL_METACOPY_MIN_SIZE;
176bf070890SAlexander Larsson }
177bf070890SAlexander Larsson 
178*9a87907dSMiklos Szeredi /* No atime modification on underlying */
179*9a87907dSMiklos Szeredi #define OVL_OPEN_FLAGS (O_NOATIME)
180*9a87907dSMiklos Szeredi 
1812d2f2d73SMiklos Szeredi extern const char *const ovl_xattr_table[][2];
18243d193f8SMiklos Szeredi static inline const char *ovl_xattr(struct ovl_fs *ofs, enum ovl_xattr ox)
18343d193f8SMiklos Szeredi {
1842d2f2d73SMiklos Szeredi 	return ovl_xattr_table[ox][ofs->config.userxattr];
18543d193f8SMiklos Szeredi }
18643d193f8SMiklos Szeredi 
187a15506eaSChristian Brauner /*
188a15506eaSChristian Brauner  * When changing ownership of an upper object map the intended ownership
189a15506eaSChristian Brauner  * according to the upper layer's idmapping. When an upper mount idmaps files
190a15506eaSChristian Brauner  * that are stored on-disk as owned by id 1001 to id 1000 this means stat on
191a15506eaSChristian Brauner  * this object will report it as being owned by id 1000 when calling stat via
192a15506eaSChristian Brauner  * the upper mount.
193a15506eaSChristian Brauner  * In order to change ownership of an object so stat reports id 1000 when
194a15506eaSChristian Brauner  * called on an idmapped upper mount the value written to disk - i.e., the
195a15506eaSChristian Brauner  * value stored in ia_*id - must 1001. The mount mapping helper will thus take
196a15506eaSChristian Brauner  * care to map 1000 to 1001.
197a15506eaSChristian Brauner  * The mnt idmapping helpers are nops if the upper layer isn't idmapped.
198a15506eaSChristian Brauner  */
199a15506eaSChristian Brauner static inline int ovl_do_notify_change(struct ovl_fs *ofs,
200a15506eaSChristian Brauner 				       struct dentry *upperdentry,
201a15506eaSChristian Brauner 				       struct iattr *attr)
202a15506eaSChristian Brauner {
203abf08576SChristian Brauner 	return notify_change(ovl_upper_mnt_idmap(ofs), upperdentry, attr, NULL);
204a15506eaSChristian Brauner }
205a15506eaSChristian Brauner 
206576bb263SChristian Brauner static inline int ovl_do_rmdir(struct ovl_fs *ofs,
207576bb263SChristian Brauner 			       struct inode *dir, struct dentry *dentry)
208e9be9d5eSMiklos Szeredi {
209abf08576SChristian Brauner 	int err = vfs_rmdir(ovl_upper_mnt_idmap(ofs), dir, dentry);
2106cf00764SAmir Goldstein 
211e9be9d5eSMiklos Szeredi 	pr_debug("rmdir(%pd2) = %i\n", dentry, err);
212e9be9d5eSMiklos Szeredi 	return err;
213e9be9d5eSMiklos Szeredi }
214e9be9d5eSMiklos Szeredi 
215576bb263SChristian Brauner static inline int ovl_do_unlink(struct ovl_fs *ofs, struct inode *dir,
216576bb263SChristian Brauner 				struct dentry *dentry)
217e9be9d5eSMiklos Szeredi {
218abf08576SChristian Brauner 	int err = vfs_unlink(ovl_upper_mnt_idmap(ofs), dir, dentry, NULL);
2196cf00764SAmir Goldstein 
220e9be9d5eSMiklos Szeredi 	pr_debug("unlink(%pd2) = %i\n", dentry, err);
221e9be9d5eSMiklos Szeredi 	return err;
222e9be9d5eSMiklos Szeredi }
223e9be9d5eSMiklos Szeredi 
224576bb263SChristian Brauner static inline int ovl_do_link(struct ovl_fs *ofs, struct dentry *old_dentry,
225576bb263SChristian Brauner 			      struct inode *dir, struct dentry *new_dentry)
226e9be9d5eSMiklos Szeredi {
227abf08576SChristian Brauner 	int err = vfs_link(old_dentry, ovl_upper_mnt_idmap(ofs), dir,
228abf08576SChristian Brauner 			   new_dentry, NULL);
2296cf00764SAmir Goldstein 
2306cf00764SAmir Goldstein 	pr_debug("link(%pd2, %pd2) = %i\n", old_dentry, new_dentry, err);
231e9be9d5eSMiklos Szeredi 	return err;
232e9be9d5eSMiklos Szeredi }
233e9be9d5eSMiklos Szeredi 
234576bb263SChristian Brauner static inline int ovl_do_create(struct ovl_fs *ofs,
235576bb263SChristian Brauner 				struct inode *dir, struct dentry *dentry,
2366cf00764SAmir Goldstein 				umode_t mode)
237e9be9d5eSMiklos Szeredi {
238abf08576SChristian Brauner 	int err = vfs_create(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, true);
2396cf00764SAmir Goldstein 
240e9be9d5eSMiklos Szeredi 	pr_debug("create(%pd2, 0%o) = %i\n", dentry, mode, err);
241e9be9d5eSMiklos Szeredi 	return err;
242e9be9d5eSMiklos Szeredi }
243e9be9d5eSMiklos Szeredi 
244576bb263SChristian Brauner static inline int ovl_do_mkdir(struct ovl_fs *ofs,
245576bb263SChristian Brauner 			       struct inode *dir, struct dentry *dentry,
2466cf00764SAmir Goldstein 			       umode_t mode)
247e9be9d5eSMiklos Szeredi {
248abf08576SChristian Brauner 	int err = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode);
249e9be9d5eSMiklos Szeredi 	pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, err);
250e9be9d5eSMiklos Szeredi 	return err;
251e9be9d5eSMiklos Szeredi }
252e9be9d5eSMiklos Szeredi 
253576bb263SChristian Brauner static inline int ovl_do_mknod(struct ovl_fs *ofs,
254576bb263SChristian Brauner 			       struct inode *dir, struct dentry *dentry,
2556cf00764SAmir Goldstein 			       umode_t mode, dev_t dev)
256e9be9d5eSMiklos Szeredi {
257abf08576SChristian Brauner 	int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev);
2586cf00764SAmir Goldstein 
2596cf00764SAmir Goldstein 	pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err);
260e9be9d5eSMiklos Szeredi 	return err;
261e9be9d5eSMiklos Szeredi }
262e9be9d5eSMiklos Szeredi 
263576bb263SChristian Brauner static inline int ovl_do_symlink(struct ovl_fs *ofs,
264576bb263SChristian Brauner 				 struct inode *dir, struct dentry *dentry,
2656cf00764SAmir Goldstein 				 const char *oldname)
266e9be9d5eSMiklos Szeredi {
267abf08576SChristian Brauner 	int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname);
2686cf00764SAmir Goldstein 
269e9be9d5eSMiklos Szeredi 	pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err);
270e9be9d5eSMiklos Szeredi 	return err;
271e9be9d5eSMiklos Szeredi }
272e9be9d5eSMiklos Szeredi 
2732d343087SAl Viro static inline ssize_t ovl_do_getxattr(const struct path *path, const char *name,
274dad7017aSChristian Brauner 				      void *value, size_t size)
275d5dc7486SMiklos Szeredi {
276dad7017aSChristian Brauner 	int err, len;
277dad7017aSChristian Brauner 
278dad7017aSChristian Brauner 	WARN_ON(path->dentry->d_sb != path->mnt->mnt_sb);
279dad7017aSChristian Brauner 
2804609e1f1SChristian Brauner 	err = vfs_getxattr(mnt_idmap(path->mnt), path->dentry,
281dad7017aSChristian Brauner 			       name, value, size);
282dad7017aSChristian Brauner 	len = (value && err > 0) ? err : 0;
2835e717c6fSAmir Goldstein 
2845e717c6fSAmir Goldstein 	pr_debug("getxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n",
285dad7017aSChristian Brauner 		 path->dentry, name, min(len, 48), value, size, err);
2865e717c6fSAmir Goldstein 	return err;
287d5dc7486SMiklos Szeredi }
288d5dc7486SMiklos Szeredi 
289dad7017aSChristian Brauner static inline ssize_t ovl_getxattr_upper(struct ovl_fs *ofs,
290dad7017aSChristian Brauner 					 struct dentry *upperdentry,
291c914c0e2SAmir Goldstein 					 enum ovl_xattr ox, void *value,
292610afc0bSMiklos Szeredi 					 size_t size)
293e9be9d5eSMiklos Szeredi {
294dad7017aSChristian Brauner 	struct path upperpath = {
295dad7017aSChristian Brauner 		.dentry = upperdentry,
296dad7017aSChristian Brauner 		.mnt = ovl_upper_mnt(ofs),
297dad7017aSChristian Brauner 	};
298dad7017aSChristian Brauner 
299dad7017aSChristian Brauner 	return ovl_do_getxattr(&upperpath, ovl_xattr(ofs, ox), value, size);
300dad7017aSChristian Brauner }
301dad7017aSChristian Brauner 
302dad7017aSChristian Brauner static inline ssize_t ovl_path_getxattr(struct ovl_fs *ofs,
3032d343087SAl Viro 					 const struct path *path,
304dad7017aSChristian Brauner 					 enum ovl_xattr ox, void *value,
305dad7017aSChristian Brauner 					 size_t size)
306dad7017aSChristian Brauner {
307dad7017aSChristian Brauner 	return ovl_do_getxattr(path, ovl_xattr(ofs, ox), value, size);
308c914c0e2SAmir Goldstein }
309c914c0e2SAmir Goldstein 
310c914c0e2SAmir Goldstein static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
311c914c0e2SAmir Goldstein 				  const char *name, const void *value,
312c914c0e2SAmir Goldstein 				  size_t size, int flags)
313c914c0e2SAmir Goldstein {
3144609e1f1SChristian Brauner 	int err = vfs_setxattr(ovl_upper_mnt_idmap(ofs), dentry, name,
3156344e669SChristian Brauner 			       value, size, flags);
316c914c0e2SAmir Goldstein 
317c914c0e2SAmir Goldstein 	pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n",
318c914c0e2SAmir Goldstein 		 dentry, name, min((int)size, 48), value, size, flags, err);
319e9be9d5eSMiklos Szeredi 	return err;
320e9be9d5eSMiklos Szeredi }
321e9be9d5eSMiklos Szeredi 
322c914c0e2SAmir Goldstein static inline int ovl_setxattr(struct ovl_fs *ofs, struct dentry *dentry,
323c914c0e2SAmir Goldstein 			       enum ovl_xattr ox, const void *value,
324c914c0e2SAmir Goldstein 			       size_t size)
325e9be9d5eSMiklos Szeredi {
326c914c0e2SAmir Goldstein 	return ovl_do_setxattr(ofs, dentry, ovl_xattr(ofs, ox), value, size, 0);
327c914c0e2SAmir Goldstein }
328c914c0e2SAmir Goldstein 
329c914c0e2SAmir Goldstein static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
330c914c0e2SAmir Goldstein 				     const char *name)
331c914c0e2SAmir Goldstein {
3324609e1f1SChristian Brauner 	int err = vfs_removexattr(ovl_upper_mnt_idmap(ofs), dentry, name);
333e9be9d5eSMiklos Szeredi 	pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err);
334e9be9d5eSMiklos Szeredi 	return err;
335e9be9d5eSMiklos Szeredi }
336e9be9d5eSMiklos Szeredi 
337c914c0e2SAmir Goldstein static inline int ovl_removexattr(struct ovl_fs *ofs, struct dentry *dentry,
338c914c0e2SAmir Goldstein 				  enum ovl_xattr ox)
339c914c0e2SAmir Goldstein {
340c914c0e2SAmir Goldstein 	return ovl_do_removexattr(ofs, dentry, ovl_xattr(ofs, ox));
341c914c0e2SAmir Goldstein }
342c914c0e2SAmir Goldstein 
3430e641857SChristian Brauner static inline int ovl_do_set_acl(struct ovl_fs *ofs, struct dentry *dentry,
3440e641857SChristian Brauner 				 const char *acl_name, struct posix_acl *acl)
3450e641857SChristian Brauner {
34613e83a49SChristian Brauner 	return vfs_set_acl(ovl_upper_mnt_idmap(ofs), dentry, acl_name, acl);
3470e641857SChristian Brauner }
3480e641857SChristian Brauner 
3490e641857SChristian Brauner static inline int ovl_do_remove_acl(struct ovl_fs *ofs, struct dentry *dentry,
3500e641857SChristian Brauner 				    const char *acl_name)
3510e641857SChristian Brauner {
35213e83a49SChristian Brauner 	return vfs_remove_acl(ovl_upper_mnt_idmap(ofs), dentry, acl_name);
3530e641857SChristian Brauner }
3540e641857SChristian Brauner 
355576bb263SChristian Brauner static inline int ovl_do_rename(struct ovl_fs *ofs, struct inode *olddir,
356576bb263SChristian Brauner 				struct dentry *olddentry, struct inode *newdir,
357576bb263SChristian Brauner 				struct dentry *newdentry, unsigned int flags)
358e9be9d5eSMiklos Szeredi {
359e9be9d5eSMiklos Szeredi 	int err;
3609fe61450SChristian Brauner 	struct renamedata rd = {
361abf08576SChristian Brauner 		.old_mnt_idmap	= ovl_upper_mnt_idmap(ofs),
3629fe61450SChristian Brauner 		.old_dir 	= olddir,
3639fe61450SChristian Brauner 		.old_dentry 	= olddentry,
364abf08576SChristian Brauner 		.new_mnt_idmap	= ovl_upper_mnt_idmap(ofs),
3659fe61450SChristian Brauner 		.new_dir 	= newdir,
3669fe61450SChristian Brauner 		.new_dentry 	= newdentry,
3679fe61450SChristian Brauner 		.flags 		= flags,
3689fe61450SChristian Brauner 	};
369e9be9d5eSMiklos Szeredi 
3706cf00764SAmir Goldstein 	pr_debug("rename(%pd2, %pd2, 0x%x)\n", olddentry, newdentry, flags);
3719fe61450SChristian Brauner 	err = vfs_rename(&rd);
372e9be9d5eSMiklos Szeredi 	if (err) {
3732773bf00SMiklos Szeredi 		pr_debug("...rename(%pd2, %pd2, ...) = %i\n",
374e9be9d5eSMiklos Szeredi 			 olddentry, newdentry, err);
375e9be9d5eSMiklos Szeredi 	}
376e9be9d5eSMiklos Szeredi 	return err;
377e9be9d5eSMiklos Szeredi }
378e9be9d5eSMiklos Szeredi 
379576bb263SChristian Brauner static inline int ovl_do_whiteout(struct ovl_fs *ofs,
380576bb263SChristian Brauner 				  struct inode *dir, struct dentry *dentry)
381e9be9d5eSMiklos Szeredi {
382abf08576SChristian Brauner 	int err = vfs_whiteout(ovl_upper_mnt_idmap(ofs), dir, dentry);
383e9be9d5eSMiklos Szeredi 	pr_debug("whiteout(%pd2) = %i\n", dentry, err);
384e9be9d5eSMiklos Szeredi 	return err;
385e9be9d5eSMiklos Szeredi }
386e9be9d5eSMiklos Szeredi 
3872b1a7746SMiklos Szeredi static inline struct file *ovl_do_tmpfile(struct ovl_fs *ofs,
388576bb263SChristian Brauner 					  struct dentry *dentry, umode_t mode)
389e7f52429SAmir Goldstein {
3902b1a7746SMiklos Szeredi 	struct path path = { .mnt = ovl_upper_mnt(ofs), .dentry = dentry };
391d56e0ddbSAmir Goldstein 	struct file *file = kernel_tmpfile_open(ovl_upper_mnt_idmap(ofs), &path,
392d56e0ddbSAmir Goldstein 						mode, O_LARGEFILE | O_WRONLY,
393d56e0ddbSAmir Goldstein 						current_cred());
3942b1a7746SMiklos Szeredi 	int err = PTR_ERR_OR_ZERO(file);
395e7f52429SAmir Goldstein 
396e7f52429SAmir Goldstein 	pr_debug("tmpfile(%pd2, 0%o) = %i\n", dentry, mode, err);
3972b1a7746SMiklos Szeredi 	return file;
398e7f52429SAmir Goldstein }
399e7f52429SAmir Goldstein 
40022f289ceSChristian Brauner static inline struct dentry *ovl_lookup_upper(struct ovl_fs *ofs,
40122f289ceSChristian Brauner 					      const char *name,
40222f289ceSChristian Brauner 					      struct dentry *base, int len)
40322f289ceSChristian Brauner {
4044609e1f1SChristian Brauner 	return lookup_one(ovl_upper_mnt_idmap(ofs), name, base, len);
40522f289ceSChristian Brauner }
40622f289ceSChristian Brauner 
4070c288874SVivek Goyal static inline bool ovl_open_flags_need_copy_up(int flags)
4080c288874SVivek Goyal {
4090c288874SVivek Goyal 	if (!flags)
4100c288874SVivek Goyal 		return false;
4110c288874SVivek Goyal 
4120c288874SVivek Goyal 	return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
4130c288874SVivek Goyal }
4140c288874SVivek Goyal 
4158a924db2SStefan Berger static inline int ovl_do_getattr(const struct path *path, struct kstat *stat,
4168a924db2SStefan Berger 				 u32 request_mask, unsigned int flags)
4178a924db2SStefan Berger {
4188a924db2SStefan Berger 	if (flags & AT_GETATTR_NOSEC)
4198a924db2SStefan Berger 		return vfs_getattr_nosec(path, stat, request_mask, flags);
4208a924db2SStefan Berger 	return vfs_getattr(path, stat, request_mask, flags);
4218a924db2SStefan Berger }
4228a924db2SStefan Berger 
423bbb1e54dSMiklos Szeredi /* util.c */
424d08d3b3cSAmir Goldstein int ovl_get_write_access(struct dentry *dentry);
425d08d3b3cSAmir Goldstein void ovl_put_write_access(struct dentry *dentry);
426d08d3b3cSAmir Goldstein void ovl_start_write(struct dentry *dentry);
427d08d3b3cSAmir Goldstein void ovl_end_write(struct dentry *dentry);
428bbb1e54dSMiklos Szeredi int ovl_want_write(struct dentry *dentry);
429bbb1e54dSMiklos Szeredi void ovl_drop_write(struct dentry *dentry);
430bbb1e54dSMiklos Szeredi struct dentry *ovl_workdir(struct dentry *dentry);
431bbb1e54dSMiklos Szeredi const struct cred *ovl_override_creds(struct super_block *sb);
432a6293b3eSAmir Goldstein 
433a6293b3eSAmir Goldstein static inline const struct cred *ovl_creds(struct super_block *sb)
434a6293b3eSAmir Goldstein {
435a6293b3eSAmir Goldstein 	return OVL_FS(sb)->creator_cred;
436a6293b3eSAmir Goldstein }
437a6293b3eSAmir Goldstein 
438e487d889SAmir Goldstein int ovl_can_decode_fh(struct super_block *sb);
43902bcd157SAmir Goldstein struct dentry *ovl_indexdir(struct super_block *sb);
440f168f109SAmir Goldstein bool ovl_index_all(struct super_block *sb);
441f168f109SAmir Goldstein bool ovl_verify_lower(struct super_block *sb);
442163db0daSAmir Goldstein struct ovl_path *ovl_stack_alloc(unsigned int n);
443163db0daSAmir Goldstein void ovl_stack_cpy(struct ovl_path *dst, struct ovl_path *src, unsigned int n);
444163db0daSAmir Goldstein void ovl_stack_put(struct ovl_path *stack, unsigned int n);
445163db0daSAmir Goldstein void ovl_stack_free(struct ovl_path *stack, unsigned int n);
446bbb1e54dSMiklos Szeredi struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
447163db0daSAmir Goldstein void ovl_free_entry(struct ovl_entry *oe);
448bbb1e54dSMiklos Szeredi bool ovl_dentry_remote(struct dentry *dentry);
449b07d5cc9SAmir Goldstein void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *realdentry);
4500af950f5SAmir Goldstein void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry,
4510af950f5SAmir Goldstein 			   struct ovl_entry *oe);
452b07d5cc9SAmir Goldstein void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
4530af950f5SAmir Goldstein 			   struct ovl_entry *oe, unsigned int mask);
454bbb1e54dSMiklos Szeredi bool ovl_dentry_weird(struct dentry *dentry);
455e9be9d5eSMiklos Szeredi enum ovl_path_type ovl_path_type(struct dentry *dentry);
456e9be9d5eSMiklos Szeredi void ovl_path_upper(struct dentry *dentry, struct path *path);
457e9be9d5eSMiklos Szeredi void ovl_path_lower(struct dentry *dentry, struct path *path);
4584f93b426SVivek Goyal void ovl_path_lowerdata(struct dentry *dentry, struct path *path);
459b2dd05f1SZhihao Cheng struct inode *ovl_i_path_real(struct inode *inode, struct path *path);
460e9be9d5eSMiklos Szeredi enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
4611248ea4bSAmir Goldstein enum ovl_path_type ovl_path_realdata(struct dentry *dentry, struct path *path);
462e9be9d5eSMiklos Szeredi struct dentry *ovl_dentry_upper(struct dentry *dentry);
463e9be9d5eSMiklos Szeredi struct dentry *ovl_dentry_lower(struct dentry *dentry);
464647d253fSVivek Goyal struct dentry *ovl_dentry_lowerdata(struct dentry *dentry);
46542dd69aeSAmir Goldstein int ovl_dentry_set_lowerdata(struct dentry *dentry, struct ovl_path *datapath);
466ffa5723cSAmir Goldstein const struct ovl_layer *ovl_i_layer_lower(struct inode *inode);
46713464165SMiklos Szeredi const struct ovl_layer *ovl_layer_lower(struct dentry *dentry);
468e9be9d5eSMiklos Szeredi struct dentry *ovl_dentry_real(struct dentry *dentry);
4691d88f183SMiklos Szeredi struct dentry *ovl_i_dentry_upper(struct inode *inode);
47009d8b586SMiklos Szeredi struct inode *ovl_inode_upper(struct inode *inode);
47109d8b586SMiklos Szeredi struct inode *ovl_inode_lower(struct inode *inode);
4722664bd08SVivek Goyal struct inode *ovl_inode_lowerdata(struct inode *inode);
47309d8b586SMiklos Szeredi struct inode *ovl_inode_real(struct inode *inode);
4744823d49cSVivek Goyal struct inode *ovl_inode_realdata(struct inode *inode);
4752b21da92SAmir Goldstein const char *ovl_lowerdata_redirect(struct inode *inode);
4764edb83bbSMiklos Szeredi struct ovl_dir_cache *ovl_dir_cache(struct inode *inode);
4774edb83bbSMiklos Szeredi void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache);
478c62520a8SAmir Goldstein void ovl_dentry_set_flag(unsigned long flag, struct dentry *dentry);
479c62520a8SAmir Goldstein void ovl_dentry_clear_flag(unsigned long flag, struct dentry *dentry);
480c62520a8SAmir Goldstein bool ovl_dentry_test_flag(unsigned long flag, struct dentry *dentry);
481e9be9d5eSMiklos Szeredi bool ovl_dentry_is_opaque(struct dentry *dentry);
482c412ce49SMiklos Szeredi bool ovl_dentry_is_whiteout(struct dentry *dentry);
4835cf5b477SMiklos Szeredi void ovl_dentry_set_opaque(struct dentry *dentry);
484420332b9SAmir Goldstein bool ovl_dentry_has_xwhiteouts(struct dentry *dentry);
485420332b9SAmir Goldstein void ovl_dentry_set_xwhiteouts(struct dentry *dentry);
486420332b9SAmir Goldstein void ovl_layer_set_xwhiteouts(struct ovl_fs *ofs,
487420332b9SAmir Goldstein 			      const struct ovl_layer *layer);
48855acc661SMiklos Szeredi bool ovl_dentry_has_upper_alias(struct dentry *dentry);
48955acc661SMiklos Szeredi void ovl_dentry_set_upper_alias(struct dentry *dentry);
4900c288874SVivek Goyal bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags);
4910c288874SVivek Goyal bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags);
4920c288874SVivek Goyal bool ovl_has_upperdata(struct inode *inode);
4930c288874SVivek Goyal void ovl_set_upperdata(struct inode *inode);
494a6c60655SMiklos Szeredi const char *ovl_dentry_get_redirect(struct dentry *dentry);
495a6c60655SMiklos Szeredi void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
49609d8b586SMiklos Szeredi void ovl_inode_update(struct inode *inode, struct dentry *upperdentry);
497d9854c87SMiklos Szeredi void ovl_dir_modified(struct dentry *dentry, bool impurity);
4981fa9c5c5SMiklos Szeredi u64 ovl_inode_version_get(struct inode *inode);
499bbb1e54dSMiklos Szeredi bool ovl_is_whiteout(struct dentry *dentry);
500bc8df7a3SAlexander Larsson bool ovl_path_is_whiteout(struct ovl_fs *ofs, const struct path *path);
5012d343087SAl Viro struct file *ovl_path_open(const struct path *path, int flags);
5020c288874SVivek Goyal int ovl_copy_up_start(struct dentry *dentry, int flags);
50339d3d60aSAmir Goldstein void ovl_copy_up_end(struct dentry *dentry);
5040c288874SVivek Goyal bool ovl_already_copied_up(struct dentry *dentry, int flags);
505420332b9SAmir Goldstein char ovl_get_dir_xattr_val(struct ovl_fs *ofs, const struct path *path,
50643d193f8SMiklos Szeredi 			   enum ovl_xattr ox);
5072d343087SAl Viro bool ovl_path_check_origin_xattr(struct ovl_fs *ofs, const struct path *path);
508bc8df7a3SAlexander Larsson bool ovl_path_check_xwhiteout_xattr(struct ovl_fs *ofs, const struct path *path);
509d9544c1bSAmir Goldstein bool ovl_init_uuid_xattr(struct super_block *sb, struct ovl_fs *ofs,
510d9544c1bSAmir Goldstein 			 const struct path *upperpath);
511dad7017aSChristian Brauner 
512bc8df7a3SAlexander Larsson static inline bool ovl_upper_is_whiteout(struct ovl_fs *ofs,
513bc8df7a3SAlexander Larsson 					 struct dentry *upperdentry)
514bc8df7a3SAlexander Larsson {
515bc8df7a3SAlexander Larsson 	struct path upperpath = {
516bc8df7a3SAlexander Larsson 		.dentry = upperdentry,
517bc8df7a3SAlexander Larsson 		.mnt = ovl_upper_mnt(ofs),
518bc8df7a3SAlexander Larsson 	};
519bc8df7a3SAlexander Larsson 	return ovl_path_is_whiteout(ofs, &upperpath);
520bc8df7a3SAlexander Larsson }
521bc8df7a3SAlexander Larsson 
522dad7017aSChristian Brauner static inline bool ovl_check_origin_xattr(struct ovl_fs *ofs,
523dad7017aSChristian Brauner 					  struct dentry *upperdentry)
524dad7017aSChristian Brauner {
525dad7017aSChristian Brauner 	struct path upperpath = {
526dad7017aSChristian Brauner 		.dentry = upperdentry,
527dad7017aSChristian Brauner 		.mnt = ovl_upper_mnt(ofs),
528dad7017aSChristian Brauner 	};
529dad7017aSChristian Brauner 	return ovl_path_check_origin_xattr(ofs, &upperpath);
530dad7017aSChristian Brauner }
531dad7017aSChristian Brauner 
532a0c236b1SAmir Goldstein int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry,
53343d193f8SMiklos Szeredi 		       enum ovl_xattr ox, const void *value, size_t size,
534f3a15685SAmir Goldstein 		       int xerr);
535f3a15685SAmir Goldstein int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry);
536ad0af710SAmir Goldstein bool ovl_inuse_trylock(struct dentry *dentry);
537ad0af710SAmir Goldstein void ovl_inuse_unlock(struct dentry *dentry);
538146d62e5SAmir Goldstein bool ovl_is_inuse(struct dentry *dentry);
53924b33ee1SAmir Goldstein bool ovl_need_index(struct dentry *dentry);
5400e32992fSAmir Goldstein int ovl_nlink_start(struct dentry *dentry);
5410e32992fSAmir Goldstein void ovl_nlink_end(struct dentry *dentry);
5425820dc08SAmir Goldstein int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
543bf070890SAlexander Larsson int ovl_check_metacopy_xattr(struct ovl_fs *ofs, const struct path *path,
544bf070890SAlexander Larsson 			     struct ovl_metacopy *data);
545184996e9SAlexander Larsson int ovl_set_metacopy_xattr(struct ovl_fs *ofs, struct dentry *d,
546184996e9SAlexander Larsson 			   struct ovl_metacopy *metacopy);
54767d756c2SVivek Goyal bool ovl_is_metacopy_dentry(struct dentry *dentry);
5482d343087SAl Viro char *ovl_get_redirect_xattr(struct ovl_fs *ofs, const struct path *path, int padding);
5490c71faf5SAlexander Larsson int ovl_ensure_verity_loaded(struct path *path);
550184996e9SAlexander Larsson int ovl_get_verity_xattr(struct ovl_fs *ofs, const struct path *path,
551184996e9SAlexander Larsson 			 u8 *digest_buf, int *buf_length);
552184996e9SAlexander Larsson int ovl_validate_verity(struct ovl_fs *ofs,
553184996e9SAlexander Larsson 			struct path *metapath,
554184996e9SAlexander Larsson 			struct path *datapath);
5550c71faf5SAlexander Larsson int ovl_get_verity_digest(struct ovl_fs *ofs, struct path *src,
5560c71faf5SAlexander Larsson 			  struct ovl_metacopy *metacopy);
557335d3fc5SSargun Dhillon int ovl_sync_status(struct ovl_fs *ofs);
558f3a15685SAmir Goldstein 
55965cd913eSAmir Goldstein static inline void ovl_set_flag(unsigned long flag, struct inode *inode)
56065cd913eSAmir Goldstein {
56165cd913eSAmir Goldstein 	set_bit(flag, &OVL_I(inode)->flags);
56265cd913eSAmir Goldstein }
56365cd913eSAmir Goldstein 
56465cd913eSAmir Goldstein static inline void ovl_clear_flag(unsigned long flag, struct inode *inode)
56565cd913eSAmir Goldstein {
56665cd913eSAmir Goldstein 	clear_bit(flag, &OVL_I(inode)->flags);
56765cd913eSAmir Goldstein }
56865cd913eSAmir Goldstein 
56965cd913eSAmir Goldstein static inline bool ovl_test_flag(unsigned long flag, struct inode *inode)
57065cd913eSAmir Goldstein {
57165cd913eSAmir Goldstein 	return test_bit(flag, &OVL_I(inode)->flags);
57265cd913eSAmir Goldstein }
57365cd913eSAmir Goldstein 
574610afc0bSMiklos Szeredi static inline bool ovl_is_impuredir(struct super_block *sb,
575dad7017aSChristian Brauner 				    struct dentry *upperdentry)
576f3a15685SAmir Goldstein {
577dad7017aSChristian Brauner 	struct ovl_fs *ofs = OVL_FS(sb);
578dad7017aSChristian Brauner 	struct path upperpath = {
579dad7017aSChristian Brauner 		.dentry = upperdentry,
580dad7017aSChristian Brauner 		.mnt = ovl_upper_mnt(ofs),
581dad7017aSChristian Brauner 	};
582dad7017aSChristian Brauner 
583420332b9SAmir Goldstein 	return ovl_get_dir_xattr_val(ofs, &upperpath, OVL_XATTR_IMPURE) == 'y';
584420332b9SAmir Goldstein }
585420332b9SAmir Goldstein 
586420332b9SAmir Goldstein static inline char ovl_get_opaquedir_val(struct ovl_fs *ofs,
587420332b9SAmir Goldstein 					 const struct path *path)
588420332b9SAmir Goldstein {
589420332b9SAmir Goldstein 	return ovl_get_dir_xattr_val(ofs, path, OVL_XATTR_OPAQUE);
590f3a15685SAmir Goldstein }
591f3a15685SAmir Goldstein 
592af5f2396SAmir Goldstein static inline bool ovl_redirect_follow(struct ovl_fs *ofs)
593af5f2396SAmir Goldstein {
594af5f2396SAmir Goldstein 	return ofs->config.redirect_mode != OVL_REDIRECT_NOFOLLOW;
595af5f2396SAmir Goldstein }
596af5f2396SAmir Goldstein 
597af5f2396SAmir Goldstein static inline bool ovl_redirect_dir(struct ovl_fs *ofs)
598af5f2396SAmir Goldstein {
599af5f2396SAmir Goldstein 	return ofs->config.redirect_mode == OVL_REDIRECT_ON;
600af5f2396SAmir Goldstein }
601af5f2396SAmir Goldstein 
602b0504bfeSAmir Goldstein static inline bool ovl_origin_uuid(struct ovl_fs *ofs)
603b0504bfeSAmir Goldstein {
604b0504bfeSAmir Goldstein 	return ofs->config.uuid != OVL_UUID_OFF;
605b0504bfeSAmir Goldstein }
606b0504bfeSAmir Goldstein 
607b0504bfeSAmir Goldstein static inline bool ovl_has_fsid(struct ovl_fs *ofs)
608b0504bfeSAmir Goldstein {
609cbb44f09SAmir Goldstein 	return ofs->config.uuid == OVL_UUID_ON ||
610cbb44f09SAmir Goldstein 	       ofs->config.uuid == OVL_UUID_AUTO;
611b0504bfeSAmir Goldstein }
612b0504bfeSAmir Goldstein 
613926e94d7SAmir Goldstein /*
614926e94d7SAmir Goldstein  * With xino=auto, we do best effort to keep all inodes on same st_dev and
615926e94d7SAmir Goldstein  * d_ino consistent with st_ino.
616926e94d7SAmir Goldstein  * With xino=on, we do the same effort but we warn if we failed.
617926e94d7SAmir Goldstein  */
618dcb399deSAmir Goldstein static inline bool ovl_xino_warn(struct ovl_fs *ofs)
619926e94d7SAmir Goldstein {
620dcb399deSAmir Goldstein 	return ofs->config.xino == OVL_XINO_ON;
621926e94d7SAmir Goldstein }
622926e94d7SAmir Goldstein 
623af5f2396SAmir Goldstein /*
624af5f2396SAmir Goldstein  * To avoid regressions in existing setups with overlay lower offline changes,
625af5f2396SAmir Goldstein  * we allow lower changes only if none of the new features are used.
626af5f2396SAmir Goldstein  */
627af5f2396SAmir Goldstein static inline bool ovl_allow_offline_changes(struct ovl_fs *ofs)
628af5f2396SAmir Goldstein {
629af5f2396SAmir Goldstein 	return (!ofs->config.index && !ofs->config.metacopy &&
630af5f2396SAmir Goldstein 		!ovl_redirect_dir(ofs) && !ovl_xino_warn(ofs));
6310f831ec8SAmir Goldstein }
632e487d889SAmir Goldstein 
633e487d889SAmir Goldstein /* All layers on same fs? */
634dcb399deSAmir Goldstein static inline bool ovl_same_fs(struct ovl_fs *ofs)
635bbb1e54dSMiklos Szeredi {
636dcb399deSAmir Goldstein 	return ofs->xino_mode == 0;
6378a22efa1SAmir Goldstein }
6388a22efa1SAmir Goldstein 
6398a22efa1SAmir Goldstein /* All overlay inodes have same st_dev? */
640dcb399deSAmir Goldstein static inline bool ovl_same_dev(struct ovl_fs *ofs)
6411e92e307SAmir Goldstein {
642dcb399deSAmir Goldstein 	return ofs->xino_mode >= 0;
6431e92e307SAmir Goldstein }
6441e92e307SAmir Goldstein 
645dcb399deSAmir Goldstein static inline unsigned int ovl_xino_bits(struct ovl_fs *ofs)
6461e92e307SAmir Goldstein {
647dcb399deSAmir Goldstein 	return ovl_same_dev(ofs) ? ofs->xino_mode : 0;
648f941866fSAmir Goldstein }
64905122443SAmir Goldstein 
650531d3040SAmir Goldstein static inline void ovl_inode_lock(struct inode *inode)
651531d3040SAmir Goldstein {
652531d3040SAmir Goldstein 	mutex_lock(&OVL_I(inode)->lock);
653531d3040SAmir Goldstein }
654531d3040SAmir Goldstein 
655531d3040SAmir Goldstein static inline int ovl_inode_lock_interruptible(struct inode *inode)
6561e92e307SAmir Goldstein {
6571e92e307SAmir Goldstein 	return mutex_lock_interruptible(&OVL_I(inode)->lock);
6581e92e307SAmir Goldstein }
6591e92e307SAmir Goldstein 
6601e92e307SAmir Goldstein static inline void ovl_inode_unlock(struct inode *inode)
6611e92e307SAmir Goldstein {
6621e92e307SAmir Goldstein 	mutex_unlock(&OVL_I(inode)->lock);
6631e92e307SAmir Goldstein }
6641e92e307SAmir Goldstein 
665e9be9d5eSMiklos Szeredi 
666bbb1e54dSMiklos Szeredi /* namei.c */
667cbe7fba8SAmir Goldstein int ovl_check_fb_len(struct ovl_fb *fb, int fb_len);
668cbe7fba8SAmir Goldstein 
669cbe7fba8SAmir Goldstein static inline int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
670cbe7fba8SAmir Goldstein {
671522f6e6cSAmir Goldstein 	if (fh_len < sizeof(struct ovl_fh))
672522f6e6cSAmir Goldstein 		return -EINVAL;
673522f6e6cSAmir Goldstein 
674cbe7fba8SAmir Goldstein 	return ovl_check_fb_len(&fh->fb, fh_len - OVL_FH_WIRE_OFFSET);
675cbe7fba8SAmir Goldstein }
676cbe7fba8SAmir Goldstein 
6771cdb0cb6SPavel Tikhomirov struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
6781cdb0cb6SPavel Tikhomirov 				  struct vfsmount *mnt, bool connected);
67905122443SAmir Goldstein int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
6801eff1a1dSAmir Goldstein 			struct dentry *upperdentry, struct ovl_path **stackp);
681610afc0bSMiklos Szeredi int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry,
6825b02bfc1SAmir Goldstein 		      enum ovl_xattr ox, const struct ovl_fh *fh,
6835b02bfc1SAmir Goldstein 		      bool is_upper, bool set);
6845b02bfc1SAmir Goldstein int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry,
6855b02bfc1SAmir Goldstein 			    enum ovl_xattr ox, struct dentry *real,
6865b02bfc1SAmir Goldstein 			    bool is_upper, bool set);
6878ea28765SAmir Goldstein struct dentry *ovl_index_upper(struct ovl_fs *ofs, struct dentry *index,
6888ea28765SAmir Goldstein 			       bool connected);
689415543d5SAmir Goldstein int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index);
6905b02bfc1SAmir Goldstein int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name);
6911cdb0cb6SPavel Tikhomirov int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin,
6921cdb0cb6SPavel Tikhomirov 		       struct qstr *name);
69391ffe7beSAmir Goldstein struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh);
69406170154SAmir Goldstein struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
69506170154SAmir Goldstein 				struct dentry *origin, bool verify);
696420332b9SAmir Goldstein int ovl_path_next(int idx, struct dentry *dentry, struct path *path,
697420332b9SAmir Goldstein 		  const struct ovl_layer **layer);
698184996e9SAlexander Larsson int ovl_verify_lowerdata(struct dentry *dentry);
6991eff1a1dSAmir Goldstein struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
7001eff1a1dSAmir Goldstein 			  unsigned int flags);
701bbb1e54dSMiklos Szeredi bool ovl_lower_positive(struct dentry *dentry);
702e9be9d5eSMiklos Szeredi 
7035b02bfc1SAmir Goldstein static inline int ovl_verify_origin_fh(struct ovl_fs *ofs, struct dentry *upper,
7045b02bfc1SAmir Goldstein 				       const struct ovl_fh *fh, bool set)
7055b02bfc1SAmir Goldstein {
7065b02bfc1SAmir Goldstein 	return ovl_verify_set_fh(ofs, upper, OVL_XATTR_ORIGIN, fh, false, set);
7075b02bfc1SAmir Goldstein }
7085b02bfc1SAmir Goldstein 
709610afc0bSMiklos Szeredi static inline int ovl_verify_origin(struct ovl_fs *ofs, struct dentry *upper,
71005122443SAmir Goldstein 				    struct dentry *origin, bool set)
71105122443SAmir Goldstein {
7125b02bfc1SAmir Goldstein 	return ovl_verify_origin_xattr(ofs, upper, OVL_XATTR_ORIGIN, origin,
713610afc0bSMiklos Szeredi 				       false, set);
71405122443SAmir Goldstein }
71505122443SAmir Goldstein 
716610afc0bSMiklos Szeredi static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index,
717ad1d615cSAmir Goldstein 				   struct dentry *upper, bool set)
718ad1d615cSAmir Goldstein {
7195b02bfc1SAmir Goldstein 	return ovl_verify_origin_xattr(ofs, index, OVL_XATTR_UPPER, upper,
7205b02bfc1SAmir Goldstein 				       true, set);
721ad1d615cSAmir Goldstein }
722ad1d615cSAmir Goldstein 
723e9be9d5eSMiklos Szeredi /* readdir.c */
724e9be9d5eSMiklos Szeredi extern const struct file_operations ovl_dir_operations;
72561536bedSAmir Goldstein struct file *ovl_dir_real_file(const struct file *file, bool want_upper);
726e9be9d5eSMiklos Szeredi int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list);
727576bb263SChristian Brauner void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper,
728576bb263SChristian Brauner 			   struct list_head *list);
729e9be9d5eSMiklos Szeredi void ovl_cache_free(struct list_head *list);
7304edb83bbSMiklos Szeredi void ovl_dir_cache_free(struct inode *inode);
7312d343087SAl Viro int ovl_check_d_type_supported(const struct path *realpath);
732576bb263SChristian Brauner int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir,
733576bb263SChristian Brauner 			struct vfsmount *mnt, struct dentry *dentry, int level);
7341eff1a1dSAmir Goldstein int ovl_indexdir_cleanup(struct ovl_fs *ofs);
735e9be9d5eSMiklos Szeredi 
73665cd913eSAmir Goldstein /*
73765cd913eSAmir Goldstein  * Can we iterate real dir directly?
73865cd913eSAmir Goldstein  *
73965cd913eSAmir Goldstein  * Non-merge dir may contain whiteouts from a time it was a merge upper, before
74065cd913eSAmir Goldstein  * lower dir was removed under it and possibly before it was rotated from upper
74165cd913eSAmir Goldstein  * to lower layer.
74265cd913eSAmir Goldstein  */
7431fa9c5c5SMiklos Szeredi static inline bool ovl_dir_is_real(struct inode *dir)
74465cd913eSAmir Goldstein {
7451fa9c5c5SMiklos Szeredi 	return !ovl_test_flag(OVL_WHITEOUTS, dir);
74665cd913eSAmir Goldstein }
74765cd913eSAmir Goldstein 
748e9be9d5eSMiklos Szeredi /* inode.c */
7495f8415d6SAmir Goldstein int ovl_set_nlink_upper(struct dentry *dentry);
7505f8415d6SAmir Goldstein int ovl_set_nlink_lower(struct dentry *dentry);
751610afc0bSMiklos Szeredi unsigned int ovl_get_nlink(struct ovl_fs *ofs, struct dentry *lowerdentry,
752caf70cb2SAmir Goldstein 			   struct dentry *upperdentry,
753caf70cb2SAmir Goldstein 			   unsigned int fallback);
7544609e1f1SChristian Brauner int ovl_permission(struct mnt_idmap *idmap, struct inode *inode,
755549c7297SChristian Brauner 		   int mask);
756ded53656SYang Xu 
757ded53656SYang Xu #ifdef CONFIG_FS_POSIX_ACL
75877435322SChristian Brauner struct posix_acl *do_ovl_get_acl(struct mnt_idmap *idmap,
7596c0a8bfbSChristian Brauner 				 struct inode *inode, int type,
7606c0a8bfbSChristian Brauner 				 bool rcu, bool noperm);
7616c0a8bfbSChristian Brauner static inline struct posix_acl *ovl_get_inode_acl(struct inode *inode, int type,
7626c0a8bfbSChristian Brauner 						  bool rcu)
7636c0a8bfbSChristian Brauner {
76477435322SChristian Brauner 	return do_ovl_get_acl(&nop_mnt_idmap, inode, type, rcu, true);
7656c0a8bfbSChristian Brauner }
76677435322SChristian Brauner static inline struct posix_acl *ovl_get_acl(struct mnt_idmap *idmap,
7676c0a8bfbSChristian Brauner 					    struct dentry *dentry, int type)
7686c0a8bfbSChristian Brauner {
76977435322SChristian Brauner 	return do_ovl_get_acl(idmap, d_inode(dentry), type, false, false);
7706c0a8bfbSChristian Brauner }
77113e83a49SChristian Brauner int ovl_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
7720e641857SChristian Brauner 		struct posix_acl *acl, int type);
77331acceb9SChristian Brauner struct posix_acl *ovl_get_acl_path(const struct path *path,
77431acceb9SChristian Brauner 				   const char *acl_name, bool noperm);
775ded53656SYang Xu #else
7766c0a8bfbSChristian Brauner #define ovl_get_inode_acl	NULL
777ded53656SYang Xu #define ovl_get_acl		NULL
7780e641857SChristian Brauner #define ovl_set_acl		NULL
77931acceb9SChristian Brauner static inline struct posix_acl *ovl_get_acl_path(const struct path *path,
78031acceb9SChristian Brauner 						 const char *acl_name,
78131acceb9SChristian Brauner 						 bool noperm)
78231acceb9SChristian Brauner {
78331acceb9SChristian Brauner 	return NULL;
78431acceb9SChristian Brauner }
785ded53656SYang Xu #endif
786ded53656SYang Xu 
787913e9928SJeff Layton int ovl_update_time(struct inode *inode, int flags);
788610afc0bSMiklos Szeredi bool ovl_is_private_xattr(struct super_block *sb, const char *name);
789e9be9d5eSMiklos Szeredi 
790ac6a52ebSVivek Goyal struct ovl_inode_params {
79101b39dccSAmir Goldstein 	struct inode *newinode;
792ac6a52ebSVivek Goyal 	struct dentry *upperdentry;
7930af950f5SAmir Goldstein 	struct ovl_entry *oe;
79474c6e384SMiklos Szeredi 	bool index;
7959cec54c8SVivek Goyal 	char *redirect;
7962b21da92SAmir Goldstein 	char *lowerdata_redirect;
797ac6a52ebSVivek Goyal };
79862c832edSAmir Goldstein void ovl_inode_init(struct inode *inode, struct ovl_inode_params *oip,
79962c832edSAmir Goldstein 		    unsigned long ino, int fsid);
800ca4c8a3aSMiklos Szeredi struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev);
8014b91c30aSAmir Goldstein struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
8024b91c30aSAmir Goldstein 			       bool is_upper);
803146d62e5SAmir Goldstein bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir);
804146d62e5SAmir Goldstein struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir);
805ac6a52ebSVivek Goyal struct inode *ovl_get_inode(struct super_block *sb,
806ac6a52ebSVivek Goyal 			    struct ovl_inode_params *oip);
8072878dffcSChristian Brauner void ovl_copyattr(struct inode *to);
808e9be9d5eSMiklos Szeredi 
80972db8211SAmir Goldstein /* vfs inode flags copied from real to ovl inode */
81072db8211SAmir Goldstein #define OVL_COPY_I_FLAGS_MASK	(S_SYNC | S_NOATIME | S_APPEND | S_IMMUTABLE)
811096a218aSAmir Goldstein /* vfs inode flags read from overlay.protattr xattr to ovl inode */
812096a218aSAmir Goldstein #define OVL_PROT_I_FLAGS_MASK	(S_APPEND | S_IMMUTABLE)
81372db8211SAmir Goldstein 
81472db8211SAmir Goldstein /*
81572db8211SAmir Goldstein  * fileattr flags copied from lower to upper inode on copy up.
816096a218aSAmir Goldstein  * We cannot copy up immutable/append-only flags, because that would prevent
817096a218aSAmir Goldstein  * linking temp inode to upper dir, so we store them in xattr instead.
81872db8211SAmir Goldstein  */
81972db8211SAmir Goldstein #define OVL_COPY_FS_FLAGS_MASK	(FS_SYNC_FL | FS_NOATIME_FL)
82072db8211SAmir Goldstein #define OVL_COPY_FSX_FLAGS_MASK	(FS_XFLAG_SYNC | FS_XFLAG_NOATIME)
821096a218aSAmir Goldstein #define OVL_PROT_FS_FLAGS_MASK  (FS_APPEND_FL | FS_IMMUTABLE_FL)
822096a218aSAmir Goldstein #define OVL_PROT_FSX_FLAGS_MASK (FS_XFLAG_APPEND | FS_XFLAG_IMMUTABLE)
823096a218aSAmir Goldstein 
824096a218aSAmir Goldstein void ovl_check_protattr(struct inode *inode, struct dentry *upper);
825096a218aSAmir Goldstein int ovl_set_protattr(struct inode *inode, struct dentry *upper,
826096a218aSAmir Goldstein 		      struct fileattr *fa);
82772db8211SAmir Goldstein 
8284f357295SMiklos Szeredi static inline void ovl_copyflags(struct inode *from, struct inode *to)
8294f357295SMiklos Szeredi {
83072db8211SAmir Goldstein 	unsigned int mask = OVL_COPY_I_FLAGS_MASK;
8314f357295SMiklos Szeredi 
8324f357295SMiklos Szeredi 	inode_set_flags(to, from->i_flags & mask, mask);
8334f357295SMiklos Szeredi }
8344f357295SMiklos Szeredi 
835e9be9d5eSMiklos Szeredi /* dir.c */
836e9be9d5eSMiklos Szeredi extern const struct inode_operations ovl_dir_inode_operations;
837c21c839bSChengguang Xu int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct inode *dir,
838e7dd0e71SAmir Goldstein 			     struct dentry *dentry);
839471ec5dcSAmir Goldstein struct ovl_cattr {
84032a3d848SAl Viro 	dev_t rdev;
84132a3d848SAl Viro 	umode_t mode;
84232a3d848SAl Viro 	const char *link;
843471ec5dcSAmir Goldstein 	struct dentry *hardlink;
84432a3d848SAl Viro };
845471ec5dcSAmir Goldstein 
846471ec5dcSAmir Goldstein #define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) })
847471ec5dcSAmir Goldstein 
848576bb263SChristian Brauner int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir,
849576bb263SChristian Brauner 		   struct dentry **newdentry, umode_t mode);
850576bb263SChristian Brauner struct dentry *ovl_create_real(struct ovl_fs *ofs,
851576bb263SChristian Brauner 			       struct inode *dir, struct dentry *newdentry,
852471ec5dcSAmir Goldstein 			       struct ovl_cattr *attr);
853576bb263SChristian Brauner int ovl_cleanup(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry);
854576bb263SChristian Brauner struct dentry *ovl_lookup_temp(struct ovl_fs *ofs, struct dentry *workdir);
855576bb263SChristian Brauner struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir,
856576bb263SChristian Brauner 			       struct ovl_cattr *attr);
857e9be9d5eSMiklos Szeredi 
858d1d04ef8SMiklos Szeredi /* file.c */
859d1d04ef8SMiklos Szeredi extern const struct file_operations ovl_file_operations;
8602d343087SAl Viro int ovl_real_fileattr_get(const struct path *realpath, struct fileattr *fa);
8612d343087SAl Viro int ovl_real_fileattr_set(const struct path *realpath, struct fileattr *fa);
86266dbfabfSMiklos Szeredi int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa);
8638782a9aeSChristian Brauner int ovl_fileattr_set(struct mnt_idmap *idmap,
86466dbfabfSMiklos Szeredi 		     struct dentry *dentry, struct fileattr *fa);
865d1d04ef8SMiklos Szeredi 
866e9be9d5eSMiklos Szeredi /* copy_up.c */
867e9be9d5eSMiklos Szeredi int ovl_copy_up(struct dentry *dentry);
868d1e6f6a9SVivek Goyal int ovl_copy_up_with_data(struct dentry *dentry);
8693428030dSAmir Goldstein int ovl_maybe_copy_up(struct dentry *dentry, int flags);
8702d343087SAl Viro int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new);
8715272eaf3SChristian Brauner int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat);
8721cdb0cb6SPavel Tikhomirov struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
8731cdb0cb6SPavel Tikhomirov 				  bool is_upper);
8745b02bfc1SAmir Goldstein struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin);
8755b02bfc1SAmir Goldstein int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh,
876a0c236b1SAmir Goldstein 		      struct dentry *upper);
8778ed5eec9SAmir Goldstein 
8788ed5eec9SAmir Goldstein /* export.c */
8798ed5eec9SAmir Goldstein extern const struct export_operations ovl_export_operations;
88016aac5adSAmir Goldstein extern const struct export_operations ovl_export_fid_operations;
8817fb7998bSChristian Brauner 
8827fb7998bSChristian Brauner /* super.c */
8837fb7998bSChristian Brauner int ovl_fill_super(struct super_block *sb, struct fs_context *fc);
8847fb7998bSChristian Brauner 
8857fb7998bSChristian Brauner /* Will this overlay be forced to mount/remount ro? */
8867fb7998bSChristian Brauner static inline bool ovl_force_readonly(struct ovl_fs *ofs)
8877fb7998bSChristian Brauner {
8887fb7998bSChristian Brauner 	return (!ovl_upper_mnt(ofs) || !ofs->workdir);
8897fb7998bSChristian Brauner }
890420a62ddSAmir Goldstein 
891420a62ddSAmir Goldstein /* xattr.c */
892420a62ddSAmir Goldstein 
893420a62ddSAmir Goldstein const struct xattr_handler * const *ovl_xattr_handlers(struct ovl_fs *ofs);
894420a62ddSAmir Goldstein int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
895420a62ddSAmir Goldstein 		struct iattr *attr);
896420a62ddSAmir Goldstein int ovl_getattr(struct mnt_idmap *idmap, const struct path *path,
897420a62ddSAmir Goldstein 		struct kstat *stat, u32 request_mask, unsigned int flags);
898420a62ddSAmir Goldstein ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
899