Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
a5f55d73
Commit
a5f55d73
authored
Apr 12, 2003
by
James Bottomley
Browse files
Options
Browse Files
Download
Plain Diff
More axboe/patmans conflicts
parents
99d60d5d
f64f6b58
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
94 additions
and
68 deletions
+94
-68
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+3
-2
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_lib.c
+86
-62
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_scan.c
+5
-4
No files found.
drivers/scsi/scsi.h
View file @
a5f55d73
...
...
@@ -533,10 +533,11 @@ extern int scsi_dev_info_list_add_str(char *);
/*
* scsi_target: representation of a scsi target, for now, this is only
* used for single_lun devices.
* used for single_lun devices. If no one has active IO to the target,
* starget_sdev_user is NULL, else it points to the active sdev.
*/
struct
scsi_target
{
unsigned
int
starget_busy
;
struct
scsi_device
*
starget_sdev_user
;
unsigned
int
starget_refcnt
;
};
...
...
drivers/scsi/scsi_lib.c
View file @
a5f55d73
...
...
@@ -327,9 +327,9 @@ void scsi_setup_cmd_retry(struct scsi_cmnd *cmd)
}
/*
* Called for single_lun devices on IO completion. Clear starget_
busy, and
*
Call __blk_run_queue for all the scsi_devices on the target - including
* current_sdev first.
* Called for single_lun devices on IO completion. Clear starget_
sdev_user,
*
and call __blk_run_queue for all the scsi_devices on the target -
*
including
current_sdev first.
*
* Called with *no* scsi locks held.
*/
...
...
@@ -338,19 +338,33 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
struct
scsi_device
*
sdev
;
unsigned
int
flags
,
flags2
;
spin_lock_irqsave
(
current_sdev
->
request_queue
->
queue_lock
,
flags2
);
spin_lock_irqsave
(
current_sdev
->
host
->
host_lock
,
flags
);
WARN_ON
(
!
current_sdev
->
sdev_target
->
starget_busy
);
if
(
current_sdev
->
device_busy
==
0
)
current_sdev
->
sdev_target
->
starget_busy
=
0
;
WARN_ON
(
!
current_sdev
->
sdev_target
->
starget_sdev_user
);
current_sdev
->
sdev_target
->
starget_sdev_user
=
NULL
;
spin_unlock_irqrestore
(
current_sdev
->
host
->
host_lock
,
flags
);
/*
* Call __blk_run_queue for all LUNs on the target, starting with
* current_sdev.
* current_sdev. We race with others (to set starget_sdev_user),
* but in most cases, we will be first. Ideally, each LU on the
* target would get some limited time or requests on the target.
*/
spin_lock_irqsave
(
current_sdev
->
request_queue
->
queue_lock
,
flags2
);
__blk_run_queue
(
current_sdev
->
request_queue
);
spin_unlock_irqrestore
(
current_sdev
->
request_queue
->
queue_lock
,
flags2
);
spin_lock_irqsave
(
current_sdev
->
host
->
host_lock
,
flags
);
if
(
current_sdev
->
sdev_target
->
starget_sdev_user
)
{
/*
* After unlock, this races with anyone clearing
* starget_sdev_user, but we (should) always enter this
* function again, avoiding any problems.
*/
spin_unlock_irqrestore
(
current_sdev
->
host
->
host_lock
,
flags
);
return
;
}
spin_unlock_irqrestore
(
current_sdev
->
host
->
host_lock
,
flags
);
list_for_each_entry
(
sdev
,
&
current_sdev
->
same_target_siblings
,
same_target_siblings
)
{
spin_lock_irqsave
(
sdev
->
request_queue
->
queue_lock
,
flags2
);
...
...
@@ -397,7 +411,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
*/
void
scsi_queue_next_request
(
request_queue_t
*
q
,
struct
scsi_cmnd
*
cmd
)
{
struct
scsi_device
*
sdev
,
*
sdev2
;
struct
scsi_device
*
sdev
;
struct
Scsi_Host
*
shost
;
unsigned
long
flags
;
...
...
@@ -446,16 +460,23 @@ void scsi_queue_next_request(request_queue_t *q, struct scsi_cmnd *cmd)
* scsi_request_fn must get the host_lock before checking
* or modifying starved_list or starved_entry.
*/
sdev
2
=
list_entry
(
shost
->
starved_list
.
next
,
sdev
=
list_entry
(
shost
->
starved_list
.
next
,
struct
scsi_device
,
starved_entry
);
list_del_init
(
&
sdev
2
->
starved_entry
);
list_del_init
(
&
sdev
->
starved_entry
);
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
spin_lock_irqsave
(
sdev
2
->
request_queue
->
queue_lock
,
flags
);
__blk_run_queue
(
sdev
2
->
request_queue
);
spin_unlock_irqrestore
(
sdev
2
->
request_queue
->
queue_lock
,
flags
);
spin_lock_irqsave
(
sdev
->
request_queue
->
queue_lock
,
flags
);
__blk_run_queue
(
sdev
->
request_queue
);
spin_unlock_irqrestore
(
sdev
->
request_queue
->
queue_lock
,
flags
);
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
if
(
unlikely
(
!
list_empty
(
&
sdev
->
starved_entry
)))
/*
* sdev lost a race, and was put back on the
* starved list. This is unlikely but without this
* in theory we could loop forever.
*/
break
;
}
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
...
...
@@ -1074,9 +1095,10 @@ static inline int scsi_dev_queue_ready(struct request_queue *q,
/*
* scsi_host_queue_ready: if we can send requests to shost, return 1 else
* return 0.
* return 0. We must end up running the queue again whenever 0 is
* returned, else IO can hang.
*
* Called with
queue_lock and
host_lock held.
* Called with host_lock held.
*/
static
inline
int
scsi_host_queue_ready
(
struct
request_queue
*
q
,
struct
Scsi_Host
*
shost
,
...
...
@@ -1101,15 +1123,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
return
0
;
if
((
shost
->
can_queue
>
0
&&
shost
->
host_busy
>=
shost
->
can_queue
)
||
shost
->
host_blocked
||
shost
->
host_self_blocked
)
{
SCSI_LOG_MLQUEUE
(
3
,
printk
(
"add starved dev <%d,%d,%d,%d>; host "
"limit %d, busy %d, blocked %d selfblocked %d
\n
"
,
sdev
->
host
->
host_no
,
sdev
->
channel
,
sdev
->
id
,
sdev
->
lun
,
shost
->
can_queue
,
shost
->
host_busy
,
shost
->
host_blocked
,
shost
->
host_self_blocked
));
list_add_tail
(
&
sdev
->
starved_entry
,
&
shost
->
starved_list
);
list_add_tail
(
&
sdev
->
starved_entry
,
&
shost
->
starved_list
);
return
0
;
}
...
...
@@ -1143,61 +1157,58 @@ static void scsi_request_fn(request_queue_t *q)
if
(
blk_queue_plugged
(
q
))
goto
completed
;
if
(
!
scsi_dev_queue_ready
(
q
,
sdev
))
goto
completed
;
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
if
(
!
scsi_host_queue_ready
(
q
,
shost
,
sdev
))
goto
after_host_lock
;
if
(
sdev
->
single_lun
&&
!
sdev
->
device_busy
&&
sdev
->
sdev_target
->
starget_busy
)
goto
after_host_lock
;
/*
* get next queueable request. We do this early to make sure
* that the request is fully prepared even if we cannot
* accept it. If there is no request, we'll detect this
* lower down.
* accept it.
*/
req
=
elv_next_request
(
q
);
if
(
!
req
)
{
/* If the device is busy, a returning I/O
* will restart the queue. Otherwise, we have
* to plug the queue */
if
(
sdev
->
device_busy
==
1
)
/*
* If the device is busy, a returning I/O will
* restart the queue. Otherwise, we have to plug
* the queue
*/
if
(
sdev
->
device_busy
==
0
)
blk_plug_device
(
q
);
goto
after_host_lock
;
goto
completed
;
}
cmd
=
req
->
special
;
/*
* Should be impossible for a correctly prepared request
* please mail the stack trace to linux-scsi@vger.kernel.org
*/
BUG_ON
(
!
cmd
);
if
(
!
scsi_dev_queue_ready
(
q
,
sdev
))
goto
completed
;
/*
* Finally, before we release the lock, we copy the
* request to the command block, and remove the
* request from the request list. Note that we always
* operate on the queue head - there is absolutely no
* reason to search the list, because all of the
* commands in this queue are for the same device.
* Remove the request from the request list.
*/
if
(
!
(
blk_queue_tagged
(
q
)
&&
(
blk_queue_start_tag
(
q
,
req
)
==
0
)))
blkdev_dequeue_request
(
req
);
if
(
sdev
->
single_lun
)
sdev
->
sdev_target
->
starget_busy
=
1
;
sdev
->
device_busy
++
;
spin_unlock_irq
(
q
->
queue_lock
);
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
if
(
!
scsi_host_queue_ready
(
q
,
shost
,
sdev
))
goto
host_lock_held
;
if
(
sdev
->
single_lun
)
{
if
(
sdev
->
sdev_target
->
starget_sdev_user
&&
(
sdev
->
sdev_target
->
starget_sdev_user
!=
sdev
))
goto
host_lock_held
;
else
sdev
->
sdev_target
->
starget_sdev_user
=
sdev
;
}
shost
->
host_busy
++
;
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
sdev
->
device_busy
++
;
spin_unlock_irq
(
q
->
queue_lock
);
cmd
=
req
->
special
;
/*
* Should be impossible for a correctly prepared request
* please mail the stack trace to linux-scsi@vger.kernel.org
*/
BUG_ON
(
!
cmd
);
/*
* Finally, initialize any error handling parameters, and set up
...
...
@@ -1219,8 +1230,21 @@ static void scsi_request_fn(request_queue_t *q)
completed:
return
;
after_host_lock
:
host_lock_held
:
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
/*
* lock q, handle tag, requeue req, and decrement device_busy. We
* must return with queue_lock held.
*
* Decrementing device_busy without checking it is OK, as all such
* cases (host limits or settings) should run the queue at some
* later time.
*/
spin_lock_irq
(
q
->
queue_lock
);
if
(
blk_rq_tagged
(
req
))
blk_queue_end_tag
(
q
,
req
);
__elv_add_request
(
q
,
req
,
0
,
0
);
sdev
->
device_busy
--
;
}
u64
scsi_calculate_bounce_limit
(
struct
Scsi_Host
*
shost
)
...
...
drivers/scsi/scsi_scan.c
View file @
a5f55d73
...
...
@@ -496,13 +496,14 @@ static void scsi_free_sdev(struct scsi_device *sdev)
sdev
->
host
->
hostt
->
slave_destroy
(
sdev
);
if
(
sdev
->
inquiry
)
kfree
(
sdev
->
inquiry
);
if
(
sdev
->
single_lun
)
{
spin_lock_irqsave
(
sdev
->
host
->
host_lock
,
flags
);
list_del
(
&
sdev
->
starved_entry
);
if
(
sdev
->
single_lun
)
{
sdev
->
sdev_target
->
starget_refcnt
--
;
if
(
sdev
->
sdev_target
->
starget_refcnt
==
0
)
kfree
(
sdev
->
sdev_target
);
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
flags
);
}
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
flags
);
kfree
(
sdev
);
}
...
...
@@ -1282,7 +1283,7 @@ static int scsi_add_lun(Scsi_Device *sdev, Scsi_Request *sreq,
}
}
if
(
!
starget
)
{
starget
=
kmalloc
(
sizeof
(
*
starget
),
GFP_
KERNEL
);
starget
=
kmalloc
(
sizeof
(
*
starget
),
GFP_
ATOMIC
);
if
(
!
starget
)
{
printk
(
ALLOC_FAILURE_MSG
,
__FUNCTION__
);
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
...
...
@@ -1290,7 +1291,7 @@ static int scsi_add_lun(Scsi_Device *sdev, Scsi_Request *sreq,
return
SCSI_SCAN_NO_RESPONSE
;
}
starget
->
starget_refcnt
=
0
;
starget
->
starget_
busy
=
0
;
starget
->
starget_
sdev_user
=
NULL
;
}
starget
->
starget_refcnt
++
;
sdev
->
sdev_target
=
starget
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment