Skip to content

Commit

Permalink
ovl: discard independent cursor in readdir()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
hujianyang authored and Miklos Szeredi committed Jan 9, 2015
1 parent 6d900f5 commit 4330397
Showing 1 changed file with 14 additions and 24 deletions.
38 changes: 14 additions & 24 deletions fs/overlayfs/readdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
};

Expand All @@ -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 list_head *cursor;
struct file *realfile;
struct file *upperfile;
};
Expand Down Expand Up @@ -97,7 +96,6 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct dentry *dir,
p->type = d_type;
p->ino = ino;
p->is_whiteout = false;
p->is_cursor = false;

if (d_type == DT_CHR) {
struct dentry *dentry;
Expand Down Expand Up @@ -196,7 +194,6 @@ 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);
WARN_ON(cache->refcount <= 0);
cache->refcount--;
if (!cache->refcount) {
Expand Down Expand Up @@ -254,6 +251,7 @@ static void ovl_dir_reset(struct file *file)
if (cache && ovl_dentry_version_get(dentry) != cache->version) {
ovl_cache_put(od, dentry);
od->cache = NULL;
od->cursor = NULL;
}
WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
if (od->is_real && OVL_TYPE_MERGE(type))
Expand Down Expand Up @@ -295,17 +293,16 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list)

static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos)
{
struct ovl_cache_entry *p;
struct list_head *p;
loff_t off = 0;

list_for_each_entry(p, &od->cache->entries, l_node) {
if (p->is_cursor)
continue;
list_for_each(p, &od->cache->entries) {
if (off >= pos)
break;
off++;
}
list_move_tail(&od->cursor.l_node, &p->l_node);
/* Cursor is safe since the cache is stable */
od->cursor = p;
}

static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
Expand Down Expand Up @@ -344,6 +341,7 @@ 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;
struct ovl_cache_entry *p;

if (!ctx->pos)
ovl_dir_reset(file);
Expand All @@ -362,19 +360,13 @@ 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;

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);
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++;
}
return 0;
}
Expand Down Expand Up @@ -493,11 +485,9 @@ 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;
file->private_data = od;

return 0;
Expand Down

0 comments on commit 4330397

Please sign in to comment.