btrfs: reduce width for stripe_len from u64 to u32
authorQu Wenruo <wqu@suse.com>
Tue, 12 Apr 2022 09:32:51 +0000 (17:32 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 May 2022 15:03:14 +0000 (17:03 +0200)
Currently btrfs uses fixed stripe length (64K), thus u32 is wide enough
for the usage.

Furthermore, even in the future we choose to enlarge stripe length to
larger values, I don't believe we would want stripe as large as 4G or
larger.

So this patch will reduce the width for all in-memory structures and
parameters, this involves:

- RAID56 related function argument lists
  This allows us to do direct division related to stripe_len.
  Although we will use bits shift to replace the division anyway.

- btrfs_io_geometry structure
  This involves one change to simplify the calculation of both @stripe_nr
  and @stripe_offset, using div64_u64_rem().
  And add extra sanity check to make sure @stripe_offset is always small
  enough for u32.

  This saves 8 bytes for the structure.

- map_lookup structure
  This convert @stripe_len to u32, which saves 8 bytes. (saved 4 bytes,
  and removed a 4-bytes hole)

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/raid56.c
fs/btrfs/raid56.h
fs/btrfs/volumes.c
fs/btrfs/volumes.h

index 79438cdd604ea779b4a749e35101ef1ac476774a..1db4395df21d35e7ace93d9d894c08a65b24bd6d 100644 (file)
@@ -949,9 +949,10 @@ static struct page *page_in_rbio(struct btrfs_raid_bio *rbio,
  * number of pages we need for the entire stripe across all the
  * drives
  */
-static unsigned long rbio_nr_pages(unsigned long stripe_len, int nr_stripes)
+static unsigned long rbio_nr_pages(u32 stripe_len, int nr_stripes)
 {
-       return DIV_ROUND_UP(stripe_len, PAGE_SIZE) * nr_stripes;
+       ASSERT(IS_ALIGNED(stripe_len, PAGE_SIZE));
+       return (stripe_len >> PAGE_SHIFT) * nr_stripes;
 }
 
 /*
@@ -960,13 +961,13 @@ static unsigned long rbio_nr_pages(unsigned long stripe_len, int nr_stripes)
  */
 static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
                                         struct btrfs_io_context *bioc,
-                                        u64 stripe_len)
+                                        u32 stripe_len)
 {
        struct btrfs_raid_bio *rbio;
        int nr_data = 0;
        int real_stripes = bioc->num_stripes - bioc->num_tgtdevs;
        int num_pages = rbio_nr_pages(stripe_len, real_stripes);
-       int stripe_npages = DIV_ROUND_UP(stripe_len, PAGE_SIZE);
+       int stripe_npages = stripe_len >> PAGE_SHIFT;
        void *p;
 
        rbio = kzalloc(sizeof(*rbio) +
@@ -1691,8 +1692,7 @@ static void btrfs_raid_unplug(struct blk_plug_cb *cb, bool from_schedule)
 /*
  * our main entry point for writes from the rest of the FS.
  */
-int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc,
-                       u64 stripe_len)
+int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc, u32 stripe_len)
 {
        struct btrfs_fs_info *fs_info = bioc->fs_info;
        struct btrfs_raid_bio *rbio;
@@ -2089,7 +2089,7 @@ cleanup:
  * of the drive.
  */
 int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
-                         u64 stripe_len, int mirror_num, int generic_io)
+                         u32 stripe_len, int mirror_num, int generic_io)
 {
        struct btrfs_fs_info *fs_info = bioc->fs_info;
        struct btrfs_raid_bio *rbio;
@@ -2195,7 +2195,7 @@ static void read_rebuild_work(struct btrfs_work *work)
 
 struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
                                struct btrfs_io_context *bioc,
-                               u64 stripe_len, struct btrfs_device *scrub_dev,
+                               u32 stripe_len, struct btrfs_device *scrub_dev,
                                unsigned long *dbitmap, int stripe_nsectors)
 {
        struct btrfs_fs_info *fs_info = bioc->fs_info;
index 72c00fc284b55373d08a6c93221c6c4bdbd48646..006b4741e5c13fa96fecb959120cda054d408f5f 100644 (file)
@@ -31,15 +31,14 @@ struct btrfs_raid_bio;
 struct btrfs_device;
 
 int raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
-                         u64 stripe_len, int mirror_num, int generic_io);
-int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc,
-                       u64 stripe_len);
+                         u32 stripe_len, int mirror_num, int generic_io);
+int raid56_parity_write(struct bio *bio, struct btrfs_io_context *bioc, u32 stripe_len);
 
 void raid56_add_scrub_pages(struct btrfs_raid_bio *rbio, struct page *page,
                            u64 logical);
 
 struct btrfs_raid_bio *raid56_parity_alloc_scrub_rbio(struct bio *bio,
-                               struct btrfs_io_context *bioc, u64 stripe_len,
+                               struct btrfs_io_context *bioc, u32 stripe_len,
                                struct btrfs_device *scrub_dev,
                                unsigned long *dbitmap, int stripe_nsectors);
 void raid56_parity_submit_scrub_rbio(struct btrfs_raid_bio *rbio);
