md: avoid deadlock when md_set_badblocks.
[firefly-linux-kernel-4.4.55.git] / drivers / md / raid5.h
index 70c49329ca9a23fbbad73061477ac0a0cfe80e6e..2113ffa82c7a2506d21ce36076c3f6bd057d922b 100644 (file)
@@ -197,6 +197,7 @@ enum reconstruct_states {
 struct stripe_head {
        struct hlist_node       hash;
        struct list_head        lru;          /* inactive_list or handle_list */
+       struct llist_node       release_list;
        struct r5conf           *raid_conf;
        short                   generation;     /* increments with every
                                                 * reshape */
@@ -211,6 +212,8 @@ struct stripe_head {
        enum check_states       check_state;
        enum reconstruct_states reconstruct_state;
        spinlock_t              stripe_lock;
+       int                     cpu;
+       struct r5worker_group   *group;
        /**
         * struct stripe_operations
         * @target - STRIPE_OP_COMPUTE_BLK target
@@ -321,6 +324,7 @@ enum {
        STRIPE_OPS_REQ_PENDING,
        STRIPE_ON_UNPLUG_LIST,
        STRIPE_DISCARD,
+       STRIPE_ON_RELEASE_LIST,
 };
 
 /*
@@ -363,6 +367,19 @@ struct disk_info {
        struct md_rdev  *rdev, *replacement;
 };
 
+struct r5worker {
+       struct work_struct work;
+       struct r5worker_group *group;
+       bool working;
+};
+
+struct r5worker_group {
+       struct list_head handle_list;
+       struct r5conf *conf;
+       struct r5worker *workers;
+       int stripes_cnt;
+};
+
 struct r5conf {
        struct hlist_head       *stripe_hashtbl;
        struct mddev            *mddev;
@@ -386,6 +403,7 @@ struct r5conf {
        int                     prev_chunk_sectors;
        int                     prev_algo;
        short                   generation; /* increments with every reshape */
+       seqcount_t              gen_lock;       /* lock against generation changes */
        unsigned long           reshape_checkpoint; /* Time we last updated
                                                     * metadata */
        long long               min_offset_diff; /* minimum difference between
@@ -445,6 +463,7 @@ struct r5conf {
         */
        atomic_t                active_stripes;
        struct list_head        inactive_list;
+       struct llist_head       released_stripes;
        wait_queue_head_t       wait_for_stripe;
        wait_queue_head_t       wait_for_overlap;
        int                     inactive_blocked;       /* release of inactive stripes blocked,
@@ -458,6 +477,9 @@ struct r5conf {
         * the new thread here until we fully activate the array.
         */
        struct md_thread        *thread;
+       struct r5worker_group   *worker_groups;
+       int                     group_cnt;
+       int                     worker_cnt_per_group;
 };
 
 /*