]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: tape device driver: improve locking | |
3 | References: bnc#434333 | |
4 | ||
5 | Symptom: 1. message "Badness at include/linux/blkdev.h" | |
6 | 2. lockdep message "INFO: inconsistent lock state" | |
7 | Problem: 1. Tape block device driver does not hold request queue lock | |
8 | when completing request via __blk_end_request. | |
9 | 2. During open() processing tape device driver receives | |
10 | interrupt while holding the tape device lock. | |
11 | Solution: 1. Use blk_end_request rather than __blk_end_request | |
12 | 2. Use spin_lock_irq to disable interrupts rather than spin_lock. | |
13 | ||
14 | Acked-by: John Jolly <jjolly@suse.de> | |
15 | --- | |
16 | drivers/s390/char/tape_block.c | 6 ++++-- | |
17 | drivers/s390/char/tape_core.c | 8 ++++---- | |
18 | 2 files changed, 8 insertions(+), 6 deletions(-) | |
19 | ||
20 | Index: temp_orig/drivers/s390/char/tape_block.c | |
21 | =================================================================== | |
22 | --- temp_orig.orig/drivers/s390/char/tape_block.c | |
23 | +++ temp_orig/drivers/s390/char/tape_block.c | |
24 | @@ -76,7 +76,7 @@ tapeblock_trigger_requeue(struct tape_de | |
25 | static void | |
26 | tapeblock_end_request(struct request *req, int error) | |
27 | { | |
28 | - if (__blk_end_request(req, error, blk_rq_bytes(req))) | |
29 | + if (blk_end_request(req, error, blk_rq_bytes(req))) | |
30 | BUG(); | |
31 | } | |
32 | ||
33 | @@ -166,7 +166,7 @@ tapeblock_requeue(struct work_struct *wo | |
34 | nr_queued++; | |
35 | spin_unlock(get_ccwdev_lock(device->cdev)); | |
36 | ||
37 | - spin_lock(&device->blk_data.request_queue_lock); | |
38 | + spin_lock_irq(&device->blk_data.request_queue_lock); | |
39 | while ( | |
40 | !blk_queue_plugged(queue) && | |
41 | elv_next_request(queue) && | |
42 | @@ -176,7 +176,9 @@ tapeblock_requeue(struct work_struct *wo | |
43 | if (rq_data_dir(req) == WRITE) { | |
44 | DBF_EVENT(1, "TBLOCK: Rejecting write request\n"); | |
45 | blkdev_dequeue_request(req); | |
46 | + spin_unlock_irq(&device->blk_data.request_queue_lock); | |
47 | tapeblock_end_request(req, -EIO); | |
48 | + spin_lock_irq(&device->blk_data.request_queue_lock); | |
49 | continue; | |
50 | } | |
51 | blkdev_dequeue_request(req); | |
52 | Index: temp_orig/drivers/s390/char/tape_core.c | |
53 | =================================================================== | |
54 | --- temp_orig.orig/drivers/s390/char/tape_core.c | |
55 | +++ temp_orig/drivers/s390/char/tape_core.c | |
56 | @@ -1199,7 +1199,7 @@ tape_open(struct tape_device *device) | |
57 | { | |
58 | int rc; | |
59 | ||
60 | - spin_lock(get_ccwdev_lock(device->cdev)); | |
61 | + spin_lock_irq(get_ccwdev_lock(device->cdev)); | |
62 | if (device->tape_state == TS_NOT_OPER) { | |
63 | DBF_EVENT(6, "TAPE:nodev\n"); | |
64 | rc = -ENODEV; | |
65 | @@ -1217,7 +1217,7 @@ tape_open(struct tape_device *device) | |
66 | tape_state_set(device, TS_IN_USE); | |
67 | rc = 0; | |
68 | } | |
69 | - spin_unlock(get_ccwdev_lock(device->cdev)); | |
70 | + spin_unlock_irq(get_ccwdev_lock(device->cdev)); | |
71 | return rc; | |
72 | } | |
73 | ||
74 | @@ -1227,11 +1227,11 @@ tape_open(struct tape_device *device) | |
75 | int | |
76 | tape_release(struct tape_device *device) | |
77 | { | |
78 | - spin_lock(get_ccwdev_lock(device->cdev)); | |
79 | + spin_lock_irq(get_ccwdev_lock(device->cdev)); | |
80 | if (device->tape_state == TS_IN_USE) | |
81 | tape_state_set(device, TS_UNUSED); | |
82 | module_put(device->discipline->owner); | |
83 | - spin_unlock(get_ccwdev_lock(device->cdev)); | |
84 | + spin_unlock_irq(get_ccwdev_lock(device->cdev)); | |
85 | return 0; | |
86 | } | |
87 |