|
@@ -5716,6 +5716,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
|
|
char *name_ptr;
|
|
char *name_ptr;
|
|
int name_len;
|
|
int name_len;
|
|
int is_curr = 0; /* ctx->pos points to the current index? */
|
|
int is_curr = 0; /* ctx->pos points to the current index? */
|
|
|
|
+ bool emitted;
|
|
|
|
|
|
/* FIXME, use a real flag for deciding about the key type */
|
|
/* FIXME, use a real flag for deciding about the key type */
|
|
if (root->fs_info->tree_root == root)
|
|
if (root->fs_info->tree_root == root)
|
|
@@ -5744,6 +5745,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
goto err;
|
|
goto err;
|
|
|
|
|
|
|
|
+ emitted = false;
|
|
while (1) {
|
|
while (1) {
|
|
leaf = path->nodes[0];
|
|
leaf = path->nodes[0];
|
|
slot = path->slots[0];
|
|
slot = path->slots[0];
|
|
@@ -5823,6 +5825,7 @@ skip:
|
|
|
|
|
|
if (over)
|
|
if (over)
|
|
goto nopos;
|
|
goto nopos;
|
|
|
|
+ emitted = true;
|
|
di_len = btrfs_dir_name_len(leaf, di) +
|
|
di_len = btrfs_dir_name_len(leaf, di) +
|
|
btrfs_dir_data_len(leaf, di) + sizeof(*di);
|
|
btrfs_dir_data_len(leaf, di) + sizeof(*di);
|
|
di_cur += di_len;
|
|
di_cur += di_len;
|
|
@@ -5835,11 +5838,20 @@ next:
|
|
if (key_type == BTRFS_DIR_INDEX_KEY) {
|
|
if (key_type == BTRFS_DIR_INDEX_KEY) {
|
|
if (is_curr)
|
|
if (is_curr)
|
|
ctx->pos++;
|
|
ctx->pos++;
|
|
- ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
|
|
|
|
|
|
+ ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
|
|
if (ret)
|
|
if (ret)
|
|
goto nopos;
|
|
goto nopos;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * If we haven't emitted any dir entry, we must not touch ctx->pos as
|
|
|
|
+ * it was was set to the termination value in previous call. We assume
|
|
|
|
+ * that "." and ".." were emitted if we reach this point and set the
|
|
|
|
+ * termination value as well for an empty directory.
|
|
|
|
+ */
|
|
|
|
+ if (ctx->pos > 2 && !emitted)
|
|
|
|
+ goto nopos;
|
|
|
|
+
|
|
/* Reached end of directory/root. Bump pos past the last item. */
|
|
/* Reached end of directory/root. Bump pos past the last item. */
|
|
ctx->pos++;
|
|
ctx->pos++;
|
|
|
|
|