Blame view

fs/overlayfs/readdir.c 14.2 KB
e9be9d5e7   Miklos Szeredi   overlay filesystem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   *
   * Copyright (C) 2011 Novell Inc.
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 as published by
   * the Free Software Foundation.
   */
  
  #include <linux/fs.h>
  #include <linux/slab.h>
  #include <linux/namei.h>
  #include <linux/file.h>
  #include <linux/xattr.h>
  #include <linux/rbtree.h>
  #include <linux/security.h>
  #include <linux/cred.h>
  #include "overlayfs.h"
  
  struct ovl_cache_entry {
e9be9d5e7   Miklos Szeredi   overlay filesystem
21
22
23
  	unsigned int len;
  	unsigned int type;
  	u64 ino;
e9be9d5e7   Miklos Szeredi   overlay filesystem
24
25
  	struct list_head l_node;
  	struct rb_node node;
cdb672795   Miklos Szeredi   ovl: lookup white...
26
  	struct ovl_cache_entry *next_maybe_whiteout;
c2096537d   Miklos Szeredi   ovl: fix check fo...
27
  	bool is_whiteout;
68bf86110   Al Viro   overlayfs: make o...
28
  	char name[];
e9be9d5e7   Miklos Szeredi   overlay filesystem
29
30
31
32
33
34
35
36
37
38
  };
  
  struct ovl_dir_cache {
  	long refcount;
  	u64 version;
  	struct list_head entries;
  };
  
  struct ovl_readdir_data {
  	struct dir_context ctx;
3fe6e52f0   Antonio Murdaca   ovl: override cre...
39
  	struct dentry *dentry;
56656e960   Miklos Szeredi   ovl: rename is_me...
40
  	bool is_lowest;
49be4fb9c   Al Viro   overlayfs: embed ...
41
  	struct rb_root root;
e9be9d5e7   Miklos Szeredi   overlay filesystem
42
  	struct list_head *list;
db6ec212b   Al Viro   overlayfs: embed ...
43
  	struct list_head middle;
cdb672795   Miklos Szeredi   ovl: lookup white...
44
  	struct ovl_cache_entry *first_maybe_whiteout;
e9be9d5e7   Miklos Szeredi   overlay filesystem
45
46
  	int count;
  	int err;
45aebeaf4   Vivek Goyal   ovl: Ensure upper...
47
  	bool d_type_supported;
e9be9d5e7   Miklos Szeredi   overlay filesystem
48
49
50
51
52
53
  };
  
  struct ovl_dir_file {
  	bool is_real;
  	bool is_upper;
  	struct ovl_dir_cache *cache;
4330397e4   hujianyang   ovl: discard inde...
54
  	struct list_head *cursor;
e9be9d5e7   Miklos Szeredi   overlay filesystem
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  	struct file *realfile;
  	struct file *upperfile;
  };
  
  static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n)
  {
  	return container_of(n, struct ovl_cache_entry, node);
  }
  
  static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root,
  						    const char *name, int len)
  {
  	struct rb_node *node = root->rb_node;
  	int cmp;
  
  	while (node) {
  		struct ovl_cache_entry *p = ovl_cache_entry_from_node(node);
  
  		cmp = strncmp(name, p->name, len);
  		if (cmp > 0)
  			node = p->node.rb_right;
  		else if (cmp < 0 || len < p->len)
  			node = p->node.rb_left;
  		else
  			return p;
  	}
  
  	return NULL;
  }
