Re: [PATCH] btrfs-progs: calculate disk space that a subvol could free upon delete

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Anand,

1) so let's say I have a subvolume and a snapshot of this subvolume.
So in this case, I will see "Sole space = 0" for both of them,
correct? Because all extents (except inline ones) are shared.

2) How is this in terms of responsiveness? On a huge subvolume, we
need to iterate all the EXTENT_DATAs and then lookup their
EXTENT_ITEMs.

3) So it's kind of poor man's replacement for quota groups, correct?

I like that it's so easy to check for exclusive data, though:)

Alex.


On Fri, Sep 13, 2013 at 6:44 PM, Wang Shilong <wangshilong1991@xxxxxxxxx> wrote:
>
> Hello Anand,
>
>> (This patch is for review and comments only)
>>
>> This patch provides a way to know how much space can be
>> relinquished if when subvol /snapshot is deleted.  With
>> this sys admin can make better judgments in managing the
>> filesystem when fs is near full.
>>
>
> I think this is really *helpful* since users can not really know how much
> space(Exclusive) in a subvolume .
>
> Thanks,
> Wang
>
>> as shown below the parameter 'sole space' indicates the size
>> which is freed when subvol is deleted. (any other better
>> term for this?, pls suggest).
>> ---------------------
>> btrfs su show /btrfs/sv1
>> /btrfs/sv1
>>       Name:                   sv1
>>       uuid:                   b078ba48-d4a5-2f49-ac03-9bd1d56cc768
>>       Parent uuid:            -
>>       Creation time:          2013-09-13 18:17:32
>>       Object ID:              257
>>       Generation (Gen):       18
>>       Gen at creation:        17
>>       Parent:                 5
>>       Top Level:              5
>>       Flags:                  -
>>       Sole space:             1.56MiB <----
>>       Snapshot(s):
>>
>> btrfs su snap /btrfs/sv1 /btrfs/ss2
>> Create a snapshot of '/btrfs/sv1' in '/btrfs/ss2'
>>
>> btrfs su show /btrfs/sv1
>> /btrfs/sv1
>>       Name:                   sv1
>>       uuid:                   b078ba48-d4a5-2f49-ac03-9bd1d56cc768
>>       Parent uuid:            -
>>       Creation time:          2013-09-13 18:17:32
>>       Object ID:              257
>>       Generation (Gen):       19
>>       Gen at creation:        17
>>       Parent:                 5
>>       Top Level:              5
>>       Flags:                  -
>>       Sole space:             0.00  <-----
>>       Snapshot(s):
>>                               ss2
>> ---------------------
>>
>> Signed-off-by: Anand Jain <anand.jain@xxxxxxxxxx>
>> ---
>> cmds-subvolume.c |   5 ++
>> utils.c          | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> utils.h          |   1 +
>> 3 files changed, 160 insertions(+)
>>
>> diff --git a/cmds-subvolume.c b/cmds-subvolume.c
>> index de246ab..2b02d66 100644
>> --- a/cmds-subvolume.c
>> +++ b/cmds-subvolume.c
>> @@ -809,6 +809,7 @@ static int cmd_subvol_show(int argc, char **argv)
>>       int fd = -1, mntfd = -1;
>>       int ret = 1;
>>       DIR *dirstream1 = NULL, *dirstream2 = NULL;
>> +     u64 freeable_bytes;
>>
>>       if (check_argc_exact(argc, 2))
>>               usage(cmd_subvol_show_usage);
>> @@ -878,6 +879,8 @@ static int cmd_subvol_show(int argc, char **argv)
>>               goto out;
>>       }
>>
>> +     freeable_bytes = get_subvol_freeable_bytes(fd);
>> +
>>       ret = 0;
>>       /* print the info */
>>       printf("%s\n", fullpath);
>> @@ -915,6 +918,8 @@ static int cmd_subvol_show(int argc, char **argv)
>>       else
>>               printf("\tFlags: \t\t\t-\n");
>>
>> +     printf("\tSole space: \t\t%s\n",
>> +             pretty_size(freeable_bytes));
>>       /* print the snapshots of the given subvol if any*/
>>       printf("\tSnapshot(s):\n");
>>       filter_set = btrfs_list_alloc_filter_set();
>> diff --git a/utils.c b/utils.c
>> index 22c3310..f01d580 100644
>> --- a/utils.c
>> +++ b/utils.c
>> @@ -2019,3 +2019,157 @@ int is_dev_excl_op_free(int fd)
>>       ret = ioctl(fd, BTRFS_IOC_CHECK_DEV_EXCL_OPS, NULL);
>>       return ret > 0 ? ret : -errno;
>> }
>> +
>> +/* gets the ref count for given extent
>> + * 0 = didn't find the item
>> + * n = number of references
>> +*/
>> +u64 get_extent_refcnt(int fd, u64 disk_blk)
>> +{
>> +     int ret = 0, i, e;
>> +     struct btrfs_ioctl_search_args args;
>> +     struct btrfs_ioctl_search_key *sk = &args.key;
>> +     struct btrfs_ioctl_search_header sh;
>> +     unsigned long off = 0;
>> +
>> +     memset(&args, 0, sizeof(args));
>> +
>> +     sk->tree_id = BTRFS_EXTENT_TREE_OBJECTID;
>> +
>> +     sk->min_type = BTRFS_EXTENT_ITEM_KEY;
>> +     sk->max_type = BTRFS_EXTENT_ITEM_KEY;
>> +
>> +     sk->min_objectid = disk_blk;
>> +     sk->max_objectid = disk_blk;
>> +
>> +     sk->max_offset = (u64)-1;
>> +     sk->max_transid = (u64)-1;
>> +
>> +     while (1) {
>> +             sk->nr_items = 4096;
>> +
>> +             ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
>> +             e = errno;
>> +             if (ret < 0) {
>> +                     fprintf(stderr, "ERROR: search failed - %s\n",
>> +                             strerror(e));
>> +                     return 0;
>> +             }
>> +             if (sk->nr_items == 0)
>> +                     break;
>> +
>> +             off = 0;
>> +             for (i = 0; i < sk->nr_items; i++) {
>> +                     struct btrfs_extent_item *ei;
>> +                     u64 ref;
>> +
>> +                     memcpy(&sh, args.buf + off, sizeof(sh));
>> +                     off += sizeof(sh);
>> +
>> +                     if (sh.type != BTRFS_EXTENT_ITEM_KEY) {
>> +                             off += sh.len;
>> +                             continue;
>> +                     }
>> +
>> +                     ei = (struct btrfs_extent_item *)(args.buf + off);
>> +                     ref = btrfs_stack_extent_refs(ei);
>> +                     return ref;
>> +             }
>> +             sk->min_objectid = sh.objectid;
>> +             sk->min_offset = sh.offset;
>> +             sk->min_type = sh.type;
>> +             if (sk->min_offset < (u64)-1)
>> +                     sk->min_offset++;
>> +             else if (sk->min_objectid < (u64)-1) {
>> +                     sk->min_objectid++;
>> +                     sk->min_offset = 0;
>> +                     sk->min_type = 0;
>> +             } else
>> +                     break;
>> +     }
>> +     return 0;
>> +}
>> +
>> +u64 get_subvol_freeable_bytes(int fd)
>> +{
>> +     int ret = 0, i, e;
>> +     struct btrfs_ioctl_search_args args;
>> +     struct btrfs_ioctl_search_key *sk = &args.key;
>> +     struct btrfs_ioctl_search_header sh;
>> +     unsigned long off = 0;
>> +     u64 size_bytes = 0;
>> +
>> +     memset(&args, 0, sizeof(args));
>> +
>> +     sk->tree_id = 0;
>> +
>> +     sk->min_type = BTRFS_EXTENT_DATA_KEY;
>> +     sk->max_type = BTRFS_EXTENT_DATA_KEY;
>> +
>> +     sk->max_objectid = (u64) -1;
>> +     sk->max_offset = (u64)-1;
>> +     sk->max_transid = (u64)-1;
>> +
>> +     while (1) {
>> +             sk->nr_items = 4096;
>> +
>> +             ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
>> +             e = errno;
>> +             if (ret < 0) {
>> +                     fprintf(stderr, "ERROR: search failed - %s\n",
>> +                             strerror(e));
>> +                     return 0;
>> +             }
>> +             if (sk->nr_items == 0)
>> +                     break;
>> +
>> +             off = 0;
>> +             for (i = 0; i < sk->nr_items; i++) {
>> +                     struct btrfs_file_extent_item *efi;
>> +                     u64 disk_bytenr = 0;
>> +                     u64 num_bytes = 0;
>> +                     u64 refcnt;
>> +                     u8 type;
>> +
>> +                     memcpy(&sh, args.buf + off, sizeof(sh));
>> +                     off += sizeof(sh);
>> +
>> +                     if (sh.type != BTRFS_EXTENT_DATA_KEY) {
>> +                             off += sh.len;
>> +                             continue;
>> +                     }
>> +
>> +                     efi = (struct btrfs_file_extent_item *)(args.buf + off);
>> +                     type = btrfs_stack_file_extent_type(efi);
>> +
>> +                     if (type == BTRFS_FILE_EXTENT_INLINE) {
>> +                             size_bytes +=
>> +                                     btrfs_stack_file_extent_ram_bytes(efi);
>> +                             goto skip_extent_data;
>> +                     }
>> +                     disk_bytenr = btrfs_stack_file_extent_disk_bytenr(efi);
>> +                     num_bytes = btrfs_stack_file_extent_num_bytes(efi);
>> +
>> +                     if (disk_bytenr) {
>> +                             refcnt = get_extent_refcnt(fd, disk_bytenr);
>> +                             if (refcnt == 1)
>> +                                     size_bytes += num_bytes;
>> +                     }
>> +skip_extent_data:
>> +                     off += sh.len;
>> +             }
>> +             sk->min_objectid = sh.objectid;
>> +             sk->min_offset = sh.offset;
>> +             sk->min_type = sh.type;
>> +
>> +             if (sk->min_offset < (u64)-1)
>> +                     sk->min_offset++;
>> +             else if (sk->min_objectid < (u64)-1) {
>> +                     sk->min_objectid++;
>> +                     sk->min_offset = 0;
>> +                     sk->min_type = 0;
>> +             } else
>> +                     break;
>> +     }
>> +     return size_bytes;
>> +}
>> diff --git a/utils.h b/utils.h
>> index 6952d34..0920bb3 100644
>> --- a/utils.h
>> +++ b/utils.h
>> @@ -86,4 +86,5 @@ int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
>>                          int verify);
>> int get_btrfs_mount(const char *dev, char *mp, size_t mp_size);
>> int is_dev_excl_op_free(int fd);
>> +u64 get_subvol_freeable_bytes(int fd);
>> #endif
>> --
>> 1.8.4.rc4.1.g0d8beaa
>>
>> --
>> 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
>
> --
> 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
--
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




[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux