mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-13 21:02:35 +00:00
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>
This commit is contained in:
parent
6d900f5a33
commit
4330397e4e
@ -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,19 +360,13 @@ 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);
|
if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
|
||||||
/* Skip cursors */
|
break;
|
||||||
if (!p->is_cursor) {
|
od->cursor = p->l_node.next;
|
||||||
if (!p->is_whiteout) {
|
ctx->pos++;
|
||||||
if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user