[lvm-devel] data alignment of structures with 'status'

Mike Snitzer snitzer at redhat.com
Mon Nov 23 23:23:45 UTC 2009


I used F11's "dwarves" package's 'pahole' tool to analyze what impact
changing 'status' from 32-bits to 64-bits would have (on x86_64); more
info on dwarves and pahole here:
http://lwn.net/Articles/335942/
https://ols2006.108.redhat.com/2007/Reprints/melo-Reprint.pdf

As you can see below, if we reorganize the 'lv_segment' structure
slightly and increase status to 64-bit we are able to have a perfectly
aligned structure.

I'll soon be sending in a proper patch to extend 'status' of 
lv_segment, logical_volume, volume_group, and physical_volume
to be 64-bits.  Extending to 64-bits is mostly free because there was at
least 1 4-byte hole in all structures except logical_volume (But
'physical_volume' would still have a 4-byte hole; it currently has 2
4-byte holes).

BTW, I think it'd be worthwhile to audit all structures with pahole
(and the kernel's DM structures too?); here are some example savings
(eliminated all holes in the following):

cmd_context: saved 16 bytes and 1 cacheline!
physical_volume: saved 8 bytes! (this was without extending status)
volume_group: saved 4 bytes! (this was without extending status)
pvcreate_params: saved 8 bytes!
vgcreate_params: saved 4 bytes!
config_info: saved 8 bytes!
daemon_parms: saved 8 bytes!


with 32-bit status:

struct lv_segment {
        struct dm_list             list;                 /*     0    16 */
        struct logical_volume *    lv;                   /*    16     8 */
        const struct segment_type  * segtype;            /*    24     8 */
        uint32_t                   le;                   /*    32     4 */
        uint32_t                   len;                  /*    36     4 */
        uint32_t                   status;               /*    40     4 */
        uint32_t                   stripe_size;          /*    44     4 */
        uint32_t                   area_count;           /*    48     4 */
        uint32_t                   area_len;             /*    52     4 */
        struct logical_volume *    origin;               /*    56     8 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        struct logical_volume *    cow;                  /*    64     8 */
        struct dm_list             origin_list;          /*    72    16 */
        uint32_t                   chunk_size;           /*    88     4 */
        uint32_t                   region_size;          /*    92     4 */
        uint32_t                   extents_copied;       /*    96     4 */

        /* XXX 4 bytes hole, try to pack */

        struct logical_volume *    log_lv;               /*   104     8 */
        void *                     segtype_private;      /*   112     8 */
        struct dm_list             tags;                 /*   120    16 */
        /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
        struct lv_segment_area *   areas;                /*   136     8 */

        /* size: 144, cachelines: 3, members: 19 */
        /* sum members: 140, holes: 1, sum holes: 4 */
        /* last cacheline: 16 bytes */
};

with 64-bit status:

struct lv_segment {
        struct dm_list             list;                 /*     0    16 */
        struct logical_volume *    lv;                   /*    16     8 */
        const struct segment_type  * segtype;            /*    24     8 */
        uint32_t                   le;                   /*    32     4 */
        uint32_t                   len;                  /*    36     4 */
        uint64_t                   status;               /*    40     8 */
        uint32_t                   stripe_size;          /*    48     4 */
        uint32_t                   area_count;           /*    52     4 */
        uint32_t                   area_len;             /*    56     4 */

        /* XXX 4 bytes hole, try to pack */

        /* --- cacheline 1 boundary (64 bytes) --- */
        struct logical_volume *    origin;               /*    64     8 */
        struct logical_volume *    cow;                  /*    72     8 */
        struct dm_list             origin_list;          /*    80    16 */
        uint32_t                   chunk_size;           /*    96     4 */
        uint32_t                   region_size;          /*   100     4 */
        uint32_t                   extents_copied;       /*   104     4 */

        /* XXX 4 bytes hole, try to pack */

        struct logical_volume *    log_lv;               /*   112     8 */
        void *                     segtype_private;      /*   120     8 */
        /* --- cacheline 2 boundary (128 bytes) --- */
        struct dm_list             tags;                 /*   128    16 */
        struct lv_segment_area *   areas;                /*   144     8 */

        /* size: 152, cachelines: 3, members: 19 */
        /* sum members: 144, holes: 2, sum holes: 8 */
        /* last cacheline: 24 bytes */
};

with 64-bit status (alignment after reoragnizing):

$ pahole --show_reorg_steps --reorganize -C lv_segment metadata.o
/* Moving 'extents_copied' from after 'region_size' to after 'area_len' */
struct lv_segment {
        struct dm_list             list;                 /*     0    16 */
        struct logical_volume *    lv;                   /*    16     8 */
        const struct segment_type  * segtype;            /*    24     8 */
        uint32_t                   le;                   /*    32     4 */
        uint32_t                   len;                  /*    36     4 */
        uint64_t                   status;               /*    40     8 */
        uint32_t                   stripe_size;          /*    48     4 */
        uint32_t                   area_count;           /*    52     4 */
        uint32_t                   area_len;             /*    56     4 */
        uint32_t                   extents_copied;       /*    60     4 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        struct logical_volume *    origin;               /*    64     8 */
        struct logical_volume *    cow;                  /*    72     8 */
        struct dm_list             origin_list;          /*    80    16 */
        uint32_t                   chunk_size;           /*    96     4 */
        uint32_t                   region_size;          /*   100     4 */
        struct logical_volume *    log_lv;               /*   104     8 */
        void *                     segtype_private;      /*   112     8 */
        struct dm_list             tags;                 /*   120    16 */
        /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
        struct lv_segment_area *   areas;                /*   136     8 */

        /* size: 144, cachelines: 3, members: 19 */
        /* last cacheline: 16 bytes */
}




More information about the lvm-devel mailing list