|
@@ -189,7 +189,7 @@ static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
|
|
|
Sg_request * srp);
|
|
|
static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
|
|
|
const char __user *buf, size_t count, int blocking,
|
|
|
- int read_only, Sg_request **o_srp);
|
|
|
+ int read_only, int sg_io_owned, Sg_request **o_srp);
|
|
|
static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
|
|
|
unsigned char *cmnd, int timeout, int blocking);
|
|
|
static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer);
|
|
@@ -561,7 +561,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
|
|
|
return -EFAULT;
|
|
|
blocking = !(filp->f_flags & O_NONBLOCK);
|
|
|
if (old_hdr.reply_len < 0)
|
|
|
- return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL);
|
|
|
+ return sg_new_write(sfp, filp, buf, count,
|
|
|
+ blocking, 0, 0, NULL);
|
|
|
if (count < (SZ_SG_HEADER + 6))
|
|
|
return -EIO; /* The minimum scsi command length is 6 bytes. */
|
|
|
|
|
@@ -642,7 +643,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
|
|
|
|
|
|
static ssize_t
|
|
|
sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
|
|
|
- size_t count, int blocking, int read_only,
|
|
|
+ size_t count, int blocking, int read_only, int sg_io_owned,
|
|
|
Sg_request **o_srp)
|
|
|
{
|
|
|
int k;
|
|
@@ -662,6 +663,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
|
|
|
SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n"));
|
|
|
return -EDOM;
|
|
|
}
|
|
|
+ srp->sg_io_owned = sg_io_owned;
|
|
|
hp = &srp->header;
|
|
|
if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
|
|
|
sg_remove_request(sfp, srp);
|
|
@@ -765,18 +767,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-sg_srp_done(Sg_request *srp, Sg_fd *sfp)
|
|
|
-{
|
|
|
- unsigned long iflags;
|
|
|
- int done;
|
|
|
-
|
|
|
- read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
|
|
- done = srp->done;
|
|
|
- read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
|
|
- return done;
|
|
|
-}
|
|
|
-
|
|
|
static int
|
|
|
sg_ioctl(struct inode *inode, struct file *filp,
|
|
|
unsigned int cmd_in, unsigned long arg)
|
|
@@ -809,27 +799,26 @@ sg_ioctl(struct inode *inode, struct file *filp,
|
|
|
return -EFAULT;
|
|
|
result =
|
|
|
sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
|
|
|
- blocking, read_only, &srp);
|
|
|
+ blocking, read_only, 1, &srp);
|
|
|
if (result < 0)
|
|
|
return result;
|
|
|
- srp->sg_io_owned = 1;
|
|
|
while (1) {
|
|
|
result = 0; /* following macro to beat race condition */
|
|
|
__wait_event_interruptible(sfp->read_wait,
|
|
|
- (sdp->detached || sfp->closed || sg_srp_done(srp, sfp)),
|
|
|
- result);
|
|
|
+ (srp->done || sdp->detached),
|
|
|
+ result);
|
|
|
if (sdp->detached)
|
|
|
return -ENODEV;
|
|
|
- if (sfp->closed)
|
|
|
- return 0; /* request packet dropped already */
|
|
|
- if (0 == result)
|
|
|
+ write_lock_irq(&sfp->rq_list_lock);
|
|
|
+ if (srp->done) {
|
|
|
+ srp->done = 2;
|
|
|
+ write_unlock_irq(&sfp->rq_list_lock);
|
|
|
break;
|
|
|
+ }
|
|
|
srp->orphan = 1;
|
|
|
+ write_unlock_irq(&sfp->rq_list_lock);
|
|
|
return result; /* -ERESTARTSYS because signal hit process */
|
|
|
}
|
|
|
- write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
|
|
- srp->done = 2;
|
|
|
- write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
|
|
result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp);
|
|
|
return (result < 0) ? result : 0;
|
|
|
}
|