@@ -153,6 +153,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
153153 struct sg_device * parentdp ; /* owning device */
154154 wait_queue_head_t read_wait ; /* queue read until command done */
155155 rwlock_t rq_list_lock ; /* protect access to list in req_arr */
156+ struct mutex f_mutex ; /* protect against changes in this fd */
156157 int timeout ; /* defaults to SG_DEFAULT_TIMEOUT */
157158 int timeout_user ; /* defaults to SG_DEFAULT_TIMEOUT_USER */
158159 Sg_scatter_hold reserve ; /* buffer held for this file descriptor */
@@ -166,6 +167,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
166167 unsigned char next_cmd_len ; /* 0: automatic, >0: use on next write() */
167168 char keep_orphan ; /* 0 -> drop orphan (def), 1 -> keep for read() */
168169 char mmap_called ; /* 0 -> mmap() never called on this fd */
170+ char res_in_use ; /* 1 -> 'reserve' array in use */
169171 struct kref f_ref ;
170172 struct execute_work ew ;
171173} Sg_fd ;
@@ -209,7 +211,6 @@ static void sg_remove_sfp(struct kref *);
209211static Sg_request * sg_get_rq_mark (Sg_fd * sfp , int pack_id );
210212static Sg_request * sg_add_request (Sg_fd * sfp );
211213static int sg_remove_request (Sg_fd * sfp , Sg_request * srp );
212- static int sg_res_in_use (Sg_fd * sfp );
213214static Sg_device * sg_get_dev (int dev );
214215static void sg_device_destroy (struct kref * kref );
215216
@@ -625,6 +626,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
625626 }
626627 buf += SZ_SG_HEADER ;
627628 __get_user (opcode , buf );
629+ mutex_lock (& sfp -> f_mutex );
628630 if (sfp -> next_cmd_len > 0 ) {
629631 cmd_size = sfp -> next_cmd_len ;
630632 sfp -> next_cmd_len = 0 ; /* reset so only this write() effected */
@@ -633,6 +635,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
633635 if ((opcode >= 0xc0 ) && old_hdr .twelve_byte )
634636 cmd_size = 12 ;
635637 }
638+ mutex_unlock (& sfp -> f_mutex );
636639 SCSI_LOG_TIMEOUT (4 , sg_printk (KERN_INFO , sdp ,
637640 "sg_write: scsi opcode=0x%02x, cmd_size=%d\n" , (int ) opcode , cmd_size ));
638641/* Determine buffer size. */
@@ -732,7 +735,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
732735 sg_remove_request (sfp , srp );
733736 return - EINVAL ; /* either MMAP_IO or DIRECT_IO (not both) */
734737 }
735- if (sg_res_in_use ( sfp ) ) {
738+ if (sfp -> res_in_use ) {
736739 sg_remove_request (sfp , srp );
737740 return - EBUSY ; /* reserve buffer already being used */
738741 }
@@ -902,7 +905,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
902905 return result ;
903906 if (val ) {
904907 sfp -> low_dma = 1 ;
905- if ((0 == sfp -> low_dma ) && ( 0 == sg_res_in_use ( sfp )) ) {
908+ if ((0 == sfp -> low_dma ) && ! sfp -> res_in_use ) {
906909 val = (int ) sfp -> reserve .bufflen ;
907910 sg_remove_scat (sfp , & sfp -> reserve );
908911 sg_build_reserve (sfp , val );
@@ -977,12 +980,18 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
977980 return - EINVAL ;
978981 val = min_t (int , val ,
979982 max_sectors_bytes (sdp -> device -> request_queue ));
983+ mutex_lock (& sfp -> f_mutex );
980984 if (val != sfp -> reserve .bufflen ) {
981- if (sg_res_in_use (sfp ) || sfp -> mmap_called )
985+ if (sfp -> mmap_called ||
986+ sfp -> res_in_use ) {
987+ mutex_unlock (& sfp -> f_mutex );
982988 return - EBUSY ;
989+ }
990+
983991 sg_remove_scat (sfp , & sfp -> reserve );
984992 sg_build_reserve (sfp , val );
985993 }
994+ mutex_unlock (& sfp -> f_mutex );
986995 return 0 ;
987996 case SG_GET_RESERVED_SIZE :
988997 val = min_t (int , sfp -> reserve .bufflen ,
@@ -1737,13 +1746,22 @@ sg_start_req(Sg_request *srp, unsigned char *cmd)
17371746 md = & map_data ;
17381747
17391748 if (md ) {
1740- if (!sg_res_in_use (sfp ) && dxfer_len <= rsv_schp -> bufflen )
1749+ mutex_lock (& sfp -> f_mutex );
1750+ if (dxfer_len <= rsv_schp -> bufflen &&
1751+ !sfp -> res_in_use ) {
1752+ sfp -> res_in_use = 1 ;
17411753 sg_link_reserve (sfp , srp , dxfer_len );
1742- else {
1754+ } else if ((hp -> flags & SG_FLAG_MMAP_IO ) && sfp -> res_in_use ) {
1755+ mutex_unlock (& sfp -> f_mutex );
1756+ return - EBUSY ;
1757+ } else {
17431758 res = sg_build_indirect (req_schp , sfp , dxfer_len );
1744- if (res )
1759+ if (res ) {
1760+ mutex_unlock (& sfp -> f_mutex );
17451761 return res ;
1762+ }
17461763 }
1764+ mutex_unlock (& sfp -> f_mutex );
17471765
17481766 md -> pages = req_schp -> pages ;
17491767 md -> page_order = req_schp -> page_order ;
@@ -2034,6 +2052,8 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
20342052 req_schp -> sglist_len = 0 ;
20352053 sfp -> save_scat_len = 0 ;
20362054 srp -> res_used = 0 ;
2055+ /* Called without mutex lock to avoid deadlock */
2056+ sfp -> res_in_use = 0 ;
20372057}
20382058
20392059static Sg_request *
@@ -2145,6 +2165,7 @@ sg_add_sfp(Sg_device * sdp)
21452165 rwlock_init (& sfp -> rq_list_lock );
21462166
21472167 kref_init (& sfp -> f_ref );
2168+ mutex_init (& sfp -> f_mutex );
21482169 sfp -> timeout = SG_DEFAULT_TIMEOUT ;
21492170 sfp -> timeout_user = SG_DEFAULT_TIMEOUT_USER ;
21502171 sfp -> force_packid = SG_DEF_FORCE_PACK_ID ;
@@ -2220,20 +2241,6 @@ sg_remove_sfp(struct kref *kref)
22202241 schedule_work (& sfp -> ew .work );
22212242}
22222243
2223- static int
2224- sg_res_in_use (Sg_fd * sfp )
2225- {
2226- const Sg_request * srp ;
2227- unsigned long iflags ;
2228-
2229- read_lock_irqsave (& sfp -> rq_list_lock , iflags );
2230- for (srp = sfp -> headrp ; srp ; srp = srp -> nextrp )
2231- if (srp -> res_used )
2232- break ;
2233- read_unlock_irqrestore (& sfp -> rq_list_lock , iflags );
2234- return srp ? 1 : 0 ;
2235- }
2236-
22372244#ifdef CONFIG_SCSI_PROC_FS
22382245static int
22392246sg_idr_max_id (int id , void * p , void * data )
0 commit comments