Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4330397e authored by hujianyang's avatar hujianyang Committed by Miklos Szeredi
Browse files

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: default avatarhujianyang <hujianyang@huawei.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
parent 6d900f5a
Loading
Loading
Loading
Loading
+14 −24
Original line number Original line Diff line number Diff line
@@ -24,7 +24,6 @@ struct ovl_cache_entry {
	struct list_head l_node;
	struct list_head l_node;
	struct rb_node node;
	struct rb_node node;
	bool is_whiteout;
	bool is_whiteout;
	bool is_cursor;
	char name[];
	char name[];
};
};


@@ -49,7 +48,7 @@ struct ovl_dir_file {
	bool is_real;
	bool is_real;
	bool is_upper;
	bool is_upper;
	struct ovl_dir_cache *cache;
	struct ovl_dir_cache *cache;
	struct ovl_cache_entry cursor;
	struct list_head *cursor;
	struct file *realfile;
	struct file *realfile;
	struct file *upperfile;
	struct file *upperfile;
};
};
@@ -97,7 +96,6 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct dentry *dir,
	p->type = d_type;
	p->type = d_type;
	p->ino = ino;
	p->ino = ino;
	p->is_whiteout = false;
	p->is_whiteout = false;
	p->is_cursor = false;


	if (d_type == DT_CHR) {
	if (d_type == DT_CHR) {
		struct dentry *dentry;
		struct dentry *dentry;
@@ -196,7 +194,6 @@ static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry)
{
{
	struct ovl_dir_cache *cache = od->cache;
	struct ovl_dir_cache *cache = od->cache;


	list_del_init(&od->cursor.l_node);
	WARN_ON(cache->refcount <= 0);
	WARN_ON(cache->refcount <= 0);
	cache->refcount--;
	cache->refcount--;
	if (!cache->refcount) {
	if (!cache->refcount) {
@@ -254,6 +251,7 @@ static void ovl_dir_reset(struct file *file)
	if (cache && ovl_dentry_version_get(dentry) != cache->version) {
	if (cache && ovl_dentry_version_get(dentry) != cache->version) {
		ovl_cache_put(od, dentry);
		ovl_cache_put(od, dentry);
		od->cache = NULL;
		od->cache = NULL;
		od->cursor = NULL;
	}
	}
	WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
	WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type));
	if (od->is_real && OVL_TYPE_MERGE(type))
	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)


static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos)
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;
	loff_t off = 0;


	list_for_each_entry(p, &od->cache->entries, l_node) {
	list_for_each(p, &od->cache->entries) {
		if (p->is_cursor)
			continue;
		if (off >= pos)
		if (off >= pos)
			break;
			break;
		off++;
		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)
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)
{
{
	struct ovl_dir_file *od = file->private_data;
	struct ovl_dir_file *od = file->private_data;
	struct dentry *dentry = file->f_path.dentry;
	struct dentry *dentry = file->f_path.dentry;
	struct ovl_cache_entry *p;


	if (!ctx->pos)
	if (!ctx->pos)
		ovl_dir_reset(file);
		ovl_dir_reset(file);
@@ -362,20 +360,14 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
		ovl_seek_cursor(od, ctx->pos);
		ovl_seek_cursor(od, ctx->pos);
	}
	}


	while (od->cursor.l_node.next != &od->cache->entries) {
	while (od->cursor != &od->cache->entries) {
		struct ovl_cache_entry *p;
		p = list_entry(od->cursor, struct ovl_cache_entry, l_node);

		if (!p->is_whiteout)
		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))
			if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
				break;
				break;
			}
		od->cursor = p->l_node.next;
		ctx->pos++;
		ctx->pos++;
	}
	}
		list_move(&od->cursor.l_node, &p->l_node);
	}
	return 0;
	return 0;
}
}


@@ -493,11 +485,9 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
		kfree(od);
		kfree(od);
		return PTR_ERR(realfile);
		return PTR_ERR(realfile);
	}
	}
	INIT_LIST_HEAD(&od->cursor.l_node);
	od->realfile = realfile;
	od->realfile = realfile;
	od->is_real = !OVL_TYPE_MERGE(type);
	od->is_real = !OVL_TYPE_MERGE(type);
	od->is_upper = OVL_TYPE_UPPER(type);
	od->is_upper = OVL_TYPE_UPPER(type);
	od->cursor.is_cursor = true;
	file->private_data = od;
	file->private_data = od;


	return 0;
	return 0;