This patch does not change the behavior of any existing code but
introduces a function that will be used by the next patch.

Signed-off-by: Bart Van Assche <[email protected]>
Cc: Keith Busch <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Sagi Grimberg <[email protected]>
Cc: Matias Bjorling <[email protected]>
Cc: <[email protected]>
---
 block/genhd.c         | 26 ++++++++++++++++++++++++--
 include/linux/genhd.h | 13 +++++++++++--
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index 8cc719a37b32..3b643152907d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1413,10 +1413,20 @@ dev_t blk_lookup_devt(const char *name, int partno)
 }
 EXPORT_SYMBOL(blk_lookup_devt);
 
-struct gendisk *__alloc_disk_node(int minors, int node_id)
+/**
+ * __alloc_disk_node - allocate a gendisk structure and initialize it
+ * @minors: number of partitions to allocate memory for
+ * @node_id: NUMA node to allocate memory from
+ * @ag: NULL or pointer to a NULL-terminated array with attribute groups that
+ *     must be attached to the disk_to_dev() of the allocated disk structure
+ */
+struct gendisk *__alloc_disk_node(int minors, int node_id,
+                                 const struct attribute_group **ag)
 {
        struct gendisk *disk;
        struct disk_part_tbl *ptbl;
+       const struct attribute_group **agp;
+       int num_groups = 0;
 
        if (minors > DISK_MAX_PARTS) {
                printk(KERN_ERR
@@ -1425,7 +1435,15 @@ struct gendisk *__alloc_disk_node(int minors, int 
node_id)
                minors = DISK_MAX_PARTS;
        }
 
-       disk = kzalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
+       if (ag) {
+               for (agp = ag; *agp; agp++)
+                       num_groups++;
+               /* Only count the terminating NULL if the array is not empty. */
+               if (num_groups)
+                       num_groups++;
+       }
+       disk = kzalloc_node(struct_size(disk, ag, num_groups), GFP_KERNEL,
+                           node_id);
        if (disk) {
                if (!init_part_stats(&disk->part0)) {
                        kfree(disk);
@@ -1461,6 +1479,10 @@ struct gendisk *__alloc_disk_node(int minors, int 
node_id)
                rand_initialize_disk(disk);
                disk_to_dev(disk)->class = &block_class;
                disk_to_dev(disk)->type = &disk_type;
+               if (num_groups) {
+                       memcpy(disk->ag, ag, num_groups * sizeof(ag));
+                       disk_to_dev(disk)->groups = disk->ag;
+               }
                device_initialize(disk_to_dev(disk));
        }
        return disk;
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 57864422a2c8..50ab6cf77fdf 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -211,6 +211,11 @@ struct gendisk {
        int node_id;
        struct badblocks *bb;
        struct lockdep_map lockdep_map;
+       /*
+        * Storage space for NULL-terminated attribute group array for
+        * disk_to_dev() of this gendisk structure.
+        */
+       const struct attribute_group *ag[0];
 };
 
 static inline struct gendisk *part_to_disk(struct hd_struct *part)
@@ -608,7 +613,8 @@ extern void __delete_partition(struct percpu_ref *);
 extern void delete_partition(struct gendisk *, int);
 extern void printk_all_partitions(void);
 
-extern struct gendisk *__alloc_disk_node(int minors, int node_id);
+extern struct gendisk *__alloc_disk_node(int minors, int node_id,
+                                        const struct attribute_group **ag);
 extern struct kobject *get_disk_and_module(struct gendisk *disk);
 extern void put_disk(struct gendisk *disk);
 extern void put_disk_and_module(struct gendisk *disk);
@@ -634,6 +640,9 @@ extern ssize_t part_fail_store(struct device *dev,
 #endif /* CONFIG_FAIL_MAKE_REQUEST */
 
 #define alloc_disk_node(minors, node_id)                               \
+       alloc_disk_node_attr(minors, node_id, NULL)
+
+#define alloc_disk_node_attr(minors, node_id, ag)                      \
 ({                                                                     \
        static struct lock_class_key __key;                             \
        const char *__name;                                             \
@@ -641,7 +650,7 @@ extern ssize_t part_fail_store(struct device *dev,
                                                                        \
        __name = "(gendisk_completion)"#minors"("#node_id")";           \
                                                                        \
-       __disk = __alloc_disk_node(minors, node_id);                    \
+       __disk = __alloc_disk_node(minors, node_id, ag);                \
                                                                        \
        if (__disk)                                                     \
                lockdep_init_map(&__disk->lockdep_map, __name, &__key, 0); \
-- 
2.18.0

Reply via email to