Commit 109bade9 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen

scsi: sg: use standard lists for sg_requests

'Sg_request' is using a private list implementation; convert it to
standard lists.
Signed-off-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Tested-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 28676d86
...@@ -122,7 +122,7 @@ struct sg_device; /* forward declarations */ ...@@ -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 */ ...@@ -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) ...@@ -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) ...@@ -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,10 +1036,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) ...@@ -1035,10 +1036,11 @@ 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 &
...@@ -1054,13 +1056,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) ...@@ -1054,13 +1056,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
(ms - srp->header.duration) : 0; (ms - srp->header.duration) : 0;
} }
rinfo[val].orphan = srp->orphan; rinfo[val].orphan = srp->orphan;
rinfo[val].sg_io_owned = rinfo[val].sg_io_owned = srp->sg_io_owned;
srp->sg_io_owned; rinfo[val].pack_id = srp->header.pack_id;
rinfo[val].pack_id = rinfo[val].usr_ptr = srp->header.usr_ptr;
srp->header.pack_id; val++;
rinfo[val].usr_ptr =
srp->header.usr_ptr;
}
} }
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) ...@@ -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) ...@@ -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) ...@@ -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;
sfp->headrp = resp;
} else {
if (0 == sfp->cmd_q)
resp = NULL; /* command queuing disallowed */
else {
for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) { for (k = 0; k < SG_MAX_QUEUE; ++k, ++rp) {
if (!rp->parentfp) if (!rp->parentfp)
break; break;
} }
if (k < SG_MAX_QUEUE) { if (k >= SG_MAX_QUEUE)
goto out_unlock;
}
memset(rp, 0, sizeof (Sg_request)); memset(rp, 0, sizeof (Sg_request));
rp->parentfp = sfp; rp->parentfp = sfp;
while (resp->nextrp) rp->header.duration = jiffies_to_msecs(jiffies);
resp = resp->nextrp; list_add_tail(&rp->entry, &sfp->rq_list);
resp->nextrp = rp;
resp = rp;
} else
resp = NULL;
}
}
if (resp) {
resp->nextrp = NULL;
resp->header.duration = jiffies_to_msecs(jiffies);
}
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;
} else {
while ((rp = prev_rp->nextrp)) {
if (srp == rp) {
prev_rp->nextrp = rp->nextrp;
rp->parentfp = NULL;
res = 1; 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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment