aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorhujianyang <hujianyang@huawei.com>2014-12-10 21:30:18 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2015-01-09 08:55:57 -0500
commit4330397e4e8a662f36d101659e2a59ce32e76ff4 (patch)
tree77ad4a8e29eaa3a02a88ab358569817e7991ab5f /fs
parent6d900f5a33393067e370736d39798f814f5e25cc (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.c38
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
296static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) 294static 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
311static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) 308static 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;