diff options
author | hujianyang <hujianyang@huawei.com> | 2014-12-10 21:30:18 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2015-01-09 08:55:57 -0500 |
commit | 4330397e4e8a662f36d101659e2a59ce32e76ff4 (patch) | |
tree | 77ad4a8e29eaa3a02a88ab358569817e7991ab5f /fs | |
parent | 6d900f5a33393067e370736d39798f814f5e25cc (diff) |
ovl: discard independent cursor in readdir()
Since the ovl_dir_cache is stable during a directory reading, the cursor
of struct ovl_dir_file don't need to be an independent entry in the list
of a merged directory.
This patch changes *cursor* to a pointer which points to the entry in the
ovl_dir_cache. After this, we don't need to check *is_cursor* either.
Signed-off-by: hujianyang <hujianyang@huawei.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/overlayfs/readdir.c | 38 |
1 files changed, 14 insertions, 24 deletions
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 9df848f2e622..dcf1d412888d 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c | |||
@@ -24,7 +24,6 @@ struct ovl_cache_entry { | |||
24 | struct list_head l_node; | 24 | struct list_head l_node; |
25 | struct rb_node node; | 25 | struct rb_node node; |
26 | bool is_whiteout; | 26 | bool is_whiteout; |
27 | bool is_cursor; | ||
28 | char name[]; | 27 | char name[]; |
29 | }; | 28 | }; |
30 | 29 | ||
@@ -49,7 +48,7 @@ struct ovl_dir_file { | |||
49 | bool is_real; | 48 | bool is_real; |
50 | bool is_upper; | 49 | bool is_upper; |
51 | struct ovl_dir_cache *cache; | 50 | struct ovl_dir_cache *cache; |
52 | struct ovl_cache_entry cursor; | 51 | struct list_head *cursor; |
53 | struct file *realfile; | 52 | struct file *realfile; |
54 | struct file *upperfile; | 53 | struct file *upperfile; |
55 | }; | 54 | }; |
@@ -97,7 +96,6 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct dentry *dir, | |||
97 | p->type = d_type; | 96 | p->type = d_type; |
98 | p->ino = ino; | 97 | p->ino = ino; |
99 | p->is_whiteout = false; | 98 | p->is_whiteout = false; |
100 | p->is_cursor = false; | ||
101 | 99 | ||
102 | if (d_type == DT_CHR) { | 100 | if (d_type == DT_CHR) { |
103 | struct dentry *dentry; | 101 | struct dentry *dentry; |
@@ -196,7 +194,6 @@ static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry) | |||
196 | { | 194 | { |
197 | struct ovl_dir_cache *cache = od->cache; | 195 | struct ovl_dir_cache *cache = od->cache; |
198 | 196 | ||
199 | list_del_init(&od->cursor.l_node); | ||
200 | WARN_ON(cache->refcount <= 0); | 197 | WARN_ON(cache->refcount <= 0); |
201 | cache->refcount--; | 198 | cache->refcount--; |
202 | if (!cache->refcount) { | 199 | if (!cache->refcount) { |
@@ -254,6 +251,7 @@ static void ovl_dir_reset(struct file *file) | |||
254 | if (cache && ovl_dentry_version_get(dentry) != cache->version) { | 251 | if (cache && ovl_dentry_version_get(dentry) != cache->version) { |
255 | ovl_cache_put(od, dentry); | 252 | ovl_cache_put(od, dentry); |
256 | od->cache = NULL; | 253 | od->cache = NULL; |
254 | od->cursor = NULL; | ||
257 | } | 255 | } |
258 | WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type)); | 256 | WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type)); |
259 | if (od->is_real && OVL_TYPE_MERGE(type)) | 257 | if (od->is_real && OVL_TYPE_MERGE(type)) |
@@ -295,17 +293,16 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) | |||
295 | 293 | ||
296 | static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) | 294 | static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) |
297 | { | 295 | { |
298 | struct ovl_cache_entry *p; | 296 | struct list_head *p; |
299 | loff_t off = 0; | 297 | loff_t off = 0; |
300 | 298 | ||
301 | list_for_each_entry(p, &od->cache->entries, l_node) { | 299 | list_for_each(p, &od->cache->entries) { |
302 | if (p->is_cursor) | ||
303 | continue; | ||
304 | if (off >= pos) | 300 | if (off >= pos) |
305 | break; | 301 | break; |
306 | off++; | 302 | off++; |
307 | } | 303 | } |
308 | list_move_tail(&od->cursor.l_node, &p->l_node); | 304 | /* Cursor is safe since the cache is stable */ |
305 | od->cursor = p; | ||
309 | } | 306 | } |
310 | 307 | ||
311 | static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | 308 | static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) |
@@ -344,6 +341,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) | |||
344 | { | 341 | { |
345 | struct ovl_dir_file *od = file->private_data; | 342 | struct ovl_dir_file *od = file->private_data; |
346 | struct dentry *dentry = file->f_path.dentry; | 343 | struct dentry *dentry = file->f_path.dentry; |
344 | struct ovl_cache_entry *p; | ||
347 | 345 | ||
348 | if (!ctx->pos) | 346 | if (!ctx->pos) |
349 | ovl_dir_reset(file); | 347 | ovl_dir_reset(file); |
@@ -362,19 +360,13 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) | |||
362 | ovl_seek_cursor(od, ctx->pos); | 360 | ovl_seek_cursor(od, ctx->pos); |
363 | } | 361 | } |
364 | 362 | ||
365 | while (od->cursor.l_node.next != &od->cache->entries) { | 363 | while (od->cursor != &od->cache->entries) { |
366 | struct ovl_cache_entry *p; | 364 | p = list_entry(od->cursor, struct ovl_cache_entry, l_node); |
367 | 365 | if (!p->is_whiteout) | |
368 | p = list_entry(od->cursor.l_node.next, struct ovl_cache_entry, l_node); | 366 | if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) |
369 | /* Skip cursors */ | 367 | break; |
370 | if (!p->is_cursor) { | 368 | od->cursor = p->l_node.next; |
371 | if (!p->is_whiteout) { | 369 | ctx->pos++; |
372 | if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) | ||
373 | break; | ||
374 | } | ||
375 | ctx->pos++; | ||
376 | } | ||
377 | list_move(&od->cursor.l_node, &p->l_node); | ||
378 | } | 370 | } |
379 | return 0; | 371 | return 0; |
380 | } | 372 | } |
@@ -493,11 +485,9 @@ static int ovl_dir_open(struct inode *inode, struct file *file) | |||
493 | kfree(od); | 485 | kfree(od); |
494 | return PTR_ERR(realfile); | 486 | return PTR_ERR(realfile); |
495 | } | 487 | } |
496 | INIT_LIST_HEAD(&od->cursor.l_node); | ||
497 | od->realfile = realfile; | 488 | od->realfile = realfile; |
498 | od->is_real = !OVL_TYPE_MERGE(type); | 489 | od->is_real = !OVL_TYPE_MERGE(type); |
499 | od->is_upper = OVL_TYPE_UPPER(type); | 490 | od->is_upper = OVL_TYPE_UPPER(type); |
500 | od->cursor.is_cursor = true; | ||
501 | file->private_data = od; | 491 | file->private_data = od; |
502 | 492 | ||
503 | return 0; | 493 | return 0; |