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@xxxxxxxxxx> --- fs/overlayfs/readdir.c | 33 ++++++++++++--------------------- 1 files changed, 12 insertions(+), 21 deletions(-) diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 8087b63..0e46aab 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -24,7 +24,6 @@ struct ovl_cache_entry { struct list_head l_node; struct rb_node node; bool is_whiteout; - bool is_cursor; char name[]; }; @@ -49,7 +48,7 @@ struct ovl_dir_file { bool is_real; bool is_upper; struct ovl_dir_cache *cache; - struct ovl_cache_entry cursor; + struct ovl_cache_entry *cursor; struct file *realfile; struct file *upperfile; }; @@ -94,7 +93,6 @@ static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len, p->type = d_type; p->ino = ino; p->is_whiteout = false; - p->is_cursor = false; } return p; @@ -195,7 +193,7 @@ static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry) { struct ovl_dir_cache *cache = od->cache; - list_del_init(&od->cursor.l_node); + od->cursor = NULL; WARN_ON(cache->refcount <= 0); cache->refcount--; if (!cache->refcount) { @@ -298,13 +296,12 @@ static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) loff_t off = 0; list_for_each_entry(p, &od->cache->entries, l_node) { - if (p->is_cursor) - continue; if (off >= pos) break; off++; } - list_move_tail(&od->cursor.l_node, &p->l_node); + /* Curosr is safe since the cache is stable */ + od->cursor = p; } static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) @@ -361,19 +358,14 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) ovl_seek_cursor(od, ctx->pos); } - while (od->cursor.l_node.next != &od->cache->entries) { - struct ovl_cache_entry *p; + while (!list_is_last(&od->cursor->l_node, &od->cache->entries)) { + struct ovl_cache_entry *p = od->cursor; - p = list_entry(od->cursor.l_node.next, struct ovl_cache_entry, l_node); - /* Skip cursors */ - if (!p->is_cursor) { - if (!p->is_whiteout) { - if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) - break; - } - ctx->pos++; - } - list_move(&od->cursor.l_node, &p->l_node); + if (!p->is_whiteout) + if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) + break; + od->cursor = list_next_entry(p, l_node); + ctx->pos++; } return 0; } @@ -492,11 +484,10 @@ static int ovl_dir_open(struct inode *inode, struct file *file) kfree(od); return PTR_ERR(realfile); } - INIT_LIST_HEAD(&od->cursor.l_node); od->realfile = realfile; od->is_real = !OVL_TYPE_MERGE(type); od->is_upper = OVL_TYPE_UPPER(type); - od->cursor.is_cursor = true; + od->cursor = NULL; file->private_data = od; return 0; -- 1.6.0.2 -- To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html