index 6ab1b71a5df02dffa39e2904c18aa9d45036a849..ba1e7f1b9a7236e196d56917b760c63182581d25 100644 (file)
@@ -6313,7 +6313,7 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, struct extent_map *em,
        u64 offset;
        u64 stripe_offset;
        u64 stripe_nr;
-       u64 stripe_len;
+       u32 stripe_len;
        u64 raid56_full_stripe_start = (u64)-1;
        int data_stripes;
 
@@ -6324,19 +6324,13 @@ int btrfs_get_io_geometry(struct btrfs_fs_info *fs_info, struct extent_map *em,
        offset = logical - em->start;
        /* Len of a stripe in a chunk */
        stripe_len = map->stripe_len;
-       /* Stripe where this block falls in */
-       stripe_nr = div64_u64(offset, stripe_len);
-       /* Offset of stripe in the chunk */
-       stripe_offset = stripe_nr * stripe_len;
-       if (offset < stripe_offset) {
-               btrfs_crit(fs_info,
-"stripe math has gone wrong, stripe_offset=%llu offset=%llu start=%llu logical=%llu stripe_len=%llu",
-                       stripe_offset, offset, em->start, logical, stripe_len);
-               return -EINVAL;
-       }
+       /*
+        * Stripe_nr is where this block falls in
+        * stripe_offset is the offset of this block in its stripe.
+        */
+       stripe_nr = div64_u64_rem(offset, stripe_len, &stripe_offset);
+       ASSERT(stripe_offset < U32_MAX);
 
-       /* stripe_offset is the offset of this block in its stripe */
-       stripe_offset = offset - stripe_offset;
        data_stripes = nr_data_stripes(map);
 
        /* Only stripe based profiles needs to check against stripe length. */
index f3e28f11cfb6e606ab4cdb14d8f45bb2352f85e8..197877e684df47fb0d7906e8598270e5d7b2c110 100644 (file)
@@ -23,11 +23,11 @@ struct btrfs_io_geometry {
        /* offset of logical address in chunk */
        u64 offset;
        /* length of single IO stripe */
-       u64 stripe_len;
+       u32 stripe_len;
+       /* offset of address in stripe */
+       u32 stripe_offset;
        /* number of stripe where address falls */
        u64 stripe_nr;
-       /* offset of address in stripe */
-       u64 stripe_offset;
        /* offset of raid56 stripe into the chunk */
        u64 raid56_stripe_offset;
 };
@@ -430,7 +430,7 @@ struct map_lookup {
        u64 type;
        int io_align;
        int io_width;
-       u64 stripe_len;
+       u32 stripe_len;
        int num_stripes;
        int sub_stripes;
        int verified_stripes; /* For mount time dev extent verification */