xref: /openbmc/linux/fs/overlayfs/util.c (revision 5cf5b477)
1bbb1e54dSMiklos Szeredi /*
2bbb1e54dSMiklos Szeredi  * Copyright (C) 2011 Novell Inc.
3bbb1e54dSMiklos Szeredi  * Copyright (C) 2016 Red Hat, Inc.
4bbb1e54dSMiklos Szeredi  *
5bbb1e54dSMiklos Szeredi  * This program is free software; you can redistribute it and/or modify it
6bbb1e54dSMiklos Szeredi  * under the terms of the GNU General Public License version 2 as published by
7bbb1e54dSMiklos Szeredi  * the Free Software Foundation.
8bbb1e54dSMiklos Szeredi  */
9bbb1e54dSMiklos Szeredi 
10bbb1e54dSMiklos Szeredi #include <linux/fs.h>
11bbb1e54dSMiklos Szeredi #include <linux/mount.h>
12bbb1e54dSMiklos Szeredi #include <linux/slab.h>
13bbb1e54dSMiklos Szeredi #include <linux/xattr.h>
14bbb1e54dSMiklos Szeredi #include "overlayfs.h"
15bbb1e54dSMiklos Szeredi #include "ovl_entry.h"
16bbb1e54dSMiklos Szeredi 
17bbb1e54dSMiklos Szeredi int ovl_want_write(struct dentry *dentry)
18bbb1e54dSMiklos Szeredi {
19bbb1e54dSMiklos Szeredi 	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
20bbb1e54dSMiklos Szeredi 	return mnt_want_write(ofs->upper_mnt);
21bbb1e54dSMiklos Szeredi }
22bbb1e54dSMiklos Szeredi 
23bbb1e54dSMiklos Szeredi void ovl_drop_write(struct dentry *dentry)
24bbb1e54dSMiklos Szeredi {
25bbb1e54dSMiklos Szeredi 	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
26bbb1e54dSMiklos Szeredi 	mnt_drop_write(ofs->upper_mnt);
27bbb1e54dSMiklos Szeredi }
28bbb1e54dSMiklos Szeredi 
29bbb1e54dSMiklos Szeredi struct dentry *ovl_workdir(struct dentry *dentry)
30bbb1e54dSMiklos Szeredi {
31bbb1e54dSMiklos Szeredi 	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
32bbb1e54dSMiklos Szeredi 	return ofs->workdir;
33bbb1e54dSMiklos Szeredi }
34bbb1e54dSMiklos Szeredi 
35bbb1e54dSMiklos Szeredi const struct cred *ovl_override_creds(struct super_block *sb)
36bbb1e54dSMiklos Szeredi {
37bbb1e54dSMiklos Szeredi 	struct ovl_fs *ofs = sb->s_fs_info;
38bbb1e54dSMiklos Szeredi 
39bbb1e54dSMiklos Szeredi 	return override_creds(ofs->creator_cred);
40bbb1e54dSMiklos Szeredi }
41bbb1e54dSMiklos Szeredi 
42bbb1e54dSMiklos Szeredi struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
43bbb1e54dSMiklos Szeredi {
44bbb1e54dSMiklos Szeredi 	size_t size = offsetof(struct ovl_entry, lowerstack[numlower]);
45bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = kzalloc(size, GFP_KERNEL);
46bbb1e54dSMiklos Szeredi 
47bbb1e54dSMiklos Szeredi 	if (oe)
48bbb1e54dSMiklos Szeredi 		oe->numlower = numlower;
49bbb1e54dSMiklos Szeredi 
50bbb1e54dSMiklos Szeredi 	return oe;
51bbb1e54dSMiklos Szeredi }
52bbb1e54dSMiklos Szeredi 
53bbb1e54dSMiklos Szeredi bool ovl_dentry_remote(struct dentry *dentry)
54bbb1e54dSMiklos Szeredi {
55bbb1e54dSMiklos Szeredi 	return dentry->d_flags &
56bbb1e54dSMiklos Szeredi 		(DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE |
57bbb1e54dSMiklos Szeredi 		 DCACHE_OP_REAL);
58bbb1e54dSMiklos Szeredi }
59bbb1e54dSMiklos Szeredi 
60bbb1e54dSMiklos Szeredi bool ovl_dentry_weird(struct dentry *dentry)
61bbb1e54dSMiklos Szeredi {
62bbb1e54dSMiklos Szeredi 	return dentry->d_flags & (DCACHE_NEED_AUTOMOUNT |
63bbb1e54dSMiklos Szeredi 				  DCACHE_MANAGE_TRANSIT |
64bbb1e54dSMiklos Szeredi 				  DCACHE_OP_HASH |
65bbb1e54dSMiklos Szeredi 				  DCACHE_OP_COMPARE);
66bbb1e54dSMiklos Szeredi }
67bbb1e54dSMiklos Szeredi 
68bbb1e54dSMiklos Szeredi enum ovl_path_type ovl_path_type(struct dentry *dentry)
69bbb1e54dSMiklos Szeredi {
70bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
71bbb1e54dSMiklos Szeredi 	enum ovl_path_type type = 0;
72bbb1e54dSMiklos Szeredi 
73bbb1e54dSMiklos Szeredi 	if (oe->__upperdentry) {
74bbb1e54dSMiklos Szeredi 		type = __OVL_PATH_UPPER;
75bbb1e54dSMiklos Szeredi 
76bbb1e54dSMiklos Szeredi 		/*
77bbb1e54dSMiklos Szeredi 		 * Non-dir dentry can hold lower dentry from previous
78bbb1e54dSMiklos Szeredi 		 * location.
79bbb1e54dSMiklos Szeredi 		 */
80bbb1e54dSMiklos Szeredi 		if (oe->numlower && d_is_dir(dentry))
81bbb1e54dSMiklos Szeredi 			type |= __OVL_PATH_MERGE;
82bbb1e54dSMiklos Szeredi 	} else {
83bbb1e54dSMiklos Szeredi 		if (oe->numlower > 1)
84bbb1e54dSMiklos Szeredi 			type |= __OVL_PATH_MERGE;
85bbb1e54dSMiklos Szeredi 	}
86bbb1e54dSMiklos Szeredi 	return type;
87bbb1e54dSMiklos Szeredi }
88bbb1e54dSMiklos Szeredi 
89bbb1e54dSMiklos Szeredi void ovl_path_upper(struct dentry *dentry, struct path *path)
90bbb1e54dSMiklos Szeredi {
91bbb1e54dSMiklos Szeredi 	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
92bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
93bbb1e54dSMiklos Szeredi 
94bbb1e54dSMiklos Szeredi 	path->mnt = ofs->upper_mnt;
95bbb1e54dSMiklos Szeredi 	path->dentry = ovl_upperdentry_dereference(oe);
96bbb1e54dSMiklos Szeredi }
97bbb1e54dSMiklos Szeredi 
98bbb1e54dSMiklos Szeredi void ovl_path_lower(struct dentry *dentry, struct path *path)
99bbb1e54dSMiklos Szeredi {
100bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
101bbb1e54dSMiklos Szeredi 
102bbb1e54dSMiklos Szeredi 	*path = oe->numlower ? oe->lowerstack[0] : (struct path) { NULL, NULL };
103bbb1e54dSMiklos Szeredi }
104bbb1e54dSMiklos Szeredi 
105bbb1e54dSMiklos Szeredi enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
106bbb1e54dSMiklos Szeredi {
107bbb1e54dSMiklos Szeredi 	enum ovl_path_type type = ovl_path_type(dentry);
108bbb1e54dSMiklos Szeredi 
109bbb1e54dSMiklos Szeredi 	if (!OVL_TYPE_UPPER(type))
110bbb1e54dSMiklos Szeredi 		ovl_path_lower(dentry, path);
111bbb1e54dSMiklos Szeredi 	else
112bbb1e54dSMiklos Szeredi 		ovl_path_upper(dentry, path);
113bbb1e54dSMiklos Szeredi 
114bbb1e54dSMiklos Szeredi 	return type;
115bbb1e54dSMiklos Szeredi }
116bbb1e54dSMiklos Szeredi 
117bbb1e54dSMiklos Szeredi struct dentry *ovl_dentry_upper(struct dentry *dentry)
118bbb1e54dSMiklos Szeredi {
119bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
120bbb1e54dSMiklos Szeredi 
121bbb1e54dSMiklos Szeredi 	return ovl_upperdentry_dereference(oe);
122bbb1e54dSMiklos Szeredi }
123bbb1e54dSMiklos Szeredi 
124bbb1e54dSMiklos Szeredi static struct dentry *__ovl_dentry_lower(struct ovl_entry *oe)
125bbb1e54dSMiklos Szeredi {
126bbb1e54dSMiklos Szeredi 	return oe->numlower ? oe->lowerstack[0].dentry : NULL;
127bbb1e54dSMiklos Szeredi }
128bbb1e54dSMiklos Szeredi 
129bbb1e54dSMiklos Szeredi struct dentry *ovl_dentry_lower(struct dentry *dentry)
130bbb1e54dSMiklos Szeredi {
131bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
132bbb1e54dSMiklos Szeredi 
133bbb1e54dSMiklos Szeredi 	return __ovl_dentry_lower(oe);
134bbb1e54dSMiklos Szeredi }
135bbb1e54dSMiklos Szeredi 
136bbb1e54dSMiklos Szeredi struct dentry *ovl_dentry_real(struct dentry *dentry)
137bbb1e54dSMiklos Szeredi {
138bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
139bbb1e54dSMiklos Szeredi 	struct dentry *realdentry;
140bbb1e54dSMiklos Szeredi 
141bbb1e54dSMiklos Szeredi 	realdentry = ovl_upperdentry_dereference(oe);
142bbb1e54dSMiklos Szeredi 	if (!realdentry)
143bbb1e54dSMiklos Szeredi 		realdentry = __ovl_dentry_lower(oe);
144bbb1e54dSMiklos Szeredi 
145bbb1e54dSMiklos Szeredi 	return realdentry;
146bbb1e54dSMiklos Szeredi }
147bbb1e54dSMiklos Szeredi 
148bbb1e54dSMiklos Szeredi struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry)
149bbb1e54dSMiklos Szeredi {
150bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
151bbb1e54dSMiklos Szeredi 
152bbb1e54dSMiklos Szeredi 	return oe->cache;
153bbb1e54dSMiklos Szeredi }
154bbb1e54dSMiklos Szeredi 
155bbb1e54dSMiklos Szeredi void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache)
156bbb1e54dSMiklos Szeredi {
157bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
158bbb1e54dSMiklos Szeredi 
159bbb1e54dSMiklos Szeredi 	oe->cache = cache;
160bbb1e54dSMiklos Szeredi }
161bbb1e54dSMiklos Szeredi 
162bbb1e54dSMiklos Szeredi bool ovl_dentry_is_opaque(struct dentry *dentry)
163bbb1e54dSMiklos Szeredi {
164bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
165bbb1e54dSMiklos Szeredi 	return oe->opaque;
166bbb1e54dSMiklos Szeredi }
167bbb1e54dSMiklos Szeredi 
168bbb1e54dSMiklos Szeredi bool ovl_dentry_is_whiteout(struct dentry *dentry)
169bbb1e54dSMiklos Szeredi {
170bbb1e54dSMiklos Szeredi 	return !dentry->d_inode && ovl_dentry_is_opaque(dentry);
171bbb1e54dSMiklos Szeredi }
172bbb1e54dSMiklos Szeredi 
1735cf5b477SMiklos Szeredi void ovl_dentry_set_opaque(struct dentry *dentry)
174bbb1e54dSMiklos Szeredi {
175bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
1765cf5b477SMiklos Szeredi 
1775cf5b477SMiklos Szeredi 	oe->opaque = true;
178bbb1e54dSMiklos Szeredi }
179bbb1e54dSMiklos Szeredi 
180a6c60655SMiklos Szeredi bool ovl_redirect_dir(struct super_block *sb)
181a6c60655SMiklos Szeredi {
182a6c60655SMiklos Szeredi 	struct ovl_fs *ofs = sb->s_fs_info;
183a6c60655SMiklos Szeredi 
184a6c60655SMiklos Szeredi 	return ofs->config.redirect_dir;
185a6c60655SMiklos Szeredi }
186a6c60655SMiklos Szeredi 
187a6c60655SMiklos Szeredi void ovl_clear_redirect_dir(struct super_block *sb)
188a6c60655SMiklos Szeredi {
189a6c60655SMiklos Szeredi 	struct ovl_fs *ofs = sb->s_fs_info;
190a6c60655SMiklos Szeredi 
191a6c60655SMiklos Szeredi 	ofs->config.redirect_dir = false;
192a6c60655SMiklos Szeredi }
193a6c60655SMiklos Szeredi 
194a6c60655SMiklos Szeredi const char *ovl_dentry_get_redirect(struct dentry *dentry)
195a6c60655SMiklos Szeredi {
196a6c60655SMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
197a6c60655SMiklos Szeredi 
198a6c60655SMiklos Szeredi 	return oe->redirect;
199a6c60655SMiklos Szeredi }
200a6c60655SMiklos Szeredi 
201a6c60655SMiklos Szeredi void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect)
202a6c60655SMiklos Szeredi {
203a6c60655SMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
204a6c60655SMiklos Szeredi 
205a6c60655SMiklos Szeredi 	kfree(oe->redirect);
206a6c60655SMiklos Szeredi 	oe->redirect = redirect;
207a6c60655SMiklos Szeredi }
208a6c60655SMiklos Szeredi 
209bbb1e54dSMiklos Szeredi void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry)
210bbb1e54dSMiklos Szeredi {
211bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
212bbb1e54dSMiklos Szeredi 
213bbb1e54dSMiklos Szeredi 	WARN_ON(!inode_is_locked(upperdentry->d_parent->d_inode));
214bbb1e54dSMiklos Szeredi 	WARN_ON(oe->__upperdentry);
215bbb1e54dSMiklos Szeredi 	/*
216bbb1e54dSMiklos Szeredi 	 * Make sure upperdentry is consistent before making it visible to
217bbb1e54dSMiklos Szeredi 	 * ovl_upperdentry_dereference().
218bbb1e54dSMiklos Szeredi 	 */
219bbb1e54dSMiklos Szeredi 	smp_wmb();
220bbb1e54dSMiklos Szeredi 	oe->__upperdentry = upperdentry;
221bbb1e54dSMiklos Szeredi }
222bbb1e54dSMiklos Szeredi 
223bbb1e54dSMiklos Szeredi void ovl_inode_init(struct inode *inode, struct inode *realinode, bool is_upper)
224bbb1e54dSMiklos Szeredi {
225bbb1e54dSMiklos Szeredi 	WRITE_ONCE(inode->i_private, (unsigned long) realinode |
226bbb1e54dSMiklos Szeredi 		   (is_upper ? OVL_ISUPPER_MASK : 0));
227bbb1e54dSMiklos Szeredi }
228bbb1e54dSMiklos Szeredi 
229bbb1e54dSMiklos Szeredi void ovl_inode_update(struct inode *inode, struct inode *upperinode)
230bbb1e54dSMiklos Szeredi {
231bbb1e54dSMiklos Szeredi 	WARN_ON(!upperinode);
232bbb1e54dSMiklos Szeredi 	WARN_ON(!inode_unhashed(inode));
233bbb1e54dSMiklos Szeredi 	WRITE_ONCE(inode->i_private,
234bbb1e54dSMiklos Szeredi 		   (unsigned long) upperinode | OVL_ISUPPER_MASK);
235bbb1e54dSMiklos Szeredi 	if (!S_ISDIR(upperinode->i_mode))
236bbb1e54dSMiklos Szeredi 		__insert_inode_hash(inode, (unsigned long) upperinode);
237bbb1e54dSMiklos Szeredi }
238bbb1e54dSMiklos Szeredi 
239bbb1e54dSMiklos Szeredi void ovl_dentry_version_inc(struct dentry *dentry)
240bbb1e54dSMiklos Szeredi {
241bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
242bbb1e54dSMiklos Szeredi 
243bbb1e54dSMiklos Szeredi 	WARN_ON(!inode_is_locked(dentry->d_inode));
244bbb1e54dSMiklos Szeredi 	oe->version++;
245bbb1e54dSMiklos Szeredi }
246bbb1e54dSMiklos Szeredi 
247bbb1e54dSMiklos Szeredi u64 ovl_dentry_version_get(struct dentry *dentry)
248bbb1e54dSMiklos Szeredi {
249bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
250bbb1e54dSMiklos Szeredi 
251bbb1e54dSMiklos Szeredi 	WARN_ON(!inode_is_locked(dentry->d_inode));
252bbb1e54dSMiklos Szeredi 	return oe->version;
253bbb1e54dSMiklos Szeredi }
254bbb1e54dSMiklos Szeredi 
255bbb1e54dSMiklos Szeredi bool ovl_is_whiteout(struct dentry *dentry)
256bbb1e54dSMiklos Szeredi {
257bbb1e54dSMiklos Szeredi 	struct inode *inode = dentry->d_inode;
258bbb1e54dSMiklos Szeredi 
259bbb1e54dSMiklos Szeredi 	return inode && IS_WHITEOUT(inode);
260bbb1e54dSMiklos Szeredi }
261bbb1e54dSMiklos Szeredi 
262bbb1e54dSMiklos Szeredi struct file *ovl_path_open(struct path *path, int flags)
263bbb1e54dSMiklos Szeredi {
264bbb1e54dSMiklos Szeredi 	return dentry_open(path, flags | O_NOATIME, current_cred());
265bbb1e54dSMiklos Szeredi }
266