|
@@ -5804,20 +5804,13 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
|
|
|
int slot;
|
|
|
unsigned char d_type;
|
|
|
int over = 0;
|
|
|
- u32 di_cur;
|
|
|
- u32 di_total;
|
|
|
- u32 di_len;
|
|
|
- int key_type = BTRFS_DIR_INDEX_KEY;
|
|
|
char tmp_name[32];
|
|
|
char *name_ptr;
|
|
|
int name_len;
|
|
|
int is_curr = 0; /* ctx->pos points to the current index? */
|
|
|
bool emitted;
|
|
|
bool put = false;
|
|
|
-
|
|
|
- /* FIXME, use a real flag for deciding about the key type */
|
|
|
- if (root->fs_info->tree_root == root)
|
|
|
- key_type = BTRFS_DIR_ITEM_KEY;
|
|
|
+ struct btrfs_key location;
|
|
|
|
|
|
if (!dir_emit_dots(file, ctx))
|
|
|
return 0;
|
|
@@ -5828,14 +5821,11 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
|
|
|
|
|
|
path->reada = READA_FORWARD;
|
|
|
|
|
|
- if (key_type == BTRFS_DIR_INDEX_KEY) {
|
|
|
- INIT_LIST_HEAD(&ins_list);
|
|
|
- INIT_LIST_HEAD(&del_list);
|
|
|
- put = btrfs_readdir_get_delayed_items(inode, &ins_list,
|
|
|
- &del_list);
|
|
|
- }
|
|
|
+ INIT_LIST_HEAD(&ins_list);
|
|
|
+ INIT_LIST_HEAD(&del_list);
|
|
|
+ put = btrfs_readdir_get_delayed_items(inode, &ins_list, &del_list);
|
|
|
|
|
|
- key.type = key_type;
|
|
|
+ key.type = BTRFS_DIR_INDEX_KEY;
|
|
|
key.offset = ctx->pos;
|
|
|
key.objectid = btrfs_ino(inode);
|
|
|
|
|
@@ -5861,85 +5851,54 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
|
|
|
|
|
|
if (found_key.objectid != key.objectid)
|
|
|
break;
|
|
|
- if (found_key.type != key_type)
|
|
|
+ if (found_key.type != BTRFS_DIR_INDEX_KEY)
|
|
|
break;
|
|
|
if (found_key.offset < ctx->pos)
|
|
|
goto next;
|
|
|
- if (key_type == BTRFS_DIR_INDEX_KEY &&
|
|
|
- btrfs_should_delete_dir_index(&del_list,
|
|
|
- found_key.offset))
|
|
|
+ if (btrfs_should_delete_dir_index(&del_list, found_key.offset))
|
|
|
goto next;
|
|
|
|
|
|
ctx->pos = found_key.offset;
|
|
|
is_curr = 1;
|
|
|
|
|
|
di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
|
|
|
- di_cur = 0;
|
|
|
- di_total = btrfs_item_size(leaf, item);
|
|
|
-
|
|
|
- while (di_cur < di_total) {
|
|
|
- struct btrfs_key location;
|
|
|
-
|
|
|
- if (verify_dir_item(root, leaf, di))
|
|
|
- break;
|
|
|
+ if (verify_dir_item(root, leaf, di))
|
|
|
+ goto next;
|
|
|
|
|
|
- name_len = btrfs_dir_name_len(leaf, di);
|
|
|
- if (name_len <= sizeof(tmp_name)) {
|
|
|
- name_ptr = tmp_name;
|
|
|
- } else {
|
|
|
- name_ptr = kmalloc(name_len, GFP_KERNEL);
|
|
|
- if (!name_ptr) {
|
|
|
- ret = -ENOMEM;
|
|
|
- goto err;
|
|
|
- }
|
|
|
+ name_len = btrfs_dir_name_len(leaf, di);
|
|
|
+ if (name_len <= sizeof(tmp_name)) {
|
|
|
+ name_ptr = tmp_name;
|
|
|
+ } else {
|
|
|
+ name_ptr = kmalloc(name_len, GFP_KERNEL);
|
|
|
+ if (!name_ptr) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto err;
|
|
|
}
|
|
|
- read_extent_buffer(leaf, name_ptr,
|
|
|
- (unsigned long)(di + 1), name_len);
|
|
|
-
|
|
|
- d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
|
|
|
- btrfs_dir_item_key_to_cpu(leaf, di, &location);
|
|
|
+ }
|
|
|
+ read_extent_buffer(leaf, name_ptr, (unsigned long)(di + 1),
|
|
|
+ name_len);
|
|
|
|
|
|
+ d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
|
|
|
+ btrfs_dir_item_key_to_cpu(leaf, di, &location);
|
|
|
|
|
|
- /* is this a reference to our own snapshot? If so
|
|
|
- * skip it.
|
|
|
- *
|
|
|
- * In contrast to old kernels, we insert the snapshot's
|
|
|
- * dir item and dir index after it has been created, so
|
|
|
- * we won't find a reference to our own snapshot. We
|
|
|
- * still keep the following code for backward
|
|
|
- * compatibility.
|
|
|
- */
|
|
|
- if (location.type == BTRFS_ROOT_ITEM_KEY &&
|
|
|
- location.objectid == root->root_key.objectid) {
|
|
|
- over = 0;
|
|
|
- goto skip;
|
|
|
- }
|
|
|
- over = !dir_emit(ctx, name_ptr, name_len,
|
|
|
- location.objectid, d_type);
|
|
|
+ over = !dir_emit(ctx, name_ptr, name_len, location.objectid,
|
|
|
+ d_type);
|
|
|
|
|
|
-skip:
|
|
|
- if (name_ptr != tmp_name)
|
|
|
- kfree(name_ptr);
|
|
|
+ if (name_ptr != tmp_name)
|
|
|
+ kfree(name_ptr);
|
|
|
|
|
|
- if (over)
|
|
|
- goto nopos;
|
|
|
emitted = true;
|
|
|
- di_len = btrfs_dir_name_len(leaf, di) +
|
|
|
- btrfs_dir_data_len(leaf, di) + sizeof(*di);
|
|
|
- di_cur += di_len;
|
|
|
- di = (struct btrfs_dir_item *)((char *)di + di_len);
|
|
|
- }
|
|
|
+ if (over)
|
|
|
+ goto nopos;
|
|
|
next:
|
|
|
path->slots[0]++;
|
|
|
}
|
|
|
|
|
|
- if (key_type == BTRFS_DIR_INDEX_KEY) {
|
|
|
- if (is_curr)
|
|
|
- ctx->pos++;
|
|
|
- ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
|
|
|
- if (ret)
|
|
|
- goto nopos;
|
|
|
- }
|
|
|
+ if (is_curr)
|
|
|
+ ctx->pos++;
|
|
|
+ ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
|
|
|
+ if (ret)
|
|
|
+ goto nopos;
|
|
|
|
|
|
/*
|
|
|
* If we haven't emitted any dir entry, we must not touch ctx->pos as
|
|
@@ -5970,12 +5929,10 @@ next:
|
|
|
* last entry requires it because doing so has broken 32bit apps
|
|
|
* in the past.
|
|
|
*/
|
|
|
- if (key_type == BTRFS_DIR_INDEX_KEY) {
|
|
|
- if (ctx->pos >= INT_MAX)
|
|
|
- ctx->pos = LLONG_MAX;
|
|
|
- else
|
|
|
- ctx->pos = INT_MAX;
|
|
|
- }
|
|
|
+ if (ctx->pos >= INT_MAX)
|
|
|
+ ctx->pos = LLONG_MAX;
|
|
|
+ else
|
|
|
+ ctx->pos = INT_MAX;
|
|
|
nopos:
|
|
|
ret = 0;
|
|
|
err:
|