cdb672795   Miklos Szeredi   ovl: lookup white...
84
  static struct ovl_cache_entry *ovl_cache_entry_new(struct ovl_readdir_data *rdd,
3e01cee3b   Miklos Szeredi   ovl: check whiteo...
85
  						   const char *name, int len,
e9be9d5e7   Miklos Szeredi   overlay filesystem
86
87
88
  						   u64 ino, unsigned int d_type)
  {
  	struct ovl_cache_entry *p;
68bf86110   Al Viro   overlayfs: make o...
89
  	size_t size = offsetof(struct ovl_cache_entry, name[len + 1]);
e9be9d5e7   Miklos Szeredi   overlay filesystem
90

68bf86110   Al Viro   overlayfs: make o...
91
  	p = kmalloc(size, GFP_KERNEL);
3e01cee3b   Miklos Szeredi   ovl: check whiteo...
92
93
94
95
96
97
98
99
100
  	if (!p)
  		return NULL;
  
  	memcpy(p->name, name, len);
  	p->name[len] = '\0';
  	p->len = len;
  	p->type = d_type;
  	p->ino = ino;
  	p->is_whiteout = false;
3e01cee3b   Miklos Szeredi   ovl: check whiteo...
101
102
  
  	if (d_type == DT_CHR) {
cdb672795   Miklos Szeredi   ovl: lookup white...
103
104
  		p->next_maybe_whiteout = rdd->first_maybe_whiteout;
  		rdd->first_maybe_whiteout = p;
3e01cee3b   Miklos Szeredi   ovl: check whiteo...
105
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
106
107
108
109
110
111
112
  	return p;
  }
  
  static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd,
  				  const char *name, int len, u64 ino,
  				  unsigned int d_type)
  {
49be4fb9c   Al Viro   overlayfs: embed ...
113
  	struct rb_node **newp = &rdd->root.rb_node;
e9be9d5e7   Miklos Szeredi   overlay filesystem
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  	struct rb_node *parent = NULL;
  	struct ovl_cache_entry *p;
  
  	while (*newp) {
  		int cmp;
  		struct ovl_cache_entry *tmp;
  
  		parent = *newp;
  		tmp = ovl_cache_entry_from_node(*newp);
  		cmp = strncmp(name, tmp->name, len);
  		if (cmp > 0)
  			newp = &tmp->node.rb_right;
  		else if (cmp < 0 || len < tmp->len)
  			newp = &tmp->node.rb_left;
  		else
  			return 0;
  	}
cdb672795   Miklos Szeredi   ovl: lookup white...
131
  	p = ovl_cache_entry_new(rdd, name, len, ino, d_type);
e9be9d5e7   Miklos Szeredi   overlay filesystem
132
133
134
135
136
  	if (p == NULL)
  		return -ENOMEM;
  
  	list_add_tail(&p->l_node, rdd->list);
  	rb_link_node(&p->node, parent, newp);
49be4fb9c   Al Viro   overlayfs: embed ...
137
  	rb_insert_color(&p->node, &rdd->root);
e9be9d5e7   Miklos Szeredi   overlay filesystem
138
139
140
  
  	return 0;
  }
56656e960   Miklos Szeredi   ovl: rename is_me...
141
142
143
  static int ovl_fill_lowest(struct ovl_readdir_data *rdd,
  			   const char *name, int namelen,
  			   loff_t offset, u64 ino, unsigned int d_type)
e9be9d5e7   Miklos Szeredi   overlay filesystem
144
145
  {
  	struct ovl_cache_entry *p;
49be4fb9c   Al Viro   overlayfs: embed ...
146
  	p = ovl_cache_entry_find(&rdd->root, name, namelen);
e9be9d5e7   Miklos Szeredi   overlay filesystem
147
  	if (p) {
db6ec212b   Al Viro   overlayfs: embed ...
148
  		list_move_tail(&p->l_node, &rdd->middle);
e9be9d5e7   Miklos Szeredi   overlay filesystem
149
  	} else {
cdb672795   Miklos Szeredi   ovl: lookup white...
150
  		p = ovl_cache_entry_new(rdd, name, namelen, ino, d_type);
e9be9d5e7   Miklos Szeredi   overlay filesystem
151
152
153
  		if (p == NULL)
  			rdd->err = -ENOMEM;
  		else
db6ec212b   Al Viro   overlayfs: embed ...
154
  			list_add_tail(&p->l_node, &rdd->middle);
e9be9d5e7   Miklos Szeredi   overlay filesystem
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  	}
  
  	return rdd->err;
  }
  
  void ovl_cache_free(struct list_head *list)
  {
  	struct ovl_cache_entry *p;
  	struct ovl_cache_entry *n;
  
  	list_for_each_entry_safe(p, n, list, l_node)
  		kfree(p);
  
  	INIT_LIST_HEAD(list);
  }
  
  static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry)
  {
  	struct ovl_dir_cache *cache = od->cache;
e9be9d5e7   Miklos Szeredi   overlay filesystem
174
175
176
177
178
179
180
181
182
183
  	WARN_ON(cache->refcount <= 0);
  	cache->refcount--;
  	if (!cache->refcount) {
  		if (ovl_dir_cache(dentry) == cache)
  			ovl_set_dir_cache(dentry, NULL);
  
  		ovl_cache_free(&cache->entries);
  		kfree(cache);
  	}
  }
