Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

EDAC/device: Get rid of the silly one-shot memory allocation in edac_device_alloc_ctl_info()

Use boring kzalloc() instead. Add pointers to the different allocated
members in struct edac_device_ctl_info for easier freeing later.

One of the reasons, perhaps, why it was done this way is to be able to
do a single kfree(ctl_info) without having to kfree() the other parts of
the struct too but that is not nearly a sensible reason as to why there
should be this obscure pointer alignment.

There should be no functional changes resulting from this.

Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220310095254.1510-4-bp@alien8.de

+60 -74
+45 -70
drivers/edac/edac_device.c
··· 59 59 struct edac_device_instance *dev_inst, *inst; 60 60 struct edac_device_block *dev_blk, *blk_p, *blk; 61 61 struct edac_dev_sysfs_block_attribute *dev_attrib, *attrib_p, *attrib; 62 - unsigned total_size; 63 - unsigned count; 64 62 unsigned instance, block, attr; 65 - void *pvt, *p; 63 + void *pvt; 66 64 int err; 67 65 68 66 edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks); 69 67 70 - /* Calculate the size of memory we need to allocate AND 71 - * determine the offsets of the various item arrays 72 - * (instance,block,attrib) from the start of an allocated structure. 73 - * We want the alignment of each item (instance,block,attrib) 74 - * to be at least as stringent as what the compiler would 75 - * provide if we could simply hardcode everything into a single struct. 76 - */ 77 - p = NULL; 78 - dev_ctl = edac_align_ptr(&p, sizeof(*dev_ctl), 1); 79 - 80 - /* Calc the 'end' offset past end of ONE ctl_info structure 81 - * which will become the start of the 'instance' array 82 - */ 83 - dev_inst = edac_align_ptr(&p, sizeof(*dev_inst), nr_instances); 84 - 85 - /* Calc the 'end' offset past the instance array within the ctl_info 86 - * which will become the start of the block array 87 - */ 88 - count = nr_instances * nr_blocks; 89 - dev_blk = edac_align_ptr(&p, sizeof(*dev_blk), count); 90 - 91 - /* Calc the 'end' offset past the dev_blk array 92 - * which will become the start of the attrib array, if any. 93 - */ 94 - /* calc how many nr_attrib we need */ 95 - if (nr_attrib > 0) 96 - count *= nr_attrib; 97 - dev_attrib = edac_align_ptr(&p, sizeof(*dev_attrib), count); 98 - 99 - /* Calc the 'end' offset past the attributes array */ 100 - pvt = edac_align_ptr(&p, sz_private, 1); 101 - 102 - /* 'pvt' now points to where the private data area is. 103 - * At this point 'pvt' (like dev_inst,dev_blk and dev_attrib) 104 - * is baselined at ZERO 105 - */ 106 - total_size = ((unsigned long)pvt) + sz_private; 107 - 108 - /* Allocate the amount of memory for the set of control structures */ 109 - dev_ctl = kzalloc(total_size, GFP_KERNEL); 110 - if (dev_ctl == NULL) 68 + dev_ctl = kzalloc(sizeof(struct edac_device_ctl_info), GFP_KERNEL); 69 + if (!dev_ctl) 111 70 return NULL; 112 71 113 - /* Adjust pointers so they point within the actual memory we 114 - * just allocated rather than an imaginary chunk of memory 115 - * located at address 0. 116 - * 'dev_ctl' points to REAL memory, while the others are 117 - * ZERO based and thus need to be adjusted to point within 118 - * the allocated memory. 119 - */ 120 - dev_inst = (struct edac_device_instance *) 121 - (((char *)dev_ctl) + ((unsigned long)dev_inst)); 122 - dev_blk = (struct edac_device_block *) 123 - (((char *)dev_ctl) + ((unsigned long)dev_blk)); 124 - dev_attrib = (struct edac_dev_sysfs_block_attribute *) 125 - (((char *)dev_ctl) + ((unsigned long)dev_attrib)); 126 - pvt = sz_private ? (((char *)dev_ctl) + ((unsigned long)pvt)) : NULL; 72 + dev_inst = kmalloc_array(nr_instances, 73 + sizeof(struct edac_device_instance), 74 + GFP_KERNEL | __GFP_ZERO); 75 + if (!dev_inst) 76 + goto free; 127 77 128 - /* Begin storing the information into the control info structure */ 129 - dev_ctl->dev_idx = device_index; 130 - dev_ctl->nr_instances = nr_instances; 131 78 dev_ctl->instances = dev_inst; 132 - dev_ctl->pvt_info = pvt; 79 + 80 + dev_blk = kmalloc_array(nr_instances * nr_blocks, 81 + sizeof(struct edac_device_block), 82 + GFP_KERNEL | __GFP_ZERO); 83 + if (!dev_blk) 84 + goto free; 85 + 86 + dev_ctl->blocks = dev_blk; 87 + 88 + if (nr_attrib) { 89 + dev_attrib = kmalloc_array(nr_attrib, 90 + sizeof(struct edac_dev_sysfs_block_attribute), 91 + GFP_KERNEL | __GFP_ZERO); 92 + if (!dev_attrib) 93 + goto free; 94 + 95 + dev_ctl->attribs = dev_attrib; 96 + } 97 + 98 + if (sz_private) { 99 + pvt = kzalloc(sz_private, GFP_KERNEL); 100 + if (!pvt) 101 + goto free; 102 + 103 + dev_ctl->pvt_info = pvt; 104 + } 105 + 106 + dev_ctl->dev_idx = device_index; 107 + dev_ctl->nr_instances = nr_instances; 133 108 134 109 /* Default logging of CEs and UEs */ 135 110 dev_ctl->log_ce = 1; 136 111 dev_ctl->log_ue = 1; 137 112 138 113 /* Name of this edac device */ 139 - snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); 140 - 141 - edac_dbg(4, "edac_dev=%p next after end=%p\n", 142 - dev_ctl, pvt + sz_private); 114 + snprintf(dev_ctl->name, sizeof(dev_ctl->name),"%s", edac_device_name); 143 115 144 116 /* Initialize every Instance */ 145 117 for (instance = 0; instance < nr_instances; instance++) { ··· 182 210 * Initialize the 'root' kobj for the edac_device controller 183 211 */ 184 212 err = edac_device_register_sysfs_main_kobj(dev_ctl); 185 - if (err) { 186 - kfree(dev_ctl); 187 - return NULL; 188 - } 213 + if (err) 214 + goto free; 189 215 190 216 /* at this point, the root kobj is valid, and in order to 191 217 * 'free' the object, then the function: ··· 193 223 */ 194 224 195 225 return dev_ctl; 226 + 227 + free: 228 + __edac_device_free_ctl_info(dev_ctl); 229 + 230 + return NULL; 196 231 } 197 232 EXPORT_SYMBOL_GPL(edac_device_alloc_ctl_info); 198 233
+14
drivers/edac/edac_device.h
··· 216 216 */ 217 217 u32 nr_instances; 218 218 struct edac_device_instance *instances; 219 + struct edac_device_block *blocks; 220 + struct edac_dev_sysfs_block_attribute *attribs; 219 221 220 222 /* Event counters for the this whole EDAC Device */ 221 223 struct edac_device_counter counters; ··· 350 348 */ 351 349 extern int edac_device_alloc_index(void); 352 350 extern const char *edac_layer_name[]; 351 + 352 + /* Free the actual struct */ 353 + static inline void __edac_device_free_ctl_info(struct edac_device_ctl_info *ci) 354 + { 355 + if (ci) { 356 + kfree(ci->pvt_info); 357 + kfree(ci->attribs); 358 + kfree(ci->blocks); 359 + kfree(ci->instances); 360 + kfree(ci); 361 + } 362 + } 353 363 #endif
+1 -4
drivers/edac/edac_device_sysfs.c
··· 208 208 /* decrement the EDAC CORE module ref count */ 209 209 module_put(edac_dev->owner); 210 210 211 - /* free the control struct containing the 'main' kobj 212 - * passed in to this routine 213 - */ 214 - kfree(edac_dev); 211 + __edac_device_free_ctl_info(edac_dev); 215 212 } 216 213 217 214 /* ktype for the main (master) kobject */