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.
Unified · Split
| @@ -24,7 +24,6 @@ struct ovl_cache_entry { · 23 unmodified lines | ||
| 24 | 24 | struct list_head l_node; |
| 25 | 25 | struct rb_node node; |
| 26 | 26 | bool is_whiteout; |
| 27 | − bool is_cursor; | |
| 28 | 27 | char name[]; |
| 29 | 28 | }; |
| 30 | 29 | |
| @@ -49,7 +48,7 @@ struct ovl_dir_file { · 18 unmodified lines | ||
| 49 | 48 | bool is_real; |
| 50 | 49 | bool is_upper; |
| 51 | 50 | struct ovl_dir_cache *cache; |
| 52 | − struct ovl_cache_entry cursor; | |
| 51 | + struct list_head *cursor; | |
| 53 | 52 | struct file *realfile; |
| 54 | 53 | struct file *upperfile; |
| 55 | 54 | }; |
| @@ -97,7 +96,6 @@ static struct ovl_cache_entry *ovl_cache_entry_new(struct dentry *dir, · 41 unmodified lines | ||
| 97 | 96 | p->type = d_type; |
| 98 | 97 | p->ino = ino; |
| 99 | 98 | p->is_whiteout = false; |
| 100 | − p->is_cursor = false; | |
| 101 | 99 | |
| 102 | 100 | if (d_type == DT_CHR) { |
| 103 | 101 | struct dentry *dentry; |
| @@ -196,7 +194,6 @@ static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry) · 92 unmodified lines | ||
| 196 | 194 | { |
| 197 | 195 | struct ovl_dir_cache *cache = od->cache; |
| 198 | 196 | |
| 199 | − list_del_init(&od->cursor.l_node); | |
| 200 | 197 | WARN_ON(cache->refcount <= 0); |
| 201 | 198 | cache->refcount--; |
| 202 | 199 | if (!cache->refcount) { |
| @@ -254,6 +251,7 @@ static void ovl_dir_reset(struct file *file) · 51 unmodified lines | ||
| 254 | 251 | if (cache && ovl_dentry_version_get(dentry) != cache->version) { |
| 255 | 252 | ovl_cache_put(od, dentry); |
| 256 | 253 | od->cache = NULL; |
| 254 | + od->cursor = NULL; | |
| 257 | 255 | } |
| 258 | 256 | WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type)); |
| 259 | 257 | 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) · 35 unmodified lines | ||
| 295 | 293 | |
| 296 | 294 | static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) |
| 297 | 295 | { |
| 298 | − struct ovl_cache_entry *p; | |
| 296 | + struct list_head *p; | |
| 299 | 297 | loff_t off = 0; |
| 300 | 298 | |
| 301 | − list_for_each_entry(p, &od->cache->entries, l_node) { | |
| 302 | − if (p->is_cursor) | |
| 303 | − continue; | |
| 299 | + list_for_each(p, &od->cache->entries) { | |
| 304 | 300 | if (off >= pos) |
| 305 | 301 | break; |
| 306 | 302 | off++; |
| 307 | 303 | } |
| 308 | − list_move_tail(&od->cursor.l_node, &p->l_node); | |
| 304 | + /* Cursor is safe since the cache is stable */ | |
| 305 | + od->cursor = p; | |
| 309 | 306 | } |
| 310 | 307 | |
| 311 | 308 | 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) · 32 unmodified lines | ||
| 344 | 341 | { |
| 345 | 342 | struct ovl_dir_file *od = file->private_data; |
| 346 | 343 | struct dentry *dentry = file->f_path.dentry; |
| 344 | + struct ovl_cache_entry *p; | |
| 347 | 345 | |
| 348 | 346 | if (!ctx->pos) |
| 349 | 347 | ovl_dir_reset(file); |
| @@ -362,19 +360,13 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) · 12 unmodified lines | ||
| 362 | 360 | ovl_seek_cursor(od, ctx->pos); |
| 363 | 361 | } |
| 364 | 362 | |
| 365 | − while (od->cursor.l_node.next != &od->cache->entries) { | |
| 366 | − struct ovl_cache_entry *p; | |
| 367 | − | |
| 368 | − p = list_entry(od->cursor.l_node.next, struct ovl_cache_entry, l_node); | |
| 369 | − /* Skip cursors */ | |
| 370 | − if (!p->is_cursor) { | |
| 371 | − if (!p->is_whiteout) { | |
| 372 | − if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) | |
| 373 | − break; | |
| 374 | − } | |
| 375 | − ctx->pos++; | |
| 376 | − } | |
| 377 | − list_move(&od->cursor.l_node, &p->l_node); | |
| 363 | + while (od->cursor != &od->cache->entries) { | |
| 364 | + p = list_entry(od->cursor, struct ovl_cache_entry, l_node); | |
| 365 | + if (!p->is_whiteout) | |
| 366 | + if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) | |
| 367 | + break; | |
| 368 | + od->cursor = p->l_node.next; | |
| 369 | + ctx->pos++; | |
| 378 | 370 | } |
| 379 | 371 | return 0; |
| 380 | 372 | } |
| @@ -493,11 +485,9 @@ static int ovl_dir_open(struct inode *inode, struct file *file) · 112 unmodified lines | ||
| 493 | 485 | kfree(od); |
| 494 | 486 | return PTR_ERR(realfile); |
| 495 | 487 | } |
| 496 | − INIT_LIST_HEAD(&od->cursor.l_node); | |
| 497 | 488 | od->realfile = realfile; |
| 498 | 489 | od->is_real = !OVL_TYPE_MERGE(type); |
| 499 | 490 | od->is_upper = OVL_TYPE_UPPER(type); |
| 500 | − od->cursor.is_cursor = true; | |
| 501 | 491 | file->private_data = od; |
| 502 | 492 | |
| 503 | 493 | return 0; |