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