On 11/11/16 11:05 AM, Omar Sandoval wrote:
> On Sat, Nov 05, 2016 at 01:26:34PM -0400, jeffm@xxxxxxxx wrote:
>> From: Jeff Mahoney <jeffm@xxxxxxxx>
>>
>> Commit 3de4586c527 (Btrfs: Allow subvolumes and snapshots anywhere
>> in the directory tree) introduced the current system of placing
>> snapshots in the directory tree. It also introduced the behavior of
>> creating the snapshot and then creating the directory entries for it.
>>
>> We've kept this code around for compatibility reasons, but it turns
>> out that no file systems with the old tree_root based snapshots can
>> be mounted on newer (>= 2009) kernels anyway. About a month after the
>> above commit, commit 2a7108ad89e (Btrfs: rev the disk format for the
>> inode compat and csum selection changes) landed, changing the superblock
>> magic number.
>>
>> As a result, we know that we'll never encounter tree_root-based dirents
>> or have to deal with skipping our own snapshot dirents. Since that
>> also means that we're now only iterating over DIR_INDEX items, which only
>> contain one directory entry per leaf item, we don't need to loop over
>> the leaf item contents anymore either.
>>
>> Signed-off-by: Jeff Mahoney <jeffm@xxxxxxxx>
>
> Hi, Jeff,
Hi Omar -
> One comment below.
>
>> ---
>> fs/btrfs/inode.c | 118 +++++++++++++++++--------------------------------------
>> 1 file changed, 37 insertions(+), 81 deletions(-)
>>
>> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
>> index 2b790bd..c52239d 100644
>> --- a/fs/btrfs/inode.c
>> +++ b/fs/btrfs/inode.c
>> @@ -5805,20 +5805,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;
>> @@ -5829,14 +5822,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);
>>
>> @@ -5862,85 +5852,53 @@ 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;
>
> Shouldn't this line (getting rid of emitted) be in the next patch?
Yep. Good catch.
Thanks,
-Jeff
>> - 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
>> @@ -5971,12 +5929,10 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
>> * 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:
>> --
>> 2.7.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
>> the body of a message to majordomo@xxxxxxxxxxxxxxx
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Jeff Mahoney
SUSE Labs
Attachment:
signature.asc
Description: OpenPGP digital signature
