aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2012-08-08 15:19:09 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-09 08:08:04 -0500
commit39a1aa7f49dc8eae5c8d3a4bf759eb7abeabe6c0 (patch)
treed75405087a78c53b95c99ab5e2e52230a5e8cc5a /drivers/block/drbd
parentfef45d297e447d710abcf0cd0bdbf8738ff469eb (diff)
drbd: Protect accesses to the uuid set with a spinlock
There is at least the worker context, the receiver context, the context of receiving netlink packts. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_int.h4
-rw-r--r--drivers/block/drbd/drbd_main.c33
-rw-r--r--drivers/block/drbd/drbd_nl.c12
-rw-r--r--drivers/block/drbd/drbd_receiver.c11
4 files changed, 49 insertions, 11 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index d8b3c88d6f1c..b83398d64a9c 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -747,6 +747,7 @@ struct drbd_md {
747 u64 md_offset; /* sector offset to 'super' block */ 747 u64 md_offset; /* sector offset to 'super' block */
748 748
749 u64 la_size_sect; /* last agreed size, unit sectors */ 749 u64 la_size_sect; /* last agreed size, unit sectors */
750 spinlock_t uuid_lock;
750 u64 uuid[UI_SIZE]; 751 u64 uuid[UI_SIZE];
751 u64 device_uuid; 752 u64 device_uuid;
752 u32 flags; 753 u32 flags;
@@ -1119,8 +1120,9 @@ extern int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev);
1119extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local); 1120extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
1120extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local); 1121extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
1121extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local); 1122extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
1122extern void _drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
1123extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local); 1123extern void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local);
1124extern void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local);
1125extern void __drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
1124extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local); 1126extern void drbd_md_set_flag(struct drbd_conf *mdev, int flags) __must_hold(local);
1125extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local); 1127extern void drbd_md_clear_flag(struct drbd_conf *mdev, int flags)__must_hold(local);
1126extern int drbd_md_test_flag(struct drbd_backing_dev *, int); 1128extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 328ce80fecfa..d831e85f1515 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -838,8 +838,10 @@ int _drbd_send_uuids(struct drbd_conf *mdev, u64 uuid_flags)
838 put_ldev(mdev); 838 put_ldev(mdev);
839 return -EIO; 839 return -EIO;
840 } 840 }
841 spin_lock_irq(&mdev->ldev->md.uuid_lock);
841 for (i = UI_CURRENT; i < UI_SIZE; i++) 842 for (i = UI_CURRENT; i < UI_SIZE; i++)
842 p->uuid[i] = mdev->ldev ? cpu_to_be64(mdev->ldev->md.uuid[i]) : 0; 843 p->uuid[i] = mdev->ldev ? cpu_to_be64(mdev->ldev->md.uuid[i]) : 0;
844 spin_unlock_irq(&mdev->ldev->md.uuid_lock);
843 845
844 mdev->comm_bm_set = drbd_bm_total_weight(mdev); 846 mdev->comm_bm_set = drbd_bm_total_weight(mdev);
845 p->uuid[UI_SIZE] = cpu_to_be64(mdev->comm_bm_set); 847 p->uuid[UI_SIZE] = cpu_to_be64(mdev->comm_bm_set);
@@ -3015,7 +3017,7 @@ void drbd_md_mark_dirty(struct drbd_conf *mdev)
3015} 3017}
3016#endif 3018#endif
3017 3019
3018static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local) 3020void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
3019{ 3021{
3020 int i; 3022 int i;
3021 3023
@@ -3023,7 +3025,7 @@ static void drbd_uuid_move_history(struct drbd_conf *mdev) __must_hold(local)
3023 mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i]; 3025 mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
3024} 3026}
3025 3027
3026void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) 3028void __drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
3027{ 3029{
3028 if (idx == UI_CURRENT) { 3030 if (idx == UI_CURRENT) {
3029 if (mdev->state.role == R_PRIMARY) 3031 if (mdev->state.role == R_PRIMARY)
@@ -3038,14 +3040,24 @@ void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
3038 drbd_md_mark_dirty(mdev); 3040 drbd_md_mark_dirty(mdev);
3039} 3041}
3040 3042
3043void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
3044{
3045 unsigned long flags;
3046 spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
3047 __drbd_uuid_set(mdev, idx, val);
3048 spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
3049}
3041 3050
3042void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local) 3051void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
3043{ 3052{
3053 unsigned long flags;
3054 spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
3044 if (mdev->ldev->md.uuid[idx]) { 3055 if (mdev->ldev->md.uuid[idx]) {
3045 drbd_uuid_move_history(mdev); 3056 drbd_uuid_move_history(mdev);
3046 mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx]; 3057 mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
3047 } 3058 }
3048 _drbd_uuid_set(mdev, idx, val); 3059 __drbd_uuid_set(mdev, idx, val);
3060 spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
3049} 3061}
3050 3062
3051/** 3063/**
@@ -3058,15 +3070,20 @@ void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
3058void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local) 3070void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
3059{ 3071{
3060 u64 val; 3072 u64 val;
3061 unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP]; 3073 unsigned long long bm_uuid;
3074
3075 get_random_bytes(&val, sizeof(u64));
3076
3077 spin_lock_irq(&mdev->ldev->md.uuid_lock);
3078 bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
3062 3079
3063 if (bm_uuid) 3080 if (bm_uuid)
3064 dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid); 3081 dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
3065 3082
3066 mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT]; 3083 mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
3084 __drbd_uuid_set(mdev, UI_CURRENT, val);
3085 spin_unlock_irq(&mdev->ldev->md.uuid_lock);
3067 3086
3068 get_random_bytes(&val, sizeof(u64));
3069 _drbd_uuid_set(mdev, UI_CURRENT, val);
3070 drbd_print_uuids(mdev, "new current UUID"); 3087 drbd_print_uuids(mdev, "new current UUID");
3071 /* get it to stable storage _now_ */ 3088 /* get it to stable storage _now_ */
3072 drbd_md_sync(mdev); 3089 drbd_md_sync(mdev);
@@ -3074,9 +3091,11 @@ void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
3074 3091
3075void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local) 3092void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
3076{ 3093{
3094 unsigned long flags;
3077 if (mdev->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) 3095 if (mdev->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
3078 return; 3096 return;
3079 3097
3098 spin_lock_irqsave(&mdev->ldev->md.uuid_lock, flags);
3080 if (val == 0) { 3099 if (val == 0) {
3081 drbd_uuid_move_history(mdev); 3100 drbd_uuid_move_history(mdev);
3082 mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP]; 3101 mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
@@ -3088,6 +3107,8 @@ void drbd_uuid_set_bm(struct drbd_conf *mdev, u64 val) __must_hold(local)
3088 3107
3089 mdev->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1); 3108 mdev->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
3090 } 3109 }
3110 spin_unlock_irqrestore(&mdev->ldev->md.uuid_lock, flags);
3111
3091 drbd_md_mark_dirty(mdev); 3112 drbd_md_mark_dirty(mdev);
3092} 3113}
3093 3114
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index c02d5265c397..d31a0261e83e 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1320,6 +1320,8 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
1320 retcode = ERR_NOMEM; 1320 retcode = ERR_NOMEM;
1321 goto fail; 1321 goto fail;
1322 } 1322 }
1323 spin_lock_init(&nbc->md.uuid_lock);
1324
1323 new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL); 1325 new_disk_conf = kzalloc(sizeof(struct disk_conf), GFP_KERNEL);
1324 if (!new_disk_conf) { 1326 if (!new_disk_conf) {
1325 retcode = ERR_NOMEM; 1327 retcode = ERR_NOMEM;
@@ -2679,8 +2681,16 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
2679 goto nla_put_failure; 2681 goto nla_put_failure;
2680 2682
2681 if (got_ldev) { 2683 if (got_ldev) {
2684 int err;
2685
2686 spin_lock_irq(&mdev->ldev->md.uuid_lock);
2687 err = nla_put(skb, T_uuids, sizeof(si->uuids), mdev->ldev->md.uuid);
2688 spin_unlock_irq(&mdev->ldev->md.uuid_lock);
2689
2690 if (err)
2691 goto nla_put_failure;
2692
2682 if (nla_put_u32(skb, T_disk_flags, mdev->ldev->md.flags) || 2693 if (nla_put_u32(skb, T_disk_flags, mdev->ldev->md.flags) ||
2683 nla_put(skb, T_uuids, sizeof(si->uuids), mdev->ldev->md.uuid) ||
2684 nla_put_u64(skb, T_bits_total, drbd_bm_bits(mdev)) || 2694 nla_put_u64(skb, T_bits_total, drbd_bm_bits(mdev)) ||
2685 nla_put_u64(skb, T_bits_oos, drbd_bm_total_weight(mdev))) 2695 nla_put_u64(skb, T_bits_oos, drbd_bm_total_weight(mdev)))
2686 goto nla_put_failure; 2696 goto nla_put_failure;
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 14df37ccd524..0eefbeb65664 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -2796,7 +2796,9 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
2796 if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) && 2796 if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
2797 (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) { 2797 (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) {
2798 dev_info(DEV, "was SyncSource, missed the resync finished event, corrected myself:\n"); 2798 dev_info(DEV, "was SyncSource, missed the resync finished event, corrected myself:\n");
2799 drbd_uuid_set_bm(mdev, 0UL); 2799 drbd_uuid_move_history(mdev);
2800 mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
2801 mdev->ldev->md.uuid[UI_BITMAP] = 0;
2800 2802
2801 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, 2803 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
2802 mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0); 2804 mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0);
@@ -2904,8 +2906,8 @@ static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(l
2904 if (mdev->tconn->agreed_pro_version < 91) 2906 if (mdev->tconn->agreed_pro_version < 91)
2905 return -1091; 2907 return -1091;
2906 2908
2907 _drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]); 2909 __drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]);
2908 _drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]); 2910 __drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]);
2909 2911
2910 dev_info(DEV, "Last syncUUID did not get through, corrected:\n"); 2912 dev_info(DEV, "Last syncUUID did not get through, corrected:\n");
2911 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, 2913 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
@@ -2959,11 +2961,14 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_conf *mdev, enum drbd_rol
2959 mydisk = mdev->new_state_tmp.disk; 2961 mydisk = mdev->new_state_tmp.disk;
2960 2962
2961 dev_info(DEV, "drbd_sync_handshake:\n"); 2963 dev_info(DEV, "drbd_sync_handshake:\n");
2964
2965 spin_lock_irq(&mdev->ldev->md.uuid_lock);
2962 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, mdev->comm_bm_set, 0); 2966 drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid, mdev->comm_bm_set, 0);
2963 drbd_uuid_dump(mdev, "peer", mdev->p_uuid, 2967 drbd_uuid_dump(mdev, "peer", mdev->p_uuid,
2964 mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]); 2968 mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
2965 2969
2966 hg = drbd_uuid_compare(mdev, &rule_nr); 2970 hg = drbd_uuid_compare(mdev, &rule_nr);
2971 spin_unlock_irq(&mdev->ldev->md.uuid_lock);
2967 2972
2968 dev_info(DEV, "uuid_compare()=%d by rule %d\n", hg, rule_nr); 2973 dev_info(DEV, "uuid_compare()=%d by rule %d\n", hg, rule_nr);
2969 2974