ac7576f4b   Miklos Szeredi   vfs: make first a...
184
185
186
  static int ovl_fill_merge(struct dir_context *ctx, const char *name,
  			  int namelen, loff_t offset, u64 ino,
  			  unsigned int d_type)
e9be9d5e7   Miklos Szeredi   overlay filesystem
187
  {
ac7576f4b   Miklos Szeredi   vfs: make first a...
188
189
  	struct ovl_readdir_data *rdd =
  		container_of(ctx, struct ovl_readdir_data, ctx);
e9be9d5e7   Miklos Szeredi   overlay filesystem
190
191
  
  	rdd->count++;
56656e960   Miklos Szeredi   ovl: rename is_me...
192
  	if (!rdd->is_lowest)
e9be9d5e7   Miklos Szeredi   overlay filesystem
193
194
  		return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type);
  	else
56656e960   Miklos Szeredi   ovl: rename is_me...
195
  		return ovl_fill_lowest(rdd, name, namelen, offset, ino, d_type);
e9be9d5e7   Miklos Szeredi   overlay filesystem
196
  }
cdb672795   Miklos Szeredi   ovl: lookup white...
197
198
199
200
201
202
  static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
  {
  	int err;
  	struct ovl_cache_entry *p;
  	struct dentry *dentry;
  	const struct cred *old_cred;
cdb672795   Miklos Szeredi   ovl: lookup white...
203

3fe6e52f0   Antonio Murdaca   ovl: override cre...
204
  	old_cred = ovl_override_creds(rdd->dentry->d_sb);
cdb672795   Miklos Szeredi   ovl: lookup white...
205

002354112   Al Viro   restore killabili...
206
  	err = down_write_killable(&dir->d_inode->i_rwsem);
cdb672795   Miklos Szeredi   ovl: lookup white...
207
208
209
210
211
212
213
214
215
216
  	if (!err) {
  		while (rdd->first_maybe_whiteout) {
  			p = rdd->first_maybe_whiteout;
  			rdd->first_maybe_whiteout = p->next_maybe_whiteout;
  			dentry = lookup_one_len(p->name, dir, p->len);
  			if (!IS_ERR(dentry)) {
  				p->is_whiteout = ovl_is_whiteout(dentry);
  				dput(dentry);
  			}
  		}
5955102c9   Al Viro   wrappers for ->i_...
217
  		inode_unlock(dir->d_inode);
cdb672795   Miklos Szeredi   ovl: lookup white...
218
219
  	}
  	revert_creds(old_cred);
cdb672795   Miklos Szeredi   ovl: lookup white...
220
221
222
  
  	return err;
  }
e9be9d5e7   Miklos Szeredi   overlay filesystem
223
224
225
226
227
228
229
230
231
  static inline int ovl_dir_read(struct path *realpath,
  			       struct ovl_readdir_data *rdd)
  {
  	struct file *realfile;
  	int err;
  
  	realfile = ovl_path_open(realpath, O_RDONLY | O_DIRECTORY);
  	if (IS_ERR(realfile))
  		return PTR_ERR(realfile);
cdb672795   Miklos Szeredi   ovl: lookup white...
232
  	rdd->first_maybe_whiteout = NULL;
e9be9d5e7   Miklos Szeredi   overlay filesystem
233
234
235
236
237
238
239
240
  	rdd->ctx.pos = 0;
  	do {
  		rdd->count = 0;
  		rdd->err = 0;
  		err = iterate_dir(realfile, &rdd->ctx);
  		if (err >= 0)
  			err = rdd->err;
  	} while (!err && rdd->count);
cdb672795   Miklos Szeredi   ovl: lookup white...
241

eea2fb485   Miklos Szeredi   ovl: proper clean...
242
  	if (!err && rdd->first_maybe_whiteout && rdd->dentry)
cdb672795   Miklos Szeredi   ovl: lookup white...
243
  		err = ovl_check_whiteouts(realpath->dentry, rdd);
e9be9d5e7   Miklos Szeredi   overlay filesystem
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  	fput(realfile);
  
  	return err;
  }
  
  static void ovl_dir_reset(struct file *file)
  {
  	struct ovl_dir_file *od = file->private_data;
  	struct ovl_dir_cache *cache = od->cache;
  	struct dentry *dentry = file->f_path.dentry;
  	enum ovl_path_type type = ovl_path_type(dentry);
  
  	if (cache && ovl_dentry_version_get(dentry) != cache->version) {
  		ovl_cache_put(od, dentry);
  		od->cache = NULL;
4330397e4   hujianyang   ovl: discard inde...
259
  		od->cursor = NULL;
e9be9d5e7   Miklos Szeredi   overlay filesystem
260
  	}
1afaba1ec   Miklos Szeredi   ovl: make path-ty...
261
262
  	WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
  	if (od->is_real && OVL_TYPE_MERGE(type))
e9be9d5e7   Miklos Szeredi   overlay filesystem
263
264
  		od->is_real = false;
  }
