ovl: discard independent cursor in readdir()
RFC PATCH 1/1 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.
--- fs/overlayfs/readdir.c | 33 ++++++++++++--------------------- 1 files changed, 12 insertions(+), 21 deletions(-)
fs/overlayfs/readdir.c +12 -21
@@ -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 ;
Signature · 1 line
1.6.0.2
Quoted 7 lines · hujianyang
Since the
ovl_dir_cacheis stable during a directory reading, the cursor of structovl_dir_filedon'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.
Sorry, there is something wrong with this patch. Please, drop it~!
fs/overlayfs/readdir.c static int ovl_iterate(struct file *file, struct dir_context *ctx) · line 361
Quoted 9 lines · hujianyang
static struct
ovl_dir_cache*ovl_cache_get(struct dentry *dentry)fs/overlayfs/readdir.c +1
-2@@ -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)) {
Seems I was mistake here. The entry which cursor points to could be the last node in the list. We have finished reading one directory until the cursor points to the head of the entries list.
Here the condition should be:
"""&od->cursor->l_node != &od->cache->entries"""
Sorry for that, I should be more careful.
I will resend this patch with this fix.
Quoted 20 lines
fs/overlayfs/readdir.c +6
-10+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 ; }