scsi: sg: use standard lists for sg_requests
'Sg_request' is using a private list implementation; convert it to standard lists. Signed-off-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Tested-by: Johannes Thumshirn <jthumshirn@suse.de> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
28676d869b
commit
109bade9c6
@ -122,7 +122,7 @@ struct sg_device; /* forward declarations */
|
|||||||
struct sg_fd;
|
struct sg_fd;
|
||||||
|
|
||||||
typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
|
typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
|
||||||
struct sg_request *nextrp; /* NULL -> tail request (slist) */
|
struct list_head entry; /* list entry */
|
||||||
struct sg_fd *parentfp; /* NULL -> not in use */
|
struct sg_fd *parentfp; /* NULL -> not in use */
|
||||||
Sg_scatter_hold data; /* hold buffer, perhaps scatter list */
|
Sg_scatter_hold data; /* hold buffer, perhaps scatter list */
|
||||||
sg_io_hdr_t header; /* scsi command+info, see <scsi/sg.h> */
|
sg_io_hdr_t header; /* scsi command+info, see <scsi/sg.h> */
|
||||||
@ -146,7 +146,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
|
|||||||
int timeout; /* defaults to SG_DEFAULT_TIMEOUT */
|
int timeout; /* defaults to SG_DEFAULT_TIMEOUT */
|
||||||
int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */
|
int timeout_user; /* defaults to SG_DEFAULT_TIMEOUT_USER */
|
||||||
Sg_scatter_hold reserve; /* buffer held for this file descriptor */
|
Sg_scatter_hold reserve; /* buffer held for this file descriptor */
|
||||||
Sg_request *headrp; /* head of request slist, NULL->empty */
|
struct list_head rq_list; /* head of request list */
|
||||||
struct fasync_struct *async_qp; /* used by asynchronous notification */
|
struct fasync_struct *async_qp; /* used by asynchronous notification */
|
||||||
Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */
|
Sg_request req_arr[SG_MAX_QUEUE]; /* used as singly-linked list */
|
||||||
char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */
|
char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */
|
||||||
@ -949,7 +949,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
|||||||
if (!access_ok(VERIFY_WRITE, ip, sizeof (int)))
|
if (!access_ok(VERIFY_WRITE, ip, sizeof (int)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
for (srp = sfp->headrp; srp; srp = srp->nextrp) {
|
list_for_each_entry(srp, &sfp->rq_list, entry) {
|
||||||
if ((1 == srp->done) && (!srp->sg_io_owned)) {
|
if ((1 == srp->done) && (!srp->sg_io_owned)) {
|
||||||
read_unlock_irqrestore(&sfp->rq_list_lock,
|
read_unlock_irqrestore(&sfp->rq_list_lock,
|
||||||
iflags);
|
iflags);
|
||||||
@ -962,7 +962,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
|||||||
return 0;
|
return 0;
|
||||||
case SG_GET_NUM_WAITING:
|
case SG_GET_NUM_WAITING:
|
||||||
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
for (val = 0, srp = sfp->headrp; srp; srp = srp->nextrp) {
|
val = 0;
|
||||||
|
list_for_each_entry(srp, &sfp->rq_list, entry) {
|
||||||
if ((1 == srp->done) && (!srp->sg_io_owned))
|
if ((1 == srp->done) && (!srp->sg_io_owned))
|
||||||
++val;
|
++val;
|
||||||
}
|
}
|
||||||
@ -1035,32 +1036,30 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
|||||||
if (!rinfo)
|
if (!rinfo)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
for (srp = sfp->headrp, val = 0; val < SG_MAX_QUEUE;
|
val = 0;
|
||||||
++val, srp = srp ? srp->nextrp : srp) {
|
list_for_each_entry(srp, &sfp->rq_list, entry) {
|
||||||
|
if (val > SG_MAX_QUEUE)
|
||||||
|
break;
|
||||||
memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
|
memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
|
||||||
if (srp) {
|
rinfo[val].req_state = srp->done + 1;
|
||||||
rinfo[val].req_state = srp->done + 1;
|
rinfo[val].problem =
|
||||||
rinfo[val].problem =
|
srp->header.masked_status &
|
||||||
srp->header.masked_status &
|
srp->header.host_status &
|
||||||
srp->header.host_status &
|
srp->header.driver_status;
|
||||||
srp->header.driver_status;
|
if (srp->done)
|
||||||
if (srp->done)
|
rinfo[val].duration =
|
||||||
rinfo[val].duration =
|
srp->header.duration;
|
||||||
srp->header.duration;
|
else {
|
||||||
else {
|
ms = jiffies_to_msecs(jiffies);
|
||||||
ms = jiffies_to_msecs(jiffies);
|
rinfo[val].duration =
|
||||||
rinfo[val].duration =
|
(ms > srp->header.duration) ?
|
||||||
(ms > srp->header.duration) ?
|
(ms - srp->header.duration) : 0;
|
||||||
(ms - srp->header.duration) : 0;
|
|
||||||
}
|
|
||||||
rinfo[val].orphan = srp->orphan;
|
|
||||||
rinfo[val].sg_io_owned =
|
|
||||||
srp->sg_io_owned;
|
|
||||||
rinfo[val].pack_id =
|
|
||||||
srp->header.pack_id;
|
|
||||||
rinfo[val].usr_ptr =
|
|
||||||
srp->header.usr_ptr;
|
|
||||||
}
|
}
|
||||||
|
rinfo[val].orphan = srp->orphan;
|
||||||
|
rinfo[val].sg_io_owned = srp->sg_io_owned;
|
||||||
|
rinfo[val].pack_id = srp->header.pack_id;
|
||||||
|
rinfo[val].usr_ptr = srp->header.usr_ptr;
|
||||||
|
val++;
|
||||||
}
|
}
|
||||||
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||||
result = __copy_to_user(p, rinfo,
|
result = __copy_to_user(p, rinfo,
|
||||||
@ -1169,7 +1168,7 @@ sg_poll(struct file *filp, poll_table * wait)
|
|||||||
return POLLERR;
|
return POLLERR;
|
||||||
poll_wait(filp, &sfp->read_wait, wait);
|
poll_wait(filp, &sfp->read_wait, wait);
|
||||||
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
for (srp = sfp->headrp; srp; srp = srp->nextrp) {
|
list_for_each_entry(srp, &sfp->rq_list, entry) {
|
||||||
/* if any read waiting, flag it */
|
/* if any read waiting, flag it */
|
||||||
if ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned))
|
if ((0 == res) && (1 == srp->done) && (!srp->sg_io_owned))
|
||||||
res = POLLIN | POLLRDNORM;
|
res = POLLIN | POLLRDNORM;
|
||||||
@ -2063,7 +2062,7 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
|
|||||||
unsigned long iflags;
|
unsigned long iflags;
|
||||||
|
|
||||||
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
for (resp = sfp->headrp; resp; resp = resp->nextrp) {
|
list_for_each_entry(resp, &sfp->rq_list, entry) {
|
||||||
/* look for requests that are ready + not SG_IO owned */
|
/* look for requests that are ready + not SG_IO owned */
|
||||||
if ((1 == resp->done) && (!resp->sg_io_owned) &&
|
if ((1 == resp->done) && (!resp->sg_io_owned) &&
|
||||||
((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
|
((-1 == pack_id) || (resp->header.pack_id == pack_id))) {
|
||||||
@ -2081,70 +2080,45 @@ sg_add_request(Sg_fd * sfp)
|
|||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
unsigned long iflags;
|
unsigned long iflags;
|
||||||
Sg_request *resp;
|
|
||||||
Sg_request *rp = sfp->req_arr;
|
Sg_request *rp = sfp->req_arr;
|
||||||
|
|
||||||
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
resp = sfp->headrp;
|
if (!list_empty(&sfp->rq_list)) {
|
||||||
if (!resp) {
|
if (!sfp->cmd_q)
|
||||||
memset(rp, 0, sizeof (Sg_request));
|
goto out_unlock;
|
||||||
rp->parentfp = sfp;
|
|
||||||
resp = rp;
|
for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
|
||||||
sfp->headrp = resp;
|
if (!rp->parentfp)
|
||||||
} else {
|
break;
|
||||||
if (0 == sfp->cmd_q)
|
|
||||||
resp = NULL; /* command queuing disallowed */
|
|
||||||
else {
|
|
||||||
for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
|
|
||||||
if (!rp->parentfp)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (k < SG_MAX_QUEUE) {
|
|
||||||
memset(rp, 0, sizeof (Sg_request));
|
|
||||||
rp->parentfp = sfp;
|
|
||||||
while (resp->nextrp)
|
|
||||||
resp = resp->nextrp;
|
|
||||||
resp->nextrp = rp;
|
|
||||||
resp = rp;
|
|
||||||
} else
|
|
||||||
resp = NULL;
|
|
||||||
}
|
}
|
||||||
|
if (k >= SG_MAX_QUEUE)
|
||||||
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
if (resp) {
|
memset(rp, 0, sizeof (Sg_request));
|
||||||
resp->nextrp = NULL;
|
rp->parentfp = sfp;
|
||||||
resp->header.duration = jiffies_to_msecs(jiffies);
|
rp->header.duration = jiffies_to_msecs(jiffies);
|
||||||
}
|
list_add_tail(&rp->entry, &sfp->rq_list);
|
||||||
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||||
return resp;
|
return rp;
|
||||||
|
out_unlock:
|
||||||
|
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return of 1 for found; 0 for not found */
|
/* Return of 1 for found; 0 for not found */
|
||||||
static int
|
static int
|
||||||
sg_remove_request(Sg_fd * sfp, Sg_request * srp)
|
sg_remove_request(Sg_fd * sfp, Sg_request * srp)
|
||||||
{
|
{
|
||||||
Sg_request *prev_rp;
|
|
||||||
Sg_request *rp;
|
|
||||||
unsigned long iflags;
|
unsigned long iflags;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
if ((!sfp) || (!srp) || (!sfp->headrp))
|
if (!sfp || !srp || list_empty(&sfp->rq_list))
|
||||||
return res;
|
return res;
|
||||||
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
prev_rp = sfp->headrp;
|
if (!list_empty(&srp->entry)) {
|
||||||
if (srp == prev_rp) {
|
list_del(&srp->entry);
|
||||||
sfp->headrp = prev_rp->nextrp;
|
srp->parentfp = NULL;
|
||||||
prev_rp->parentfp = NULL;
|
|
||||||
res = 1;
|
res = 1;
|
||||||
} else {
|
|
||||||
while ((rp = prev_rp->nextrp)) {
|
|
||||||
if (srp == rp) {
|
|
||||||
prev_rp->nextrp = rp->nextrp;
|
|
||||||
rp->parentfp = NULL;
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev_rp = rp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||||
return res;
|
return res;
|
||||||
@ -2163,7 +2137,7 @@ sg_add_sfp(Sg_device * sdp)
|
|||||||
|
|
||||||
init_waitqueue_head(&sfp->read_wait);
|
init_waitqueue_head(&sfp->read_wait);
|
||||||
rwlock_init(&sfp->rq_list_lock);
|
rwlock_init(&sfp->rq_list_lock);
|
||||||
|
INIT_LIST_HEAD(&sfp->rq_list);
|
||||||
kref_init(&sfp->f_ref);
|
kref_init(&sfp->f_ref);
|
||||||
mutex_init(&sfp->f_mutex);
|
mutex_init(&sfp->f_mutex);
|
||||||
sfp->timeout = SG_DEFAULT_TIMEOUT;
|
sfp->timeout = SG_DEFAULT_TIMEOUT;
|
||||||
@ -2202,10 +2176,13 @@ sg_remove_sfp_usercontext(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
|
struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
|
||||||
struct sg_device *sdp = sfp->parentdp;
|
struct sg_device *sdp = sfp->parentdp;
|
||||||
|
Sg_request *srp;
|
||||||
|
|
||||||
/* Cleanup any responses which were never read(). */
|
/* Cleanup any responses which were never read(). */
|
||||||
while (sfp->headrp)
|
while (!list_empty(&sfp->rq_list)) {
|
||||||
sg_finish_rem_req(sfp->headrp);
|
srp = list_first_entry(&sfp->rq_list, Sg_request, entry);
|
||||||
|
sg_finish_rem_req(srp);
|
||||||
|
}
|
||||||
|
|
||||||
if (sfp->reserve.bufflen > 0) {
|
if (sfp->reserve.bufflen > 0) {
|
||||||
SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp,
|
SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp,
|
||||||
@ -2608,7 +2585,7 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
|
|||||||
/* must be called while holding sg_index_lock */
|
/* must be called while holding sg_index_lock */
|
||||||
static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
||||||
{
|
{
|
||||||
int k, m, new_interface, blen, usg;
|
int k, new_interface, blen, usg;
|
||||||
Sg_request *srp;
|
Sg_request *srp;
|
||||||
Sg_fd *fp;
|
Sg_fd *fp;
|
||||||
const sg_io_hdr_t *hp;
|
const sg_io_hdr_t *hp;
|
||||||
@ -2628,9 +2605,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
|||||||
seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
|
seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=0\n",
|
||||||
(int) fp->cmd_q, (int) fp->force_packid,
|
(int) fp->cmd_q, (int) fp->force_packid,
|
||||||
(int) fp->keep_orphan);
|
(int) fp->keep_orphan);
|
||||||
for (m = 0, srp = fp->headrp;
|
list_for_each_entry(srp, &fp->rq_list, entry) {
|
||||||
srp != NULL;
|
|
||||||
++m, srp = srp->nextrp) {
|
|
||||||
hp = &srp->header;
|
hp = &srp->header;
|
||||||
new_interface = (hp->interface_id == '\0') ? 0 : 1;
|
new_interface = (hp->interface_id == '\0') ? 0 : 1;
|
||||||
if (srp->res_used) {
|
if (srp->res_used) {
|
||||||
@ -2665,7 +2640,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
|||||||
seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
|
seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
|
||||||
(int) srp->data.cmd_opcode);
|
(int) srp->data.cmd_opcode);
|
||||||
}
|
}
|
||||||
if (0 == m)
|
if (list_empty(&fp->rq_list))
|
||||||
seq_puts(s, " No requests active\n");
|
seq_puts(s, " No requests active\n");
|
||||||
read_unlock(&fp->rq_list_lock);
|
read_unlock(&fp->rq_list_lock);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user