mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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
					
				
					 1 changed files with 61 additions and 86 deletions
				
			
		| 
						 | 
					@ -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 a new issue