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
65862c41
Commit
65862c41
authored
Mar 25, 2003
by
Patrick Mansfield
Committed by
James Bottomley
Mar 25, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] 7/7 fix single_lun code for per-scsi_device queue_lock
Fix single_lun code for per-scsi_device queue_lock
parent
00879482
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
84 additions
and
38 deletions
+84
-38
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+10
-0
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_lib.c
+30
-36
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_scan.c
+44
-2
No files found.
drivers/scsi/scsi.h
View file @
65862c41
...
...
@@ -530,6 +530,15 @@ struct scsi_dev_info_list {
extern
struct
list_head
scsi_dev_info_list
;
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.
*/
struct
scsi_target
{
unsigned
int
starget_busy
;
unsigned
int
starget_refcnt
;
};
/*
* The scsi_device struct contains what we know about each given scsi
* device.
...
...
@@ -588,6 +597,7 @@ struct scsi_device {
unsigned
char
current_tag
;
/* current tag */
// unsigned char sync_min_period; /* Not less than this period */
// unsigned char sync_max_offset; /* Not greater than this offset */
struct
scsi_target
*
sdev_target
;
/* used only for single_lun */
unsigned
online
:
1
;
unsigned
writeable
:
1
;
...
...
drivers/scsi/scsi_lib.c
View file @
65862c41
...
...
@@ -327,45 +327,35 @@ void scsi_setup_cmd_retry(struct scsi_cmnd *cmd)
}
/*
* Called for single_lun devices. The target associated with current_sdev can
* only handle one active command at a time. Scan through all of the luns
* on the same target as current_sdev, return 1 if any are active.
*/
static
int
scsi_single_lun_check
(
struct
scsi_device
*
current_sdev
)
{
struct
scsi_device
*
sdev
;
list_for_each_entry
(
sdev
,
&
current_sdev
->
same_target_siblings
,
same_target_siblings
)
if
(
sdev
->
device_busy
)
return
1
;
return
0
;
}
/*
* Called for single_lun devices on IO completion. If no requests
* outstanding for current_sdev, call __blk_run_queue for the next
* scsi_device on the same target that has requests.
* 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 with *no* scsi locks held.
*/
static
void
scsi_single_lun_run
(
struct
scsi_device
*
current_sdev
,
struct
request_queue
*
q
)
static
void
scsi_single_lun_run
(
struct
scsi_device
*
current_sdev
)
{
struct
scsi_device
*
sdev
;
struct
Scsi_Host
*
shost
;
unsigned
int
flags
,
flags2
;
shost
=
current_sdev
->
host
;
if
(
blk_queue_empty
(
q
)
&&
current_sdev
->
device_busy
==
0
&&
!
shost
->
host_blocked
&&
!
shost
->
host_self_blocked
&&
!
((
shost
->
can_queue
>
0
)
&&
(
shost
->
host_busy
>=
shost
->
can_queue
)))
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
;
spin_unlock_irqrestore
(
current_sdev
->
host
->
host_lock
,
flags
);
/*
* Call __blk_run_queue for all LUNs on the target, starting with
* current_sdev.
*/
__blk_run_queue
(
current_sdev
->
request_queue
);
spin_unlock_irqrestore
(
current_sdev
->
request_queue
->
queue_lock
,
flags2
);
list_for_each_entry
(
sdev
,
&
current_sdev
->
same_target_siblings
,
same_target_siblings
)
if
(
!
sdev
->
device_blocked
&&
!
blk_queue_empty
(
sdev
->
request_queue
))
{
same_target_siblings
)
{
spin_lock_irqsave
(
sdev
->
request_queue
->
queue_lock
,
flags2
);
__blk_run_queue
(
sdev
->
request_queue
);
break
;
spin_unlock_irqrestore
(
sdev
->
request_queue
->
queue_lock
,
flags2
)
;
}
}
...
...
@@ -438,7 +428,7 @@ void scsi_queue_next_request(request_queue_t *q, struct scsi_cmnd *cmd)
sdev
=
q
->
queuedata
;
if
(
sdev
->
single_lun
)
scsi_single_lun_run
(
sdev
,
q
);
scsi_single_lun_run
(
sdev
);
shost
=
sdev
->
host
;
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
...
...
@@ -1166,7 +1156,8 @@ static void scsi_request_fn(request_queue_t *q)
if
(
scsi_check_shost
(
q
,
shost
,
sdev
))
goto
after_host_lock
;
if
(
sdev
->
single_lun
&&
scsi_single_lun_check
(
sdev
))
if
(
sdev
->
single_lun
&&
!
sdev
->
device_busy
&&
sdev
->
sdev_target
->
starget_busy
)
goto
after_host_lock
;
/*
...
...
@@ -1204,6 +1195,9 @@ static void scsi_request_fn(request_queue_t *q)
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
;
shost
->
host_busy
++
;
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
...
...
drivers/scsi/scsi_scan.c
View file @
65862c41
...
...
@@ -478,6 +478,8 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
**/
static
void
scsi_free_sdev
(
struct
scsi_device
*
sdev
)
{
unsigned
int
flags
;
list_del
(
&
sdev
->
siblings
);
list_del
(
&
sdev
->
same_target_siblings
);
...
...
@@ -487,6 +489,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
);
sdev
->
sdev_target
->
starget_refcnt
--
;
if
(
sdev
->
sdev_target
->
starget_refcnt
==
0
)
kfree
(
sdev
->
sdev_target
);
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
flags
);
}
kfree
(
sdev
);
}
...
...
@@ -1122,6 +1132,10 @@ static void scsi_probe_lun(Scsi_Request *sreq, char *inq_result,
static
int
scsi_add_lun
(
Scsi_Device
*
sdev
,
Scsi_Request
*
sreq
,
char
*
inq_result
,
int
*
bflags
)
{
struct
scsi_device
*
sdev_sibling
;
struct
scsi_target
*
starget
;
unsigned
int
flags
;
/*
* XXX do not save the inquiry, since it can change underneath us,
* save just vendor/model/rev.
...
...
@@ -1243,10 +1257,38 @@ static int scsi_add_lun(Scsi_Device *sdev, Scsi_Request *sreq,
/*
* If we need to allow I/O to only one of the luns attached to
* this target id at a time, then we set this flag.
* this target id at a time set single_lun, and allocate or modify
* sdev_target.
*/
if
(
*
bflags
&
BLIST_SINGLELUN
)
if
(
*
bflags
&
BLIST_SINGLELUN
)
{
sdev
->
single_lun
=
1
;
spin_lock_irqsave
(
sdev
->
host
->
host_lock
,
flags
);
starget
=
NULL
;
/*
* Search for an existing target for this sdev.
*/
list_for_each_entry
(
sdev_sibling
,
&
sdev
->
same_target_siblings
,
same_target_siblings
)
{
if
(
sdev_sibling
->
sdev_target
!=
NULL
)
{
starget
=
sdev_sibling
->
sdev_target
;
break
;
}
}
if
(
!
starget
)
{
starget
=
kmalloc
(
sizeof
(
*
starget
),
GFP_KERNEL
);
if
(
!
starget
)
{
printk
(
ALLOC_FAILURE_MSG
,
__FUNCTION__
);
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
flags
);
return
SCSI_SCAN_NO_RESPONSE
;
}
starget
->
starget_refcnt
=
0
;
starget
->
starget_busy
=
0
;
}
starget
->
starget_refcnt
++
;
sdev
->
sdev_target
=
starget
;
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
flags
);
}
/* if the device needs this changing, it may do so in the detect
* function */
...
...
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