c9f00fdb9   Miklos Szeredi   ovl: pass dentry ...
265
  static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list)
e9be9d5e7   Miklos Szeredi   overlay filesystem
266
267
  {
  	int err;
9d7459d83   Miklos Szeredi   ovl: multi-layer ...
268
  	struct path realpath;
e9be9d5e7   Miklos Szeredi   overlay filesystem
269
270
  	struct ovl_readdir_data rdd = {
  		.ctx.actor = ovl_fill_merge,
3fe6e52f0   Antonio Murdaca   ovl: override cre...
271
  		.dentry = dentry,
e9be9d5e7   Miklos Szeredi   overlay filesystem
272
  		.list = list,
49be4fb9c   Al Viro   overlayfs: embed ...
273
  		.root = RB_ROOT,
56656e960   Miklos Szeredi   ovl: rename is_me...
274
  		.is_lowest = false,
e9be9d5e7   Miklos Szeredi   overlay filesystem
275
  	};
9d7459d83   Miklos Szeredi   ovl: multi-layer ...
276
  	int idx, next;
e9be9d5e7   Miklos Szeredi   overlay filesystem
277

9d7459d83   Miklos Szeredi   ovl: multi-layer ...
278
279
  	for (idx = 0; idx != -1; idx = next) {
  		next = ovl_path_next(idx, dentry, &realpath);
c9f00fdb9   Miklos Szeredi   ovl: pass dentry ...
280

9d7459d83   Miklos Szeredi   ovl: multi-layer ...
281
  		if (next != -1) {
9d7459d83   Miklos Szeredi   ovl: multi-layer ...
282
  			err = ovl_dir_read(&realpath, &rdd);
e9be9d5e7   Miklos Szeredi   overlay filesystem
283
  			if (err)
9d7459d83   Miklos Szeredi   ovl: multi-layer ...
284
285
286
287
288
289
290
  				break;
  		} else {
  			/*
  			 * Insert lowest layer entries before upper ones, this
  			 * allows offsets to be reasonably constant
  			 */
  			list_add(&rdd.middle, rdd.list);
56656e960   Miklos Szeredi   ovl: rename is_me...
291
  			rdd.is_lowest = true;
9d7459d83   Miklos Szeredi   ovl: multi-layer ...
292
293
  			err = ovl_dir_read(&realpath, &rdd);
  			list_del(&rdd.middle);
e9be9d5e7   Miklos Szeredi   overlay filesystem
294
295
  		}
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
296
  	return err;
e9be9d5e7   Miklos Szeredi   overlay filesystem
297
298
299
300
  }
  
  static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos)
  {
4330397e4   hujianyang   ovl: discard inde...
301
  	struct list_head *p;
e9be9d5e7   Miklos Szeredi   overlay filesystem
302
  	loff_t off = 0;
4330397e4   hujianyang   ovl: discard inde...
303
  	list_for_each(p, &od->cache->entries) {
e9be9d5e7   Miklos Szeredi   overlay filesystem
304
305
306
307
  		if (off >= pos)
  			break;
  		off++;
  	}
4330397e4   hujianyang   ovl: discard inde...
308
309
  	/* Cursor is safe since the cache is stable */
  	od->cursor = p;
e9be9d5e7   Miklos Szeredi   overlay filesystem
310
311
312
313
314
  }
  
  static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
  {
  	int res;
e9be9d5e7   Miklos Szeredi   overlay filesystem
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
  	struct ovl_dir_cache *cache;
  
  	cache = ovl_dir_cache(dentry);
  	if (cache && ovl_dentry_version_get(dentry) == cache->version) {
  		cache->refcount++;
  		return cache;
  	}
  	ovl_set_dir_cache(dentry, NULL);
  
  	cache = kzalloc(sizeof(struct ovl_dir_cache), GFP_KERNEL);
  	if (!cache)
  		return ERR_PTR(-ENOMEM);
  
  	cache->refcount = 1;
  	INIT_LIST_HEAD(&cache->entries);
c9f00fdb9   Miklos Szeredi   ovl: pass dentry ...
330
  	res = ovl_dir_read_merged(dentry, &cache->entries);
e9be9d5e7   Miklos Szeredi   overlay filesystem
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  	if (res) {
  		ovl_cache_free(&cache->entries);
  		kfree(cache);
  		return ERR_PTR(res);
  	}
  
  	cache->version = ovl_dentry_version_get(dentry);
  	ovl_set_dir_cache(dentry, cache);
  
  	return cache;
  }
  
  static int ovl_iterate(struct file *file, struct dir_context *ctx)
  {
  	struct ovl_dir_file *od = file->private_data;
  	struct dentry *dentry = file->f_path.dentry;
4330397e4   hujianyang   ovl: discard inde...
347
  	struct ovl_cache_entry *p;
e9be9d5e7   Miklos Szeredi   overlay filesystem
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
  
  	if (!ctx->pos)
  		ovl_dir_reset(file);
  
  	if (od->is_real)
  		return iterate_dir(od->realfile, ctx);
  
  	if (!od->cache) {
  		struct ovl_dir_cache *cache;
  
  		cache = ovl_cache_get(dentry);
  		if (IS_ERR(cache))
  			return PTR_ERR(cache);
  
  		od->cache = cache;
  		ovl_seek_cursor(od, ctx->pos);
  	}
4330397e4   hujianyang   ovl: discard inde...
365
366
367
368
369
370
371
  	while (od->cursor != &od->cache->entries) {
  		p = list_entry(od->cursor, struct ovl_cache_entry, l_node);
  		if (!p->is_whiteout)
  			if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
  				break;
  		od->cursor = p->l_node.next;
  		ctx->pos++;
e9be9d5e7   Miklos Szeredi   overlay filesystem
372
373
374
375
376
377
378
379
  	}
  	return 0;
  }
  
  static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
  {
  	loff_t res;
  	struct ovl_dir_file *od = file->private_data;
5955102c9   Al Viro   wrappers for ->i_...
380
  	inode_lock(file_inode(file));
e9be9d5e7   Miklos Szeredi   overlay filesystem
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  	if (!file->f_pos)
  		ovl_dir_reset(file);
  
  	if (od->is_real) {
  		res = vfs_llseek(od->realfile, offset, origin);
  		file->f_pos = od->realfile->f_pos;
  	} else {
  		res = -EINVAL;
  
  		switch (origin) {
  		case SEEK_CUR:
  			offset += file->f_pos;
  			break;
  		case SEEK_SET:
  			break;
  		default:
  			goto out_unlock;
  		}
  		if (offset < 0)
  			goto out_unlock;
  
  		if (offset != file->f_pos) {
  			file->f_pos = offset;
  			if (od->cache)
  				ovl_seek_cursor(od, offset);
  		}
  		res = offset;
  	}
  out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
410
  	inode_unlock(file_inode(file));
e9be9d5e7   Miklos Szeredi   overlay filesystem
411
412
413
414
415
416
417
418
419
420
421
422
423
424
  
  	return res;
  }
  
  static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
  			 int datasync)
  {
  	struct ovl_dir_file *od = file->private_data;
  	struct dentry *dentry = file->f_path.dentry;
  	struct file *realfile = od->realfile;
  
  	/*
  	 * Need to check if we started out being a lower dir, but got copied up
  	 */
1afaba1ec   Miklos Szeredi   ovl: make path-ty...
425
  	if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) {
e9be9d5e7   Miklos Szeredi   overlay filesystem
426
  		struct inode *inode = file_inode(file);
7676895f4   Miklos Szeredi   ovl: ovl_dir_fsyn...
427
  		realfile = lockless_dereference(od->upperfile);
e9be9d5e7   Miklos Szeredi   overlay filesystem
428
429
430
431
432
  		if (!realfile) {
  			struct path upperpath;
  
  			ovl_path_upper(dentry, &upperpath);
  			realfile = ovl_path_open(&upperpath, O_RDONLY);
d45f00ae4   Al Viro   overlayfs: barrie...
433
  			smp_mb__before_spinlock();
5955102c9   Al Viro   wrappers for ->i_...
434
  			inode_lock(inode);
3d268c9b1   Al Viro   overlayfs: don't ...
435
436
  			if (!od->upperfile) {
  				if (IS_ERR(realfile)) {
5955102c9   Al Viro   wrappers for ->i_...
437
  					inode_unlock(inode);
3d268c9b1   Al Viro   overlayfs: don't ...
438
439
440
441
442
443
444
445
  					return PTR_ERR(realfile);
  				}
  				od->upperfile = realfile;
  			} else {
  				/* somebody has beaten us to it */
  				if (!IS_ERR(realfile))
  					fput(realfile);
  				realfile = od->upperfile;
e9be9d5e7   Miklos Szeredi   overlay filesystem
446
  			}
5955102c9   Al Viro   wrappers for ->i_...
447
  			inode_unlock(inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
448
  		}
e9be9d5e7   Miklos Szeredi   overlay filesystem
449
450
451
452
453
454
455
456
457
458
  	}
  
  	return vfs_fsync_range(realfile, start, end, datasync);
  }
  
  static int ovl_dir_release(struct inode *inode, struct file *file)
  {
  	struct ovl_dir_file *od = file->private_data;
  
  	if (od->cache) {
5955102c9   Al Viro   wrappers for ->i_...
459
  		inode_lock(inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
460
  		ovl_cache_put(od, file->f_path.dentry);
5955102c9   Al Viro   wrappers for ->i_...
461
  		inode_unlock(inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  	}
  	fput(od->realfile);
  	if (od->upperfile)
  		fput(od->upperfile);
  	kfree(od);
  
  	return 0;
  }
  
  static int ovl_dir_open(struct inode *inode, struct file *file)
  {
  	struct path realpath;
  	struct file *realfile;
  	struct ovl_dir_file *od;
  	enum ovl_path_type type;
  
  	od = kzalloc(sizeof(struct ovl_dir_file), GFP_KERNEL);
  	if (!od)
  		return -ENOMEM;
  
  	type = ovl_path_real(file->f_path.dentry, &realpath);
  	realfile = ovl_path_open(&realpath, file->f_flags);
  	if (IS_ERR(realfile)) {
  		kfree(od);
  		return PTR_ERR(realfile);
  	}
e9be9d5e7   Miklos Szeredi   overlay filesystem
488
  	od->realfile = realfile;
1afaba1ec   Miklos Szeredi   ovl: make path-ty...
489
490
  	od->is_real = !OVL_TYPE_MERGE(type);
  	od->is_upper = OVL_TYPE_UPPER(type);
e9be9d5e7   Miklos Szeredi   overlay filesystem
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
  	file->private_data = od;
  
  	return 0;
  }
  
  const struct file_operations ovl_dir_operations = {
  	.read		= generic_read_dir,
  	.open		= ovl_dir_open,
  	.iterate	= ovl_iterate,
  	.llseek		= ovl_dir_llseek,
  	.fsync		= ovl_dir_fsync,
  	.release	= ovl_dir_release,
  };
  
  int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
  {
  	int err;
e9be9d5e7   Miklos Szeredi   overlay filesystem
508
  	struct ovl_cache_entry *p;
c9f00fdb9   Miklos Szeredi   ovl: pass dentry ...
509
  	err = ovl_dir_read_merged(dentry, list);
e9be9d5e7   Miklos Szeredi   overlay filesystem
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  	if (err)
  		return err;
  
  	err = 0;
  
  	list_for_each_entry(p, list, l_node) {
  		if (p->is_whiteout)
  			continue;
  
  		if (p->name[0] == '.') {
  			if (p->len == 1)
  				continue;
  			if (p->len == 2 && p->name[1] == '.')
  				continue;
  		}
  		err = -ENOTEMPTY;
  		break;
  	}
  
  	return err;
  }
  
  void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list)
  {
  	struct ovl_cache_entry *p;
5955102c9   Al Viro   wrappers for ->i_...
535
  	inode_lock_nested(upper->d_inode, I_MUTEX_CHILD);
e9be9d5e7   Miklos Szeredi   overlay filesystem
536
537
538
539
540
541
542
543
544
545
546
547
548
549
  	list_for_each_entry(p, list, l_node) {
  		struct dentry *dentry;
  
  		if (!p->is_whiteout)
  			continue;
  
  		dentry = lookup_one_len(p->name, upper, p->len);
  		if (IS_ERR(dentry)) {
  			pr_err("overlayfs: lookup '%s/%.*s' failed (%i)
  ",
  			       upper->d_name.name, p->len, p->name,
  			       (int) PTR_ERR(dentry));
  			continue;
  		}
84889d493   Konstantin Khlebnikov   ovl: check dentry...
550
551
  		if (dentry->d_inode)
  			ovl_cleanup(upper->d_inode, dentry);
e9be9d5e7   Miklos Szeredi   overlay filesystem
552
553
  		dput(dentry);
  	}
5955102c9   Al Viro   wrappers for ->i_...
554
  	inode_unlock(upper->d_inode);
e9be9d5e7   Miklos Szeredi   overlay filesystem
555
  }
45aebeaf4   Vivek Goyal   ovl: Ensure upper...
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
  
  static int ovl_check_d_type(struct dir_context *ctx, const char *name,
  			  int namelen, loff_t offset, u64 ino,
  			  unsigned int d_type)
  {
  	struct ovl_readdir_data *rdd =
  		container_of(ctx, struct ovl_readdir_data, ctx);
  
  	/* Even if d_type is not supported, DT_DIR is returned for . and .. */
  	if (!strncmp(name, ".", namelen) || !strncmp(name, "..", namelen))
  		return 0;
  
  	if (d_type != DT_UNKNOWN)
  		rdd->d_type_supported = true;
  
  	return 0;
  }
  
  /*
   * Returns 1 if d_type is supported, 0 not supported/unknown. Negative values
   * if error is encountered.
   */
  int ovl_check_d_type_supported(struct path *realpath)
  {
  	int err;
  	struct ovl_readdir_data rdd = {
  		.ctx.actor = ovl_check_d_type,
  		.d_type_supported = false,
  	};
  
  	err = ovl_dir_read(realpath, &rdd);
  	if (err)
  		return err;
  
  	return rdd.d_type_supported;
  }
eea2fb485   Miklos Szeredi   ovl: proper clean...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
  
  static void ovl_workdir_cleanup_recurse(struct path *path, int level)
  {
  	int err;
  	struct inode *dir = path->dentry->d_inode;
  	LIST_HEAD(list);
  	struct ovl_cache_entry *p;
  	struct ovl_readdir_data rdd = {
  		.ctx.actor = ovl_fill_merge,
  		.dentry = NULL,
  		.list = &list,
  		.root = RB_ROOT,
  		.is_lowest = false,
  	};
  
  	err = ovl_dir_read(path, &rdd);
  	if (err)
  		goto out;
  
  	inode_lock_nested(dir, I_MUTEX_PARENT);
  	list_for_each_entry(p, &list, l_node) {
  		struct dentry *dentry;
  
  		if (p->name[0] == '.') {
  			if (p->len == 1)
  				continue;
  			if (p->len == 2 && p->name[1] == '.')
  				continue;
  		}
  		dentry = lookup_one_len(p->name, path->dentry, p->len);
  		if (IS_ERR(dentry))
  			continue;
  		if (dentry->d_inode)
  			ovl_workdir_cleanup(dir, path->mnt, dentry, level);
  		dput(dentry);
  	}
  	inode_unlock(dir);
  out:
  	ovl_cache_free(&list);
  }
  
  void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
  			 struct dentry *dentry, int level)
  {
  	int err;
  
  	if (!d_is_dir(dentry) || level > 1) {
  		ovl_cleanup(dir, dentry);
  		return;
  	}
  
  	err = ovl_do_rmdir(dir, dentry);
  	if (err) {
  		struct path path = { .mnt = mnt, .dentry = dentry };
  
  		inode_unlock(dir);
  		ovl_workdir_cleanup_recurse(&path, level + 1);
  		inode_lock_nested(dir, I_MUTEX_PARENT);
  		ovl_cleanup(dir, dentry);
  	}
  }